diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..1b46a355c2be9f1f3781c49b2a1c051cdf77ef02
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+.classpath
+.project
+.settings
+*.jardesc
+*.jar
+*.7z
+bin/
+target/
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8199f4f684d34d0dabd77a7ac46b3a1f24cc539d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>pom-icy</artifactId>
+        <groupId>org.bioimageanalysis.icy</groupId>
+        <version>1.0.4</version>
+    </parent>
+
+    <artifactId>icy-jython</artifactId>
+    <version>2.8.0</version>
+
+    <packaging>jar</packaging>
+
+    <name>Jython for Icy</name>
+    <description>
+        Jython library for Icy
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.bioimageanalysis.icy</groupId>
+            <artifactId>icy-ezplug</artifactId>
+            <version>3.15.13</version>
+        </dependency>
+    </dependencies>
+
+    <repositories>
+        <repository>
+            <id>icy-prod</id>
+            <url>https://icy-nexus.pasteur.fr/repository/Icy/</url>
+        </repository>
+    </repositories>
+</project>
\ No newline at end of file
diff --git a/src/main/java/plugins/tlecomte/jythonForIcy/ExtractionHelper.java b/src/main/java/plugins/tlecomte/jythonForIcy/ExtractionHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..e976e6162ccee619a2032f639da3fc038cebeaff
--- /dev/null
+++ b/src/main/java/plugins/tlecomte/jythonForIcy/ExtractionHelper.java
@@ -0,0 +1,301 @@
+package plugins.tlecomte.jythonForIcy;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.python.core.PySystemState;
+
+import icy.file.FileUtil;
+import icy.plugin.PluginDescriptor;
+import icy.plugin.PluginLoader;
+import icy.plugin.abstract_.Plugin;
+
+class ExtractionHelper
+{
+    final static String pythonDirName = "PythonLibs";
+    final static String extractionDir = pythonDirName;
+
+    /**
+     * Walk the plugin list to look for plugins that contain py files
+     * and extract them.
+     * 
+     * @return the list of dirs whose contents have been extracted
+     */
+    static void extractPyFiles(ExtractionTimestamps timestamps)
+    {
+        ArrayList<PluginDescriptor> pluginList = PluginLoader.getPlugins();
+
+        String destDir = getPythonLibDir();
+        if (destDir == null)
+        {
+            System.err.println("Failed to extract python library files because sys.prefix is not set");
+            return;
+        }
+
+        // extract Python files
+        for (PluginDescriptor plugin : pluginList)
+        {
+            if (plugin.getPluginClass().getAnnotation(PythonLibraries.class) != null)
+            {
+                try
+                {
+                    extractPyFiles(plugin, destDir, timestamps);
+                }
+                catch (IOException e)
+                {
+                    System.err.println("Failed to extract python library files for plugin " + plugin);
+                    e.printStackTrace();
+                }
+                catch (URISyntaxException e)
+                {
+                    System.err.println("Failed to extract python library files for plugin " + plugin);
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    static String getPythonLibDir()
+    {
+        // Note: this is done in a thread, otherwise ThreadLocal variables in Jython
+        // prevents the whole classloader from being garbage-collected.
+        ExecutorService executor = Executors.newSingleThreadExecutor();
+        Callable<String> callable = new Callable<String>()
+        {
+            @Override
+            public String call()
+            {
+                // create a new PySystemState (will initialize Jython state if not done already)
+                PySystemState sys = new PySystemState();
+                // retrieve Python prefix (i.e. where the 'Lib' folder will be looked for)
+                String sys_prefix = PySystemState.prefix.asString();
+                // cleanup immediately to remove shutdown hooks that prevent the classloader from being garbage-collected
+                sys.cleanup();
+                return sys_prefix;
+            }
+        };
+        Future<String> future = executor.submit(callable);
+        executor.shutdown();
+        executor = null;
+
+        String sys_prefix;
+        try
+        {
+            sys_prefix = future.get();
+        }
+        catch (InterruptedException e)
+        {
+            System.err.println("Failed to retrieve Python prefix");
+            sys_prefix = null;
+        }
+        catch (ExecutionException e)
+        {
+            System.err.println("Failed to retrieve Python prefix");
+            sys_prefix = null;
+        }
+
+        String Lib_prefix = null;
+        if (sys_prefix == null)
+        {
+            System.err.println("Error: sys.prefix is None.");
+            System.err.println("If you are developing in Eclipse, please set the 'python.home' property");
+            System.err.println("on the Java command-line. For example:");
+            System.err.println("	-Dpython.home=plugins");
+        }
+        else
+        {
+            Lib_prefix = sys_prefix + File.separator + "Lib";
+        }
+
+        return Lib_prefix;
+    }
+
+    static void extractPyFiles(PluginDescriptor plugin, String destDir, ExtractionTimestamps timestamps)
+            throws IOException, URISyntaxException
+    {
+
+        // Jython can use python files that are actually on disk
+        // or files that are inside a jar.
+        // However, files inside a jar will not be found by modules
+        // like 'inspect' that are actively working on the source
+        // code. This is preventing the interpreter from displaying
+        // complete backtraces whenever they go through a file in a jar.
+        // Additionally, it prevents execnet from correctly bootstrapping
+        // itself.
+
+        // To overcome this, we choose to make sure that all python files
+        // provided by Icy are extracted to an actual folder on disk.
+
+        // This will work on files provided by all plugins implementing PythonLibrariesBundle
+        // JythonExtrasForIcy and JythonExecnetForIcy are first users of this interface.
+
+        Class<? extends Plugin> klass = plugin.getPluginClass();
+
+        URL classUrl = klass.getResource(klass.getSimpleName() + ".class");
+
+        URLConnection connection = classUrl.openConnection();
+
+        if (connection instanceof JarURLConnection)
+        {
+            JarURLConnection jarConnection = (JarURLConnection) connection;
+
+            extractPyFilesFromJarIfNewer(jarConnection, plugin, destDir, timestamps);
+        }
+        else
+        {
+            // the files are already on disk !
+            // (this happens when developing the plugins in Eclipse)
+
+            System.out.println("Extracting Python files from disk for plugin " + plugin);
+            String srcDir = findPythonFilesFromDisk(classUrl);
+            FileUtil.copy(srcDir, destDir, true, true); // force and recursive
+        }
+    }
+
+    static void extractPyFilesFromJarIfNewer(JarURLConnection jarConnection, PluginDescriptor plugin, String destDir,
+            ExtractionTimestamps timestamps) throws IOException, URISyntaxException
+    {
+        URL jarUrl = jarConnection.getJarFileURL();
+
+        URI jarURI = jarUrl.toURI();
+
+        JarFile jarFile = new JarFile(new File(jarURI));
+
+        long jarLastModified = new File(jarFile.getName()).lastModified();
+
+        // retrieve the lastModified info of the last time we extracted
+        Long extractionTimestamp = timestamps.getTimestamp(plugin);
+
+        if (extractionTimestamp.longValue() == jarLastModified)
+        {
+            // no need to extract anything, the proper version exists
+            return;
+        }
+
+        // the bundled version is newer, extract !
+        System.out.println("Extracting Python files from plugin " + plugin);
+        extractPyFilesFromJar(jarFile, destDir);
+
+        // store the extracted version
+        timestamps.setTimestamp(plugin, new Long(jarLastModified));
+    }
+
+    static void extractPyFilesFromJar(JarFile jarFile, String destDir) throws IOException
+    {
+        Enumeration<JarEntry> entries = jarFile.entries();
+        while (entries.hasMoreElements())
+        {
+            JarEntry jarEntry = entries.nextElement();
+
+            String name = jarEntry.getName();
+
+            // extract all files contained in a dir named $pythonDirName
+            if (!jarEntry.isDirectory() && name.startsWith(pythonDirName))
+            {
+                String strippedName = name.substring(pythonDirName.length() + 1);
+                String outName = destDir + File.separator + strippedName;
+
+                InputStream inputStream = jarFile.getInputStream(jarEntry);
+                File destFile = new File(outName);
+                FileOutputStream fileOutputStream;
+                try
+                {
+                    fileOutputStream = new FileOutputStream(destFile);
+                }
+                catch (FileNotFoundException e)
+                {
+                    destFile.getParentFile().mkdirs();
+                    fileOutputStream = new FileOutputStream(destFile);
+                }
+                byte[] b = new byte[16384];
+                int bytes;
+                while ((bytes = inputStream.read(b)) > 0)
+                {
+                    fileOutputStream.write(b, 0, bytes);
+                }
+                fileOutputStream.close();
+                inputStream.close();
+            }
+        }
+    }
+
+    /**
+     * Given a directory, walk the sub-directories until it finds
+     * one that is named "PythonLibs"
+     * If no directory with that name is found, reset the starting
+     * directory with its parent and start again
+     * 
+     * @param connection
+     * @return the "PythonLibs" directory as a File object, null if none is found
+     * @throws URISyntaxException
+     */
+    static String findPythonFilesFromDisk(URL classUrl) throws URISyntaxException
+    {
+        // the URL needs to be converted to an URI to handle spaces in paths
+        File classFile = new File(classUrl.toURI());
+
+        File pythonParent = null;
+        File leaf = classFile;
+
+        while (pythonParent == null)
+        {
+            leaf = leaf.getParentFile();
+            pythonParent = findPythonFilesInSubDirs(leaf);
+        }
+
+        return pythonParent.getAbsolutePath();
+    }
+
+    /**
+     * Given a root directory, walk the sub-directories until it finds
+     * one that is named "PythonLibs"
+     * 
+     * @param connection
+     * @return the "PythonLibs" directory as a File object, null if none is found
+     */
+    static File findPythonFilesInSubDirs(File root)
+    {
+        if (!root.isDirectory())
+        {
+            return null;
+        }
+
+        for (File file : root.listFiles())
+        {
+            if (file.isDirectory())
+            {
+                if (file.getName().endsWith(pythonDirName))
+                {
+                    return file;
+                }
+                else
+                {
+                    File res = findPythonFilesInSubDirs(file); // recursive !
+                    if (res != null)
+                    {
+                        return res;
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/src/main/java/plugins/tlecomte/jythonForIcy/ExtractionTimestamps.java b/src/main/java/plugins/tlecomte/jythonForIcy/ExtractionTimestamps.java
new file mode 100644
index 0000000000000000000000000000000000000000..956e9bbd0bf0b8fec3a90caa42cb1cd01cdaf159
--- /dev/null
+++ b/src/main/java/plugins/tlecomte/jythonForIcy/ExtractionTimestamps.java
@@ -0,0 +1,85 @@
+package plugins.tlecomte.jythonForIcy;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import icy.file.xml.XMLPersistent;
+import icy.plugin.PluginDescriptor;
+import icy.util.XMLUtil;
+
+public class ExtractionTimestamps implements XMLPersistent {
+	
+	Hashtable<String, Long> timestamps;
+	
+	static final String ID_PLUGINS = "plugins";
+	static final String ID_PLUGIN = "plugin";
+	static final String ID_CLASSNAME = "className";
+	static final String ID_TIMESTAMP = "timestamp";
+	
+	ExtractionTimestamps() {
+		timestamps = new Hashtable<String, Long>();
+	}
+	
+	public Long getTimestamp(PluginDescriptor plugin) {
+		Long timestamp = timestamps.get(plugin.getClassName());
+		if (timestamp == null) {
+			timestamp = new Long(0);
+		}
+		return timestamp;
+	}
+    
+	public void setTimestamp(PluginDescriptor plugin, Long timestamp) {
+		timestamps.put(plugin.getClassName(), timestamp);
+	}
+
+	@Override
+	public boolean loadFromXML(Node node) {
+        if (node == null)
+            return false;
+
+        final Node pluginsNode = XMLUtil.getElement(node, ID_PLUGINS);
+
+        if (pluginsNode != null)
+        {
+            final ArrayList<Node> pluginNodes = XMLUtil.getChildren(pluginsNode, ID_PLUGIN);
+
+            for (Node n : pluginNodes)
+            {
+            	String pluginName = XMLUtil.getElementValue(n, ID_CLASSNAME, "noClassName");
+            	Long timestamp = XMLUtil.getElementLongValue(n, ID_TIMESTAMP, 0);
+            	timestamps.put(pluginName, timestamp);
+            }
+        }
+
+        return true;
+	}
+
+	@Override
+	public boolean saveToXML(Node node) {
+        if (node == null)
+            return false;
+
+        final Element pluginsNode = XMLUtil.setElement(node, ID_PLUGINS);
+
+        if (pluginsNode != null)
+        {
+            XMLUtil.removeAllChildren(pluginsNode);
+            
+            Enumeration<String> enumKey = timestamps.keys();
+            while(enumKey.hasMoreElements()) {
+                String key = enumKey.nextElement();
+                Long timestamp = timestamps.get(key);
+                Element n = XMLUtil.addElement(pluginsNode, ID_PLUGIN);
+                XMLUtil.setElementValue(n, ID_CLASSNAME, key);
+                XMLUtil.setElementLongValue(n, ID_TIMESTAMP, timestamp);
+            }
+        }
+
+        return true;
+	}
+
+}
diff --git a/src/main/java/plugins/tlecomte/jythonForIcy/JythonForIcy.java b/src/main/java/plugins/tlecomte/jythonForIcy/JythonForIcy.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc40caea94e178c3a2154c025cf1c34579a5ac48
--- /dev/null
+++ b/src/main/java/plugins/tlecomte/jythonForIcy/JythonForIcy.java
@@ -0,0 +1,107 @@
+package plugins.tlecomte.jythonForIcy;
+
+import java.io.File;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.python.core.Py;
+import org.python.core.PySystemState;
+
+import icy.file.xml.XMLPersistentHelper;
+import icy.plugin.abstract_.Plugin;
+import icy.plugin.interface_.PluginDaemon;
+import icy.plugin.interface_.PluginLibrary;
+import icy.util.ClassUtil;
+import icy.util.XMLUtil;
+
+@PythonLibraries
+public class JythonForIcy extends Plugin implements PluginDaemon, PluginLibrary
+{
+    final String TIMESTAMPS_FILENAME = "ExtractDescriptor";
+
+    @Override
+    public void init()
+    {
+        // allow to avoid warning on jython loading
+        System.setProperty("python.console.encoding", "UTF-8");
+
+        // load timestamps of last extraction from XML file
+        ExtractionTimestamps timestamps = new ExtractionTimestamps();
+
+        String qualifiedDir = new File(ClassUtil.getPathFromQualifiedName(getDescriptor().getClassName())).getParent();
+        String timestampsFile = qualifiedDir + File.separator + TIMESTAMPS_FILENAME + XMLUtil.FILE_DOT_EXTENSION;
+        boolean loadSuccess = XMLPersistentHelper.loadFromXML(timestamps, timestampsFile);
+
+        if (!loadSuccess)
+        {
+            File file = new File(timestampsFile);
+            // if the file does not exist, the failure is normal
+            if (file.exists())
+            {
+                System.err.println("Failed to load the Python extraction timestamp file from " + timestampsFile);
+            }
+        }
+
+        // do the hard work here
+        ExtractionHelper.extractPyFiles(timestamps);
+
+        // save timestamps
+        boolean saveSucess = XMLPersistentHelper.saveToXML(timestamps, timestampsFile);
+
+        if (!saveSucess)
+        {
+            System.err.println("Failed to save the Python extraction timestamp file to " + timestampsFile);
+        }
+    }
+
+    @Override
+    public void run()
+    {
+        // nothing to do here
+    }
+
+    @Override
+    public void stop()
+    {
+        // This is our last chance of cleanup before a classloader reload
+        // If we do not ask for a cleanup, the registered shutdown hooks will
+        // prevent the whole classloader from being garbage collected,
+        // utlimately leading to a PermGenSpace error.
+
+        // Note that we need to do that in a thread to prevent ThreadLocal variables from
+        // being kept forever and preventing the classloader from being collected.
+
+        ExecutorService executor = Executors.newSingleThreadExecutor();
+        Runnable runnable = new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                // Cleanup to remove shutdown hooks that prevent the classloader from being garbage-collected.
+                // Note: instantiating a new PySystemState will cleanup those that have been marked as garbage previously
+                // and this new one must be cleaned up too immediately.
+                new PySystemState().cleanup();
+
+                // the defaultSystemState is defined static, so it is never marked as garbage.
+                // We must clean it up manually.
+                Py.defaultSystemState.cleanup();
+            }
+        };
+        Future<?> future = executor.submit(runnable);
+        executor.shutdown();
+        try
+        {
+            future.get();
+        }
+        catch (InterruptedException e)
+        {
+            // ignore
+        }
+        catch (ExecutionException e)
+        {
+            // ignore
+        }
+    }
+}
diff --git a/src/main/java/plugins/tlecomte/jythonForIcy/PythonExtractorManager.java b/src/main/java/plugins/tlecomte/jythonForIcy/PythonExtractorManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e41efe4e0bcad6545b7adbe5752e350d53b7b93
--- /dev/null
+++ b/src/main/java/plugins/tlecomte/jythonForIcy/PythonExtractorManager.java
@@ -0,0 +1,111 @@
+package plugins.tlecomte.jythonForIcy;
+
+/*
+ * Copyright 2013 Institut Pasteur.
+ * 
+ * This file is part of ICY.
+ * 
+ * ICY is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * ICY is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with ICY. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import icy.plugin.interface_.PluginBundled;
+import plugins.adufour.ezplug.EzButton;
+import plugins.adufour.ezplug.EzLabel;
+import plugins.adufour.ezplug.EzPlug;
+import plugins.adufour.ezplug.EzVarText;
+
+public class PythonExtractorManager extends EzPlug implements PluginBundled, ActionListener
+{
+
+    EzLabel description = new EzLabel("The Python Extractor walks the plugins list"
+            + " to extract all the Python scripts packaged inside the plugins."
+            + "\n\nThis operation is done automatically each time Icy starts and each"
+            + " time the plugins list is reloaded (after an update for example)."
+            + "\n\nIn some cases, you may want to force this operation manually."
+            + " This is useful when developping your own Python plugins inside" + " Eclipse for example.");
+    EzButton startButton = null;
+
+    EzLabel folderDescription = new EzLabel(
+            "\nFor your information, the Python files" + " are extracted to the following folder:");
+    EzVarText folder = new EzVarText("Extraction path", "");
+
+    EzLabel customizeDescription = new EzLabel(
+            "\nYou can customize your Python installation" + " by creating or editing the following file:");
+    EzVarText sitecustomizePath = new EzVarText("Site customization script", "");
+    EzLabel customizeDescription2 = new EzLabel("If it exists, this file is executed automatically"
+            + " each time the Python interpreter is launched. This file is a good place to extend the Python import"
+            + " path with the directories containing your own Python modules." + "\n" + "\n"
+            + "Please note that the embedded Python interpreter inside Icy also offers the"
+            + " other customization mechanisms offered by Python 2.7 (USERS_SITE, usercustomize.py, etc.)."
+            + " Look at http://docs.python.org/2/library/site.html for more information.");
+
+    public PythonExtractorManager()
+    {
+        startButton = new EzButton("Force extraction", this);
+        description.setNumberOfColumns(20);
+        description.setNumberOfRows(0);
+        String pythonlibDir = ExtractionHelper.getPythonLibDir();
+        folder.setValue(pythonlibDir);
+        sitecustomizePath
+                .setValue(pythonlibDir + File.separator + "site-packages" + File.separator + "sitecustomize.py");
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent arg0)
+    {
+        // Launch the extraction with an empty timestamps object,
+        // so that every plugin will be extracted again
+        ExtractionHelper.extractPyFiles(new ExtractionTimestamps());
+    }
+
+    @Override
+    public void clean()
+    {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    protected void execute()
+    {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    protected void initialize()
+    {
+        getUI().setActionPanelVisible(false);
+
+        addEzComponent(description);
+        addEzComponent(startButton);
+        addEzComponent(folderDescription);
+        addEzComponent(folder);
+        addEzComponent(customizeDescription);
+        addEzComponent(sitecustomizePath);
+        addEzComponent(customizeDescription2);
+
+        getUI().repack(true);
+    }
+
+    @Override
+    public String getMainPluginClassName()
+    {
+        return JythonForIcy.class.getName();
+    }
+}
diff --git a/src/main/java/plugins/tlecomte/jythonForIcy/PythonLibraries.java b/src/main/java/plugins/tlecomte/jythonForIcy/PythonLibraries.java
new file mode 100644
index 0000000000000000000000000000000000000000..53f2d356407a6959abd7efb1e4e775b4a611d93b
--- /dev/null
+++ b/src/main/java/plugins/tlecomte/jythonForIcy/PythonLibraries.java
@@ -0,0 +1,18 @@
+package plugins.tlecomte.jythonForIcy;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+
+/**
+ * Annotation used to mark that a plugin contains Python scripts.
+ * In turn Icy will extract these files from the jar to to the disk.
+ * 
+ * @author Timothee Lecomte
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface PythonLibraries {
+
+}
diff --git a/src/main/resources/META-INF/LICENSE b/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7
--- /dev/null
+++ b/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000000000000000000000000000000000..d76a648ee8cd95f9f35b02976ad26f9264375032
--- /dev/null
+++ b/src/main/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Ant-Version: Apache Ant 1.8.4
+Built-By: tlecomte
+Created-By: 1.6.0_65-b14-462-10M4609 (Apple Inc.)
+Main-Class: org.python.util.jython
+
+Name: Build-Info
+informix: ${informix.present}
+build-compiler: modern
+debug: true
+oracle: ${oracle.present}
+jdk-target-version: 1.6
+version: 2.7b1+
+
diff --git a/src/main/resources/META-INF/NOTICE b/src/main/resources/META-INF/NOTICE
new file mode 100644
index 0000000000000000000000000000000000000000..85e6e4eeeaeb491b088e73c9ee36a4ad76925d83
--- /dev/null
+++ b/src/main/resources/META-INF/NOTICE
@@ -0,0 +1,17 @@
+   =========================================================================
+   ==  NOTICE file corresponding to section 4(d) of the Apache License,   ==
+   ==  Version 2.0, in this case for the Apache Xerces Java distribution. ==
+   =========================================================================
+
+   Apache Xerces Java
+   Copyright 1999-2010 The Apache Software Foundation
+
+   This product includes software developed at
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Portions of this software were originally based on the following:
+     - software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
+     - software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
+     - voluntary contributions made by Paul Eng on behalf of the 
+       Apache Software Foundation that were originally developed at iClick, Inc.,
+       software copyright (c) 1999.
\ No newline at end of file
diff --git a/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000000000000000000000000000000000000..5f6c08eb062a3912d857f4a16d060c545db9ce27
--- /dev/null
+++ b/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1 @@
+org.python.jsr223.PyScriptEngineFactory
diff --git a/src/main/resources/ProxyDeserialization.class b/src/main/resources/ProxyDeserialization.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7a506acb80e24422b0210367eddc121d414725b
Binary files /dev/null and b/src/main/resources/ProxyDeserialization.class differ
diff --git a/src/main/resources/PythonLibs/BaseHTTPServer.py b/src/main/resources/PythonLibs/BaseHTTPServer.py
new file mode 100644
index 0000000000000000000000000000000000000000..deaf2f960b83c76b38b0c494db91202c70886833
--- /dev/null
+++ b/src/main/resources/PythonLibs/BaseHTTPServer.py
@@ -0,0 +1,603 @@
+"""HTTP server base class.
+
+Note: the class in this module doesn't implement any HTTP request; see
+SimpleHTTPServer for simple implementations of GET, HEAD and POST
+(including CGI scripts).  It does, however, optionally implement HTTP/1.1
+persistent connections, as of version 0.3.
+
+Contents:
+
+- BaseHTTPRequestHandler: HTTP request handler base class
+- test: test function
+
+XXX To do:
+
+- log requests even later (to capture byte count)
+- log user-agent header and other interesting goodies
+- send error log to separate file
+"""
+
+
+# See also:
+#
+# HTTP Working Group                                        T. Berners-Lee
+# INTERNET-DRAFT                                            R. T. Fielding
+# <draft-ietf-http-v10-spec-00.txt>                     H. Frystyk Nielsen
+# Expires September 8, 1995                                  March 8, 1995
+#
+# URL: http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt
+#
+# and
+#
+# Network Working Group                                      R. Fielding
+# Request for Comments: 2616                                       et al
+# Obsoletes: 2068                                              June 1999
+# Category: Standards Track
+#
+# URL: http://www.faqs.org/rfcs/rfc2616.html
+
+# Log files
+# ---------
+#
+# Here's a quote from the NCSA httpd docs about log file format.
+#
+# | The logfile format is as follows. Each line consists of:
+# |
+# | host rfc931 authuser [DD/Mon/YYYY:hh:mm:ss] "request" ddd bbbb
+# |
+# |        host: Either the DNS name or the IP number of the remote client
+# |        rfc931: Any information returned by identd for this person,
+# |                - otherwise.
+# |        authuser: If user sent a userid for authentication, the user name,
+# |                  - otherwise.
+# |        DD: Day
+# |        Mon: Month (calendar name)
+# |        YYYY: Year
+# |        hh: hour (24-hour format, the machine's timezone)
+# |        mm: minutes
+# |        ss: seconds
+# |        request: The first line of the HTTP request as sent by the client.
+# |        ddd: the status code returned by the server, - if not available.
+# |        bbbb: the total number of bytes sent,
+# |              *not including the HTTP/1.0 header*, - if not available
+# |
+# | You can determine the name of the file accessed through request.
+#
+# (Actually, the latter is only true if you know the server configuration
+# at the time the request was made!)
+
+__version__ = "0.3"
+
+__all__ = ["HTTPServer", "BaseHTTPRequestHandler"]
+
+import sys
+import time
+import socket # For gethostbyaddr()
+from warnings import filterwarnings, catch_warnings
+with catch_warnings():
+    if sys.py3kwarning:
+        filterwarnings("ignore", ".*mimetools has been removed",
+                        DeprecationWarning)
+    import mimetools
+import SocketServer
+
+# Default error message template
+DEFAULT_ERROR_MESSAGE = """\
+<head>
+<title>Error response</title>
+</head>
+<body>
+<h1>Error response</h1>
+<p>Error code %(code)d.
+<p>Message: %(message)s.
+<p>Error code explanation: %(code)s = %(explain)s.
+</body>
+"""
+
+DEFAULT_ERROR_CONTENT_TYPE = "text/html"
+
+def _quote_html(html):
+    return html.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
+
+class HTTPServer(SocketServer.TCPServer):
+
+    allow_reuse_address = 1    # Seems to make sense in testing environment
+
+    def server_bind(self):
+        """Override server_bind to store the server name."""
+        SocketServer.TCPServer.server_bind(self)
+        host, port = self.socket.getsockname()[:2]
+        self.server_name = socket.getfqdn(host)
+        self.server_port = port
+
+
+class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
+
+    """HTTP request handler base class.
+
+    The following explanation of HTTP serves to guide you through the
+    code as well as to expose any misunderstandings I may have about
+    HTTP (so you don't need to read the code to figure out I'm wrong
+    :-).
+
+    HTTP (HyperText Transfer Protocol) is an extensible protocol on
+    top of a reliable stream transport (e.g. TCP/IP).  The protocol
+    recognizes three parts to a request:
+
+    1. One line identifying the request type and path
+    2. An optional set of RFC-822-style headers
+    3. An optional data part
+
+    The headers and data are separated by a blank line.
+
+    The first line of the request has the form
+
+    <command> <path> <version>
+
+    where <command> is a (case-sensitive) keyword such as GET or POST,
+    <path> is a string containing path information for the request,
+    and <version> should be the string "HTTP/1.0" or "HTTP/1.1".
+    <path> is encoded using the URL encoding scheme (using %xx to signify
+    the ASCII character with hex code xx).
+
+    The specification specifies that lines are separated by CRLF but
+    for compatibility with the widest range of clients recommends
+    servers also handle LF.  Similarly, whitespace in the request line
+    is treated sensibly (allowing multiple spaces between components
+    and allowing trailing whitespace).
+
+    Similarly, for output, lines ought to be separated by CRLF pairs
+    but most clients grok LF characters just fine.
+
+    If the first line of the request has the form
+
+    <command> <path>
+
+    (i.e. <version> is left out) then this is assumed to be an HTTP
+    0.9 request; this form has no optional headers and data part and
+    the reply consists of just the data.
+
+    The reply form of the HTTP 1.x protocol again has three parts:
+
+    1. One line giving the response code
+    2. An optional set of RFC-822-style headers
+    3. The data
+
+    Again, the headers and data are separated by a blank line.
+
+    The response code line has the form
+
+    <version> <responsecode> <responsestring>
+
+    where <version> is the protocol version ("HTTP/1.0" or "HTTP/1.1"),
+    <responsecode> is a 3-digit response code indicating success or
+    failure of the request, and <responsestring> is an optional
+    human-readable string explaining what the response code means.
+
+    This server parses the request and the headers, and then calls a
+    function specific to the request type (<command>).  Specifically,
+    a request SPAM will be handled by a method do_SPAM().  If no
+    such method exists the server sends an error response to the
+    client.  If it exists, it is called with no arguments:
+
+    do_SPAM()
+
+    Note that the request name is case sensitive (i.e. SPAM and spam
+    are different requests).
+
+    The various request details are stored in instance variables:
+
+    - client_address is the client IP address in the form (host,
+    port);
+
+    - command, path and version are the broken-down request line;
+
+    - headers is an instance of mimetools.Message (or a derived
+    class) containing the header information;
+
+    - rfile is a file object open for reading positioned at the
+    start of the optional input data part;
+
+    - wfile is a file object open for writing.
+
+    IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!
+
+    The first thing to be written must be the response line.  Then
+    follow 0 or more header lines, then a blank line, and then the
+    actual data (if any).  The meaning of the header lines depends on
+    the command executed by the server; in most cases, when data is
+    returned, there should be at least one header line of the form
+
+    Content-type: <type>/<subtype>
+
+    where <type> and <subtype> should be registered MIME types,
+    e.g. "text/html" or "text/plain".
+
+    """
+
+    # The Python system version, truncated to its first component.
+    sys_version = "Python/" + sys.version.split()[0]
+
+    # The server software version.  You may want to override this.
+    # The format is multiple whitespace-separated strings,
+    # where each string is of the form name[/version].
+    server_version = "BaseHTTP/" + __version__
+
+    # The default request version.  This only affects responses up until
+    # the point where the request line is parsed, so it mainly decides what
+    # the client gets back when sending a malformed request line.
+    # Most web servers default to HTTP 0.9, i.e. don't send a status line.
+    default_request_version = "HTTP/0.9"
+
+    def parse_request(self):
+        """Parse a request (internal).
+
+        The request should be stored in self.raw_requestline; the results
+        are in self.command, self.path, self.request_version and
+        self.headers.
+
+        Return True for success, False for failure; on failure, an
+        error is sent back.
+
+        """
+        self.command = None  # set in case of error on the first line
+        self.request_version = version = self.default_request_version
+        self.close_connection = 1
+        requestline = self.raw_requestline
+        requestline = requestline.rstrip('\r\n')
+        self.requestline = requestline
+        words = requestline.split()
+        if len(words) == 3:
+            command, path, version = words
+            if version[:5] != 'HTTP/':
+                self.send_error(400, "Bad request version (%r)" % version)
+                return False
+            try:
+                base_version_number = version.split('/', 1)[1]
+                version_number = base_version_number.split(".")
+                # RFC 2145 section 3.1 says there can be only one "." and
+                #   - major and minor numbers MUST be treated as
+                #      separate integers;
+                #   - HTTP/2.4 is a lower version than HTTP/2.13, which in
+                #      turn is lower than HTTP/12.3;
+                #   - Leading zeros MUST be ignored by recipients.
+                if len(version_number) != 2:
+                    raise ValueError
+                version_number = int(version_number[0]), int(version_number[1])
+            except (ValueError, IndexError):
+                self.send_error(400, "Bad request version (%r)" % version)
+                return False
+            if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1":
+                self.close_connection = 0
+            if version_number >= (2, 0):
+                self.send_error(505,
+                          "Invalid HTTP Version (%s)" % base_version_number)
+                return False
+        elif len(words) == 2:
+            command, path = words
+            self.close_connection = 1
+            if command != 'GET':
+                self.send_error(400,
+                                "Bad HTTP/0.9 request type (%r)" % command)
+                return False
+        elif not words:
+            return False
+        else:
+            self.send_error(400, "Bad request syntax (%r)" % requestline)
+            return False
+        self.command, self.path, self.request_version = command, path, version
+
+        # Examine the headers and look for a Connection directive
+        self.headers = self.MessageClass(self.rfile, 0)
+
+        conntype = self.headers.get('Connection', "")
+        if conntype.lower() == 'close':
+            self.close_connection = 1
+        elif (conntype.lower() == 'keep-alive' and
+              self.protocol_version >= "HTTP/1.1"):
+            self.close_connection = 0
+        return True
+
+    def handle_one_request(self):
+        """Handle a single HTTP request.
+
+        You normally don't need to override this method; see the class
+        __doc__ string for information on how to handle specific HTTP
+        commands such as GET and POST.
+
+        """
+        try:
+            self.raw_requestline = self.rfile.readline(65537)
+            if len(self.raw_requestline) > 65536:
+                self.requestline = ''
+                self.request_version = ''
+                self.command = ''
+                self.send_error(414)
+                return
+            if not self.raw_requestline:
+                self.close_connection = 1
+                return
+            if not self.parse_request():
+                # An error code has been sent, just exit
+                return
+            mname = 'do_' + self.command
+            if not hasattr(self, mname):
+                self.send_error(501, "Unsupported method (%r)" % self.command)
+                return
+            method = getattr(self, mname)
+            method()
+            self.wfile.flush() #actually send the response if not already done.
+        except socket.timeout, e:
+            #a read or a write timed out.  Discard this connection
+            self.log_error("Request timed out: %r", e)
+            self.close_connection = 1
+            return
+
+    def handle(self):
+        """Handle multiple requests if necessary."""
+        self.close_connection = 1
+
+        self.handle_one_request()
+        while not self.close_connection:
+            self.handle_one_request()
+
+    def send_error(self, code, message=None):
+        """Send and log an error reply.
+
+        Arguments are the error code, and a detailed message.
+        The detailed message defaults to the short entry matching the
+        response code.
+
+        This sends an error response (so it must be called before any
+        output has been generated), logs the error, and finally sends
+        a piece of HTML explaining the error to the user.
+
+        """
+
+        try:
+            short, long = self.responses[code]
+        except KeyError:
+            short, long = '???', '???'
+        if message is None:
+            message = short
+        explain = long
+        self.log_error("code %d, message %s", code, message)
+        # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201)
+        content = (self.error_message_format %
+                   {'code': code, 'message': _quote_html(message), 'explain': explain})
+        self.send_response(code, message)
+        self.send_header("Content-Type", self.error_content_type)
+        self.send_header('Connection', 'close')
+        self.end_headers()
+        if self.command != 'HEAD' and code >= 200 and code not in (204, 304):
+            self.wfile.write(content)
+
+    error_message_format = DEFAULT_ERROR_MESSAGE
+    error_content_type = DEFAULT_ERROR_CONTENT_TYPE
+
+    def send_response(self, code, message=None):
+        """Send the response header and log the response code.
+
+        Also send two standard headers with the server software
+        version and the current date.
+
+        """
+        self.log_request(code)
+        if message is None:
+            if code in self.responses:
+                message = self.responses[code][0]
+            else:
+                message = ''
+        if self.request_version != 'HTTP/0.9':
+            self.wfile.write("%s %d %s\r\n" %
+                             (self.protocol_version, code, message))
+            # print (self.protocol_version, code, message)
+        self.send_header('Server', self.version_string())
+        self.send_header('Date', self.date_time_string())
+
+    def send_header(self, keyword, value):
+        """Send a MIME header."""
+        if self.request_version != 'HTTP/0.9':
+            self.wfile.write("%s: %s\r\n" % (keyword, value))
+
+        if keyword.lower() == 'connection':
+            if value.lower() == 'close':
+                self.close_connection = 1
+            elif value.lower() == 'keep-alive':
+                self.close_connection = 0
+
+    def end_headers(self):
+        """Send the blank line ending the MIME headers."""
+        if self.request_version != 'HTTP/0.9':
+            self.wfile.write("\r\n")
+
+    def log_request(self, code='-', size='-'):
+        """Log an accepted request.
+
+        This is called by send_response().
+
+        """
+
+        self.log_message('"%s" %s %s',
+                         self.requestline, str(code), str(size))
+
+    def log_error(self, format, *args):
+        """Log an error.
+
+        This is called when a request cannot be fulfilled.  By
+        default it passes the message on to log_message().
+
+        Arguments are the same as for log_message().
+
+        XXX This should go to the separate error log.
+
+        """
+
+        self.log_message(format, *args)
+
+    def log_message(self, format, *args):
+        """Log an arbitrary message.
+
+        This is used by all other logging functions.  Override
+        it if you have specific logging wishes.
+
+        The first argument, FORMAT, is a format string for the
+        message to be logged.  If the format string contains
+        any % escapes requiring parameters, they should be
+        specified as subsequent arguments (it's just like
+        printf!).
+
+        The client ip address and current date/time are prefixed to every
+        message.
+
+        """
+
+        sys.stderr.write("%s - - [%s] %s\n" %
+                         (self.client_address[0],
+                          self.log_date_time_string(),
+                          format%args))
+
+    def version_string(self):
+        """Return the server software version string."""
+        return self.server_version + ' ' + self.sys_version
+
+    def date_time_string(self, timestamp=None):
+        """Return the current date and time formatted for a message header."""
+        if timestamp is None:
+            timestamp = time.time()
+        year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp)
+        s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
+                self.weekdayname[wd],
+                day, self.monthname[month], year,
+                hh, mm, ss)
+        return s
+
+    def log_date_time_string(self):
+        """Return the current time formatted for logging."""
+        now = time.time()
+        year, month, day, hh, mm, ss, x, y, z = time.localtime(now)
+        s = "%02d/%3s/%04d %02d:%02d:%02d" % (
+                day, self.monthname[month], year, hh, mm, ss)
+        return s
+
+    weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+
+    monthname = [None,
+                 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+                 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+
+    def address_string(self):
+        """Return the client address formatted for logging.
+
+        This version looks up the full hostname using gethostbyaddr(),
+        and tries to find a name that contains at least one dot.
+
+        """
+
+        host, port = self.client_address[:2]
+        return socket.getfqdn(host)
+
+    # Essentially static class variables
+
+    # The version of the HTTP protocol we support.
+    # Set this to HTTP/1.1 to enable automatic keepalive
+    protocol_version = "HTTP/1.0"
+
+    # The Message-like class used to parse headers
+    MessageClass = mimetools.Message
+
+    # Table mapping response codes to messages; entries have the
+    # form {code: (shortmessage, longmessage)}.
+    # See RFC 2616.
+    responses = {
+        100: ('Continue', 'Request received, please continue'),
+        101: ('Switching Protocols',
+              'Switching to new protocol; obey Upgrade header'),
+
+        200: ('OK', 'Request fulfilled, document follows'),
+        201: ('Created', 'Document created, URL follows'),
+        202: ('Accepted',
+              'Request accepted, processing continues off-line'),
+        203: ('Non-Authoritative Information', 'Request fulfilled from cache'),
+        204: ('No Content', 'Request fulfilled, nothing follows'),
+        205: ('Reset Content', 'Clear input form for further input.'),
+        206: ('Partial Content', 'Partial content follows.'),
+
+        300: ('Multiple Choices',
+              'Object has several resources -- see URI list'),
+        301: ('Moved Permanently', 'Object moved permanently -- see URI list'),
+        302: ('Found', 'Object moved temporarily -- see URI list'),
+        303: ('See Other', 'Object moved -- see Method and URL list'),
+        304: ('Not Modified',
+              'Document has not changed since given time'),
+        305: ('Use Proxy',
+              'You must use proxy specified in Location to access this '
+              'resource.'),
+        307: ('Temporary Redirect',
+              'Object moved temporarily -- see URI list'),
+
+        400: ('Bad Request',
+              'Bad request syntax or unsupported method'),
+        401: ('Unauthorized',
+              'No permission -- see authorization schemes'),
+        402: ('Payment Required',
+              'No payment -- see charging schemes'),
+        403: ('Forbidden',
+              'Request forbidden -- authorization will not help'),
+        404: ('Not Found', 'Nothing matches the given URI'),
+        405: ('Method Not Allowed',
+              'Specified method is invalid for this resource.'),
+        406: ('Not Acceptable', 'URI not available in preferred format.'),
+        407: ('Proxy Authentication Required', 'You must authenticate with '
+              'this proxy before proceeding.'),
+        408: ('Request Timeout', 'Request timed out; try again later.'),
+        409: ('Conflict', 'Request conflict.'),
+        410: ('Gone',
+              'URI no longer exists and has been permanently removed.'),
+        411: ('Length Required', 'Client must specify Content-Length.'),
+        412: ('Precondition Failed', 'Precondition in headers is false.'),
+        413: ('Request Entity Too Large', 'Entity is too large.'),
+        414: ('Request-URI Too Long', 'URI is too long.'),
+        415: ('Unsupported Media Type', 'Entity body in unsupported format.'),
+        416: ('Requested Range Not Satisfiable',
+              'Cannot satisfy request range.'),
+        417: ('Expectation Failed',
+              'Expect condition could not be satisfied.'),
+
+        500: ('Internal Server Error', 'Server got itself in trouble'),
+        501: ('Not Implemented',
+              'Server does not support this operation'),
+        502: ('Bad Gateway', 'Invalid responses from another server/proxy.'),
+        503: ('Service Unavailable',
+              'The server cannot process the request due to a high load'),
+        504: ('Gateway Timeout',
+              'The gateway server did not receive a timely response'),
+        505: ('HTTP Version Not Supported', 'Cannot fulfill request.'),
+        }
+
+
+def test(HandlerClass = BaseHTTPRequestHandler,
+         ServerClass = HTTPServer, protocol="HTTP/1.0"):
+    """Test the HTTP request handler class.
+
+    This runs an HTTP server on port 8000 (or the first command line
+    argument).
+
+    """
+
+    if sys.argv[1:]:
+        port = int(sys.argv[1])
+    else:
+        port = 8000
+    server_address = ('', port)
+
+    HandlerClass.protocol_version = protocol
+    httpd = ServerClass(server_address, HandlerClass)
+
+    sa = httpd.socket.getsockname()
+    print "Serving HTTP on", sa[0], "port", sa[1], "..."
+    httpd.serve_forever()
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/CGIHTTPServer.py b/src/main/resources/PythonLibs/CGIHTTPServer.py
new file mode 100644
index 0000000000000000000000000000000000000000..47a994cab1fe90850dcecf79fd4a2ccbe46ba1f2
--- /dev/null
+++ b/src/main/resources/PythonLibs/CGIHTTPServer.py
@@ -0,0 +1,378 @@
+"""CGI-savvy HTTP Server.
+
+This module builds on SimpleHTTPServer by implementing GET and POST
+requests to cgi-bin scripts.
+
+If the os.fork() function is not present (e.g. on Windows),
+os.popen2() is used as a fallback, with slightly altered semantics; if
+that function is not present either (e.g. on Macintosh), only Python
+scripts are supported, and they are executed by the current process.
+
+In all cases, the implementation is intentionally naive -- all
+requests are executed sychronously.
+
+SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
+-- it may execute arbitrary Python code or external programs.
+
+Note that status code 200 is sent prior to execution of a CGI script, so
+scripts cannot send other status codes such as 302 (redirect).
+"""
+
+
+__version__ = "0.4"
+
+__all__ = ["CGIHTTPRequestHandler"]
+
+import os
+import sys
+import urllib
+import BaseHTTPServer
+import SimpleHTTPServer
+import select
+import copy
+
+
+class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+
+    """Complete HTTP server with GET, HEAD and POST commands.
+
+    GET and HEAD also support running CGI scripts.
+
+    The POST command is *only* implemented for CGI scripts.
+
+    """
+
+    # Determine platform specifics
+    have_fork = hasattr(os, 'fork')
+    have_popen2 = hasattr(os, 'popen2')
+    have_popen3 = hasattr(os, 'popen3')
+
+    # Make rfile unbuffered -- we need to read one line and then pass
+    # the rest to a subprocess, so we can't use buffered input.
+    rbufsize = 0
+
+    def do_POST(self):
+        """Serve a POST request.
+
+        This is only implemented for CGI scripts.
+
+        """
+
+        if self.is_cgi():
+            self.run_cgi()
+        else:
+            self.send_error(501, "Can only POST to CGI scripts")
+
+    def send_head(self):
+        """Version of send_head that support CGI scripts"""
+        if self.is_cgi():
+            return self.run_cgi()
+        else:
+            return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)
+
+    def is_cgi(self):
+        """Test whether self.path corresponds to a CGI script.
+
+        Returns True and updates the cgi_info attribute to the tuple
+        (dir, rest) if self.path requires running a CGI script.
+        Returns False otherwise.
+
+        If any exception is raised, the caller should assume that
+        self.path was rejected as invalid and act accordingly.
+
+        The default implementation tests whether the normalized url
+        path begins with one of the strings in self.cgi_directories
+        (and the next character is a '/' or the end of the string).
+        """
+        collapsed_path = _url_collapse_path(self.path)
+        dir_sep = collapsed_path.find('/', 1)
+        head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]
+        if head in self.cgi_directories:
+            self.cgi_info = head, tail
+            return True
+        return False
+
+    cgi_directories = ['/cgi-bin', '/htbin']
+
+    def is_executable(self, path):
+        """Test whether argument path is an executable file."""
+        return executable(path)
+
+    def is_python(self, path):
+        """Test whether argument path is a Python script."""
+        head, tail = os.path.splitext(path)
+        return tail.lower() in (".py", ".pyw")
+
+    def run_cgi(self):
+        """Execute a CGI script."""
+        path = self.path
+        dir, rest = self.cgi_info
+
+        i = path.find('/', len(dir) + 1)
+        while i >= 0:
+            nextdir = path[:i]
+            nextrest = path[i+1:]
+
+            scriptdir = self.translate_path(nextdir)
+            if os.path.isdir(scriptdir):
+                dir, rest = nextdir, nextrest
+                i = path.find('/', len(dir) + 1)
+            else:
+                break
+
+        # find an explicit query string, if present.
+        i = rest.rfind('?')
+        if i >= 0:
+            rest, query = rest[:i], rest[i+1:]
+        else:
+            query = ''
+
+        # dissect the part after the directory name into a script name &
+        # a possible additional path, to be stored in PATH_INFO.
+        i = rest.find('/')
+        if i >= 0:
+            script, rest = rest[:i], rest[i:]
+        else:
+            script, rest = rest, ''
+
+        scriptname = dir + '/' + script
+        scriptfile = self.translate_path(scriptname)
+        if not os.path.exists(scriptfile):
+            self.send_error(404, "No such CGI script (%r)" % scriptname)
+            return
+        if not os.path.isfile(scriptfile):
+            self.send_error(403, "CGI script is not a plain file (%r)" %
+                            scriptname)
+            return
+        ispy = self.is_python(scriptname)
+        if not ispy:
+            if not (self.have_fork or self.have_popen2 or self.have_popen3):
+                self.send_error(403, "CGI script is not a Python script (%r)" %
+                                scriptname)
+                return
+            if not self.is_executable(scriptfile):
+                self.send_error(403, "CGI script is not executable (%r)" %
+                                scriptname)
+                return
+
+        # Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html
+        # XXX Much of the following could be prepared ahead of time!
+        env = copy.deepcopy(os.environ)
+        env['SERVER_SOFTWARE'] = self.version_string()
+        env['SERVER_NAME'] = self.server.server_name
+        env['GATEWAY_INTERFACE'] = 'CGI/1.1'
+        env['SERVER_PROTOCOL'] = self.protocol_version
+        env['SERVER_PORT'] = str(self.server.server_port)
+        env['REQUEST_METHOD'] = self.command
+        uqrest = urllib.unquote(rest)
+        env['PATH_INFO'] = uqrest
+        env['PATH_TRANSLATED'] = self.translate_path(uqrest)
+        env['SCRIPT_NAME'] = scriptname
+        if query:
+            env['QUERY_STRING'] = query
+        host = self.address_string()
+        if host != self.client_address[0]:
+            env['REMOTE_HOST'] = host
+        env['REMOTE_ADDR'] = self.client_address[0]
+        authorization = self.headers.getheader("authorization")
+        if authorization:
+            authorization = authorization.split()
+            if len(authorization) == 2:
+                import base64, binascii
+                env['AUTH_TYPE'] = authorization[0]
+                if authorization[0].lower() == "basic":
+                    try:
+                        authorization = base64.decodestring(authorization[1])
+                    except binascii.Error:
+                        pass
+                    else:
+                        authorization = authorization.split(':')
+                        if len(authorization) == 2:
+                            env['REMOTE_USER'] = authorization[0]
+        # XXX REMOTE_IDENT
+        if self.headers.typeheader is None:
+            env['CONTENT_TYPE'] = self.headers.type
+        else:
+            env['CONTENT_TYPE'] = self.headers.typeheader
+        length = self.headers.getheader('content-length')
+        if length:
+            env['CONTENT_LENGTH'] = length
+        referer = self.headers.getheader('referer')
+        if referer:
+            env['HTTP_REFERER'] = referer
+        accept = []
+        for line in self.headers.getallmatchingheaders('accept'):
+            if line[:1] in "\t\n\r ":
+                accept.append(line.strip())
+            else:
+                accept = accept + line[7:].split(',')
+        env['HTTP_ACCEPT'] = ','.join(accept)
+        ua = self.headers.getheader('user-agent')
+        if ua:
+            env['HTTP_USER_AGENT'] = ua
+        co = filter(None, self.headers.getheaders('cookie'))
+        if co:
+            env['HTTP_COOKIE'] = ', '.join(co)
+        # XXX Other HTTP_* headers
+        # Since we're setting the env in the parent, provide empty
+        # values to override previously set values
+        for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH',
+                  'HTTP_USER_AGENT', 'HTTP_COOKIE', 'HTTP_REFERER'):
+            env.setdefault(k, "")
+
+        self.send_response(200, "Script output follows")
+
+        decoded_query = query.replace('+', ' ')
+
+        if self.have_fork:
+            # Unix -- fork as we should
+            args = [script]
+            if '=' not in decoded_query:
+                args.append(decoded_query)
+            nobody = nobody_uid()
+            self.wfile.flush() # Always flush before forking
+            pid = os.fork()
+            if pid != 0:
+                # Parent
+                pid, sts = os.waitpid(pid, 0)
+                # throw away additional data [see bug #427345]
+                while select.select([self.rfile], [], [], 0)[0]:
+                    if not self.rfile.read(1):
+                        break
+                if sts:
+                    self.log_error("CGI script exit status %#x", sts)
+                return
+            # Child
+            try:
+                try:
+                    os.setuid(nobody)
+                except os.error:
+                    pass
+                os.dup2(self.rfile.fileno(), 0)
+                os.dup2(self.wfile.fileno(), 1)
+                os.execve(scriptfile, args, env)
+            except:
+                self.server.handle_error(self.request, self.client_address)
+                os._exit(127)
+
+        else:
+            # Non Unix - use subprocess
+            import subprocess
+            cmdline = [scriptfile]
+            if self.is_python(scriptfile):
+                interp = sys.executable
+                if interp.lower().endswith("w.exe"):
+                    # On Windows, use python.exe, not pythonw.exe
+                    interp = interp[:-5] + interp[-4:]
+                cmdline = [interp, '-u'] + cmdline
+            if '=' not in query:
+                cmdline.append(query)
+
+            self.log_message("command: %s", subprocess.list2cmdline(cmdline))
+            try:
+                nbytes = int(length)
+            except (TypeError, ValueError):
+                nbytes = 0
+            p = subprocess.Popen(cmdline,
+                                 stdin = subprocess.PIPE,
+                                 stdout = subprocess.PIPE,
+                                 stderr = subprocess.PIPE,
+                                 env = env
+                                )
+            if self.command.lower() == "post" and nbytes > 0:
+                data = self.rfile.read(nbytes)
+            else:
+                data = None
+            # throw away additional data [see bug #427345]
+            while select.select([self.rfile._sock], [], [], 0)[0]:
+                if not self.rfile._sock.recv(1):
+                    break
+            stdout, stderr = p.communicate(data)
+            self.wfile.write(stdout)
+            if stderr:
+                self.log_error('%s', stderr)
+            p.stderr.close()
+            p.stdout.close()
+            status = p.returncode
+            if status:
+                self.log_error("CGI script exit status %#x", status)
+            else:
+                self.log_message("CGI script exited OK")
+
+
+def _url_collapse_path(path):
+    """
+    Given a URL path, remove extra '/'s and '.' path elements and collapse
+    any '..' references and returns a colllapsed path.
+
+    Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
+    The utility of this function is limited to is_cgi method and helps
+    preventing some security attacks.
+
+    Returns: A tuple of (head, tail) where tail is everything after the final /
+    and head is everything before it.  Head will always start with a '/' and,
+    if it contains anything else, never have a trailing '/'.
+
+    Raises: IndexError if too many '..' occur within the path.
+
+    """
+    # Similar to os.path.split(os.path.normpath(path)) but specific to URL
+    # path semantics rather than local operating system semantics.
+    path_parts = path.split('/')
+    head_parts = []
+    for part in path_parts[:-1]:
+        if part == '..':
+            head_parts.pop() # IndexError if more '..' than prior parts
+        elif part and part != '.':
+            head_parts.append( part )
+    if path_parts:
+        tail_part = path_parts.pop()
+        if tail_part:
+            if tail_part == '..':
+                head_parts.pop()
+                tail_part = ''
+            elif tail_part == '.':
+                tail_part = ''
+    else:
+        tail_part = ''
+
+    splitpath = ('/' + '/'.join(head_parts), tail_part)
+    collapsed_path = "/".join(splitpath)
+
+    return collapsed_path
+
+
+nobody = None
+
+def nobody_uid():
+    """Internal routine to get nobody's uid"""
+    global nobody
+    if nobody:
+        return nobody
+    try:
+        import pwd
+    except ImportError:
+        return -1
+    try:
+        nobody = pwd.getpwnam('nobody')[2]
+    except KeyError:
+        nobody = 1 + max(map(lambda x: x[2], pwd.getpwall()))
+    return nobody
+
+
+def executable(path):
+    """Test for executable file."""
+    try:
+        st = os.stat(path)
+    except os.error:
+        return False
+    return st.st_mode & 0111 != 0
+
+
+def test(HandlerClass = CGIHTTPRequestHandler,
+         ServerClass = BaseHTTPServer.HTTPServer):
+    SimpleHTTPServer.test(HandlerClass, ServerClass)
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/ConfigParser.py b/src/main/resources/PythonLibs/ConfigParser.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e6cdbc30a766f55933cca102afd564522a50806
--- /dev/null
+++ b/src/main/resources/PythonLibs/ConfigParser.py
@@ -0,0 +1,753 @@
+"""Configuration file parser.
+
+A setup file consists of sections, lead by a "[section]" header,
+and followed by "name: value" entries, with continuations and such in
+the style of RFC 822.
+
+The option values can contain format strings which refer to other values in
+the same section, or values in a special [DEFAULT] section.
+
+For example:
+
+    something: %(dir)s/whatever
+
+would resolve the "%(dir)s" to the value of dir.  All reference
+expansions are done late, on demand.
+
+Intrinsic defaults can be specified by passing them into the
+ConfigParser constructor as a dictionary.
+
+class:
+
+ConfigParser -- responsible for parsing a list of
+                configuration files, and managing the parsed database.
+
+    methods:
+
+    __init__(defaults=None)
+        create the parser and specify a dictionary of intrinsic defaults.  The
+        keys must be strings, the values must be appropriate for %()s string
+        interpolation.  Note that `__name__' is always an intrinsic default;
+        its value is the section's name.
+
+    sections()
+        return all the configuration section names, sans DEFAULT
+
+    has_section(section)
+        return whether the given section exists
+
+    has_option(section, option)
+        return whether the given option exists in the given section
+
+    options(section)
+        return list of configuration options for the named section
+
+    read(filenames)
+        read and parse the list of named configuration files, given by
+        name.  A single filename is also allowed.  Non-existing files
+        are ignored.  Return list of successfully read files.
+
+    readfp(fp, filename=None)
+        read and parse one configuration file, given as a file object.
+        The filename defaults to fp.name; it is only used in error
+        messages (if fp has no `name' attribute, the string `<???>' is used).
+
+    get(section, option, raw=False, vars=None)
+        return a string value for the named option.  All % interpolations are
+        expanded in the return values, based on the defaults passed into the
+        constructor and the DEFAULT section.  Additional substitutions may be
+        provided using the `vars' argument, which must be a dictionary whose
+        contents override any pre-existing defaults.
+
+    getint(section, options)
+        like get(), but convert value to an integer
+
+    getfloat(section, options)
+        like get(), but convert value to a float
+
+    getboolean(section, options)
+        like get(), but convert value to a boolean (currently case
+        insensitively defined as 0, false, no, off for False, and 1, true,
+        yes, on for True).  Returns False or True.
+
+    items(section, raw=False, vars=None)
+        return a list of tuples with (name, value) for each option
+        in the section.
+
+    remove_section(section)
+        remove the given file section and all its options
+
+    remove_option(section, option)
+        remove the given option from the given section
+
+    set(section, option, value)
+        set the given option
+
+    write(fp)
+        write the configuration state in .ini format
+"""
+
+try:
+    from collections import OrderedDict as _default_dict
+except ImportError:
+    # fallback for setup.py which hasn't yet built _collections
+    _default_dict = dict
+
+import re
+
+__all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError",
+           "InterpolationError", "InterpolationDepthError",
+           "InterpolationSyntaxError", "ParsingError",
+           "MissingSectionHeaderError",
+           "ConfigParser", "SafeConfigParser", "RawConfigParser",
+           "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
+
+DEFAULTSECT = "DEFAULT"
+
+MAX_INTERPOLATION_DEPTH = 10
+
+
+
+# exception classes
+class Error(Exception):
+    """Base class for ConfigParser exceptions."""
+
+    def _get_message(self):
+        """Getter for 'message'; needed only to override deprecation in
+        BaseException."""
+        return self.__message
+
+    def _set_message(self, value):
+        """Setter for 'message'; needed only to override deprecation in
+        BaseException."""
+        self.__message = value
+
+    # BaseException.message has been deprecated since Python 2.6.  To prevent
+    # DeprecationWarning from popping up over this pre-existing attribute, use
+    # a new property that takes lookup precedence.
+    message = property(_get_message, _set_message)
+
+    def __init__(self, msg=''):
+        self.message = msg
+        Exception.__init__(self, msg)
+
+    def __repr__(self):
+        return self.message
+
+    __str__ = __repr__
+
+class NoSectionError(Error):
+    """Raised when no section matches a requested option."""
+
+    def __init__(self, section):
+        Error.__init__(self, 'No section: %r' % (section,))
+        self.section = section
+        self.args = (section, )
+
+class DuplicateSectionError(Error):
+    """Raised when a section is multiply-created."""
+
+    def __init__(self, section):
+        Error.__init__(self, "Section %r already exists" % section)
+        self.section = section
+        self.args = (section, )
+
+class NoOptionError(Error):
+    """A requested option was not found."""
+
+    def __init__(self, option, section):
+        Error.__init__(self, "No option %r in section: %r" %
+                       (option, section))
+        self.option = option
+        self.section = section
+        self.args = (option, section)
+
+class InterpolationError(Error):
+    """Base class for interpolation-related exceptions."""
+
+    def __init__(self, option, section, msg):
+        Error.__init__(self, msg)
+        self.option = option
+        self.section = section
+        self.args = (option, section, msg)
+
+class InterpolationMissingOptionError(InterpolationError):
+    """A string substitution required a setting which was not available."""
+
+    def __init__(self, option, section, rawval, reference):
+        msg = ("Bad value substitution:\n"
+               "\tsection: [%s]\n"
+               "\toption : %s\n"
+               "\tkey    : %s\n"
+               "\trawval : %s\n"
+               % (section, option, reference, rawval))
+        InterpolationError.__init__(self, option, section, msg)
+        self.reference = reference
+        self.args = (option, section, rawval, reference)
+
+class InterpolationSyntaxError(InterpolationError):
+    """Raised when the source text into which substitutions are made
+    does not conform to the required syntax."""
+
+class InterpolationDepthError(InterpolationError):
+    """Raised when substitutions are nested too deeply."""
+
+    def __init__(self, option, section, rawval):
+        msg = ("Value interpolation too deeply recursive:\n"
+               "\tsection: [%s]\n"
+               "\toption : %s\n"
+               "\trawval : %s\n"
+               % (section, option, rawval))
+        InterpolationError.__init__(self, option, section, msg)
+        self.args = (option, section, rawval)
+
+class ParsingError(Error):
+    """Raised when a configuration file does not follow legal syntax."""
+
+    def __init__(self, filename):
+        Error.__init__(self, 'File contains parsing errors: %s' % filename)
+        self.filename = filename
+        self.errors = []
+        self.args = (filename, )
+
+    def append(self, lineno, line):
+        self.errors.append((lineno, line))
+        self.message += '\n\t[line %2d]: %s' % (lineno, line)
+
+class MissingSectionHeaderError(ParsingError):
+    """Raised when a key-value pair is found before any section header."""
+
+    def __init__(self, filename, lineno, line):
+        Error.__init__(
+            self,
+            'File contains no section headers.\nfile: %s, line: %d\n%r' %
+            (filename, lineno, line))
+        self.filename = filename
+        self.lineno = lineno
+        self.line = line
+        self.args = (filename, lineno, line)
+
+
+class RawConfigParser:
+    def __init__(self, defaults=None, dict_type=_default_dict,
+                 allow_no_value=False):
+        self._dict = dict_type
+        self._sections = self._dict()
+        self._defaults = self._dict()
+        if allow_no_value:
+            self._optcre = self.OPTCRE_NV
+        else:
+            self._optcre = self.OPTCRE
+        if defaults:
+            for key, value in defaults.items():
+                self._defaults[self.optionxform(key)] = value
+
+    def defaults(self):
+        return self._defaults
+
+    def sections(self):
+        """Return a list of section names, excluding [DEFAULT]"""
+        # self._sections will never have [DEFAULT] in it
+        return self._sections.keys()
+
+    def add_section(self, section):
+        """Create a new section in the configuration.
+
+        Raise DuplicateSectionError if a section by the specified name
+        already exists. Raise ValueError if name is DEFAULT or any of it's
+        case-insensitive variants.
+        """
+        if section.lower() == "default":
+            raise ValueError, 'Invalid section name: %s' % section
+
+        if section in self._sections:
+            raise DuplicateSectionError(section)
+        self._sections[section] = self._dict()
+
+    def has_section(self, section):
+        """Indicate whether the named section is present in the configuration.
+
+        The DEFAULT section is not acknowledged.
+        """
+        return section in self._sections
+
+    def options(self, section):
+        """Return a list of option names for the given section name."""
+        try:
+            opts = self._sections[section].copy()
+        except KeyError:
+            raise NoSectionError(section)
+        opts.update(self._defaults)
+        if '__name__' in opts:
+            del opts['__name__']
+        return opts.keys()
+
+    def read(self, filenames):
+        """Read and parse a filename or a list of filenames.
+
+        Files that cannot be opened are silently ignored; this is
+        designed so that you can specify a list of potential
+        configuration file locations (e.g. current directory, user's
+        home directory, systemwide directory), and all existing
+        configuration files in the list will be read.  A single
+        filename may also be given.
+
+        Return list of successfully read files.
+        """
+        if isinstance(filenames, basestring):
+            filenames = [filenames]
+        read_ok = []
+        for filename in filenames:
+            try:
+                fp = open(filename)
+            except IOError:
+                continue
+            self._read(fp, filename)
+            fp.close()
+            read_ok.append(filename)
+        return read_ok
+
+    def readfp(self, fp, filename=None):
+        """Like read() but the argument must be a file-like object.
+
+        The `fp' argument must have a `readline' method.  Optional
+        second argument is the `filename', which if not given, is
+        taken from fp.name.  If fp has no `name' attribute, `<???>' is
+        used.
+
+        """
+        if filename is None:
+            try:
+                filename = fp.name
+            except AttributeError:
+                filename = '<???>'
+        self._read(fp, filename)
+
+    def get(self, section, option):
+        opt = self.optionxform(option)
+        if section not in self._sections:
+            if section != DEFAULTSECT:
+                raise NoSectionError(section)
+            if opt in self._defaults:
+                return self._defaults[opt]
+            else:
+                raise NoOptionError(option, section)
+        elif opt in self._sections[section]:
+            return self._sections[section][opt]
+        elif opt in self._defaults:
+            return self._defaults[opt]
+        else:
+            raise NoOptionError(option, section)
+
+    def items(self, section):
+        try:
+            d2 = self._sections[section]
+        except KeyError:
+            if section != DEFAULTSECT:
+                raise NoSectionError(section)
+            d2 = self._dict()
+        d = self._defaults.copy()
+        d.update(d2)
+        if "__name__" in d:
+            del d["__name__"]
+        return d.items()
+
+    def _get(self, section, conv, option):
+        return conv(self.get(section, option))
+
+    def getint(self, section, option):
+        return self._get(section, int, option)
+
+    def getfloat(self, section, option):
+        return self._get(section, float, option)
+
+    _boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
+                       '0': False, 'no': False, 'false': False, 'off': False}
+
+    def getboolean(self, section, option):
+        v = self.get(section, option)
+        if v.lower() not in self._boolean_states:
+            raise ValueError, 'Not a boolean: %s' % v
+        return self._boolean_states[v.lower()]
+
+    def optionxform(self, optionstr):
+        return optionstr.lower()
+
+    def has_option(self, section, option):
+        """Check for the existence of a given option in a given section."""
+        if not section or section == DEFAULTSECT:
+            option = self.optionxform(option)
+            return option in self._defaults
+        elif section not in self._sections:
+            return False
+        else:
+            option = self.optionxform(option)
+            return (option in self._sections[section]
+                    or option in self._defaults)
+
+    def set(self, section, option, value=None):
+        """Set an option."""
+        if not section or section == DEFAULTSECT:
+            sectdict = self._defaults
+        else:
+            try:
+                sectdict = self._sections[section]
+            except KeyError:
+                raise NoSectionError(section)
+        sectdict[self.optionxform(option)] = value
+
+    def write(self, fp):
+        """Write an .ini-format representation of the configuration state."""
+        if self._defaults:
+            fp.write("[%s]\n" % DEFAULTSECT)
+            for (key, value) in self._defaults.items():
+                fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
+            fp.write("\n")
+        for section in self._sections:
+            fp.write("[%s]\n" % section)
+            for (key, value) in self._sections[section].items():
+                if key == "__name__":
+                    continue
+                if (value is not None) or (self._optcre == self.OPTCRE):
+                    key = " = ".join((key, str(value).replace('\n', '\n\t')))
+                fp.write("%s\n" % (key))
+            fp.write("\n")
+
+    def remove_option(self, section, option):
+        """Remove an option."""
+        if not section or section == DEFAULTSECT:
+            sectdict = self._defaults
+        else:
+            try:
+                sectdict = self._sections[section]
+            except KeyError:
+                raise NoSectionError(section)
+        option = self.optionxform(option)
+        existed = option in sectdict
+        if existed:
+            del sectdict[option]
+        return existed
+
+    def remove_section(self, section):
+        """Remove a file section."""
+        existed = section in self._sections
+        if existed:
+            del self._sections[section]
+        return existed
+
+    #
+    # Regular expressions for parsing section headers and options.
+    #
+    SECTCRE = re.compile(
+        r'\['                                 # [
+        r'(?P<header>[^]]+)'                  # very permissive!
+        r'\]'                                 # ]
+        )
+    OPTCRE = re.compile(
+        r'(?P<option>[^:=\s][^:=]*)'          # very permissive!
+        r'\s*(?P<vi>[:=])\s*'                 # any number of space/tab,
+                                              # followed by separator
+                                              # (either : or =), followed
+                                              # by any # space/tab
+        r'(?P<value>.*)$'                     # everything up to eol
+        )
+    OPTCRE_NV = re.compile(
+        r'(?P<option>[^:=\s][^:=]*)'          # very permissive!
+        r'\s*(?:'                             # any number of space/tab,
+        r'(?P<vi>[:=])\s*'                    # optionally followed by
+                                              # separator (either : or
+                                              # =), followed by any #
+                                              # space/tab
+        r'(?P<value>.*))?$'                   # everything up to eol
+        )
+
+    def _read(self, fp, fpname):
+        """Parse a sectioned setup file.
+
+        The sections in setup file contains a title line at the top,
+        indicated by a name in square brackets (`[]'), plus key/value
+        options lines, indicated by `name: value' format lines.
+        Continuations are represented by an embedded newline then
+        leading whitespace.  Blank lines, lines beginning with a '#',
+        and just about everything else are ignored.
+        """
+        cursect = None                        # None, or a dictionary
+        optname = None
+        lineno = 0
+        e = None                              # None, or an exception
+        while True:
+            line = fp.readline()
+            if not line:
+                break
+            lineno = lineno + 1
+            # comment or blank line?
+            if line.strip() == '' or line[0] in '#;':
+                continue
+            if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
+                # no leading whitespace
+                continue
+            # continuation line?
+            if line[0].isspace() and cursect is not None and optname:
+                value = line.strip()
+                if value:
+                    cursect[optname].append(value)
+            # a section header or option header?
+            else:
+                # is it a section header?
+                mo = self.SECTCRE.match(line)
+                if mo:
+                    sectname = mo.group('header')
+                    if sectname in self._sections:
+                        cursect = self._sections[sectname]
+                    elif sectname == DEFAULTSECT:
+                        cursect = self._defaults
+                    else:
+                        cursect = self._dict()
+                        cursect['__name__'] = sectname
+                        self._sections[sectname] = cursect
+                    # So sections can't start with a continuation line
+                    optname = None
+                # no section header in the file?
+                elif cursect is None:
+                    raise MissingSectionHeaderError(fpname, lineno, line)
+                # an option line?
+                else:
+                    mo = self._optcre.match(line)
+                    if mo:
+                        optname, vi, optval = mo.group('option', 'vi', 'value')
+                        optname = self.optionxform(optname.rstrip())
+                        # This check is fine because the OPTCRE cannot
+                        # match if it would set optval to None
+                        if optval is not None:
+                            if vi in ('=', ':') and ';' in optval:
+                                # ';' is a comment delimiter only if it follows
+                                # a spacing character
+                                pos = optval.find(';')
+                                if pos != -1 and optval[pos-1].isspace():
+                                    optval = optval[:pos]
+                            optval = optval.strip()
+                            # allow empty values
+                            if optval == '""':
+                                optval = ''
+                            cursect[optname] = [optval]
+                        else:
+                            # valueless option handling
+                            cursect[optname] = optval
+                    else:
+                        # a non-fatal parsing error occurred.  set up the
+                        # exception but keep going. the exception will be
+                        # raised at the end of the file and will contain a
+                        # list of all bogus lines
+                        if not e:
+                            e = ParsingError(fpname)
+                        e.append(lineno, repr(line))
+        # if any parsing errors occurred, raise an exception
+        if e:
+            raise e
+
+        # join the multi-line values collected while reading
+        all_sections = [self._defaults]
+        all_sections.extend(self._sections.values())
+        for options in all_sections:
+            for name, val in options.items():
+                if isinstance(val, list):
+                    options[name] = '\n'.join(val)
+
+import UserDict as _UserDict
+
+class _Chainmap(_UserDict.DictMixin):
+    """Combine multiple mappings for successive lookups.
+
+    For example, to emulate Python's normal lookup sequence:
+
+        import __builtin__
+        pylookup = _Chainmap(locals(), globals(), vars(__builtin__))
+    """
+
+    def __init__(self, *maps):
+        self._maps = maps
+
+    def __getitem__(self, key):
+        for mapping in self._maps:
+            try:
+                return mapping[key]
+            except KeyError:
+                pass
+        raise KeyError(key)
+
+    def keys(self):
+        result = []
+        seen = set()
+        for mapping in self._maps:
+            for key in mapping:
+                if key not in seen:
+                    result.append(key)
+                    seen.add(key)
+        return result
+
+class ConfigParser(RawConfigParser):
+
+    def get(self, section, option, raw=False, vars=None):
+        """Get an option value for a given section.
+
+        If `vars' is provided, it must be a dictionary. The option is looked up
+        in `vars' (if provided), `section', and in `defaults' in that order.
+
+        All % interpolations are expanded in the return values, unless the
+        optional argument `raw' is true. Values for interpolation keys are
+        looked up in the same manner as the option.
+
+        The section DEFAULT is special.
+        """
+        sectiondict = {}
+        try:
+            sectiondict = self._sections[section]
+        except KeyError:
+            if section != DEFAULTSECT:
+                raise NoSectionError(section)
+        # Update with the entry specific variables
+        vardict = {}
+        if vars:
+            for key, value in vars.items():
+                vardict[self.optionxform(key)] = value
+        d = _Chainmap(vardict, sectiondict, self._defaults)
+        option = self.optionxform(option)
+        try:
+            value = d[option]
+        except KeyError:
+            raise NoOptionError(option, section)
+
+        if raw or value is None:
+            return value
+        else:
+            return self._interpolate(section, option, value, d)
+
+    def items(self, section, raw=False, vars=None):
+        """Return a list of tuples with (name, value) for each option
+        in the section.
+
+        All % interpolations are expanded in the return values, based on the
+        defaults passed into the constructor, unless the optional argument
+        `raw' is true.  Additional substitutions may be provided using the
+        `vars' argument, which must be a dictionary whose contents overrides
+        any pre-existing defaults.
+
+        The section DEFAULT is special.
+        """
+        d = self._defaults.copy()
+        try:
+            d.update(self._sections[section])
+        except KeyError:
+            if section != DEFAULTSECT:
+                raise NoSectionError(section)
+        # Update with the entry specific variables
+        if vars:
+            for key, value in vars.items():
+                d[self.optionxform(key)] = value
+        options = d.keys()
+        if "__name__" in options:
+            options.remove("__name__")
+        if raw:
+            return [(option, d[option])
+                    for option in options]
+        else:
+            return [(option, self._interpolate(section, option, d[option], d))
+                    for option in options]
+
+    def _interpolate(self, section, option, rawval, vars):
+        # do the string interpolation
+        value = rawval
+        depth = MAX_INTERPOLATION_DEPTH
+        while depth:                    # Loop through this until it's done
+            depth -= 1
+            if value and "%(" in value:
+                value = self._KEYCRE.sub(self._interpolation_replace, value)
+                try:
+                    value = value % vars
+                except KeyError, e:
+                    raise InterpolationMissingOptionError(
+                        option, section, rawval, e.args[0])
+            else:
+                break
+        if value and "%(" in value:
+            raise InterpolationDepthError(option, section, rawval)
+        return value
+
+    _KEYCRE = re.compile(r"%\(([^)]*)\)s|.")
+
+    def _interpolation_replace(self, match):
+        s = match.group(1)
+        if s is None:
+            return match.group()
+        else:
+            return "%%(%s)s" % self.optionxform(s)
+
+
+class SafeConfigParser(ConfigParser):
+
+    def _interpolate(self, section, option, rawval, vars):
+        # do the string interpolation
+        L = []
+        self._interpolate_some(option, L, rawval, section, vars, 1)
+        return ''.join(L)
+
+    _interpvar_re = re.compile(r"%\(([^)]+)\)s")
+
+    def _interpolate_some(self, option, accum, rest, section, map, depth):
+        if depth > MAX_INTERPOLATION_DEPTH:
+            raise InterpolationDepthError(option, section, rest)
+        while rest:
+            p = rest.find("%")
+            if p < 0:
+                accum.append(rest)
+                return
+            if p > 0:
+                accum.append(rest[:p])
+                rest = rest[p:]
+            # p is no longer used
+            c = rest[1:2]
+            if c == "%":
+                accum.append("%")
+                rest = rest[2:]
+            elif c == "(":
+                m = self._interpvar_re.match(rest)
+                if m is None:
+                    raise InterpolationSyntaxError(option, section,
+                        "bad interpolation variable reference %r" % rest)
+                var = self.optionxform(m.group(1))
+                rest = rest[m.end():]
+                try:
+                    v = map[var]
+                except KeyError:
+                    raise InterpolationMissingOptionError(
+                        option, section, rest, var)
+                if "%" in v:
+                    self._interpolate_some(option, accum, v,
+                                           section, map, depth + 1)
+                else:
+                    accum.append(v)
+            else:
+                raise InterpolationSyntaxError(
+                    option, section,
+                    "'%%' must be followed by '%%' or '(', found: %r" % (rest,))
+
+    def set(self, section, option, value=None):
+        """Set an option.  Extend ConfigParser.set: check for string values."""
+        # The only legal non-string value if we allow valueless
+        # options is None, so we need to check if the value is a
+        # string if:
+        # - we do not allow valueless options, or
+        # - we allow valueless options but the value is not None
+        if self._optcre is self.OPTCRE or value:
+            if not isinstance(value, basestring):
+                raise TypeError("option values must be strings")
+        if value is not None:
+            # check for bad percent signs:
+            # first, replace all "good" interpolations
+            tmp_value = value.replace('%%', '')
+            tmp_value = self._interpvar_re.sub('', tmp_value)
+            # then, check if there's a lone percent sign left
+            if '%' in tmp_value:
+                raise ValueError("invalid interpolation syntax in %r at "
+                                "position %d" % (value, tmp_value.find('%')))
+        ConfigParser.set(self, section, option, value)
diff --git a/src/main/resources/PythonLibs/Cookie.py b/src/main/resources/PythonLibs/Cookie.py
new file mode 100644
index 0000000000000000000000000000000000000000..2eda48c0bb156c12c07ab1ac761b346e77c727db
--- /dev/null
+++ b/src/main/resources/PythonLibs/Cookie.py
@@ -0,0 +1,761 @@
+#!/usr/bin/env python
+#
+
+####
+# Copyright 2000 by Timothy O'Malley <timo@alum.mit.edu>
+#
+#                All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software
+# and its documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appear in all
+# copies and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Timothy O'Malley  not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# Timothy O'Malley DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL Timothy O'Malley BE LIABLE FOR
+# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+#
+####
+#
+# Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp
+#   by Timothy O'Malley <timo@alum.mit.edu>
+#
+#  Cookie.py is a Python module for the handling of HTTP
+#  cookies as a Python dictionary.  See RFC 2109 for more
+#  information on cookies.
+#
+#  The original idea to treat Cookies as a dictionary came from
+#  Dave Mitchell (davem@magnet.com) in 1995, when he released the
+#  first version of nscookie.py.
+#
+####
+
+r"""
+Here's a sample session to show how to use this module.
+At the moment, this is the only documentation.
+
+The Basics
+----------
+
+Importing is easy..
+
+   >>> import Cookie
+
+Most of the time you start by creating a cookie.  Cookies come in
+three flavors, each with slightly different encoding semantics, but
+more on that later.
+
+   >>> C = Cookie.SimpleCookie()
+   >>> C = Cookie.SerialCookie()
+   >>> C = Cookie.SmartCookie()
+
+[Note: Long-time users of Cookie.py will remember using
+Cookie.Cookie() to create an Cookie object.  Although deprecated, it
+is still supported by the code.  See the Backward Compatibility notes
+for more information.]
+
+Once you've created your Cookie, you can add values just as if it were
+a dictionary.
+
+   >>> C = Cookie.SmartCookie()
+   >>> C["fig"] = "newton"
+   >>> C["sugar"] = "wafer"
+   >>> C.output()
+   'Set-Cookie: fig=newton\r\nSet-Cookie: sugar=wafer'
+
+Notice that the printable representation of a Cookie is the
+appropriate format for a Set-Cookie: header.  This is the
+default behavior.  You can change the header and printed
+attributes by using the .output() function
+
+   >>> C = Cookie.SmartCookie()
+   >>> C["rocky"] = "road"
+   >>> C["rocky"]["path"] = "/cookie"
+   >>> print C.output(header="Cookie:")
+   Cookie: rocky=road; Path=/cookie
+   >>> print C.output(attrs=[], header="Cookie:")
+   Cookie: rocky=road
+
+The load() method of a Cookie extracts cookies from a string.  In a
+CGI script, you would use this method to extract the cookies from the
+HTTP_COOKIE environment variable.
+
+   >>> C = Cookie.SmartCookie()
+   >>> C.load("chips=ahoy; vienna=finger")
+   >>> C.output()
+   'Set-Cookie: chips=ahoy\r\nSet-Cookie: vienna=finger'
+
+The load() method is darn-tootin smart about identifying cookies
+within a string.  Escaped quotation marks, nested semicolons, and other
+such trickeries do not confuse it.
+
+   >>> C = Cookie.SmartCookie()
+   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
+   >>> print C
+   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"
+
+Each element of the Cookie also supports all of the RFC 2109
+Cookie attributes.  Here's an example which sets the Path
+attribute.
+
+   >>> C = Cookie.SmartCookie()
+   >>> C["oreo"] = "doublestuff"
+   >>> C["oreo"]["path"] = "/"
+   >>> print C
+   Set-Cookie: oreo=doublestuff; Path=/
+
+Each dictionary element has a 'value' attribute, which gives you
+back the value associated with the key.
+
+   >>> C = Cookie.SmartCookie()
+   >>> C["twix"] = "none for you"
+   >>> C["twix"].value
+   'none for you'
+
+
+A Bit More Advanced
+-------------------
+
+As mentioned before, there are three different flavors of Cookie
+objects, each with different encoding/decoding semantics.  This
+section briefly discusses the differences.
+
+SimpleCookie
+
+The SimpleCookie expects that all values should be standard strings.
+Just to be sure, SimpleCookie invokes the str() builtin to convert
+the value to a string, when the values are set dictionary-style.
+
+   >>> C = Cookie.SimpleCookie()
+   >>> C["number"] = 7
+   >>> C["string"] = "seven"
+   >>> C["number"].value
+   '7'
+   >>> C["string"].value
+   'seven'
+   >>> C.output()
+   'Set-Cookie: number=7\r\nSet-Cookie: string=seven'
+
+
+SerialCookie
+
+The SerialCookie expects that all values should be serialized using
+cPickle (or pickle, if cPickle isn't available).  As a result of
+serializing, SerialCookie can save almost any Python object to a
+value, and recover the exact same object when the cookie has been
+returned.  (SerialCookie can yield some strange-looking cookie
+values, however.)
+
+   >>> C = Cookie.SerialCookie()
+   >>> C["number"] = 7
+   >>> C["string"] = "seven"
+   >>> C["number"].value
+   7
+   >>> C["string"].value
+   'seven'
+   >>> C.output()
+   'Set-Cookie: number="I7\\012."\r\nSet-Cookie: string="S\'seven\'\\012p1\\012."'
+
+Be warned, however, if SerialCookie cannot de-serialize a value (because
+it isn't a valid pickle'd object), IT WILL RAISE AN EXCEPTION.
+
+
+SmartCookie
+
+The SmartCookie combines aspects of each of the other two flavors.
+When setting a value in a dictionary-fashion, the SmartCookie will
+serialize (ala cPickle) the value *if and only if* it isn't a
+Python string.  String objects are *not* serialized.  Similarly,
+when the load() method parses out values, it attempts to de-serialize
+the value.  If it fails, then it fallsback to treating the value
+as a string.
+
+   >>> C = Cookie.SmartCookie()
+   >>> C["number"] = 7
+   >>> C["string"] = "seven"
+   >>> C["number"].value
+   7
+   >>> C["string"].value
+   'seven'
+   >>> C.output()
+   'Set-Cookie: number="I7\\012."\r\nSet-Cookie: string=seven'
+
+
+Backwards Compatibility
+-----------------------
+
+In order to keep compatibilty with earlier versions of Cookie.py,
+it is still possible to use Cookie.Cookie() to create a Cookie.  In
+fact, this simply returns a SmartCookie.
+
+   >>> C = Cookie.Cookie()
+   >>> print C.__class__.__name__
+   SmartCookie
+
+
+Finis.
+"""  #"
+#     ^
+#     |----helps out font-lock
+
+#
+# Import our required modules
+#
+import string
+
+try:
+    from cPickle import dumps, loads
+except ImportError:
+    from pickle import dumps, loads
+
+import re, warnings
+
+__all__ = ["CookieError","BaseCookie","SimpleCookie","SerialCookie",
+           "SmartCookie","Cookie"]
+
+_nulljoin = ''.join
+_semispacejoin = '; '.join
+_spacejoin = ' '.join
+
+#
+# Define an exception visible to External modules
+#
+class CookieError(Exception):
+    pass
+
+
+# These quoting routines conform to the RFC2109 specification, which in
+# turn references the character definitions from RFC2068.  They provide
+# a two-way quoting algorithm.  Any non-text character is translated
+# into a 4 character sequence: a forward-slash followed by the
+# three-digit octal equivalent of the character.  Any '\' or '"' is
+# quoted with a preceeding '\' slash.
+#
+# These are taken from RFC2068 and RFC2109.
+#       _LegalChars       is the list of chars which don't require "'s
+#       _Translator       hash-table for fast quoting
+#
+_LegalChars       = string.ascii_letters + string.digits + "!#$%&'*+-.^_`|~"
+_Translator       = {
+    '\000' : '\\000',  '\001' : '\\001',  '\002' : '\\002',
+    '\003' : '\\003',  '\004' : '\\004',  '\005' : '\\005',
+    '\006' : '\\006',  '\007' : '\\007',  '\010' : '\\010',
+    '\011' : '\\011',  '\012' : '\\012',  '\013' : '\\013',
+    '\014' : '\\014',  '\015' : '\\015',  '\016' : '\\016',
+    '\017' : '\\017',  '\020' : '\\020',  '\021' : '\\021',
+    '\022' : '\\022',  '\023' : '\\023',  '\024' : '\\024',
+    '\025' : '\\025',  '\026' : '\\026',  '\027' : '\\027',
+    '\030' : '\\030',  '\031' : '\\031',  '\032' : '\\032',
+    '\033' : '\\033',  '\034' : '\\034',  '\035' : '\\035',
+    '\036' : '\\036',  '\037' : '\\037',
+
+    # Because of the way browsers really handle cookies (as opposed
+    # to what the RFC says) we also encode , and ;
+
+    ',' : '\\054', ';' : '\\073',
+
+    '"' : '\\"',       '\\' : '\\\\',
+
+    '\177' : '\\177',  '\200' : '\\200',  '\201' : '\\201',
+    '\202' : '\\202',  '\203' : '\\203',  '\204' : '\\204',
+    '\205' : '\\205',  '\206' : '\\206',  '\207' : '\\207',
+    '\210' : '\\210',  '\211' : '\\211',  '\212' : '\\212',
+    '\213' : '\\213',  '\214' : '\\214',  '\215' : '\\215',
+    '\216' : '\\216',  '\217' : '\\217',  '\220' : '\\220',
+    '\221' : '\\221',  '\222' : '\\222',  '\223' : '\\223',
+    '\224' : '\\224',  '\225' : '\\225',  '\226' : '\\226',
+    '\227' : '\\227',  '\230' : '\\230',  '\231' : '\\231',
+    '\232' : '\\232',  '\233' : '\\233',  '\234' : '\\234',
+    '\235' : '\\235',  '\236' : '\\236',  '\237' : '\\237',
+    '\240' : '\\240',  '\241' : '\\241',  '\242' : '\\242',
+    '\243' : '\\243',  '\244' : '\\244',  '\245' : '\\245',
+    '\246' : '\\246',  '\247' : '\\247',  '\250' : '\\250',
+    '\251' : '\\251',  '\252' : '\\252',  '\253' : '\\253',
+    '\254' : '\\254',  '\255' : '\\255',  '\256' : '\\256',
+    '\257' : '\\257',  '\260' : '\\260',  '\261' : '\\261',
+    '\262' : '\\262',  '\263' : '\\263',  '\264' : '\\264',
+    '\265' : '\\265',  '\266' : '\\266',  '\267' : '\\267',
+    '\270' : '\\270',  '\271' : '\\271',  '\272' : '\\272',
+    '\273' : '\\273',  '\274' : '\\274',  '\275' : '\\275',
+    '\276' : '\\276',  '\277' : '\\277',  '\300' : '\\300',
+    '\301' : '\\301',  '\302' : '\\302',  '\303' : '\\303',
+    '\304' : '\\304',  '\305' : '\\305',  '\306' : '\\306',
+    '\307' : '\\307',  '\310' : '\\310',  '\311' : '\\311',
+    '\312' : '\\312',  '\313' : '\\313',  '\314' : '\\314',
+    '\315' : '\\315',  '\316' : '\\316',  '\317' : '\\317',
+    '\320' : '\\320',  '\321' : '\\321',  '\322' : '\\322',
+    '\323' : '\\323',  '\324' : '\\324',  '\325' : '\\325',
+    '\326' : '\\326',  '\327' : '\\327',  '\330' : '\\330',
+    '\331' : '\\331',  '\332' : '\\332',  '\333' : '\\333',
+    '\334' : '\\334',  '\335' : '\\335',  '\336' : '\\336',
+    '\337' : '\\337',  '\340' : '\\340',  '\341' : '\\341',
+    '\342' : '\\342',  '\343' : '\\343',  '\344' : '\\344',
+    '\345' : '\\345',  '\346' : '\\346',  '\347' : '\\347',
+    '\350' : '\\350',  '\351' : '\\351',  '\352' : '\\352',
+    '\353' : '\\353',  '\354' : '\\354',  '\355' : '\\355',
+    '\356' : '\\356',  '\357' : '\\357',  '\360' : '\\360',
+    '\361' : '\\361',  '\362' : '\\362',  '\363' : '\\363',
+    '\364' : '\\364',  '\365' : '\\365',  '\366' : '\\366',
+    '\367' : '\\367',  '\370' : '\\370',  '\371' : '\\371',
+    '\372' : '\\372',  '\373' : '\\373',  '\374' : '\\374',
+    '\375' : '\\375',  '\376' : '\\376',  '\377' : '\\377'
+    }
+
+_idmap = ''.join(chr(x) for x in xrange(256))
+
+def _quote(str, LegalChars=_LegalChars,
+           idmap=_idmap, translate=string.translate):
+    #
+    # If the string does not need to be double-quoted,
+    # then just return the string.  Otherwise, surround
+    # the string in doublequotes and precede quote (with a \)
+    # special characters.
+    #
+    if "" == translate(str, idmap, LegalChars):
+        return str
+    else:
+        return '"' + _nulljoin( map(_Translator.get, str, str) ) + '"'
+# end _quote
+
+
+_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]")
+_QuotePatt = re.compile(r"[\\].")
+
+def _unquote(str):
+    # If there aren't any doublequotes,
+    # then there can't be any special characters.  See RFC 2109.
+    if  len(str) < 2:
+        return str
+    if str[0] != '"' or str[-1] != '"':
+        return str
+
+    # We have to assume that we must decode this string.
+    # Down to work.
+
+    # Remove the "s
+    str = str[1:-1]
+
+    # Check for special sequences.  Examples:
+    #    \012 --> \n
+    #    \"   --> "
+    #
+    i = 0
+    n = len(str)
+    res = []
+    while 0 <= i < n:
+        Omatch = _OctalPatt.search(str, i)
+        Qmatch = _QuotePatt.search(str, i)
+        if not Omatch and not Qmatch:              # Neither matched
+            res.append(str[i:])
+            break
+        # else:
+        j = k = -1
+        if Omatch: j = Omatch.start(0)
+        if Qmatch: k = Qmatch.start(0)
+        if Qmatch and ( not Omatch or k < j ):     # QuotePatt matched
+            res.append(str[i:k])
+            res.append(str[k+1])
+            i = k+2
+        else:                                      # OctalPatt matched
+            res.append(str[i:j])
+            res.append( chr( int(str[j+1:j+4], 8) ) )
+            i = j+4
+    return _nulljoin(res)
+# end _unquote
+
+# The _getdate() routine is used to set the expiration time in
+# the cookie's HTTP header.      By default, _getdate() returns the
+# current time in the appropriate "expires" format for a
+# Set-Cookie header.     The one optional argument is an offset from
+# now, in seconds.      For example, an offset of -3600 means "one hour ago".
+# The offset may be a floating point number.
+#
+
+_weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+
+_monthname = [None,
+              'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+              'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+
+def _getdate(future=0, weekdayname=_weekdayname, monthname=_monthname):
+    from time import gmtime, time
+    now = time()
+    year, month, day, hh, mm, ss, wd, y, z = gmtime(now + future)
+    return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % \
+           (weekdayname[wd], day, monthname[month], year, hh, mm, ss)
+
+
+#
+# A class to hold ONE key,value pair.
+# In a cookie, each such pair may have several attributes.
+#       so this class is used to keep the attributes associated
+#       with the appropriate key,value pair.
+# This class also includes a coded_value attribute, which
+#       is used to hold the network representation of the
+#       value.  This is most useful when Python objects are
+#       pickled for network transit.
+#
+
+class Morsel(dict):
+    # RFC 2109 lists these attributes as reserved:
+    #   path       comment         domain
+    #   max-age    secure      version
+    #
+    # For historical reasons, these attributes are also reserved:
+    #   expires
+    #
+    # This is an extension from Microsoft:
+    #   httponly
+    #
+    # This dictionary provides a mapping from the lowercase
+    # variant on the left to the appropriate traditional
+    # formatting on the right.
+    _reserved = { "expires" : "expires",
+                   "path"        : "Path",
+                   "comment" : "Comment",
+                   "domain"      : "Domain",
+                   "max-age" : "Max-Age",
+                   "secure"      : "secure",
+                   "httponly"  : "httponly",
+                   "version" : "Version",
+                   }
+
+    def __init__(self):
+        # Set defaults
+        self.key = self.value = self.coded_value = None
+
+        # Set default attributes
+        for K in self._reserved:
+            dict.__setitem__(self, K, "")
+    # end __init__
+
+    def __setitem__(self, K, V):
+        K = K.lower()
+        if not K in self._reserved:
+            raise CookieError("Invalid Attribute %s" % K)
+        dict.__setitem__(self, K, V)
+    # end __setitem__
+
+    def isReservedKey(self, K):
+        return K.lower() in self._reserved
+    # end isReservedKey
+
+    def set(self, key, val, coded_val,
+            LegalChars=_LegalChars,
+            idmap=_idmap, translate=string.translate):
+        # First we verify that the key isn't a reserved word
+        # Second we make sure it only contains legal characters
+        if key.lower() in self._reserved:
+            raise CookieError("Attempt to set a reserved key: %s" % key)
+        if "" != translate(key, idmap, LegalChars):
+            raise CookieError("Illegal key value: %s" % key)
+
+        # It's a good key, so save it.
+        self.key                 = key
+        self.value               = val
+        self.coded_value         = coded_val
+    # end set
+
+    def output(self, attrs=None, header = "Set-Cookie:"):
+        return "%s %s" % ( header, self.OutputString(attrs) )
+
+    __str__ = output
+
+    def __repr__(self):
+        return '<%s: %s=%s>' % (self.__class__.__name__,
+                                self.key, repr(self.value) )
+
+    def js_output(self, attrs=None):
+        # Print javascript
+        return """
+        <script type="text/javascript">
+        <!-- begin hiding
+        document.cookie = \"%s\";
+        // end hiding -->
+        </script>
+        """ % ( self.OutputString(attrs).replace('"',r'\"'), )
+    # end js_output()
+
+    def OutputString(self, attrs=None):
+        # Build up our result
+        #
+        result = []
+        RA = result.append
+
+        # First, the key=value pair
+        RA("%s=%s" % (self.key, self.coded_value))
+
+        # Now add any defined attributes
+        if attrs is None:
+            attrs = self._reserved
+        items = self.items()
+        items.sort()
+        for K,V in items:
+            if V == "": continue
+            if K not in attrs: continue
+            if K == "expires" and type(V) == type(1):
+                RA("%s=%s" % (self._reserved[K], _getdate(V)))
+            elif K == "max-age" and type(V) == type(1):
+                RA("%s=%d" % (self._reserved[K], V))
+            elif K == "secure":
+                RA(str(self._reserved[K]))
+            elif K == "httponly":
+                RA(str(self._reserved[K]))
+            else:
+                RA("%s=%s" % (self._reserved[K], V))
+
+        # Return the result
+        return _semispacejoin(result)
+    # end OutputString
+# end Morsel class
+
+
+
+#
+# Pattern for finding cookie
+#
+# This used to be strict parsing based on the RFC2109 and RFC2068
+# specifications.  I have since discovered that MSIE 3.0x doesn't
+# follow the character rules outlined in those specs.  As a
+# result, the parsing rules here are less strict.
+#
+
+_LegalCharsPatt  = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]"
+_CookiePattern = re.compile(
+    r"(?x)"                       # This is a Verbose pattern
+    r"(?P<key>"                   # Start of group 'key'
+    ""+ _LegalCharsPatt +"+?"     # Any word of at least one letter, nongreedy
+    r")"                          # End of group 'key'
+    r"\s*=\s*"                    # Equal Sign
+    r"(?P<val>"                   # Start of group 'val'
+    r'"(?:[^\\"]|\\.)*"'            # Any doublequoted string
+    r"|"                            # or
+    r"\w{3},\s[\s\w\d-]{9,11}\s[\d:]{8}\sGMT" # Special case for "expires" attr
+    r"|"                            # or
+    ""+ _LegalCharsPatt +"*"        # Any word or empty string
+    r")"                          # End of group 'val'
+    r"\s*;?"                      # Probably ending in a semi-colon
+    )
+
+
+# At long last, here is the cookie class.
+#   Using this class is almost just like using a dictionary.
+# See this module's docstring for example usage.
+#
+class BaseCookie(dict):
+    # A container class for a set of Morsels
+    #
+
+    def value_decode(self, val):
+        """real_value, coded_value = value_decode(STRING)
+        Called prior to setting a cookie's value from the network
+        representation.  The VALUE is the value read from HTTP
+        header.
+        Override this function to modify the behavior of cookies.
+        """
+        return val, val
+    # end value_encode
+
+    def value_encode(self, val):
+        """real_value, coded_value = value_encode(VALUE)
+        Called prior to setting a cookie's value from the dictionary
+        representation.  The VALUE is the value being assigned.
+        Override this function to modify the behavior of cookies.
+        """
+        strval = str(val)
+        return strval, strval
+    # end value_encode
+
+    def __init__(self, input=None):
+        if input: self.load(input)
+    # end __init__
+
+    def __set(self, key, real_value, coded_value):
+        """Private method for setting a cookie's value"""
+        M = self.get(key, Morsel())
+        M.set(key, real_value, coded_value)
+        dict.__setitem__(self, key, M)
+    # end __set
+
+    def __setitem__(self, key, value):
+        """Dictionary style assignment."""
+        rval, cval = self.value_encode(value)
+        self.__set(key, rval, cval)
+    # end __setitem__
+
+    def output(self, attrs=None, header="Set-Cookie:", sep="\015\012"):
+        """Return a string suitable for HTTP."""
+        result = []
+        items = self.items()
+        items.sort()
+        for K,V in items:
+            result.append( V.output(attrs, header) )
+        return sep.join(result)
+    # end output
+
+    __str__ = output
+
+    def __repr__(self):
+        L = []
+        items = self.items()
+        items.sort()
+        for K,V in items:
+            L.append( '%s=%s' % (K,repr(V.value) ) )
+        return '<%s: %s>' % (self.__class__.__name__, _spacejoin(L))
+
+    def js_output(self, attrs=None):
+        """Return a string suitable for JavaScript."""
+        result = []
+        items = self.items()
+        items.sort()
+        for K,V in items:
+            result.append( V.js_output(attrs) )
+        return _nulljoin(result)
+    # end js_output
+
+    def load(self, rawdata):
+        """Load cookies from a string (presumably HTTP_COOKIE) or
+        from a dictionary.  Loading cookies from a dictionary 'd'
+        is equivalent to calling:
+            map(Cookie.__setitem__, d.keys(), d.values())
+        """
+        if type(rawdata) == type(""):
+            self.__ParseString(rawdata)
+        else:
+            # self.update() wouldn't call our custom __setitem__
+            for k, v in rawdata.items():
+                self[k] = v
+        return
+    # end load()
+
+    def __ParseString(self, str, patt=_CookiePattern):
+        i = 0            # Our starting point
+        n = len(str)     # Length of string
+        M = None         # current morsel
+
+        while 0 <= i < n:
+            # Start looking for a cookie
+            match = patt.search(str, i)
+            if not match: break          # No more cookies
+
+            K,V = match.group("key"), match.group("val")
+            i = match.end(0)
+
+            # Parse the key, value in case it's metainfo
+            if K[0] == "$":
+                # We ignore attributes which pertain to the cookie
+                # mechanism as a whole.  See RFC 2109.
+                # (Does anyone care?)
+                if M:
+                    M[ K[1:] ] = V
+            elif K.lower() in Morsel._reserved:
+                if M:
+                    M[ K ] = _unquote(V)
+            else:
+                rval, cval = self.value_decode(V)
+                self.__set(K, rval, cval)
+                M = self[K]
+    # end __ParseString
+# end BaseCookie class
+
+class SimpleCookie(BaseCookie):
+    """SimpleCookie
+    SimpleCookie supports strings as cookie values.  When setting
+    the value using the dictionary assignment notation, SimpleCookie
+    calls the builtin str() to convert the value to a string.  Values
+    received from HTTP are kept as strings.
+    """
+    def value_decode(self, val):
+        return _unquote( val ), val
+    def value_encode(self, val):
+        strval = str(val)
+        return strval, _quote( strval )
+# end SimpleCookie
+
+class SerialCookie(BaseCookie):
+    """SerialCookie
+    SerialCookie supports arbitrary objects as cookie values. All
+    values are serialized (using cPickle) before being sent to the
+    client.  All incoming values are assumed to be valid Pickle
+    representations.  IF AN INCOMING VALUE IS NOT IN A VALID PICKLE
+    FORMAT, THEN AN EXCEPTION WILL BE RAISED.
+
+    Note: Large cookie values add overhead because they must be
+    retransmitted on every HTTP transaction.
+
+    Note: HTTP has a 2k limit on the size of a cookie.  This class
+    does not check for this limit, so be careful!!!
+    """
+    def __init__(self, input=None):
+        warnings.warn("SerialCookie class is insecure; do not use it",
+                      DeprecationWarning)
+        BaseCookie.__init__(self, input)
+    # end __init__
+    def value_decode(self, val):
+        # This could raise an exception!
+        return loads( _unquote(val) ), val
+    def value_encode(self, val):
+        return val, _quote( dumps(val) )
+# end SerialCookie
+
+class SmartCookie(BaseCookie):
+    """SmartCookie
+    SmartCookie supports arbitrary objects as cookie values.  If the
+    object is a string, then it is quoted.  If the object is not a
+    string, however, then SmartCookie will use cPickle to serialize
+    the object into a string representation.
+
+    Note: Large cookie values add overhead because they must be
+    retransmitted on every HTTP transaction.
+
+    Note: HTTP has a 2k limit on the size of a cookie.  This class
+    does not check for this limit, so be careful!!!
+    """
+    def __init__(self, input=None):
+        warnings.warn("Cookie/SmartCookie class is insecure; do not use it",
+                      DeprecationWarning)
+        BaseCookie.__init__(self, input)
+    # end __init__
+    def value_decode(self, val):
+        strval = _unquote(val)
+        try:
+            return loads(strval), val
+        except:
+            return strval, val
+    def value_encode(self, val):
+        if type(val) == type(""):
+            return val, _quote(val)
+        else:
+            return val, _quote( dumps(val) )
+# end SmartCookie
+
+
+###########################################################
+# Backwards Compatibility:  Don't break any existing code!
+
+# We provide Cookie() as an alias for SmartCookie()
+Cookie = SmartCookie
+
+#
+###########################################################
+
+def _test():
+    import doctest, Cookie
+    return doctest.testmod(Cookie)
+
+if __name__ == "__main__":
+    _test()
+
+
+#Local Variables:
+#tab-width: 4
+#end:
diff --git a/src/main/resources/PythonLibs/DocXMLRPCServer.py b/src/main/resources/PythonLibs/DocXMLRPCServer.py
new file mode 100644
index 0000000000000000000000000000000000000000..4064ec2e48d4ddcb5cfd5f9663cb5c143c7dd568
--- /dev/null
+++ b/src/main/resources/PythonLibs/DocXMLRPCServer.py
@@ -0,0 +1,279 @@
+"""Self documenting XML-RPC Server.
+
+This module can be used to create XML-RPC servers that
+serve pydoc-style documentation in response to HTTP
+GET requests. This documentation is dynamically generated
+based on the functions and methods registered with the
+server.
+
+This module is built upon the pydoc and SimpleXMLRPCServer
+modules.
+"""
+
+import pydoc
+import inspect
+import re
+import sys
+
+from SimpleXMLRPCServer import (SimpleXMLRPCServer,
+            SimpleXMLRPCRequestHandler,
+            CGIXMLRPCRequestHandler,
+            resolve_dotted_attribute)
+
+class ServerHTMLDoc(pydoc.HTMLDoc):
+    """Class used to generate pydoc HTML document for a server"""
+
+    def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
+        """Mark up some plain text, given a context of symbols to look for.
+        Each context dictionary maps object names to anchor names."""
+        escape = escape or self.escape
+        results = []
+        here = 0
+
+        # XXX Note that this regular expression does not allow for the
+        # hyperlinking of arbitrary strings being used as method
+        # names. Only methods with names consisting of word characters
+        # and '.'s are hyperlinked.
+        pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
+                                r'RFC[- ]?(\d+)|'
+                                r'PEP[- ]?(\d+)|'
+                                r'(self\.)?((?:\w|\.)+))\b')
+        while 1:
+            match = pattern.search(text, here)
+            if not match: break
+            start, end = match.span()
+            results.append(escape(text[here:start]))
+
+            all, scheme, rfc, pep, selfdot, name = match.groups()
+            if scheme:
+                url = escape(all).replace('"', '&quot;')
+                results.append('<a href="%s">%s</a>' % (url, url))
+            elif rfc:
+                url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
+                results.append('<a href="%s">%s</a>' % (url, escape(all)))
+            elif pep:
+                url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
+                results.append('<a href="%s">%s</a>' % (url, escape(all)))
+            elif text[end:end+1] == '(':
+                results.append(self.namelink(name, methods, funcs, classes))
+            elif selfdot:
+                results.append('self.<strong>%s</strong>' % name)
+            else:
+                results.append(self.namelink(name, classes))
+            here = end
+        results.append(escape(text[here:]))
+        return ''.join(results)
+
+    def docroutine(self, object, name, mod=None,
+                   funcs={}, classes={}, methods={}, cl=None):
+        """Produce HTML documentation for a function or method object."""
+
+        anchor = (cl and cl.__name__ or '') + '-' + name
+        note = ''
+
+        title = '<a name="%s"><strong>%s</strong></a>' % (
+            self.escape(anchor), self.escape(name))
+
+        if inspect.ismethod(object):
+            args, varargs, varkw, defaults = inspect.getargspec(object.im_func)
+            # exclude the argument bound to the instance, it will be
+            # confusing to the non-Python user
+            argspec = inspect.formatargspec (
+                    args[1:],
+                    varargs,
+                    varkw,
+                    defaults,
+                    formatvalue=self.formatvalue
+                )
+        elif inspect.isfunction(object):
+            args, varargs, varkw, defaults = inspect.getargspec(object)
+            argspec = inspect.formatargspec(
+                args, varargs, varkw, defaults, formatvalue=self.formatvalue)
+        else:
+            argspec = '(...)'
+
+        if isinstance(object, tuple):
+            argspec = object[0] or argspec
+            docstring = object[1] or ""
+        else:
+            docstring = pydoc.getdoc(object)
+
+        decl = title + argspec + (note and self.grey(
+               '<font face="helvetica, arial">%s</font>' % note))
+
+        doc = self.markup(
+            docstring, self.preformat, funcs, classes, methods)
+        doc = doc and '<dd><tt>%s</tt></dd>' % doc
+        return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
+
+    def docserver(self, server_name, package_documentation, methods):
+        """Produce HTML documentation for an XML-RPC server."""
+
+        fdict = {}
+        for key, value in methods.items():
+            fdict[key] = '#-' + key
+            fdict[value] = fdict[key]
+
+        server_name = self.escape(server_name)
+        head = '<big><big><strong>%s</strong></big></big>' % server_name
+        result = self.heading(head, '#ffffff', '#7799ee')
+
+        doc = self.markup(package_documentation, self.preformat, fdict)
+        doc = doc and '<tt>%s</tt>' % doc
+        result = result + '<p>%s</p>\n' % doc
+
+        contents = []
+        method_items = sorted(methods.items())
+        for key, value in method_items:
+            contents.append(self.docroutine(value, key, funcs=fdict))
+        result = result + self.bigsection(
+            'Methods', '#ffffff', '#eeaa77', pydoc.join(contents))
+
+        return result
+
+class XMLRPCDocGenerator:
+    """Generates documentation for an XML-RPC server.
+
+    This class is designed as mix-in and should not
+    be constructed directly.
+    """
+
+    def __init__(self):
+        # setup variables used for HTML documentation
+        self.server_name = 'XML-RPC Server Documentation'
+        self.server_documentation = \
+            "This server exports the following methods through the XML-RPC "\
+            "protocol."
+        self.server_title = 'XML-RPC Server Documentation'
+
+    def set_server_title(self, server_title):
+        """Set the HTML title of the generated server documentation"""
+
+        self.server_title = server_title
+
+    def set_server_name(self, server_name):
+        """Set the name of the generated HTML server documentation"""
+
+        self.server_name = server_name
+
+    def set_server_documentation(self, server_documentation):
+        """Set the documentation string for the entire server."""
+
+        self.server_documentation = server_documentation
+
+    def generate_html_documentation(self):
+        """generate_html_documentation() => html documentation for the server
+
+        Generates HTML documentation for the server using introspection for
+        installed functions and instances that do not implement the
+        _dispatch method. Alternatively, instances can choose to implement
+        the _get_method_argstring(method_name) method to provide the
+        argument string used in the documentation and the
+        _methodHelp(method_name) method to provide the help text used
+        in the documentation."""
+
+        methods = {}
+
+        for method_name in self.system_listMethods():
+            if method_name in self.funcs:
+                method = self.funcs[method_name]
+            elif self.instance is not None:
+                method_info = [None, None] # argspec, documentation
+                if hasattr(self.instance, '_get_method_argstring'):
+                    method_info[0] = self.instance._get_method_argstring(method_name)
+                if hasattr(self.instance, '_methodHelp'):
+                    method_info[1] = self.instance._methodHelp(method_name)
+
+                method_info = tuple(method_info)
+                if method_info != (None, None):
+                    method = method_info
+                elif not hasattr(self.instance, '_dispatch'):
+                    try:
+                        method = resolve_dotted_attribute(
+                                    self.instance,
+                                    method_name
+                                    )
+                    except AttributeError:
+                        method = method_info
+                else:
+                    method = method_info
+            else:
+                assert 0, "Could not find method in self.functions and no "\
+                          "instance installed"
+
+            methods[method_name] = method
+
+        documenter = ServerHTMLDoc()
+        documentation = documenter.docserver(
+                                self.server_name,
+                                self.server_documentation,
+                                methods
+                            )
+
+        return documenter.page(self.server_title, documentation)
+
+class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
+    """XML-RPC and documentation request handler class.
+
+    Handles all HTTP POST requests and attempts to decode them as
+    XML-RPC requests.
+
+    Handles all HTTP GET requests and interprets them as requests
+    for documentation.
+    """
+
+    def do_GET(self):
+        """Handles the HTTP GET request.
+
+        Interpret all HTTP GET requests as requests for server
+        documentation.
+        """
+        # Check that the path is legal
+        if not self.is_rpc_path_valid():
+            self.report_404()
+            return
+
+        response = self.server.generate_html_documentation()
+        self.send_response(200)
+        self.send_header("Content-type", "text/html")
+        self.send_header("Content-length", str(len(response)))
+        self.end_headers()
+        self.wfile.write(response)
+
+class DocXMLRPCServer(  SimpleXMLRPCServer,
+                        XMLRPCDocGenerator):
+    """XML-RPC and HTML documentation server.
+
+    Adds the ability to serve server documentation to the capabilities
+    of SimpleXMLRPCServer.
+    """
+
+    def __init__(self, addr, requestHandler=DocXMLRPCRequestHandler,
+                 logRequests=1, allow_none=False, encoding=None,
+                 bind_and_activate=True):
+        SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests,
+                                    allow_none, encoding, bind_and_activate)
+        XMLRPCDocGenerator.__init__(self)
+
+class DocCGIXMLRPCRequestHandler(   CGIXMLRPCRequestHandler,
+                                    XMLRPCDocGenerator):
+    """Handler for XML-RPC data and documentation requests passed through
+    CGI"""
+
+    def handle_get(self):
+        """Handles the HTTP GET request.
+
+        Interpret all HTTP GET requests as requests for server
+        documentation.
+        """
+
+        response = self.generate_html_documentation()
+
+        print 'Content-Type: text/html'
+        print 'Content-Length: %d' % len(response)
+        print
+        sys.stdout.write(response)
+
+    def __init__(self):
+        CGIXMLRPCRequestHandler.__init__(self)
+        XMLRPCDocGenerator.__init__(self)
diff --git a/src/main/resources/PythonLibs/HTMLParser.py b/src/main/resources/PythonLibs/HTMLParser.py
new file mode 100644
index 0000000000000000000000000000000000000000..b336a4c31df64988f41f094cd9cb3912ff939d59
--- /dev/null
+++ b/src/main/resources/PythonLibs/HTMLParser.py
@@ -0,0 +1,472 @@
+"""A parser for HTML and XHTML."""
+
+# This file is based on sgmllib.py, but the API is slightly different.
+
+# XXX There should be a way to distinguish between PCDATA (parsed
+# character data -- the normal case), RCDATA (replaceable character
+# data -- only char and entity references and end tags are special)
+# and CDATA (character data -- only end tags are special).
+
+
+import markupbase
+import re
+
+# Regular expressions used for parsing
+
+interesting_normal = re.compile('[&<]')
+incomplete = re.compile('&[a-zA-Z#]')
+
+entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
+charref = re.compile('&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]')
+
+starttagopen = re.compile('<[a-zA-Z]')
+piclose = re.compile('>')
+commentclose = re.compile(r'--\s*>')
+tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*')
+# see http://www.w3.org/TR/html5/tokenization.html#tag-open-state
+# and http://www.w3.org/TR/html5/tokenization.html#tag-name-state
+tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*')
+
+attrfind = re.compile(
+    r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*'
+    r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*')
+
+locatestarttagend = re.compile(r"""
+  <[a-zA-Z][-.a-zA-Z0-9:_]*          # tag name
+  (?:[\s/]*                          # optional whitespace before attribute name
+    (?:(?<=['"\s/])[^\s/>][^\s/=>]*  # attribute name
+      (?:\s*=+\s*                    # value indicator
+        (?:'[^']*'                   # LITA-enclosed value
+          |"[^"]*"                   # LIT-enclosed value
+          |(?!['"])[^>\s]*           # bare value
+         )
+       )?(?:\s|/(?!>))*
+     )*
+   )?
+  \s*                                # trailing whitespace
+""", re.VERBOSE)
+endendtag = re.compile('>')
+# the HTML 5 spec, section 8.1.2.2, doesn't allow spaces between
+# </ and the tag name, so maybe this should be fixed
+endtagfind = re.compile('</\s*([a-zA-Z][-.a-zA-Z0-9:_]*)\s*>')
+
+
+class HTMLParseError(Exception):
+    """Exception raised for all parse errors."""
+
+    def __init__(self, msg, position=(None, None)):
+        assert msg
+        self.msg = msg
+        self.lineno = position[0]
+        self.offset = position[1]
+
+    def __str__(self):
+        result = self.msg
+        if self.lineno is not None:
+            result = result + ", at line %d" % self.lineno
+        if self.offset is not None:
+            result = result + ", column %d" % (self.offset + 1)
+        return result
+
+
+class HTMLParser(markupbase.ParserBase):
+    """Find tags and other markup and call handler functions.
+
+    Usage:
+        p = HTMLParser()
+        p.feed(data)
+        ...
+        p.close()
+
+    Start tags are handled by calling self.handle_starttag() or
+    self.handle_startendtag(); end tags by self.handle_endtag().  The
+    data between tags is passed from the parser to the derived class
+    by calling self.handle_data() with the data as argument (the data
+    may be split up in arbitrary chunks).  Entity references are
+    passed by calling self.handle_entityref() with the entity
+    reference as the argument.  Numeric character references are
+    passed to self.handle_charref() with the string containing the
+    reference as the argument.
+    """
+
+    CDATA_CONTENT_ELEMENTS = ("script", "style")
+
+
+    def __init__(self):
+        """Initialize and reset this instance."""
+        self.reset()
+
+    def reset(self):
+        """Reset this instance.  Loses all unprocessed data."""
+        self.rawdata = ''
+        self.lasttag = '???'
+        self.interesting = interesting_normal
+        self.cdata_elem = None
+        markupbase.ParserBase.reset(self)
+
+    def feed(self, data):
+        r"""Feed data to the parser.
+
+        Call this as often as you want, with as little or as much text
+        as you want (may include '\n').
+        """
+        self.rawdata = self.rawdata + data
+        self.goahead(0)
+
+    def close(self):
+        """Handle any buffered data."""
+        self.goahead(1)
+
+    def error(self, message):
+        raise HTMLParseError(message, self.getpos())
+
+    __starttag_text = None
+
+    def get_starttag_text(self):
+        """Return full source of start tag: '<...>'."""
+        return self.__starttag_text
+
+    def set_cdata_mode(self, elem):
+        self.cdata_elem = elem.lower()
+        self.interesting = re.compile(r'</\s*%s\s*>' % self.cdata_elem, re.I)
+
+    def clear_cdata_mode(self):
+        self.interesting = interesting_normal
+        self.cdata_elem = None
+
+    # Internal -- handle data as far as reasonable.  May leave state
+    # and data to be processed by a subsequent call.  If 'end' is
+    # true, force handling all data as if followed by EOF marker.
+    def goahead(self, end):
+        rawdata = self.rawdata
+        i = 0
+        n = len(rawdata)
+        while i < n:
+            match = self.interesting.search(rawdata, i) # < or &
+            if match:
+                j = match.start()
+            else:
+                if self.cdata_elem:
+                    break
+                j = n
+            if i < j: self.handle_data(rawdata[i:j])
+            i = self.updatepos(i, j)
+            if i == n: break
+            startswith = rawdata.startswith
+            if startswith('<', i):
+                if starttagopen.match(rawdata, i): # < + letter
+                    k = self.parse_starttag(i)
+                elif startswith("</", i):
+                    k = self.parse_endtag(i)
+                elif startswith("<!--", i):
+                    k = self.parse_comment(i)
+                elif startswith("<?", i):
+                    k = self.parse_pi(i)
+                elif startswith("<!", i):
+                    k = self.parse_html_declaration(i)
+                elif (i + 1) < n:
+                    self.handle_data("<")
+                    k = i + 1
+                else:
+                    break
+                if k < 0:
+                    if not end:
+                        break
+                    k = rawdata.find('>', i + 1)
+                    if k < 0:
+                        k = rawdata.find('<', i + 1)
+                        if k < 0:
+                            k = i + 1
+                    else:
+                        k += 1
+                    self.handle_data(rawdata[i:k])
+                i = self.updatepos(i, k)
+            elif startswith("&#", i):
+                match = charref.match(rawdata, i)
+                if match:
+                    name = match.group()[2:-1]
+                    self.handle_charref(name)
+                    k = match.end()
+                    if not startswith(';', k-1):
+                        k = k - 1
+                    i = self.updatepos(i, k)
+                    continue
+                else:
+                    if ";" in rawdata[i:]: #bail by consuming &#
+                        self.handle_data(rawdata[0:2])
+                        i = self.updatepos(i, 2)
+                    break
+            elif startswith('&', i):
+                match = entityref.match(rawdata, i)
+                if match:
+                    name = match.group(1)
+                    self.handle_entityref(name)
+                    k = match.end()
+                    if not startswith(';', k-1):
+                        k = k - 1
+                    i = self.updatepos(i, k)
+                    continue
+                match = incomplete.match(rawdata, i)
+                if match:
+                    # match.group() will contain at least 2 chars
+                    if end and match.group() == rawdata[i:]:
+                        self.error("EOF in middle of entity or char ref")
+                    # incomplete
+                    break
+                elif (i + 1) < n:
+                    # not the end of the buffer, and can't be confused
+                    # with some other construct
+                    self.handle_data("&")
+                    i = self.updatepos(i, i + 1)
+                else:
+                    break
+            else:
+                assert 0, "interesting.search() lied"
+        # end while
+        if end and i < n and not self.cdata_elem:
+            self.handle_data(rawdata[i:n])
+            i = self.updatepos(i, n)
+        self.rawdata = rawdata[i:]
+
+    # Internal -- parse html declarations, return length or -1 if not terminated
+    # See w3.org/TR/html5/tokenization.html#markup-declaration-open-state
+    # See also parse_declaration in _markupbase
+    def parse_html_declaration(self, i):
+        rawdata = self.rawdata
+        if rawdata[i:i+2] != '<!':
+            self.error('unexpected call to parse_html_declaration()')
+        if rawdata[i:i+4] == '<!--':
+            # this case is actually already handled in goahead()
+            return self.parse_comment(i)
+        elif rawdata[i:i+3] == '<![':
+            return self.parse_marked_section(i)
+        elif rawdata[i:i+9].lower() == '<!doctype':
+            # find the closing >
+            gtpos = rawdata.find('>', i+9)
+            if gtpos == -1:
+                return -1
+            self.handle_decl(rawdata[i+2:gtpos])
+            return gtpos+1
+        else:
+            return self.parse_bogus_comment(i)
+
+    # Internal -- parse bogus comment, return length or -1 if not terminated
+    # see http://www.w3.org/TR/html5/tokenization.html#bogus-comment-state
+    def parse_bogus_comment(self, i, report=1):
+        rawdata = self.rawdata
+        if rawdata[i:i+2] not in ('<!', '</'):
+            self.error('unexpected call to parse_comment()')
+        pos = rawdata.find('>', i+2)
+        if pos == -1:
+            return -1
+        if report:
+            self.handle_comment(rawdata[i+2:pos])
+        return pos + 1
+
+    # Internal -- parse processing instr, return end or -1 if not terminated
+    def parse_pi(self, i):
+        rawdata = self.rawdata
+        assert rawdata[i:i+2] == '<?', 'unexpected call to parse_pi()'
+        match = piclose.search(rawdata, i+2) # >
+        if not match:
+            return -1
+        j = match.start()
+        self.handle_pi(rawdata[i+2: j])
+        j = match.end()
+        return j
+
+    # Internal -- handle starttag, return end or -1 if not terminated
+    def parse_starttag(self, i):
+        self.__starttag_text = None
+        endpos = self.check_for_whole_start_tag(i)
+        if endpos < 0:
+            return endpos
+        rawdata = self.rawdata
+        self.__starttag_text = rawdata[i:endpos]
+
+        # Now parse the data between i+1 and j into a tag and attrs
+        attrs = []
+        match = tagfind.match(rawdata, i+1)
+        assert match, 'unexpected call to parse_starttag()'
+        k = match.end()
+        self.lasttag = tag = match.group(1).lower()
+
+        while k < endpos:
+            m = attrfind.match(rawdata, k)
+            if not m:
+                break
+            attrname, rest, attrvalue = m.group(1, 2, 3)
+            if not rest:
+                attrvalue = None
+            elif attrvalue[:1] == '\'' == attrvalue[-1:] or \
+                 attrvalue[:1] == '"' == attrvalue[-1:]:
+                attrvalue = attrvalue[1:-1]
+            if attrvalue:
+                attrvalue = self.unescape(attrvalue)
+            attrs.append((attrname.lower(), attrvalue))
+            k = m.end()
+
+        end = rawdata[k:endpos].strip()
+        if end not in (">", "/>"):
+            lineno, offset = self.getpos()
+            if "\n" in self.__starttag_text:
+                lineno = lineno + self.__starttag_text.count("\n")
+                offset = len(self.__starttag_text) \
+                         - self.__starttag_text.rfind("\n")
+            else:
+                offset = offset + len(self.__starttag_text)
+            self.handle_data(rawdata[i:endpos])
+            return endpos
+        if end.endswith('/>'):
+            # XHTML-style empty tag: <span attr="value" />
+            self.handle_startendtag(tag, attrs)
+        else:
+            self.handle_starttag(tag, attrs)
+            if tag in self.CDATA_CONTENT_ELEMENTS:
+                self.set_cdata_mode(tag)
+        return endpos
+
+    # Internal -- check to see if we have a complete starttag; return end
+    # or -1 if incomplete.
+    def check_for_whole_start_tag(self, i):
+        rawdata = self.rawdata
+        m = locatestarttagend.match(rawdata, i)
+        if m:
+            j = m.end()
+            next = rawdata[j:j+1]
+            if next == ">":
+                return j + 1
+            if next == "/":
+                if rawdata.startswith("/>", j):
+                    return j + 2
+                if rawdata.startswith("/", j):
+                    # buffer boundary
+                    return -1
+                # else bogus input
+                self.updatepos(i, j + 1)
+                self.error("malformed empty start tag")
+            if next == "":
+                # end of input
+                return -1
+            if next in ("abcdefghijklmnopqrstuvwxyz=/"
+                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
+                # end of input in or before attribute value, or we have the
+                # '/' from a '/>' ending
+                return -1
+            if j > i:
+                return j
+            else:
+                return i + 1
+        raise AssertionError("we should not get here!")
+
+    # Internal -- parse endtag, return end or -1 if incomplete
+    def parse_endtag(self, i):
+        rawdata = self.rawdata
+        assert rawdata[i:i+2] == "</", "unexpected call to parse_endtag"
+        match = endendtag.search(rawdata, i+1) # >
+        if not match:
+            return -1
+        gtpos = match.end()
+        match = endtagfind.match(rawdata, i) # </ + tag + >
+        if not match:
+            if self.cdata_elem is not None:
+                self.handle_data(rawdata[i:gtpos])
+                return gtpos
+            # find the name: w3.org/TR/html5/tokenization.html#tag-name-state
+            namematch = tagfind_tolerant.match(rawdata, i+2)
+            if not namematch:
+                # w3.org/TR/html5/tokenization.html#end-tag-open-state
+                if rawdata[i:i+3] == '</>':
+                    return i+3
+                else:
+                    return self.parse_bogus_comment(i)
+            tagname = namematch.group().lower()
+            # consume and ignore other stuff between the name and the >
+            # Note: this is not 100% correct, since we might have things like
+            # </tag attr=">">, but looking for > after tha name should cover
+            # most of the cases and is much simpler
+            gtpos = rawdata.find('>', namematch.end())
+            self.handle_endtag(tagname)
+            return gtpos+1
+
+        elem = match.group(1).lower() # script or style
+        if self.cdata_elem is not None:
+            if elem != self.cdata_elem:
+                self.handle_data(rawdata[i:gtpos])
+                return gtpos
+
+        self.handle_endtag(elem)
+        self.clear_cdata_mode()
+        return gtpos
+
+    # Overridable -- finish processing of start+end tag: <tag.../>
+    def handle_startendtag(self, tag, attrs):
+        self.handle_starttag(tag, attrs)
+        self.handle_endtag(tag)
+
+    # Overridable -- handle start tag
+    def handle_starttag(self, tag, attrs):
+        pass
+
+    # Overridable -- handle end tag
+    def handle_endtag(self, tag):
+        pass
+
+    # Overridable -- handle character reference
+    def handle_charref(self, name):
+        pass
+
+    # Overridable -- handle entity reference
+    def handle_entityref(self, name):
+        pass
+
+    # Overridable -- handle data
+    def handle_data(self, data):
+        pass
+
+    # Overridable -- handle comment
+    def handle_comment(self, data):
+        pass
+
+    # Overridable -- handle declaration
+    def handle_decl(self, decl):
+        pass
+
+    # Overridable -- handle processing instruction
+    def handle_pi(self, data):
+        pass
+
+    def unknown_decl(self, data):
+        pass
+
+    # Internal -- helper to remove special character quoting
+    entitydefs = None
+    def unescape(self, s):
+        if '&' not in s:
+            return s
+        def replaceEntities(s):
+            s = s.groups()[0]
+            try:
+                if s[0] == "#":
+                    s = s[1:]
+                    if s[0] in ['x','X']:
+                        c = int(s[1:], 16)
+                    else:
+                        c = int(s)
+                    return unichr(c)
+            except ValueError:
+                return '&#'+s+';'
+            else:
+                # Cannot use name2codepoint directly, because HTMLParser supports apos,
+                # which is not part of HTML 4
+                import htmlentitydefs
+                if HTMLParser.entitydefs is None:
+                    entitydefs = HTMLParser.entitydefs = {'apos':u"'"}
+                    for k, v in htmlentitydefs.name2codepoint.iteritems():
+                        entitydefs[k] = unichr(v)
+                try:
+                    return self.entitydefs[s]
+                except KeyError:
+                    return '&'+s+';'
+
+        return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", replaceEntities, s)
diff --git a/src/main/resources/PythonLibs/MimeWriter.py b/src/main/resources/PythonLibs/MimeWriter.py
new file mode 100644
index 0000000000000000000000000000000000000000..e898f9ff231793672ae281c770666be8953be6ec
--- /dev/null
+++ b/src/main/resources/PythonLibs/MimeWriter.py
@@ -0,0 +1,186 @@
+"""Generic MIME writer.
+
+This module defines the class MimeWriter.  The MimeWriter class implements
+a basic formatter for creating MIME multi-part files.  It doesn't seek around
+the output file nor does it use large amounts of buffer space. You must write
+the parts out in the order that they should occur in the final file.
+MimeWriter does buffer the headers you add, allowing you to rearrange their
+order.
+
+"""
+
+
+import mimetools
+
+__all__ = ["MimeWriter"]
+
+import warnings
+
+warnings.warn("the MimeWriter module is deprecated; use the email package instead",
+                DeprecationWarning, 2)
+
+class MimeWriter:
+
+    """Generic MIME writer.
+
+    Methods:
+
+    __init__()
+    addheader()
+    flushheaders()
+    startbody()
+    startmultipartbody()
+    nextpart()
+    lastpart()
+
+    A MIME writer is much more primitive than a MIME parser.  It
+    doesn't seek around on the output file, and it doesn't use large
+    amounts of buffer space, so you have to write the parts in the
+    order they should occur on the output file.  It does buffer the
+    headers you add, allowing you to rearrange their order.
+
+    General usage is:
+
+    f = <open the output file>
+    w = MimeWriter(f)
+    ...call w.addheader(key, value) 0 or more times...
+
+    followed by either:
+
+    f = w.startbody(content_type)
+    ...call f.write(data) for body data...
+
+    or:
+
+    w.startmultipartbody(subtype)
+    for each part:
+        subwriter = w.nextpart()
+        ...use the subwriter's methods to create the subpart...
+    w.lastpart()
+
+    The subwriter is another MimeWriter instance, and should be
+    treated in the same way as the toplevel MimeWriter.  This way,
+    writing recursive body parts is easy.
+
+    Warning: don't forget to call lastpart()!
+
+    XXX There should be more state so calls made in the wrong order
+    are detected.
+
+    Some special cases:
+
+    - startbody() just returns the file passed to the constructor;
+      but don't use this knowledge, as it may be changed.
+
+    - startmultipartbody() actually returns a file as well;
+      this can be used to write the initial 'if you can read this your
+      mailer is not MIME-aware' message.
+
+    - If you call flushheaders(), the headers accumulated so far are
+      written out (and forgotten); this is useful if you don't need a
+      body part at all, e.g. for a subpart of type message/rfc822
+      that's (mis)used to store some header-like information.
+
+    - Passing a keyword argument 'prefix=<flag>' to addheader(),
+      start*body() affects where the header is inserted; 0 means
+      append at the end, 1 means insert at the start; default is
+      append for addheader(), but insert for start*body(), which use
+      it to determine where the Content-Type header goes.
+
+    """
+
+    def __init__(self, fp):
+        self._fp = fp
+        self._headers = []
+
+    def addheader(self, key, value, prefix=0):
+        """Add a header line to the MIME message.
+
+        The key is the name of the header, where the value obviously provides
+        the value of the header. The optional argument prefix determines
+        where the header is inserted; 0 means append at the end, 1 means
+        insert at the start. The default is to append.
+
+        """
+        lines = value.split("\n")
+        while lines and not lines[-1]: del lines[-1]
+        while lines and not lines[0]: del lines[0]
+        for i in range(1, len(lines)):
+            lines[i] = "    " + lines[i].strip()
+        value = "\n".join(lines) + "\n"
+        line = key + ": " + value
+        if prefix:
+            self._headers.insert(0, line)
+        else:
+            self._headers.append(line)
+
+    def flushheaders(self):
+        """Writes out and forgets all headers accumulated so far.
+
+        This is useful if you don't need a body part at all; for example,
+        for a subpart of type message/rfc822 that's (mis)used to store some
+        header-like information.
+
+        """
+        self._fp.writelines(self._headers)
+        self._headers = []
+
+    def startbody(self, ctype, plist=[], prefix=1):
+        """Returns a file-like object for writing the body of the message.
+
+        The content-type is set to the provided ctype, and the optional
+        parameter, plist, provides additional parameters for the
+        content-type declaration.  The optional argument prefix determines
+        where the header is inserted; 0 means append at the end, 1 means
+        insert at the start. The default is to insert at the start.
+
+        """
+        for name, value in plist:
+            ctype = ctype + ';\n %s=\"%s\"' % (name, value)
+        self.addheader("Content-Type", ctype, prefix=prefix)
+        self.flushheaders()
+        self._fp.write("\n")
+        return self._fp
+
+    def startmultipartbody(self, subtype, boundary=None, plist=[], prefix=1):
+        """Returns a file-like object for writing the body of the message.
+
+        Additionally, this method initializes the multi-part code, where the
+        subtype parameter provides the multipart subtype, the boundary
+        parameter may provide a user-defined boundary specification, and the
+        plist parameter provides optional parameters for the subtype.  The
+        optional argument, prefix, determines where the header is inserted;
+        0 means append at the end, 1 means insert at the start. The default
+        is to insert at the start.  Subparts should be created using the
+        nextpart() method.
+
+        """
+        self._boundary = boundary or mimetools.choose_boundary()
+        return self.startbody("multipart/" + subtype,
+                              [("boundary", self._boundary)] + plist,
+                              prefix=prefix)
+
+    def nextpart(self):
+        """Returns a new instance of MimeWriter which represents an
+        individual part in a multipart message.
+
+        This may be used to write the part as well as used for creating
+        recursively complex multipart messages. The message must first be
+        initialized with the startmultipartbody() method before using the
+        nextpart() method.
+
+        """
+        self._fp.write("\n--" + self._boundary + "\n")
+        return self.__class__(self._fp)
+
+    def lastpart(self):
+        """This is used to designate the last part of a multipart message.
+
+        It should always be used when writing multipart messages.
+
+        """
+        self._fp.write("\n--" + self._boundary + "--\n")
+
+
+if __name__ == '__main__':
+    import test.test_MimeWriter
diff --git a/src/main/resources/PythonLibs/Queue.py b/src/main/resources/PythonLibs/Queue.py
new file mode 100644
index 0000000000000000000000000000000000000000..2db8d76966535ac458d5f21ab5533dd4aca8297b
--- /dev/null
+++ b/src/main/resources/PythonLibs/Queue.py
@@ -0,0 +1,244 @@
+"""A multi-producer, multi-consumer queue."""
+
+from time import time as _time
+try:
+    import threading as _threading
+except ImportError:
+    import dummy_threading as _threading
+from collections import deque
+import heapq
+
+__all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue']
+
+class Empty(Exception):
+    "Exception raised by Queue.get(block=0)/get_nowait()."
+    pass
+
+class Full(Exception):
+    "Exception raised by Queue.put(block=0)/put_nowait()."
+    pass
+
+class Queue:
+    """Create a queue object with a given maximum size.
+
+    If maxsize is <= 0, the queue size is infinite.
+    """
+    def __init__(self, maxsize=0):
+        self.maxsize = maxsize
+        self._init(maxsize)
+        # mutex must be held whenever the queue is mutating.  All methods
+        # that acquire mutex must release it before returning.  mutex
+        # is shared between the three conditions, so acquiring and
+        # releasing the conditions also acquires and releases mutex.
+        self.mutex = _threading.Lock()
+        # Notify not_empty whenever an item is added to the queue; a
+        # thread waiting to get is notified then.
+        self.not_empty = _threading.Condition(self.mutex)
+        # Notify not_full whenever an item is removed from the queue;
+        # a thread waiting to put is notified then.
+        self.not_full = _threading.Condition(self.mutex)
+        # Notify all_tasks_done whenever the number of unfinished tasks
+        # drops to zero; thread waiting to join() is notified to resume
+        self.all_tasks_done = _threading.Condition(self.mutex)
+        self.unfinished_tasks = 0
+
+    def task_done(self):
+        """Indicate that a formerly enqueued task is complete.
+
+        Used by Queue consumer threads.  For each get() used to fetch a task,
+        a subsequent call to task_done() tells the queue that the processing
+        on the task is complete.
+
+        If a join() is currently blocking, it will resume when all items
+        have been processed (meaning that a task_done() call was received
+        for every item that had been put() into the queue).
+
+        Raises a ValueError if called more times than there were items
+        placed in the queue.
+        """
+        self.all_tasks_done.acquire()
+        try:
+            unfinished = self.unfinished_tasks - 1
+            if unfinished <= 0:
+                if unfinished < 0:
+                    raise ValueError('task_done() called too many times')
+                self.all_tasks_done.notify_all()
+            self.unfinished_tasks = unfinished
+        finally:
+            self.all_tasks_done.release()
+
+    def join(self):
+        """Blocks until all items in the Queue have been gotten and processed.
+
+        The count of unfinished tasks goes up whenever an item is added to the
+        queue. The count goes down whenever a consumer thread calls task_done()
+        to indicate the item was retrieved and all work on it is complete.
+
+        When the count of unfinished tasks drops to zero, join() unblocks.
+        """
+        self.all_tasks_done.acquire()
+        try:
+            while self.unfinished_tasks:
+                self.all_tasks_done.wait()
+        finally:
+            self.all_tasks_done.release()
+
+    def qsize(self):
+        """Return the approximate size of the queue (not reliable!)."""
+        self.mutex.acquire()
+        n = self._qsize()
+        self.mutex.release()
+        return n
+
+    def empty(self):
+        """Return True if the queue is empty, False otherwise (not reliable!)."""
+        self.mutex.acquire()
+        n = not self._qsize()
+        self.mutex.release()
+        return n
+
+    def full(self):
+        """Return True if the queue is full, False otherwise (not reliable!)."""
+        self.mutex.acquire()
+        n = 0 < self.maxsize == self._qsize()
+        self.mutex.release()
+        return n
+
+    def put(self, item, block=True, timeout=None):
+        """Put an item into the queue.
+
+        If optional args 'block' is true and 'timeout' is None (the default),
+        block if necessary until a free slot is available. If 'timeout' is
+        a positive number, it blocks at most 'timeout' seconds and raises
+        the Full exception if no free slot was available within that time.
+        Otherwise ('block' is false), put an item on the queue if a free slot
+        is immediately available, else raise the Full exception ('timeout'
+        is ignored in that case).
+        """
+        self.not_full.acquire()
+        try:
+            if self.maxsize > 0:
+                if not block:
+                    if self._qsize() == self.maxsize:
+                        raise Full
+                elif timeout is None:
+                    while self._qsize() == self.maxsize:
+                        self.not_full.wait()
+                elif timeout < 0:
+                    raise ValueError("'timeout' must be a positive number")
+                else:
+                    endtime = _time() + timeout
+                    while self._qsize() == self.maxsize:
+                        remaining = endtime - _time()
+                        if remaining <= 0.0:
+                            raise Full
+                        self.not_full.wait(remaining)
+            self._put(item)
+            self.unfinished_tasks += 1
+            self.not_empty.notify()
+        finally:
+            self.not_full.release()
+
+    def put_nowait(self, item):
+        """Put an item into the queue without blocking.
+
+        Only enqueue the item if a free slot is immediately available.
+        Otherwise raise the Full exception.
+        """
+        return self.put(item, False)
+
+    def get(self, block=True, timeout=None):
+        """Remove and return an item from the queue.
+
+        If optional args 'block' is true and 'timeout' is None (the default),
+        block if necessary until an item is available. If 'timeout' is
+        a positive number, it blocks at most 'timeout' seconds and raises
+        the Empty exception if no item was available within that time.
+        Otherwise ('block' is false), return an item if one is immediately
+        available, else raise the Empty exception ('timeout' is ignored
+        in that case).
+        """
+        self.not_empty.acquire()
+        try:
+            if not block:
+                if not self._qsize():
+                    raise Empty
+            elif timeout is None:
+                while not self._qsize():
+                    self.not_empty.wait()
+            elif timeout < 0:
+                raise ValueError("'timeout' must be a positive number")
+            else:
+                endtime = _time() + timeout
+                while not self._qsize():
+                    remaining = endtime - _time()
+                    if remaining <= 0.0:
+                        raise Empty
+                    self.not_empty.wait(remaining)
+            item = self._get()
+            self.not_full.notify()
+            return item
+        finally:
+            self.not_empty.release()
+
+    def get_nowait(self):
+        """Remove and return an item from the queue without blocking.
+
+        Only get an item if one is immediately available. Otherwise
+        raise the Empty exception.
+        """
+        return self.get(False)
+
+    # Override these methods to implement other queue organizations
+    # (e.g. stack or priority queue).
+    # These will only be called with appropriate locks held
+
+    # Initialize the queue representation
+    def _init(self, maxsize):
+        self.queue = deque()
+
+    def _qsize(self, len=len):
+        return len(self.queue)
+
+    # Put a new item in the queue
+    def _put(self, item):
+        self.queue.append(item)
+
+    # Get an item from the queue
+    def _get(self):
+        return self.queue.popleft()
+
+
+class PriorityQueue(Queue):
+    '''Variant of Queue that retrieves open entries in priority order (lowest first).
+
+    Entries are typically tuples of the form:  (priority number, data).
+    '''
+
+    def _init(self, maxsize):
+        self.queue = []
+
+    def _qsize(self, len=len):
+        return len(self.queue)
+
+    def _put(self, item, heappush=heapq.heappush):
+        heappush(self.queue, item)
+
+    def _get(self, heappop=heapq.heappop):
+        return heappop(self.queue)
+
+
+class LifoQueue(Queue):
+    '''Variant of Queue that retrieves most recently added entries first.'''
+
+    def _init(self, maxsize):
+        self.queue = []
+
+    def _qsize(self, len=len):
+        return len(self.queue)
+
+    def _put(self, item):
+        self.queue.append(item)
+
+    def _get(self):
+        return self.queue.pop()
diff --git a/src/main/resources/PythonLibs/SimpleHTTPServer.py b/src/main/resources/PythonLibs/SimpleHTTPServer.py
new file mode 100644
index 0000000000000000000000000000000000000000..c015742d19441da69c9b76f09af45877fa604018
--- /dev/null
+++ b/src/main/resources/PythonLibs/SimpleHTTPServer.py
@@ -0,0 +1,221 @@
+"""Simple HTTP Server.
+
+This module builds on BaseHTTPServer by implementing the standard GET
+and HEAD requests in a fairly straightforward manner.
+
+"""
+
+
+__version__ = "0.6"
+
+__all__ = ["SimpleHTTPRequestHandler"]
+
+import os
+import posixpath
+import BaseHTTPServer
+import urllib
+import cgi
+import sys
+import shutil
+import mimetypes
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+
+class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+
+    """Simple HTTP request handler with GET and HEAD commands.
+
+    This serves files from the current directory and any of its
+    subdirectories.  The MIME type for files is determined by
+    calling the .guess_type() method.
+
+    The GET and HEAD requests are identical except that the HEAD
+    request omits the actual contents of the file.
+
+    """
+
+    server_version = "SimpleHTTP/" + __version__
+
+    def do_GET(self):
+        """Serve a GET request."""
+        f = self.send_head()
+        if f:
+            self.copyfile(f, self.wfile)
+            f.close()
+
+    def do_HEAD(self):
+        """Serve a HEAD request."""
+        f = self.send_head()
+        if f:
+            f.close()
+
+    def send_head(self):
+        """Common code for GET and HEAD commands.
+
+        This sends the response code and MIME headers.
+
+        Return value is either a file object (which has to be copied
+        to the outputfile by the caller unless the command was HEAD,
+        and must be closed by the caller under all circumstances), or
+        None, in which case the caller has nothing further to do.
+
+        """
+        path = self.translate_path(self.path)
+        f = None
+        if os.path.isdir(path):
+            if not self.path.endswith('/'):
+                # redirect browser - doing basically what apache does
+                self.send_response(301)
+                self.send_header("Location", self.path + "/")
+                self.end_headers()
+                return None
+            for index in "index.html", "index.htm":
+                index = os.path.join(path, index)
+                if os.path.exists(index):
+                    path = index
+                    break
+            else:
+                return self.list_directory(path)
+        ctype = self.guess_type(path)
+        try:
+            # Always read in binary mode. Opening files in text mode may cause
+            # newline translations, making the actual size of the content
+            # transmitted *less* than the content-length!
+            f = open(path, 'rb')
+        except IOError:
+            self.send_error(404, "File not found")
+            return None
+        self.send_response(200)
+        self.send_header("Content-type", ctype)
+        fs = os.fstat(f.fileno()) if hasattr(os, 'fstat') else os.stat(path)
+        self.send_header("Content-Length", str(fs[6]))
+        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
+        self.end_headers()
+        return f
+
+    def list_directory(self, path):
+        """Helper to produce a directory listing (absent index.html).
+
+        Return value is either a file object, or None (indicating an
+        error).  In either case, the headers are sent, making the
+        interface the same as for send_head().
+
+        """
+        try:
+            list = os.listdir(path)
+        except os.error:
+            self.send_error(404, "No permission to list directory")
+            return None
+        list.sort(key=lambda a: a.lower())
+        f = StringIO()
+        displaypath = cgi.escape(urllib.unquote(self.path))
+        f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
+        f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
+        f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
+        f.write("<hr>\n<ul>\n")
+        for name in list:
+            fullname = os.path.join(path, name)
+            displayname = linkname = name
+            # Append / for directories or @ for symbolic links
+            if os.path.isdir(fullname):
+                displayname = name + "/"
+                linkname = name + "/"
+            if os.path.islink(fullname):
+                displayname = name + "@"
+                # Note: a link to a directory displays with @ and links with /
+            f.write('<li><a href="%s">%s</a>\n'
+                    % (urllib.quote(linkname), cgi.escape(displayname)))
+        f.write("</ul>\n<hr>\n</body>\n</html>\n")
+        length = f.tell()
+        f.seek(0)
+        self.send_response(200)
+        if not sys.platform.startswith("java"):
+            encoding = sys.getfilesystemencoding()
+            self.send_header("Content-type", "text/html; charset=%s" % encoding)
+        self.send_header("Content-Length", str(length))
+        self.end_headers()
+        return f
+
+    def translate_path(self, path):
+        """Translate a /-separated PATH to the local filename syntax.
+
+        Components that mean special things to the local file system
+        (e.g. drive or directory names) are ignored.  (XXX They should
+        probably be diagnosed.)
+
+        """
+        # abandon query parameters
+        path = path.split('?',1)[0]
+        path = path.split('#',1)[0]
+        path = posixpath.normpath(urllib.unquote(path))
+        words = path.split('/')
+        words = filter(None, words)
+        path = os.getcwd()
+        for word in words:
+            drive, word = os.path.splitdrive(word)
+            head, word = os.path.split(word)
+            if word in (os.curdir, os.pardir): continue
+            path = os.path.join(path, word)
+        return path
+
+    def copyfile(self, source, outputfile):
+        """Copy all data between two file objects.
+
+        The SOURCE argument is a file object open for reading
+        (or anything with a read() method) and the DESTINATION
+        argument is a file object open for writing (or
+        anything with a write() method).
+
+        The only reason for overriding this would be to change
+        the block size or perhaps to replace newlines by CRLF
+        -- note however that this the default server uses this
+        to copy binary data as well.
+
+        """
+        shutil.copyfileobj(source, outputfile)
+
+    def guess_type(self, path):
+        """Guess the type of a file.
+
+        Argument is a PATH (a filename).
+
+        Return value is a string of the form type/subtype,
+        usable for a MIME Content-type header.
+
+        The default implementation looks the file's extension
+        up in the table self.extensions_map, using application/octet-stream
+        as a default; however it would be permissible (if
+        slow) to look inside the data to make a better guess.
+
+        """
+
+        base, ext = posixpath.splitext(path)
+        if ext in self.extensions_map:
+            return self.extensions_map[ext]
+        ext = ext.lower()
+        if ext in self.extensions_map:
+            return self.extensions_map[ext]
+        else:
+            return self.extensions_map['']
+
+    if not mimetypes.inited:
+        mimetypes.init() # try to read system mime.types
+    extensions_map = mimetypes.types_map.copy()
+    extensions_map.update({
+        '': 'application/octet-stream', # Default
+        '.py': 'text/plain',
+        '.c': 'text/plain',
+        '.h': 'text/plain',
+        })
+
+
+def test(HandlerClass = SimpleHTTPRequestHandler,
+         ServerClass = BaseHTTPServer.HTTPServer):
+    BaseHTTPServer.test(HandlerClass, ServerClass)
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/SimpleXMLRPCServer.py b/src/main/resources/PythonLibs/SimpleXMLRPCServer.py
new file mode 100644
index 0000000000000000000000000000000000000000..f15cd62f4cfb676502a574857cc80c934bc7ba3c
--- /dev/null
+++ b/src/main/resources/PythonLibs/SimpleXMLRPCServer.py
@@ -0,0 +1,707 @@
+r"""Simple XML-RPC Server.
+
+This module can be used to create simple XML-RPC servers
+by creating a server and either installing functions, a
+class instance, or by extending the SimpleXMLRPCServer
+class.
+
+It can also be used to handle XML-RPC requests in a CGI
+environment using CGIXMLRPCRequestHandler.
+
+A list of possible usage patterns follows:
+
+1. Install functions:
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_function(pow)
+server.register_function(lambda x,y: x+y, 'add')
+server.serve_forever()
+
+2. Install an instance:
+
+class MyFuncs:
+    def __init__(self):
+        # make all of the string functions available through
+        # string.func_name
+        import string
+        self.string = string
+    def _listMethods(self):
+        # implement this method so that system.listMethods
+        # knows to advertise the strings methods
+        return list_public_methods(self) + \
+                ['string.' + method for method in list_public_methods(self.string)]
+    def pow(self, x, y): return pow(x, y)
+    def add(self, x, y) : return x + y
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_introspection_functions()
+server.register_instance(MyFuncs())
+server.serve_forever()
+
+3. Install an instance with custom dispatch method:
+
+class Math:
+    def _listMethods(self):
+        # this method must be present for system.listMethods
+        # to work
+        return ['add', 'pow']
+    def _methodHelp(self, method):
+        # this method must be present for system.methodHelp
+        # to work
+        if method == 'add':
+            return "add(2,3) => 5"
+        elif method == 'pow':
+            return "pow(x, y[, z]) => number"
+        else:
+            # By convention, return empty
+            # string if no help is available
+            return ""
+    def _dispatch(self, method, params):
+        if method == 'pow':
+            return pow(*params)
+        elif method == 'add':
+            return params[0] + params[1]
+        else:
+            raise 'bad method'
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_introspection_functions()
+server.register_instance(Math())
+server.serve_forever()
+
+4. Subclass SimpleXMLRPCServer:
+
+class MathServer(SimpleXMLRPCServer):
+    def _dispatch(self, method, params):
+        try:
+            # We are forcing the 'export_' prefix on methods that are
+            # callable through XML-RPC to prevent potential security
+            # problems
+            func = getattr(self, 'export_' + method)
+        except AttributeError:
+            raise Exception('method "%s" is not supported' % method)
+        else:
+            return func(*params)
+
+    def export_add(self, x, y):
+        return x + y
+
+server = MathServer(("localhost", 8000))
+server.serve_forever()
+
+5. CGI script:
+
+server = CGIXMLRPCRequestHandler()
+server.register_function(pow)
+server.handle_request()
+"""
+
+# Written by Brian Quinlan (brian@sweetapp.com).
+# Based on code written by Fredrik Lundh.
+
+import xmlrpclib
+from xmlrpclib import Fault
+import SocketServer
+import BaseHTTPServer
+import sys
+import os
+import traceback
+import re
+try:
+    import fcntl
+except ImportError:
+    fcntl = None
+
+def resolve_dotted_attribute(obj, attr, allow_dotted_names=True):
+    """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d
+
+    Resolves a dotted attribute name to an object.  Raises
+    an AttributeError if any attribute in the chain starts with a '_'.
+
+    If the optional allow_dotted_names argument is false, dots are not
+    supported and this function operates similar to getattr(obj, attr).
+    """
+
+    if allow_dotted_names:
+        attrs = attr.split('.')
+    else:
+        attrs = [attr]
+
+    for i in attrs:
+        if i.startswith('_'):
+            raise AttributeError(
+                'attempt to access private attribute "%s"' % i
+                )
+        else:
+            obj = getattr(obj,i)
+    return obj
+
+def list_public_methods(obj):
+    """Returns a list of attribute strings, found in the specified
+    object, which represent callable attributes"""
+
+    return [member for member in dir(obj)
+                if not member.startswith('_') and
+                    hasattr(getattr(obj, member), '__call__')]
+
+def remove_duplicates(lst):
+    """remove_duplicates([2,2,2,1,3,3]) => [3,1,2]
+
+    Returns a copy of a list without duplicates. Every list
+    item must be hashable and the order of the items in the
+    resulting list is not defined.
+    """
+    u = {}
+    for x in lst:
+        u[x] = 1
+
+    return u.keys()
+
+class SimpleXMLRPCDispatcher:
+    """Mix-in class that dispatches XML-RPC requests.
+
+    This class is used to register XML-RPC method handlers
+    and then to dispatch them. This class doesn't need to be
+    instanced directly when used by SimpleXMLRPCServer but it
+    can be instanced when used by the MultiPathXMLRPCServer.
+    """
+
+    def __init__(self, allow_none=False, encoding=None):
+        self.funcs = {}
+        self.instance = None
+        self.allow_none = allow_none
+        self.encoding = encoding
+
+    def register_instance(self, instance, allow_dotted_names=False):
+        """Registers an instance to respond to XML-RPC requests.
+
+        Only one instance can be installed at a time.
+
+        If the registered instance has a _dispatch method then that
+        method will be called with the name of the XML-RPC method and
+        its parameters as a tuple
+        e.g. instance._dispatch('add',(2,3))
+
+        If the registered instance does not have a _dispatch method
+        then the instance will be searched to find a matching method
+        and, if found, will be called. Methods beginning with an '_'
+        are considered private and will not be called by
+        SimpleXMLRPCServer.
+
+        If a registered function matches a XML-RPC request, then it
+        will be called instead of the registered instance.
+
+        If the optional allow_dotted_names argument is true and the
+        instance does not have a _dispatch method, method names
+        containing dots are supported and resolved, as long as none of
+        the name segments start with an '_'.
+
+            *** SECURITY WARNING: ***
+
+            Enabling the allow_dotted_names options allows intruders
+            to access your module's global variables and may allow
+            intruders to execute arbitrary code on your machine.  Only
+            use this option on a secure, closed network.
+
+        """
+
+        self.instance = instance
+        self.allow_dotted_names = allow_dotted_names
+
+    def register_function(self, function, name = None):
+        """Registers a function to respond to XML-RPC requests.
+
+        The optional name argument can be used to set a Unicode name
+        for the function.
+        """
+
+        if name is None:
+            name = function.__name__
+        self.funcs[name] = function
+
+    def register_introspection_functions(self):
+        """Registers the XML-RPC introspection methods in the system
+        namespace.
+
+        see http://xmlrpc.usefulinc.com/doc/reserved.html
+        """
+
+        self.funcs.update({'system.listMethods' : self.system_listMethods,
+                      'system.methodSignature' : self.system_methodSignature,
+                      'system.methodHelp' : self.system_methodHelp})
+
+    def register_multicall_functions(self):
+        """Registers the XML-RPC multicall method in the system
+        namespace.
+
+        see http://www.xmlrpc.com/discuss/msgReader$1208"""
+
+        self.funcs.update({'system.multicall' : self.system_multicall})
+
+    def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
+        """Dispatches an XML-RPC method from marshalled (XML) data.
+
+        XML-RPC methods are dispatched from the marshalled (XML) data
+        using the _dispatch method and the result is returned as
+        marshalled data. For backwards compatibility, a dispatch
+        function can be provided as an argument (see comment in
+        SimpleXMLRPCRequestHandler.do_POST) but overriding the
+        existing method through subclassing is the preferred means
+        of changing method dispatch behavior.
+        """
+
+        try:
+            params, method = xmlrpclib.loads(data)
+
+            # generate response
+            if dispatch_method is not None:
+                response = dispatch_method(method, params)
+            else:
+                response = self._dispatch(method, params)
+            # wrap response in a singleton tuple
+            response = (response,)
+            response = xmlrpclib.dumps(response, methodresponse=1,
+                                       allow_none=self.allow_none, encoding=self.encoding)
+        except Fault, fault:
+            response = xmlrpclib.dumps(fault, allow_none=self.allow_none,
+                                       encoding=self.encoding)
+        except:
+            # report exception back to server
+            exc_type, exc_value, exc_tb = sys.exc_info()
+            response = xmlrpclib.dumps(
+                xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)),
+                encoding=self.encoding, allow_none=self.allow_none,
+                )
+
+        return response
+
+    def system_listMethods(self):
+        """system.listMethods() => ['add', 'subtract', 'multiple']
+
+        Returns a list of the methods supported by the server."""
+
+        methods = self.funcs.keys()
+        if self.instance is not None:
+            # Instance can implement _listMethod to return a list of
+            # methods
+            if hasattr(self.instance, '_listMethods'):
+                methods = remove_duplicates(
+                        methods + self.instance._listMethods()
+                    )
+            # if the instance has a _dispatch method then we
+            # don't have enough information to provide a list
+            # of methods
+            elif not hasattr(self.instance, '_dispatch'):
+                methods = remove_duplicates(
+                        methods + list_public_methods(self.instance)
+                    )
+        methods.sort()
+        return methods
+
+    def system_methodSignature(self, method_name):
+        """system.methodSignature('add') => [double, int, int]
+
+        Returns a list describing the signature of the method. In the
+        above example, the add method takes two integers as arguments
+        and returns a double result.
+
+        This server does NOT support system.methodSignature."""
+
+        # See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html
+
+        return 'signatures not supported'
+
+    def system_methodHelp(self, method_name):
+        """system.methodHelp('add') => "Adds two integers together"
+
+        Returns a string containing documentation for the specified method."""
+
+        method = None
+        if method_name in self.funcs:
+            method = self.funcs[method_name]
+        elif self.instance is not None:
+            # Instance can implement _methodHelp to return help for a method
+            if hasattr(self.instance, '_methodHelp'):
+                return self.instance._methodHelp(method_name)
+            # if the instance has a _dispatch method then we
+            # don't have enough information to provide help
+            elif not hasattr(self.instance, '_dispatch'):
+                try:
+                    method = resolve_dotted_attribute(
+                                self.instance,
+                                method_name,
+                                self.allow_dotted_names
+                                )
+                except AttributeError:
+                    pass
+
+        # Note that we aren't checking that the method actually
+        # be a callable object of some kind
+        if method is None:
+            return ""
+        else:
+            import pydoc
+            return pydoc.getdoc(method)
+
+    def system_multicall(self, call_list):
+        """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => \
+[[4], ...]
+
+        Allows the caller to package multiple XML-RPC calls into a single
+        request.
+
+        See http://www.xmlrpc.com/discuss/msgReader$1208
+        """
+
+        results = []
+        for call in call_list:
+            method_name = call['methodName']
+            params = call['params']
+
+            try:
+                # XXX A marshalling error in any response will fail the entire
+                # multicall. If someone cares they should fix this.
+                results.append([self._dispatch(method_name, params)])
+            except Fault, fault:
+                results.append(
+                    {'faultCode' : fault.faultCode,
+                     'faultString' : fault.faultString}
+                    )
+            except:
+                exc_type, exc_value, exc_tb = sys.exc_info()
+                results.append(
+                    {'faultCode' : 1,
+                     'faultString' : "%s:%s" % (exc_type, exc_value)}
+                    )
+        return results
+
+    def _dispatch(self, method, params):
+        """Dispatches the XML-RPC method.
+
+        XML-RPC calls are forwarded to a registered function that
+        matches the called XML-RPC method name. If no such function
+        exists then the call is forwarded to the registered instance,
+        if available.
+
+        If the registered instance has a _dispatch method then that
+        method will be called with the name of the XML-RPC method and
+        its parameters as a tuple
+        e.g. instance._dispatch('add',(2,3))
+
+        If the registered instance does not have a _dispatch method
+        then the instance will be searched to find a matching method
+        and, if found, will be called.
+
+        Methods beginning with an '_' are considered private and will
+        not be called.
+        """
+
+        func = None
+        try:
+            # check to see if a matching function has been registered
+            func = self.funcs[method]
+        except KeyError:
+            if self.instance is not None:
+                # check for a _dispatch method
+                if hasattr(self.instance, '_dispatch'):
+                    return self.instance._dispatch(method, params)
+                else:
+                    # call instance method directly
+                    try:
+                        func = resolve_dotted_attribute(
+                            self.instance,
+                            method,
+                            self.allow_dotted_names
+                            )
+                    except AttributeError:
+                        pass
+
+        if func is not None:
+            return func(*params)
+        else:
+            raise Exception('method "%s" is not supported' % method)
+
+class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+    """Simple XML-RPC request handler class.
+
+    Handles all HTTP POST requests and attempts to decode them as
+    XML-RPC requests.
+    """
+
+    # Class attribute listing the accessible path components;
+    # paths not on this list will result in a 404 error.
+    rpc_paths = ('/', '/RPC2')
+
+    #if not None, encode responses larger than this, if possible
+    encode_threshold = 1400 #a common MTU
+
+    #Override form StreamRequestHandler: full buffering of output
+    #and no Nagle.
+    wbufsize = -1
+    disable_nagle_algorithm = True
+
+    # a re to match a gzip Accept-Encoding
+    aepattern = re.compile(r"""
+                            \s* ([^\s;]+) \s*            #content-coding
+                            (;\s* q \s*=\s* ([0-9\.]+))? #q
+                            """, re.VERBOSE | re.IGNORECASE)
+
+    def accept_encodings(self):
+        r = {}
+        ae = self.headers.get("Accept-Encoding", "")
+        for e in ae.split(","):
+            match = self.aepattern.match(e)
+            if match:
+                v = match.group(3)
+                v = float(v) if v else 1.0
+                r[match.group(1)] = v
+        return r
+
+    def is_rpc_path_valid(self):
+        if self.rpc_paths:
+            return self.path in self.rpc_paths
+        else:
+            # If .rpc_paths is empty, just assume all paths are legal
+            return True
+
+    def do_POST(self):
+        """Handles the HTTP POST request.
+
+        Attempts to interpret all HTTP POST requests as XML-RPC calls,
+        which are forwarded to the server's _dispatch method for handling.
+        """
+
+        # Check that the path is legal
+        if not self.is_rpc_path_valid():
+            self.report_404()
+            return
+
+        try:
+            # Get arguments by reading body of request.
+            # We read this in chunks to avoid straining
+            # socket.read(); around the 10 or 15Mb mark, some platforms
+            # begin to have problems (bug #792570).
+            max_chunk_size = 10*1024*1024
+            size_remaining = int(self.headers["content-length"])
+            L = []
+            while size_remaining:
+                chunk_size = min(size_remaining, max_chunk_size)
+                chunk = self.rfile.read(chunk_size)
+                if not chunk:
+                    break
+                L.append(chunk)
+                size_remaining -= len(L[-1])
+            data = ''.join(L)
+
+            data = self.decode_request_content(data)
+            if data is None:
+                return #response has been sent
+
+            # In previous versions of SimpleXMLRPCServer, _dispatch
+            # could be overridden in this class, instead of in
+            # SimpleXMLRPCDispatcher. To maintain backwards compatibility,
+            # check to see if a subclass implements _dispatch and dispatch
+            # using that method if present.
+            response = self.server._marshaled_dispatch(
+                    data, getattr(self, '_dispatch', None), self.path
+                )
+        except Exception, e: # This should only happen if the module is buggy
+            # internal error, report as HTTP server error
+            self.send_response(500)
+
+            # Send information about the exception if requested
+            if hasattr(self.server, '_send_traceback_header') and \
+                    self.server._send_traceback_header:
+                self.send_header("X-exception", str(e))
+                self.send_header("X-traceback", traceback.format_exc())
+
+            self.send_header("Content-length", "0")
+            self.end_headers()
+        else:
+            # got a valid XML RPC response
+            self.send_response(200)
+            self.send_header("Content-type", "text/xml")
+            if self.encode_threshold is not None:
+                if len(response) > self.encode_threshold:
+                    q = self.accept_encodings().get("gzip", 0)
+                    if q:
+                        try:
+                            response = xmlrpclib.gzip_encode(response)
+                            self.send_header("Content-Encoding", "gzip")
+                        except NotImplementedError:
+                            pass
+            self.send_header("Content-length", str(len(response)))
+            self.end_headers()
+            self.wfile.write(response)
+
+    def decode_request_content(self, data):
+        #support gzip encoding of request
+        encoding = self.headers.get("content-encoding", "identity").lower()
+        if encoding == "identity":
+            return data
+        if encoding == "gzip":
+            try:
+                return xmlrpclib.gzip_decode(data)
+            except NotImplementedError:
+                self.send_response(501, "encoding %r not supported" % encoding)
+            except ValueError:
+                self.send_response(400, "error decoding gzip content")
+        else:
+            self.send_response(501, "encoding %r not supported" % encoding)
+        self.send_header("Content-length", "0")
+        self.end_headers()
+
+    def report_404 (self):
+            # Report a 404 error
+        self.send_response(404)
+        response = 'No such page'
+        self.send_header("Content-type", "text/plain")
+        self.send_header("Content-length", str(len(response)))
+        self.end_headers()
+        self.wfile.write(response)
+
+    def log_request(self, code='-', size='-'):
+        """Selectively log an accepted request."""
+
+        if self.server.logRequests:
+            BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size)
+
+class SimpleXMLRPCServer(SocketServer.TCPServer,
+                         SimpleXMLRPCDispatcher):
+    """Simple XML-RPC server.
+
+    Simple XML-RPC server that allows functions and a single instance
+    to be installed to handle requests. The default implementation
+    attempts to dispatch XML-RPC calls to the functions or instance
+    installed in the server. Override the _dispatch method inhereted
+    from SimpleXMLRPCDispatcher to change this behavior.
+    """
+
+    allow_reuse_address = True
+
+    # Warning: this is for debugging purposes only! Never set this to True in
+    # production code, as will be sending out sensitive information (exception
+    # and stack trace details) when exceptions are raised inside
+    # SimpleXMLRPCRequestHandler.do_POST
+    _send_traceback_header = False
+
+    def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
+                 logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
+        self.logRequests = logRequests
+
+        SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
+        SocketServer.TCPServer.__init__(self, addr, requestHandler, bind_and_activate)
+
+        # [Bug #1222790] If possible, set close-on-exec flag; if a
+        # method spawns a subprocess, the subprocess shouldn't have
+        # the listening socket open.
+        if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
+            flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
+            flags |= fcntl.FD_CLOEXEC
+            fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
+
+class MultiPathXMLRPCServer(SimpleXMLRPCServer):
+    """Multipath XML-RPC Server
+    This specialization of SimpleXMLRPCServer allows the user to create
+    multiple Dispatcher instances and assign them to different
+    HTTP request paths.  This makes it possible to run two or more
+    'virtual XML-RPC servers' at the same port.
+    Make sure that the requestHandler accepts the paths in question.
+    """
+    def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
+                 logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
+
+        SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests, allow_none,
+                                    encoding, bind_and_activate)
+        self.dispatchers = {}
+        self.allow_none = allow_none
+        self.encoding = encoding
+
+    def add_dispatcher(self, path, dispatcher):
+        self.dispatchers[path] = dispatcher
+        return dispatcher
+
+    def get_dispatcher(self, path):
+        return self.dispatchers[path]
+
+    def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
+        try:
+            response = self.dispatchers[path]._marshaled_dispatch(
+               data, dispatch_method, path)
+        except:
+            # report low level exception back to server
+            # (each dispatcher should have handled their own
+            # exceptions)
+            exc_type, exc_value = sys.exc_info()[:2]
+            response = xmlrpclib.dumps(
+                xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)),
+                encoding=self.encoding, allow_none=self.allow_none)
+        return response
+
+class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
+    """Simple handler for XML-RPC data passed through CGI."""
+
+    def __init__(self, allow_none=False, encoding=None):
+        SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
+
+    def handle_xmlrpc(self, request_text):
+        """Handle a single XML-RPC request"""
+
+        response = self._marshaled_dispatch(request_text)
+
+        print 'Content-Type: text/xml'
+        print 'Content-Length: %d' % len(response)
+        print
+        sys.stdout.write(response)
+
+    def handle_get(self):
+        """Handle a single HTTP GET request.
+
+        Default implementation indicates an error because
+        XML-RPC uses the POST method.
+        """
+
+        code = 400
+        message, explain = \
+                 BaseHTTPServer.BaseHTTPRequestHandler.responses[code]
+
+        response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % \
+            {
+             'code' : code,
+             'message' : message,
+             'explain' : explain
+            }
+        print 'Status: %d %s' % (code, message)
+        print 'Content-Type: %s' % BaseHTTPServer.DEFAULT_ERROR_CONTENT_TYPE
+        print 'Content-Length: %d' % len(response)
+        print
+        sys.stdout.write(response)
+
+    def handle_request(self, request_text = None):
+        """Handle a single XML-RPC request passed through a CGI post method.
+
+        If no XML data is given then it is read from stdin. The resulting
+        XML-RPC response is printed to stdout along with the correct HTTP
+        headers.
+        """
+
+        if request_text is None and \
+            os.environ.get('REQUEST_METHOD', None) == 'GET':
+            self.handle_get()
+        else:
+            # POST data is normally available through stdin
+            try:
+                length = int(os.environ.get('CONTENT_LENGTH', None))
+            except (TypeError, ValueError):
+                length = -1
+            if request_text is None:
+                request_text = sys.stdin.read(length)
+
+            self.handle_xmlrpc(request_text)
+
+if __name__ == '__main__':
+    print 'Running XML-RPC server on port 8000'
+    server = SimpleXMLRPCServer(("localhost", 8000))
+    server.register_function(pow)
+    server.register_function(lambda x,y: x+y, 'add')
+    server.serve_forever()
diff --git a/src/main/resources/PythonLibs/SocketServer.py b/src/main/resources/PythonLibs/SocketServer.py
new file mode 100644
index 0000000000000000000000000000000000000000..fab03ac0f7d28b81d8faf85241fd39da85c2776c
--- /dev/null
+++ b/src/main/resources/PythonLibs/SocketServer.py
@@ -0,0 +1,723 @@
+"""Generic socket server classes.
+
+This module tries to capture the various aspects of defining a server:
+
+For socket-based servers:
+
+- address family:
+        - AF_INET{,6}: IP (Internet Protocol) sockets (default)
+        - AF_UNIX: Unix domain sockets
+        - others, e.g. AF_DECNET are conceivable (see <socket.h>
+- socket type:
+        - SOCK_STREAM (reliable stream, e.g. TCP)
+        - SOCK_DGRAM (datagrams, e.g. UDP)
+
+For request-based servers (including socket-based):
+
+- client address verification before further looking at the request
+        (This is actually a hook for any processing that needs to look
+         at the request before anything else, e.g. logging)
+- how to handle multiple requests:
+        - synchronous (one request is handled at a time)
+        - forking (each request is handled by a new process)
+        - threading (each request is handled by a new thread)
+
+The classes in this module favor the server type that is simplest to
+write: a synchronous TCP/IP server.  This is bad class design, but
+save some typing.  (There's also the issue that a deep class hierarchy
+slows down method lookups.)
+
+There are five classes in an inheritance diagram, four of which represent
+synchronous servers of four types:
+
+        +------------+
+        | BaseServer |
+        +------------+
+              |
+              v
+        +-----------+        +------------------+
+        | TCPServer |------->| UnixStreamServer |
+        +-----------+        +------------------+
+              |
+              v
+        +-----------+        +--------------------+
+        | UDPServer |------->| UnixDatagramServer |
+        +-----------+        +--------------------+
+
+Note that UnixDatagramServer derives from UDPServer, not from
+UnixStreamServer -- the only difference between an IP and a Unix
+stream server is the address family, which is simply repeated in both
+unix server classes.
+
+Forking and threading versions of each type of server can be created
+using the ForkingMixIn and ThreadingMixIn mix-in classes.  For
+instance, a threading UDP server class is created as follows:
+
+        class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
+
+The Mix-in class must come first, since it overrides a method defined
+in UDPServer! Setting the various member variables also changes
+the behavior of the underlying server mechanism.
+
+To implement a service, you must derive a class from
+BaseRequestHandler and redefine its handle() method.  You can then run
+various versions of the service by combining one of the server classes
+with your request handler class.
+
+The request handler class must be different for datagram or stream
+services.  This can be hidden by using the request handler
+subclasses StreamRequestHandler or DatagramRequestHandler.
+
+Of course, you still have to use your head!
+
+For instance, it makes no sense to use a forking server if the service
+contains state in memory that can be modified by requests (since the
+modifications in the child process would never reach the initial state
+kept in the parent process and passed to each child).  In this case,
+you can use a threading server, but you will probably have to use
+locks to avoid two requests that come in nearly simultaneous to apply
+conflicting changes to the server state.
+
+On the other hand, if you are building e.g. an HTTP server, where all
+data is stored externally (e.g. in the file system), a synchronous
+class will essentially render the service "deaf" while one request is
+being handled -- which may be for a very long time if a client is slow
+to reqd all the data it has requested.  Here a threading or forking
+server is appropriate.
+
+In some cases, it may be appropriate to process part of a request
+synchronously, but to finish processing in a forked child depending on
+the request data.  This can be implemented by using a synchronous
+server and doing an explicit fork in the request handler class
+handle() method.
+
+Another approach to handling multiple simultaneous requests in an
+environment that supports neither threads nor fork (or where these are
+too expensive or inappropriate for the service) is to maintain an
+explicit table of partially finished requests and to use select() to
+decide which request to work on next (or whether to handle a new
+incoming request).  This is particularly important for stream services
+where each client can potentially be connected for a long time (if
+threads or subprocesses cannot be used).
+
+Future work:
+- Standard classes for Sun RPC (which uses either UDP or TCP)
+- Standard mix-in classes to implement various authentication
+  and encryption schemes
+- Standard framework for select-based multiplexing
+
+XXX Open problems:
+- What to do with out-of-band data?
+
+BaseServer:
+- split generic "request" functionality out into BaseServer class.
+  Copyright (C) 2000  Luke Kenneth Casson Leighton <lkcl@samba.org>
+
+  example: read entries from a SQL database (requires overriding
+  get_request() to return a table entry from the database).
+  entry is processed by a RequestHandlerClass.
+
+"""
+
+# Author of the BaseServer patch: Luke Kenneth Casson Leighton
+
+# XXX Warning!
+# There is a test suite for this module, but it cannot be run by the
+# standard regression test.
+# To run it manually, run Lib/test/test_socketserver.py.
+
+__version__ = "0.4"
+
+
+import socket
+import select
+import sys
+import os
+try:
+    import threading
+except ImportError:
+    import dummy_threading as threading
+
+select_fn = select.select
+if sys.platform.startswith('java'):
+    select_fn = select.cpython_compatible_select
+
+__all__ = ["TCPServer","UDPServer","ForkingUDPServer","ForkingTCPServer",
+           "ThreadingUDPServer","ThreadingTCPServer","BaseRequestHandler",
+           "StreamRequestHandler","DatagramRequestHandler",
+           "ThreadingMixIn", "ForkingMixIn"]
+if hasattr(socket, "AF_UNIX"):
+    __all__.extend(["UnixStreamServer","UnixDatagramServer",
+                    "ThreadingUnixStreamServer",
+                    "ThreadingUnixDatagramServer"])
+
+class BaseServer:
+
+    """Base class for server classes.
+
+    Methods for the caller:
+
+    - __init__(server_address, RequestHandlerClass)
+    - serve_forever(poll_interval=0.5)
+    - shutdown()
+    - handle_request()  # if you do not use serve_forever()
+    - fileno() -> int   # for select()
+
+    Methods that may be overridden:
+
+    - server_bind()
+    - server_activate()
+    - get_request() -> request, client_address
+    - handle_timeout()
+    - verify_request(request, client_address)
+    - server_close()
+    - process_request(request, client_address)
+    - shutdown_request(request)
+    - close_request(request)
+    - handle_error()
+
+    Methods for derived classes:
+
+    - finish_request(request, client_address)
+
+    Class variables that may be overridden by derived classes or
+    instances:
+
+    - timeout
+    - address_family
+    - socket_type
+    - allow_reuse_address
+
+    Instance variables:
+
+    - RequestHandlerClass
+    - socket
+
+    """
+
+    timeout = None
+
+    def __init__(self, server_address, RequestHandlerClass):
+        """Constructor.  May be extended, do not override."""
+        self.server_address = server_address
+        self.RequestHandlerClass = RequestHandlerClass
+        self.__is_shut_down = threading.Event()
+        self.__shutdown_request = False
+
+    def server_activate(self):
+        """Called by constructor to activate the server.
+
+        May be overridden.
+
+        """
+        pass
+
+    def serve_forever(self, poll_interval=0.5):
+        """Handle one request at a time until shutdown.
+
+        Polls for shutdown every poll_interval seconds. Ignores
+        self.timeout. If you need to do periodic tasks, do them in
+        another thread.
+        """
+        self.__is_shut_down.clear()
+        try:
+            while not self.__shutdown_request:
+                # XXX: Consider using another file descriptor or
+                # connecting to the socket to wake this up instead of
+                # polling. Polling reduces our responsiveness to a
+                # shutdown request and wastes cpu at all other times.
+                r, w, e = select_fn([self], [], [], poll_interval)
+                if self in r:
+                    self._handle_request_noblock()
+        finally:
+            self.__shutdown_request = False
+            self.__is_shut_down.set()
+
+    def shutdown(self):
+        """Stops the serve_forever loop.
+
+        Blocks until the loop has finished. This must be called while
+        serve_forever() is running in another thread, or it will
+        deadlock.
+        """
+        self.__shutdown_request = True
+        self.__is_shut_down.wait()
+
+    # The distinction between handling, getting, processing and
+    # finishing a request is fairly arbitrary.  Remember:
+    #
+    # - handle_request() is the top-level call.  It calls
+    #   select, get_request(), verify_request() and process_request()
+    # - get_request() is different for stream or datagram sockets
+    # - process_request() is the place that may fork a new process
+    #   or create a new thread to finish the request
+    # - finish_request() instantiates the request handler class;
+    #   this constructor will handle the request all by itself
+
+    def handle_request(self):
+        """Handle one request, possibly blocking.
+
+        Respects self.timeout.
+        """
+        # Support people who used socket.settimeout() to escape
+        # handle_request before self.timeout was available.
+        timeout = self.socket.gettimeout()
+        if timeout is None:
+            timeout = self.timeout
+        elif self.timeout is not None:
+            timeout = min(timeout, self.timeout)
+        fd_sets = select_fn([self], [], [], timeout)
+        if not fd_sets[0]:
+            self.handle_timeout()
+            return
+        self._handle_request_noblock()
+
+    def _handle_request_noblock(self):
+        """Handle one request, without blocking.
+
+        I assume that select_fn has returned that the socket is
+        readable before this function was called, so there should be
+        no risk of blocking in get_request().
+        """
+        try:
+            request, client_address = self.get_request()
+        except socket.error:
+            return
+        if self.verify_request(request, client_address):
+            try:
+                self.process_request(request, client_address)
+            except:
+                self.handle_error(request, client_address)
+                self.shutdown_request(request)
+
+    def handle_timeout(self):
+        """Called if no new request arrives within self.timeout.
+
+        Overridden by ForkingMixIn.
+        """
+        pass
+
+    def verify_request(self, request, client_address):
+        """Verify the request.  May be overridden.
+
+        Return True if we should proceed with this request.
+
+        """
+        return True
+
+    def process_request(self, request, client_address):
+        """Call finish_request.
+
+        Overridden by ForkingMixIn and ThreadingMixIn.
+
+        """
+        self.finish_request(request, client_address)
+        self.shutdown_request(request)
+
+    def server_close(self):
+        """Called to clean-up the server.
+
+        May be overridden.
+
+        """
+        pass
+
+    def finish_request(self, request, client_address):
+        """Finish one request by instantiating RequestHandlerClass."""
+        self.RequestHandlerClass(request, client_address, self)
+
+    def shutdown_request(self, request):
+        """Called to shutdown and close an individual request."""
+        self.close_request(request)
+
+    def close_request(self, request):
+        """Called to clean up an individual request."""
+        pass
+
+    def handle_error(self, request, client_address):
+        """Handle an error gracefully.  May be overridden.
+
+        The default is to print a traceback and continue.
+
+        """
+        print '-'*40
+        print 'Exception happened during processing of request from',
+        print client_address
+        import traceback
+        traceback.print_exc() # XXX But this goes to stderr!
+        print '-'*40
+
+
+class TCPServer(BaseServer):
+
+    """Base class for various socket-based server classes.
+
+    Defaults to synchronous IP stream (i.e., TCP).
+
+    Methods for the caller:
+
+    - __init__(server_address, RequestHandlerClass, bind_and_activate=True)
+    - serve_forever(poll_interval=0.5)
+    - shutdown()
+    - handle_request()  # if you don't use serve_forever()
+    - fileno() -> int   # for select()
+
+    Methods that may be overridden:
+
+    - server_bind()
+    - server_activate()
+    - get_request() -> request, client_address
+    - handle_timeout()
+    - verify_request(request, client_address)
+    - process_request(request, client_address)
+    - shutdown_request(request)
+    - close_request(request)
+    - handle_error()
+
+    Methods for derived classes:
+
+    - finish_request(request, client_address)
+
+    Class variables that may be overridden by derived classes or
+    instances:
+
+    - timeout
+    - address_family
+    - socket_type
+    - request_queue_size (only for stream sockets)
+    - allow_reuse_address
+
+    Instance variables:
+
+    - server_address
+    - RequestHandlerClass
+    - socket
+
+    """
+
+    address_family = socket.AF_INET
+
+    socket_type = socket.SOCK_STREAM
+
+    request_queue_size = 5
+
+    allow_reuse_address = False
+
+    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
+        """Constructor.  May be extended, do not override."""
+        BaseServer.__init__(self, server_address, RequestHandlerClass)
+        self.socket = socket.socket(self.address_family,
+                                    self.socket_type)
+        if bind_and_activate:
+            self.server_bind()
+            self.server_activate()
+
+    def server_bind(self):
+        """Called by constructor to bind the socket.
+
+        May be overridden.
+
+        """
+        if self.allow_reuse_address:
+            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        self.socket.bind(self.server_address)
+        self.server_address = self.socket.getsockname()
+
+    def server_activate(self):
+        """Called by constructor to activate the server.
+
+        May be overridden.
+
+        """
+        self.socket.listen(self.request_queue_size)
+        # Adding a second call to getsockname() because of this issue
+        # http://wiki.python.org/jython/NewSocketModule#Deferredsocketcreationonjython
+        self.server_address = self.socket.getsockname()
+
+    def server_close(self):
+        """Called to clean-up the server.
+
+        May be overridden.
+
+        """
+        self.socket.close()
+
+    def fileno(self):
+        """Return socket file number.
+
+        Interface required by select().
+
+        """
+        return self.socket.fileno()
+
+    def get_request(self):
+        """Get the request and client address from the socket.
+
+        May be overridden.
+
+        """
+        return self.socket.accept()
+
+    def shutdown_request(self, request):
+        """Called to shutdown and close an individual request."""
+        try:
+            #explicitly shutdown.  socket.close() merely releases
+            #the socket and waits for GC to perform the actual close.
+            request.shutdown(socket.SHUT_WR)
+        except socket.error:
+            pass #some platforms may raise ENOTCONN here
+        self.close_request(request)
+
+    def close_request(self, request):
+        """Called to clean up an individual request."""
+        request.close()
+
+
+class UDPServer(TCPServer):
+
+    """UDP server class."""
+
+    allow_reuse_address = False
+
+    socket_type = socket.SOCK_DGRAM
+
+    max_packet_size = 8192
+
+    def get_request(self):
+        data, client_addr = self.socket.recvfrom(self.max_packet_size)
+        return (data, self.socket), client_addr
+
+    def server_activate(self):
+        # No need to call listen() for UDP.
+        pass
+
+    def shutdown_request(self, request):
+        # No need to shutdown anything.
+        self.close_request(request)
+
+    def close_request(self, request):
+        # No need to close anything.
+        pass
+
+class ForkingMixIn:
+
+    """Mix-in class to handle each request in a new process."""
+
+    timeout = 300
+    active_children = None
+    max_children = 40
+
+    def collect_children(self):
+        """Internal routine to wait for children that have exited."""
+        if self.active_children is None: return
+        while len(self.active_children) >= self.max_children:
+            # XXX: This will wait for any child process, not just ones
+            # spawned by this library. This could confuse other
+            # libraries that expect to be able to wait for their own
+            # children.
+            try:
+                pid, status = os.waitpid(0, 0)
+            except os.error:
+                pid = None
+            if pid not in self.active_children: continue
+            self.active_children.remove(pid)
+
+        # XXX: This loop runs more system calls than it ought
+        # to. There should be a way to put the active_children into a
+        # process group and then use os.waitpid(-pgid) to wait for any
+        # of that set, but I couldn't find a way to allocate pgids
+        # that couldn't collide.
+        for child in self.active_children:
+            try:
+                pid, status = os.waitpid(child, os.WNOHANG)
+            except os.error:
+                pid = None
+            if not pid: continue
+            try:
+                self.active_children.remove(pid)
+            except ValueError, e:
+                raise ValueError('%s. x=%d and list=%r' % (e.message, pid,
+                                                           self.active_children))
+
+    def handle_timeout(self):
+        """Wait for zombies after self.timeout seconds of inactivity.
+
+        May be extended, do not override.
+        """
+        self.collect_children()
+
+    def process_request(self, request, client_address):
+        """Fork a new subprocess to process the request."""
+        self.collect_children()
+        pid = os.fork()
+        if pid:
+            # Parent process
+            if self.active_children is None:
+                self.active_children = []
+            self.active_children.append(pid)
+            self.close_request(request) #close handle in parent process
+            return
+        else:
+            # Child process.
+            # This must never return, hence os._exit()!
+            try:
+                self.finish_request(request, client_address)
+                self.shutdown_request(request)
+                os._exit(0)
+            except:
+                try:
+                    self.handle_error(request, client_address)
+                    self.shutdown_request(request)
+                finally:
+                    os._exit(1)
+
+
+class ThreadingMixIn:
+    """Mix-in class to handle each request in a new thread."""
+
+    # Decides how threads will act upon termination of the
+    # main process
+    daemon_threads = False
+
+    def process_request_thread(self, request, client_address):
+        """Same as in BaseServer but as a thread.
+
+        In addition, exception handling is done here.
+
+        """
+        try:
+            self.finish_request(request, client_address)
+            self.shutdown_request(request)
+        except:
+            self.handle_error(request, client_address)
+            self.shutdown_request(request)
+
+    def process_request(self, request, client_address):
+        """Start a new thread to process the request."""
+        t = threading.Thread(target = self.process_request_thread,
+                             args = (request, client_address))
+        if self.daemon_threads:
+            t.setDaemon (1)
+        t.start()
+
+
+class ForkingUDPServer(ForkingMixIn, UDPServer): pass
+class ForkingTCPServer(ForkingMixIn, TCPServer): pass
+
+class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
+class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
+
+if hasattr(socket, 'AF_UNIX'):
+
+    class UnixStreamServer(TCPServer):
+        address_family = socket.AF_UNIX
+
+    class UnixDatagramServer(UDPServer):
+        address_family = socket.AF_UNIX
+
+    class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): pass
+
+    class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): pass
+
+class BaseRequestHandler:
+
+    """Base class for request handler classes.
+
+    This class is instantiated for each request to be handled.  The
+    constructor sets the instance variables request, client_address
+    and server, and then calls the handle() method.  To implement a
+    specific service, all you need to do is to derive a class which
+    defines a handle() method.
+
+    The handle() method can find the request as self.request, the
+    client address as self.client_address, and the server (in case it
+    needs access to per-server information) as self.server.  Since a
+    separate instance is created for each request, the handle() method
+    can define arbitrary other instance variariables.
+
+    """
+
+    def __init__(self, request, client_address, server):
+        self.request = request
+        self.client_address = client_address
+        self.server = server
+        self.setup()
+        try:
+            self.handle()
+        finally:
+            self.finish()
+
+    def setup(self):
+        pass
+
+    def handle(self):
+        pass
+
+    def finish(self):
+        pass
+
+
+# The following two classes make it possible to use the same service
+# class for stream or datagram servers.
+# Each class sets up these instance variables:
+# - rfile: a file object from which receives the request is read
+# - wfile: a file object to which the reply is written
+# When the handle() method returns, wfile is flushed properly
+
+
+class StreamRequestHandler(BaseRequestHandler):
+
+    """Define self.rfile and self.wfile for stream sockets."""
+
+    # Default buffer sizes for rfile, wfile.
+    # We default rfile to buffered because otherwise it could be
+    # really slow for large data (a getc() call per byte); we make
+    # wfile unbuffered because (a) often after a write() we want to
+    # read and we need to flush the line; (b) big writes to unbuffered
+    # files are typically optimized by stdio even when big reads
+    # aren't.
+    rbufsize = -1
+    wbufsize = 0
+
+    # A timeout to apply to the request socket, if not None.
+    timeout = None
+
+    # Disable nagle algorithm for this socket, if True.
+    # Use only when wbufsize != 0, to avoid small packets.
+    disable_nagle_algorithm = False
+
+    def setup(self):
+        self.connection = self.request
+        if self.timeout is not None:
+            self.connection.settimeout(self.timeout)
+        if self.disable_nagle_algorithm:
+            self.connection.setsockopt(socket.IPPROTO_TCP,
+                                       socket.TCP_NODELAY, True)
+        self.rfile = self.connection.makefile('rb', self.rbufsize)
+        self.wfile = self.connection.makefile('wb', self.wbufsize)
+
+    def finish(self):
+        if not self.wfile.closed:
+            self.wfile.flush()
+        self.wfile.close()
+        self.rfile.close()
+
+
+class DatagramRequestHandler(BaseRequestHandler):
+
+    # XXX Regrettably, I cannot get this working on Linux;
+    # s.recvfrom() doesn't return a meaningful client address.
+
+    """Define self.rfile and self.wfile for datagram sockets."""
+
+    def setup(self):
+        try:
+            from cStringIO import StringIO
+        except ImportError:
+            from StringIO import StringIO
+        self.packet, self.socket = self.request
+        self.rfile = StringIO(self.packet)
+        self.wfile = StringIO()
+
+    def finish(self):
+        self.socket.sendto(self.wfile.getvalue(), self.client_address)
diff --git a/src/main/resources/PythonLibs/StringIO.py b/src/main/resources/PythonLibs/StringIO.py
new file mode 100644
index 0000000000000000000000000000000000000000..b63525b9bfdcef6a146dea47cfd61d8683bfeb31
--- /dev/null
+++ b/src/main/resources/PythonLibs/StringIO.py
@@ -0,0 +1,324 @@
+r"""File-like objects that read from or write to a string buffer.
+
+This implements (nearly) all stdio methods.
+
+f = StringIO()      # ready for writing
+f = StringIO(buf)   # ready for reading
+f.close()           # explicitly release resources held
+flag = f.isatty()   # always false
+pos = f.tell()      # get current position
+f.seek(pos)         # set current position
+f.seek(pos, mode)   # mode 0: absolute; 1: relative; 2: relative to EOF
+buf = f.read()      # read until EOF
+buf = f.read(n)     # read up to n bytes
+buf = f.readline()  # read until end of line ('\n') or EOF
+list = f.readlines()# list of f.readline() results until EOF
+f.truncate([size])  # truncate file at to at most size (default: current pos)
+f.write(buf)        # write at current position
+f.writelines(list)  # for line in list: f.write(line)
+f.getvalue()        # return whole file's contents as a string
+
+Notes:
+- Using a real file is often faster (but less convenient).
+- There's also a much faster implementation in C, called cStringIO, but
+  it's not subclassable.
+- fileno() is left unimplemented so that code which uses it triggers
+  an exception early.
+- Seeking far beyond EOF and then writing will insert real null
+  bytes that occupy space in the buffer.
+- There's a simple test set (see end of this file).
+"""
+try:
+    from errno import EINVAL
+except ImportError:
+    EINVAL = 22
+
+__all__ = ["StringIO"]
+
+def _complain_ifclosed(closed):
+    if closed:
+        raise ValueError, "I/O operation on closed file"
+
+class StringIO:
+    """class StringIO([buffer])
+
+    When a StringIO object is created, it can be initialized to an existing
+    string by passing the string to the constructor. If no string is given,
+    the StringIO will start empty.
+
+    The StringIO object can accept either Unicode or 8-bit strings, but
+    mixing the two may take some care. If both are used, 8-bit strings that
+    cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause
+    a UnicodeError to be raised when getvalue() is called.
+    """
+    def __init__(self, buf = ''):
+        # Force self.buf to be a string or unicode
+        if not isinstance(buf, basestring):
+            buf = str(buf)
+        self.buf = buf
+        self.len = len(buf)
+        self.buflist = []
+        self.pos = 0
+        self.closed = False
+        self.softspace = 0
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        """A file object is its own iterator, for example iter(f) returns f
+        (unless f is closed). When a file is used as an iterator, typically
+        in a for loop (for example, for line in f: print line), the next()
+        method is called repeatedly. This method returns the next input line,
+        or raises StopIteration when EOF is hit.
+        """
+        _complain_ifclosed(self.closed)
+        r = self.readline()
+        if not r:
+            raise StopIteration
+        return r
+
+    def close(self):
+        """Free the memory buffer.
+        """
+        if not self.closed:
+            self.closed = True
+            del self.buf, self.pos
+
+    def isatty(self):
+        """Returns False because StringIO objects are not connected to a
+        tty-like device.
+        """
+        _complain_ifclosed(self.closed)
+        return False
+
+    def seek(self, pos, mode = 0):
+        """Set the file's current position.
+
+        The mode argument is optional and defaults to 0 (absolute file
+        positioning); other values are 1 (seek relative to the current
+        position) and 2 (seek relative to the file's end).
+
+        There is no return value.
+        """
+        _complain_ifclosed(self.closed)
+        if self.buflist:
+            self.buf += ''.join(self.buflist)
+            self.buflist = []
+        if mode == 1:
+            pos += self.pos
+        elif mode == 2:
+            pos += self.len
+        self.pos = max(0, pos)
+
+    def tell(self):
+        """Return the file's current position."""
+        _complain_ifclosed(self.closed)
+        return self.pos
+
+    def read(self, n = -1):
+        """Read at most size bytes from the file
+        (less if the read hits EOF before obtaining size bytes).
+
+        If the size argument is negative or omitted, read all data until EOF
+        is reached. The bytes are returned as a string object. An empty
+        string is returned when EOF is encountered immediately.
+        """
+        _complain_ifclosed(self.closed)
+        if self.buflist:
+            self.buf += ''.join(self.buflist)
+            self.buflist = []
+        if n is None or n < 0:
+            newpos = self.len
+        else:
+            newpos = min(self.pos+n, self.len)
+        r = self.buf[self.pos:newpos]
+        self.pos = newpos
+        return r
+
+    def readline(self, length=None):
+        r"""Read one entire line from the file.
+
+        A trailing newline character is kept in the string (but may be absent
+        when a file ends with an incomplete line). If the size argument is
+        present and non-negative, it is a maximum byte count (including the
+        trailing newline) and an incomplete line may be returned.
+
+        An empty string is returned only when EOF is encountered immediately.
+
+        Note: Unlike stdio's fgets(), the returned string contains null
+        characters ('\0') if they occurred in the input.
+        """
+        _complain_ifclosed(self.closed)
+        if self.buflist:
+            self.buf += ''.join(self.buflist)
+            self.buflist = []
+        i = self.buf.find('\n', self.pos)
+        if i < 0:
+            newpos = self.len
+        else:
+            newpos = i+1
+        if length is not None and length >= 0:
+            if self.pos + length < newpos:
+                newpos = self.pos + length
+        r = self.buf[self.pos:newpos]
+        self.pos = newpos
+        return r
+
+    def readlines(self, sizehint = 0):
+        """Read until EOF using readline() and return a list containing the
+        lines thus read.
+
+        If the optional sizehint argument is present, instead of reading up
+        to EOF, whole lines totalling approximately sizehint bytes (or more
+        to accommodate a final whole line).
+        """
+        total = 0
+        lines = []
+        line = self.readline()
+        while line:
+            lines.append(line)
+            total += len(line)
+            if 0 < sizehint <= total:
+                break
+            line = self.readline()
+        return lines
+
+    def truncate(self, size=None):
+        """Truncate the file's size.
+
+        If the optional size argument is present, the file is truncated to
+        (at most) that size. The size defaults to the current position.
+        The current file position is not changed unless the position
+        is beyond the new file size.
+
+        If the specified size exceeds the file's current size, the
+        file remains unchanged.
+        """
+        _complain_ifclosed(self.closed)
+        if size is None:
+            size = self.pos
+        elif size < 0:
+            raise IOError(EINVAL, "Negative size not allowed")
+        elif size < self.pos:
+            self.pos = size
+        self.buf = self.getvalue()[:size]
+        self.len = size
+
+    def write(self, s):
+        """Write a string to the file.
+
+        There is no return value.
+        """
+        _complain_ifclosed(self.closed)
+        if not s: return
+        # Force s to be a string or unicode
+        if not isinstance(s, basestring):
+            s = str(s)
+        spos = self.pos
+        slen = self.len
+        if spos == slen:
+            self.buflist.append(s)
+            self.len = self.pos = spos + len(s)
+            return
+        if spos > slen:
+            self.buflist.append('\0'*(spos - slen))
+            slen = spos
+        newpos = spos + len(s)
+        if spos < slen:
+            if self.buflist:
+                self.buf += ''.join(self.buflist)
+            self.buflist = [self.buf[:spos], s, self.buf[newpos:]]
+            self.buf = ''
+            if newpos > slen:
+                slen = newpos
+        else:
+            self.buflist.append(s)
+            slen = newpos
+        self.len = slen
+        self.pos = newpos
+
+    def writelines(self, iterable):
+        """Write a sequence of strings to the file. The sequence can be any
+        iterable object producing strings, typically a list of strings. There
+        is no return value.
+
+        (The name is intended to match readlines(); writelines() does not add
+        line separators.)
+        """
+        write = self.write
+        for line in iterable:
+            write(line)
+
+    def flush(self):
+        """Flush the internal buffer
+        """
+        _complain_ifclosed(self.closed)
+
+    def getvalue(self):
+        """
+        Retrieve the entire contents of the "file" at any time before
+        the StringIO object's close() method is called.
+
+        The StringIO object can accept either Unicode or 8-bit strings,
+        but mixing the two may take some care. If both are used, 8-bit
+        strings that cannot be interpreted as 7-bit ASCII (that use the
+        8th bit) will cause a UnicodeError to be raised when getvalue()
+        is called.
+        """
+        _complain_ifclosed(self.closed)
+        if self.buflist:
+            self.buf += ''.join(self.buflist)
+            self.buflist = []
+        return self.buf
+
+
+# A little test suite
+
+def test():
+    import sys
+    if sys.argv[1:]:
+        file = sys.argv[1]
+    else:
+        file = '/etc/passwd'
+    lines = open(file, 'r').readlines()
+    text = open(file, 'r').read()
+    f = StringIO()
+    for line in lines[:-2]:
+        f.write(line)
+    f.writelines(lines[-2:])
+    if f.getvalue() != text:
+        raise RuntimeError, 'write failed'
+    length = f.tell()
+    print 'File length =', length
+    f.seek(len(lines[0]))
+    f.write(lines[1])
+    f.seek(0)
+    print 'First line =', repr(f.readline())
+    print 'Position =', f.tell()
+    line = f.readline()
+    print 'Second line =', repr(line)
+    f.seek(-len(line), 1)
+    line2 = f.read(len(line))
+    if line != line2:
+        raise RuntimeError, 'bad result after seek back'
+    f.seek(len(line2), 1)
+    list = f.readlines()
+    line = list[-1]
+    f.seek(f.tell() - len(line))
+    line2 = f.read()
+    if line != line2:
+        raise RuntimeError, 'bad result after seek back from EOF'
+    print 'Read', len(list), 'more lines'
+    print 'File length =', f.tell()
+    if f.tell() != length:
+        raise RuntimeError, 'bad length'
+    f.truncate(length/2)
+    f.seek(0, 2)
+    print 'Truncated length =', f.tell()
+    if f.tell() != length/2:
+        raise RuntimeError, 'truncate did not adjust length'
+    f.close()
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/UserDict.py b/src/main/resources/PythonLibs/UserDict.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb2218ab6ce5d808a4016105d69b7b637d1252a6
--- /dev/null
+++ b/src/main/resources/PythonLibs/UserDict.py
@@ -0,0 +1,180 @@
+"""A more or less complete user-defined wrapper around dictionary objects."""
+
+class UserDict:
+    def __init__(self, dict=None, **kwargs):
+        self.data = {}
+        if dict is not None:
+            self.update(dict)
+        if len(kwargs):
+            self.update(kwargs)
+    def __repr__(self): return repr(self.data)
+    def __cmp__(self, dict):
+        if isinstance(dict, UserDict):
+            return cmp(self.data, dict.data)
+        else:
+            return cmp(self.data, dict)
+    __hash__ = None # Avoid Py3k warning
+    def __len__(self): return len(self.data)
+    def __getitem__(self, key):
+        if key in self.data:
+            return self.data[key]
+        if hasattr(self.__class__, "__missing__"):
+            return self.__class__.__missing__(self, key)
+        raise KeyError(key)
+    def __setitem__(self, key, item): self.data[key] = item
+    def __delitem__(self, key): del self.data[key]
+    def clear(self): self.data.clear()
+    def copy(self):
+        if self.__class__ is UserDict:
+            return UserDict(self.data.copy())
+        import copy
+        data = self.data
+        try:
+            self.data = {}
+            c = copy.copy(self)
+        finally:
+            self.data = data
+        c.update(self)
+        return c
+    def keys(self): return self.data.keys()
+    def items(self): return self.data.items()
+    def iteritems(self): return self.data.iteritems()
+    def iterkeys(self): return self.data.iterkeys()
+    def itervalues(self): return self.data.itervalues()
+    def values(self): return self.data.values()
+    def has_key(self, key): return key in self.data
+    def update(self, dict=None, **kwargs):
+        if dict is None:
+            pass
+        elif isinstance(dict, UserDict):
+            self.data.update(dict.data)
+        elif isinstance(dict, type({})) or not hasattr(dict, 'items'):
+            self.data.update(dict)
+        else:
+            for k, v in dict.items():
+                self[k] = v
+        if len(kwargs):
+            self.data.update(kwargs)
+    def get(self, key, failobj=None):
+        if key not in self:
+            return failobj
+        return self[key]
+    def setdefault(self, key, failobj=None):
+        if key not in self:
+            self[key] = failobj
+        return self[key]
+    def pop(self, key, *args):
+        return self.data.pop(key, *args)
+    def popitem(self):
+        return self.data.popitem()
+    def __contains__(self, key):
+        return key in self.data
+    @classmethod
+    def fromkeys(cls, iterable, value=None):
+        d = cls()
+        for key in iterable:
+            d[key] = value
+        return d
+
+class IterableUserDict(UserDict):
+    def __iter__(self):
+        return iter(self.data)
+
+import _abcoll
+_abcoll.MutableMapping.register(IterableUserDict)
+
+
+class DictMixin:
+    # Mixin defining all dictionary methods for classes that already have
+    # a minimum dictionary interface including getitem, setitem, delitem,
+    # and keys. Without knowledge of the subclass constructor, the mixin
+    # does not define __init__() or copy().  In addition to the four base
+    # methods, progressively more efficiency comes with defining
+    # __contains__(), __iter__(), and iteritems().
+
+    # second level definitions support higher levels
+    def __iter__(self):
+        for k in self.keys():
+            yield k
+    def has_key(self, key):
+        try:
+            self[key]
+        except KeyError:
+            return False
+        return True
+    def __contains__(self, key):
+        return self.has_key(key)
+
+    # third level takes advantage of second level definitions
+    def iteritems(self):
+        for k in self:
+            yield (k, self[k])
+    def iterkeys(self):
+        return self.__iter__()
+
+    # fourth level uses definitions from lower levels
+    def itervalues(self):
+        for _, v in self.iteritems():
+            yield v
+    def values(self):
+        return [v for _, v in self.iteritems()]
+    def items(self):
+        return list(self.iteritems())
+    def clear(self):
+        for key in self.keys():
+            del self[key]
+    def setdefault(self, key, default=None):
+        try:
+            return self[key]
+        except KeyError:
+            self[key] = default
+        return default
+    def pop(self, key, *args):
+        if len(args) > 1:
+            raise TypeError, "pop expected at most 2 arguments, got "\
+                              + repr(1 + len(args))
+        try:
+            value = self[key]
+        except KeyError:
+            if args:
+                return args[0]
+            raise
+        del self[key]
+        return value
+    def popitem(self):
+        try:
+            k, v = self.iteritems().next()
+        except StopIteration:
+            raise KeyError, 'container is empty'
+        del self[k]
+        return (k, v)
+    def update(self, other=None, **kwargs):
+        # Make progressively weaker assumptions about "other"
+        if other is None:
+            pass
+        elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
+            for k, v in other.iteritems():
+                self[k] = v
+        elif hasattr(other, 'keys'):
+            for k in other.keys():
+                self[k] = other[k]
+        else:
+            for k, v in other:
+                self[k] = v
+        if kwargs:
+            self.update(kwargs)
+    def get(self, key, default=None):
+        try:
+            return self[key]
+        except KeyError:
+            return default
+    def __repr__(self):
+        return repr(dict(self.iteritems()))
+    def __cmp__(self, other):
+        if other is None:
+            return 1
+        if isinstance(other, DictMixin):
+            other = dict(other.iteritems())
+        return cmp(dict(self.iteritems()), other)
+    def __len__(self):
+        return len(self.keys())
diff --git a/src/main/resources/PythonLibs/UserList.py b/src/main/resources/PythonLibs/UserList.py
new file mode 100644
index 0000000000000000000000000000000000000000..b44598570790f42374623b357780bd6b131b4089
--- /dev/null
+++ b/src/main/resources/PythonLibs/UserList.py
@@ -0,0 +1,88 @@
+"""A more or less complete user-defined wrapper around list objects."""
+
+import collections
+
+class UserList(collections.MutableSequence):
+    def __init__(self, initlist=None):
+        self.data = []
+        if initlist is not None:
+            # XXX should this accept an arbitrary sequence?
+            if type(initlist) == type(self.data):
+                self.data[:] = initlist
+            elif isinstance(initlist, UserList):
+                self.data[:] = initlist.data[:]
+            else:
+                self.data = list(initlist)
+    def __repr__(self): return repr(self.data)
+    def __lt__(self, other): return self.data <  self.__cast(other)
+    def __le__(self, other): return self.data <= self.__cast(other)
+    def __eq__(self, other): return self.data == self.__cast(other)
+    def __ne__(self, other): return self.data != self.__cast(other)
+    def __gt__(self, other): return self.data >  self.__cast(other)
+    def __ge__(self, other): return self.data >= self.__cast(other)
+    def __cast(self, other):
+        if isinstance(other, UserList): return other.data
+        else: return other
+    def __cmp__(self, other):
+        return cmp(self.data, self.__cast(other))
+    __hash__ = None # Mutable sequence, so not hashable
+    def __contains__(self, item): return item in self.data
+    def __len__(self): return len(self.data)
+    def __getitem__(self, i): return self.data[i]
+    def __setitem__(self, i, item): self.data[i] = item
+    def __delitem__(self, i): del self.data[i]
+    def __getslice__(self, i, j):
+        i = max(i, 0); j = max(j, 0)
+        return self.__class__(self.data[i:j])
+    def __setslice__(self, i, j, other):
+        i = max(i, 0); j = max(j, 0)
+        if isinstance(other, UserList):
+            self.data[i:j] = other.data
+        elif isinstance(other, type(self.data)):
+            self.data[i:j] = other
+        else:
+            self.data[i:j] = list(other)
+    def __delslice__(self, i, j):
+        i = max(i, 0); j = max(j, 0)
+        del self.data[i:j]
+    def __add__(self, other):
+        if isinstance(other, UserList):
+            return self.__class__(self.data + other.data)
+        elif isinstance(other, type(self.data)):
+            return self.__class__(self.data + other)
+        else:
+            return self.__class__(self.data + list(other))
+    def __radd__(self, other):
+        if isinstance(other, UserList):
+            return self.__class__(other.data + self.data)
+        elif isinstance(other, type(self.data)):
+            return self.__class__(other + self.data)
+        else:
+            return self.__class__(list(other) + self.data)
+    def __iadd__(self, other):
+        if isinstance(other, UserList):
+            self.data += other.data
+        elif isinstance(other, type(self.data)):
+            self.data += other
+        else:
+            self.data += list(other)
+        return self
+    def __mul__(self, n):
+        return self.__class__(self.data*n)
+    __rmul__ = __mul__
+    def __imul__(self, n):
+        self.data *= n
+        return self
+    def append(self, item): self.data.append(item)
+    def insert(self, i, item): self.data.insert(i, item)
+    def pop(self, i=-1): return self.data.pop(i)
+    def remove(self, item): self.data.remove(item)
+    def count(self, item): return self.data.count(item)
+    def index(self, item, *args): return self.data.index(item, *args)
+    def reverse(self): self.data.reverse()
+    def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
+    def extend(self, other):
+        if isinstance(other, UserList):
+            self.data.extend(other.data)
+        else:
+            self.data.extend(other)
diff --git a/src/main/resources/PythonLibs/UserString.py b/src/main/resources/PythonLibs/UserString.py
new file mode 100644
index 0000000000000000000000000000000000000000..726b3f7d3c81f75a8529a4e60e265817736f1d86
--- /dev/null
+++ b/src/main/resources/PythonLibs/UserString.py
@@ -0,0 +1,228 @@
+#!/usr/bin/env python
+## vim:ts=4:et:nowrap
+"""A user-defined wrapper around string objects
+
+Note: string objects have grown methods in Python 1.6
+This module requires Python 1.6 or later.
+"""
+import sys
+import collections
+
+__all__ = ["UserString","MutableString"]
+
+class UserString(collections.Sequence):
+    def __init__(self, seq):
+        if isinstance(seq, basestring):
+            self.data = seq
+        elif isinstance(seq, UserString):
+            self.data = seq.data[:]
+        else:
+            self.data = str(seq)
+    def __str__(self): return str(self.data)
+    def __repr__(self): return repr(self.data)
+    def __int__(self): return int(self.data)
+    def __long__(self): return long(self.data)
+    def __float__(self): return float(self.data)
+    def __complex__(self): return complex(self.data)
+    def __hash__(self): return hash(self.data)
+
+    def __cmp__(self, string):
+        if isinstance(string, UserString):
+            return cmp(self.data, string.data)
+        else:
+            return cmp(self.data, string)
+    def __contains__(self, char):
+        return char in self.data
+
+    def __len__(self): return len(self.data)
+    def __getitem__(self, index): return self.__class__(self.data[index])
+    def __getslice__(self, start, end):
+        start = max(start, 0); end = max(end, 0)
+        return self.__class__(self.data[start:end])
+
+    def __add__(self, other):
+        if isinstance(other, UserString):
+            return self.__class__(self.data + other.data)
+        elif isinstance(other, basestring):
+            return self.__class__(self.data + other)
+        else:
+            return self.__class__(self.data + str(other))
+    def __radd__(self, other):
+        if isinstance(other, basestring):
+            return self.__class__(other + self.data)
+        else:
+            return self.__class__(str(other) + self.data)
+    def __mul__(self, n):
+        return self.__class__(self.data*n)
+    __rmul__ = __mul__
+    def __mod__(self, args):
+        return self.__class__(self.data % args)
+
+    # the following methods are defined in alphabetical order:
+    def capitalize(self): return self.__class__(self.data.capitalize())
+    def center(self, width, *args):
+        return self.__class__(self.data.center(width, *args))
+    def count(self, sub, start=0, end=sys.maxint):
+        return self.data.count(sub, start, end)
+    def decode(self, encoding=None, errors=None): # XXX improve this?
+        if encoding:
+            if errors:
+                return self.__class__(self.data.decode(encoding, errors))
+            else:
+                return self.__class__(self.data.decode(encoding))
+        else:
+            return self.__class__(self.data.decode())
+    def encode(self, encoding=None, errors=None): # XXX improve this?
+        if encoding:
+            if errors:
+                return self.__class__(self.data.encode(encoding, errors))
+            else:
+                return self.__class__(self.data.encode(encoding))
+        else:
+            return self.__class__(self.data.encode())
+    def endswith(self, suffix, start=0, end=sys.maxint):
+        return self.data.endswith(suffix, start, end)
+    def expandtabs(self, tabsize=8):
+        return self.__class__(self.data.expandtabs(tabsize))
+    def find(self, sub, start=0, end=sys.maxint):
+        return self.data.find(sub, start, end)
+    def index(self, sub, start=0, end=sys.maxint):
+        return self.data.index(sub, start, end)
+    def isalpha(self): return self.data.isalpha()
+    def isalnum(self): return self.data.isalnum()
+    def isdecimal(self): return self.data.isdecimal()
+    def isdigit(self): return self.data.isdigit()
+    def islower(self): return self.data.islower()
+    def isnumeric(self): return self.data.isnumeric()
+    def isspace(self): return self.data.isspace()
+    def istitle(self): return self.data.istitle()
+    def isupper(self): return self.data.isupper()
+    def join(self, seq): return self.data.join(seq)
+    def ljust(self, width, *args):
+        return self.__class__(self.data.ljust(width, *args))
+    def lower(self): return self.__class__(self.data.lower())
+    def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
+    def partition(self, sep):
+        return self.data.partition(sep)
+    def replace(self, old, new, maxsplit=-1):
+        return self.__class__(self.data.replace(old, new, maxsplit))
+    def rfind(self, sub, start=0, end=sys.maxint):
+        return self.data.rfind(sub, start, end)
+    def rindex(self, sub, start=0, end=sys.maxint):
+        return self.data.rindex(sub, start, end)
+    def rjust(self, width, *args):
+        return self.__class__(self.data.rjust(width, *args))
+    def rpartition(self, sep):
+        return self.data.rpartition(sep)
+    def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars))
+    def split(self, sep=None, maxsplit=-1):
+        return self.data.split(sep, maxsplit)
+    def rsplit(self, sep=None, maxsplit=-1):
+        return self.data.rsplit(sep, maxsplit)
+    def splitlines(self, keepends=0): return self.data.splitlines(keepends)
+    def startswith(self, prefix, start=0, end=sys.maxint):
+        return self.data.startswith(prefix, start, end)
+    def strip(self, chars=None): return self.__class__(self.data.strip(chars))
+    def swapcase(self): return self.__class__(self.data.swapcase())
+    def title(self): return self.__class__(self.data.title())
+    def translate(self, *args):
+        return self.__class__(self.data.translate(*args))
+    def upper(self): return self.__class__(self.data.upper())
+    def zfill(self, width): return self.__class__(self.data.zfill(width))
+
+class MutableString(UserString, collections.MutableSequence):
+    """mutable string objects
+
+    Python strings are immutable objects.  This has the advantage, that
+    strings may be used as dictionary keys.  If this property isn't needed
+    and you insist on changing string values in place instead, you may cheat
+    and use MutableString.
+
+    But the purpose of this class is an educational one: to prevent
+    people from inventing their own mutable string class derived
+    from UserString and than forget thereby to remove (override) the
+    __hash__ method inherited from UserString.  This would lead to
+    errors that would be very hard to track down.
+
+    A faster and better solution is to rewrite your program using lists."""
+    def __init__(self, string=""):
+        from warnings import warnpy3k
+        warnpy3k('the class UserString.MutableString has been removed in '
+                    'Python 3.0', stacklevel=2)
+        self.data = string
+
+    # We inherit object.__hash__, so we must deny this explicitly
+    __hash__ = None
+
+    def __setitem__(self, index, sub):
+        if isinstance(index, slice):
+            if isinstance(sub, UserString):
+                sub = sub.data
+            elif not isinstance(sub, basestring):
+                sub = str(sub)
+            start, stop, step = index.indices(len(self.data))
+            if step == -1:
+                start, stop = stop+1, start+1
+                sub = sub[::-1]
+            elif step != 1:
+                # XXX(twouters): I guess we should be reimplementing
+                # the extended slice assignment/deletion algorithm here...
+                raise TypeError, "invalid step in slicing assignment"
+            start = min(start, stop)
+            self.data = self.data[:start] + sub + self.data[stop:]
+        else:
+            if index < 0:
+                index += len(self.data)
+            if index < 0 or index >= len(self.data): raise IndexError
+            self.data = self.data[:index] + sub + self.data[index+1:]
+    def __delitem__(self, index):
+        if isinstance(index, slice):
+            start, stop, step = index.indices(len(self.data))
+            if step == -1:
+                start, stop = stop+1, start+1
+            elif step != 1:
+                # XXX(twouters): see same block in __setitem__
+                raise TypeError, "invalid step in slicing deletion"
+            start = min(start, stop)
+            self.data = self.data[:start] + self.data[stop:]
+        else:
+            if index < 0:
+                index += len(self.data)
+            if index < 0 or index >= len(self.data): raise IndexError
+            self.data = self.data[:index] + self.data[index+1:]
+    def __setslice__(self, start, end, sub):
+        start = max(start, 0); end = max(end, 0)
+        if isinstance(sub, UserString):
+            self.data = self.data[:start]+sub.data+self.data[end:]
+        elif isinstance(sub, basestring):
+            self.data = self.data[:start]+sub+self.data[end:]
+        else:
+            self.data =  self.data[:start]+str(sub)+self.data[end:]
+    def __delslice__(self, start, end):
+        start = max(start, 0); end = max(end, 0)
+        self.data = self.data[:start] + self.data[end:]
+    def immutable(self):
+        return UserString(self.data)
+    def __iadd__(self, other):
+        if isinstance(other, UserString):
+            self.data += other.data
+        elif isinstance(other, basestring):
+            self.data += other
+        else:
+            self.data += str(other)
+        return self
+    def __imul__(self, n):
+        self.data *= n
+        return self
+    def insert(self, index, value):
+        self[index:index] = value
+
+if __name__ == "__main__":
+    # execute the regression test to stdout, if called as a script:
+    import os
+    called_in_dir, called_as = os.path.split(sys.argv[0])
+    called_as, py = os.path.splitext(called_as)
+    if '-q' in sys.argv:
+        from test import test_support
+        test_support.verbose = 0
+    __import__('test.test_' + called_as.lower())
diff --git a/src/main/resources/PythonLibs/_LWPCookieJar.py b/src/main/resources/PythonLibs/_LWPCookieJar.py
new file mode 100644
index 0000000000000000000000000000000000000000..90cc633d53164d02a3bb1fbbb059cf8c9004732a
--- /dev/null
+++ b/src/main/resources/PythonLibs/_LWPCookieJar.py
@@ -0,0 +1,170 @@
+"""Load / save to libwww-perl (LWP) format files.
+
+Actually, the format is slightly extended from that used by LWP's
+(libwww-perl's) HTTP::Cookies, to avoid losing some RFC 2965 information
+not recorded by LWP.
+
+It uses the version string "2.0", though really there isn't an LWP Cookies
+2.0 format.  This indicates that there is extra information in here
+(domain_dot and # port_spec) while still being compatible with
+libwww-perl, I hope.
+
+"""
+
+import time, re
+from cookielib import (_warn_unhandled_exception, FileCookieJar, LoadError,
+                       Cookie, MISSING_FILENAME_TEXT,
+                       join_header_words, split_header_words,
+                       iso2time, time2isoz)
+
+def lwp_cookie_str(cookie):
+    """Return string representation of Cookie in an the LWP cookie file format.
+
+    Actually, the format is extended a bit -- see module docstring.
+
+    """
+    h = [(cookie.name, cookie.value),
+         ("path", cookie.path),
+         ("domain", cookie.domain)]
+    if cookie.port is not None: h.append(("port", cookie.port))
+    if cookie.path_specified: h.append(("path_spec", None))
+    if cookie.port_specified: h.append(("port_spec", None))
+    if cookie.domain_initial_dot: h.append(("domain_dot", None))
+    if cookie.secure: h.append(("secure", None))
+    if cookie.expires: h.append(("expires",
+                               time2isoz(float(cookie.expires))))
+    if cookie.discard: h.append(("discard", None))
+    if cookie.comment: h.append(("comment", cookie.comment))
+    if cookie.comment_url: h.append(("commenturl", cookie.comment_url))
+
+    keys = cookie._rest.keys()
+    keys.sort()
+    for k in keys:
+        h.append((k, str(cookie._rest[k])))
+
+    h.append(("version", str(cookie.version)))
+
+    return join_header_words([h])
+
+class LWPCookieJar(FileCookieJar):
+    """
+    The LWPCookieJar saves a sequence of "Set-Cookie3" lines.
+    "Set-Cookie3" is the format used by the libwww-perl libary, not known
+    to be compatible with any browser, but which is easy to read and
+    doesn't lose information about RFC 2965 cookies.
+
+    Additional methods
+
+    as_lwp_str(ignore_discard=True, ignore_expired=True)
+
+    """
+
+    def as_lwp_str(self, ignore_discard=True, ignore_expires=True):
+        """Return cookies as a string of "\\n"-separated "Set-Cookie3" headers.
+
+        ignore_discard and ignore_expires: see docstring for FileCookieJar.save
+
+        """
+        now = time.time()
+        r = []
+        for cookie in self:
+            if not ignore_discard and cookie.discard:
+                continue
+            if not ignore_expires and cookie.is_expired(now):
+                continue
+            r.append("Set-Cookie3: %s" % lwp_cookie_str(cookie))
+        return "\n".join(r+[""])
+
+    def save(self, filename=None, ignore_discard=False, ignore_expires=False):
+        if filename is None:
+            if self.filename is not None: filename = self.filename
+            else: raise ValueError(MISSING_FILENAME_TEXT)
+
+        f = open(filename, "w")
+        try:
+            # There really isn't an LWP Cookies 2.0 format, but this indicates
+            # that there is extra information in here (domain_dot and
+            # port_spec) while still being compatible with libwww-perl, I hope.
+            f.write("#LWP-Cookies-2.0\n")
+            f.write(self.as_lwp_str(ignore_discard, ignore_expires))
+        finally:
+            f.close()
+
+    def _really_load(self, f, filename, ignore_discard, ignore_expires):
+        magic = f.readline()
+        if not re.search(self.magic_re, magic):
+            msg = ("%r does not look like a Set-Cookie3 (LWP) format "
+                   "file" % filename)
+            raise LoadError(msg)
+
+        now = time.time()
+
+        header = "Set-Cookie3:"
+        boolean_attrs = ("port_spec", "path_spec", "domain_dot",
+                         "secure", "discard")
+        value_attrs = ("version",
+                       "port", "path", "domain",
+                       "expires",
+                       "comment", "commenturl")
+
+        try:
+            while 1:
+                line = f.readline()
+                if line == "": break
+                if not line.startswith(header):
+                    continue
+                line = line[len(header):].strip()
+
+                for data in split_header_words([line]):
+                    name, value = data[0]
+                    standard = {}
+                    rest = {}
+                    for k in boolean_attrs:
+                        standard[k] = False
+                    for k, v in data[1:]:
+                        if k is not None:
+                            lc = k.lower()
+                        else:
+                            lc = None
+                        # don't lose case distinction for unknown fields
+                        if (lc in value_attrs) or (lc in boolean_attrs):
+                            k = lc
+                        if k in boolean_attrs:
+                            if v is None: v = True
+                            standard[k] = v
+                        elif k in value_attrs:
+                            standard[k] = v
+                        else:
+                            rest[k] = v
+
+                    h = standard.get
+                    expires = h("expires")
+                    discard = h("discard")
+                    if expires is not None:
+                        expires = iso2time(expires)
+                    if expires is None:
+                        discard = True
+                    domain = h("domain")
+                    domain_specified = domain.startswith(".")
+                    c = Cookie(h("version"), name, value,
+                               h("port"), h("port_spec"),
+                               domain, domain_specified, h("domain_dot"),
+                               h("path"), h("path_spec"),
+                               h("secure"),
+                               expires,
+                               discard,
+                               h("comment"),
+                               h("commenturl"),
+                               rest)
+                    if not ignore_discard and c.discard:
+                        continue
+                    if not ignore_expires and c.is_expired(now):
+                        continue
+                    self.set_cookie(c)
+
+        except IOError:
+            raise
+        except Exception:
+            _warn_unhandled_exception()
+            raise LoadError("invalid Set-Cookie3 format file %r: %r" %
+                            (filename, line))
diff --git a/src/main/resources/PythonLibs/_MozillaCookieJar.py b/src/main/resources/PythonLibs/_MozillaCookieJar.py
new file mode 100644
index 0000000000000000000000000000000000000000..00e8bcf981911e24d1d67c739c517148b301bdef
--- /dev/null
+++ b/src/main/resources/PythonLibs/_MozillaCookieJar.py
@@ -0,0 +1,149 @@
+"""Mozilla / Netscape cookie loading / saving."""
+
+import re, time
+
+from cookielib import (_warn_unhandled_exception, FileCookieJar, LoadError,
+                       Cookie, MISSING_FILENAME_TEXT)
+
+class MozillaCookieJar(FileCookieJar):
+    """
+
+    WARNING: you may want to backup your browser's cookies file if you use
+    this class to save cookies.  I *think* it works, but there have been
+    bugs in the past!
+
+    This class differs from CookieJar only in the format it uses to save and
+    load cookies to and from a file.  This class uses the Mozilla/Netscape
+    `cookies.txt' format.  lynx uses this file format, too.
+
+    Don't expect cookies saved while the browser is running to be noticed by
+    the browser (in fact, Mozilla on unix will overwrite your saved cookies if
+    you change them on disk while it's running; on Windows, you probably can't
+    save at all while the browser is running).
+
+    Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
+    Netscape cookies on saving.
+
+    In particular, the cookie version and port number information is lost,
+    together with information about whether or not Path, Port and Discard were
+    specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
+    domain as set in the HTTP header started with a dot (yes, I'm aware some
+    domains in Netscape files start with a dot and some don't -- trust me, you
+    really don't want to know any more about this).
+
+    Note that though Mozilla and Netscape use the same format, they use
+    slightly different headers.  The class saves cookies using the Netscape
+    header by default (Mozilla can cope with that).
+
+    """
+    magic_re = "#( Netscape)? HTTP Cookie File"
+    header = """\
+# Netscape HTTP Cookie File
+# http://www.netscape.com/newsref/std/cookie_spec.html
+# This is a generated file!  Do not edit.
+
+"""
+
+    def _really_load(self, f, filename, ignore_discard, ignore_expires):
+        now = time.time()
+
+        magic = f.readline()
+        if not re.search(self.magic_re, magic):
+            f.close()
+            raise LoadError(
+                "%r does not look like a Netscape format cookies file" %
+                filename)
+
+        try:
+            while 1:
+                line = f.readline()
+                if line == "": break
+
+                # last field may be absent, so keep any trailing tab
+                if line.endswith("\n"): line = line[:-1]
+
+                # skip comments and blank lines XXX what is $ for?
+                if (line.strip().startswith(("#", "$")) or
+                    line.strip() == ""):
+                    continue
+
+                domain, domain_specified, path, secure, expires, name, value = \
+                        line.split("\t")
+                secure = (secure == "TRUE")
+                domain_specified = (domain_specified == "TRUE")
+                if name == "":
+                    # cookies.txt regards 'Set-Cookie: foo' as a cookie
+                    # with no name, whereas cookielib regards it as a
+                    # cookie with no value.
+                    name = value
+                    value = None
+
+                initial_dot = domain.startswith(".")
+                assert domain_specified == initial_dot
+
+                discard = False
+                if expires == "":
+                    expires = None
+                    discard = True
+
+                # assume path_specified is false
+                c = Cookie(0, name, value,
+                           None, False,
+                           domain, domain_specified, initial_dot,
+                           path, False,
+                           secure,
+                           expires,
+                           discard,
+                           None,
+                           None,
+                           {})
+                if not ignore_discard and c.discard:
+                    continue
+                if not ignore_expires and c.is_expired(now):
+                    continue
+                self.set_cookie(c)
+
+        except IOError:
+            raise
+        except Exception:
+            _warn_unhandled_exception()
+            raise LoadError("invalid Netscape format cookies file %r: %r" %
+                            (filename, line))
+
+    def save(self, filename=None, ignore_discard=False, ignore_expires=False):
+        if filename is None:
+            if self.filename is not None: filename = self.filename
+            else: raise ValueError(MISSING_FILENAME_TEXT)
+
+        f = open(filename, "w")
+        try:
+            f.write(self.header)
+            now = time.time()
+            for cookie in self:
+                if not ignore_discard and cookie.discard:
+                    continue
+                if not ignore_expires and cookie.is_expired(now):
+                    continue
+                if cookie.secure: secure = "TRUE"
+                else: secure = "FALSE"
+                if cookie.domain.startswith("."): initial_dot = "TRUE"
+                else: initial_dot = "FALSE"
+                if cookie.expires is not None:
+                    expires = str(cookie.expires)
+                else:
+                    expires = ""
+                if cookie.value is None:
+                    # cookies.txt regards 'Set-Cookie: foo' as a cookie
+                    # with no name, whereas cookielib regards it as a
+                    # cookie with no value.
+                    name = ""
+                    value = cookie.name
+                else:
+                    name = cookie.name
+                    value = cookie.value
+                f.write(
+                    "\t".join([cookie.domain, initial_dot, cookie.path,
+                               secure, expires, name, value])+
+                    "\n")
+        finally:
+            f.close()
diff --git a/src/main/resources/PythonLibs/__future__.py b/src/main/resources/PythonLibs/__future__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0996eb007bf2673dd253b71a336127777353183
--- /dev/null
+++ b/src/main/resources/PythonLibs/__future__.py
@@ -0,0 +1,128 @@
+"""Record of phased-in incompatible language changes.
+
+Each line is of the form:
+
+    FeatureName = "_Feature(" OptionalRelease "," MandatoryRelease ","
+                              CompilerFlag ")"
+
+where, normally, OptionalRelease < MandatoryRelease, and both are 5-tuples
+of the same form as sys.version_info:
+
+    (PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int
+     PY_MINOR_VERSION, # the 1; an int
+     PY_MICRO_VERSION, # the 0; an int
+     PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string
+     PY_RELEASE_SERIAL # the 3; an int
+    )
+
+OptionalRelease records the first release in which
+
+    from __future__ import FeatureName
+
+was accepted.
+
+In the case of MandatoryReleases that have not yet occurred,
+MandatoryRelease predicts the release in which the feature will become part
+of the language.
+
+Else MandatoryRelease records when the feature became part of the language;
+in releases at or after that, modules no longer need
+
+    from __future__ import FeatureName
+
+to use the feature in question, but may continue to use such imports.
+
+MandatoryRelease may also be None, meaning that a planned feature got
+dropped.
+
+Instances of class _Feature have two corresponding methods,
+.getOptionalRelease() and .getMandatoryRelease().
+
+CompilerFlag is the (bitfield) flag that should be passed in the fourth
+argument to the builtin function compile() to enable the feature in
+dynamically compiled code.  This flag is stored in the .compiler_flag
+attribute on _Future instances.  These values must match the appropriate
+#defines of CO_xxx flags in Include/compile.h.
+
+No feature line is ever to be deleted from this file.
+"""
+
+all_feature_names = [
+    "nested_scopes",
+    "generators",
+    "division",
+    "absolute_import",
+    "with_statement",
+    "print_function",
+    "unicode_literals",
+]
+
+__all__ = ["all_feature_names"] + all_feature_names
+
+# The CO_xxx symbols are defined here under the same names used by
+# compile.h, so that an editor search will find them here.  However,
+# they're not exported in __all__, because they don't really belong to
+# this module.
+CO_NESTED            = 0x0010   # nested_scopes
+CO_GENERATOR_ALLOWED = 0        # generators (obsolete, was 0x1000)
+CO_FUTURE_DIVISION   = 0x2000   # division
+CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 # perform absolute imports by default
+CO_FUTURE_WITH_STATEMENT  = 0x8000   # with statement
+CO_FUTURE_PRINT_FUNCTION  = 0x10000   # print function
+CO_FUTURE_UNICODE_LITERALS = 0x20000 # unicode string literals
+
+class _Feature:
+    def __init__(self, optionalRelease, mandatoryRelease, compiler_flag):
+        self.optional = optionalRelease
+        self.mandatory = mandatoryRelease
+        self.compiler_flag = compiler_flag
+
+    def getOptionalRelease(self):
+        """Return first release in which this feature was recognized.
+
+        This is a 5-tuple, of the same form as sys.version_info.
+        """
+
+        return self.optional
+
+    def getMandatoryRelease(self):
+        """Return release in which this feature will become mandatory.
+
+        This is a 5-tuple, of the same form as sys.version_info, or, if
+        the feature was dropped, is None.
+        """
+
+        return self.mandatory
+
+    def __repr__(self):
+        return "_Feature" + repr((self.optional,
+                                  self.mandatory,
+                                  self.compiler_flag))
+
+nested_scopes = _Feature((2, 1, 0, "beta",  1),
+                         (2, 2, 0, "alpha", 0),
+                         CO_NESTED)
+
+generators = _Feature((2, 2, 0, "alpha", 1),
+                      (2, 3, 0, "final", 0),
+                      CO_GENERATOR_ALLOWED)
+
+division = _Feature((2, 2, 0, "alpha", 2),
+                    (3, 0, 0, "alpha", 0),
+                    CO_FUTURE_DIVISION)
+
+absolute_import = _Feature((2, 5, 0, "alpha", 1),
+                           (3, 0, 0, "alpha", 0),
+                           CO_FUTURE_ABSOLUTE_IMPORT)
+
+with_statement = _Feature((2, 5, 0, "alpha", 1),
+                          (2, 6, 0, "alpha", 0),
+                          CO_FUTURE_WITH_STATEMENT)
+
+print_function = _Feature((2, 6, 0, "alpha", 2),
+                          (3, 0, 0, "alpha", 0),
+                          CO_FUTURE_PRINT_FUNCTION)
+
+unicode_literals = _Feature((2, 6, 0, "alpha", 2),
+                            (3, 0, 0, "alpha", 0),
+                            CO_FUTURE_UNICODE_LITERALS)
diff --git a/src/main/resources/PythonLibs/_abcoll.py b/src/main/resources/PythonLibs/_abcoll.py
new file mode 100644
index 0000000000000000000000000000000000000000..c59ccaaa0bd4b60277f1aca00bde3472724a89d4
--- /dev/null
+++ b/src/main/resources/PythonLibs/_abcoll.py
@@ -0,0 +1,602 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Abstract Base Classes (ABCs) for collections, according to PEP 3119.
+
+DON'T USE THIS MODULE DIRECTLY!  The classes here should be imported
+via collections; they are defined here only to alleviate certain
+bootstrapping issues.  Unit tests are in test_collections.
+"""
+
+from abc import ABCMeta, abstractmethod
+import sys
+
+__all__ = ["Hashable", "Iterable", "Iterator",
+           "Sized", "Container", "Callable",
+           "Set", "MutableSet",
+           "Mapping", "MutableMapping",
+           "MappingView", "KeysView", "ItemsView", "ValuesView",
+           "Sequence", "MutableSequence",
+           ]
+
+### ONE-TRICK PONIES ###
+
+def _hasattr(C, attr):
+    try:
+        return any(attr in B.__dict__ for B in C.__mro__)
+    except AttributeError:
+        # Old-style class
+        return hasattr(C, attr)
+
+
+class Hashable:
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def __hash__(self):
+        return 0
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Hashable:
+            try:
+                for B in C.__mro__:
+                    if "__hash__" in B.__dict__:
+                        if B.__dict__["__hash__"]:
+                            return True
+                        break
+            except AttributeError:
+                # Old-style class
+                if getattr(C, "__hash__", None):
+                    return True
+        return NotImplemented
+
+
+class Iterable:
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def __iter__(self):
+        while False:
+            yield None
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Iterable:
+            if _hasattr(C, "__iter__"):
+                return True
+        return NotImplemented
+
+Iterable.register(str)
+
+
+class Iterator(Iterable):
+
+    @abstractmethod
+    def next(self):
+        raise StopIteration
+
+    def __iter__(self):
+        return self
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Iterator:
+            if _hasattr(C, "next"):
+                return True
+        return NotImplemented
+
+
+class Sized:
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def __len__(self):
+        return 0
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Sized:
+            if _hasattr(C, "__len__"):
+                return True
+        return NotImplemented
+
+
+class Container:
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def __contains__(self, x):
+        return False
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Container:
+            if _hasattr(C, "__contains__"):
+                return True
+        return NotImplemented
+
+
+class Callable:
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def __call__(self, *args, **kwds):
+        return False
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Callable:
+            if _hasattr(C, "__call__"):
+                return True
+        return NotImplemented
+
+
+### SETS ###
+
+
+class Set(Sized, Iterable, Container):
+    """A set is a finite, iterable container.
+
+    This class provides concrete generic implementations of all
+    methods except for __contains__, __iter__ and __len__.
+
+    To override the comparisons (presumably for speed, as the
+    semantics are fixed), all you have to do is redefine __le__ and
+    then the other operations will automatically follow suit.
+    """
+
+    def __le__(self, other):
+        if not isinstance(other, Set):
+            return NotImplemented
+        if len(self) > len(other):
+            return False
+        for elem in self:
+            if elem not in other:
+                return False
+        return True
+
+    def __lt__(self, other):
+        if not isinstance(other, Set):
+            return NotImplemented
+        return len(self) < len(other) and self.__le__(other)
+
+    def __gt__(self, other):
+        if not isinstance(other, Set):
+            return NotImplemented
+        return other < self
+
+    def __ge__(self, other):
+        if not isinstance(other, Set):
+            return NotImplemented
+        return other <= self
+
+    def __eq__(self, other):
+        if not isinstance(other, Set):
+            return NotImplemented
+        return len(self) == len(other) and self.__le__(other)
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    @classmethod
+    def _from_iterable(cls, it):
+        '''Construct an instance of the class from any iterable input.
+
+        Must override this method if the class constructor signature
+        does not accept an iterable for an input.
+        '''
+        return cls(it)
+
+    def __and__(self, other):
+        if not isinstance(other, Iterable):
+            return NotImplemented
+        return self._from_iterable(value for value in other if value in self)
+
+    def isdisjoint(self, other):
+        for value in other:
+            if value in self:
+                return False
+        return True
+
+    def __or__(self, other):
+        if not isinstance(other, Iterable):
+            return NotImplemented
+        chain = (e for s in (self, other) for e in s)
+        return self._from_iterable(chain)
+
+    def __sub__(self, other):
+        if not isinstance(other, Set):
+            if not isinstance(other, Iterable):
+                return NotImplemented
+            other = self._from_iterable(other)
+        return self._from_iterable(value for value in self
+                                   if value not in other)
+
+    def __xor__(self, other):
+        if not isinstance(other, Set):
+            if not isinstance(other, Iterable):
+                return NotImplemented
+            other = self._from_iterable(other)
+        return (self - other) | (other - self)
+
+    # Sets are not hashable by default, but subclasses can change this
+    __hash__ = None
+
+    def _hash(self):
+        """Compute the hash value of a set.
+
+        Note that we don't define __hash__: not all sets are hashable.
+        But if you define a hashable set type, its __hash__ should
+        call this function.
+
+        This must be compatible __eq__.
+
+        All sets ought to compare equal if they contain the same
+        elements, regardless of how they are implemented, and
+        regardless of the order of the elements; so there's not much
+        freedom for __eq__ or __hash__.  We match the algorithm used
+        by the built-in frozenset type.
+        """
+        MAX = sys.maxint
+        MASK = 2 * MAX + 1
+        n = len(self)
+        h = 1927868237 * (n + 1)
+        h &= MASK
+        for x in self:
+            hx = hash(x)
+            h ^= (hx ^ (hx << 16) ^ 89869747)  * 3644798167
+            h &= MASK
+        h = h * 69069 + 907133923
+        h &= MASK
+        if h > MAX:
+            h -= MASK + 1
+        if h == -1:
+            h = 590923713
+        return h
+
+Set.register(frozenset)
+
+
+class MutableSet(Set):
+
+    @abstractmethod
+    def add(self, value):
+        """Add an element."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def discard(self, value):
+        """Remove an element.  Do not raise an exception if absent."""
+        raise NotImplementedError
+
+    def remove(self, value):
+        """Remove an element. If not a member, raise a KeyError."""
+        if value not in self:
+            raise KeyError(value)
+        self.discard(value)
+
+    def pop(self):
+        """Return the popped value.  Raise KeyError if empty."""
+        it = iter(self)
+        try:
+            value = next(it)
+        except StopIteration:
+            raise KeyError
+        self.discard(value)
+        return value
+
+    def clear(self):
+        """This is slow (creates N new iterators!) but effective."""
+        try:
+            while True:
+                self.pop()
+        except KeyError:
+            pass
+
+    def __ior__(self, it):
+        for value in it:
+            self.add(value)
+        return self
+
+    def __iand__(self, it):
+        for value in (self - it):
+            self.discard(value)
+        return self
+
+    def __ixor__(self, it):
+        if it is self:
+            self.clear()
+        else:
+            if not isinstance(it, Set):
+                it = self._from_iterable(it)
+            for value in it:
+                if value in self:
+                    self.discard(value)
+                else:
+                    self.add(value)
+        return self
+
+    def __isub__(self, it):
+        if it is self:
+            self.clear()
+        else:
+            for value in it:
+                self.discard(value)
+        return self
+
+MutableSet.register(set)
+
+
+### MAPPINGS ###
+
+
+class Mapping(Sized, Iterable, Container):
+
+    @abstractmethod
+    def __getitem__(self, key):
+        raise KeyError
+
+    def get(self, key, default=None):
+        try:
+            return self[key]
+        except KeyError:
+            return default
+
+    def __contains__(self, key):
+        try:
+            self[key]
+        except KeyError:
+            return False
+        else:
+            return True
+
+    def iterkeys(self):
+        return iter(self)
+
+    def itervalues(self):
+        for key in self:
+            yield self[key]
+
+    def iteritems(self):
+        for key in self:
+            yield (key, self[key])
+
+    def keys(self):
+        return list(self)
+
+    def items(self):
+        return [(key, self[key]) for key in self]
+
+    def values(self):
+        return [self[key] for key in self]
+
+    # Mappings are not hashable by default, but subclasses can change this
+    __hash__ = None
+
+    def __eq__(self, other):
+        if not isinstance(other, Mapping):
+            return NotImplemented
+        return dict(self.items()) == dict(other.items())
+
+    def __ne__(self, other):
+        return not (self == other)
+
+class MappingView(Sized):
+
+    def __init__(self, mapping):
+        self._mapping = mapping
+
+    def __len__(self):
+        return len(self._mapping)
+
+    def __repr__(self):
+        return '{0.__class__.__name__}({0._mapping!r})'.format(self)
+
+
+class KeysView(MappingView, Set):
+
+    @classmethod
+    def _from_iterable(self, it):
+        return set(it)
+
+    def __contains__(self, key):
+        return key in self._mapping
+
+    def __iter__(self):
+        for key in self._mapping:
+            yield key
+
+
+class ItemsView(MappingView, Set):
+
+    @classmethod
+    def _from_iterable(self, it):
+        return set(it)
+
+    def __contains__(self, item):
+        key, value = item
+        try:
+            v = self._mapping[key]
+        except KeyError:
+            return False
+        else:
+            return v == value
+
+    def __iter__(self):
+        for key in self._mapping:
+            yield (key, self._mapping[key])
+
+
+class ValuesView(MappingView):
+
+    def __contains__(self, value):
+        for key in self._mapping:
+            if value == self._mapping[key]:
+                return True
+        return False
+
+    def __iter__(self):
+        for key in self._mapping:
+            yield self._mapping[key]
+
+
+class MutableMapping(Mapping):
+
+    @abstractmethod
+    def __setitem__(self, key, value):
+        raise KeyError
+
+    @abstractmethod
+    def __delitem__(self, key):
+        raise KeyError
+
+    __marker = object()
+
+    def pop(self, key, default=__marker):
+        try:
+            value = self[key]
+        except KeyError:
+            if default is self.__marker:
+                raise
+            return default
+        else:
+            del self[key]
+            return value
+
+    def popitem(self):
+        try:
+            key = next(iter(self))
+        except StopIteration:
+            raise KeyError
+        value = self[key]
+        del self[key]
+        return key, value
+
+    def clear(self):
+        try:
+            while True:
+                self.popitem()
+        except KeyError:
+            pass
+
+    def update(*args, **kwds):
+        if len(args) > 2:
+            raise TypeError("update() takes at most 2 positional "
+                            "arguments ({} given)".format(len(args)))
+        elif not args:
+            raise TypeError("update() takes at least 1 argument (0 given)")
+        self = args[0]
+        other = args[1] if len(args) >= 2 else ()
+
+        if isinstance(other, Mapping):
+            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
+
+    def setdefault(self, key, default=None):
+        try:
+            return self[key]
+        except KeyError:
+            self[key] = default
+        return default
+
+MutableMapping.register(dict)
+
+
+### SEQUENCES ###
+
+
+class Sequence(Sized, Iterable, Container):
+    """All the operations on a read-only sequence.
+
+    Concrete subclasses must override __new__ or __init__,
+    __getitem__, and __len__.
+    """
+
+    @abstractmethod
+    def __getitem__(self, index):
+        raise IndexError
+
+    def __iter__(self):
+        i = 0
+        try:
+            while True:
+                v = self[i]
+                yield v
+                i += 1
+        except IndexError:
+            return
+
+    def __contains__(self, value):
+        for v in self:
+            if v == value:
+                return True
+        return False
+
+    def __reversed__(self):
+        for i in reversed(range(len(self))):
+            yield self[i]
+
+    def index(self, value):
+        for i, v in enumerate(self):
+            if v == value:
+                return i
+        raise ValueError
+
+    def count(self, value):
+        return sum(1 for v in self if v == value)
+
+Sequence.register(tuple)
+Sequence.register(basestring)
+if sys.platform[:4] != "java":
+    Sequence.register(buffer)
+Sequence.register(xrange)
+
+
+class MutableSequence(Sequence):
+
+    @abstractmethod
+    def __setitem__(self, index, value):
+        raise IndexError
+
+    @abstractmethod
+    def __delitem__(self, index):
+        raise IndexError
+
+    @abstractmethod
+    def insert(self, index, value):
+        raise IndexError
+
+    def append(self, value):
+        self.insert(len(self), value)
+
+    def reverse(self):
+        n = len(self)
+        for i in range(n//2):
+            self[i], self[n-i-1] = self[n-i-1], self[i]
+
+    def extend(self, values):
+        for v in values:
+            self.append(v)
+
+    def pop(self, index=-1):
+        v = self[index]
+        del self[index]
+        return v
+
+    def remove(self, value):
+        del self[self.index(value)]
+
+    def __iadd__(self, values):
+        self.extend(values)
+        return self
+
+MutableSequence.register(list)
diff --git a/src/main/resources/PythonLibs/_fsum.py b/src/main/resources/PythonLibs/_fsum.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d58363e15e236d6c1724bcd718de06576d09fd2
--- /dev/null
+++ b/src/main/resources/PythonLibs/_fsum.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+from sys import float_info
+import math
+
+
+mant_dig = float_info.mant_dig
+etiny = float_info.min_exp - mant_dig
+
+def fsum(iterable):
+    """Full precision summation.  Compute sum(iterable) without any
+    intermediate accumulation of error.  Based on the 'lsum' function
+    at http://code.activestate.com/recipes/393090/
+
+    """
+    tmant, texp = 0, 0
+    for x in iterable:
+        mant, exp = math.frexp(x)
+        mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
+        if texp > exp:
+            tmant <<= texp-exp
+            texp = exp
+        else:
+            mant <<= exp-texp
+        tmant += mant
+
+    # Round tmant * 2**texp to a float.  The original recipe
+    # used float(str(tmant)) * 2.0**texp for this, but that's
+    # a little unsafe because str -> float conversion can't be
+    # relied upon to do correct rounding on all platforms.
+    tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
+    if tail > 0:
+        h = 1 << (tail-1)
+        tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
+        texp += tail
+    return math.ldexp(tmant, texp)
diff --git a/src/main/resources/PythonLibs/_google_ipaddr_r234.py b/src/main/resources/PythonLibs/_google_ipaddr_r234.py
new file mode 100644
index 0000000000000000000000000000000000000000..a89298a315ddcfa3aa6cc89027e9c93d5afb909d
--- /dev/null
+++ b/src/main/resources/PythonLibs/_google_ipaddr_r234.py
@@ -0,0 +1,1907 @@
+#!/usr/bin/python
+#
+# Copyright 2007 Google Inc.
+#  Licensed to PSF under a Contributor Agreement.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+
+"""A fast, lightweight IPv4/IPv6 manipulation library in Python.
+
+This library is used to create/poke/manipulate IPv4 and IPv6 addresses
+and networks.
+
+"""
+
+__version__ = 'trunk'
+
+import struct
+
+IPV4LENGTH = 32
+IPV6LENGTH = 128
+
+
+class AddressValueError(ValueError):
+    """A Value Error related to the address."""
+
+
+class NetmaskValueError(ValueError):
+    """A Value Error related to the netmask."""
+
+
+def IPAddress(address, version=None):
+    """Take an IP string/int and return an object of the correct type.
+
+    Args:
+        address: A string or integer, the IP address.  Either IPv4 or
+          IPv6 addresses may be supplied; integers less than 2**32 will
+          be considered to be IPv4 by default.
+        version: An Integer, 4 or 6. If set, don't try to automatically
+          determine what the IP address type is. important for things
+          like IPAddress(1), which could be IPv4, '0.0.0.1',  or IPv6,
+          '::1'.
+
+    Returns:
+        An IPv4Address or IPv6Address object.
+
+    Raises:
+        ValueError: if the string passed isn't either a v4 or a v6
+          address.
+
+    """
+    if version:
+        if version == 4:
+            return IPv4Address(address)
+        elif version == 6:
+            return IPv6Address(address)
+
+    try:
+        return IPv4Address(address)
+    except (AddressValueError, NetmaskValueError):
+        pass
+
+    try:
+        return IPv6Address(address)
+    except (AddressValueError, NetmaskValueError):
+        pass
+
+    raise ValueError('%r does not appear to be an IPv4 or IPv6 address' %
+                     address)
+
+
+def IPNetwork(address, version=None, strict=False):
+    """Take an IP string/int and return an object of the correct type.
+
+    Args:
+        address: A string or integer, the IP address.  Either IPv4 or
+          IPv6 addresses may be supplied; integers less than 2**32 will
+          be considered to be IPv4 by default.
+        version: An Integer, if set, don't try to automatically
+          determine what the IP address type is. important for things
+          like IPNetwork(1), which could be IPv4, '0.0.0.1/32', or IPv6,
+          '::1/128'.
+
+    Returns:
+        An IPv4Network or IPv6Network object.
+
+    Raises:
+        ValueError: if the string passed isn't either a v4 or a v6
+          address. Or if a strict network was requested and a strict
+          network wasn't given.
+
+    """
+    if version:
+        if version == 4:
+            return IPv4Network(address, strict)
+        elif version == 6:
+            return IPv6Network(address, strict)
+
+    try:
+        return IPv4Network(address, strict)
+    except (AddressValueError, NetmaskValueError):
+        pass
+
+    try:
+        return IPv6Network(address, strict)
+    except (AddressValueError, NetmaskValueError):
+        pass
+
+    raise ValueError('%r does not appear to be an IPv4 or IPv6 network' %
+                     address)
+
+
+def v4_int_to_packed(address):
+    """The binary representation of this address.
+
+    Args:
+        address: An integer representation of an IPv4 IP address.
+
+    Returns:
+        The binary representation of this address.
+
+    Raises:
+        ValueError: If the integer is too large to be an IPv4 IP
+          address.
+    """
+    if address > _BaseV4._ALL_ONES:
+        raise ValueError('Address too large for IPv4')
+    return struct.pack('!I', address)
+
+
+def v6_int_to_packed(address):
+    """The binary representation of this address.
+
+    Args:
+        address: An integer representation of an IPv4 IP address.
+
+    Returns:
+        The binary representation of this address.
+    """
+    return struct.pack('!QQ', address >> 64, address & (2**64 - 1))
+
+
+def _find_address_range(addresses):
+    """Find a sequence of addresses.
+
+    Args:
+        addresses: a list of IPv4 or IPv6 addresses.
+
+    Returns:
+        A tuple containing the first and last IP addresses in the sequence.
+
+    """
+    first = last = addresses[0]
+    for ip in addresses[1:]:
+        if ip._ip == last._ip + 1:
+            last = ip
+        else:
+            break
+    return (first, last)
+
+def _get_prefix_length(number1, number2, bits):
+    """Get the number of leading bits that are same for two numbers.
+
+    Args:
+        number1: an integer.
+        number2: another integer.
+        bits: the maximum number of bits to compare.
+
+    Returns:
+        The number of leading bits that are the same for two numbers.
+
+    """
+    for i in range(bits):
+        if number1 >> i == number2 >> i:
+            return bits - i
+    return 0
+
+def _count_righthand_zero_bits(number, bits):
+    """Count the number of zero bits on the right hand side.
+
+    Args:
+        number: an integer.
+        bits: maximum number of bits to count.
+
+    Returns:
+        The number of zero bits on the right hand side of the number.
+
+    """
+    if number == 0:
+        return bits
+    for i in range(bits):
+        if (number >> i) % 2:
+            return i
+
+def summarize_address_range(first, last):
+    """Summarize a network range given the first and last IP addresses.
+
+    Example:
+        >>> summarize_address_range(IPv4Address('1.1.1.0'),
+            IPv4Address('1.1.1.130'))
+        [IPv4Network('1.1.1.0/25'), IPv4Network('1.1.1.128/31'),
+        IPv4Network('1.1.1.130/32')]
+
+    Args:
+        first: the first IPv4Address or IPv6Address in the range.
+        last: the last IPv4Address or IPv6Address in the range.
+
+    Returns:
+        The address range collapsed to a list of IPv4Network's or
+        IPv6Network's.
+
+    Raise:
+        TypeError:
+            If the first and last objects are not IP addresses.
+            If the first and last objects are not the same version.
+        ValueError:
+            If the last object is not greater than the first.
+            If the version is not 4 or 6.
+
+    """
+    if not (isinstance(first, _BaseIP) and isinstance(last, _BaseIP)):
+        raise TypeError('first and last must be IP addresses, not networks')
+    if first.version != last.version:
+        raise TypeError("%s and %s are not of the same version" % (
+                str(first), str(last)))
+    if first > last:
+        raise ValueError('last IP address must be greater than first')
+
+    networks = []
+
+    if first.version == 4:
+        ip = IPv4Network
+    elif first.version == 6:
+        ip = IPv6Network
+    else:
+        raise ValueError('unknown IP version')
+
+    ip_bits = first._max_prefixlen
+    first_int = first._ip
+    last_int = last._ip
+    while first_int <= last_int:
+        nbits = _count_righthand_zero_bits(first_int, ip_bits)
+        current = None
+        while nbits >= 0:
+            addend = 2**nbits - 1
+            current = first_int + addend
+            nbits -= 1
+            if current <= last_int:
+                break
+        prefix = _get_prefix_length(first_int, current, ip_bits)
+        net = ip('%s/%d' % (str(first), prefix))
+        networks.append(net)
+        if current == ip._ALL_ONES:
+            break
+        first_int = current + 1
+        first = IPAddress(first_int, version=first._version)
+    return networks
+
+def _collapse_address_list_recursive(addresses):
+    """Loops through the addresses, collapsing concurrent netblocks.
+
+    Example:
+
+        ip1 = IPv4Network('1.1.0.0/24')
+        ip2 = IPv4Network('1.1.1.0/24')
+        ip3 = IPv4Network('1.1.2.0/24')
+        ip4 = IPv4Network('1.1.3.0/24')
+        ip5 = IPv4Network('1.1.4.0/24')
+        ip6 = IPv4Network('1.1.0.1/22')
+
+        _collapse_address_list_recursive([ip1, ip2, ip3, ip4, ip5, ip6]) ->
+          [IPv4Network('1.1.0.0/22'), IPv4Network('1.1.4.0/24')]
+
+        This shouldn't be called directly; it is called via
+          collapse_address_list([]).
+
+    Args:
+        addresses: A list of IPv4Network's or IPv6Network's
+
+    Returns:
+        A list of IPv4Network's or IPv6Network's depending on what we were
+        passed.
+
+    """
+    ret_array = []
+    optimized = False
+
+    for cur_addr in addresses:
+        if not ret_array:
+            ret_array.append(cur_addr)
+            continue
+        if cur_addr in ret_array[-1]:
+            optimized = True
+        elif cur_addr == ret_array[-1].supernet().subnet()[1]:
+            ret_array.append(ret_array.pop().supernet())
+            optimized = True
+        else:
+            ret_array.append(cur_addr)
+
+    if optimized:
+        return _collapse_address_list_recursive(ret_array)
+
+    return ret_array
+
+
+def collapse_address_list(addresses):
+    """Collapse a list of IP objects.
+
+    Example:
+        collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) ->
+          [IPv4('1.1.0.0/23')]
+
+    Args:
+        addresses: A list of IPv4Network or IPv6Network objects.
+
+    Returns:
+        A list of IPv4Network or IPv6Network objects depending on what we
+        were passed.
+
+    Raises:
+        TypeError: If passed a list of mixed version objects.
+
+    """
+    i = 0
+    addrs = []
+    ips = []
+    nets = []
+
+    # split IP addresses and networks
+    for ip in addresses:
+        if isinstance(ip, _BaseIP):
+            if ips and ips[-1]._version != ip._version:
+                raise TypeError("%s and %s are not of the same version" % (
+                        str(ip), str(ips[-1])))
+            ips.append(ip)
+        elif ip._prefixlen == ip._max_prefixlen:
+            if ips and ips[-1]._version != ip._version:
+                raise TypeError("%s and %s are not of the same version" % (
+                        str(ip), str(ips[-1])))
+            ips.append(ip.ip)
+        else:
+            if nets and nets[-1]._version != ip._version:
+                raise TypeError("%s and %s are not of the same version" % (
+                        str(ip), str(ips[-1])))
+            nets.append(ip)
+
+    # sort and dedup
+    ips = sorted(set(ips))
+    nets = sorted(set(nets))
+
+    while i < len(ips):
+        (first, last) = _find_address_range(ips[i:])
+        i = ips.index(last) + 1
+        addrs.extend(summarize_address_range(first, last))
+
+    return _collapse_address_list_recursive(sorted(
+        addrs + nets, key=_BaseNet._get_networks_key))
+
+# backwards compatibility
+CollapseAddrList = collapse_address_list
+
+# Test whether this Python implementation supports byte objects that
+# are not identical to str ones.
+# We need to exclude platforms where bytes == str so that we can
+# distinguish between packed representations and strings, for example
+# b'12::' (the IPv4 address 49.50.58.58) and '12::' (an IPv6 address).
+try:
+    _compat_has_real_bytes = bytes is not str
+except NameError: # <Python2.6
+    _compat_has_real_bytes = False
+
+def get_mixed_type_key(obj):
+    """Return a key suitable for sorting between networks and addresses.
+
+    Address and Network objects are not sortable by default; they're
+    fundamentally different so the expression
+
+        IPv4Address('1.1.1.1') <= IPv4Network('1.1.1.1/24')
+
+    doesn't make any sense.  There are some times however, where you may wish
+    to have ipaddr sort these for you anyway. If you need to do this, you
+    can use this function as the key= argument to sorted().
+
+    Args:
+      obj: either a Network or Address object.
+    Returns:
+      appropriate key.
+
+    """
+    if isinstance(obj, _BaseNet):
+        return obj._get_networks_key()
+    elif isinstance(obj, _BaseIP):
+        return obj._get_address_key()
+    return NotImplemented
+
+class _IPAddrBase(object):
+
+    """The mother class."""
+
+    def __index__(self):
+        return self._ip
+
+    def __int__(self):
+        return self._ip
+
+    def __hex__(self):
+        return hex(self._ip)
+
+    @property
+    def exploded(self):
+        """Return the longhand version of the IP address as a string."""
+        return self._explode_shorthand_ip_string()
+
+    @property
+    def compressed(self):
+        """Return the shorthand version of the IP address as a string."""
+        return str(self)
+
+
+class _BaseIP(_IPAddrBase):
+
+    """A generic IP object.
+
+    This IP class contains the version independent methods which are
+    used by single IP addresses.
+
+    """
+
+    def __init__(self, address):
+        if (not (_compat_has_real_bytes and isinstance(address, bytes))
+            and '/' in str(address)):
+            raise AddressValueError(address)
+
+    def __eq__(self, other):
+        try:
+            return (self._ip == other._ip
+                    and self._version == other._version)
+        except AttributeError:
+            return NotImplemented
+
+    def __ne__(self, other):
+        eq = self.__eq__(other)
+        if eq is NotImplemented:
+            return NotImplemented
+        return not eq
+
+    def __le__(self, other):
+        gt = self.__gt__(other)
+        if gt is NotImplemented:
+            return NotImplemented
+        return not gt
+
+    def __ge__(self, other):
+        lt = self.__lt__(other)
+        if lt is NotImplemented:
+            return NotImplemented
+        return not lt
+
+    def __lt__(self, other):
+        if self._version != other._version:
+            raise TypeError('%s and %s are not of the same version' % (
+                    str(self), str(other)))
+        if not isinstance(other, _BaseIP):
+            raise TypeError('%s and %s are not of the same type' % (
+                    str(self), str(other)))
+        if self._ip != other._ip:
+            return self._ip < other._ip
+        return False
+
+    def __gt__(self, other):
+        if self._version != other._version:
+            raise TypeError('%s and %s are not of the same version' % (
+                    str(self), str(other)))
+        if not isinstance(other, _BaseIP):
+            raise TypeError('%s and %s are not of the same type' % (
+                    str(self), str(other)))
+        if self._ip != other._ip:
+            return self._ip > other._ip
+        return False
+
+    # Shorthand for Integer addition and subtraction. This is not
+    # meant to ever support addition/subtraction of addresses.
+    def __add__(self, other):
+        if not isinstance(other, int):
+            return NotImplemented
+        return IPAddress(int(self) + other, version=self._version)
+
+    def __sub__(self, other):
+        if not isinstance(other, int):
+            return NotImplemented
+        return IPAddress(int(self) - other, version=self._version)
+
+    def __repr__(self):
+        return '%s(%r)' % (self.__class__.__name__, str(self))
+
+    def __str__(self):
+        return  '%s' % self._string_from_ip_int(self._ip)
+
+    def __hash__(self):
+        return hash(hex(long(self._ip)))
+
+    def _get_address_key(self):
+        return (self._version, self)
+
+    @property
+    def version(self):
+        raise NotImplementedError('BaseIP has no version')
+
+
+class _BaseNet(_IPAddrBase):
+
+    """A generic IP object.
+
+    This IP class contains the version independent methods which are
+    used by networks.
+
+    """
+
+    def __init__(self, address):
+        self._cache = {}
+
+    def __repr__(self):
+        return '%s(%r)' % (self.__class__.__name__, str(self))
+
+    def iterhosts(self):
+        """Generate Iterator over usable hosts in a network.
+
+           This is like __iter__ except it doesn't return the network
+           or broadcast addresses.
+
+        """
+        cur = int(self.network) + 1
+        bcast = int(self.broadcast) - 1
+        while cur <= bcast:
+            cur += 1
+            yield IPAddress(cur - 1, version=self._version)
+
+    def __iter__(self):
+        cur = int(self.network)
+        bcast = int(self.broadcast)
+        while cur <= bcast:
+            cur += 1
+            yield IPAddress(cur - 1, version=self._version)
+
+    def __getitem__(self, n):
+        network = int(self.network)
+        broadcast = int(self.broadcast)
+        if n >= 0:
+            if network + n > broadcast:
+                raise IndexError
+            return IPAddress(network + n, version=self._version)
+        else:
+            n += 1
+            if broadcast + n < network:
+                raise IndexError
+            return IPAddress(broadcast + n, version=self._version)
+
+    def __lt__(self, other):
+        if self._version != other._version:
+            raise TypeError('%s and %s are not of the same version' % (
+                    str(self), str(other)))
+        if not isinstance(other, _BaseNet):
+            raise TypeError('%s and %s are not of the same type' % (
+                    str(self), str(other)))
+        if self.network != other.network:
+            return self.network < other.network
+        if self.netmask != other.netmask:
+            return self.netmask < other.netmask
+        return False
+
+    def __gt__(self, other):
+        if self._version != other._version:
+            raise TypeError('%s and %s are not of the same version' % (
+                    str(self), str(other)))
+        if not isinstance(other, _BaseNet):
+            raise TypeError('%s and %s are not of the same type' % (
+                    str(self), str(other)))
+        if self.network != other.network:
+            return self.network > other.network
+        if self.netmask != other.netmask:
+            return self.netmask > other.netmask
+        return False
+
+    def __le__(self, other):
+        gt = self.__gt__(other)
+        if gt is NotImplemented:
+            return NotImplemented
+        return not gt
+
+    def __ge__(self, other):
+        lt = self.__lt__(other)
+        if lt is NotImplemented:
+            return NotImplemented
+        return not lt
+
+    def __eq__(self, other):
+        try:
+            return (self._version == other._version
+                    and self.network == other.network
+                    and int(self.netmask) == int(other.netmask))
+        except AttributeError:
+            if isinstance(other, _BaseIP):
+                return (self._version == other._version
+                        and self._ip == other._ip)
+
+    def __ne__(self, other):
+        eq = self.__eq__(other)
+        if eq is NotImplemented:
+            return NotImplemented
+        return not eq
+
+    def __str__(self):
+        return  '%s/%s' % (str(self.ip),
+                           str(self._prefixlen))
+
+    def __hash__(self):
+        return hash(int(self.network) ^ int(self.netmask))
+
+    def __contains__(self, other):
+        # always false if one is v4 and the other is v6.
+        if self._version != other._version:
+          return False
+        # dealing with another network.
+        if isinstance(other, _BaseNet):
+            return (self.network <= other.network and
+                    self.broadcast >= other.broadcast)
+        # dealing with another address
+        else:
+            return (int(self.network) <= int(other._ip) <=
+                    int(self.broadcast))
+
+    def overlaps(self, other):
+        """Tell if self is partly contained in other."""
+        return self.network in other or self.broadcast in other or (
+            other.network in self or other.broadcast in self)
+
+    @property
+    def network(self):
+        x = self._cache.get('network')
+        if x is None:
+            x = IPAddress(self._ip & int(self.netmask), version=self._version)
+            self._cache['network'] = x
+        return x
+
+    @property
+    def broadcast(self):
+        x = self._cache.get('broadcast')
+        if x is None:
+            x = IPAddress(self._ip | int(self.hostmask), version=self._version)
+            self._cache['broadcast'] = x
+        return x
+
+    @property
+    def hostmask(self):
+        x = self._cache.get('hostmask')
+        if x is None:
+            x = IPAddress(int(self.netmask) ^ self._ALL_ONES,
+                          version=self._version)
+            self._cache['hostmask'] = x
+        return x
+
+    @property
+    def with_prefixlen(self):
+        return '%s/%d' % (str(self.ip), self._prefixlen)
+
+    @property
+    def with_netmask(self):
+        return '%s/%s' % (str(self.ip), str(self.netmask))
+
+    @property
+    def with_hostmask(self):
+        return '%s/%s' % (str(self.ip), str(self.hostmask))
+
+    @property
+    def numhosts(self):
+        """Number of hosts in the current subnet."""
+        return int(self.broadcast) - int(self.network) + 1
+
+    @property
+    def version(self):
+        raise NotImplementedError('BaseNet has no version')
+
+    @property
+    def prefixlen(self):
+        return self._prefixlen
+
+    def address_exclude(self, other):
+        """Remove an address from a larger block.
+
+        For example:
+
+            addr1 = IPNetwork('10.1.1.0/24')
+            addr2 = IPNetwork('10.1.1.0/26')
+            addr1.address_exclude(addr2) =
+                [IPNetwork('10.1.1.64/26'), IPNetwork('10.1.1.128/25')]
+
+        or IPv6:
+
+            addr1 = IPNetwork('::1/32')
+            addr2 = IPNetwork('::1/128')
+            addr1.address_exclude(addr2) = [IPNetwork('::0/128'),
+                IPNetwork('::2/127'),
+                IPNetwork('::4/126'),
+                IPNetwork('::8/125'),
+                ...
+                IPNetwork('0:0:8000::/33')]
+
+        Args:
+            other: An IPvXNetwork object of the same type.
+
+        Returns:
+            A sorted list of IPvXNetwork objects addresses which is self
+            minus other.
+
+        Raises:
+            TypeError: If self and other are of difffering address
+              versions, or if other is not a network object.
+            ValueError: If other is not completely contained by self.
+
+        """
+        if not self._version == other._version:
+            raise TypeError("%s and %s are not of the same version" % (
+                str(self), str(other)))
+
+        if not isinstance(other, _BaseNet):
+            raise TypeError("%s is not a network object" % str(other))
+
+        if other not in self:
+            raise ValueError('%s not contained in %s' % (str(other),
+                                                         str(self)))
+        if other == self:
+            return []
+
+        ret_addrs = []
+
+        # Make sure we're comparing the network of other.
+        other = IPNetwork('%s/%s' % (str(other.network), str(other.prefixlen)),
+                   version=other._version)
+
+        s1, s2 = self.subnet()
+        while s1 != other and s2 != other:
+            if other in s1:
+                ret_addrs.append(s2)
+                s1, s2 = s1.subnet()
+            elif other in s2:
+                ret_addrs.append(s1)
+                s1, s2 = s2.subnet()
+            else:
+                # If we got here, there's a bug somewhere.
+                assert True == False, ('Error performing exclusion: '
+                                       's1: %s s2: %s other: %s' %
+                                       (str(s1), str(s2), str(other)))
+        if s1 == other:
+            ret_addrs.append(s2)
+        elif s2 == other:
+            ret_addrs.append(s1)
+        else:
+            # If we got here, there's a bug somewhere.
+            assert True == False, ('Error performing exclusion: '
+                                   's1: %s s2: %s other: %s' %
+                                   (str(s1), str(s2), str(other)))
+
+        return sorted(ret_addrs, key=_BaseNet._get_networks_key)
+
+    def compare_networks(self, other):
+        """Compare two IP objects.
+
+        This is only concerned about the comparison of the integer
+        representation of the network addresses.  This means that the
+        host bits aren't considered at all in this method.  If you want
+        to compare host bits, you can easily enough do a
+        'HostA._ip < HostB._ip'
+
+        Args:
+            other: An IP object.
+
+        Returns:
+            If the IP versions of self and other are the same, returns:
+
+            -1 if self < other:
+              eg: IPv4('1.1.1.0/24') < IPv4('1.1.2.0/24')
+              IPv6('1080::200C:417A') < IPv6('1080::200B:417B')
+            0 if self == other
+              eg: IPv4('1.1.1.1/24') == IPv4('1.1.1.2/24')
+              IPv6('1080::200C:417A/96') == IPv6('1080::200C:417B/96')
+            1 if self > other
+              eg: IPv4('1.1.1.0/24') > IPv4('1.1.0.0/24')
+              IPv6('1080::1:200C:417A/112') >
+              IPv6('1080::0:200C:417A/112')
+
+            If the IP versions of self and other are different, returns:
+
+            -1 if self._version < other._version
+              eg: IPv4('10.0.0.1/24') < IPv6('::1/128')
+            1 if self._version > other._version
+              eg: IPv6('::1/128') > IPv4('255.255.255.0/24')
+
+        """
+        if self._version < other._version:
+            return -1
+        if self._version > other._version:
+            return 1
+        # self._version == other._version below here:
+        if self.network < other.network:
+            return -1
+        if self.network > other.network:
+            return 1
+        # self.network == other.network below here:
+        if self.netmask < other.netmask:
+            return -1
+        if self.netmask > other.netmask:
+            return 1
+        # self.network == other.network and self.netmask == other.netmask
+        return 0
+
+    def _get_networks_key(self):
+        """Network-only key function.
+
+        Returns an object that identifies this address' network and
+        netmask. This function is a suitable "key" argument for sorted()
+        and list.sort().
+
+        """
+        return (self._version, self.network, self.netmask)
+
+    def _ip_int_from_prefix(self, prefixlen=None):
+        """Turn the prefix length netmask into a int for comparison.
+
+        Args:
+            prefixlen: An integer, the prefix length.
+
+        Returns:
+            An integer.
+
+        """
+        if not prefixlen and prefixlen != 0:
+            prefixlen = self._prefixlen
+        return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen)
+
+    def _prefix_from_ip_int(self, ip_int, mask=32):
+        """Return prefix length from the decimal netmask.
+
+        Args:
+            ip_int: An integer, the IP address.
+            mask: The netmask.  Defaults to 32.
+
+        Returns:
+            An integer, the prefix length.
+
+        """
+        while mask:
+            if ip_int & 1 == 1:
+                break
+            ip_int >>= 1
+            mask -= 1
+
+        return mask
+
+    def _ip_string_from_prefix(self, prefixlen=None):
+        """Turn a prefix length into a dotted decimal string.
+
+        Args:
+            prefixlen: An integer, the netmask prefix length.
+
+        Returns:
+            A string, the dotted decimal netmask string.
+
+        """
+        if not prefixlen:
+            prefixlen = self._prefixlen
+        return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen))
+
+    def iter_subnets(self, prefixlen_diff=1, new_prefix=None):
+        """The subnets which join to make the current subnet.
+
+        In the case that self contains only one IP
+        (self._prefixlen == 32 for IPv4 or self._prefixlen == 128
+        for IPv6), return a list with just ourself.
+
+        Args:
+            prefixlen_diff: An integer, the amount the prefix length
+              should be increased by. This should not be set if
+              new_prefix is also set.
+            new_prefix: The desired new prefix length. This must be a
+              larger number (smaller prefix) than the existing prefix.
+              This should not be set if prefixlen_diff is also set.
+
+        Returns:
+            An iterator of IPv(4|6) objects.
+
+        Raises:
+            ValueError: The prefixlen_diff is too small or too large.
+                OR
+            prefixlen_diff and new_prefix are both set or new_prefix
+              is a smaller number than the current prefix (smaller
+              number means a larger network)
+
+        """
+        if self._prefixlen == self._max_prefixlen:
+            yield self
+            return
+
+        if new_prefix is not None:
+            if new_prefix < self._prefixlen:
+                raise ValueError('new prefix must be longer')
+            if prefixlen_diff != 1:
+                raise ValueError('cannot set prefixlen_diff and new_prefix')
+            prefixlen_diff = new_prefix - self._prefixlen
+
+        if prefixlen_diff < 0:
+            raise ValueError('prefix length diff must be > 0')
+        new_prefixlen = self._prefixlen + prefixlen_diff
+
+        if not self._is_valid_netmask(str(new_prefixlen)):
+            raise ValueError(
+                'prefix length diff %d is invalid for netblock %s' % (
+                    new_prefixlen, str(self)))
+
+        first = IPNetwork('%s/%s' % (str(self.network),
+                                     str(self._prefixlen + prefixlen_diff)),
+                         version=self._version)
+
+        yield first
+        current = first
+        while True:
+            broadcast = current.broadcast
+            if broadcast == self.broadcast:
+                return
+            new_addr = IPAddress(int(broadcast) + 1, version=self._version)
+            current = IPNetwork('%s/%s' % (str(new_addr), str(new_prefixlen)),
+                                version=self._version)
+
+            yield current
+
+    def masked(self):
+        """Return the network object with the host bits masked out."""
+        return IPNetwork('%s/%d' % (self.network, self._prefixlen),
+                         version=self._version)
+
+    def subnet(self, prefixlen_diff=1, new_prefix=None):
+        """Return a list of subnets, rather than an iterator."""
+        return list(self.iter_subnets(prefixlen_diff, new_prefix))
+
+    def supernet(self, prefixlen_diff=1, new_prefix=None):
+        """The supernet containing the current network.
+
+        Args:
+            prefixlen_diff: An integer, the amount the prefix length of
+              the network should be decreased by.  For example, given a
+              /24 network and a prefixlen_diff of 3, a supernet with a
+              /21 netmask is returned.
+
+        Returns:
+            An IPv4 network object.
+
+        Raises:
+            ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have a
+              negative prefix length.
+                OR
+            If prefixlen_diff and new_prefix are both set or new_prefix is a
+              larger number than the current prefix (larger number means a
+              smaller network)
+
+        """
+        if self._prefixlen == 0:
+            return self
+
+        if new_prefix is not None:
+            if new_prefix > self._prefixlen:
+                raise ValueError('new prefix must be shorter')
+            if prefixlen_diff != 1:
+                raise ValueError('cannot set prefixlen_diff and new_prefix')
+            prefixlen_diff = self._prefixlen - new_prefix
+
+
+        if self.prefixlen - prefixlen_diff < 0:
+            raise ValueError(
+                'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
+                (self.prefixlen, prefixlen_diff))
+        return IPNetwork('%s/%s' % (str(self.network),
+                                    str(self.prefixlen - prefixlen_diff)),
+                         version=self._version)
+
+    # backwards compatibility
+    Subnet = subnet
+    Supernet = supernet
+    AddressExclude = address_exclude
+    CompareNetworks = compare_networks
+    Contains = __contains__
+
+
+class _BaseV4(object):
+
+    """Base IPv4 object.
+
+    The following methods are used by IPv4 objects in both single IP
+    addresses and networks.
+
+    """
+
+    # Equivalent to 255.255.255.255 or 32 bits of 1's.
+    _ALL_ONES = (2**IPV4LENGTH) - 1
+    _DECIMAL_DIGITS = frozenset('0123456789')
+
+    def __init__(self, address):
+        self._version = 4
+        self._max_prefixlen = IPV4LENGTH
+
+    def _explode_shorthand_ip_string(self, ip_str=None):
+        if not ip_str:
+            ip_str = str(self)
+        return ip_str
+
+    def _ip_int_from_string(self, ip_str):
+        """Turn the given IP string into an integer for comparison.
+
+        Args:
+            ip_str: A string, the IP ip_str.
+
+        Returns:
+            The IP ip_str as an integer.
+
+        Raises:
+            AddressValueError: if ip_str isn't a valid IPv4 Address.
+
+        """
+        octets = ip_str.split('.')
+        if len(octets) != 4:
+            raise AddressValueError(ip_str)
+
+        packed_ip = 0
+        for oc in octets:
+            try:
+                packed_ip = (packed_ip << 8) | self._parse_octet(oc)
+            except ValueError:
+                raise AddressValueError(ip_str)
+        return packed_ip
+
+    def _parse_octet(self, octet_str):
+        """Convert a decimal octet into an integer.
+
+        Args:
+            octet_str: A string, the number to parse.
+
+        Returns:
+            The octet as an integer.
+
+        Raises:
+            ValueError: if the octet isn't strictly a decimal from [0..255].
+
+        """
+        # Whitelist the characters, since int() allows a lot of bizarre stuff.
+        if not self._DECIMAL_DIGITS.issuperset(octet_str):
+            raise ValueError
+        octet_int = int(octet_str, 10)
+        # Disallow leading zeroes, because no clear standard exists on
+        # whether these should be interpreted as decimal or octal.
+        if octet_int > 255 or (octet_str[0] == '0' and len(octet_str) > 1):
+            raise ValueError
+        return octet_int
+
+    def _string_from_ip_int(self, ip_int):
+        """Turns a 32-bit integer into dotted decimal notation.
+
+        Args:
+            ip_int: An integer, the IP address.
+
+        Returns:
+            The IP address as a string in dotted decimal notation.
+
+        """
+        octets = []
+        for _ in xrange(4):
+            octets.insert(0, str(ip_int & 0xFF))
+            ip_int >>= 8
+        return '.'.join(octets)
+
+    @property
+    def max_prefixlen(self):
+        return self._max_prefixlen
+
+    @property
+    def packed(self):
+        """The binary representation of this address."""
+        return v4_int_to_packed(self._ip)
+
+    @property
+    def version(self):
+        return self._version
+
+    @property
+    def is_reserved(self):
+       """Test if the address is otherwise IETF reserved.
+
+        Returns:
+            A boolean, True if the address is within the
+            reserved IPv4 Network range.
+
+       """
+       return self in IPv4Network('240.0.0.0/4')
+
+    @property
+    def is_private(self):
+        """Test if this address is allocated for private networks.
+
+        Returns:
+            A boolean, True if the address is reserved per RFC 1918.
+
+        """
+        return (self in IPv4Network('10.0.0.0/8') or
+                self in IPv4Network('172.16.0.0/12') or
+                self in IPv4Network('192.168.0.0/16'))
+
+    @property
+    def is_multicast(self):
+        """Test if the address is reserved for multicast use.
+
+        Returns:
+            A boolean, True if the address is multicast.
+            See RFC 3171 for details.
+
+        """
+        return self in IPv4Network('224.0.0.0/4')
+
+    @property
+    def is_unspecified(self):
+        """Test if the address is unspecified.
+
+        Returns:
+            A boolean, True if this is the unspecified address as defined in
+            RFC 5735 3.
+
+        """
+        return self in IPv4Network('0.0.0.0')
+
+    @property
+    def is_loopback(self):
+        """Test if the address is a loopback address.
+
+        Returns:
+            A boolean, True if the address is a loopback per RFC 3330.
+
+        """
+        return self in IPv4Network('127.0.0.0/8')
+
+    @property
+    def is_link_local(self):
+        """Test if the address is reserved for link-local.
+
+        Returns:
+            A boolean, True if the address is link-local per RFC 3927.
+
+        """
+        return self in IPv4Network('169.254.0.0/16')
+
+
+class IPv4Address(_BaseV4, _BaseIP):
+
+    """Represent and manipulate single IPv4 Addresses."""
+
+    def __init__(self, address):
+
+        """
+        Args:
+            address: A string or integer representing the IP
+              '192.168.1.1'
+
+              Additionally, an integer can be passed, so
+              IPv4Address('192.168.1.1') == IPv4Address(3232235777).
+              or, more generally
+              IPv4Address(int(IPv4Address('192.168.1.1'))) ==
+                IPv4Address('192.168.1.1')
+
+        Raises:
+            AddressValueError: If ipaddr isn't a valid IPv4 address.
+
+        """
+        _BaseIP.__init__(self, address)
+        _BaseV4.__init__(self, address)
+
+        # Efficient constructor from integer.
+        if isinstance(address, (int, long)):
+            self._ip = address
+            if address < 0 or address > self._ALL_ONES:
+                raise AddressValueError(address)
+            return
+
+        # Constructing from a packed address
+        if _compat_has_real_bytes:
+            if isinstance(address, bytes) and len(address) == 4:
+                self._ip = struct.unpack('!I', address)[0]
+                return
+
+        # Assume input argument to be string or any object representation
+        # which converts into a formatted IP string.
+        addr_str = str(address)
+        self._ip = self._ip_int_from_string(addr_str)
+
+
+class IPv4Network(_BaseV4, _BaseNet):
+
+    """This class represents and manipulates 32-bit IPv4 networks.
+
+    Attributes: [examples for IPv4Network('1.2.3.4/27')]
+        ._ip: 16909060
+        .ip: IPv4Address('1.2.3.4')
+        .network: IPv4Address('1.2.3.0')
+        .hostmask: IPv4Address('0.0.0.31')
+        .broadcast: IPv4Address('1.2.3.31')
+        .netmask: IPv4Address('255.255.255.224')
+        .prefixlen: 27
+
+    """
+
+    # the valid octets for host and netmasks. only useful for IPv4.
+    _valid_mask_octets = set((255, 254, 252, 248, 240, 224, 192, 128, 0))
+
+    def __init__(self, address, strict=False):
+        """Instantiate a new IPv4 network object.
+
+        Args:
+            address: A string or integer representing the IP [& network].
+              '192.168.1.1/24'
+              '192.168.1.1/255.255.255.0'
+              '192.168.1.1/0.0.0.255'
+              are all functionally the same in IPv4. Similarly,
+              '192.168.1.1'
+              '192.168.1.1/255.255.255.255'
+              '192.168.1.1/32'
+              are also functionaly equivalent. That is to say, failing to
+              provide a subnetmask will create an object with a mask of /32.
+
+              If the mask (portion after the / in the argument) is given in
+              dotted quad form, it is treated as a netmask if it starts with a
+              non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it
+              starts with a zero field (e.g. 0.255.255.255 == /8), with the
+              single exception of an all-zero mask which is treated as a
+              netmask == /0. If no mask is given, a default of /32 is used.
+
+              Additionally, an integer can be passed, so
+              IPv4Network('192.168.1.1') == IPv4Network(3232235777).
+              or, more generally
+              IPv4Network(int(IPv4Network('192.168.1.1'))) ==
+                IPv4Network('192.168.1.1')
+
+            strict: A boolean. If true, ensure that we have been passed
+              A true network address, eg, 192.168.1.0/24 and not an
+              IP address on a network, eg, 192.168.1.1/24.
+
+        Raises:
+            AddressValueError: If ipaddr isn't a valid IPv4 address.
+            NetmaskValueError: If the netmask isn't valid for
+              an IPv4 address.
+            ValueError: If strict was True and a network address was not
+              supplied.
+
+        """
+        _BaseNet.__init__(self, address)
+        _BaseV4.__init__(self, address)
+
+        # Efficient constructor from integer.
+        if isinstance(address, (int, long)):
+            self._ip = address
+            self.ip = IPv4Address(self._ip)
+            self._prefixlen = self._max_prefixlen
+            self.netmask = IPv4Address(self._ALL_ONES)
+            if address < 0 or address > self._ALL_ONES:
+                raise AddressValueError(address)
+            return
+
+        # Constructing from a packed address
+        if _compat_has_real_bytes:
+            if isinstance(address, bytes) and len(address) == 4:
+                self._ip = struct.unpack('!I', address)[0]
+                self.ip = IPv4Address(self._ip)
+                self._prefixlen = self._max_prefixlen
+                self.netmask = IPv4Address(self._ALL_ONES)
+                return
+
+        # Assume input argument to be string or any object representation
+        # which converts into a formatted IP prefix string.
+        addr = str(address).split('/')
+
+        if len(addr) > 2:
+            raise AddressValueError(address)
+
+        self._ip = self._ip_int_from_string(addr[0])
+        self.ip = IPv4Address(self._ip)
+
+        if len(addr) == 2:
+            mask = addr[1].split('.')
+            if len(mask) == 4:
+                # We have dotted decimal netmask.
+                if self._is_valid_netmask(addr[1]):
+                    self.netmask = IPv4Address(self._ip_int_from_string(
+                            addr[1]))
+                elif self._is_hostmask(addr[1]):
+                    self.netmask = IPv4Address(
+                        self._ip_int_from_string(addr[1]) ^ self._ALL_ONES)
+                else:
+                    raise NetmaskValueError('%s is not a valid netmask'
+                                                     % addr[1])
+
+                self._prefixlen = self._prefix_from_ip_int(int(self.netmask))
+            else:
+                # We have a netmask in prefix length form.
+                if not self._is_valid_netmask(addr[1]):
+                    raise NetmaskValueError(addr[1])
+                self._prefixlen = int(addr[1])
+                self.netmask = IPv4Address(self._ip_int_from_prefix(
+                    self._prefixlen))
+        else:
+            self._prefixlen = self._max_prefixlen
+            self.netmask = IPv4Address(self._ip_int_from_prefix(
+                self._prefixlen))
+        if strict:
+            if self.ip != self.network:
+                raise ValueError('%s has host bits set' %
+                                 self.ip)
+
+    def _is_hostmask(self, ip_str):
+        """Test if the IP string is a hostmask (rather than a netmask).
+
+        Args:
+            ip_str: A string, the potential hostmask.
+
+        Returns:
+            A boolean, True if the IP string is a hostmask.
+
+        """
+        bits = ip_str.split('.')
+        try:
+            parts = [int(x) for x in bits if int(x) in self._valid_mask_octets]
+        except ValueError:
+            return False
+        if len(parts) != len(bits):
+            return False
+        if parts[0] < parts[-1]:
+            return True
+        return False
+
+    def _is_valid_netmask(self, netmask):
+        """Verify that the netmask is valid.
+
+        Args:
+            netmask: A string, either a prefix or dotted decimal
+              netmask.
+
+        Returns:
+            A boolean, True if the prefix represents a valid IPv4
+            netmask.
+
+        """
+        mask = netmask.split('.')
+        if len(mask) == 4:
+            if [x for x in mask if int(x) not in self._valid_mask_octets]:
+                return False
+            if [y for idx, y in enumerate(mask) if idx > 0 and
+                y > mask[idx - 1]]:
+                return False
+            return True
+        try:
+            netmask = int(netmask)
+        except ValueError:
+            return False
+        return 0 <= netmask <= self._max_prefixlen
+
+    # backwards compatibility
+    IsRFC1918 = lambda self: self.is_private
+    IsMulticast = lambda self: self.is_multicast
+    IsLoopback = lambda self: self.is_loopback
+    IsLinkLocal = lambda self: self.is_link_local
+
+
+class _BaseV6(object):
+
+    """Base IPv6 object.
+
+    The following methods are used by IPv6 objects in both single IP
+    addresses and networks.
+
+    """
+
+    _ALL_ONES = (2**IPV6LENGTH) - 1
+    _HEXTET_COUNT = 8
+    _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef')
+
+    def __init__(self, address):
+        self._version = 6
+        self._max_prefixlen = IPV6LENGTH
+
+    def _ip_int_from_string(self, ip_str):
+        """Turn an IPv6 ip_str into an integer.
+
+        Args:
+            ip_str: A string, the IPv6 ip_str.
+
+        Returns:
+            A long, the IPv6 ip_str.
+
+        Raises:
+            AddressValueError: if ip_str isn't a valid IPv6 Address.
+
+        """
+        parts = ip_str.split(':')
+
+        # An IPv6 address needs at least 2 colons (3 parts).
+        if len(parts) < 3:
+            raise AddressValueError(ip_str)
+
+        # If the address has an IPv4-style suffix, convert it to hexadecimal.
+        if '.' in parts[-1]:
+            ipv4_int = IPv4Address(parts.pop())._ip
+            parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF))
+            parts.append('%x' % (ipv4_int & 0xFFFF))
+
+        # An IPv6 address can't have more than 8 colons (9 parts).
+        if len(parts) > self._HEXTET_COUNT + 1:
+            raise AddressValueError(ip_str)
+
+        # Disregarding the endpoints, find '::' with nothing in between.
+        # This indicates that a run of zeroes has been skipped.
+        try:
+            skip_index, = (
+                [i for i in xrange(1, len(parts) - 1) if not parts[i]] or
+                [None])
+        except ValueError:
+            # Can't have more than one '::'
+            raise AddressValueError(ip_str)
+
+        # parts_hi is the number of parts to copy from above/before the '::'
+        # parts_lo is the number of parts to copy from below/after the '::'
+        if skip_index is not None:
+            # If we found a '::', then check if it also covers the endpoints.
+            parts_hi = skip_index
+            parts_lo = len(parts) - skip_index - 1
+            if not parts[0]:
+                parts_hi -= 1
+                if parts_hi:
+                    raise AddressValueError(ip_str)  # ^: requires ^::
+            if not parts[-1]:
+                parts_lo -= 1
+                if parts_lo:
+                    raise AddressValueError(ip_str)  # :$ requires ::$
+            parts_skipped = self._HEXTET_COUNT - (parts_hi + parts_lo)
+            if parts_skipped < 1:
+                raise AddressValueError(ip_str)
+        else:
+            # Otherwise, allocate the entire address to parts_hi.  The endpoints
+            # could still be empty, but _parse_hextet() will check for that.
+            if len(parts) != self._HEXTET_COUNT:
+                raise AddressValueError(ip_str)
+            parts_hi = len(parts)
+            parts_lo = 0
+            parts_skipped = 0
+
+        try:
+            # Now, parse the hextets into a 128-bit integer.
+            ip_int = 0L
+            for i in xrange(parts_hi):
+                ip_int <<= 16
+                ip_int |= self._parse_hextet(parts[i])
+            ip_int <<= 16 * parts_skipped
+            for i in xrange(-parts_lo, 0):
+                ip_int <<= 16
+                ip_int |= self._parse_hextet(parts[i])
+            return ip_int
+        except ValueError:
+            raise AddressValueError(ip_str)
+
+    def _parse_hextet(self, hextet_str):
+        """Convert an IPv6 hextet string into an integer.
+
+        Args:
+            hextet_str: A string, the number to parse.
+
+        Returns:
+            The hextet as an integer.
+
+        Raises:
+            ValueError: if the input isn't strictly a hex number from [0..FFFF].
+
+        """
+        # Whitelist the characters, since int() allows a lot of bizarre stuff.
+        if not self._HEX_DIGITS.issuperset(hextet_str):
+            raise ValueError
+        hextet_int = int(hextet_str, 16)
+        if hextet_int > 0xFFFF:
+            raise ValueError
+        return hextet_int
+
+    def _compress_hextets(self, hextets):
+        """Compresses a list of hextets.
+
+        Compresses a list of strings, replacing the longest continuous
+        sequence of "0" in the list with "" and adding empty strings at
+        the beginning or at the end of the string such that subsequently
+        calling ":".join(hextets) will produce the compressed version of
+        the IPv6 address.
+
+        Args:
+            hextets: A list of strings, the hextets to compress.
+
+        Returns:
+            A list of strings.
+
+        """
+        best_doublecolon_start = -1
+        best_doublecolon_len = 0
+        doublecolon_start = -1
+        doublecolon_len = 0
+        for index in range(len(hextets)):
+            if hextets[index] == '0':
+                doublecolon_len += 1
+                if doublecolon_start == -1:
+                    # Start of a sequence of zeros.
+                    doublecolon_start = index
+                if doublecolon_len > best_doublecolon_len:
+                    # This is the longest sequence of zeros so far.
+                    best_doublecolon_len = doublecolon_len
+                    best_doublecolon_start = doublecolon_start
+            else:
+                doublecolon_len = 0
+                doublecolon_start = -1
+
+        if best_doublecolon_len > 1:
+            best_doublecolon_end = (best_doublecolon_start +
+                                    best_doublecolon_len)
+            # For zeros at the end of the address.
+            if best_doublecolon_end == len(hextets):
+                hextets += ['']
+            hextets[best_doublecolon_start:best_doublecolon_end] = ['']
+            # For zeros at the beginning of the address.
+            if best_doublecolon_start == 0:
+                hextets = [''] + hextets
+
+        return hextets
+
+    def _string_from_ip_int(self, ip_int=None):
+        """Turns a 128-bit integer into hexadecimal notation.
+
+        Args:
+            ip_int: An integer, the IP address.
+
+        Returns:
+            A string, the hexadecimal representation of the address.
+
+        Raises:
+            ValueError: The address is bigger than 128 bits of all ones.
+
+        """
+        if not ip_int and ip_int != 0:
+            ip_int = int(self._ip)
+
+        if ip_int > self._ALL_ONES:
+            raise ValueError('IPv6 address is too large')
+
+        hex_str = '%032x' % ip_int
+        hextets = []
+        for x in range(0, 32, 4):
+            hextets.append('%x' % int(hex_str[x:x+4], 16))
+
+        hextets = self._compress_hextets(hextets)
+        return ':'.join(hextets)
+
+    def _explode_shorthand_ip_string(self, ip_str=None):
+        """Expand a shortened IPv6 address.
+
+        Args:
+            ip_str: A string, the IPv6 address.
+
+        Returns:
+            A string, the expanded IPv6 address.
+
+        """
+        if not ip_str:
+            ip_str = str(self)
+            if isinstance(self, _BaseNet):
+                ip_str = str(self.ip)
+
+        ip_int = self._ip_int_from_string(ip_str)
+        parts = []
+        for i in xrange(self._HEXTET_COUNT):
+            parts.append('%04x' % (ip_int & 0xFFFF))
+            ip_int >>= 16
+        parts.reverse()
+        return ':'.join(parts)
+
+    @property
+    def max_prefixlen(self):
+        return self._max_prefixlen
+
+    @property
+    def packed(self):
+        """The binary representation of this address."""
+        return v6_int_to_packed(self._ip)
+
+    @property
+    def version(self):
+        return self._version
+
+    @property
+    def is_multicast(self):
+        """Test if the address is reserved for multicast use.
+
+        Returns:
+            A boolean, True if the address is a multicast address.
+            See RFC 2373 2.7 for details.
+
+        """
+        return self in IPv6Network('ff00::/8')
+
+    @property
+    def is_reserved(self):
+        """Test if the address is otherwise IETF reserved.
+
+        Returns:
+            A boolean, True if the address is within one of the
+            reserved IPv6 Network ranges.
+
+        """
+        return (self in IPv6Network('::/8') or
+                self in IPv6Network('100::/8') or
+                self in IPv6Network('200::/7') or
+                self in IPv6Network('400::/6') or
+                self in IPv6Network('800::/5') or
+                self in IPv6Network('1000::/4') or
+                self in IPv6Network('4000::/3') or
+                self in IPv6Network('6000::/3') or
+                self in IPv6Network('8000::/3') or
+                self in IPv6Network('A000::/3') or
+                self in IPv6Network('C000::/3') or
+                self in IPv6Network('E000::/4') or
+                self in IPv6Network('F000::/5') or
+                self in IPv6Network('F800::/6') or
+                self in IPv6Network('FE00::/9'))
+
+    @property
+    def is_unspecified(self):
+        """Test if the address is unspecified.
+
+        Returns:
+            A boolean, True if this is the unspecified address as defined in
+            RFC 2373 2.5.2.
+
+        """
+        return self._ip == 0 and getattr(self, '_prefixlen', 128) == 128
+
+    @property
+    def is_loopback(self):
+        """Test if the address is a loopback address.
+
+        Returns:
+            A boolean, True if the address is a loopback address as defined in
+            RFC 2373 2.5.3.
+
+        """
+        return self._ip == 1 and getattr(self, '_prefixlen', 128) == 128
+
+    @property
+    def is_link_local(self):
+        """Test if the address is reserved for link-local.
+
+        Returns:
+            A boolean, True if the address is reserved per RFC 4291.
+
+        """
+        return self in IPv6Network('fe80::/10')
+
+    @property
+    def is_site_local(self):
+        """Test if the address is reserved for site-local.
+
+        Note that the site-local address space has been deprecated by RFC 3879.
+        Use is_private to test if this address is in the space of unique local
+        addresses as defined by RFC 4193.
+
+        Returns:
+            A boolean, True if the address is reserved per RFC 3513 2.5.6.
+
+        """
+        return self in IPv6Network('fec0::/10')
+
+    @property
+    def is_private(self):
+        """Test if this address is allocated for private networks.
+
+        Returns:
+            A boolean, True if the address is reserved per RFC 4193.
+
+        """
+        return self in IPv6Network('fc00::/7')
+
+    @property
+    def ipv4_mapped(self):
+        """Return the IPv4 mapped address.
+
+        Returns:
+            If the IPv6 address is a v4 mapped address, return the
+            IPv4 mapped address. Return None otherwise.
+
+        """
+        if (self._ip >> 32) != 0xFFFF:
+            return None
+        return IPv4Address(self._ip & 0xFFFFFFFF)
+
+    @property
+    def teredo(self):
+        """Tuple of embedded teredo IPs.
+
+        Returns:
+            Tuple of the (server, client) IPs or None if the address
+            doesn't appear to be a teredo address (doesn't start with
+            2001::/32)
+
+        """
+        if (self._ip >> 96) != 0x20010000:
+            return None
+        return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF),
+                IPv4Address(~self._ip & 0xFFFFFFFF))
+
+    @property
+    def sixtofour(self):
+        """Return the IPv4 6to4 embedded address.
+
+        Returns:
+            The IPv4 6to4-embedded address if present or None if the
+            address doesn't appear to contain a 6to4 embedded address.
+
+        """
+        if (self._ip >> 112) != 0x2002:
+            return None
+        return IPv4Address((self._ip >> 80) & 0xFFFFFFFF)
+
+
+class IPv6Address(_BaseV6, _BaseIP):
+
+    """Represent and manipulate single IPv6 Addresses.
+    """
+
+    def __init__(self, address):
+        """Instantiate a new IPv6 address object.
+
+        Args:
+            address: A string or integer representing the IP
+
+              Additionally, an integer can be passed, so
+              IPv6Address('2001:4860::') ==
+                IPv6Address(42541956101370907050197289607612071936L).
+              or, more generally
+              IPv6Address(IPv6Address('2001:4860::')._ip) ==
+                IPv6Address('2001:4860::')
+
+        Raises:
+            AddressValueError: If address isn't a valid IPv6 address.
+
+        """
+        _BaseIP.__init__(self, address)
+        _BaseV6.__init__(self, address)
+
+        # Efficient constructor from integer.
+        if isinstance(address, (int, long)):
+            self._ip = address
+            if address < 0 or address > self._ALL_ONES:
+                raise AddressValueError(address)
+            return
+
+        # Constructing from a packed address
+        if _compat_has_real_bytes:
+            if isinstance(address, bytes) and len(address) == 16:
+                tmp = struct.unpack('!QQ', address)
+                self._ip = (tmp[0] << 64) | tmp[1]
+                return
+
+        # Assume input argument to be string or any object representation
+        # which converts into a formatted IP string.
+        addr_str = str(address)
+        if not addr_str:
+            raise AddressValueError('')
+
+        self._ip = self._ip_int_from_string(addr_str)
+
+
+class IPv6Network(_BaseV6, _BaseNet):
+
+    """This class represents and manipulates 128-bit IPv6 networks.
+
+    Attributes: [examples for IPv6('2001:658:22A:CAFE:200::1/64')]
+        .ip: IPv6Address('2001:658:22a:cafe:200::1')
+        .network: IPv6Address('2001:658:22a:cafe::')
+        .hostmask: IPv6Address('::ffff:ffff:ffff:ffff')
+        .broadcast: IPv6Address('2001:658:22a:cafe:ffff:ffff:ffff:ffff')
+        .netmask: IPv6Address('ffff:ffff:ffff:ffff::')
+        .prefixlen: 64
+
+    """
+
+
+    def __init__(self, address, strict=False):
+        """Instantiate a new IPv6 Network object.
+
+        Args:
+            address: A string or integer representing the IPv6 network or the IP
+              and prefix/netmask.
+              '2001:4860::/128'
+              '2001:4860:0000:0000:0000:0000:0000:0000/128'
+              '2001:4860::'
+              are all functionally the same in IPv6.  That is to say,
+              failing to provide a subnetmask will create an object with
+              a mask of /128.
+
+              Additionally, an integer can be passed, so
+              IPv6Network('2001:4860::') ==
+                IPv6Network(42541956101370907050197289607612071936L).
+              or, more generally
+              IPv6Network(IPv6Network('2001:4860::')._ip) ==
+                IPv6Network('2001:4860::')
+
+            strict: A boolean. If true, ensure that we have been passed
+              A true network address, eg, 192.168.1.0/24 and not an
+              IP address on a network, eg, 192.168.1.1/24.
+
+        Raises:
+            AddressValueError: If address isn't a valid IPv6 address.
+            NetmaskValueError: If the netmask isn't valid for
+              an IPv6 address.
+            ValueError: If strict was True and a network address was not
+              supplied.
+
+        """
+        _BaseNet.__init__(self, address)
+        _BaseV6.__init__(self, address)
+
+        # Efficient constructor from integer.
+        if isinstance(address, (int, long)):
+            self._ip = address
+            self.ip = IPv6Address(self._ip)
+            self._prefixlen = self._max_prefixlen
+            self.netmask = IPv6Address(self._ALL_ONES)
+            if address < 0 or address > self._ALL_ONES:
+                raise AddressValueError(address)
+            return
+
+        # Constructing from a packed address
+        if _compat_has_real_bytes:
+            if isinstance(address, bytes) and len(address) == 16:
+                tmp = struct.unpack('!QQ', address)
+                self._ip = (tmp[0] << 64) | tmp[1]
+                self.ip = IPv6Address(self._ip)
+                self._prefixlen = self._max_prefixlen
+                self.netmask = IPv6Address(self._ALL_ONES)
+                return
+
+        # Assume input argument to be string or any object representation
+        # which converts into a formatted IP prefix string.
+        addr = str(address).split('/')
+
+        if len(addr) > 2:
+            raise AddressValueError(address)
+
+        self._ip = self._ip_int_from_string(addr[0])
+        self.ip = IPv6Address(self._ip)
+
+        if len(addr) == 2:
+            if self._is_valid_netmask(addr[1]):
+                self._prefixlen = int(addr[1])
+            else:
+                raise NetmaskValueError(addr[1])
+        else:
+            self._prefixlen = self._max_prefixlen
+
+        self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen))
+
+        if strict:
+            if self.ip != self.network:
+                raise ValueError('%s has host bits set' %
+                                 self.ip)
+
+    def _is_valid_netmask(self, prefixlen):
+        """Verify that the netmask/prefixlen is valid.
+
+        Args:
+            prefixlen: A string, the netmask in prefix length format.
+
+        Returns:
+            A boolean, True if the prefix represents a valid IPv6
+            netmask.
+
+        """
+        try:
+            prefixlen = int(prefixlen)
+        except ValueError:
+            return False
+        return 0 <= prefixlen <= self._max_prefixlen
+
+    @property
+    def with_netmask(self):
+        return self.with_prefixlen
diff --git a/src/main/resources/PythonLibs/_jyio.py b/src/main/resources/PythonLibs/_jyio.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f595f17a432e10bcd847cca46f56d8870a70d96
--- /dev/null
+++ b/src/main/resources/PythonLibs/_jyio.py
@@ -0,0 +1,1646 @@
+"""
+This is based on  _pyio.py from CPython 2.7 which is Python implementation of
+the io module. The upgrade from a 2.6-ish version accounts for the large
+number of changes made all at once.
+
+It is here to stand in for classes that should be provided by the _io module.
+In CPython 2.7, when client code imports io, that module imports a set of
+classes from _io and re-exports them as its own. In Jython, io.py imports
+those things from _jyio, which in turn imports from _io those so far
+implemented in Java. _jyio implements the rest here using nearly the same
+code as _pyio.
+
+Some classes have gained an underscore to match their _io module names:
+_IOBase, _RawIOBase, _BufferedIOBase, _TextIOBase.
+
+As Jython implements more and more of _io in Java, the Python implementations here
+will progressively be replaced with imports from _io. Eventually we should implement
+all this in Java, remove this module and revert io.py to its CPython original.
+"""
+
+from __future__ import (print_function, unicode_literals)
+
+import _io  # Java implementations to replace this module
+
+import os
+import abc
+import codecs
+import warnings
+import errno
+import array
+# Import thread instead of threading to reduce startup cost
+try:
+    from thread import allocate_lock as Lock
+except ImportError:
+    from dummy_thread import allocate_lock as Lock
+
+#import io
+#from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)
+from errno import EINTR
+
+__metaclass__ = type
+
+# open() uses st_blksize whenever we can
+from _io import DEFAULT_BUFFER_SIZE
+
+# NOTE: Base classes defined here are registered with the "official" ABCs
+# defined in io.py.
+
+
+class BlockingIOError(IOError):
+
+    """Exception raised when I/O would block on a non-blocking I/O stream."""
+
+    def __init__(self, errno, strerror, characters_written=0):
+        super(IOError, self).__init__(errno, strerror)
+        if not isinstance(characters_written, (int, long)):
+            raise TypeError("characters_written must be a integer")
+        self.characters_written = characters_written
+
+
+from _io import (open, UnsupportedOperation, _IOBase, _RawIOBase, FileIO)
+
+
+class _BufferedIOBase(_IOBase):
+
+    """Base class for buffered IO objects.
+
+    The main difference with _RawIOBase is that the read() method
+    supports omitting the size argument, and does not have a default
+    implementation that defers to readinto().
+
+    In addition, read(), readinto() and write() may raise
+    BlockingIOError if the underlying raw stream is in non-blocking
+    mode and not ready; unlike their raw counterparts, they will never
+    return None.
+
+    A typical implementation should not inherit from a _RawIOBase
+    implementation, but wrap one.
+    """
+
+    def read(self, n=None):
+        """Read and return up to n bytes.
+
+        If the argument is omitted, None, or negative, reads and
+        returns all data until EOF.
+
+        If the argument is positive, and the underlying raw stream is
+        not 'interactive', multiple raw reads may be issued to satisfy
+        the byte count (unless EOF is reached first).  But for
+        interactive raw streams (XXX and for pipes?), at most one raw
+        read will be issued, and a short result does not imply that
+        EOF is imminent.
+
+        Returns an empty bytes array on EOF.
+
+        Raises BlockingIOError if the underlying raw stream has no
+        data at the moment.
+        """
+        self._unsupported("read")
+
+    def read1(self, n=None):
+        """Read up to n bytes with at most one read() system call."""
+        self._unsupported("read1")
+
+    def readinto(self, b):
+        """Read up to len(b) bytes into b.
+
+        Like read(), this may issue multiple reads to the underlying raw
+        stream, unless the latter is 'interactive'.
+
+        Returns the number of bytes read (0 for EOF).
+
+        Raises BlockingIOError if the underlying raw stream has no
+        data at the moment.
+        """
+        # XXX This ought to work with anything that supports the buffer API
+        data = self.read(len(b))
+        n = len(data)
+        try:
+            b[:n] = data
+        except TypeError as err:
+            import array
+            if not isinstance(b, array.array):
+                raise err
+            b[:n] = array.array(b'b', data)
+        return n
+
+    def write(self, b):
+        """Write the given buffer to the IO stream.
+
+        Return the number of bytes written, which is never less than
+        len(b).
+
+        Raises BlockingIOError if the buffer is full and the
+        underlying raw stream cannot accept more data at the moment.
+        """
+        self._unsupported("write")
+
+    def detach(self):
+        """
+        Separate the underlying raw stream from the buffer and return it.
+
+        After the raw stream has been detached, the buffer is in an unusable
+        state.
+        """
+        self._unsupported("detach")
+
+
+class _BufferedIOMixin(_BufferedIOBase):
+
+    """A mixin implementation of _BufferedIOBase with an underlying raw stream.
+
+    This passes most requests on to the underlying raw stream.  It
+    does *not* provide implementations of read(), readinto() or
+    write().
+    """
+
+    def __init__(self, raw):
+        self._ok = False    # Jython: subclass __init__ must set when state valid
+        self._raw = raw
+
+    ### Positioning ###
+
+    def seek(self, pos, whence=0):
+        new_position = self.raw.seek(pos, whence)
+        if new_position < 0:
+            raise IOError("seek() returned an invalid position")
+        return new_position
+
+    def tell(self):
+        pos = self.raw.tell()
+        if pos < 0:
+            raise IOError("tell() returned an invalid position")
+        return pos
+
+    def truncate(self, pos=None):
+        # Flush the stream.  We're mixing buffered I/O with lower-level I/O,
+        # and a flush may be necessary to synch both views of the current
+        # file state.
+        self.flush()
+
+        if pos is None:
+            pos = self.tell()
+        # XXX: Should seek() be used, instead of passing the position
+        # XXX  directly to truncate?
+        return self.raw.truncate(pos)
+
+    ### Flush and close ###
+
+    def flush(self):
+        if self.closed:
+            raise ValueError("flush of closed file")
+        self.raw.flush()
+
+    def close(self):
+        if self.raw is not None and not self.closed:
+            try:
+                # Jython difference: call super.close() which manages "closed to client" state,
+                # and calls flush(), which may raise BlockingIOError or BrokenPipeError etc.
+                super(_BufferedIOBase, self).close()
+            finally:
+                self.raw.close()
+
+    def detach(self):
+        if self.raw is None:
+            raise ValueError("raw stream already detached")
+        self.flush()
+        raw = self._raw
+        self._raw = None
+        return raw
+
+    ### Inquiries ###
+
+    def seekable(self):
+        self._checkInitialized()     # Jython: to forbid use in an invalid state
+        return self.raw.seekable()
+
+    def readable(self):
+        self._checkInitialized()     # Jython: to forbid use in an invalid state
+        return self.raw.readable()
+
+    def writable(self):
+        self._checkInitialized()     # Jython: to forbid use in an invalid state
+        return self.raw.writable()
+
+    @property
+    def raw(self):
+        return self._raw
+
+    @property
+    def closed(self):
+        return self.raw.closed
+
+    # Jython difference: emulate C implementation CHECK_INITIALIZED. This is for
+    # compatibility, to pass test.test_io.CTextIOWrapperTest.test_initialization.
+    def _checkInitialized(self):
+        if not self._ok:
+            if self.raw is None:
+                raise ValueError("raw stream has been detached")
+            else:
+                raise ValueError("I/O operation on uninitialized object")
+
+    @property
+    def name(self):
+        return self.raw.name
+
+    @property
+    def mode(self):
+        return self.raw.mode
+
+    def __repr__(self):
+        clsname = self.__class__.__name__
+        try:
+            name = self.name
+        except AttributeError:
+            return "<_jyio.{0}>".format(clsname)
+        else:
+            return "<_jyio.{0} name={1!r}>".format(clsname, name)
+
+    ### Lower-level APIs ###
+
+    def fileno(self):
+        return self.raw.fileno()
+
+    def isatty(self):
+        return self.raw.isatty()
+
+
+class BytesIO(_BufferedIOBase):
+
+    """Buffered I/O implementation using an in-memory bytes buffer."""
+
+    def __init__(self, initial_bytes=None):
+        buf = bytearray()
+        if initial_bytes is not None:
+            buf.extend(initial_bytes)
+        self._buffer = buf
+        self._pos = 0
+
+    # Jython: modelled after bytesio.c::bytesio_getstate
+    def __getstate__(self):
+        d = getattr(self, '__dict__', None)
+        if d is not None :
+            d = d.copy()
+        return (self.getvalue(), self._pos, d)
+
+    # Jython: modelled after bytesio.c::bytesio_setstate
+    def __setstate__(self, state):
+
+        if not isinstance(state, tuple) or len(state) < 3 :
+            fmt = "%s.__setstate__ argument should be 3-tuple got %s"
+            raise TypeError( fmt % (type(self), type(state)) )
+
+        # Reset the object to its default state. This is only needed to handle
+        # the case of repeated calls to __setstate__. */
+        self._buffer = bytearray()
+        self._pos = 0
+
+        # Set the value of the internal buffer. If state[0] does not support the
+        # buffer protocol, bytesio_write will raise the appropriate TypeError. */
+        self.write(state[0]);
+
+        # Carefully set the position value. Alternatively, we could use the seek
+        # method instead of modifying self._pos directly to better protect the
+        # object internal state against erroneous (or malicious) inputs. */
+        p = state[1]
+        if not isinstance(p, (int, long)) :
+            fmt = "second item of state must be an integer, got %s"
+            raise TypeError( fmt % type(p) )
+        elif p < 0 :
+            raise ValueError("position value cannot be negative")
+        self._pos = p
+
+        # Set the dictionary of the instance variables. */
+        d = state[2]
+        if not d is None :
+            if isinstance(d, dict) :
+                self.__dict__ = d
+            else :
+                fmt = "third item of state should be a dict, got %s"
+                raise TypeError( fmt % type(d) )
+
+    def getvalue(self):
+        """Return the bytes value (contents) of the buffer
+        """
+        if self.closed:
+            raise ValueError("getvalue on closed file")
+        return bytes(self._buffer)
+
+    def read(self, n=None):
+        if self.closed:
+            raise ValueError("read from closed file")
+        if n is None:
+            n = -1
+        if not isinstance(n, (int, long)):
+            raise TypeError("integer argument expected, got {0!r}".format(
+                type(n)))
+        if n < 0:
+            n = len(self._buffer)
+        if len(self._buffer) <= self._pos:
+            return b""
+        newpos = min(len(self._buffer), self._pos + n)
+        b = self._buffer[self._pos : newpos]
+        self._pos = newpos
+        return bytes(b)
+
+    def read1(self, n):
+        """This is the same as read.
+        """
+        return self.read(n)
+
+    def write(self, b):
+        if self.closed:
+            raise ValueError("write to closed file")
+        if isinstance(b, unicode):
+            raise TypeError("can't write unicode to binary stream")
+        n = len(b)
+        if n == 0:
+            return 0
+        pos = self._pos
+        if pos > len(self._buffer):
+            # Inserts null bytes between the current end of the file
+            # and the new write position.
+            padding = b'\x00' * (pos - len(self._buffer))
+            self._buffer += padding
+        self._buffer[pos:pos + n] = b
+        self._pos += n
+        return n
+
+    def seek(self, pos, whence=0):
+        if self.closed:
+            raise ValueError("seek on closed file")
+        try:
+            pos.__index__
+        except AttributeError:
+            raise TypeError("an integer is required")
+        if whence == 0:
+            if pos < 0:
+                raise ValueError("negative seek position %r" % (pos,))
+            self._pos = pos
+        elif whence == 1:
+            self._pos = max(0, self._pos + pos)
+        elif whence == 2:
+            self._pos = max(0, len(self._buffer) + pos)
+        else:
+            raise ValueError("invalid whence value")
+        return self._pos
+
+    def tell(self):
+        if self.closed:
+            raise ValueError("tell on closed file")
+        return self._pos
+
+    def truncate(self, pos=None):
+        if self.closed:
+            raise ValueError("truncate on closed file")
+        if pos is None:
+            pos = self._pos
+        else:
+            try:
+                pos.__index__
+            except AttributeError:
+                raise TypeError("an integer is required")
+            if pos < 0:
+                raise ValueError("negative truncate position %r" % (pos,))
+        del self._buffer[pos:]
+        return pos
+
+    def readable(self):
+        self._checkClosed()
+        return True
+
+    def writable(self):
+        self._checkClosed()
+        return True
+
+    def seekable(self):
+        self._checkClosed()
+        return True
+
+
+class BufferedReader(_BufferedIOMixin):
+
+    """BufferedReader(raw[, buffer_size])
+
+    A buffer for a readable, sequential BaseRawIO object.
+
+    The constructor creates a BufferedReader for the given readable raw
+    stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE
+    is used.
+    """
+
+    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
+        """Create a new buffered reader using the given readable raw IO object.
+        """
+        if not raw.readable():
+            raise IOError('"raw" argument must be readable.')
+
+        _BufferedIOMixin.__init__(self, raw)
+        if buffer_size <= 0:
+            raise ValueError("invalid buffer size")
+        self.buffer_size = buffer_size
+        self._reset_read_buf()
+        self._read_lock = Lock()
+        self._ok = True     # Jython: to enable use now in a valid state
+
+    def _reset_read_buf(self):
+        self._read_buf = b""
+        self._read_pos = 0
+
+    def read(self, n=None):
+        """Read n bytes.
+
+        Returns exactly n bytes of data unless the underlying raw IO
+        stream reaches EOF or if the call would block in non-blocking
+        mode. If n is negative, read until EOF or until read() would
+        block.
+        """
+        self._checkReadable()       # Jython: to forbid use in an invalid state
+        if n is not None and n < -1:
+            raise ValueError("invalid number of bytes to read")
+        with self._read_lock:
+            return self._read_unlocked(n)
+
+    def _read_unlocked(self, n=None):
+        nodata_val = b""
+        empty_values = (b"", None)
+        buf = self._read_buf
+        pos = self._read_pos
+
+        # Special case for when the number of bytes to read is unspecified.
+        if n is None or n == -1:
+            self._reset_read_buf()
+            chunks = [buf[pos:]]  # Strip the consumed bytes.
+            current_size = 0
+            while True:
+                # Read until EOF or until read() would block.
+                try:
+                    chunk = self.raw.read()
+                except IOError as e:
+                    if e.errno != EINTR:
+                        raise
+                    continue
+                if chunk in empty_values:
+                    nodata_val = chunk
+                    break
+                current_size += len(chunk)
+                chunks.append(chunk)
+            return b"".join(chunks) or nodata_val
+
+        # The number of bytes to read is specified, return at most n bytes.
+        avail = len(buf) - pos  # Length of the available buffered data.
+        if n <= avail:
+            # Fast path: the data to read is fully buffered.
+            self._read_pos += n
+            return buf[pos:pos+n]
+        # Slow path: read from the stream until enough bytes are read,
+        # or until an EOF occurs or until read() would block.
+        chunks = [buf[pos:]]
+        wanted = max(self.buffer_size, n)
+        while avail < n:
+            try:
+                chunk = self.raw.read(wanted)
+            except IOError as e:
+                if e.errno != EINTR:
+                    raise
+                continue
+            if chunk in empty_values:
+                nodata_val = chunk
+                break
+            avail += len(chunk)
+            chunks.append(chunk)
+        # n is more then avail only when an EOF occurred or when
+        # read() would have blocked.
+        n = min(n, avail)
+        out = b"".join(chunks)
+        self._read_buf = out[n:]  # Save the extra data in the buffer.
+        self._read_pos = 0
+        return out[:n] if out else nodata_val
+
+    def peek(self, n=0):
+        """Returns buffered bytes without advancing the position.
+
+        The argument indicates a desired minimal number of bytes; we
+        do at most one raw read to satisfy it.  We never return more
+        than self.buffer_size.
+        """
+        with self._read_lock:
+            return self._peek_unlocked(n)
+
+    def _peek_unlocked(self, n=0):
+        want = min(n, self.buffer_size)
+        have = len(self._read_buf) - self._read_pos
+        if have < want or have <= 0:
+            to_read = self.buffer_size - have
+            while True:
+                try:
+                    current = self.raw.read(to_read)
+                except IOError as e:
+                    if e.errno != EINTR:
+                        raise
+                    continue
+                break
+            if current:
+                self._read_buf = self._read_buf[self._read_pos:] + current
+                self._read_pos = 0
+        return self._read_buf[self._read_pos:]
+
+    def read1(self, n):
+        """Reads up to n bytes, with at most one read() system call."""
+        # Returns up to n bytes.  If at least one byte is buffered, we
+        # only return buffered bytes.  Otherwise, we do one raw read.
+        self._checkReadable()       # Jython: to forbid use in an invalid state
+        if n < 0:
+            raise ValueError("number of bytes to read must be positive")
+        if n == 0:
+            return b""
+        with self._read_lock:
+            self._peek_unlocked(1)
+            return self._read_unlocked(
+                min(n, len(self._read_buf) - self._read_pos))
+
+    def tell(self):
+        return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos
+
+    def seek(self, pos, whence=0):
+        if not (0 <= whence <= 2):
+            raise ValueError("invalid whence value")
+        with self._read_lock:
+            if whence == 1:
+                pos -= len(self._read_buf) - self._read_pos
+            pos = _BufferedIOMixin.seek(self, pos, whence)
+            self._reset_read_buf()
+            return pos
+
+
+class BufferedWriter(_BufferedIOMixin):
+
+    """A buffer for a writeable sequential RawIO object.
+
+    The constructor creates a BufferedWriter for the given writeable raw
+    stream. If the buffer_size is not given, it defaults to
+    DEFAULT_BUFFER_SIZE.
+    """
+
+    _warning_stack_offset = 2
+
+    def __init__(self, raw,
+                 buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None):
+        if not raw.writable():
+            raise IOError('"raw" argument must be writable.')
+
+        _BufferedIOMixin.__init__(self, raw)
+        if buffer_size <= 0:
+            raise ValueError("invalid buffer size")
+        if max_buffer_size is not None:
+            warnings.warn("max_buffer_size is deprecated", DeprecationWarning,
+                          self._warning_stack_offset)
+        self.buffer_size = buffer_size
+        self._write_buf = bytearray()
+        self._write_lock = Lock()
+        self._ok = True     # Jython: to enable use now in a valid state
+
+    def write(self, b):
+        self._checkWritable()       # Jython: to forbid use in an invalid state
+        if self.closed:
+            raise ValueError("write to closed file")
+        if isinstance(b, unicode):
+            raise TypeError("can't write unicode to binary stream")
+        with self._write_lock:
+            # XXX we can implement some more tricks to try and avoid
+            # partial writes
+            if len(self._write_buf) > self.buffer_size:
+                # We're full, so let's pre-flush the buffer.  (This may
+                # raise BlockingIOError with characters_written == 0.)
+                self._flush_unlocked()
+            before = len(self._write_buf)
+            if isinstance(b, array.array):              # _pyio.py version fails on array.array
+                self._write_buf.extend(b.tostring())    # Jython version works (while needed)
+            else:
+                self._write_buf.extend(b)
+            written = len(self._write_buf) - before
+            if len(self._write_buf) > self.buffer_size:
+                try:
+                    self._flush_unlocked()
+                except BlockingIOError as e:
+                    if len(self._write_buf) > self.buffer_size:
+                        # We've hit the buffer_size. We have to accept a partial
+                        # write and cut back our buffer.
+                        overage = len(self._write_buf) - self.buffer_size
+                        written -= overage
+                        self._write_buf = self._write_buf[:self.buffer_size]
+                        raise BlockingIOError(e.errno, e.strerror, written)
+            return written
+
+    def truncate(self, pos=None):
+        with self._write_lock:
+            self._flush_unlocked()
+            if pos is None:
+                pos = self.raw.tell()
+            return self.raw.truncate(pos)
+
+    def flush(self):
+        with self._write_lock:
+            self._flush_unlocked()
+
+    def _flush_unlocked(self):
+        if self.closed:
+            raise ValueError("flush of closed file")
+        self._checkWritable()       # Jython: to forbid use in an invalid state
+        while self._write_buf:
+            try:
+                n = self.raw.write(self._write_buf)
+            except BlockingIOError:
+                raise RuntimeError("self.raw should implement _RawIOBase: it "
+                                   "should not raise BlockingIOError")
+            except IOError as e:
+                if e.errno != EINTR:
+                    raise
+                continue
+            if n is None:
+                raise BlockingIOError(
+                    errno.EAGAIN,
+                    "write could not complete without blocking", 0)
+            if n > len(self._write_buf) or n < 0:
+                raise IOError("write() returned incorrect number of bytes")
+            del self._write_buf[:n]
+
+    def tell(self):
+        return _BufferedIOMixin.tell(self) + len(self._write_buf)
+
+    def seek(self, pos, whence=0):
+        if not (0 <= whence <= 2):
+            raise ValueError("invalid whence")
+        with self._write_lock:
+            self._flush_unlocked()
+            return _BufferedIOMixin.seek(self, pos, whence)
+
+
+class BufferedRWPair(_BufferedIOBase):
+
+    """A buffered reader and writer object together.
+
+    A buffered reader object and buffered writer object put together to
+    form a sequential IO object that can read and write. This is typically
+    used with a socket or two-way pipe.
+
+    reader and writer are _RawIOBase objects that are readable and
+    writeable respectively. If the buffer_size is omitted it defaults to
+    DEFAULT_BUFFER_SIZE.
+    """
+
+    # XXX The usefulness of this (compared to having two separate IO
+    # objects) is questionable.
+
+    def __init__(self, reader, writer,
+                 buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None):
+        """Constructor.
+
+        The arguments are two RawIO instances.
+        """
+        if max_buffer_size is not None:
+            warnings.warn("max_buffer_size is deprecated", DeprecationWarning, 2)
+
+        if not reader.readable():
+            raise IOError('"reader" argument must be readable.')
+
+        if not writer.writable():
+            raise IOError('"writer" argument must be writable.')
+
+        self.reader = BufferedReader(reader, buffer_size)
+        self.writer = BufferedWriter(writer, buffer_size)
+
+    def read(self, n=None):
+        if n is None:
+            n = -1
+        return self.reader.read(n)
+
+    def readinto(self, b):
+        return self.reader.readinto(b)
+
+    def write(self, b):
+        return self.writer.write(b)
+
+    def peek(self, n=0):
+        return self.reader.peek(n)
+
+    def read1(self, n):
+        return self.reader.read1(n)
+
+    def readable(self):
+        return self.reader.readable()
+
+    def writable(self):
+        return self.writer.writable()
+
+    def flush(self):
+        return self.writer.flush()
+
+    def close(self):
+        self.writer.close()
+        self.reader.close()
+
+    def isatty(self):
+        return self.reader.isatty() or self.writer.isatty()
+
+    @property
+    def closed(self):
+        return self.writer.closed
+
+
+class BufferedRandom(BufferedWriter, BufferedReader):
+
+    """A buffered interface to random access streams.
+
+    The constructor creates a reader and writer for a seekable stream,
+    raw, given in the first argument. If the buffer_size is omitted it
+    defaults to DEFAULT_BUFFER_SIZE.
+    """
+
+    _warning_stack_offset = 3
+
+    def __init__(self, raw,
+                 buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None):
+        raw._checkSeekable()
+        BufferedReader.__init__(self, raw, buffer_size)
+        BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size)
+
+    def seek(self, pos, whence=0):
+        if not (0 <= whence <= 2):
+            raise ValueError("invalid whence")
+        self.flush()
+        if self._read_buf:
+            # Undo read ahead.
+            with self._read_lock:
+                self.raw.seek(self._read_pos - len(self._read_buf), 1)
+        # First do the raw seek, then empty the read buffer, so that
+        # if the raw seek fails, we don't lose buffered data forever.
+        pos = self.raw.seek(pos, whence)
+        with self._read_lock:
+            self._reset_read_buf()
+        if pos < 0:
+            raise IOError("seek() returned invalid position")
+        return pos
+
+    def tell(self):
+        if self._write_buf:
+            return BufferedWriter.tell(self)
+        else:
+            return BufferedReader.tell(self)
+
+    def truncate(self, pos=None):
+        if pos is None:
+            pos = self.tell()
+        # Use seek to flush the read buffer.
+        return BufferedWriter.truncate(self, pos)
+
+    def read(self, n=None):
+        if n is None:
+            n = -1
+        self.flush()
+        return BufferedReader.read(self, n)
+
+    def readinto(self, b):
+        self.flush()
+        return BufferedReader.readinto(self, b)
+
+    def peek(self, n=0):
+        self.flush()
+        return BufferedReader.peek(self, n)
+
+    def read1(self, n):
+        self.flush()
+        return BufferedReader.read1(self, n)
+
+    def write(self, b):
+        if self._read_buf:
+            # Undo readahead
+            with self._read_lock:
+                self.raw.seek(self._read_pos - len(self._read_buf), 1)
+                self._reset_read_buf()
+        return BufferedWriter.write(self, b)
+
+
+class _TextIOBase(_IOBase):
+
+    """Base class for text I/O.
+
+    This class provides a character and line based interface to stream
+    I/O. There is no readinto method because Python's character strings
+    are immutable. There is no public constructor.
+    """
+
+    def read(self, n=-1):
+        """Read at most n characters from stream.
+
+        Read from underlying buffer until we have n characters or we hit EOF.
+        If n is negative or omitted, read until EOF.
+        """
+        self._unsupported("read")
+
+    def write(self, s):
+        """Write string s to stream."""
+        self._unsupported("write")
+
+    def truncate(self, pos=None):
+        """Truncate size to pos."""
+        self._unsupported("truncate")
+
+    def readline(self):
+        """Read until newline or EOF.
+
+        Returns an empty string if EOF is hit immediately.
+        """
+        self._unsupported("readline")
+
+    def detach(self):
+        """
+        Separate the underlying buffer from the _TextIOBase and return it.
+
+        After the underlying buffer has been detached, the TextIO is in an
+        unusable state.
+        """
+        self._unsupported("detach")
+
+    @property
+    def encoding(self):
+        """Subclasses should override."""
+        return None
+
+    @property
+    def newlines(self):
+        """Line endings translated so far.
+
+        Only line endings translated during reading are considered.
+
+        Subclasses should override.
+        """
+        return None
+
+    @property
+    def errors(self):
+        """Error setting of the decoder or encoder.
+
+        Subclasses should override."""
+        return None
+
+
+class IncrementalNewlineDecoder(codecs.IncrementalDecoder):
+    r"""Codec used when reading a file in universal newlines mode.  It wraps
+    another incremental decoder, translating \r\n and \r into \n.  It also
+    records the types of newlines encountered.  When used with
+    translate=False, it ensures that the newline sequence is returned in
+    one piece.
+    """
+    def __init__(self, decoder, translate, errors='strict'):
+        codecs.IncrementalDecoder.__init__(self, errors=errors)
+        self.translate = translate
+        self.decoder = decoder
+        self.seennl = 0
+        self.pendingcr = False
+
+    def decode(self, input, final=False):
+        # decode input (with the eventual \r from a previous pass)
+        if self.decoder is None:
+            output = input
+        else:
+            output = self.decoder.decode(input, final=final)
+        if self.pendingcr and (output or final):
+            output = "\r" + output
+            self.pendingcr = False
+
+        # retain last \r even when not translating data:
+        # then readline() is sure to get \r\n in one pass
+        if output.endswith("\r") and not final:
+            output = output[:-1]
+            self.pendingcr = True
+
+        # Record which newlines are read
+        crlf = output.count('\r\n')
+        cr = output.count('\r') - crlf
+        lf = output.count('\n') - crlf
+        self.seennl |= (lf and self._LF) | (cr and self._CR) \
+                    | (crlf and self._CRLF)
+
+        if self.translate:
+            if crlf:
+                output = output.replace("\r\n", "\n")
+            if cr:
+                output = output.replace("\r", "\n")
+
+        return output
+
+    def getstate(self):
+        if self.decoder is None:
+            buf = b""
+            flag = 0
+        else:
+            buf, flag = self.decoder.getstate()
+        flag <<= 1
+        if self.pendingcr:
+            flag |= 1
+        return buf, flag
+
+    def setstate(self, state):
+        buf, flag = state
+        self.pendingcr = bool(flag & 1)
+        if self.decoder is not None:
+            self.decoder.setstate((buf, flag >> 1))
+
+    def reset(self):
+        self.seennl = 0
+        self.pendingcr = False
+        if self.decoder is not None:
+            self.decoder.reset()
+
+    _LF = 1
+    _CR = 2
+    _CRLF = 4
+
+    @property
+    def newlines(self):
+        return (None,
+                "\n",
+                "\r",
+                ("\r", "\n"),
+                "\r\n",
+                ("\n", "\r\n"),
+                ("\r", "\r\n"),
+                ("\r", "\n", "\r\n")
+               )[self.seennl]
+
+
+def _check_decoded_chars(chars):
+    """Check decoder output is unicode"""
+    if not isinstance(chars, unicode):
+        raise TypeError("decoder should return a string result, not '%s'" %
+                        type(chars))
+
+def _check_buffered_bytes(b, context="read"):
+    """Check buffer has returned bytes"""
+    if not isinstance(b, str):
+        raise TypeError("underlying %s() should have returned a bytes object, not '%s'" %
+                        (context, type(b)))
+
+
+
+class TextIOWrapper(_TextIOBase):
+
+    r"""Character and line based layer over a _BufferedIOBase object, buffer.
+
+    encoding gives the name of the encoding that the stream will be
+    decoded or encoded with. It defaults to locale.getpreferredencoding.
+
+    errors determines the strictness of encoding and decoding (see the
+    codecs.register) and defaults to "strict".
+
+    newline can be None, '', '\n', '\r', or '\r\n'.  It controls the
+    handling of line endings. If it is None, universal newlines is
+    enabled.  With this enabled, on input, the lines endings '\n', '\r',
+    or '\r\n' are translated to '\n' before being returned to the
+    caller. Conversely, on output, '\n' is translated to the system
+    default line separator, os.linesep. If newline is any other of its
+    legal values, that newline becomes the newline when the file is read
+    and it is returned untranslated. On output, '\n' is converted to the
+    newline.
+
+    If line_buffering is True, a call to flush is implied when a call to
+    write contains a newline character.
+    """
+
+    _CHUNK_SIZE = 2048
+
+    def __init__(self, buffer, encoding=None, errors=None, newline=None,
+                 line_buffering=False):
+        self._ok = False    # Jython: to forbid use in an invalid state
+        if newline is not None and not isinstance(newline, basestring):
+            raise TypeError("illegal newline type: %r" % (type(newline),))
+        if newline not in (None, "", "\n", "\r", "\r\n"):
+            raise ValueError("illegal newline value: %r" % (newline,))
+        if encoding is None:
+            try:
+                import locale
+            except ImportError:
+                # Importing locale may fail if Python is being built
+                encoding = "ascii"
+            else:
+                encoding = locale.getpreferredencoding()
+
+        if not isinstance(encoding, basestring):
+            raise ValueError("invalid encoding: %r" % encoding)
+
+        if errors is None:
+            errors = "strict"
+        else:
+            if not isinstance(errors, basestring):
+                raise ValueError("invalid errors: %r" % errors)
+
+        self._buffer = buffer
+        self._line_buffering = line_buffering
+        self._encoding = encoding
+        self._errors = errors
+        self._readuniversal = not newline
+        self._readtranslate = newline is None
+        self._readnl = newline
+        self._writetranslate = newline != ''
+        self._writenl = newline or os.linesep
+        self._encoder = None
+        self._decoder = None
+        self._decoded_chars = ''  # buffer for text returned from decoder
+        self._decoded_chars_used = 0  # offset into _decoded_chars for read()
+        self._snapshot = None  # info for reconstructing decoder state
+        self._seekable = self._telling = self.buffer.seekable()
+
+        self._ok = True     # Jython: to enable use now in a valid state
+
+        if self._seekable and self.writable():
+            position = self.buffer.tell()
+            if position != 0:
+                try:
+                    self._get_encoder().setstate(0)
+                except LookupError:
+                    # Sometimes the encoder doesn't exist
+                    pass
+
+    # self._snapshot is either None, or a tuple (dec_flags, next_input)
+    # where dec_flags is the second (integer) item of the decoder state
+    # and next_input is the chunk of input bytes that comes next after the
+    # snapshot point.  We use this to reconstruct decoder states in tell().
+
+    # Naming convention:
+    #   - "bytes_..." for integer variables that count input bytes
+    #   - "chars_..." for integer variables that count decoded characters
+
+    def __repr__(self):
+        try:
+            name = self.name
+        except AttributeError:
+            return "<_jyio.TextIOWrapper encoding='{0}'>".format(self.encoding)
+        else:
+            return "<_jyio.TextIOWrapper name={0!r} encoding='{1}'>".format(
+                name, self.encoding)
+
+    @property
+    def encoding(self):
+        return self._encoding
+
+    @property
+    def errors(self):
+        return self._errors
+
+    @property
+    def line_buffering(self):
+        return self._line_buffering
+
+    @property
+    def buffer(self):
+        return self._buffer
+
+    def seekable(self):
+        self._checkInitialized()    # Jython: to forbid use in an invalid state
+        self._checkClosed()
+        return self._seekable
+
+    def readable(self):
+        self._checkInitialized()    # Jython: to forbid use in an invalid state
+        return self.buffer.readable()
+
+    def writable(self):
+        self._checkInitialized()    # Jython: to forbid use in an invalid state
+        return self.buffer.writable()
+
+    def flush(self):
+        self._checkInitialized()    # Jython: to forbid use in an invalid state
+        self.buffer.flush()
+        self._telling = self._seekable
+
+    def close(self):
+        if self.buffer is not None and not self.closed:
+            try:
+                # Jython difference: flush and close via super.
+                # Sets __closed for quick _checkClosed().
+                super(TextIOWrapper, self).close()
+            finally:
+                self.buffer.close()
+
+    @property
+    def closed(self):
+        return self.buffer.closed
+
+    # Jython difference: emulate C implementation CHECK_INITIALIZED. This is for
+    # compatibility, to pass test.test_io.CTextIOWrapperTest.test_initialization.
+    def _checkInitialized(self):
+        if not self._ok:
+            if self.buffer is None:
+                raise ValueError("underlying buffer has been detached")
+            else:
+                raise ValueError("I/O operation on uninitialized object")
+
+    @property
+    def name(self):
+        return self.buffer.name
+
+    def fileno(self):
+        return self.buffer.fileno()
+
+    def isatty(self):
+        return self.buffer.isatty()
+
+    def write(self, s):
+        self._checkWritable()       # Jython: to forbid use in an invalid state
+        if self.closed:
+            raise ValueError("write to closed file")
+        if not isinstance(s, unicode):
+            raise TypeError("can't write %s to text stream" %
+                            s.__class__.__name__)
+        length = len(s)
+        haslf = (self._writetranslate or self._line_buffering) and "\n" in s
+        if haslf and self._writetranslate and self._writenl != "\n":
+            s = s.replace("\n", self._writenl)
+        encoder = self._encoder or self._get_encoder()
+        # XXX What if we were just reading?
+        b = encoder.encode(s)
+        self.buffer.write(b)
+        if self._line_buffering and (haslf or "\r" in s):
+            self.flush()
+        self._snapshot = None
+        if self._decoder:
+            self._decoder.reset()
+        return length
+
+    def _get_encoder(self):
+        make_encoder = codecs.getincrementalencoder(self._encoding)
+        self._encoder = make_encoder(self._errors)
+        return self._encoder
+
+    def _get_decoder(self):
+        make_decoder = codecs.getincrementaldecoder(self._encoding)
+        decoder = make_decoder(self._errors)
+        if self._readuniversal:
+            decoder = IncrementalNewlineDecoder(decoder, self._readtranslate)
+        self._decoder = decoder
+        return decoder
+
+    # The following three methods implement an ADT for _decoded_chars.
+    # Text returned from the decoder is buffered here until the client
+    # requests it by calling our read() or readline() method.
+    def _set_decoded_chars(self, chars):
+        """Set the _decoded_chars buffer."""
+        self._decoded_chars = chars
+        self._decoded_chars_used = 0
+
+    def _get_decoded_chars(self, n=None):
+        """Advance into the _decoded_chars buffer."""
+        offset = self._decoded_chars_used
+        if n is None:
+            chars = self._decoded_chars[offset:]
+        else:
+            chars = self._decoded_chars[offset:offset + n]
+        self._decoded_chars_used += len(chars)
+        return chars
+
+    def _rewind_decoded_chars(self, n):
+        """Rewind the _decoded_chars buffer."""
+        if self._decoded_chars_used < n:
+            raise AssertionError("rewind decoded_chars out of bounds")
+        self._decoded_chars_used -= n
+
+    def _read_chunk(self):
+        """
+        Read and decode the next chunk of data from the BufferedReader.
+        """
+
+        # The return value is True unless EOF was reached.  The decoded
+        # string is placed in self._decoded_chars (replacing its previous
+        # value).  The entire input chunk is sent to the decoder, though
+        # some of it may remain buffered in the decoder, yet to be
+        # converted.
+
+        if self._decoder is None:
+            raise ValueError("no decoder")
+
+        if self._telling:
+            # To prepare for tell(), we need to snapshot a point in the
+            # file where the decoder's input buffer is empty.
+
+            dec_buffer, dec_flags = self._decoder.getstate()
+            # Given this, we know there was a valid snapshot point
+            # len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
+
+        # Read a chunk, decode it, and put the result in self._decoded_chars.
+        input_chunk = self.buffer.read1(self._CHUNK_SIZE)
+        _check_buffered_bytes(input_chunk, "read1")
+
+        eof = not input_chunk
+        decoded_chunk = self._decoder.decode(input_chunk, eof)
+        _check_decoded_chars(decoded_chunk)
+        self._set_decoded_chars(decoded_chunk)
+
+        if self._telling:
+            # At the snapshot point, len(dec_buffer) bytes before the read,
+            # the next input to be decoded is dec_buffer + input_chunk.
+            self._snapshot = (dec_flags, dec_buffer + input_chunk)
+
+        return not eof
+
+    def _pack_cookie(self, position, dec_flags=0,
+                           bytes_to_feed=0, need_eof=0, chars_to_skip=0):
+        # The meaning of a tell() cookie is: seek to position, set the
+        # decoder flags to dec_flags, read bytes_to_feed bytes, feed them
+        # into the decoder with need_eof as the EOF flag, then skip
+        # chars_to_skip characters of the decoded result.  For most simple
+        # decoders, tell() will often just give a byte offset in the file.
+        return (position | (dec_flags<<64) | (bytes_to_feed<<128) |
+               (chars_to_skip<<192) | bool(need_eof)<<256)
+
+    def _unpack_cookie(self, bigint):
+        rest, position = divmod(bigint, 1<<64)
+        rest, dec_flags = divmod(rest, 1<<64)
+        rest, bytes_to_feed = divmod(rest, 1<<64)
+        need_eof, chars_to_skip = divmod(rest, 1<<64)
+        return position, dec_flags, bytes_to_feed, need_eof, chars_to_skip
+
+    def tell(self):
+        if not self._seekable:
+            raise IOError("underlying stream is not seekable")
+        if not self._telling:
+            raise IOError("telling position disabled by next() call")
+        self.flush()
+        position = self.buffer.tell()
+        decoder = self._decoder
+        if decoder is None or self._snapshot is None:
+            if self._decoded_chars:
+                # This should never happen.
+                raise AssertionError("pending decoded text")
+            return position
+
+        # Skip backward to the snapshot point (see _read_chunk).
+        dec_flags, next_input = self._snapshot
+        position -= len(next_input)
+
+        # How many decoded characters have been used up since the snapshot?
+        chars_to_skip = self._decoded_chars_used
+        if chars_to_skip == 0:
+            # We haven't moved from the snapshot point.
+            return self._pack_cookie(position, dec_flags)
+
+        # Starting from the snapshot position, we will walk the decoder
+        # forward until it gives us enough decoded characters.
+        saved_state = decoder.getstate()
+        try:
+            # Note our initial start point.
+            decoder.setstate((b'', dec_flags))
+            start_pos = position
+            start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0
+            need_eof = 0
+
+            # Feed the decoder one byte at a time.  As we go, note the
+            # nearest "safe start point" before the current location
+            # (a point where the decoder has nothing buffered, so seek()
+            # can safely start from there and advance to this location).
+            for next_byte in next_input:
+                bytes_fed += 1
+                chars_decoded += len(decoder.decode(next_byte))
+                dec_buffer, dec_flags = decoder.getstate()
+                if not dec_buffer and chars_decoded <= chars_to_skip:
+                    # Decoder buffer is empty, so this is a safe start point.
+                    start_pos += bytes_fed
+                    chars_to_skip -= chars_decoded
+                    start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0
+                if chars_decoded >= chars_to_skip:
+                    break
+            else:
+                # We didn't get enough decoded data; signal EOF to get more.
+                chars_decoded += len(decoder.decode(b'', final=True))
+                need_eof = 1
+                if chars_decoded < chars_to_skip:
+                    raise IOError("can't reconstruct logical file position")
+
+            # The returned cookie corresponds to the last safe start point.
+            return self._pack_cookie(
+                start_pos, start_flags, bytes_fed, need_eof, chars_to_skip)
+        finally:
+            decoder.setstate(saved_state)
+
+    def truncate(self, pos=None):
+        self.flush()
+        if pos is None:
+            pos = self.tell()
+        return self.buffer.truncate(pos)
+
+    def detach(self):
+        if self.buffer is None:
+            raise ValueError("buffer is already detached")
+        self.flush()
+        self._ok = False    # Jython: to forbid use in an invalid state
+        buffer = self._buffer
+        self._buffer = None
+        return buffer
+
+    def seek(self, cookie, whence=0):
+        if self.closed:
+            raise ValueError("tell on closed file")
+        if not self._seekable:
+            raise IOError("underlying stream is not seekable")
+        if whence == 1: # seek relative to current position
+            if cookie != 0:
+                raise IOError("can't do nonzero cur-relative seeks")
+            # Seeking to the current position should attempt to
+            # sync the underlying buffer with the current position.
+            whence = 0
+            cookie = self.tell()
+        if whence == 2: # seek relative to end of file
+            if cookie != 0:
+                raise IOError("can't do nonzero end-relative seeks")
+            self.flush()
+            position = self.buffer.seek(0, 2)
+            self._set_decoded_chars('')
+            self._snapshot = None
+            if self._decoder:
+                self._decoder.reset()
+            return position
+        if whence != 0:
+            raise ValueError("invalid whence (%r, should be 0, 1 or 2)" %
+                             (whence,))
+        if cookie < 0:
+            raise ValueError("negative seek position %r" % (cookie,))
+        self.flush()
+
+        # The strategy of seek() is to go back to the safe start point
+        # and replay the effect of read(chars_to_skip) from there.
+        start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \
+            self._unpack_cookie(cookie)
+
+        # Seek back to the safe start point.
+        self.buffer.seek(start_pos)
+        self._set_decoded_chars('')
+        self._snapshot = None
+
+        # Restore the decoder to its state from the safe start point.
+        if cookie == 0 and self._decoder:
+            self._decoder.reset()
+        elif self._decoder or dec_flags or chars_to_skip:
+            self._decoder = self._decoder or self._get_decoder()
+            self._decoder.setstate((b'', dec_flags))
+            self._snapshot = (dec_flags, b'')
+
+        if chars_to_skip:
+            # Just like _read_chunk, feed the decoder and save a snapshot.
+            input_chunk = self.buffer.read(bytes_to_feed)
+            _check_buffered_bytes(input_chunk)
+            decoded_chunk = self._decoder.decode(input_chunk, need_eof)
+            _check_decoded_chars(decoded_chunk)
+            self._set_decoded_chars(decoded_chunk)
+
+            self._snapshot = (dec_flags, input_chunk)
+
+            # Skip chars_to_skip of the decoded characters.
+            if len(self._decoded_chars) < chars_to_skip:
+                raise IOError("can't restore logical file position")
+            self._decoded_chars_used = chars_to_skip
+
+        # Finally, reset the encoder (merely useful for proper BOM handling)
+        try:
+            encoder = self._encoder or self._get_encoder()
+        except LookupError:
+            # Sometimes the encoder doesn't exist
+            pass
+        else:
+            if cookie != 0:
+                encoder.setstate(0)
+            else:
+                encoder.reset()
+        return cookie
+
+    def read(self, n=None):
+        self._checkReadable()
+        if n is None:
+            n = -1
+        decoder = self._decoder or self._get_decoder()
+        try:
+            n.__index__
+        except AttributeError:
+            raise TypeError("an integer is required")
+        if n < 0:
+            # Read everything.
+            input_chunk = self.buffer.read()
+            # Jython difference: CPython textio.c omits:
+            _check_buffered_bytes(input_chunk)
+            decoded_chunk = decoder.decode(input_chunk, final=True)
+            _check_decoded_chars(decoded_chunk)
+            result = self._get_decoded_chars() + decoded_chunk
+            self._set_decoded_chars('')
+            self._snapshot = None
+            return result
+        else:
+            # Keep reading chunks until we have n characters to return.
+            eof = False
+            result = self._get_decoded_chars(n)
+            while len(result) < n and not eof:
+                eof = not self._read_chunk()
+                result += self._get_decoded_chars(n - len(result))
+            return result
+
+    def next(self):
+        self._telling = False
+        line = self.readline()
+        if not line:
+            self._snapshot = None
+            self._telling = self._seekable
+            raise StopIteration
+        return line
+
+    def readline(self, limit=None):
+        if self.closed:
+            raise ValueError("read from closed file")
+        if limit is None:
+            limit = -1
+        elif not isinstance(limit, (int, long)):
+            raise TypeError("limit must be an integer")
+
+        # Grab all the decoded text (we will rewind any extra bits later).
+        line = self._get_decoded_chars()
+
+        start = 0
+        # Make the decoder if it doesn't already exist.
+        if not self._decoder:
+            self._get_decoder()
+
+        pos = endpos = None
+        while True:
+            if self._readtranslate:
+                # Newlines are already translated, only search for \n
+                pos = line.find('\n', start)
+                if pos >= 0:
+                    endpos = pos + 1
+                    break
+                else:
+                    start = len(line)
+
+            elif self._readuniversal:
+                # Universal newline search. Find any of \r, \r\n, \n
+                # The decoder ensures that \r\n are not split in two pieces
+
+                # In C we'd look for these in parallel of course.
+                nlpos = line.find("\n", start)
+                crpos = line.find("\r", start)
+                if crpos == -1:
+                    if nlpos == -1:
+                        # Nothing found
+                        start = len(line)
+                    else:
+                        # Found \n
+                        endpos = nlpos + 1
+                        break
+                elif nlpos == -1:
+                    # Found lone \r
+                    endpos = crpos + 1
+                    break
+                elif nlpos < crpos:
+                    # Found \n
+                    endpos = nlpos + 1
+                    break
+                elif nlpos == crpos + 1:
+                    # Found \r\n
+                    endpos = crpos + 2
+                    break
+                else:
+                    # Found \r
+                    endpos = crpos + 1
+                    break
+            else:
+                # non-universal
+                pos = line.find(self._readnl)
+                if pos >= 0:
+                    endpos = pos + len(self._readnl)
+                    break
+
+            if limit >= 0 and len(line) >= limit:
+                endpos = limit  # reached length limit
+                break
+
+            # No line ending seen yet - get more data'
+            while self._read_chunk():
+                if self._decoded_chars:
+                    break
+            if self._decoded_chars:
+                line += self._get_decoded_chars()
+            else:
+                # end of file
+                self._set_decoded_chars('')
+                self._snapshot = None
+                return line
+
+        if limit >= 0 and endpos > limit:
+            endpos = limit  # don't exceed limit
+
+        # Rewind _decoded_chars to just after the line ending we found.
+        self._rewind_decoded_chars(len(line) - endpos)
+        return line[:endpos]
+
+    @property
+    def newlines(self):
+        return self._decoder.newlines if self._decoder else None
+
+
+class StringIO(TextIOWrapper):
+    """Text I/O implementation using an in-memory buffer.
+
+    The initial_value argument sets the value of object.  The newline
+    argument is like the one of TextIOWrapper's constructor.
+    """
+
+    def __init__(self, initial_value="", newline="\n"):
+
+        # Newline mark needs to be in bytes: convert if not already so
+        if isinstance(newline, unicode) :
+            newline = newline.encode("utf-8")
+
+        super(StringIO, self).__init__(BytesIO(),
+                                       encoding="utf-8",
+                                       errors="strict",
+                                       newline=newline)
+        # Issue #5645: make universal newlines semantics the same as in the
+        # C version, even under Windows.
+        if newline is None:
+            self._writetranslate = False
+        # An initial value may have been supplied (and must be unicode)
+        if initial_value is not None:
+            if not isinstance(initial_value, unicode) :
+                fmt = "initial value should be unicode or None, got %s"
+                raise TypeError( fmt % type(initial_value) )
+            if initial_value:
+                self.write(initial_value)
+                self.seek(0)
+
+    # Jython: modelled after stringio.c::stringio_getstate
+    def __getstate__(self):
+        d = getattr(self, '__dict__', None)
+        if d is not None :
+            d = d.copy()
+        return (self.getvalue(), self._readnl, self.tell(), d)
+
+    # Jython: modelled after stringio.c:stringio_setstate
+    def __setstate__(self, state):
+        self._checkClosed()
+
+        if not isinstance(state, tuple) or len(state) < 4 :
+            fmt = "%s.__setstate__ argument should be 4-tuple got %s"
+            raise TypeError( fmt % (type(self), type(state)) )
+
+        # Initialize the object's state, but empty
+        self.__init__(None, state[1])
+
+        # Write the buffer, bypassing end-of-line translation.
+        value = state[0]
+        if value is not None:
+            if not isinstance(value, unicode) :
+                fmt = "ivalue should be unicode or None, got %s"
+                raise TypeError( fmt % type(value) )
+            encoder = self._encoder or self._get_encoder()
+            b = encoder.encode(state[0])
+            self.buffer.write(b)
+
+        # Reset the object to its default state. This is only needed to handle
+        # the case of repeated calls to __setstate__.
+        self.seek(0)
+
+        # Set the position value using seek. A long is tolerated (e.g from pickle).
+        p = state[2]
+        if not isinstance(p, (int, long)) :
+            fmt = "third item of state must be an integer, got %s"
+            raise TypeError( fmt % type(p) )
+        elif p < 0 :
+            raise ValueError("position value cannot be negative")
+        self.seek(p)
+
+        # Set the dictionary of the instance variables. */
+        d = state[3]
+        if not d is None :
+            if isinstance(d, dict) :
+                self.__dict__ = d
+            else :
+                fmt = "fourth item of state should be a dict, got %s"
+                raise TypeError( fmt % type(d) )
+
+    def getvalue(self):
+        self.flush()
+        return self.buffer.getvalue().decode(self._encoding, self._errors)
+
+    def __repr__(self):
+        # TextIOWrapper tells the encoding in its repr. In StringIO,
+        # that's a implementation detail.
+        return object.__repr__(self)
+
+    @property
+    def errors(self):
+        return None
+
+    @property
+    def encoding(self):
+        return None
+
+    def detach(self):
+        # This doesn't make sense on StringIO.
+        self._unsupported("detach")
diff --git a/src/main/resources/PythonLibs/_pyio.py b/src/main/resources/PythonLibs/_pyio.py
new file mode 100644
index 0000000000000000000000000000000000000000..ac7832e1bda34e8279ab3c99355fa3a747cd449c
--- /dev/null
+++ b/src/main/resources/PythonLibs/_pyio.py
@@ -0,0 +1,2017 @@
+"""
+Python implementation of the io module.
+"""
+
+from __future__ import (print_function, unicode_literals)
+
+import os
+import abc
+import codecs
+import warnings
+import errno
+# Import thread instead of threading to reduce startup cost
+try:
+    from thread import allocate_lock as Lock
+except ImportError:
+    from dummy_thread import allocate_lock as Lock
+
+import io
+from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)
+from errno import EINTR
+
+__metaclass__ = type
+
+# open() uses st_blksize whenever we can
+DEFAULT_BUFFER_SIZE = 8 * 1024  # bytes
+
+# NOTE: Base classes defined here are registered with the "official" ABCs
+# defined in io.py. We don't use real inheritance though, because we don't
+# want to inherit the C implementations.
+
+
+class BlockingIOError(IOError):
+
+    """Exception raised when I/O would block on a non-blocking I/O stream."""
+
+    def __init__(self, errno, strerror, characters_written=0):
+        super(IOError, self).__init__(errno, strerror)
+        if not isinstance(characters_written, (int, long)):
+            raise TypeError("characters_written must be a integer")
+        self.characters_written = characters_written
+
+
+def open(file, mode="r", buffering=-1,
+         encoding=None, errors=None,
+         newline=None, closefd=True):
+
+    r"""Open file and return a stream.  Raise IOError upon failure.
+
+    file is either a text or byte string giving the name (and the path
+    if the file isn't in the current working directory) of the file to
+    be opened or an integer file descriptor of the file to be
+    wrapped. (If a file descriptor is given, it is closed when the
+    returned I/O object is closed, unless closefd is set to False.)
+
+    mode is an optional string that specifies the mode in which the file
+    is opened. It defaults to 'r' which means open for reading in text
+    mode.  Other common values are 'w' for writing (truncating the file if
+    it already exists), and 'a' for appending (which on some Unix systems,
+    means that all writes append to the end of the file regardless of the
+    current seek position). In text mode, if encoding is not specified the
+    encoding used is platform dependent. (For reading and writing raw
+    bytes use binary mode and leave encoding unspecified.) The available
+    modes are:
+
+    ========= ===============================================================
+    Character Meaning
+    --------- ---------------------------------------------------------------
+    'r'       open for reading (default)
+    'w'       open for writing, truncating the file first
+    'a'       open for writing, appending to the end of the file if it exists
+    'b'       binary mode
+    't'       text mode (default)
+    '+'       open a disk file for updating (reading and writing)
+    'U'       universal newline mode (for backwards compatibility; unneeded
+              for new code)
+    ========= ===============================================================
+
+    The default mode is 'rt' (open for reading text). For binary random
+    access, the mode 'w+b' opens and truncates the file to 0 bytes, while
+    'r+b' opens the file without truncation.
+
+    Python distinguishes between files opened in binary and text modes,
+    even when the underlying operating system doesn't. Files opened in
+    binary mode (appending 'b' to the mode argument) return contents as
+    bytes objects without any decoding. In text mode (the default, or when
+    't' is appended to the mode argument), the contents of the file are
+    returned as strings, the bytes having been first decoded using a
+    platform-dependent encoding or using the specified encoding if given.
+
+    buffering is an optional integer used to set the buffering policy.
+    Pass 0 to switch buffering off (only allowed in binary mode), 1 to select
+    line buffering (only usable in text mode), and an integer > 1 to indicate
+    the size of a fixed-size chunk buffer.  When no buffering argument is
+    given, the default buffering policy works as follows:
+
+    * Binary files are buffered in fixed-size chunks; the size of the buffer
+      is chosen using a heuristic trying to determine the underlying device's
+      "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`.
+      On many systems, the buffer will typically be 4096 or 8192 bytes long.
+
+    * "Interactive" text files (files for which isatty() returns True)
+      use line buffering.  Other text files use the policy described above
+      for binary files.
+
+    encoding is the name of the encoding used to decode or encode the
+    file. This should only be used in text mode. The default encoding is
+    platform dependent, but any encoding supported by Python can be
+    passed.  See the codecs module for the list of supported encodings.
+
+    errors is an optional string that specifies how encoding errors are to
+    be handled---this argument should not be used in binary mode. Pass
+    'strict' to raise a ValueError exception if there is an encoding error
+    (the default of None has the same effect), or pass 'ignore' to ignore
+    errors. (Note that ignoring encoding errors can lead to data loss.)
+    See the documentation for codecs.register for a list of the permitted
+    encoding error strings.
+
+    newline controls how universal newlines works (it only applies to text
+    mode). It can be None, '', '\n', '\r', and '\r\n'.  It works as
+    follows:
+
+    * On input, if newline is None, universal newlines mode is
+      enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
+      these are translated into '\n' before being returned to the
+      caller. If it is '', universal newline mode is enabled, but line
+      endings are returned to the caller untranslated. If it has any of
+      the other legal values, input lines are only terminated by the given
+      string, and the line ending is returned to the caller untranslated.
+
+    * On output, if newline is None, any '\n' characters written are
+      translated to the system default line separator, os.linesep. If
+      newline is '', no translation takes place. If newline is any of the
+      other legal values, any '\n' characters written are translated to
+      the given string.
+
+    If closefd is False, the underlying file descriptor will be kept open
+    when the file is closed. This does not work when a file name is given
+    and must be True in that case.
+
+    open() returns a file object whose type depends on the mode, and
+    through which the standard file operations such as reading and writing
+    are performed. When open() is used to open a file in a text mode ('w',
+    'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open
+    a file in a binary mode, the returned class varies: in read binary
+    mode, it returns a BufferedReader; in write binary and append binary
+    modes, it returns a BufferedWriter, and in read/write mode, it returns
+    a BufferedRandom.
+
+    It is also possible to use a string or bytearray as a file for both
+    reading and writing. For strings StringIO can be used like a file
+    opened in a text mode, and for bytes a BytesIO can be used like a file
+    opened in a binary mode.
+    """
+    if not isinstance(file, (basestring, int, long)):
+        raise TypeError("invalid file: %r" % file)
+    if not isinstance(mode, basestring):
+        raise TypeError("invalid mode: %r" % mode)
+    if not isinstance(buffering, (int, long)):
+        raise TypeError("invalid buffering: %r" % buffering)
+    if encoding is not None and not isinstance(encoding, basestring):
+        raise TypeError("invalid encoding: %r" % encoding)
+    if errors is not None and not isinstance(errors, basestring):
+        raise TypeError("invalid errors: %r" % errors)
+    modes = set(mode)
+    if modes - set("arwb+tU") or len(mode) > len(modes):
+        raise ValueError("invalid mode: %r" % mode)
+    reading = "r" in modes
+    writing = "w" in modes
+    appending = "a" in modes
+    updating = "+" in modes
+    text = "t" in modes
+    binary = "b" in modes
+    if "U" in modes:
+        if writing or appending:
+            raise ValueError("can't use U and writing mode at once")
+        reading = True
+    if text and binary:
+        raise ValueError("can't have text and binary mode at once")
+    if reading + writing + appending > 1:
+        raise ValueError("can't have read/write/append mode at once")
+    if not (reading or writing or appending):
+        raise ValueError("must have exactly one of read/write/append mode")
+    if binary and encoding is not None:
+        raise ValueError("binary mode doesn't take an encoding argument")
+    if binary and errors is not None:
+        raise ValueError("binary mode doesn't take an errors argument")
+    if binary and newline is not None:
+        raise ValueError("binary mode doesn't take a newline argument")
+    raw = FileIO(file,
+                 (reading and "r" or "") +
+                 (writing and "w" or "") +
+                 (appending and "a" or "") +
+                 (updating and "+" or ""),
+                 closefd)
+    line_buffering = False
+    if buffering == 1 or buffering < 0 and raw.isatty():
+        buffering = -1
+        line_buffering = True
+    if buffering < 0:
+        buffering = DEFAULT_BUFFER_SIZE
+        try:
+            bs = os.fstat(raw.fileno()).st_blksize
+        except (os.error, AttributeError):
+            pass
+        else:
+            if bs > 1:
+                buffering = bs
+    if buffering < 0:
+        raise ValueError("invalid buffering size")
+    if buffering == 0:
+        if binary:
+            return raw
+        raise ValueError("can't have unbuffered text I/O")
+    if updating:
+        buffer = BufferedRandom(raw, buffering)
+    elif writing or appending:
+        buffer = BufferedWriter(raw, buffering)
+    elif reading:
+        buffer = BufferedReader(raw, buffering)
+    else:
+        raise ValueError("unknown mode: %r" % mode)
+    if binary:
+        return buffer
+    text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering)
+    text.mode = mode
+    return text
+
+
+class DocDescriptor:
+    """Helper for builtins.open.__doc__
+    """
+    def __get__(self, obj, typ):
+        return (
+            "open(file, mode='r', buffering=-1, encoding=None, "
+                 "errors=None, newline=None, closefd=True)\n\n" +
+            open.__doc__)
+
+class OpenWrapper:
+    """Wrapper for builtins.open
+
+    Trick so that open won't become a bound method when stored
+    as a class variable (as dbm.dumb does).
+
+    See initstdio() in Python/pythonrun.c.
+    """
+    __doc__ = DocDescriptor()
+
+    def __new__(cls, *args, **kwargs):
+        return open(*args, **kwargs)
+
+
+class UnsupportedOperation(ValueError, IOError):
+    pass
+
+
+class IOBase:
+    __metaclass__ = abc.ABCMeta
+
+    """The abstract base class for all I/O classes, acting on streams of
+    bytes. There is no public constructor.
+
+    This class provides dummy implementations for many methods that
+    derived classes can override selectively; the default implementations
+    represent a file that cannot be read, written or seeked.
+
+    Even though IOBase does not declare read, readinto, or write because
+    their signatures will vary, implementations and clients should
+    consider those methods part of the interface. Also, implementations
+    may raise a IOError when operations they do not support are called.
+
+    The basic type used for binary data read from or written to a file is
+    bytes. bytearrays are accepted too, and in some cases (such as
+    readinto) needed. Text I/O classes work with str data.
+
+    Note that calling any method (even inquiries) on a closed stream is
+    undefined. Implementations may raise IOError in this case.
+
+    IOBase (and its subclasses) support the iterator protocol, meaning
+    that an IOBase object can be iterated over yielding the lines in a
+    stream.
+
+    IOBase also supports the :keyword:`with` statement. In this example,
+    fp is closed after the suite of the with statement is complete:
+
+    with open('spam.txt', 'r') as fp:
+        fp.write('Spam and eggs!')
+    """
+
+    ### Internal ###
+
+    def _unsupported(self, name):
+        """Internal: raise an exception for unsupported operations."""
+        raise UnsupportedOperation("%s.%s() not supported" %
+                                   (self.__class__.__name__, name))
+
+    ### Positioning ###
+
+    def seek(self, pos, whence=0):
+        """Change stream position.
+
+        Change the stream position to byte offset offset. offset is
+        interpreted relative to the position indicated by whence.  Values
+        for whence are:
+
+        * 0 -- start of stream (the default); offset should be zero or positive
+        * 1 -- current stream position; offset may be negative
+        * 2 -- end of stream; offset is usually negative
+
+        Return the new absolute position.
+        """
+        self._unsupported("seek")
+
+    def tell(self):
+        """Return current stream position."""
+        return self.seek(0, 1)
+
+    def truncate(self, pos=None):
+        """Truncate file to size bytes.
+
+        Size defaults to the current IO position as reported by tell().  Return
+        the new size.
+        """
+        self._unsupported("truncate")
+
+    ### Flush and close ###
+
+    def flush(self):
+        """Flush write buffers, if applicable.
+
+        This is not implemented for read-only and non-blocking streams.
+        """
+        self._checkClosed()
+        # XXX Should this return the number of bytes written???
+
+    __closed = False
+
+    def close(self):
+        """Flush and close the IO object.
+
+        This method has no effect if the file is already closed.
+        """
+        if not self.__closed:
+            try:
+                self.flush()
+            finally:
+                self.__closed = True
+
+    def __del__(self):
+        """Destructor.  Calls close()."""
+        # The try/except block is in case this is called at program
+        # exit time, when it's possible that globals have already been
+        # deleted, and then the close() call might fail.  Since
+        # there's nothing we can do about such failures and they annoy
+        # the end users, we suppress the traceback.
+        try:
+            self.close()
+        except:
+            pass
+
+    ### Inquiries ###
+
+    def seekable(self):
+        """Return whether object supports random access.
+
+        If False, seek(), tell() and truncate() will raise IOError.
+        This method may need to do a test seek().
+        """
+        return False
+
+    def _checkSeekable(self, msg=None):
+        """Internal: raise an IOError if file is not seekable
+        """
+        if not self.seekable():
+            raise IOError("File or stream is not seekable."
+                          if msg is None else msg)
+
+
+    def readable(self):
+        """Return whether object was opened for reading.
+
+        If False, read() will raise IOError.
+        """
+        return False
+
+    def _checkReadable(self, msg=None):
+        """Internal: raise an IOError if file is not readable
+        """
+        if not self.readable():
+            raise IOError("File or stream is not readable."
+                          if msg is None else msg)
+
+    def writable(self):
+        """Return whether object was opened for writing.
+
+        If False, write() and truncate() will raise IOError.
+        """
+        return False
+
+    def _checkWritable(self, msg=None):
+        """Internal: raise an IOError if file is not writable
+        """
+        if not self.writable():
+            raise IOError("File or stream is not writable."
+                          if msg is None else msg)
+
+    @property
+    def closed(self):
+        """closed: bool.  True iff the file has been closed.
+
+        For backwards compatibility, this is a property, not a predicate.
+        """
+        return self.__closed
+
+    def _checkClosed(self, msg=None):
+        """Internal: raise an ValueError if file is closed
+        """
+        if self.closed:
+            raise ValueError("I/O operation on closed file."
+                             if msg is None else msg)
+
+    ### Context manager ###
+
+    def __enter__(self):
+        """Context management protocol.  Returns self."""
+        self._checkClosed()
+        return self
+
+    def __exit__(self, *args):
+        """Context management protocol.  Calls close()"""
+        self.close()
+
+    ### Lower-level APIs ###
+
+    # XXX Should these be present even if unimplemented?
+
+    def fileno(self):
+        """Returns underlying file descriptor if one exists.
+
+        An IOError is raised if the IO object does not use a file descriptor.
+        """
+        self._unsupported("fileno")
+
+    def isatty(self):
+        """Return whether this is an 'interactive' stream.
+
+        Return False if it can't be determined.
+        """
+        self._checkClosed()
+        return False
+
+    ### Readline[s] and writelines ###
+
+    def readline(self, limit=-1):
+        r"""Read and return a line from the stream.
+
+        If limit is specified, at most limit bytes will be read.
+
+        The line terminator is always b'\n' for binary files; for text
+        files, the newlines argument to open can be used to select the line
+        terminator(s) recognized.
+        """
+        # For backwards compatibility, a (slowish) readline().
+        if hasattr(self, "peek"):
+            def nreadahead():
+                readahead = self.peek(1)
+                if not readahead:
+                    return 1
+                n = (readahead.find(b"\n") + 1) or len(readahead)
+                if limit >= 0:
+                    n = min(n, limit)
+                return n
+        else:
+            def nreadahead():
+                return 1
+        if limit is None:
+            limit = -1
+        elif not isinstance(limit, (int, long)):
+            raise TypeError("limit must be an integer")
+        res = bytearray()
+        while limit < 0 or len(res) < limit:
+            b = self.read(nreadahead())
+            if not b:
+                break
+            res += b
+            if res.endswith(b"\n"):
+                break
+        return bytes(res)
+
+    def __iter__(self):
+        self._checkClosed()
+        return self
+
+    def next(self):
+        line = self.readline()
+        if not line:
+            raise StopIteration
+        return line
+
+    def readlines(self, hint=None):
+        """Return a list of lines from the stream.
+
+        hint can be specified to control the number of lines read: no more
+        lines will be read if the total size (in bytes/characters) of all
+        lines so far exceeds hint.
+        """
+        if hint is not None and not isinstance(hint, (int, long)):
+            raise TypeError("integer or None expected")
+        if hint is None or hint <= 0:
+            return list(self)
+        n = 0
+        lines = []
+        for line in self:
+            lines.append(line)
+            n += len(line)
+            if n >= hint:
+                break
+        return lines
+
+    def writelines(self, lines):
+        self._checkClosed()
+        for line in lines:
+            self.write(line)
+
+io.IOBase.register(IOBase)
+
+
+class RawIOBase(IOBase):
+
+    """Base class for raw binary I/O."""
+
+    # The read() method is implemented by calling readinto(); derived
+    # classes that want to support read() only need to implement
+    # readinto() as a primitive operation.  In general, readinto() can be
+    # more efficient than read().
+
+    # (It would be tempting to also provide an implementation of
+    # readinto() in terms of read(), in case the latter is a more suitable
+    # primitive operation, but that would lead to nasty recursion in case
+    # a subclass doesn't implement either.)
+
+    def read(self, n=-1):
+        """Read and return up to n bytes.
+
+        Returns an empty bytes object on EOF, or None if the object is
+        set not to block and has no data to read.
+        """
+        if n is None:
+            n = -1
+        if n < 0:
+            return self.readall()
+        b = bytearray(n.__index__())
+        n = self.readinto(b)
+        if n is None:
+            return None
+        del b[n:]
+        return bytes(b)
+
+    def readall(self):
+        """Read until EOF, using multiple read() call."""
+        res = bytearray()
+        while True:
+            data = self.read(DEFAULT_BUFFER_SIZE)
+            if not data:
+                break
+            res += data
+        if res:
+            return bytes(res)
+        else:
+            # b'' or None
+            return data
+
+    def readinto(self, b):
+        """Read up to len(b) bytes into b.
+
+        Returns number of bytes read (0 for EOF), or None if the object
+        is set not to block and has no data to read.
+        """
+        self._unsupported("readinto")
+
+    def write(self, b):
+        """Write the given buffer to the IO stream.
+
+        Returns the number of bytes written, which may be less than len(b).
+        """
+        self._unsupported("write")
+
+io.RawIOBase.register(RawIOBase)
+from _io import FileIO
+RawIOBase.register(FileIO)
+
+
+class BufferedIOBase(IOBase):
+
+    """Base class for buffered IO objects.
+
+    The main difference with RawIOBase is that the read() method
+    supports omitting the size argument, and does not have a default
+    implementation that defers to readinto().
+
+    In addition, read(), readinto() and write() may raise
+    BlockingIOError if the underlying raw stream is in non-blocking
+    mode and not ready; unlike their raw counterparts, they will never
+    return None.
+
+    A typical implementation should not inherit from a RawIOBase
+    implementation, but wrap one.
+    """
+
+    def read(self, n=None):
+        """Read and return up to n bytes.
+
+        If the argument is omitted, None, or negative, reads and
+        returns all data until EOF.
+
+        If the argument is positive, and the underlying raw stream is
+        not 'interactive', multiple raw reads may be issued to satisfy
+        the byte count (unless EOF is reached first).  But for
+        interactive raw streams (XXX and for pipes?), at most one raw
+        read will be issued, and a short result does not imply that
+        EOF is imminent.
+
+        Returns an empty bytes array on EOF.
+
+        Raises BlockingIOError if the underlying raw stream has no
+        data at the moment.
+        """
+        self._unsupported("read")
+
+    def read1(self, n=None):
+        """Read up to n bytes with at most one read() system call."""
+        self._unsupported("read1")
+
+    def readinto(self, b):
+        """Read up to len(b) bytes into b.
+
+        Like read(), this may issue multiple reads to the underlying raw
+        stream, unless the latter is 'interactive'.
+
+        Returns the number of bytes read (0 for EOF).
+
+        Raises BlockingIOError if the underlying raw stream has no
+        data at the moment.
+        """
+        # XXX This ought to work with anything that supports the buffer API
+        data = self.read(len(b))
+        n = len(data)
+        try:
+            b[:n] = data
+        except TypeError as err:
+            import array
+            if not isinstance(b, array.array):
+                raise err
+            b[:n] = array.array(b'b', data)
+        return n
+
+    def write(self, b):
+        """Write the given buffer to the IO stream.
+
+        Return the number of bytes written, which is never less than
+        len(b).
+
+        Raises BlockingIOError if the buffer is full and the
+        underlying raw stream cannot accept more data at the moment.
+        """
+        self._unsupported("write")
+
+    def detach(self):
+        """
+        Separate the underlying raw stream from the buffer and return it.
+
+        After the raw stream has been detached, the buffer is in an unusable
+        state.
+        """
+        self._unsupported("detach")
+
+io.BufferedIOBase.register(BufferedIOBase)
+
+
+class _BufferedIOMixin(BufferedIOBase):
+
+    """A mixin implementation of BufferedIOBase with an underlying raw stream.
+
+    This passes most requests on to the underlying raw stream.  It
+    does *not* provide implementations of read(), readinto() or
+    write().
+    """
+
+    def __init__(self, raw):
+        self._raw = raw
+
+    ### Positioning ###
+
+    def seek(self, pos, whence=0):
+        new_position = self.raw.seek(pos, whence)
+        if new_position < 0:
+            raise IOError("seek() returned an invalid position")
+        return new_position
+
+    def tell(self):
+        pos = self.raw.tell()
+        if pos < 0:
+            raise IOError("tell() returned an invalid position")
+        return pos
+
+    def truncate(self, pos=None):
+        # Flush the stream.  We're mixing buffered I/O with lower-level I/O,
+        # and a flush may be necessary to synch both views of the current
+        # file state.
+        self.flush()
+
+        if pos is None:
+            pos = self.tell()
+        # XXX: Should seek() be used, instead of passing the position
+        # XXX  directly to truncate?
+        return self.raw.truncate(pos)
+
+    ### Flush and close ###
+
+    def flush(self):
+        if self.closed:
+            raise ValueError("flush of closed file")
+        self.raw.flush()
+
+    def close(self):
+        if self.raw is not None and not self.closed:
+            try:
+                # may raise BlockingIOError or BrokenPipeError etc
+                self.flush()
+            finally:
+                self.raw.close()
+
+    def detach(self):
+        if self.raw is None:
+            raise ValueError("raw stream already detached")
+        self.flush()
+        raw = self._raw
+        self._raw = None
+        return raw
+
+    ### Inquiries ###
+
+    def seekable(self):
+        return self.raw.seekable()
+
+    def readable(self):
+        return self.raw.readable()
+
+    def writable(self):
+        return self.raw.writable()
+
+    @property
+    def raw(self):
+        return self._raw
+
+    @property
+    def closed(self):
+        return self.raw.closed
+
+    @property
+    def name(self):
+        return self.raw.name
+
+    @property
+    def mode(self):
+        return self.raw.mode
+
+    def __repr__(self):
+        clsname = self.__class__.__name__
+        try:
+            name = self.name
+        except AttributeError:
+            return "<_pyio.{0}>".format(clsname)
+        else:
+            return "<_pyio.{0} name={1!r}>".format(clsname, name)
+
+    ### Lower-level APIs ###
+
+    def fileno(self):
+        return self.raw.fileno()
+
+    def isatty(self):
+        return self.raw.isatty()
+
+
+class BytesIO(BufferedIOBase):
+
+    """Buffered I/O implementation using an in-memory bytes buffer."""
+
+    def __init__(self, initial_bytes=None):
+        buf = bytearray()
+        if initial_bytes is not None:
+            buf.extend(initial_bytes)
+        self._buffer = buf
+        self._pos = 0
+
+    def __getstate__(self):
+        if self.closed:
+            raise ValueError("__getstate__ on closed file")
+        return self.__dict__.copy()
+
+    def getvalue(self):
+        """Return the bytes value (contents) of the buffer
+        """
+        if self.closed:
+            raise ValueError("getvalue on closed file")
+        return bytes(self._buffer)
+
+    def read(self, n=None):
+        if self.closed:
+            raise ValueError("read from closed file")
+        if n is None:
+            n = -1
+        if not isinstance(n, (int, long)):
+            raise TypeError("integer argument expected, got {0!r}".format(
+                type(n)))
+        if n < 0:
+            n = len(self._buffer)
+        if len(self._buffer) <= self._pos:
+            return b""
+        newpos = min(len(self._buffer), self._pos + n)
+        b = self._buffer[self._pos : newpos]
+        self._pos = newpos
+        return bytes(b)
+
+    def read1(self, n):
+        """This is the same as read.
+        """
+        return self.read(n)
+
+    def write(self, b):
+        if self.closed:
+            raise ValueError("write to closed file")
+        if isinstance(b, unicode):
+            raise TypeError("can't write unicode to binary stream")
+        n = len(b)
+        if n == 0:
+            return 0
+        pos = self._pos
+        if pos > len(self._buffer):
+            # Inserts null bytes between the current end of the file
+            # and the new write position.
+            padding = b'\x00' * (pos - len(self._buffer))
+            self._buffer += padding
+        self._buffer[pos:pos + n] = b
+        self._pos += n
+        return n
+
+    def seek(self, pos, whence=0):
+        if self.closed:
+            raise ValueError("seek on closed file")
+        try:
+            pos.__index__
+        except AttributeError:
+            raise TypeError("an integer is required")
+        if whence == 0:
+            if pos < 0:
+                raise ValueError("negative seek position %r" % (pos,))
+            self._pos = pos
+        elif whence == 1:
+            self._pos = max(0, self._pos + pos)
+        elif whence == 2:
+            self._pos = max(0, len(self._buffer) + pos)
+        else:
+            raise ValueError("invalid whence value")
+        return self._pos
+
+    def tell(self):
+        if self.closed:
+            raise ValueError("tell on closed file")
+        return self._pos
+
+    def truncate(self, pos=None):
+        if self.closed:
+            raise ValueError("truncate on closed file")
+        if pos is None:
+            pos = self._pos
+        else:
+            try:
+                pos.__index__
+            except AttributeError:
+                raise TypeError("an integer is required")
+            if pos < 0:
+                raise ValueError("negative truncate position %r" % (pos,))
+        del self._buffer[pos:]
+        return pos
+
+    def readable(self):
+        if self.closed:
+            raise ValueError("I/O operation on closed file.")
+        return True
+
+    def writable(self):
+        if self.closed:
+            raise ValueError("I/O operation on closed file.")
+        return True
+
+    def seekable(self):
+        if self.closed:
+            raise ValueError("I/O operation on closed file.")
+        return True
+
+
+class BufferedReader(_BufferedIOMixin):
+
+    """BufferedReader(raw[, buffer_size])
+
+    A buffer for a readable, sequential BaseRawIO object.
+
+    The constructor creates a BufferedReader for the given readable raw
+    stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE
+    is used.
+    """
+
+    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
+        """Create a new buffered reader using the given readable raw IO object.
+        """
+        if not raw.readable():
+            raise IOError('"raw" argument must be readable.')
+
+        _BufferedIOMixin.__init__(self, raw)
+        if buffer_size <= 0:
+            raise ValueError("invalid buffer size")
+        self.buffer_size = buffer_size
+        self._reset_read_buf()
+        self._read_lock = Lock()
+
+    def _reset_read_buf(self):
+        self._read_buf = b""
+        self._read_pos = 0
+
+    def read(self, n=None):
+        """Read n bytes.
+
+        Returns exactly n bytes of data unless the underlying raw IO
+        stream reaches EOF or if the call would block in non-blocking
+        mode. If n is negative, read until EOF or until read() would
+        block.
+        """
+        if n is not None and n < -1:
+            raise ValueError("invalid number of bytes to read")
+        with self._read_lock:
+            return self._read_unlocked(n)
+
+    def _read_unlocked(self, n=None):
+        nodata_val = b""
+        empty_values = (b"", None)
+        buf = self._read_buf
+        pos = self._read_pos
+
+        # Special case for when the number of bytes to read is unspecified.
+        if n is None or n == -1:
+            self._reset_read_buf()
+            chunks = [buf[pos:]]  # Strip the consumed bytes.
+            current_size = 0
+            while True:
+                # Read until EOF or until read() would block.
+                try:
+                    chunk = self.raw.read()
+                except IOError as e:
+                    if e.errno != EINTR:
+                        raise
+                    continue
+                if chunk in empty_values:
+                    nodata_val = chunk
+                    break
+                current_size += len(chunk)
+                chunks.append(chunk)
+            return b"".join(chunks) or nodata_val
+
+        # The number of bytes to read is specified, return at most n bytes.
+        avail = len(buf) - pos  # Length of the available buffered data.
+        if n <= avail:
+            # Fast path: the data to read is fully buffered.
+            self._read_pos += n
+            return buf[pos:pos+n]
+        # Slow path: read from the stream until enough bytes are read,
+        # or until an EOF occurs or until read() would block.
+        chunks = [buf[pos:]]
+        wanted = max(self.buffer_size, n)
+        while avail < n:
+            try:
+                chunk = self.raw.read(wanted)
+            except IOError as e:
+                if e.errno != EINTR:
+                    raise
+                continue
+            if chunk in empty_values:
+                nodata_val = chunk
+                break
+            avail += len(chunk)
+            chunks.append(chunk)
+        # n is more then avail only when an EOF occurred or when
+        # read() would have blocked.
+        n = min(n, avail)
+        out = b"".join(chunks)
+        self._read_buf = out[n:]  # Save the extra data in the buffer.
+        self._read_pos = 0
+        return out[:n] if out else nodata_val
+
+    def peek(self, n=0):
+        """Returns buffered bytes without advancing the position.
+
+        The argument indicates a desired minimal number of bytes; we
+        do at most one raw read to satisfy it.  We never return more
+        than self.buffer_size.
+        """
+        with self._read_lock:
+            return self._peek_unlocked(n)
+
+    def _peek_unlocked(self, n=0):
+        want = min(n, self.buffer_size)
+        have = len(self._read_buf) - self._read_pos
+        if have < want or have <= 0:
+            to_read = self.buffer_size - have
+            while True:
+                try:
+                    current = self.raw.read(to_read)
+                except IOError as e:
+                    if e.errno != EINTR:
+                        raise
+                    continue
+                break
+            if current:
+                self._read_buf = self._read_buf[self._read_pos:] + current
+                self._read_pos = 0
+        return self._read_buf[self._read_pos:]
+
+    def read1(self, n):
+        """Reads up to n bytes, with at most one read() system call."""
+        # Returns up to n bytes.  If at least one byte is buffered, we
+        # only return buffered bytes.  Otherwise, we do one raw read.
+        if n < 0:
+            raise ValueError("number of bytes to read must be positive")
+        if n == 0:
+            return b""
+        with self._read_lock:
+            self._peek_unlocked(1)
+            return self._read_unlocked(
+                min(n, len(self._read_buf) - self._read_pos))
+
+    def tell(self):
+        return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos
+
+    def seek(self, pos, whence=0):
+        if not (0 <= whence <= 2):
+            raise ValueError("invalid whence value")
+        with self._read_lock:
+            if whence == 1:
+                pos -= len(self._read_buf) - self._read_pos
+            pos = _BufferedIOMixin.seek(self, pos, whence)
+            self._reset_read_buf()
+            return pos
+
+class BufferedWriter(_BufferedIOMixin):
+
+    """A buffer for a writeable sequential RawIO object.
+
+    The constructor creates a BufferedWriter for the given writeable raw
+    stream. If the buffer_size is not given, it defaults to
+    DEFAULT_BUFFER_SIZE.
+    """
+
+    _warning_stack_offset = 2
+
+    def __init__(self, raw,
+                 buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None):
+        if not raw.writable():
+            raise IOError('"raw" argument must be writable.')
+
+        _BufferedIOMixin.__init__(self, raw)
+        if buffer_size <= 0:
+            raise ValueError("invalid buffer size")
+        if max_buffer_size is not None:
+            warnings.warn("max_buffer_size is deprecated", DeprecationWarning,
+                          self._warning_stack_offset)
+        self.buffer_size = buffer_size
+        self._write_buf = bytearray()
+        self._write_lock = Lock()
+
+    def write(self, b):
+        if self.closed:
+            raise ValueError("write to closed file")
+        if isinstance(b, unicode):
+            raise TypeError("can't write unicode to binary stream")
+        with self._write_lock:
+            # XXX we can implement some more tricks to try and avoid
+            # partial writes
+            if len(self._write_buf) > self.buffer_size:
+                # We're full, so let's pre-flush the buffer.  (This may
+                # raise BlockingIOError with characters_written == 0.)
+                self._flush_unlocked()
+            before = len(self._write_buf)
+            self._write_buf.extend(b)
+            written = len(self._write_buf) - before
+            if len(self._write_buf) > self.buffer_size:
+                try:
+                    self._flush_unlocked()
+                except BlockingIOError as e:
+                    if len(self._write_buf) > self.buffer_size:
+                        # We've hit the buffer_size. We have to accept a partial
+                        # write and cut back our buffer.
+                        overage = len(self._write_buf) - self.buffer_size
+                        written -= overage
+                        self._write_buf = self._write_buf[:self.buffer_size]
+                        raise BlockingIOError(e.errno, e.strerror, written)
+            return written
+
+    def truncate(self, pos=None):
+        with self._write_lock:
+            self._flush_unlocked()
+            if pos is None:
+                pos = self.raw.tell()
+            return self.raw.truncate(pos)
+
+    def flush(self):
+        with self._write_lock:
+            self._flush_unlocked()
+
+    def _flush_unlocked(self):
+        if self.closed:
+            raise ValueError("flush of closed file")
+        while self._write_buf:
+            try:
+                n = self.raw.write(self._write_buf)
+            except BlockingIOError:
+                raise RuntimeError("self.raw should implement RawIOBase: it "
+                                   "should not raise BlockingIOError")
+            except IOError as e:
+                if e.errno != EINTR:
+                    raise
+                continue
+            if n is None:
+                raise BlockingIOError(
+                    errno.EAGAIN,
+                    "write could not complete without blocking", 0)
+            if n > len(self._write_buf) or n < 0:
+                raise IOError("write() returned incorrect number of bytes")
+            del self._write_buf[:n]
+
+    def tell(self):
+        return _BufferedIOMixin.tell(self) + len(self._write_buf)
+
+    def seek(self, pos, whence=0):
+        if not (0 <= whence <= 2):
+            raise ValueError("invalid whence")
+        with self._write_lock:
+            self._flush_unlocked()
+            return _BufferedIOMixin.seek(self, pos, whence)
+
+
+class BufferedRWPair(BufferedIOBase):
+
+    """A buffered reader and writer object together.
+
+    A buffered reader object and buffered writer object put together to
+    form a sequential IO object that can read and write. This is typically
+    used with a socket or two-way pipe.
+
+    reader and writer are RawIOBase objects that are readable and
+    writeable respectively. If the buffer_size is omitted it defaults to
+    DEFAULT_BUFFER_SIZE.
+    """
+
+    # XXX The usefulness of this (compared to having two separate IO
+    # objects) is questionable.
+
+    def __init__(self, reader, writer,
+                 buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None):
+        """Constructor.
+
+        The arguments are two RawIO instances.
+        """
+        if max_buffer_size is not None:
+            warnings.warn("max_buffer_size is deprecated", DeprecationWarning, 2)
+
+        if not reader.readable():
+            raise IOError('"reader" argument must be readable.')
+
+        if not writer.writable():
+            raise IOError('"writer" argument must be writable.')
+
+        self.reader = BufferedReader(reader, buffer_size)
+        self.writer = BufferedWriter(writer, buffer_size)
+
+    def read(self, n=None):
+        if n is None:
+            n = -1
+        return self.reader.read(n)
+
+    def readinto(self, b):
+        return self.reader.readinto(b)
+
+    def write(self, b):
+        return self.writer.write(b)
+
+    def peek(self, n=0):
+        return self.reader.peek(n)
+
+    def read1(self, n):
+        return self.reader.read1(n)
+
+    def readable(self):
+        return self.reader.readable()
+
+    def writable(self):
+        return self.writer.writable()
+
+    def flush(self):
+        return self.writer.flush()
+
+    def close(self):
+        self.writer.close()
+        self.reader.close()
+
+    def isatty(self):
+        return self.reader.isatty() or self.writer.isatty()
+
+    @property
+    def closed(self):
+        return self.writer.closed
+
+
+class BufferedRandom(BufferedWriter, BufferedReader):
+
+    """A buffered interface to random access streams.
+
+    The constructor creates a reader and writer for a seekable stream,
+    raw, given in the first argument. If the buffer_size is omitted it
+    defaults to DEFAULT_BUFFER_SIZE.
+    """
+
+    _warning_stack_offset = 3
+
+    def __init__(self, raw,
+                 buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None):
+        raw._checkSeekable()
+        BufferedReader.__init__(self, raw, buffer_size)
+        BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size)
+
+    def seek(self, pos, whence=0):
+        if not (0 <= whence <= 2):
+            raise ValueError("invalid whence")
+        self.flush()
+        if self._read_buf:
+            # Undo read ahead.
+            with self._read_lock:
+                self.raw.seek(self._read_pos - len(self._read_buf), 1)
+        # First do the raw seek, then empty the read buffer, so that
+        # if the raw seek fails, we don't lose buffered data forever.
+        pos = self.raw.seek(pos, whence)
+        with self._read_lock:
+            self._reset_read_buf()
+        if pos < 0:
+            raise IOError("seek() returned invalid position")
+        return pos
+
+    def tell(self):
+        if self._write_buf:
+            return BufferedWriter.tell(self)
+        else:
+            return BufferedReader.tell(self)
+
+    def truncate(self, pos=None):
+        if pos is None:
+            pos = self.tell()
+        # Use seek to flush the read buffer.
+        return BufferedWriter.truncate(self, pos)
+
+    def read(self, n=None):
+        if n is None:
+            n = -1
+        self.flush()
+        return BufferedReader.read(self, n)
+
+    def readinto(self, b):
+        self.flush()
+        return BufferedReader.readinto(self, b)
+
+    def peek(self, n=0):
+        self.flush()
+        return BufferedReader.peek(self, n)
+
+    def read1(self, n):
+        self.flush()
+        return BufferedReader.read1(self, n)
+
+    def write(self, b):
+        if self._read_buf:
+            # Undo readahead
+            with self._read_lock:
+                self.raw.seek(self._read_pos - len(self._read_buf), 1)
+                self._reset_read_buf()
+        return BufferedWriter.write(self, b)
+
+
+class TextIOBase(IOBase):
+
+    """Base class for text I/O.
+
+    This class provides a character and line based interface to stream
+    I/O. There is no readinto method because Python's character strings
+    are immutable. There is no public constructor.
+    """
+
+    def read(self, n=-1):
+        """Read at most n characters from stream.
+
+        Read from underlying buffer until we have n characters or we hit EOF.
+        If n is negative or omitted, read until EOF.
+        """
+        self._unsupported("read")
+
+    def write(self, s):
+        """Write string s to stream."""
+        self._unsupported("write")
+
+    def truncate(self, pos=None):
+        """Truncate size to pos."""
+        self._unsupported("truncate")
+
+    def readline(self):
+        """Read until newline or EOF.
+
+        Returns an empty string if EOF is hit immediately.
+        """
+        self._unsupported("readline")
+
+    def detach(self):
+        """
+        Separate the underlying buffer from the TextIOBase and return it.
+
+        After the underlying buffer has been detached, the TextIO is in an
+        unusable state.
+        """
+        self._unsupported("detach")
+
+    @property
+    def encoding(self):
+        """Subclasses should override."""
+        return None
+
+    @property
+    def newlines(self):
+        """Line endings translated so far.
+
+        Only line endings translated during reading are considered.
+
+        Subclasses should override.
+        """
+        return None
+
+    @property
+    def errors(self):
+        """Error setting of the decoder or encoder.
+
+        Subclasses should override."""
+        return None
+
+io.TextIOBase.register(TextIOBase)
+
+
+class IncrementalNewlineDecoder(codecs.IncrementalDecoder):
+    r"""Codec used when reading a file in universal newlines mode.  It wraps
+    another incremental decoder, translating \r\n and \r into \n.  It also
+    records the types of newlines encountered.  When used with
+    translate=False, it ensures that the newline sequence is returned in
+    one piece.
+    """
+    def __init__(self, decoder, translate, errors='strict'):
+        codecs.IncrementalDecoder.__init__(self, errors=errors)
+        self.translate = translate
+        self.decoder = decoder
+        self.seennl = 0
+        self.pendingcr = False
+
+    def decode(self, input, final=False):
+        # decode input (with the eventual \r from a previous pass)
+        if self.decoder is None:
+            output = input
+        else:
+            output = self.decoder.decode(input, final=final)
+        if self.pendingcr and (output or final):
+            output = "\r" + output
+            self.pendingcr = False
+
+        # retain last \r even when not translating data:
+        # then readline() is sure to get \r\n in one pass
+        if output.endswith("\r") and not final:
+            output = output[:-1]
+            self.pendingcr = True
+
+        # Record which newlines are read
+        crlf = output.count('\r\n')
+        cr = output.count('\r') - crlf
+        lf = output.count('\n') - crlf
+        self.seennl |= (lf and self._LF) | (cr and self._CR) \
+                    | (crlf and self._CRLF)
+
+        if self.translate:
+            if crlf:
+                output = output.replace("\r\n", "\n")
+            if cr:
+                output = output.replace("\r", "\n")
+
+        return output
+
+    def getstate(self):
+        if self.decoder is None:
+            buf = b""
+            flag = 0
+        else:
+            buf, flag = self.decoder.getstate()
+        flag <<= 1
+        if self.pendingcr:
+            flag |= 1
+        return buf, flag
+
+    def setstate(self, state):
+        buf, flag = state
+        self.pendingcr = bool(flag & 1)
+        if self.decoder is not None:
+            self.decoder.setstate((buf, flag >> 1))
+
+    def reset(self):
+        self.seennl = 0
+        self.pendingcr = False
+        if self.decoder is not None:
+            self.decoder.reset()
+
+    _LF = 1
+    _CR = 2
+    _CRLF = 4
+
+    @property
+    def newlines(self):
+        return (None,
+                "\n",
+                "\r",
+                ("\r", "\n"),
+                "\r\n",
+                ("\n", "\r\n"),
+                ("\r", "\r\n"),
+                ("\r", "\n", "\r\n")
+               )[self.seennl]
+
+
+class TextIOWrapper(TextIOBase):
+
+    r"""Character and line based layer over a BufferedIOBase object, buffer.
+
+    encoding gives the name of the encoding that the stream will be
+    decoded or encoded with. It defaults to locale.getpreferredencoding.
+
+    errors determines the strictness of encoding and decoding (see the
+    codecs.register) and defaults to "strict".
+
+    newline can be None, '', '\n', '\r', or '\r\n'.  It controls the
+    handling of line endings. If it is None, universal newlines is
+    enabled.  With this enabled, on input, the lines endings '\n', '\r',
+    or '\r\n' are translated to '\n' before being returned to the
+    caller. Conversely, on output, '\n' is translated to the system
+    default line separator, os.linesep. If newline is any other of its
+    legal values, that newline becomes the newline when the file is read
+    and it is returned untranslated. On output, '\n' is converted to the
+    newline.
+
+    If line_buffering is True, a call to flush is implied when a call to
+    write contains a newline character.
+    """
+
+    _CHUNK_SIZE = 2048
+
+    def __init__(self, buffer, encoding=None, errors=None, newline=None,
+                 line_buffering=False):
+        if newline is not None and not isinstance(newline, basestring):
+            raise TypeError("illegal newline type: %r" % (type(newline),))
+        if newline not in (None, "", "\n", "\r", "\r\n"):
+            raise ValueError("illegal newline value: %r" % (newline,))
+        if encoding is None:
+            try:
+                import locale
+            except ImportError:
+                # Importing locale may fail if Python is being built
+                encoding = "ascii"
+            else:
+                encoding = locale.getpreferredencoding()
+
+        if not isinstance(encoding, basestring):
+            raise ValueError("invalid encoding: %r" % encoding)
+
+        if errors is None:
+            errors = "strict"
+        else:
+            if not isinstance(errors, basestring):
+                raise ValueError("invalid errors: %r" % errors)
+
+        self._buffer = buffer
+        self._line_buffering = line_buffering
+        self._encoding = encoding
+        self._errors = errors
+        self._readuniversal = not newline
+        self._readtranslate = newline is None
+        self._readnl = newline
+        self._writetranslate = newline != ''
+        self._writenl = newline or os.linesep
+        self._encoder = None
+        self._decoder = None
+        self._decoded_chars = ''  # buffer for text returned from decoder
+        self._decoded_chars_used = 0  # offset into _decoded_chars for read()
+        self._snapshot = None  # info for reconstructing decoder state
+        self._seekable = self._telling = self.buffer.seekable()
+
+        if self._seekable and self.writable():
+            position = self.buffer.tell()
+            if position != 0:
+                try:
+                    self._get_encoder().setstate(0)
+                except LookupError:
+                    # Sometimes the encoder doesn't exist
+                    pass
+
+    # self._snapshot is either None, or a tuple (dec_flags, next_input)
+    # where dec_flags is the second (integer) item of the decoder state
+    # and next_input is the chunk of input bytes that comes next after the
+    # snapshot point.  We use this to reconstruct decoder states in tell().
+
+    # Naming convention:
+    #   - "bytes_..." for integer variables that count input bytes
+    #   - "chars_..." for integer variables that count decoded characters
+
+    def __repr__(self):
+        try:
+            name = self.name
+        except AttributeError:
+            return "<_pyio.TextIOWrapper encoding='{0}'>".format(self.encoding)
+        else:
+            return "<_pyio.TextIOWrapper name={0!r} encoding='{1}'>".format(
+                name, self.encoding)
+
+    @property
+    def encoding(self):
+        return self._encoding
+
+    @property
+    def errors(self):
+        return self._errors
+
+    @property
+    def line_buffering(self):
+        return self._line_buffering
+
+    @property
+    def buffer(self):
+        return self._buffer
+
+    def seekable(self):
+        if self.closed:
+            raise ValueError("I/O operation on closed file.")
+        return self._seekable
+
+    def readable(self):
+        return self.buffer.readable()
+
+    def writable(self):
+        return self.buffer.writable()
+
+    def flush(self):
+        self.buffer.flush()
+        self._telling = self._seekable
+
+    def close(self):
+        if self.buffer is not None and not self.closed:
+            try:
+                self.flush()
+            finally:
+                self.buffer.close()
+
+    @property
+    def closed(self):
+        return self.buffer.closed
+
+    @property
+    def name(self):
+        return self.buffer.name
+
+    def fileno(self):
+        return self.buffer.fileno()
+
+    def isatty(self):
+        return self.buffer.isatty()
+
+    def write(self, s):
+        if self.closed:
+            raise ValueError("write to closed file")
+        if not isinstance(s, unicode):
+            raise TypeError("can't write %s to text stream" %
+                            s.__class__.__name__)
+        length = len(s)
+        haslf = (self._writetranslate or self._line_buffering) and "\n" in s
+        if haslf and self._writetranslate and self._writenl != "\n":
+            s = s.replace("\n", self._writenl)
+        encoder = self._encoder or self._get_encoder()
+        # XXX What if we were just reading?
+        b = encoder.encode(s)
+        self.buffer.write(b)
+        if self._line_buffering and (haslf or "\r" in s):
+            self.flush()
+        self._snapshot = None
+        if self._decoder:
+            self._decoder.reset()
+        return length
+
+    def _get_encoder(self):
+        make_encoder = codecs.getincrementalencoder(self._encoding)
+        self._encoder = make_encoder(self._errors)
+        return self._encoder
+
+    def _get_decoder(self):
+        make_decoder = codecs.getincrementaldecoder(self._encoding)
+        decoder = make_decoder(self._errors)
+        if self._readuniversal:
+            decoder = IncrementalNewlineDecoder(decoder, self._readtranslate)
+        self._decoder = decoder
+        return decoder
+
+    # The following three methods implement an ADT for _decoded_chars.
+    # Text returned from the decoder is buffered here until the client
+    # requests it by calling our read() or readline() method.
+    def _set_decoded_chars(self, chars):
+        """Set the _decoded_chars buffer."""
+        self._decoded_chars = chars
+        self._decoded_chars_used = 0
+
+    def _get_decoded_chars(self, n=None):
+        """Advance into the _decoded_chars buffer."""
+        offset = self._decoded_chars_used
+        if n is None:
+            chars = self._decoded_chars[offset:]
+        else:
+            chars = self._decoded_chars[offset:offset + n]
+        self._decoded_chars_used += len(chars)
+        return chars
+
+    def _rewind_decoded_chars(self, n):
+        """Rewind the _decoded_chars buffer."""
+        if self._decoded_chars_used < n:
+            raise AssertionError("rewind decoded_chars out of bounds")
+        self._decoded_chars_used -= n
+
+    def _read_chunk(self):
+        """
+        Read and decode the next chunk of data from the BufferedReader.
+        """
+
+        # The return value is True unless EOF was reached.  The decoded
+        # string is placed in self._decoded_chars (replacing its previous
+        # value).  The entire input chunk is sent to the decoder, though
+        # some of it may remain buffered in the decoder, yet to be
+        # converted.
+
+        if self._decoder is None:
+            raise ValueError("no decoder")
+
+        if self._telling:
+            # To prepare for tell(), we need to snapshot a point in the
+            # file where the decoder's input buffer is empty.
+
+            dec_buffer, dec_flags = self._decoder.getstate()
+            # Given this, we know there was a valid snapshot point
+            # len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
+
+        # Read a chunk, decode it, and put the result in self._decoded_chars.
+        input_chunk = self.buffer.read1(self._CHUNK_SIZE)
+        eof = not input_chunk
+        self._set_decoded_chars(self._decoder.decode(input_chunk, eof))
+
+        if self._telling:
+            # At the snapshot point, len(dec_buffer) bytes before the read,
+            # the next input to be decoded is dec_buffer + input_chunk.
+            self._snapshot = (dec_flags, dec_buffer + input_chunk)
+
+        return not eof
+
+    def _pack_cookie(self, position, dec_flags=0,
+                           bytes_to_feed=0, need_eof=0, chars_to_skip=0):
+        # The meaning of a tell() cookie is: seek to position, set the
+        # decoder flags to dec_flags, read bytes_to_feed bytes, feed them
+        # into the decoder with need_eof as the EOF flag, then skip
+        # chars_to_skip characters of the decoded result.  For most simple
+        # decoders, tell() will often just give a byte offset in the file.
+        return (position | (dec_flags<<64) | (bytes_to_feed<<128) |
+               (chars_to_skip<<192) | bool(need_eof)<<256)
+
+    def _unpack_cookie(self, bigint):
+        rest, position = divmod(bigint, 1<<64)
+        rest, dec_flags = divmod(rest, 1<<64)
+        rest, bytes_to_feed = divmod(rest, 1<<64)
+        need_eof, chars_to_skip = divmod(rest, 1<<64)
+        return position, dec_flags, bytes_to_feed, need_eof, chars_to_skip
+
+    def tell(self):
+        if not self._seekable:
+            raise IOError("underlying stream is not seekable")
+        if not self._telling:
+            raise IOError("telling position disabled by next() call")
+        self.flush()
+        position = self.buffer.tell()
+        decoder = self._decoder
+        if decoder is None or self._snapshot is None:
+            if self._decoded_chars:
+                # This should never happen.
+                raise AssertionError("pending decoded text")
+            return position
+
+        # Skip backward to the snapshot point (see _read_chunk).
+        dec_flags, next_input = self._snapshot
+        position -= len(next_input)
+
+        # How many decoded characters have been used up since the snapshot?
+        chars_to_skip = self._decoded_chars_used
+        if chars_to_skip == 0:
+            # We haven't moved from the snapshot point.
+            return self._pack_cookie(position, dec_flags)
+
+        # Starting from the snapshot position, we will walk the decoder
+        # forward until it gives us enough decoded characters.
+        saved_state = decoder.getstate()
+        try:
+            # Note our initial start point.
+            decoder.setstate((b'', dec_flags))
+            start_pos = position
+            start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0
+            need_eof = 0
+
+            # Feed the decoder one byte at a time.  As we go, note the
+            # nearest "safe start point" before the current location
+            # (a point where the decoder has nothing buffered, so seek()
+            # can safely start from there and advance to this location).
+            for next_byte in next_input:
+                bytes_fed += 1
+                chars_decoded += len(decoder.decode(next_byte))
+                dec_buffer, dec_flags = decoder.getstate()
+                if not dec_buffer and chars_decoded <= chars_to_skip:
+                    # Decoder buffer is empty, so this is a safe start point.
+                    start_pos += bytes_fed
+                    chars_to_skip -= chars_decoded
+                    start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0
+                if chars_decoded >= chars_to_skip:
+                    break
+            else:
+                # We didn't get enough decoded data; signal EOF to get more.
+                chars_decoded += len(decoder.decode(b'', final=True))
+                need_eof = 1
+                if chars_decoded < chars_to_skip:
+                    raise IOError("can't reconstruct logical file position")
+
+            # The returned cookie corresponds to the last safe start point.
+            return self._pack_cookie(
+                start_pos, start_flags, bytes_fed, need_eof, chars_to_skip)
+        finally:
+            decoder.setstate(saved_state)
+
+    def truncate(self, pos=None):
+        self.flush()
+        if pos is None:
+            pos = self.tell()
+        return self.buffer.truncate(pos)
+
+    def detach(self):
+        if self.buffer is None:
+            raise ValueError("buffer is already detached")
+        self.flush()
+        buffer = self._buffer
+        self._buffer = None
+        return buffer
+
+    def seek(self, cookie, whence=0):
+        if self.closed:
+            raise ValueError("tell on closed file")
+        if not self._seekable:
+            raise IOError("underlying stream is not seekable")
+        if whence == 1: # seek relative to current position
+            if cookie != 0:
+                raise IOError("can't do nonzero cur-relative seeks")
+            # Seeking to the current position should attempt to
+            # sync the underlying buffer with the current position.
+            whence = 0
+            cookie = self.tell()
+        if whence == 2: # seek relative to end of file
+            if cookie != 0:
+                raise IOError("can't do nonzero end-relative seeks")
+            self.flush()
+            position = self.buffer.seek(0, 2)
+            self._set_decoded_chars('')
+            self._snapshot = None
+            if self._decoder:
+                self._decoder.reset()
+            return position
+        if whence != 0:
+            raise ValueError("invalid whence (%r, should be 0, 1 or 2)" %
+                             (whence,))
+        if cookie < 0:
+            raise ValueError("negative seek position %r" % (cookie,))
+        self.flush()
+
+        # The strategy of seek() is to go back to the safe start point
+        # and replay the effect of read(chars_to_skip) from there.
+        start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \
+            self._unpack_cookie(cookie)
+
+        # Seek back to the safe start point.
+        self.buffer.seek(start_pos)
+        self._set_decoded_chars('')
+        self._snapshot = None
+
+        # Restore the decoder to its state from the safe start point.
+        if cookie == 0 and self._decoder:
+            self._decoder.reset()
+        elif self._decoder or dec_flags or chars_to_skip:
+            self._decoder = self._decoder or self._get_decoder()
+            self._decoder.setstate((b'', dec_flags))
+            self._snapshot = (dec_flags, b'')
+
+        if chars_to_skip:
+            # Just like _read_chunk, feed the decoder and save a snapshot.
+            input_chunk = self.buffer.read(bytes_to_feed)
+            self._set_decoded_chars(
+                self._decoder.decode(input_chunk, need_eof))
+            self._snapshot = (dec_flags, input_chunk)
+
+            # Skip chars_to_skip of the decoded characters.
+            if len(self._decoded_chars) < chars_to_skip:
+                raise IOError("can't restore logical file position")
+            self._decoded_chars_used = chars_to_skip
+
+        # Finally, reset the encoder (merely useful for proper BOM handling)
+        try:
+            encoder = self._encoder or self._get_encoder()
+        except LookupError:
+            # Sometimes the encoder doesn't exist
+            pass
+        else:
+            if cookie != 0:
+                encoder.setstate(0)
+            else:
+                encoder.reset()
+        return cookie
+
+    def read(self, n=None):
+        self._checkReadable()
+        if n is None:
+            n = -1
+        decoder = self._decoder or self._get_decoder()
+        try:
+            n.__index__
+        except AttributeError:
+            raise TypeError("an integer is required")
+        if n < 0:
+            # Read everything.
+            result = (self._get_decoded_chars() +
+                      decoder.decode(self.buffer.read(), final=True))
+            self._set_decoded_chars('')
+            self._snapshot = None
+            return result
+        else:
+            # Keep reading chunks until we have n characters to return.
+            eof = False
+            result = self._get_decoded_chars(n)
+            while len(result) < n and not eof:
+                eof = not self._read_chunk()
+                result += self._get_decoded_chars(n - len(result))
+            return result
+
+    def next(self):
+        self._telling = False
+        line = self.readline()
+        if not line:
+            self._snapshot = None
+            self._telling = self._seekable
+            raise StopIteration
+        return line
+
+    def readline(self, limit=None):
+        if self.closed:
+            raise ValueError("read from closed file")
+        if limit is None:
+            limit = -1
+        elif not isinstance(limit, (int, long)):
+            raise TypeError("limit must be an integer")
+
+        # Grab all the decoded text (we will rewind any extra bits later).
+        line = self._get_decoded_chars()
+
+        start = 0
+        # Make the decoder if it doesn't already exist.
+        if not self._decoder:
+            self._get_decoder()
+
+        pos = endpos = None
+        while True:
+            if self._readtranslate:
+                # Newlines are already translated, only search for \n
+                pos = line.find('\n', start)
+                if pos >= 0:
+                    endpos = pos + 1
+                    break
+                else:
+                    start = len(line)
+
+            elif self._readuniversal:
+                # Universal newline search. Find any of \r, \r\n, \n
+                # The decoder ensures that \r\n are not split in two pieces
+
+                # In C we'd look for these in parallel of course.
+                nlpos = line.find("\n", start)
+                crpos = line.find("\r", start)
+                if crpos == -1:
+                    if nlpos == -1:
+                        # Nothing found
+                        start = len(line)
+                    else:
+                        # Found \n
+                        endpos = nlpos + 1
+                        break
+                elif nlpos == -1:
+                    # Found lone \r
+                    endpos = crpos + 1
+                    break
+                elif nlpos < crpos:
+                    # Found \n
+                    endpos = nlpos + 1
+                    break
+                elif nlpos == crpos + 1:
+                    # Found \r\n
+                    endpos = crpos + 2
+                    break
+                else:
+                    # Found \r
+                    endpos = crpos + 1
+                    break
+            else:
+                # non-universal
+                pos = line.find(self._readnl)
+                if pos >= 0:
+                    endpos = pos + len(self._readnl)
+                    break
+
+            if limit >= 0 and len(line) >= limit:
+                endpos = limit  # reached length limit
+                break
+
+            # No line ending seen yet - get more data'
+            while self._read_chunk():
+                if self._decoded_chars:
+                    break
+            if self._decoded_chars:
+                line += self._get_decoded_chars()
+            else:
+                # end of file
+                self._set_decoded_chars('')
+                self._snapshot = None
+                return line
+
+        if limit >= 0 and endpos > limit:
+            endpos = limit  # don't exceed limit
+
+        # Rewind _decoded_chars to just after the line ending we found.
+        self._rewind_decoded_chars(len(line) - endpos)
+        return line[:endpos]
+
+    @property
+    def newlines(self):
+        return self._decoder.newlines if self._decoder else None
+
+
+class StringIO(TextIOWrapper):
+    """Text I/O implementation using an in-memory buffer.
+
+    The initial_value argument sets the value of object.  The newline
+    argument is like the one of TextIOWrapper's constructor.
+    """
+
+    def __init__(self, initial_value="", newline="\n"):
+        super(StringIO, self).__init__(BytesIO(),
+                                       encoding="utf-8",
+                                       errors="strict",
+                                       newline=newline)
+        # Issue #5645: make universal newlines semantics the same as in the
+        # C version, even under Windows.
+        if newline is None:
+            self._writetranslate = False
+        if initial_value:
+            if not isinstance(initial_value, unicode):
+                initial_value = unicode(initial_value)
+            self.write(initial_value)
+            self.seek(0)
+
+    def getvalue(self):
+        self.flush()
+        return self.buffer.getvalue().decode(self._encoding, self._errors)
+
+    def __repr__(self):
+        # TextIOWrapper tells the encoding in its repr. In StringIO,
+        # that's a implementation detail.
+        return object.__repr__(self)
+
+    @property
+    def errors(self):
+        return None
+
+    @property
+    def encoding(self):
+        return None
+
+    def detach(self):
+        # This doesn't make sense on StringIO.
+        self._unsupported("detach")
diff --git a/src/main/resources/PythonLibs/_rawffi.py b/src/main/resources/PythonLibs/_rawffi.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc255e2d8a13bffb4a199e8a675294e2d551d6f3
--- /dev/null
+++ b/src/main/resources/PythonLibs/_rawffi.py
@@ -0,0 +1,54 @@
+import com.sun.jna as jna
+
+def get_libc():
+    return CDLL("c")
+
+typecode_map = {'h': 2, 'H': 2}
+
+class Array(object):
+    def __init__(self, typecode):
+        self.typecode = typecode
+        self.itemsize = typecode_map[typecode]
+
+    def __call__(self, size, autofree=False):
+        if not autofree:
+            raise Exception
+        return ArrayInstance(self, size)
+
+class ArrayInstance(object):
+    def __init__(self, shape, size):
+        self.shape = shape
+        self.alloc = jna.Memory(shape.itemsize * size)
+
+    def __setitem__(self, index, value):
+        self.alloc.setShort(index, value)
+
+    def __getitem__(self, index):
+        return self.alloc.getShort(index)
+
+class FuncPtr(object):
+    def __init__(self, fn, name, argtypes, restype):
+        self.fn = fn
+        self.name = name
+        self.argtypes = argtypes
+        self.restype = restype
+
+    def __call__(self, *args):
+        container = Array('H')(1, autofree=True)
+        container[0] = self.fn.invokeInt([i[0] for i in args])
+        return container
+
+class CDLL(object):
+    def __init__(self, libname):
+        self.lib = jna.NativeLibrary.getInstance(libname)
+        self.cache = dict()
+
+    def ptr(self, name, argtypes, restype):
+        key = (name, tuple(argtypes), restype)
+        try:
+            return self.cache[key]
+        except KeyError:
+            fn = self.lib.getFunction(name)
+            fnp = FuncPtr(fn, name, argtypes, restype)
+            self.cache[key] = fnp
+            return fnp
diff --git a/src/main/resources/PythonLibs/_strptime.py b/src/main/resources/PythonLibs/_strptime.py
new file mode 100644
index 0000000000000000000000000000000000000000..2df30a22ea5e8aaa35c742e0c5c76f80e91b6dc5
--- /dev/null
+++ b/src/main/resources/PythonLibs/_strptime.py
@@ -0,0 +1,467 @@
+"""Strptime-related classes and functions.
+
+CLASSES:
+    LocaleTime -- Discovers and stores locale-specific time information
+    TimeRE -- Creates regexes for pattern matching a string of text containing
+                time information
+
+FUNCTIONS:
+    _getlang -- Figure out what language is being used for the locale
+    strptime -- Calculates the time struct represented by the passed-in string
+
+"""
+import time
+import locale
+import calendar
+from re import compile as re_compile
+from re import IGNORECASE
+from re import escape as re_escape
+from datetime import date as datetime_date
+try:
+    from thread import allocate_lock as _thread_allocate_lock
+except:
+    from dummy_thread import allocate_lock as _thread_allocate_lock
+
+__all__ = []
+
+def _getlang():
+    # Figure out what the current language is set to.
+    return locale.getlocale(locale.LC_TIME)
+
+class LocaleTime(object):
+    """Stores and handles locale-specific information related to time.
+
+    ATTRIBUTES:
+        f_weekday -- full weekday names (7-item list)
+        a_weekday -- abbreviated weekday names (7-item list)
+        f_month -- full month names (13-item list; dummy value in [0], which
+                    is added by code)
+        a_month -- abbreviated month names (13-item list, dummy value in
+                    [0], which is added by code)
+        am_pm -- AM/PM representation (2-item list)
+        LC_date_time -- format string for date/time representation (string)
+        LC_date -- format string for date representation (string)
+        LC_time -- format string for time representation (string)
+        timezone -- daylight- and non-daylight-savings timezone representation
+                    (2-item list of sets)
+        lang -- Language used by instance (2-item tuple)
+    """
+
+    def __init__(self):
+        """Set all attributes.
+
+        Order of methods called matters for dependency reasons.
+
+        The locale language is set at the offset and then checked again before
+        exiting.  This is to make sure that the attributes were not set with a
+        mix of information from more than one locale.  This would most likely
+        happen when using threads where one thread calls a locale-dependent
+        function while another thread changes the locale while the function in
+        the other thread is still running.  Proper coding would call for
+        locks to prevent changing the locale while locale-dependent code is
+        running.  The check here is done in case someone does not think about
+        doing this.
+
+        Only other possible issue is if someone changed the timezone and did
+        not call tz.tzset .  That is an issue for the programmer, though,
+        since changing the timezone is worthless without that call.
+
+        """
+        self.lang = _getlang()
+        self.__calc_weekday()
+        self.__calc_month()
+        self.__calc_am_pm()
+        self.__calc_timezone()
+        self.__calc_date_time()
+        if _getlang() != self.lang:
+            raise ValueError("locale changed during initialization")
+
+    def __pad(self, seq, front):
+        # Add '' to seq to either the front (is True), else the back.
+        seq = list(seq)
+        if front:
+            seq.insert(0, '')
+        else:
+            seq.append('')
+        return seq
+
+    def __calc_weekday(self):
+        # Set self.a_weekday and self.f_weekday using the calendar
+        # module.
+        a_weekday = [calendar.day_abbr[i].lower() for i in range(7)]
+        f_weekday = [calendar.day_name[i].lower() for i in range(7)]
+        self.a_weekday = a_weekday
+        self.f_weekday = f_weekday
+
+    def __calc_month(self):
+        # Set self.f_month and self.a_month using the calendar module.
+        a_month = [calendar.month_abbr[i].lower() for i in range(13)]
+        f_month = [calendar.month_name[i].lower() for i in range(13)]
+        self.a_month = a_month
+        self.f_month = f_month
+
+    def __calc_am_pm(self):
+        # Set self.am_pm by using time.strftime().
+
+        # The magic date (1999,3,17,hour,44,55,2,76,0) is not really that
+        # magical; just happened to have used it everywhere else where a
+        # static date was needed.
+        am_pm = []
+        for hour in (01,22):
+            time_tuple = time.struct_time((1999,3,17,hour,44,55,2,76,0))
+            am_pm.append(time.strftime("%p", time_tuple).lower())
+        self.am_pm = am_pm
+
+    def __calc_date_time(self):
+        # Set self.date_time, self.date, & self.time by using
+        # time.strftime().
+
+        # Use (1999,3,17,22,44,55,2,76,0) for magic date because the amount of
+        # overloaded numbers is minimized.  The order in which searches for
+        # values within the format string is very important; it eliminates
+        # possible ambiguity for what something represents.
+        time_tuple = time.struct_time((1999,3,17,22,44,55,2,76,0))
+        date_time = [None, None, None]
+        date_time[0] = time.strftime("%c", time_tuple).lower()
+        date_time[1] = time.strftime("%x", time_tuple).lower()
+        date_time[2] = time.strftime("%X", time_tuple).lower()
+        replacement_pairs = [('%', '%%'), (self.f_weekday[2], '%A'),
+                    (self.f_month[3], '%B'), (self.a_weekday[2], '%a'),
+                    (self.a_month[3], '%b'), (self.am_pm[1], '%p'),
+                    ('1999', '%Y'), ('99', '%y'), ('22', '%H'),
+                    ('44', '%M'), ('55', '%S'), ('76', '%j'),
+                    ('17', '%d'), ('03', '%m'), ('3', '%m'),
+                    # '3' needed for when no leading zero.
+                    ('2', '%w'), ('10', '%I')]
+        replacement_pairs.extend([(tz, "%Z") for tz_values in self.timezone
+                                                for tz in tz_values])
+        for offset,directive in ((0,'%c'), (1,'%x'), (2,'%X')):
+            current_format = date_time[offset]
+            for old, new in replacement_pairs:
+                # Must deal with possible lack of locale info
+                # manifesting itself as the empty string (e.g., Swedish's
+                # lack of AM/PM info) or a platform returning a tuple of empty
+                # strings (e.g., MacOS 9 having timezone as ('','')).
+                if old:
+                    current_format = current_format.replace(old, new)
+            # If %W is used, then Sunday, 2005-01-03 will fall on week 0 since
+            # 2005-01-03 occurs before the first Monday of the year.  Otherwise
+            # %U is used.
+            time_tuple = time.struct_time((1999,1,3,1,1,1,6,3,0))
+            if '00' in time.strftime(directive, time_tuple):
+                U_W = '%W'
+            else:
+                U_W = '%U'
+            date_time[offset] = current_format.replace('11', U_W)
+        self.LC_date_time = date_time[0]
+        self.LC_date = date_time[1]
+        self.LC_time = date_time[2]
+
+    def __calc_timezone(self):
+        # Set self.timezone by using time.tzname.
+        # Do not worry about possibility of time.tzname[0] == timetzname[1]
+        # and time.daylight; handle that in strptime .
+        try:
+            time.tzset()
+        except AttributeError:
+            pass
+        no_saving = frozenset(["utc", "gmt", time.tzname[0].lower()])
+        if time.daylight:
+            has_saving = frozenset([time.tzname[1].lower()])
+        else:
+            has_saving = frozenset()
+        self.timezone = (no_saving, has_saving)
+
+
+class TimeRE(dict):
+    """Handle conversion from format directives to regexes."""
+
+    def __init__(self, locale_time=None):
+        """Create keys/values.
+
+        Order of execution is important for dependency reasons.
+
+        """
+        if locale_time:
+            self.locale_time = locale_time
+        else:
+            self.locale_time = LocaleTime()
+        base = super(TimeRE, self)
+        base.__init__({
+            # The " \d" part of the regex is to make %c from ANSI C work
+            'd': r"(?P<d>3[0-1]|[1-2]\d|0[1-9]|[1-9]| [1-9])",
+            'f': r"(?P<f>[0-9]{1,6})",
+            'H': r"(?P<H>2[0-3]|[0-1]\d|\d)",
+            'I': r"(?P<I>1[0-2]|0[1-9]|[1-9])",
+            'j': r"(?P<j>36[0-6]|3[0-5]\d|[1-2]\d\d|0[1-9]\d|00[1-9]|[1-9]\d|0[1-9]|[1-9])",
+            'm': r"(?P<m>1[0-2]|0[1-9]|[1-9])",
+            'M': r"(?P<M>[0-5]\d|\d)",
+            'S': r"(?P<S>6[0-1]|[0-5]\d|\d)",
+            'U': r"(?P<U>5[0-3]|[0-4]\d|\d)",
+            'w': r"(?P<w>[0-6])",
+            # W is set below by using 'U'
+            'y': r"(?P<y>\d\d)",
+            #XXX: Does 'Y' need to worry about having less or more than
+            #     4 digits?
+            'Y': r"(?P<Y>\d\d\d\d)",
+            'A': self.__seqToRE(self.locale_time.f_weekday, 'A'),
+            'a': self.__seqToRE(self.locale_time.a_weekday, 'a'),
+            'B': self.__seqToRE(self.locale_time.f_month[1:], 'B'),
+            'b': self.__seqToRE(self.locale_time.a_month[1:], 'b'),
+            'p': self.__seqToRE(self.locale_time.am_pm, 'p'),
+            'Z': self.__seqToRE((tz for tz_names in self.locale_time.timezone
+                                        for tz in tz_names),
+                                'Z'),
+            '%': '%'})
+        base.__setitem__('W', base.__getitem__('U').replace('U', 'W'))
+        base.__setitem__('c', self.pattern(self.locale_time.LC_date_time))
+        base.__setitem__('x', self.pattern(self.locale_time.LC_date))
+        base.__setitem__('X', self.pattern(self.locale_time.LC_time))
+
+    def __seqToRE(self, to_convert, directive):
+        """Convert a list to a regex string for matching a directive.
+
+        Want possible matching values to be from longest to shortest.  This
+        prevents the possibility of a match occuring for a value that also
+        a substring of a larger value that should have matched (e.g., 'abc'
+        matching when 'abcdef' should have been the match).
+
+        """
+        to_convert = sorted(to_convert, key=len, reverse=True)
+        for value in to_convert:
+            if value != '':
+                break
+        else:
+            return ''
+        regex = '|'.join(re_escape(stuff) for stuff in to_convert)
+        regex = '(?P<%s>%s' % (directive, regex)
+        return '%s)' % regex
+
+    def pattern(self, format):
+        """Return regex pattern for the format string.
+
+        Need to make sure that any characters that might be interpreted as
+        regex syntax are escaped.
+
+        """
+        processed_format = ''
+        # The sub() call escapes all characters that might be misconstrued
+        # as regex syntax.  Cannot use re.escape since we have to deal with
+        # format directives (%m, etc.).
+        regex_chars = re_compile(r"([\\.^$*+?\(\){}\[\]|])")
+        format = regex_chars.sub(r"\\\1", format)
+        whitespace_replacement = re_compile('\s+')
+        format = whitespace_replacement.sub('\s+', format)
+        while '%' in format:
+            directive_index = format.index('%')+1
+            processed_format = "%s%s%s" % (processed_format,
+                                           format[:directive_index-1],
+                                           self[format[directive_index]])
+            format = format[directive_index+1:]
+        return "%s%s" % (processed_format, format)
+
+    def compile(self, format):
+        """Return a compiled re object for the format string."""
+        return re_compile(self.pattern(format), IGNORECASE)
+
+_cache_lock = _thread_allocate_lock()
+# DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock
+# first!
+_TimeRE_cache = TimeRE()
+_CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache
+_regex_cache = {}
+
+def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon):
+    """Calculate the Julian day based on the year, week of the year, and day of
+    the week, with week_start_day representing whether the week of the year
+    assumes the week starts on Sunday or Monday (6 or 0)."""
+    first_weekday = datetime_date(year, 1, 1).weekday()
+    # If we are dealing with the %U directive (week starts on Sunday), it's
+    # easier to just shift the view to Sunday being the first day of the
+    # week.
+    if not week_starts_Mon:
+        first_weekday = (first_weekday + 1) % 7
+        day_of_week = (day_of_week + 1) % 7
+    # Need to watch out for a week 0 (when the first day of the year is not
+    # the same as that specified by %U or %W).
+    week_0_length = (7 - first_weekday) % 7
+    if week_of_year == 0:
+        return 1 + day_of_week - first_weekday
+    else:
+        days_to_week = week_0_length + (7 * (week_of_year - 1))
+        return 1 + days_to_week + day_of_week
+
+
+def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
+    """Return a time struct based on the input string and the format string."""
+    global _TimeRE_cache, _regex_cache
+    with _cache_lock:
+        if _getlang() != _TimeRE_cache.locale_time.lang:
+            _TimeRE_cache = TimeRE()
+            _regex_cache.clear()
+        if len(_regex_cache) > _CACHE_MAX_SIZE:
+            _regex_cache.clear()
+        locale_time = _TimeRE_cache.locale_time
+        format_regex = _regex_cache.get(format)
+        if not format_regex:
+            try:
+                format_regex = _TimeRE_cache.compile(format)
+            # KeyError raised when a bad format is found; can be specified as
+            # \\, in which case it was a stray % but with a space after it
+            except KeyError, err:
+                bad_directive = err.args[0]
+                if bad_directive == "\\":
+                    bad_directive = "%"
+                del err
+                raise ValueError("'%s' is a bad directive in format '%s'" %
+                                    (bad_directive, format))
+            # IndexError only occurs when the format string is "%"
+            except IndexError:
+                raise ValueError("stray %% in format '%s'" % format)
+            _regex_cache[format] = format_regex
+    found = format_regex.match(data_string)
+    if not found:
+        raise ValueError("time data %r does not match format %r" %
+                         (data_string, format))
+    if len(data_string) != found.end():
+        raise ValueError("unconverted data remains: %s" %
+                          data_string[found.end():])
+
+    year = None
+    month = day = 1
+    hour = minute = second = fraction = 0
+    tz = -1
+    # Default to -1 to signify that values not known; not critical to have,
+    # though
+    week_of_year = -1
+    week_of_year_start = -1
+    # weekday and julian defaulted to -1 so as to signal need to calculate
+    # values
+    weekday = julian = -1
+    found_dict = found.groupdict()
+    for group_key in found_dict.iterkeys():
+        # Directives not explicitly handled below:
+        #   c, x, X
+        #      handled by making out of other directives
+        #   U, W
+        #      worthless without day of the week
+        if group_key == 'y':
+            year = int(found_dict['y'])
+            # Open Group specification for strptime() states that a %y
+            #value in the range of [00, 68] is in the century 2000, while
+            #[69,99] is in the century 1900
+            if year <= 68:
+                year += 2000
+            else:
+                year += 1900
+        elif group_key == 'Y':
+            year = int(found_dict['Y'])
+        elif group_key == 'm':
+            month = int(found_dict['m'])
+        elif group_key == 'B':
+            month = locale_time.f_month.index(found_dict['B'].lower())
+        elif group_key == 'b':
+            month = locale_time.a_month.index(found_dict['b'].lower())
+        elif group_key == 'd':
+            day = int(found_dict['d'])
+        elif group_key == 'H':
+            hour = int(found_dict['H'])
+        elif group_key == 'I':
+            hour = int(found_dict['I'])
+            ampm = found_dict.get('p', '').lower()
+            # If there was no AM/PM indicator, we'll treat this like AM
+            if ampm in ('', locale_time.am_pm[0]):
+                # We're in AM so the hour is correct unless we're
+                # looking at 12 midnight.
+                # 12 midnight == 12 AM == hour 0
+                if hour == 12:
+                    hour = 0
+            elif ampm == locale_time.am_pm[1]:
+                # We're in PM so we need to add 12 to the hour unless
+                # we're looking at 12 noon.
+                # 12 noon == 12 PM == hour 12
+                if hour != 12:
+                    hour += 12
+        elif group_key == 'M':
+            minute = int(found_dict['M'])
+        elif group_key == 'S':
+            second = int(found_dict['S'])
+        elif group_key == 'f':
+            s = found_dict['f']
+            # Pad to always return microseconds.
+            s += "0" * (6 - len(s))
+            fraction = int(s)
+        elif group_key == 'A':
+            weekday = locale_time.f_weekday.index(found_dict['A'].lower())
+        elif group_key == 'a':
+            weekday = locale_time.a_weekday.index(found_dict['a'].lower())
+        elif group_key == 'w':
+            weekday = int(found_dict['w'])
+            if weekday == 0:
+                weekday = 6
+            else:
+                weekday -= 1
+        elif group_key == 'j':
+            julian = int(found_dict['j'])
+        elif group_key in ('U', 'W'):
+            week_of_year = int(found_dict[group_key])
+            if group_key == 'U':
+                # U starts week on Sunday.
+                week_of_year_start = 6
+            else:
+                # W starts week on Monday.
+                week_of_year_start = 0
+        elif group_key == 'Z':
+            # Since -1 is default value only need to worry about setting tz if
+            # it can be something other than -1.
+            found_zone = found_dict['Z'].lower()
+            for value, tz_values in enumerate(locale_time.timezone):
+                if found_zone in tz_values:
+                    # Deal with bad locale setup where timezone names are the
+                    # same and yet time.daylight is true; too ambiguous to
+                    # be able to tell what timezone has daylight savings
+                    if (time.tzname[0] == time.tzname[1] and
+                       time.daylight and found_zone not in ("utc", "gmt")):
+                        break
+                    else:
+                        tz = value
+                        break
+    leap_year_fix = False
+    if year is None and month == 2 and day == 29:
+        year = 1904  # 1904 is first leap year of 20th century
+        leap_year_fix = True
+    elif year is None:
+        year = 1900
+    # If we know the week of the year and what day of that week, we can figure
+    # out the Julian day of the year.
+    if julian == -1 and week_of_year != -1 and weekday != -1:
+        week_starts_Mon = True if week_of_year_start == 0 else False
+        julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
+                                            week_starts_Mon)
+    # Cannot pre-calculate datetime_date() since can change in Julian
+    # calculation and thus could have different value for the day of the week
+    # calculation.
+    if julian == -1:
+        # Need to add 1 to result since first day of the year is 1, not 0.
+        julian = datetime_date(year, month, day).toordinal() - \
+                  datetime_date(year, 1, 1).toordinal() + 1
+    else:  # Assume that if they bothered to include Julian day it will
+           # be accurate.
+        datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal())
+        year = datetime_result.year
+        month = datetime_result.month
+        day = datetime_result.day
+    if weekday == -1:
+        weekday = datetime_date(year, month, day).weekday()
+    if leap_year_fix:
+        # the caller didn't supply a year but asked for Feb 29th. We couldn't
+        # use the default of 1900 for computations. We set it back to ensure
+        # that February 29th is smaller than March 1st.
+        year = 1900
+
+    return (time.struct_time((year, month, day,
+                              hour, minute, second,
+                              weekday, julian, tz)), fraction)
+
+def _strptime_time(data_string, format="%a %b %d %H:%M:%S %Y"):
+    return _strptime(data_string, format)[0]
diff --git a/src/main/resources/PythonLibs/_threading_local.py b/src/main/resources/PythonLibs/_threading_local.py
new file mode 100644
index 0000000000000000000000000000000000000000..09a3515bdb92b40b1e43caa0cca25f0da5981aae
--- /dev/null
+++ b/src/main/resources/PythonLibs/_threading_local.py
@@ -0,0 +1,251 @@
+"""Thread-local objects.
+
+(Note that this module provides a Python version of the threading.local
+ class.  Depending on the version of Python you're using, there may be a
+ faster one available.  You should always import the `local` class from
+ `threading`.)
+
+Thread-local objects support the management of thread-local data.
+If you have data that you want to be local to a thread, simply create
+a thread-local object and use its attributes:
+
+  >>> mydata = local()
+  >>> mydata.number = 42
+  >>> mydata.number
+  42
+
+You can also access the local-object's dictionary:
+
+  >>> mydata.__dict__
+  {'number': 42}
+  >>> mydata.__dict__.setdefault('widgets', [])
+  []
+  >>> mydata.widgets
+  []
+
+What's important about thread-local objects is that their data are
+local to a thread. If we access the data in a different thread:
+
+  >>> log = []
+  >>> def f():
+  ...     items = mydata.__dict__.items()
+  ...     items.sort()
+  ...     log.append(items)
+  ...     mydata.number = 11
+  ...     log.append(mydata.number)
+
+  >>> import threading
+  >>> thread = threading.Thread(target=f)
+  >>> thread.start()
+  >>> thread.join()
+  >>> log
+  [[], 11]
+
+we get different data.  Furthermore, changes made in the other thread
+don't affect data seen in this thread:
+
+  >>> mydata.number
+  42
+
+Of course, values you get from a local object, including a __dict__
+attribute, are for whatever thread was current at the time the
+attribute was read.  For that reason, you generally don't want to save
+these values across threads, as they apply only to the thread they
+came from.
+
+You can create custom local objects by subclassing the local class:
+
+  >>> class MyLocal(local):
+  ...     number = 2
+  ...     initialized = False
+  ...     def __init__(self, **kw):
+  ...         if self.initialized:
+  ...             raise SystemError('__init__ called too many times')
+  ...         self.initialized = True
+  ...         self.__dict__.update(kw)
+  ...     def squared(self):
+  ...         return self.number ** 2
+
+This can be useful to support default values, methods and
+initialization.  Note that if you define an __init__ method, it will be
+called each time the local object is used in a separate thread.  This
+is necessary to initialize each thread's dictionary.
+
+Now if we create a local object:
+
+  >>> mydata = MyLocal(color='red')
+
+Now we have a default number:
+
+  >>> mydata.number
+  2
+
+an initial color:
+
+  >>> mydata.color
+  'red'
+  >>> del mydata.color
+
+And a method that operates on the data:
+
+  >>> mydata.squared()
+  4
+
+As before, we can access the data in a separate thread:
+
+  >>> log = []
+  >>> thread = threading.Thread(target=f)
+  >>> thread.start()
+  >>> thread.join()
+  >>> log
+  [[('color', 'red'), ('initialized', True)], 11]
+
+without affecting this thread's data:
+
+  >>> mydata.number
+  2
+  >>> mydata.color
+  Traceback (most recent call last):
+  ...
+  AttributeError: 'MyLocal' object has no attribute 'color'
+
+Note that subclasses can define slots, but they are not thread
+local. They are shared across threads:
+
+  >>> class MyLocal(local):
+  ...     __slots__ = 'number'
+
+  >>> mydata = MyLocal()
+  >>> mydata.number = 42
+  >>> mydata.color = 'red'
+
+So, the separate thread:
+
+  >>> thread = threading.Thread(target=f)
+  >>> thread.start()
+  >>> thread.join()
+
+affects what we see:
+
+  >>> mydata.number
+  11
+
+>>> del mydata
+"""
+
+__all__ = ["local"]
+
+# We need to use objects from the threading module, but the threading
+# module may also want to use our `local` class, if support for locals
+# isn't compiled in to the `thread` module.  This creates potential problems
+# with circular imports.  For that reason, we don't import `threading`
+# until the bottom of this file (a hack sufficient to worm around the
+# potential problems).  Note that almost all platforms do have support for
+# locals in the `thread` module, and there is no circular import problem
+# then, so problems introduced by fiddling the order of imports here won't
+# manifest on most boxes.
+
+class _localbase(object):
+    __slots__ = '_local__key', '_local__args', '_local__lock'
+
+    def __new__(cls, *args, **kw):
+        self = object.__new__(cls)
+        key = '_local__key', 'thread.local.' + str(id(self))
+        object.__setattr__(self, '_local__key', key)
+        object.__setattr__(self, '_local__args', (args, kw))
+        object.__setattr__(self, '_local__lock', RLock())
+
+        if (args or kw) and (cls.__init__ is object.__init__):
+            raise TypeError("Initialization arguments are not supported")
+
+        # We need to create the thread dict in anticipation of
+        # __init__ being called, to make sure we don't call it
+        # again ourselves.
+        dict = object.__getattribute__(self, '__dict__')
+        current_thread().__dict__[key] = dict
+
+        return self
+
+def _patch(self):
+    key = object.__getattribute__(self, '_local__key')
+    d = current_thread().__dict__.get(key)
+    if d is None:
+        d = {}
+        current_thread().__dict__[key] = d
+        object.__setattr__(self, '__dict__', d)
+
+        # we have a new instance dict, so call out __init__ if we have
+        # one
+        cls = type(self)
+        if cls.__init__ is not object.__init__:
+            args, kw = object.__getattribute__(self, '_local__args')
+            cls.__init__(self, *args, **kw)
+    else:
+        object.__setattr__(self, '__dict__', d)
+
+class local(_localbase):
+
+    def __getattribute__(self, name):
+        lock = object.__getattribute__(self, '_local__lock')
+        lock.acquire()
+        try:
+            _patch(self)
+            return object.__getattribute__(self, name)
+        finally:
+            lock.release()
+
+    def __setattr__(self, name, value):
+        if name == '__dict__':
+            raise AttributeError(
+                "%r object attribute '__dict__' is read-only"
+                % self.__class__.__name__)
+        lock = object.__getattribute__(self, '_local__lock')
+        lock.acquire()
+        try:
+            _patch(self)
+            return object.__setattr__(self, name, value)
+        finally:
+            lock.release()
+
+    def __delattr__(self, name):
+        if name == '__dict__':
+            raise AttributeError(
+                "%r object attribute '__dict__' is read-only"
+                % self.__class__.__name__)
+        lock = object.__getattribute__(self, '_local__lock')
+        lock.acquire()
+        try:
+            _patch(self)
+            return object.__delattr__(self, name)
+        finally:
+            lock.release()
+
+    def __del__(self):
+        import threading
+
+        key = object.__getattribute__(self, '_local__key')
+
+        try:
+            # We use the non-locking API since we might already hold the lock
+            # (__del__ can be called at any point by the cyclic GC).
+            threads = threading._enumerate()
+        except:
+            # If enumerating the current threads fails, as it seems to do
+            # during shutdown, we'll skip cleanup under the assumption
+            # that there is nothing to clean up.
+            return
+
+        for thread in threads:
+            try:
+                __dict__ = thread.__dict__
+            except AttributeError:
+                # Thread is dying, rest in peace.
+                continue
+
+            if key in __dict__:
+                try:
+                    del __dict__[key]
+                except KeyError:
+                    pass # didn't have anything in this thread
+
+from threading import current_thread, RLock
diff --git a/src/main/resources/PythonLibs/_weakrefset.py b/src/main/resources/PythonLibs/_weakrefset.py
new file mode 100644
index 0000000000000000000000000000000000000000..90e07d4768b8c0b6a6f41e983294a6109ac1bc8f
--- /dev/null
+++ b/src/main/resources/PythonLibs/_weakrefset.py
@@ -0,0 +1,212 @@
+# Access WeakSet through the weakref module.
+# This code is separated-out because it is needed
+# by abc.py to load everything else at startup.
+
+from _weakref import ref
+
+__all__ = ['WeakSet']
+
+
+class _IterationGuard(object):
+    # This context manager registers itself in the current iterators of the
+    # weak container, such as to delay all removals until the context manager
+    # exits.
+    # This technique should be relatively thread-safe (since sets are).
+
+    def __init__(self, weakcontainer):
+        # Don't create cycles
+        self.weakcontainer = ref(weakcontainer)
+
+    def __enter__(self):
+        w = self.weakcontainer()
+        if w is not None:
+            w._iterating.add(self)
+        return self
+
+    def __exit__(self, e, t, b):
+        w = self.weakcontainer()
+        if w is not None:
+            s = w._iterating
+            s.remove(self)
+            if not s:
+                w._commit_removals()
+
+
+class WeakSet(object):
+    def __init__(self, data=None):
+        self.data = set()
+        def _remove(item, selfref=ref(self)):
+            self = selfref()
+            if self is not None:
+                if self._iterating:
+                    self._pending_removals.append(item)
+                else:
+                    self.data.discard(item)
+        self._remove = _remove
+        # A list of keys to be removed
+        self._pending_removals = []
+        self._iterating = set()
+        if data is not None:
+            self.update(data)
+
+    def _commit_removals(self):
+        l = self._pending_removals
+        discard = self.data.discard
+        while l:
+            discard(l.pop())
+
+    def __iter__(self):
+        with _IterationGuard(self):
+            for itemref in self.data:
+                item = itemref()
+                if item is not None:
+                    yield item
+
+    def __len__(self):
+        return sum(x() is not None for x in self.data)
+
+    def __contains__(self, item):
+        return ref(item) in self.data
+
+    def __reduce__(self):
+        return (self.__class__, (list(self),),
+                getattr(self, '__dict__', None))
+
+    __hash__ = None
+
+    def add(self, item):
+        if self._pending_removals:
+            self._commit_removals()
+        self.data.add(ref(item, self._remove))
+
+    def clear(self):
+        if self._pending_removals:
+            self._commit_removals()
+        self.data.clear()
+
+    def copy(self):
+        return self.__class__(self)
+
+    def pop(self):
+        if self._pending_removals:
+            self._commit_removals()
+        while True:
+            try:
+                itemref = self.data.pop()
+            except KeyError:
+                raise KeyError('pop from empty WeakSet')
+            item = itemref()
+            if item is not None:
+                return item
+
+    def remove(self, item):
+        if self._pending_removals:
+            self._commit_removals()
+        self.data.remove(ref(item))
+
+    def discard(self, item):
+        if self._pending_removals:
+            self._commit_removals()
+        self.data.discard(ref(item))
+
+    def update(self, other):
+        if self._pending_removals:
+            self._commit_removals()
+        if isinstance(other, self.__class__):
+            self.data.update(other.data)
+        else:
+            for element in other:
+                self.add(element)
+
+    def __ior__(self, other):
+        self.update(other)
+        return self
+
+    # Helper functions for simple delegating methods.
+    def _apply(self, other, method):
+        if not isinstance(other, self.__class__):
+            other = self.__class__(other)
+        newdata = method(other.data)
+        newset = self.__class__()
+        newset.data = newdata
+        return newset
+
+    def difference(self, other):
+        return self._apply(other, self.data.difference)
+    __sub__ = difference
+
+    def difference_update(self, other):
+        if self._pending_removals:
+            self._commit_removals()
+        if self is other:
+            self.data.clear()
+        else:
+            self.data.difference_update(ref(item) for item in other)
+    def __isub__(self, other):
+        if self._pending_removals:
+            self._commit_removals()
+        if self is other:
+            self.data.clear()
+        else:
+            self.data.difference_update(ref(item) for item in other)
+        return self
+
+    def intersection(self, other):
+        return self._apply(other, self.data.intersection)
+    __and__ = intersection
+
+    def intersection_update(self, other):
+        if self._pending_removals:
+            self._commit_removals()
+        self.data.intersection_update(ref(item) for item in other)
+    def __iand__(self, other):
+        if self._pending_removals:
+            self._commit_removals()
+        self.data.intersection_update(ref(item) for item in other)
+        return self
+
+    def issubset(self, other):
+        return self.data.issubset(ref(item) for item in other)
+    __lt__ = issubset
+
+    def __le__(self, other):
+        return self.data <= set(ref(item) for item in other)
+
+    def issuperset(self, other):
+        return self.data.issuperset(ref(item) for item in other)
+    __gt__ = issuperset
+
+    def __ge__(self, other):
+        return self.data >= set(ref(item) for item in other)
+
+    def __eq__(self, other):
+        if not isinstance(other, self.__class__):
+            return NotImplemented
+        return self.data == set(ref(item) for item in other)
+
+    def symmetric_difference(self, other):
+        return self._apply(other, self.data.symmetric_difference)
+    __xor__ = symmetric_difference
+
+    def symmetric_difference_update(self, other):
+        if self._pending_removals:
+            self._commit_removals()
+        if self is other:
+            self.data.clear()
+        else:
+            self.data.symmetric_difference_update(ref(item) for item in other)
+    def __ixor__(self, other):
+        if self._pending_removals:
+            self._commit_removals()
+        if self is other:
+            self.data.clear()
+        else:
+            self.data.symmetric_difference_update(ref(item) for item in other)
+        return self
+
+    def union(self, other):
+        return self._apply(other, self.data.union)
+    __or__ = union
+
+    def isdisjoint(self, other):
+        return len(self.intersection(other)) == 0
diff --git a/src/main/resources/PythonLibs/abc.py b/src/main/resources/PythonLibs/abc.py
new file mode 100644
index 0000000000000000000000000000000000000000..02e48a1bb32f9bb0353180e4b0546e6985b0725d
--- /dev/null
+++ b/src/main/resources/PythonLibs/abc.py
@@ -0,0 +1,185 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Abstract Base Classes (ABCs) according to PEP 3119."""
+
+import types
+
+from _weakrefset import WeakSet
+
+# Instance of old-style class
+class _C: pass
+_InstanceType = type(_C())
+
+
+def abstractmethod(funcobj):
+    """A decorator indicating abstract methods.
+
+    Requires that the metaclass is ABCMeta or derived from it.  A
+    class that has a metaclass derived from ABCMeta cannot be
+    instantiated unless all of its abstract methods are overridden.
+    The abstract methods can be called using any of the normal
+    'super' call mechanisms.
+
+    Usage:
+
+        class C:
+            __metaclass__ = ABCMeta
+            @abstractmethod
+            def my_abstract_method(self, ...):
+                ...
+    """
+    funcobj.__isabstractmethod__ = True
+    return funcobj
+
+
+class abstractproperty(property):
+    """A decorator indicating abstract properties.
+
+    Requires that the metaclass is ABCMeta or derived from it.  A
+    class that has a metaclass derived from ABCMeta cannot be
+    instantiated unless all of its abstract properties are overridden.
+    The abstract properties can be called using any of the normal
+    'super' call mechanisms.
+
+    Usage:
+
+        class C:
+            __metaclass__ = ABCMeta
+            @abstractproperty
+            def my_abstract_property(self):
+                ...
+
+    This defines a read-only property; you can also define a read-write
+    abstract property using the 'long' form of property declaration:
+
+        class C:
+            __metaclass__ = ABCMeta
+            def getx(self): ...
+            def setx(self, value): ...
+            x = abstractproperty(getx, setx)
+    """
+    __isabstractmethod__ = True
+
+
+class ABCMeta(type):
+
+    """Metaclass for defining Abstract Base Classes (ABCs).
+
+    Use this metaclass to create an ABC.  An ABC can be subclassed
+    directly, and then acts as a mix-in class.  You can also register
+    unrelated concrete classes (even built-in classes) and unrelated
+    ABCs as 'virtual subclasses' -- these and their descendants will
+    be considered subclasses of the registering ABC by the built-in
+    issubclass() function, but the registering ABC won't show up in
+    their MRO (Method Resolution Order) nor will method
+    implementations defined by the registering ABC be callable (not
+    even via super()).
+
+    """
+
+    # A global counter that is incremented each time a class is
+    # registered as a virtual subclass of anything.  It forces the
+    # negative cache to be cleared before its next use.
+    _abc_invalidation_counter = 0
+
+    def __new__(mcls, name, bases, namespace):
+        cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace)
+        # Compute set of abstract method names
+        abstracts = set(name
+                     for name, value in namespace.items()
+                     if getattr(value, "__isabstractmethod__", False))
+        for base in bases:
+            for name in getattr(base, "__abstractmethods__", set()):
+                value = getattr(cls, name, None)
+                if getattr(value, "__isabstractmethod__", False):
+                    abstracts.add(name)
+        cls.__abstractmethods__ = frozenset(abstracts)
+        # Set up inheritance registry
+        cls._abc_registry = WeakSet()
+        cls._abc_cache = WeakSet()
+        cls._abc_negative_cache = WeakSet()
+        cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
+        return cls
+
+    def register(cls, subclass):
+        """Register a virtual subclass of an ABC."""
+        if not isinstance(subclass, (type, types.ClassType)):
+            raise TypeError("Can only register classes")
+        if issubclass(subclass, cls):
+            return  # Already a subclass
+        # Subtle: test for cycles *after* testing for "already a subclass";
+        # this means we allow X.register(X) and interpret it as a no-op.
+        if issubclass(cls, subclass):
+            # This would create a cycle, which is bad for the algorithm below
+            raise RuntimeError("Refusing to create an inheritance cycle")
+        cls._abc_registry.add(subclass)
+        ABCMeta._abc_invalidation_counter += 1  # Invalidate negative cache
+
+    def _dump_registry(cls, file=None):
+        """Debug helper to print the ABC registry."""
+        print >> file, "Class: %s.%s" % (cls.__module__, cls.__name__)
+        print >> file, "Inv.counter: %s" % ABCMeta._abc_invalidation_counter
+        for name in sorted(cls.__dict__.keys()):
+            if name.startswith("_abc_"):
+                value = getattr(cls, name)
+                print >> file, "%s: %r" % (name, value)
+
+    def __instancecheck__(cls, instance):
+        """Override for isinstance(instance, cls)."""
+        # Inline the cache checking when it's simple.
+        subclass = getattr(instance, '__class__', None)
+        if subclass is not None and subclass in cls._abc_cache:
+            return True
+        subtype = type(instance)
+        # Old-style instances
+        if subtype is _InstanceType:
+            subtype = subclass
+        if subtype is subclass or subclass is None:
+            if (cls._abc_negative_cache_version ==
+                ABCMeta._abc_invalidation_counter and
+                subtype in cls._abc_negative_cache):
+                return False
+            # Fall back to the subclass check.
+            return cls.__subclasscheck__(subtype)
+        return (cls.__subclasscheck__(subclass) or
+                cls.__subclasscheck__(subtype))
+
+    def __subclasscheck__(cls, subclass):
+        """Override for issubclass(subclass, cls)."""
+        # Check cache
+        if subclass in cls._abc_cache:
+            return True
+        # Check negative cache; may have to invalidate
+        if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
+            # Invalidate the negative cache
+            cls._abc_negative_cache = WeakSet()
+            cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
+        elif subclass in cls._abc_negative_cache:
+            return False
+        # Check the subclass hook
+        ok = cls.__subclasshook__(subclass)
+        if ok is not NotImplemented:
+            assert isinstance(ok, bool)
+            if ok:
+                cls._abc_cache.add(subclass)
+            else:
+                cls._abc_negative_cache.add(subclass)
+            return ok
+        # Check if it's a direct subclass
+        if cls in getattr(subclass, '__mro__', ()):
+            cls._abc_cache.add(subclass)
+            return True
+        # Check if it's a subclass of a registered class (recursive)
+        for rcls in cls._abc_registry:
+            if issubclass(subclass, rcls):
+                cls._abc_cache.add(subclass)
+                return True
+        # Check if it's a subclass of a subclass (recursive)
+        for scls in cls.__subclasses__():
+            if issubclass(subclass, scls):
+                cls._abc_cache.add(subclass)
+                return True
+        # No dice; update negative cache
+        cls._abc_negative_cache.add(subclass)
+        return False
diff --git a/src/main/resources/PythonLibs/aifc.py b/src/main/resources/PythonLibs/aifc.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0cfe5fc57e1ee76d440b0f4181bdd8c41b04312
--- /dev/null
+++ b/src/main/resources/PythonLibs/aifc.py
@@ -0,0 +1,975 @@
+"""Stuff to parse AIFF-C and AIFF files.
+
+Unless explicitly stated otherwise, the description below is true
+both for AIFF-C files and AIFF files.
+
+An AIFF-C file has the following structure.
+
+  +-----------------+
+  | FORM            |
+  +-----------------+
+  | <size>          |
+  +----+------------+
+  |    | AIFC       |
+  |    +------------+
+  |    | <chunks>   |
+  |    |    .       |
+  |    |    .       |
+  |    |    .       |
+  +----+------------+
+
+An AIFF file has the string "AIFF" instead of "AIFC".
+
+A chunk consists of an identifier (4 bytes) followed by a size (4 bytes,
+big endian order), followed by the data.  The size field does not include
+the size of the 8 byte header.
+
+The following chunk types are recognized.
+
+  FVER
+      <version number of AIFF-C defining document> (AIFF-C only).
+  MARK
+      <# of markers> (2 bytes)
+      list of markers:
+          <marker ID> (2 bytes, must be > 0)
+          <position> (4 bytes)
+          <marker name> ("pstring")
+  COMM
+      <# of channels> (2 bytes)
+      <# of sound frames> (4 bytes)
+      <size of the samples> (2 bytes)
+      <sampling frequency> (10 bytes, IEEE 80-bit extended
+          floating point)
+      in AIFF-C files only:
+      <compression type> (4 bytes)
+      <human-readable version of compression type> ("pstring")
+  SSND
+      <offset> (4 bytes, not used by this program)
+      <blocksize> (4 bytes, not used by this program)
+      <sound data>
+
+A pstring consists of 1 byte length, a string of characters, and 0 or 1
+byte pad to make the total length even.
+
+Usage.
+
+Reading AIFF files:
+  f = aifc.open(file, 'r')
+where file is either the name of a file or an open file pointer.
+The open file pointer must have methods read(), seek(), and close().
+In some types of audio files, if the setpos() method is not used,
+the seek() method is not necessary.
+
+This returns an instance of a class with the following public methods:
+  getnchannels()  -- returns number of audio channels (1 for
+             mono, 2 for stereo)
+  getsampwidth()  -- returns sample width in bytes
+  getframerate()  -- returns sampling frequency
+  getnframes()    -- returns number of audio frames
+  getcomptype()   -- returns compression type ('NONE' for AIFF files)
+  getcompname()   -- returns human-readable version of
+             compression type ('not compressed' for AIFF files)
+  getparams() -- returns a tuple consisting of all of the
+             above in the above order
+  getmarkers()    -- get the list of marks in the audio file or None
+             if there are no marks
+  getmark(id) -- get mark with the specified id (raises an error
+             if the mark does not exist)
+  readframes(n)   -- returns at most n frames of audio
+  rewind()    -- rewind to the beginning of the audio stream
+  setpos(pos) -- seek to the specified position
+  tell()      -- return the current position
+  close()     -- close the instance (make it unusable)
+The position returned by tell(), the position given to setpos() and
+the position of marks are all compatible and have nothing to do with
+the actual position in the file.
+The close() method is called automatically when the class instance
+is destroyed.
+
+Writing AIFF files:
+  f = aifc.open(file, 'w')
+where file is either the name of a file or an open file pointer.
+The open file pointer must have methods write(), tell(), seek(), and
+close().
+
+This returns an instance of a class with the following public methods:
+  aiff()      -- create an AIFF file (AIFF-C default)
+  aifc()      -- create an AIFF-C file
+  setnchannels(n) -- set the number of channels
+  setsampwidth(n) -- set the sample width
+  setframerate(n) -- set the frame rate
+  setnframes(n)   -- set the number of frames
+  setcomptype(type, name)
+          -- set the compression type and the
+             human-readable compression type
+  setparams(tuple)
+          -- set all parameters at once
+  setmark(id, pos, name)
+          -- add specified mark to the list of marks
+  tell()      -- return current position in output file (useful
+             in combination with setmark())
+  writeframesraw(data)
+          -- write audio frames without pathing up the
+             file header
+  writeframes(data)
+          -- write audio frames and patch up the file header
+  close()     -- patch up the file header and close the
+             output file
+You should set the parameters before the first writeframesraw or
+writeframes.  The total number of frames does not need to be set,
+but when it is set to the correct value, the header does not have to
+be patched up.
+It is best to first set all parameters, perhaps possibly the
+compression type, and then write audio frames using writeframesraw.
+When all frames have been written, either call writeframes('') or
+close() to patch up the sizes in the header.
+Marks can be added anytime.  If there are any marks, ypu must call
+close() after all frames have been written.
+The close() method is called automatically when the class instance
+is destroyed.
+
+When a file is opened with the extension '.aiff', an AIFF file is
+written, otherwise an AIFF-C file is written.  This default can be
+changed by calling aiff() or aifc() before the first writeframes or
+writeframesraw.
+"""
+
+import struct
+import __builtin__
+
+__all__ = ["Error","open","openfp"]
+
+class Error(Exception):
+    pass
+
+_AIFC_version = 0xA2805140L     # Version 1 of AIFF-C
+
+def _read_long(file):
+    try:
+        return struct.unpack('>l', file.read(4))[0]
+    except struct.error:
+        raise EOFError
+
+def _read_ulong(file):
+    try:
+        return struct.unpack('>L', file.read(4))[0]
+    except struct.error:
+        raise EOFError
+
+def _read_short(file):
+    try:
+        return struct.unpack('>h', file.read(2))[0]
+    except struct.error:
+        raise EOFError
+
+def _read_ushort(file):
+    try:
+        return struct.unpack('>H', file.read(2))[0]
+    except struct.error:
+        raise EOFError
+
+def _read_string(file):
+    length = ord(file.read(1))
+    if length == 0:
+        data = ''
+    else:
+        data = file.read(length)
+    if length & 1 == 0:
+        dummy = file.read(1)
+    return data
+
+_HUGE_VAL = 1.79769313486231e+308 # See <limits.h>
+
+def _read_float(f): # 10 bytes
+    expon = _read_short(f) # 2 bytes
+    sign = 1
+    if expon < 0:
+        sign = -1
+        expon = expon + 0x8000
+    himant = _read_ulong(f) # 4 bytes
+    lomant = _read_ulong(f) # 4 bytes
+    if expon == himant == lomant == 0:
+        f = 0.0
+    elif expon == 0x7FFF:
+        f = _HUGE_VAL
+    else:
+        expon = expon - 16383
+        f = (himant * 0x100000000L + lomant) * pow(2.0, expon - 63)
+    return sign * f
+
+def _write_short(f, x):
+    f.write(struct.pack('>h', x))
+
+def _write_ushort(f, x):
+    f.write(struct.pack('>H', x))
+
+def _write_long(f, x):
+    f.write(struct.pack('>l', x))
+
+def _write_ulong(f, x):
+    f.write(struct.pack('>L', x))
+
+def _write_string(f, s):
+    if len(s) > 255:
+        raise ValueError("string exceeds maximum pstring length")
+    f.write(struct.pack('B', len(s)))
+    f.write(s)
+    if len(s) & 1 == 0:
+        f.write(chr(0))
+
+def _write_float(f, x):
+    import math
+    if x < 0:
+        sign = 0x8000
+        x = x * -1
+    else:
+        sign = 0
+    if x == 0:
+        expon = 0
+        himant = 0
+        lomant = 0
+    else:
+        fmant, expon = math.frexp(x)
+        if expon > 16384 or fmant >= 1 or fmant != fmant: # Infinity or NaN
+            expon = sign|0x7FFF
+            himant = 0
+            lomant = 0
+        else:                   # Finite
+            expon = expon + 16382
+            if expon < 0:           # denormalized
+                fmant = math.ldexp(fmant, expon)
+                expon = 0
+            expon = expon | sign
+            fmant = math.ldexp(fmant, 32)
+            fsmant = math.floor(fmant)
+            himant = long(fsmant)
+            fmant = math.ldexp(fmant - fsmant, 32)
+            fsmant = math.floor(fmant)
+            lomant = long(fsmant)
+    _write_ushort(f, expon)
+    _write_ulong(f, himant)
+    _write_ulong(f, lomant)
+
+from chunk import Chunk
+
+class Aifc_read:
+    # Variables used in this class:
+    #
+    # These variables are available to the user though appropriate
+    # methods of this class:
+    # _file -- the open file with methods read(), close(), and seek()
+    #       set through the __init__() method
+    # _nchannels -- the number of audio channels
+    #       available through the getnchannels() method
+    # _nframes -- the number of audio frames
+    #       available through the getnframes() method
+    # _sampwidth -- the number of bytes per audio sample
+    #       available through the getsampwidth() method
+    # _framerate -- the sampling frequency
+    #       available through the getframerate() method
+    # _comptype -- the AIFF-C compression type ('NONE' if AIFF)
+    #       available through the getcomptype() method
+    # _compname -- the human-readable AIFF-C compression type
+    #       available through the getcomptype() method
+    # _markers -- the marks in the audio file
+    #       available through the getmarkers() and getmark()
+    #       methods
+    # _soundpos -- the position in the audio stream
+    #       available through the tell() method, set through the
+    #       setpos() method
+    #
+    # These variables are used internally only:
+    # _version -- the AIFF-C version number
+    # _decomp -- the decompressor from builtin module cl
+    # _comm_chunk_read -- 1 iff the COMM chunk has been read
+    # _aifc -- 1 iff reading an AIFF-C file
+    # _ssnd_seek_needed -- 1 iff positioned correctly in audio
+    #       file for readframes()
+    # _ssnd_chunk -- instantiation of a chunk class for the SSND chunk
+    # _framesize -- size of one frame in the file
+
+    def initfp(self, file):
+        self._version = 0
+        self._decomp = None
+        self._convert = None
+        self._markers = []
+        self._soundpos = 0
+        self._file = file
+        chunk = Chunk(file)
+        if chunk.getname() != 'FORM':
+            raise Error, 'file does not start with FORM id'
+        formdata = chunk.read(4)
+        if formdata == 'AIFF':
+            self._aifc = 0
+        elif formdata == 'AIFC':
+            self._aifc = 1
+        else:
+            raise Error, 'not an AIFF or AIFF-C file'
+        self._comm_chunk_read = 0
+        while 1:
+            self._ssnd_seek_needed = 1
+            try:
+                chunk = Chunk(self._file)
+            except EOFError:
+                break
+            chunkname = chunk.getname()
+            if chunkname == 'COMM':
+                self._read_comm_chunk(chunk)
+                self._comm_chunk_read = 1
+            elif chunkname == 'SSND':
+                self._ssnd_chunk = chunk
+                dummy = chunk.read(8)
+                self._ssnd_seek_needed = 0
+            elif chunkname == 'FVER':
+                self._version = _read_ulong(chunk)
+            elif chunkname == 'MARK':
+                self._readmark(chunk)
+            chunk.skip()
+        if not self._comm_chunk_read or not self._ssnd_chunk:
+            raise Error, 'COMM chunk and/or SSND chunk missing'
+        if self._aifc and self._decomp:
+            import cl
+            params = [cl.ORIGINAL_FORMAT, 0,
+                  cl.BITS_PER_COMPONENT, self._sampwidth * 8,
+                  cl.FRAME_RATE, self._framerate]
+            if self._nchannels == 1:
+                params[1] = cl.MONO
+            elif self._nchannels == 2:
+                params[1] = cl.STEREO_INTERLEAVED
+            else:
+                raise Error, 'cannot compress more than 2 channels'
+            self._decomp.SetParams(params)
+
+    def __init__(self, f):
+        if type(f) == type(''):
+            f = __builtin__.open(f, 'rb')
+        # else, assume it is an open file object already
+        self.initfp(f)
+
+    #
+    # User visible methods.
+    #
+    def getfp(self):
+        return self._file
+
+    def rewind(self):
+        self._ssnd_seek_needed = 1
+        self._soundpos = 0
+
+    def close(self):
+        if self._decomp:
+            self._decomp.CloseDecompressor()
+            self._decomp = None
+        self._file.close()
+
+    def tell(self):
+        return self._soundpos
+
+    def getnchannels(self):
+        return self._nchannels
+
+    def getnframes(self):
+        return self._nframes
+
+    def getsampwidth(self):
+        return self._sampwidth
+
+    def getframerate(self):
+        return self._framerate
+
+    def getcomptype(self):
+        return self._comptype
+
+    def getcompname(self):
+        return self._compname
+
+##  def getversion(self):
+##      return self._version
+
+    def getparams(self):
+        return self.getnchannels(), self.getsampwidth(), \
+              self.getframerate(), self.getnframes(), \
+              self.getcomptype(), self.getcompname()
+
+    def getmarkers(self):
+        if len(self._markers) == 0:
+            return None
+        return self._markers
+
+    def getmark(self, id):
+        for marker in self._markers:
+            if id == marker[0]:
+                return marker
+        raise Error, 'marker %r does not exist' % (id,)
+
+    def setpos(self, pos):
+        if pos < 0 or pos > self._nframes:
+            raise Error, 'position not in range'
+        self._soundpos = pos
+        self._ssnd_seek_needed = 1
+
+    def readframes(self, nframes):
+        if self._ssnd_seek_needed:
+            self._ssnd_chunk.seek(0)
+            dummy = self._ssnd_chunk.read(8)
+            pos = self._soundpos * self._framesize
+            if pos:
+                self._ssnd_chunk.seek(pos + 8)
+            self._ssnd_seek_needed = 0
+        if nframes == 0:
+            return ''
+        data = self._ssnd_chunk.read(nframes * self._framesize)
+        if self._convert and data:
+            data = self._convert(data)
+        self._soundpos = self._soundpos + len(data) // (self._nchannels * self._sampwidth)
+        return data
+
+    #
+    # Internal methods.
+    #
+
+    def _decomp_data(self, data):
+        import cl
+        dummy = self._decomp.SetParam(cl.FRAME_BUFFER_SIZE,
+                          len(data) * 2)
+        return self._decomp.Decompress(len(data) // self._nchannels,
+                           data)
+
+    def _ulaw2lin(self, data):
+        import audioop
+        return audioop.ulaw2lin(data, 2)
+
+    def _adpcm2lin(self, data):
+        import audioop
+        if not hasattr(self, '_adpcmstate'):
+            # first time
+            self._adpcmstate = None
+        data, self._adpcmstate = audioop.adpcm2lin(data, 2,
+                               self._adpcmstate)
+        return data
+
+    def _read_comm_chunk(self, chunk):
+        self._nchannels = _read_short(chunk)
+        self._nframes = _read_long(chunk)
+        self._sampwidth = (_read_short(chunk) + 7) // 8
+        self._framerate = int(_read_float(chunk))
+        self._framesize = self._nchannels * self._sampwidth
+        if self._aifc:
+            #DEBUG: SGI's soundeditor produces a bad size :-(
+            kludge = 0
+            if chunk.chunksize == 18:
+                kludge = 1
+                print 'Warning: bad COMM chunk size'
+                chunk.chunksize = 23
+            #DEBUG end
+            self._comptype = chunk.read(4)
+            #DEBUG start
+            if kludge:
+                length = ord(chunk.file.read(1))
+                if length & 1 == 0:
+                    length = length + 1
+                chunk.chunksize = chunk.chunksize + length
+                chunk.file.seek(-1, 1)
+            #DEBUG end
+            self._compname = _read_string(chunk)
+            if self._comptype != 'NONE':
+                if self._comptype == 'G722':
+                    try:
+                        import audioop
+                    except ImportError:
+                        pass
+                    else:
+                        self._convert = self._adpcm2lin
+                        self._framesize = self._framesize // 4
+                        return
+                # for ULAW and ALAW try Compression Library
+                try:
+                    import cl
+                except ImportError:
+                    if self._comptype == 'ULAW':
+                        try:
+                            import audioop
+                            self._convert = self._ulaw2lin
+                            self._framesize = self._framesize // 2
+                            return
+                        except ImportError:
+                            pass
+                    raise Error, 'cannot read compressed AIFF-C files'
+                if self._comptype == 'ULAW':
+                    scheme = cl.G711_ULAW
+                    self._framesize = self._framesize // 2
+                elif self._comptype == 'ALAW':
+                    scheme = cl.G711_ALAW
+                    self._framesize = self._framesize // 2
+                else:
+                    raise Error, 'unsupported compression type'
+                self._decomp = cl.OpenDecompressor(scheme)
+                self._convert = self._decomp_data
+        else:
+            self._comptype = 'NONE'
+            self._compname = 'not compressed'
+
+    def _readmark(self, chunk):
+        nmarkers = _read_short(chunk)
+        # Some files appear to contain invalid counts.
+        # Cope with this by testing for EOF.
+        try:
+            for i in range(nmarkers):
+                id = _read_short(chunk)
+                pos = _read_long(chunk)
+                name = _read_string(chunk)
+                if pos or name:
+                    # some files appear to have
+                    # dummy markers consisting of
+                    # a position 0 and name ''
+                    self._markers.append((id, pos, name))
+        except EOFError:
+            print 'Warning: MARK chunk contains only',
+            print len(self._markers),
+            if len(self._markers) == 1: print 'marker',
+            else: print 'markers',
+            print 'instead of', nmarkers
+
+class Aifc_write:
+    # Variables used in this class:
+    #
+    # These variables are user settable through appropriate methods
+    # of this class:
+    # _file -- the open file with methods write(), close(), tell(), seek()
+    #       set through the __init__() method
+    # _comptype -- the AIFF-C compression type ('NONE' in AIFF)
+    #       set through the setcomptype() or setparams() method
+    # _compname -- the human-readable AIFF-C compression type
+    #       set through the setcomptype() or setparams() method
+    # _nchannels -- the number of audio channels
+    #       set through the setnchannels() or setparams() method
+    # _sampwidth -- the number of bytes per audio sample
+    #       set through the setsampwidth() or setparams() method
+    # _framerate -- the sampling frequency
+    #       set through the setframerate() or setparams() method
+    # _nframes -- the number of audio frames written to the header
+    #       set through the setnframes() or setparams() method
+    # _aifc -- whether we're writing an AIFF-C file or an AIFF file
+    #       set through the aifc() method, reset through the
+    #       aiff() method
+    #
+    # These variables are used internally only:
+    # _version -- the AIFF-C version number
+    # _comp -- the compressor from builtin module cl
+    # _nframeswritten -- the number of audio frames actually written
+    # _datalength -- the size of the audio samples written to the header
+    # _datawritten -- the size of the audio samples actually written
+
+    def __init__(self, f):
+        if type(f) == type(''):
+            filename = f
+            f = __builtin__.open(f, 'wb')
+        else:
+            # else, assume it is an open file object already
+            filename = '???'
+        self.initfp(f)
+        if filename[-5:] == '.aiff':
+            self._aifc = 0
+        else:
+            self._aifc = 1
+
+    def initfp(self, file):
+        self._file = file
+        self._version = _AIFC_version
+        self._comptype = 'NONE'
+        self._compname = 'not compressed'
+        self._comp = None
+        self._convert = None
+        self._nchannels = 0
+        self._sampwidth = 0
+        self._framerate = 0
+        self._nframes = 0
+        self._nframeswritten = 0
+        self._datawritten = 0
+        self._datalength = 0
+        self._markers = []
+        self._marklength = 0
+        self._aifc = 1      # AIFF-C is default
+
+    def __del__(self):
+        if self._file:
+            self.close()
+
+    #
+    # User visible methods.
+    #
+    def aiff(self):
+        if self._nframeswritten:
+            raise Error, 'cannot change parameters after starting to write'
+        self._aifc = 0
+
+    def aifc(self):
+        if self._nframeswritten:
+            raise Error, 'cannot change parameters after starting to write'
+        self._aifc = 1
+
+    def setnchannels(self, nchannels):
+        if self._nframeswritten:
+            raise Error, 'cannot change parameters after starting to write'
+        if nchannels < 1:
+            raise Error, 'bad # of channels'
+        self._nchannels = nchannels
+
+    def getnchannels(self):
+        if not self._nchannels:
+            raise Error, 'number of channels not set'
+        return self._nchannels
+
+    def setsampwidth(self, sampwidth):
+        if self._nframeswritten:
+            raise Error, 'cannot change parameters after starting to write'
+        if sampwidth < 1 or sampwidth > 4:
+            raise Error, 'bad sample width'
+        self._sampwidth = sampwidth
+
+    def getsampwidth(self):
+        if not self._sampwidth:
+            raise Error, 'sample width not set'
+        return self._sampwidth
+
+    def setframerate(self, framerate):
+        if self._nframeswritten:
+            raise Error, 'cannot change parameters after starting to write'
+        if framerate <= 0:
+            raise Error, 'bad frame rate'
+        self._framerate = framerate
+
+    def getframerate(self):
+        if not self._framerate:
+            raise Error, 'frame rate not set'
+        return self._framerate
+
+    def setnframes(self, nframes):
+        if self._nframeswritten:
+            raise Error, 'cannot change parameters after starting to write'
+        self._nframes = nframes
+
+    def getnframes(self):
+        return self._nframeswritten
+
+    def setcomptype(self, comptype, compname):
+        if self._nframeswritten:
+            raise Error, 'cannot change parameters after starting to write'
+        if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722'):
+            raise Error, 'unsupported compression type'
+        self._comptype = comptype
+        self._compname = compname
+
+    def getcomptype(self):
+        return self._comptype
+
+    def getcompname(self):
+        return self._compname
+
+##  def setversion(self, version):
+##      if self._nframeswritten:
+##          raise Error, 'cannot change parameters after starting to write'
+##      self._version = version
+
+    def setparams(self, info):
+        nchannels, sampwidth, framerate, nframes, comptype, compname = info
+        if self._nframeswritten:
+            raise Error, 'cannot change parameters after starting to write'
+        if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722'):
+            raise Error, 'unsupported compression type'
+        self.setnchannels(nchannels)
+        self.setsampwidth(sampwidth)
+        self.setframerate(framerate)
+        self.setnframes(nframes)
+        self.setcomptype(comptype, compname)
+
+    def getparams(self):
+        if not self._nchannels or not self._sampwidth or not self._framerate:
+            raise Error, 'not all parameters set'
+        return self._nchannels, self._sampwidth, self._framerate, \
+              self._nframes, self._comptype, self._compname
+
+    def setmark(self, id, pos, name):
+        if id <= 0:
+            raise Error, 'marker ID must be > 0'
+        if pos < 0:
+            raise Error, 'marker position must be >= 0'
+        if type(name) != type(''):
+            raise Error, 'marker name must be a string'
+        for i in range(len(self._markers)):
+            if id == self._markers[i][0]:
+                self._markers[i] = id, pos, name
+                return
+        self._markers.append((id, pos, name))
+
+    def getmark(self, id):
+        for marker in self._markers:
+            if id == marker[0]:
+                return marker
+        raise Error, 'marker %r does not exist' % (id,)
+
+    def getmarkers(self):
+        if len(self._markers) == 0:
+            return None
+        return self._markers
+
+    def tell(self):
+        return self._nframeswritten
+
+    def writeframesraw(self, data):
+        self._ensure_header_written(len(data))
+        nframes = len(data) // (self._sampwidth * self._nchannels)
+        if self._convert:
+            data = self._convert(data)
+        self._file.write(data)
+        self._nframeswritten = self._nframeswritten + nframes
+        self._datawritten = self._datawritten + len(data)
+
+    def writeframes(self, data):
+        self.writeframesraw(data)
+        if self._nframeswritten != self._nframes or \
+              self._datalength != self._datawritten:
+            self._patchheader()
+
+    def close(self):
+        if self._file is None:
+            return
+        try:
+            self._ensure_header_written(0)
+            if self._datawritten & 1:
+                # quick pad to even size
+                self._file.write(chr(0))
+                self._datawritten = self._datawritten + 1
+            self._writemarkers()
+            if self._nframeswritten != self._nframes or \
+                  self._datalength != self._datawritten or \
+                  self._marklength:
+                self._patchheader()
+            if self._comp:
+                self._comp.CloseCompressor()
+                self._comp = None
+        finally:
+            # Prevent ref cycles
+            self._convert = None
+            f = self._file
+            self._file = None
+            f.close()
+
+    #
+    # Internal methods.
+    #
+
+    def _comp_data(self, data):
+        import cl
+        dummy = self._comp.SetParam(cl.FRAME_BUFFER_SIZE, len(data))
+        dummy = self._comp.SetParam(cl.COMPRESSED_BUFFER_SIZE, len(data))
+        return self._comp.Compress(self._nframes, data)
+
+    def _lin2ulaw(self, data):
+        import audioop
+        return audioop.lin2ulaw(data, 2)
+
+    def _lin2adpcm(self, data):
+        import audioop
+        if not hasattr(self, '_adpcmstate'):
+            self._adpcmstate = None
+        data, self._adpcmstate = audioop.lin2adpcm(data, 2,
+                               self._adpcmstate)
+        return data
+
+    def _ensure_header_written(self, datasize):
+        if not self._nframeswritten:
+            if self._comptype in ('ULAW', 'ALAW'):
+                if not self._sampwidth:
+                    self._sampwidth = 2
+                if self._sampwidth != 2:
+                    raise Error, 'sample width must be 2 when compressing with ULAW or ALAW'
+            if self._comptype == 'G722':
+                if not self._sampwidth:
+                    self._sampwidth = 2
+                if self._sampwidth != 2:
+                    raise Error, 'sample width must be 2 when compressing with G7.22 (ADPCM)'
+            if not self._nchannels:
+                raise Error, '# channels not specified'
+            if not self._sampwidth:
+                raise Error, 'sample width not specified'
+            if not self._framerate:
+                raise Error, 'sampling rate not specified'
+            self._write_header(datasize)
+
+    def _init_compression(self):
+        if self._comptype == 'G722':
+            self._convert = self._lin2adpcm
+            return
+        try:
+            import cl
+        except ImportError:
+            if self._comptype == 'ULAW':
+                try:
+                    import audioop
+                    self._convert = self._lin2ulaw
+                    return
+                except ImportError:
+                    pass
+            raise Error, 'cannot write compressed AIFF-C files'
+        if self._comptype == 'ULAW':
+            scheme = cl.G711_ULAW
+        elif self._comptype == 'ALAW':
+            scheme = cl.G711_ALAW
+        else:
+            raise Error, 'unsupported compression type'
+        self._comp = cl.OpenCompressor(scheme)
+        params = [cl.ORIGINAL_FORMAT, 0,
+              cl.BITS_PER_COMPONENT, self._sampwidth * 8,
+              cl.FRAME_RATE, self._framerate,
+              cl.FRAME_BUFFER_SIZE, 100,
+              cl.COMPRESSED_BUFFER_SIZE, 100]
+        if self._nchannels == 1:
+            params[1] = cl.MONO
+        elif self._nchannels == 2:
+            params[1] = cl.STEREO_INTERLEAVED
+        else:
+            raise Error, 'cannot compress more than 2 channels'
+        self._comp.SetParams(params)
+        # the compressor produces a header which we ignore
+        dummy = self._comp.Compress(0, '')
+        self._convert = self._comp_data
+
+    def _write_header(self, initlength):
+        if self._aifc and self._comptype != 'NONE':
+            self._init_compression()
+        self._file.write('FORM')
+        if not self._nframes:
+            self._nframes = initlength // (self._nchannels * self._sampwidth)
+        self._datalength = self._nframes * self._nchannels * self._sampwidth
+        if self._datalength & 1:
+            self._datalength = self._datalength + 1
+        if self._aifc:
+            if self._comptype in ('ULAW', 'ALAW'):
+                self._datalength = self._datalength // 2
+                if self._datalength & 1:
+                    self._datalength = self._datalength + 1
+            elif self._comptype == 'G722':
+                self._datalength = (self._datalength + 3) // 4
+                if self._datalength & 1:
+                    self._datalength = self._datalength + 1
+        self._form_length_pos = self._file.tell()
+        commlength = self._write_form_length(self._datalength)
+        if self._aifc:
+            self._file.write('AIFC')
+            self._file.write('FVER')
+            _write_ulong(self._file, 4)
+            _write_ulong(self._file, self._version)
+        else:
+            self._file.write('AIFF')
+        self._file.write('COMM')
+        _write_ulong(self._file, commlength)
+        _write_short(self._file, self._nchannels)
+        self._nframes_pos = self._file.tell()
+        _write_ulong(self._file, self._nframes)
+        _write_short(self._file, self._sampwidth * 8)
+        _write_float(self._file, self._framerate)
+        if self._aifc:
+            self._file.write(self._comptype)
+            _write_string(self._file, self._compname)
+        self._file.write('SSND')
+        self._ssnd_length_pos = self._file.tell()
+        _write_ulong(self._file, self._datalength + 8)
+        _write_ulong(self._file, 0)
+        _write_ulong(self._file, 0)
+
+    def _write_form_length(self, datalength):
+        if self._aifc:
+            commlength = 18 + 5 + len(self._compname)
+            if commlength & 1:
+                commlength = commlength + 1
+            verslength = 12
+        else:
+            commlength = 18
+            verslength = 0
+        _write_ulong(self._file, 4 + verslength + self._marklength + \
+                     8 + commlength + 16 + datalength)
+        return commlength
+
+    def _patchheader(self):
+        curpos = self._file.tell()
+        if self._datawritten & 1:
+            datalength = self._datawritten + 1
+            self._file.write(chr(0))
+        else:
+            datalength = self._datawritten
+        if datalength == self._datalength and \
+              self._nframes == self._nframeswritten and \
+              self._marklength == 0:
+            self._file.seek(curpos, 0)
+            return
+        self._file.seek(self._form_length_pos, 0)
+        dummy = self._write_form_length(datalength)
+        self._file.seek(self._nframes_pos, 0)
+        _write_ulong(self._file, self._nframeswritten)
+        self._file.seek(self._ssnd_length_pos, 0)
+        _write_ulong(self._file, datalength + 8)
+        self._file.seek(curpos, 0)
+        self._nframes = self._nframeswritten
+        self._datalength = datalength
+
+    def _writemarkers(self):
+        if len(self._markers) == 0:
+            return
+        self._file.write('MARK')
+        length = 2
+        for marker in self._markers:
+            id, pos, name = marker
+            length = length + len(name) + 1 + 6
+            if len(name) & 1 == 0:
+                length = length + 1
+        _write_ulong(self._file, length)
+        self._marklength = length + 8
+        _write_short(self._file, len(self._markers))
+        for marker in self._markers:
+            id, pos, name = marker
+            _write_short(self._file, id)
+            _write_ulong(self._file, pos)
+            _write_string(self._file, name)
+
+def open(f, mode=None):
+    if mode is None:
+        if hasattr(f, 'mode'):
+            mode = f.mode
+        else:
+            mode = 'rb'
+    if mode in ('r', 'rb'):
+        return Aifc_read(f)
+    elif mode in ('w', 'wb'):
+        return Aifc_write(f)
+    else:
+        raise Error, "mode must be 'r', 'rb', 'w', or 'wb'"
+
+openfp = open # B/W compatibility
+
+if __name__ == '__main__':
+    import sys
+    if not sys.argv[1:]:
+        sys.argv.append('/usr/demos/data/audio/bach.aiff')
+    fn = sys.argv[1]
+    f = open(fn, 'r')
+    print "Reading", fn
+    print "nchannels =", f.getnchannels()
+    print "nframes   =", f.getnframes()
+    print "sampwidth =", f.getsampwidth()
+    print "framerate =", f.getframerate()
+    print "comptype  =", f.getcomptype()
+    print "compname  =", f.getcompname()
+    if sys.argv[2:]:
+        gn = sys.argv[2]
+        print "Writing", gn
+        g = open(gn, 'w')
+        g.setparams(f.getparams())
+        while 1:
+            data = f.readframes(1024)
+            if not data:
+                break
+            g.writeframes(data)
+        g.close()
+        f.close()
+        print "Done."
diff --git a/src/main/resources/PythonLibs/anydbm.py b/src/main/resources/PythonLibs/anydbm.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba7e90510a0a523a53c81a0c9b168caf4a2da251
--- /dev/null
+++ b/src/main/resources/PythonLibs/anydbm.py
@@ -0,0 +1,85 @@
+"""Generic interface to all dbm clones.
+
+Instead of
+
+        import dbm
+        d = dbm.open(file, 'w', 0666)
+
+use
+
+        import anydbm
+        d = anydbm.open(file, 'w')
+
+The returned object is a dbhash, gdbm, dbm or dumbdbm object,
+dependent on the type of database being opened (determined by whichdb
+module) in the case of an existing dbm. If the dbm does not exist and
+the create or new flag ('c' or 'n') was specified, the dbm type will
+be determined by the availability of the modules (tested in the above
+order).
+
+It has the following interface (key and data are strings):
+
+        d[key] = data   # store data at key (may override data at
+                        # existing key)
+        data = d[key]   # retrieve data at key (raise KeyError if no
+                        # such key)
+        del d[key]      # delete data stored at key (raises KeyError
+                        # if no such key)
+        flag = key in d   # true if the key exists
+        list = d.keys() # return a list of all existing keys (slow!)
+
+Future versions may change the order in which implementations are
+tested for existence, and add interfaces to other dbm-like
+implementations.
+"""
+
+class error(Exception):
+    pass
+
+_names = ['dbhash', 'gdbm', 'dbm', 'dumbdbm']
+_errors = [error]
+_defaultmod = None
+
+for _name in _names:
+    try:
+        _mod = __import__(_name)
+    except ImportError:
+        continue
+    if not _defaultmod:
+        _defaultmod = _mod
+    _errors.append(_mod.error)
+
+if not _defaultmod:
+    raise ImportError, "no dbm clone found; tried %s" % _names
+
+error = tuple(_errors)
+
+def open(file, flag='r', mode=0666):
+    """Open or create database at path given by *file*.
+
+    Optional argument *flag* can be 'r' (default) for read-only access, 'w'
+    for read-write access of an existing database, 'c' for read-write access
+    to a new or existing database, and 'n' for read-write access to a new
+    database.
+
+    Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it
+    only if it doesn't exist; and 'n' always creates a new database.
+    """
+
+    # guess the type of an existing database
+    from whichdb import whichdb
+    result=whichdb(file)
+    if result is None:
+        # db doesn't exist
+        if 'c' in flag or 'n' in flag:
+            # file doesn't exist and the new
+            # flag was used so use default type
+            mod = _defaultmod
+        else:
+            raise error, "need 'c' or 'n' flag to open new db"
+    elif result == "":
+        # db type cannot be determined
+        raise error, "db type could not be determined"
+    else:
+        mod = __import__(result)
+    return mod.open(file, flag, mode)
diff --git a/src/main/resources/PythonLibs/argparse.py b/src/main/resources/PythonLibs/argparse.py
new file mode 100644
index 0000000000000000000000000000000000000000..30bae57896c316501940247fa76512756ea08932
--- /dev/null
+++ b/src/main/resources/PythonLibs/argparse.py
@@ -0,0 +1,2361 @@
+# Author: Steven J. Bethard <steven.bethard@gmail.com>.
+
+"""Command-line parsing library
+
+This module is an optparse-inspired command-line parsing library that:
+
+    - handles both optional and positional arguments
+    - produces highly informative usage messages
+    - supports parsers that dispatch to sub-parsers
+
+The following is a simple usage example that sums integers from the
+command-line and writes the result to a file::
+
+    parser = argparse.ArgumentParser(
+        description='sum the integers at the command line')
+    parser.add_argument(
+        'integers', metavar='int', nargs='+', type=int,
+        help='an integer to be summed')
+    parser.add_argument(
+        '--log', default=sys.stdout, type=argparse.FileType('w'),
+        help='the file where the sum should be written')
+    args = parser.parse_args()
+    args.log.write('%s' % sum(args.integers))
+    args.log.close()
+
+The module contains the following public classes:
+
+    - ArgumentParser -- The main entry point for command-line parsing. As the
+        example above shows, the add_argument() method is used to populate
+        the parser with actions for optional and positional arguments. Then
+        the parse_args() method is invoked to convert the args at the
+        command-line into an object with attributes.
+
+    - ArgumentError -- The exception raised by ArgumentParser objects when
+        there are errors with the parser's actions. Errors raised while
+        parsing the command-line are caught by ArgumentParser and emitted
+        as command-line messages.
+
+    - FileType -- A factory for defining types of files to be created. As the
+        example above shows, instances of FileType are typically passed as
+        the type= argument of add_argument() calls.
+
+    - Action -- The base class for parser actions. Typically actions are
+        selected by passing strings like 'store_true' or 'append_const' to
+        the action= argument of add_argument(). However, for greater
+        customization of ArgumentParser actions, subclasses of Action may
+        be defined and passed as the action= argument.
+
+    - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
+        ArgumentDefaultsHelpFormatter -- Formatter classes which
+        may be passed as the formatter_class= argument to the
+        ArgumentParser constructor. HelpFormatter is the default,
+        RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
+        not to change the formatting for help text, and
+        ArgumentDefaultsHelpFormatter adds information about argument defaults
+        to the help.
+
+All other classes in this module are considered implementation details.
+(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
+considered public as object names -- the API of the formatter objects is
+still considered an implementation detail.)
+"""
+
+__version__ = '1.1'
+__all__ = [
+    'ArgumentParser',
+    'ArgumentError',
+    'ArgumentTypeError',
+    'FileType',
+    'HelpFormatter',
+    'ArgumentDefaultsHelpFormatter',
+    'RawDescriptionHelpFormatter',
+    'RawTextHelpFormatter',
+    'Namespace',
+    'Action',
+    'ONE_OR_MORE',
+    'OPTIONAL',
+    'PARSER',
+    'REMAINDER',
+    'SUPPRESS',
+    'ZERO_OR_MORE',
+]
+
+
+import collections as _collections
+import copy as _copy
+import os as _os
+import re as _re
+import sys as _sys
+import textwrap as _textwrap
+
+from gettext import gettext as _
+
+
+def _callable(obj):
+    return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
+
+
+SUPPRESS = '==SUPPRESS=='
+
+OPTIONAL = '?'
+ZERO_OR_MORE = '*'
+ONE_OR_MORE = '+'
+PARSER = 'A...'
+REMAINDER = '...'
+_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'
+
+# =============================
+# Utility functions and classes
+# =============================
+
+class _AttributeHolder(object):
+    """Abstract base class that provides __repr__.
+
+    The __repr__ method returns a string in the format::
+        ClassName(attr=name, attr=name, ...)
+    The attributes are determined either by a class-level attribute,
+    '_kwarg_names', or by inspecting the instance __dict__.
+    """
+
+    def __repr__(self):
+        type_name = type(self).__name__
+        arg_strings = []
+        for arg in self._get_args():
+            arg_strings.append(repr(arg))
+        for name, value in self._get_kwargs():
+            arg_strings.append('%s=%r' % (name, value))
+        return '%s(%s)' % (type_name, ', '.join(arg_strings))
+
+    def _get_kwargs(self):
+        return sorted(self.__dict__.items())
+
+    def _get_args(self):
+        return []
+
+
+def _ensure_value(namespace, name, value):
+    if getattr(namespace, name, None) is None:
+        setattr(namespace, name, value)
+    return getattr(namespace, name)
+
+
+# ===============
+# Formatting Help
+# ===============
+
+class HelpFormatter(object):
+    """Formatter for generating usage messages and argument help strings.
+
+    Only the name of this class is considered a public API. All the methods
+    provided by the class are considered an implementation detail.
+    """
+
+    def __init__(self,
+                 prog,
+                 indent_increment=2,
+                 max_help_position=24,
+                 width=None):
+
+        # default setting for width
+        if width is None:
+            try:
+                width = int(_os.environ['COLUMNS'])
+            except (KeyError, ValueError):
+                width = 80
+            width -= 2
+
+        self._prog = prog
+        self._indent_increment = indent_increment
+        self._max_help_position = max_help_position
+        self._width = width
+
+        self._current_indent = 0
+        self._level = 0
+        self._action_max_length = 0
+
+        self._root_section = self._Section(self, None)
+        self._current_section = self._root_section
+
+        self._whitespace_matcher = _re.compile(r'\s+')
+        self._long_break_matcher = _re.compile(r'\n\n\n+')
+
+    # ===============================
+    # Section and indentation methods
+    # ===============================
+    def _indent(self):
+        self._current_indent += self._indent_increment
+        self._level += 1
+
+    def _dedent(self):
+        self._current_indent -= self._indent_increment
+        assert self._current_indent >= 0, 'Indent decreased below 0.'
+        self._level -= 1
+
+    class _Section(object):
+
+        def __init__(self, formatter, parent, heading=None):
+            self.formatter = formatter
+            self.parent = parent
+            self.heading = heading
+            self.items = []
+
+        def format_help(self):
+            # format the indented section
+            if self.parent is not None:
+                self.formatter._indent()
+            join = self.formatter._join_parts
+            for func, args in self.items:
+                func(*args)
+            item_help = join([func(*args) for func, args in self.items])
+            if self.parent is not None:
+                self.formatter._dedent()
+
+            # return nothing if the section was empty
+            if not item_help:
+                return ''
+
+            # add the heading if the section was non-empty
+            if self.heading is not SUPPRESS and self.heading is not None:
+                current_indent = self.formatter._current_indent
+                heading = '%*s%s:\n' % (current_indent, '', self.heading)
+            else:
+                heading = ''
+
+            # join the section-initial newline, the heading and the help
+            return join(['\n', heading, item_help, '\n'])
+
+    def _add_item(self, func, args):
+        self._current_section.items.append((func, args))
+
+    # ========================
+    # Message building methods
+    # ========================
+    def start_section(self, heading):
+        self._indent()
+        section = self._Section(self, self._current_section, heading)
+        self._add_item(section.format_help, [])
+        self._current_section = section
+
+    def end_section(self):
+        self._current_section = self._current_section.parent
+        self._dedent()
+
+    def add_text(self, text):
+        if text is not SUPPRESS and text is not None:
+            self._add_item(self._format_text, [text])
+
+    def add_usage(self, usage, actions, groups, prefix=None):
+        if usage is not SUPPRESS:
+            args = usage, actions, groups, prefix
+            self._add_item(self._format_usage, args)
+
+    def add_argument(self, action):
+        if action.help is not SUPPRESS:
+
+            # find all invocations
+            get_invocation = self._format_action_invocation
+            invocations = [get_invocation(action)]
+            for subaction in self._iter_indented_subactions(action):
+                invocations.append(get_invocation(subaction))
+
+            # update the maximum item length
+            invocation_length = max([len(s) for s in invocations])
+            action_length = invocation_length + self._current_indent
+            self._action_max_length = max(self._action_max_length,
+                                          action_length)
+
+            # add the item to the list
+            self._add_item(self._format_action, [action])
+
+    def add_arguments(self, actions):
+        for action in actions:
+            self.add_argument(action)
+
+    # =======================
+    # Help-formatting methods
+    # =======================
+    def format_help(self):
+        help = self._root_section.format_help()
+        if help:
+            help = self._long_break_matcher.sub('\n\n', help)
+            help = help.strip('\n') + '\n'
+        return help
+
+    def _join_parts(self, part_strings):
+        return ''.join([part
+                        for part in part_strings
+                        if part and part is not SUPPRESS])
+
+    def _format_usage(self, usage, actions, groups, prefix):
+        if prefix is None:
+            prefix = _('usage: ')
+
+        # if usage is specified, use that
+        if usage is not None:
+            usage = usage % dict(prog=self._prog)
+
+        # if no optionals or positionals are available, usage is just prog
+        elif usage is None and not actions:
+            usage = '%(prog)s' % dict(prog=self._prog)
+
+        # if optionals and positionals are available, calculate usage
+        elif usage is None:
+            prog = '%(prog)s' % dict(prog=self._prog)
+
+            # split optionals from positionals
+            optionals = []
+            positionals = []
+            for action in actions:
+                if action.option_strings:
+                    optionals.append(action)
+                else:
+                    positionals.append(action)
+
+            # build full usage string
+            format = self._format_actions_usage
+            action_usage = format(optionals + positionals, groups)
+            usage = ' '.join([s for s in [prog, action_usage] if s])
+
+            # wrap the usage parts if it's too long
+            text_width = self._width - self._current_indent
+            if len(prefix) + len(usage) > text_width:
+
+                # break usage into wrappable parts
+                part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
+                opt_usage = format(optionals, groups)
+                pos_usage = format(positionals, groups)
+                opt_parts = _re.findall(part_regexp, opt_usage)
+                pos_parts = _re.findall(part_regexp, pos_usage)
+                assert ' '.join(opt_parts) == opt_usage
+                assert ' '.join(pos_parts) == pos_usage
+
+                # helper for wrapping lines
+                def get_lines(parts, indent, prefix=None):
+                    lines = []
+                    line = []
+                    if prefix is not None:
+                        line_len = len(prefix) - 1
+                    else:
+                        line_len = len(indent) - 1
+                    for part in parts:
+                        if line_len + 1 + len(part) > text_width:
+                            lines.append(indent + ' '.join(line))
+                            line = []
+                            line_len = len(indent) - 1
+                        line.append(part)
+                        line_len += len(part) + 1
+                    if line:
+                        lines.append(indent + ' '.join(line))
+                    if prefix is not None:
+                        lines[0] = lines[0][len(indent):]
+                    return lines
+
+                # if prog is short, follow it with optionals or positionals
+                if len(prefix) + len(prog) <= 0.75 * text_width:
+                    indent = ' ' * (len(prefix) + len(prog) + 1)
+                    if opt_parts:
+                        lines = get_lines([prog] + opt_parts, indent, prefix)
+                        lines.extend(get_lines(pos_parts, indent))
+                    elif pos_parts:
+                        lines = get_lines([prog] + pos_parts, indent, prefix)
+                    else:
+                        lines = [prog]
+
+                # if prog is long, put it on its own line
+                else:
+                    indent = ' ' * len(prefix)
+                    parts = opt_parts + pos_parts
+                    lines = get_lines(parts, indent)
+                    if len(lines) > 1:
+                        lines = []
+                        lines.extend(get_lines(opt_parts, indent))
+                        lines.extend(get_lines(pos_parts, indent))
+                    lines = [prog] + lines
+
+                # join lines into usage
+                usage = '\n'.join(lines)
+
+        # prefix with 'usage:'
+        return '%s%s\n\n' % (prefix, usage)
+
+    def _format_actions_usage(self, actions, groups):
+        # find group indices and identify actions in groups
+        group_actions = set()
+        inserts = {}
+        for group in groups:
+            try:
+                start = actions.index(group._group_actions[0])
+            except ValueError:
+                continue
+            else:
+                end = start + len(group._group_actions)
+                if actions[start:end] == group._group_actions:
+                    for action in group._group_actions:
+                        group_actions.add(action)
+                    if not group.required:
+                        if start in inserts:
+                            inserts[start] += ' ['
+                        else:
+                            inserts[start] = '['
+                        inserts[end] = ']'
+                    else:
+                        if start in inserts:
+                            inserts[start] += ' ('
+                        else:
+                            inserts[start] = '('
+                        inserts[end] = ')'
+                    for i in range(start + 1, end):
+                        inserts[i] = '|'
+
+        # collect all actions format strings
+        parts = []
+        for i, action in enumerate(actions):
+
+            # suppressed arguments are marked with None
+            # remove | separators for suppressed arguments
+            if action.help is SUPPRESS:
+                parts.append(None)
+                if inserts.get(i) == '|':
+                    inserts.pop(i)
+                elif inserts.get(i + 1) == '|':
+                    inserts.pop(i + 1)
+
+            # produce all arg strings
+            elif not action.option_strings:
+                part = self._format_args(action, action.dest)
+
+                # if it's in a group, strip the outer []
+                if action in group_actions:
+                    if part[0] == '[' and part[-1] == ']':
+                        part = part[1:-1]
+
+                # add the action string to the list
+                parts.append(part)
+
+            # produce the first way to invoke the option in brackets
+            else:
+                option_string = action.option_strings[0]
+
+                # if the Optional doesn't take a value, format is:
+                #    -s or --long
+                if action.nargs == 0:
+                    part = '%s' % option_string
+
+                # if the Optional takes a value, format is:
+                #    -s ARGS or --long ARGS
+                else:
+                    default = action.dest.upper()
+                    args_string = self._format_args(action, default)
+                    part = '%s %s' % (option_string, args_string)
+
+                # make it look optional if it's not required or in a group
+                if not action.required and action not in group_actions:
+                    part = '[%s]' % part
+
+                # add the action string to the list
+                parts.append(part)
+
+        # insert things at the necessary indices
+        for i in sorted(inserts, reverse=True):
+            parts[i:i] = [inserts[i]]
+
+        # join all the action items with spaces
+        text = ' '.join([item for item in parts if item is not None])
+
+        # clean up separators for mutually exclusive groups
+        open = r'[\[(]'
+        close = r'[\])]'
+        text = _re.sub(r'(%s) ' % open, r'\1', text)
+        text = _re.sub(r' (%s)' % close, r'\1', text)
+        text = _re.sub(r'%s *%s' % (open, close), r'', text)
+        text = _re.sub(r'\(([^|]*)\)', r'\1', text)
+        text = text.strip()
+
+        # return the text
+        return text
+
+    def _format_text(self, text):
+        if '%(prog)' in text:
+            text = text % dict(prog=self._prog)
+        text_width = self._width - self._current_indent
+        indent = ' ' * self._current_indent
+        return self._fill_text(text, text_width, indent) + '\n\n'
+
+    def _format_action(self, action):
+        # determine the required width and the entry label
+        help_position = min(self._action_max_length + 2,
+                            self._max_help_position)
+        help_width = self._width - help_position
+        action_width = help_position - self._current_indent - 2
+        action_header = self._format_action_invocation(action)
+
+        # ho nelp; start on same line and add a final newline
+        if not action.help:
+            tup = self._current_indent, '', action_header
+            action_header = '%*s%s\n' % tup
+
+        # short action name; start on the same line and pad two spaces
+        elif len(action_header) <= action_width:
+            tup = self._current_indent, '', action_width, action_header
+            action_header = '%*s%-*s  ' % tup
+            indent_first = 0
+
+        # long action name; start on the next line
+        else:
+            tup = self._current_indent, '', action_header
+            action_header = '%*s%s\n' % tup
+            indent_first = help_position
+
+        # collect the pieces of the action help
+        parts = [action_header]
+
+        # if there was help for the action, add lines of help text
+        if action.help:
+            help_text = self._expand_help(action)
+            help_lines = self._split_lines(help_text, help_width)
+            parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
+            for line in help_lines[1:]:
+                parts.append('%*s%s\n' % (help_position, '', line))
+
+        # or add a newline if the description doesn't end with one
+        elif not action_header.endswith('\n'):
+            parts.append('\n')
+
+        # if there are any sub-actions, add their help as well
+        for subaction in self._iter_indented_subactions(action):
+            parts.append(self._format_action(subaction))
+
+        # return a single string
+        return self._join_parts(parts)
+
+    def _format_action_invocation(self, action):
+        if not action.option_strings:
+            metavar, = self._metavar_formatter(action, action.dest)(1)
+            return metavar
+
+        else:
+            parts = []
+
+            # if the Optional doesn't take a value, format is:
+            #    -s, --long
+            if action.nargs == 0:
+                parts.extend(action.option_strings)
+
+            # if the Optional takes a value, format is:
+            #    -s ARGS, --long ARGS
+            else:
+                default = action.dest.upper()
+                args_string = self._format_args(action, default)
+                for option_string in action.option_strings:
+                    parts.append('%s %s' % (option_string, args_string))
+
+            return ', '.join(parts)
+
+    def _metavar_formatter(self, action, default_metavar):
+        if action.metavar is not None:
+            result = action.metavar
+        elif action.choices is not None:
+            choice_strs = [str(choice) for choice in action.choices]
+            result = '{%s}' % ','.join(choice_strs)
+        else:
+            result = default_metavar
+
+        def format(tuple_size):
+            if isinstance(result, tuple):
+                return result
+            else:
+                return (result, ) * tuple_size
+        return format
+
+    def _format_args(self, action, default_metavar):
+        get_metavar = self._metavar_formatter(action, default_metavar)
+        if action.nargs is None:
+            result = '%s' % get_metavar(1)
+        elif action.nargs == OPTIONAL:
+            result = '[%s]' % get_metavar(1)
+        elif action.nargs == ZERO_OR_MORE:
+            result = '[%s [%s ...]]' % get_metavar(2)
+        elif action.nargs == ONE_OR_MORE:
+            result = '%s [%s ...]' % get_metavar(2)
+        elif action.nargs == REMAINDER:
+            result = '...'
+        elif action.nargs == PARSER:
+            result = '%s ...' % get_metavar(1)
+        else:
+            formats = ['%s' for _ in range(action.nargs)]
+            result = ' '.join(formats) % get_metavar(action.nargs)
+        return result
+
+    def _expand_help(self, action):
+        params = dict(vars(action), prog=self._prog)
+        for name in list(params):
+            if params[name] is SUPPRESS:
+                del params[name]
+        for name in list(params):
+            if hasattr(params[name], '__name__'):
+                params[name] = params[name].__name__
+        if params.get('choices') is not None:
+            choices_str = ', '.join([str(c) for c in params['choices']])
+            params['choices'] = choices_str
+        return self._get_help_string(action) % params
+
+    def _iter_indented_subactions(self, action):
+        try:
+            get_subactions = action._get_subactions
+        except AttributeError:
+            pass
+        else:
+            self._indent()
+            for subaction in get_subactions():
+                yield subaction
+            self._dedent()
+
+    def _split_lines(self, text, width):
+        text = self._whitespace_matcher.sub(' ', text).strip()
+        return _textwrap.wrap(text, width)
+
+    def _fill_text(self, text, width, indent):
+        text = self._whitespace_matcher.sub(' ', text).strip()
+        return _textwrap.fill(text, width, initial_indent=indent,
+                                           subsequent_indent=indent)
+
+    def _get_help_string(self, action):
+        return action.help
+
+
+class RawDescriptionHelpFormatter(HelpFormatter):
+    """Help message formatter which retains any formatting in descriptions.
+
+    Only the name of this class is considered a public API. All the methods
+    provided by the class are considered an implementation detail.
+    """
+
+    def _fill_text(self, text, width, indent):
+        return ''.join([indent + line for line in text.splitlines(True)])
+
+
+class RawTextHelpFormatter(RawDescriptionHelpFormatter):
+    """Help message formatter which retains formatting of all help text.
+
+    Only the name of this class is considered a public API. All the methods
+    provided by the class are considered an implementation detail.
+    """
+
+    def _split_lines(self, text, width):
+        return text.splitlines()
+
+
+class ArgumentDefaultsHelpFormatter(HelpFormatter):
+    """Help message formatter which adds default values to argument help.
+
+    Only the name of this class is considered a public API. All the methods
+    provided by the class are considered an implementation detail.
+    """
+
+    def _get_help_string(self, action):
+        help = action.help
+        if '%(default)' not in action.help:
+            if action.default is not SUPPRESS:
+                defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
+                if action.option_strings or action.nargs in defaulting_nargs:
+                    help += ' (default: %(default)s)'
+        return help
+
+
+# =====================
+# Options and Arguments
+# =====================
+
+def _get_action_name(argument):
+    if argument is None:
+        return None
+    elif argument.option_strings:
+        return  '/'.join(argument.option_strings)
+    elif argument.metavar not in (None, SUPPRESS):
+        return argument.metavar
+    elif argument.dest not in (None, SUPPRESS):
+        return argument.dest
+    else:
+        return None
+
+
+class ArgumentError(Exception):
+    """An error from creating or using an argument (optional or positional).
+
+    The string value of this exception is the message, augmented with
+    information about the argument that caused it.
+    """
+
+    def __init__(self, argument, message):
+        self.argument_name = _get_action_name(argument)
+        self.message = message
+
+    def __str__(self):
+        if self.argument_name is None:
+            format = '%(message)s'
+        else:
+            format = 'argument %(argument_name)s: %(message)s'
+        return format % dict(message=self.message,
+                             argument_name=self.argument_name)
+
+
+class ArgumentTypeError(Exception):
+    """An error from trying to convert a command line string to a type."""
+    pass
+
+
+# ==============
+# Action classes
+# ==============
+
+class Action(_AttributeHolder):
+    """Information about how to convert command line strings to Python objects.
+
+    Action objects are used by an ArgumentParser to represent the information
+    needed to parse a single argument from one or more strings from the
+    command line. The keyword arguments to the Action constructor are also
+    all attributes of Action instances.
+
+    Keyword Arguments:
+
+        - option_strings -- A list of command-line option strings which
+            should be associated with this action.
+
+        - dest -- The name of the attribute to hold the created object(s)
+
+        - nargs -- The number of command-line arguments that should be
+            consumed. By default, one argument will be consumed and a single
+            value will be produced.  Other values include:
+                - N (an integer) consumes N arguments (and produces a list)
+                - '?' consumes zero or one arguments
+                - '*' consumes zero or more arguments (and produces a list)
+                - '+' consumes one or more arguments (and produces a list)
+            Note that the difference between the default and nargs=1 is that
+            with the default, a single value will be produced, while with
+            nargs=1, a list containing a single value will be produced.
+
+        - const -- The value to be produced if the option is specified and the
+            option uses an action that takes no values.
+
+        - default -- The value to be produced if the option is not specified.
+
+        - type -- A callable that accepts a single string argument, and
+            returns the converted value.  The standard Python types str, int,
+            float, and complex are useful examples of such callables.  If None,
+            str is used.
+
+        - choices -- A container of values that should be allowed. If not None,
+            after a command-line argument has been converted to the appropriate
+            type, an exception will be raised if it is not a member of this
+            collection.
+
+        - required -- True if the action must always be specified at the
+            command line. This is only meaningful for optional command-line
+            arguments.
+
+        - help -- The help string describing the argument.
+
+        - metavar -- The name to be used for the option's argument with the
+            help string. If None, the 'dest' value will be used as the name.
+    """
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 nargs=None,
+                 const=None,
+                 default=None,
+                 type=None,
+                 choices=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        self.option_strings = option_strings
+        self.dest = dest
+        self.nargs = nargs
+        self.const = const
+        self.default = default
+        self.type = type
+        self.choices = choices
+        self.required = required
+        self.help = help
+        self.metavar = metavar
+
+    def _get_kwargs(self):
+        names = [
+            'option_strings',
+            'dest',
+            'nargs',
+            'const',
+            'default',
+            'type',
+            'choices',
+            'help',
+            'metavar',
+        ]
+        return [(name, getattr(self, name)) for name in names]
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        raise NotImplementedError(_('.__call__() not defined'))
+
+
+class _StoreAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 nargs=None,
+                 const=None,
+                 default=None,
+                 type=None,
+                 choices=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        if nargs == 0:
+            raise ValueError('nargs for store actions must be > 0; if you '
+                             'have nothing to store, actions such as store '
+                             'true or store const may be more appropriate')
+        if const is not None and nargs != OPTIONAL:
+            raise ValueError('nargs must be %r to supply const' % OPTIONAL)
+        super(_StoreAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=nargs,
+            const=const,
+            default=default,
+            type=type,
+            choices=choices,
+            required=required,
+            help=help,
+            metavar=metavar)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        setattr(namespace, self.dest, values)
+
+
+class _StoreConstAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 const,
+                 default=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        super(_StoreConstAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=0,
+            const=const,
+            default=default,
+            required=required,
+            help=help)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        setattr(namespace, self.dest, self.const)
+
+
+class _StoreTrueAction(_StoreConstAction):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 default=False,
+                 required=False,
+                 help=None):
+        super(_StoreTrueAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            const=True,
+            default=default,
+            required=required,
+            help=help)
+
+
+class _StoreFalseAction(_StoreConstAction):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 default=True,
+                 required=False,
+                 help=None):
+        super(_StoreFalseAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            const=False,
+            default=default,
+            required=required,
+            help=help)
+
+
+class _AppendAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 nargs=None,
+                 const=None,
+                 default=None,
+                 type=None,
+                 choices=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        if nargs == 0:
+            raise ValueError('nargs for append actions must be > 0; if arg '
+                             'strings are not supplying the value to append, '
+                             'the append const action may be more appropriate')
+        if const is not None and nargs != OPTIONAL:
+            raise ValueError('nargs must be %r to supply const' % OPTIONAL)
+        super(_AppendAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=nargs,
+            const=const,
+            default=default,
+            type=type,
+            choices=choices,
+            required=required,
+            help=help,
+            metavar=metavar)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        items = _copy.copy(_ensure_value(namespace, self.dest, []))
+        items.append(values)
+        setattr(namespace, self.dest, items)
+
+
+class _AppendConstAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 const,
+                 default=None,
+                 required=False,
+                 help=None,
+                 metavar=None):
+        super(_AppendConstAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=0,
+            const=const,
+            default=default,
+            required=required,
+            help=help,
+            metavar=metavar)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        items = _copy.copy(_ensure_value(namespace, self.dest, []))
+        items.append(self.const)
+        setattr(namespace, self.dest, items)
+
+
+class _CountAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest,
+                 default=None,
+                 required=False,
+                 help=None):
+        super(_CountAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=0,
+            default=default,
+            required=required,
+            help=help)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        new_count = _ensure_value(namespace, self.dest, 0) + 1
+        setattr(namespace, self.dest, new_count)
+
+
+class _HelpAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 dest=SUPPRESS,
+                 default=SUPPRESS,
+                 help=None):
+        super(_HelpAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            default=default,
+            nargs=0,
+            help=help)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        parser.print_help()
+        parser.exit()
+
+
+class _VersionAction(Action):
+
+    def __init__(self,
+                 option_strings,
+                 version=None,
+                 dest=SUPPRESS,
+                 default=SUPPRESS,
+                 help="show program's version number and exit"):
+        super(_VersionAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            default=default,
+            nargs=0,
+            help=help)
+        self.version = version
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        version = self.version
+        if version is None:
+            version = parser.version
+        formatter = parser._get_formatter()
+        formatter.add_text(version)
+        parser.exit(message=formatter.format_help())
+
+
+class _SubParsersAction(Action):
+
+    class _ChoicesPseudoAction(Action):
+
+        def __init__(self, name, help):
+            sup = super(_SubParsersAction._ChoicesPseudoAction, self)
+            sup.__init__(option_strings=[], dest=name, help=help)
+
+    def __init__(self,
+                 option_strings,
+                 prog,
+                 parser_class,
+                 dest=SUPPRESS,
+                 help=None,
+                 metavar=None):
+
+        self._prog_prefix = prog
+        self._parser_class = parser_class
+        self._name_parser_map = _collections.OrderedDict()
+        self._choices_actions = []
+
+        super(_SubParsersAction, self).__init__(
+            option_strings=option_strings,
+            dest=dest,
+            nargs=PARSER,
+            choices=self._name_parser_map,
+            help=help,
+            metavar=metavar)
+
+    def add_parser(self, name, **kwargs):
+        # set prog from the existing prefix
+        if kwargs.get('prog') is None:
+            kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
+
+        # create a pseudo-action to hold the choice help
+        if 'help' in kwargs:
+            help = kwargs.pop('help')
+            choice_action = self._ChoicesPseudoAction(name, help)
+            self._choices_actions.append(choice_action)
+
+        # create the parser and add it to the map
+        parser = self._parser_class(**kwargs)
+        self._name_parser_map[name] = parser
+        return parser
+
+    def _get_subactions(self):
+        return self._choices_actions
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        parser_name = values[0]
+        arg_strings = values[1:]
+
+        # set the parser name if requested
+        if self.dest is not SUPPRESS:
+            setattr(namespace, self.dest, parser_name)
+
+        # select the parser
+        try:
+            parser = self._name_parser_map[parser_name]
+        except KeyError:
+            tup = parser_name, ', '.join(self._name_parser_map)
+            msg = _('unknown parser %r (choices: %s)') % tup
+            raise ArgumentError(self, msg)
+
+        # parse all the remaining options into the namespace
+        # store any unrecognized options on the object, so that the top
+        # level parser can decide what to do with them
+        namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)
+        if arg_strings:
+            vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
+            getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
+
+
+# ==============
+# Type classes
+# ==============
+
+class FileType(object):
+    """Factory for creating file object types
+
+    Instances of FileType are typically passed as type= arguments to the
+    ArgumentParser add_argument() method.
+
+    Keyword Arguments:
+        - mode -- A string indicating how the file is to be opened. Accepts the
+            same values as the builtin open() function.
+        - bufsize -- The file's desired buffer size. Accepts the same values as
+            the builtin open() function.
+    """
+
+    def __init__(self, mode='r', bufsize=-1):
+        self._mode = mode
+        self._bufsize = bufsize
+
+    def __call__(self, string):
+        # the special argument "-" means sys.std{in,out}
+        if string == '-':
+            if 'r' in self._mode:
+                return _sys.stdin
+            elif 'w' in self._mode:
+                return _sys.stdout
+            else:
+                msg = _('argument "-" with mode %r') % self._mode
+                raise ValueError(msg)
+
+        # all other arguments are used as file names
+        try:
+            return open(string, self._mode, self._bufsize)
+        except IOError as e:
+            message = _("can't open '%s': %s")
+            raise ArgumentTypeError(message % (string, e))
+
+    def __repr__(self):
+        args = self._mode, self._bufsize
+        args_str = ', '.join(repr(arg) for arg in args if arg != -1)
+        return '%s(%s)' % (type(self).__name__, args_str)
+
+# ===========================
+# Optional and Positional Parsing
+# ===========================
+
+class Namespace(_AttributeHolder):
+    """Simple object for storing attributes.
+
+    Implements equality by attribute names and values, and provides a simple
+    string representation.
+    """
+
+    def __init__(self, **kwargs):
+        for name in kwargs:
+            setattr(self, name, kwargs[name])
+
+    __hash__ = None
+
+    def __eq__(self, other):
+        return vars(self) == vars(other)
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __contains__(self, key):
+        return key in self.__dict__
+
+
+class _ActionsContainer(object):
+
+    def __init__(self,
+                 description,
+                 prefix_chars,
+                 argument_default,
+                 conflict_handler):
+        super(_ActionsContainer, self).__init__()
+
+        self.description = description
+        self.argument_default = argument_default
+        self.prefix_chars = prefix_chars
+        self.conflict_handler = conflict_handler
+
+        # set up registries
+        self._registries = {}
+
+        # register actions
+        self.register('action', None, _StoreAction)
+        self.register('action', 'store', _StoreAction)
+        self.register('action', 'store_const', _StoreConstAction)
+        self.register('action', 'store_true', _StoreTrueAction)
+        self.register('action', 'store_false', _StoreFalseAction)
+        self.register('action', 'append', _AppendAction)
+        self.register('action', 'append_const', _AppendConstAction)
+        self.register('action', 'count', _CountAction)
+        self.register('action', 'help', _HelpAction)
+        self.register('action', 'version', _VersionAction)
+        self.register('action', 'parsers', _SubParsersAction)
+
+        # raise an exception if the conflict handler is invalid
+        self._get_handler()
+
+        # action storage
+        self._actions = []
+        self._option_string_actions = {}
+
+        # groups
+        self._action_groups = []
+        self._mutually_exclusive_groups = []
+
+        # defaults storage
+        self._defaults = {}
+
+        # determines whether an "option" looks like a negative number
+        self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')
+
+        # whether or not there are any optionals that look like negative
+        # numbers -- uses a list so it can be shared and edited
+        self._has_negative_number_optionals = []
+
+    # ====================
+    # Registration methods
+    # ====================
+    def register(self, registry_name, value, object):
+        registry = self._registries.setdefault(registry_name, {})
+        registry[value] = object
+
+    def _registry_get(self, registry_name, value, default=None):
+        return self._registries[registry_name].get(value, default)
+
+    # ==================================
+    # Namespace default accessor methods
+    # ==================================
+    def set_defaults(self, **kwargs):
+        self._defaults.update(kwargs)
+
+        # if these defaults match any existing arguments, replace
+        # the previous default on the object with the new one
+        for action in self._actions:
+            if action.dest in kwargs:
+                action.default = kwargs[action.dest]
+
+    def get_default(self, dest):
+        for action in self._actions:
+            if action.dest == dest and action.default is not None:
+                return action.default
+        return self._defaults.get(dest, None)
+
+
+    # =======================
+    # Adding argument actions
+    # =======================
+    def add_argument(self, *args, **kwargs):
+        """
+        add_argument(dest, ..., name=value, ...)
+        add_argument(option_string, option_string, ..., name=value, ...)
+        """
+
+        # if no positional args are supplied or only one is supplied and
+        # it doesn't look like an option string, parse a positional
+        # argument
+        chars = self.prefix_chars
+        if not args or len(args) == 1 and args[0][0] not in chars:
+            if args and 'dest' in kwargs:
+                raise ValueError('dest supplied twice for positional argument')
+            kwargs = self._get_positional_kwargs(*args, **kwargs)
+
+        # otherwise, we're adding an optional argument
+        else:
+            kwargs = self._get_optional_kwargs(*args, **kwargs)
+
+        # if no default was supplied, use the parser-level default
+        if 'default' not in kwargs:
+            dest = kwargs['dest']
+            if dest in self._defaults:
+                kwargs['default'] = self._defaults[dest]
+            elif self.argument_default is not None:
+                kwargs['default'] = self.argument_default
+
+        # create the action object, and add it to the parser
+        action_class = self._pop_action_class(kwargs)
+        if not _callable(action_class):
+            raise ValueError('unknown action "%s"' % (action_class,))
+        action = action_class(**kwargs)
+
+        # raise an error if the action type is not callable
+        type_func = self._registry_get('type', action.type, action.type)
+        if not _callable(type_func):
+            raise ValueError('%r is not callable' % (type_func,))
+
+        # raise an error if the metavar does not match the type
+        if hasattr(self, "_get_formatter"):
+            try:
+                self._get_formatter()._format_args(action, None)
+            except TypeError:
+                raise ValueError("length of metavar tuple does not match nargs")
+
+        return self._add_action(action)
+
+    def add_argument_group(self, *args, **kwargs):
+        group = _ArgumentGroup(self, *args, **kwargs)
+        self._action_groups.append(group)
+        return group
+
+    def add_mutually_exclusive_group(self, **kwargs):
+        group = _MutuallyExclusiveGroup(self, **kwargs)
+        self._mutually_exclusive_groups.append(group)
+        return group
+
+    def _add_action(self, action):
+        # resolve any conflicts
+        self._check_conflict(action)
+
+        # add to actions list
+        self._actions.append(action)
+        action.container = self
+
+        # index the action by any option strings it has
+        for option_string in action.option_strings:
+            self._option_string_actions[option_string] = action
+
+        # set the flag if any option strings look like negative numbers
+        for option_string in action.option_strings:
+            if self._negative_number_matcher.match(option_string):
+                if not self._has_negative_number_optionals:
+                    self._has_negative_number_optionals.append(True)
+
+        # return the created action
+        return action
+
+    def _remove_action(self, action):
+        self._actions.remove(action)
+
+    def _add_container_actions(self, container):
+        # collect groups by titles
+        title_group_map = {}
+        for group in self._action_groups:
+            if group.title in title_group_map:
+                msg = _('cannot merge actions - two groups are named %r')
+                raise ValueError(msg % (group.title))
+            title_group_map[group.title] = group
+
+        # map each action to its group
+        group_map = {}
+        for group in container._action_groups:
+
+            # if a group with the title exists, use that, otherwise
+            # create a new group matching the container's group
+            if group.title not in title_group_map:
+                title_group_map[group.title] = self.add_argument_group(
+                    title=group.title,
+                    description=group.description,
+                    conflict_handler=group.conflict_handler)
+
+            # map the actions to their new group
+            for action in group._group_actions:
+                group_map[action] = title_group_map[group.title]
+
+        # add container's mutually exclusive groups
+        # NOTE: if add_mutually_exclusive_group ever gains title= and
+        # description= then this code will need to be expanded as above
+        for group in container._mutually_exclusive_groups:
+            mutex_group = self.add_mutually_exclusive_group(
+                required=group.required)
+
+            # map the actions to their new mutex group
+            for action in group._group_actions:
+                group_map[action] = mutex_group
+
+        # add all actions to this container or their group
+        for action in container._actions:
+            group_map.get(action, self)._add_action(action)
+
+    def _get_positional_kwargs(self, dest, **kwargs):
+        # make sure required is not specified
+        if 'required' in kwargs:
+            msg = _("'required' is an invalid argument for positionals")
+            raise TypeError(msg)
+
+        # mark positional arguments as required if at least one is
+        # always required
+        if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
+            kwargs['required'] = True
+        if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
+            kwargs['required'] = True
+
+        # return the keyword arguments with no option strings
+        return dict(kwargs, dest=dest, option_strings=[])
+
+    def _get_optional_kwargs(self, *args, **kwargs):
+        # determine short and long option strings
+        option_strings = []
+        long_option_strings = []
+        for option_string in args:
+            # error on strings that don't start with an appropriate prefix
+            if not option_string[0] in self.prefix_chars:
+                msg = _('invalid option string %r: '
+                        'must start with a character %r')
+                tup = option_string, self.prefix_chars
+                raise ValueError(msg % tup)
+
+            # strings starting with two prefix characters are long options
+            option_strings.append(option_string)
+            if option_string[0] in self.prefix_chars:
+                if len(option_string) > 1:
+                    if option_string[1] in self.prefix_chars:
+                        long_option_strings.append(option_string)
+
+        # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
+        dest = kwargs.pop('dest', None)
+        if dest is None:
+            if long_option_strings:
+                dest_option_string = long_option_strings[0]
+            else:
+                dest_option_string = option_strings[0]
+            dest = dest_option_string.lstrip(self.prefix_chars)
+            if not dest:
+                msg = _('dest= is required for options like %r')
+                raise ValueError(msg % option_string)
+            dest = dest.replace('-', '_')
+
+        # return the updated keyword arguments
+        return dict(kwargs, dest=dest, option_strings=option_strings)
+
+    def _pop_action_class(self, kwargs, default=None):
+        action = kwargs.pop('action', default)
+        return self._registry_get('action', action, action)
+
+    def _get_handler(self):
+        # determine function from conflict handler string
+        handler_func_name = '_handle_conflict_%s' % self.conflict_handler
+        try:
+            return getattr(self, handler_func_name)
+        except AttributeError:
+            msg = _('invalid conflict_resolution value: %r')
+            raise ValueError(msg % self.conflict_handler)
+
+    def _check_conflict(self, action):
+
+        # find all options that conflict with this option
+        confl_optionals = []
+        for option_string in action.option_strings:
+            if option_string in self._option_string_actions:
+                confl_optional = self._option_string_actions[option_string]
+                confl_optionals.append((option_string, confl_optional))
+
+        # resolve any conflicts
+        if confl_optionals:
+            conflict_handler = self._get_handler()
+            conflict_handler(action, confl_optionals)
+
+    def _handle_conflict_error(self, action, conflicting_actions):
+        message = _('conflicting option string(s): %s')
+        conflict_string = ', '.join([option_string
+                                     for option_string, action
+                                     in conflicting_actions])
+        raise ArgumentError(action, message % conflict_string)
+
+    def _handle_conflict_resolve(self, action, conflicting_actions):
+
+        # remove all conflicting options
+        for option_string, action in conflicting_actions:
+
+            # remove the conflicting option
+            action.option_strings.remove(option_string)
+            self._option_string_actions.pop(option_string, None)
+
+            # if the option now has no option string, remove it from the
+            # container holding it
+            if not action.option_strings:
+                action.container._remove_action(action)
+
+
+class _ArgumentGroup(_ActionsContainer):
+
+    def __init__(self, container, title=None, description=None, **kwargs):
+        # add any missing keyword arguments by checking the container
+        update = kwargs.setdefault
+        update('conflict_handler', container.conflict_handler)
+        update('prefix_chars', container.prefix_chars)
+        update('argument_default', container.argument_default)
+        super_init = super(_ArgumentGroup, self).__init__
+        super_init(description=description, **kwargs)
+
+        # group attributes
+        self.title = title
+        self._group_actions = []
+
+        # share most attributes with the container
+        self._registries = container._registries
+        self._actions = container._actions
+        self._option_string_actions = container._option_string_actions
+        self._defaults = container._defaults
+        self._has_negative_number_optionals = \
+            container._has_negative_number_optionals
+        self._mutually_exclusive_groups = container._mutually_exclusive_groups
+
+    def _add_action(self, action):
+        action = super(_ArgumentGroup, self)._add_action(action)
+        self._group_actions.append(action)
+        return action
+
+    def _remove_action(self, action):
+        super(_ArgumentGroup, self)._remove_action(action)
+        self._group_actions.remove(action)
+
+
+class _MutuallyExclusiveGroup(_ArgumentGroup):
+
+    def __init__(self, container, required=False):
+        super(_MutuallyExclusiveGroup, self).__init__(container)
+        self.required = required
+        self._container = container
+
+    def _add_action(self, action):
+        if action.required:
+            msg = _('mutually exclusive arguments must be optional')
+            raise ValueError(msg)
+        action = self._container._add_action(action)
+        self._group_actions.append(action)
+        return action
+
+    def _remove_action(self, action):
+        self._container._remove_action(action)
+        self._group_actions.remove(action)
+
+
+class ArgumentParser(_AttributeHolder, _ActionsContainer):
+    """Object for parsing command line strings into Python objects.
+
+    Keyword Arguments:
+        - prog -- The name of the program (default: sys.argv[0])
+        - usage -- A usage message (default: auto-generated from arguments)
+        - description -- A description of what the program does
+        - epilog -- Text following the argument descriptions
+        - parents -- Parsers whose arguments should be copied into this one
+        - formatter_class -- HelpFormatter class for printing help messages
+        - prefix_chars -- Characters that prefix optional arguments
+        - fromfile_prefix_chars -- Characters that prefix files containing
+            additional arguments
+        - argument_default -- The default value for all arguments
+        - conflict_handler -- String indicating how to handle conflicts
+        - add_help -- Add a -h/-help option
+    """
+
+    def __init__(self,
+                 prog=None,
+                 usage=None,
+                 description=None,
+                 epilog=None,
+                 version=None,
+                 parents=[],
+                 formatter_class=HelpFormatter,
+                 prefix_chars='-',
+                 fromfile_prefix_chars=None,
+                 argument_default=None,
+                 conflict_handler='error',
+                 add_help=True):
+
+        if version is not None:
+            import warnings
+            warnings.warn(
+                """The "version" argument to ArgumentParser is deprecated. """
+                """Please use """
+                """"add_argument(..., action='version', version="N", ...)" """
+                """instead""", DeprecationWarning)
+
+        superinit = super(ArgumentParser, self).__init__
+        superinit(description=description,
+                  prefix_chars=prefix_chars,
+                  argument_default=argument_default,
+                  conflict_handler=conflict_handler)
+
+        # default setting for prog
+        if prog is None:
+            prog = _os.path.basename(_sys.argv[0])
+
+        self.prog = prog
+        self.usage = usage
+        self.epilog = epilog
+        self.version = version
+        self.formatter_class = formatter_class
+        self.fromfile_prefix_chars = fromfile_prefix_chars
+        self.add_help = add_help
+
+        add_group = self.add_argument_group
+        self._positionals = add_group(_('positional arguments'))
+        self._optionals = add_group(_('optional arguments'))
+        self._subparsers = None
+
+        # register types
+        def identity(string):
+            return string
+        self.register('type', None, identity)
+
+        # add help and version arguments if necessary
+        # (using explicit default to override global argument_default)
+        default_prefix = '-' if '-' in prefix_chars else prefix_chars[0]
+        if self.add_help:
+            self.add_argument(
+                default_prefix+'h', default_prefix*2+'help',
+                action='help', default=SUPPRESS,
+                help=_('show this help message and exit'))
+        if self.version:
+            self.add_argument(
+                default_prefix+'v', default_prefix*2+'version',
+                action='version', default=SUPPRESS,
+                version=self.version,
+                help=_("show program's version number and exit"))
+
+        # add parent arguments and defaults
+        for parent in parents:
+            self._add_container_actions(parent)
+            try:
+                defaults = parent._defaults
+            except AttributeError:
+                pass
+            else:
+                self._defaults.update(defaults)
+
+    # =======================
+    # Pretty __repr__ methods
+    # =======================
+    def _get_kwargs(self):
+        names = [
+            'prog',
+            'usage',
+            'description',
+            'version',
+            'formatter_class',
+            'conflict_handler',
+            'add_help',
+        ]
+        return [(name, getattr(self, name)) for name in names]
+
+    # ==================================
+    # Optional/Positional adding methods
+    # ==================================
+    def add_subparsers(self, **kwargs):
+        if self._subparsers is not None:
+            self.error(_('cannot have multiple subparser arguments'))
+
+        # add the parser class to the arguments if it's not present
+        kwargs.setdefault('parser_class', type(self))
+
+        if 'title' in kwargs or 'description' in kwargs:
+            title = _(kwargs.pop('title', 'subcommands'))
+            description = _(kwargs.pop('description', None))
+            self._subparsers = self.add_argument_group(title, description)
+        else:
+            self._subparsers = self._positionals
+
+        # prog defaults to the usage message of this parser, skipping
+        # optional arguments and with no "usage:" prefix
+        if kwargs.get('prog') is None:
+            formatter = self._get_formatter()
+            positionals = self._get_positional_actions()
+            groups = self._mutually_exclusive_groups
+            formatter.add_usage(self.usage, positionals, groups, '')
+            kwargs['prog'] = formatter.format_help().strip()
+
+        # create the parsers action and add it to the positionals list
+        parsers_class = self._pop_action_class(kwargs, 'parsers')
+        action = parsers_class(option_strings=[], **kwargs)
+        self._subparsers._add_action(action)
+
+        # return the created parsers action
+        return action
+
+    def _add_action(self, action):
+        if action.option_strings:
+            self._optionals._add_action(action)
+        else:
+            self._positionals._add_action(action)
+        return action
+
+    def _get_optional_actions(self):
+        return [action
+                for action in self._actions
+                if action.option_strings]
+
+    def _get_positional_actions(self):
+        return [action
+                for action in self._actions
+                if not action.option_strings]
+
+    # =====================================
+    # Command line argument parsing methods
+    # =====================================
+    def parse_args(self, args=None, namespace=None):
+        args, argv = self.parse_known_args(args, namespace)
+        if argv:
+            msg = _('unrecognized arguments: %s')
+            self.error(msg % ' '.join(argv))
+        return args
+
+    def parse_known_args(self, args=None, namespace=None):
+        if args is None:
+            # args default to the system args
+            args = _sys.argv[1:]
+        else:
+            # make sure that args are mutable
+            args = list(args)
+
+        # default Namespace built from parser defaults
+        if namespace is None:
+            namespace = Namespace()
+
+        # add any action defaults that aren't present
+        for action in self._actions:
+            if action.dest is not SUPPRESS:
+                if not hasattr(namespace, action.dest):
+                    if action.default is not SUPPRESS:
+                        setattr(namespace, action.dest, action.default)
+
+        # add any parser defaults that aren't present
+        for dest in self._defaults:
+            if not hasattr(namespace, dest):
+                setattr(namespace, dest, self._defaults[dest])
+
+        # parse the arguments and exit if there are any errors
+        try:
+            namespace, args = self._parse_known_args(args, namespace)
+            if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
+                args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
+                delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
+            return namespace, args
+        except ArgumentError:
+            err = _sys.exc_info()[1]
+            self.error(str(err))
+
+    def _parse_known_args(self, arg_strings, namespace):
+        # replace arg strings that are file references
+        if self.fromfile_prefix_chars is not None:
+            arg_strings = self._read_args_from_files(arg_strings)
+
+        # map all mutually exclusive arguments to the other arguments
+        # they can't occur with
+        action_conflicts = {}
+        for mutex_group in self._mutually_exclusive_groups:
+            group_actions = mutex_group._group_actions
+            for i, mutex_action in enumerate(mutex_group._group_actions):
+                conflicts = action_conflicts.setdefault(mutex_action, [])
+                conflicts.extend(group_actions[:i])
+                conflicts.extend(group_actions[i + 1:])
+
+        # find all option indices, and determine the arg_string_pattern
+        # which has an 'O' if there is an option at an index,
+        # an 'A' if there is an argument, or a '-' if there is a '--'
+        option_string_indices = {}
+        arg_string_pattern_parts = []
+        arg_strings_iter = iter(arg_strings)
+        for i, arg_string in enumerate(arg_strings_iter):
+
+            # all args after -- are non-options
+            if arg_string == '--':
+                arg_string_pattern_parts.append('-')
+                for arg_string in arg_strings_iter:
+                    arg_string_pattern_parts.append('A')
+
+            # otherwise, add the arg to the arg strings
+            # and note the index if it was an option
+            else:
+                option_tuple = self._parse_optional(arg_string)
+                if option_tuple is None:
+                    pattern = 'A'
+                else:
+                    option_string_indices[i] = option_tuple
+                    pattern = 'O'
+                arg_string_pattern_parts.append(pattern)
+
+        # join the pieces together to form the pattern
+        arg_strings_pattern = ''.join(arg_string_pattern_parts)
+
+        # converts arg strings to the appropriate and then takes the action
+        seen_actions = set()
+        seen_non_default_actions = set()
+
+        def take_action(action, argument_strings, option_string=None):
+            seen_actions.add(action)
+            argument_values = self._get_values(action, argument_strings)
+
+            # error if this argument is not allowed with other previously
+            # seen arguments, assuming that actions that use the default
+            # value don't really count as "present"
+            if argument_values is not action.default:
+                seen_non_default_actions.add(action)
+                for conflict_action in action_conflicts.get(action, []):
+                    if conflict_action in seen_non_default_actions:
+                        msg = _('not allowed with argument %s')
+                        action_name = _get_action_name(conflict_action)
+                        raise ArgumentError(action, msg % action_name)
+
+            # take the action if we didn't receive a SUPPRESS value
+            # (e.g. from a default)
+            if argument_values is not SUPPRESS:
+                action(self, namespace, argument_values, option_string)
+
+        # function to convert arg_strings into an optional action
+        def consume_optional(start_index):
+
+            # get the optional identified at this index
+            option_tuple = option_string_indices[start_index]
+            action, option_string, explicit_arg = option_tuple
+
+            # identify additional optionals in the same arg string
+            # (e.g. -xyz is the same as -x -y -z if no args are required)
+            match_argument = self._match_argument
+            action_tuples = []
+            while True:
+
+                # if we found no optional action, skip it
+                if action is None:
+                    extras.append(arg_strings[start_index])
+                    return start_index + 1
+
+                # if there is an explicit argument, try to match the
+                # optional's string arguments to only this
+                if explicit_arg is not None:
+                    arg_count = match_argument(action, 'A')
+
+                    # if the action is a single-dash option and takes no
+                    # arguments, try to parse more single-dash options out
+                    # of the tail of the option string
+                    chars = self.prefix_chars
+                    if arg_count == 0 and option_string[1] not in chars:
+                        action_tuples.append((action, [], option_string))
+                        char = option_string[0]
+                        option_string = char + explicit_arg[0]
+                        new_explicit_arg = explicit_arg[1:] or None
+                        optionals_map = self._option_string_actions
+                        if option_string in optionals_map:
+                            action = optionals_map[option_string]
+                            explicit_arg = new_explicit_arg
+                        else:
+                            msg = _('ignored explicit argument %r')
+                            raise ArgumentError(action, msg % explicit_arg)
+
+                    # if the action expect exactly one argument, we've
+                    # successfully matched the option; exit the loop
+                    elif arg_count == 1:
+                        stop = start_index + 1
+                        args = [explicit_arg]
+                        action_tuples.append((action, args, option_string))
+                        break
+
+                    # error if a double-dash option did not use the
+                    # explicit argument
+                    else:
+                        msg = _('ignored explicit argument %r')
+                        raise ArgumentError(action, msg % explicit_arg)
+
+                # if there is no explicit argument, try to match the
+                # optional's string arguments with the following strings
+                # if successful, exit the loop
+                else:
+                    start = start_index + 1
+                    selected_patterns = arg_strings_pattern[start:]
+                    arg_count = match_argument(action, selected_patterns)
+                    stop = start + arg_count
+                    args = arg_strings[start:stop]
+                    action_tuples.append((action, args, option_string))
+                    break
+
+            # add the Optional to the list and return the index at which
+            # the Optional's string args stopped
+            assert action_tuples
+            for action, args, option_string in action_tuples:
+                take_action(action, args, option_string)
+            return stop
+
+        # the list of Positionals left to be parsed; this is modified
+        # by consume_positionals()
+        positionals = self._get_positional_actions()
+
+        # function to convert arg_strings into positional actions
+        def consume_positionals(start_index):
+            # match as many Positionals as possible
+            match_partial = self._match_arguments_partial
+            selected_pattern = arg_strings_pattern[start_index:]
+            arg_counts = match_partial(positionals, selected_pattern)
+
+            # slice off the appropriate arg strings for each Positional
+            # and add the Positional and its args to the list
+            for action, arg_count in zip(positionals, arg_counts):
+                args = arg_strings[start_index: start_index + arg_count]
+                start_index += arg_count
+                take_action(action, args)
+
+            # slice off the Positionals that we just parsed and return the
+            # index at which the Positionals' string args stopped
+            positionals[:] = positionals[len(arg_counts):]
+            return start_index
+
+        # consume Positionals and Optionals alternately, until we have
+        # passed the last option string
+        extras = []
+        start_index = 0
+        if option_string_indices:
+            max_option_string_index = max(option_string_indices)
+        else:
+            max_option_string_index = -1
+        while start_index <= max_option_string_index:
+
+            # consume any Positionals preceding the next option
+            next_option_string_index = min([
+                index
+                for index in option_string_indices
+                if index >= start_index])
+            if start_index != next_option_string_index:
+                positionals_end_index = consume_positionals(start_index)
+
+                # only try to parse the next optional if we didn't consume
+                # the option string during the positionals parsing
+                if positionals_end_index > start_index:
+                    start_index = positionals_end_index
+                    continue
+                else:
+                    start_index = positionals_end_index
+
+            # if we consumed all the positionals we could and we're not
+            # at the index of an option string, there were extra arguments
+            if start_index not in option_string_indices:
+                strings = arg_strings[start_index:next_option_string_index]
+                extras.extend(strings)
+                start_index = next_option_string_index
+
+            # consume the next optional and any arguments for it
+            start_index = consume_optional(start_index)
+
+        # consume any positionals following the last Optional
+        stop_index = consume_positionals(start_index)
+
+        # if we didn't consume all the argument strings, there were extras
+        extras.extend(arg_strings[stop_index:])
+
+        # if we didn't use all the Positional objects, there were too few
+        # arg strings supplied.
+        if positionals:
+            self.error(_('too few arguments'))
+
+        # make sure all required actions were present, and convert defaults.
+        for action in self._actions:
+            if action not in seen_actions:
+                if action.required:
+                    name = _get_action_name(action)
+                    self.error(_('argument %s is required') % name)
+                else:
+                    # Convert action default now instead of doing it before
+                    # parsing arguments to avoid calling convert functions
+                    # twice (which may fail) if the argument was given, but
+                    # only if it was defined already in the namespace
+                    if (action.default is not None and
+                            isinstance(action.default, basestring) and
+                            hasattr(namespace, action.dest) and
+                            action.default is getattr(namespace, action.dest)):
+                        setattr(namespace, action.dest,
+                                self._get_value(action, action.default))
+
+        # make sure all required groups had one option present
+        for group in self._mutually_exclusive_groups:
+            if group.required:
+                for action in group._group_actions:
+                    if action in seen_non_default_actions:
+                        break
+
+                # if no actions were used, report the error
+                else:
+                    names = [_get_action_name(action)
+                             for action in group._group_actions
+                             if action.help is not SUPPRESS]
+                    msg = _('one of the arguments %s is required')
+                    self.error(msg % ' '.join(names))
+
+        # return the updated namespace and the extra arguments
+        return namespace, extras
+
+    def _read_args_from_files(self, arg_strings):
+        # expand arguments referencing files
+        new_arg_strings = []
+        for arg_string in arg_strings:
+
+            # for regular arguments, just add them back into the list
+            if not arg_string or arg_string[0] not in self.fromfile_prefix_chars:
+                new_arg_strings.append(arg_string)
+
+            # replace arguments referencing files with the file content
+            else:
+                try:
+                    args_file = open(arg_string[1:])
+                    try:
+                        arg_strings = []
+                        for arg_line in args_file.read().splitlines():
+                            for arg in self.convert_arg_line_to_args(arg_line):
+                                arg_strings.append(arg)
+                        arg_strings = self._read_args_from_files(arg_strings)
+                        new_arg_strings.extend(arg_strings)
+                    finally:
+                        args_file.close()
+                except IOError:
+                    err = _sys.exc_info()[1]
+                    self.error(str(err))
+
+        # return the modified argument list
+        return new_arg_strings
+
+    def convert_arg_line_to_args(self, arg_line):
+        return [arg_line]
+
+    def _match_argument(self, action, arg_strings_pattern):
+        # match the pattern for this action to the arg strings
+        nargs_pattern = self._get_nargs_pattern(action)
+        match = _re.match(nargs_pattern, arg_strings_pattern)
+
+        # raise an exception if we weren't able to find a match
+        if match is None:
+            nargs_errors = {
+                None: _('expected one argument'),
+                OPTIONAL: _('expected at most one argument'),
+                ONE_OR_MORE: _('expected at least one argument'),
+            }
+            default = _('expected %s argument(s)') % action.nargs
+            msg = nargs_errors.get(action.nargs, default)
+            raise ArgumentError(action, msg)
+
+        # return the number of arguments matched
+        return len(match.group(1))
+
+    def _match_arguments_partial(self, actions, arg_strings_pattern):
+        # progressively shorten the actions list by slicing off the
+        # final actions until we find a match
+        result = []
+        for i in range(len(actions), 0, -1):
+            actions_slice = actions[:i]
+            pattern = ''.join([self._get_nargs_pattern(action)
+                               for action in actions_slice])
+            match = _re.match(pattern, arg_strings_pattern)
+            if match is not None:
+                result.extend([len(string) for string in match.groups()])
+                break
+
+        # return the list of arg string counts
+        return result
+
+    def _parse_optional(self, arg_string):
+        # if it's an empty string, it was meant to be a positional
+        if not arg_string:
+            return None
+
+        # if it doesn't start with a prefix, it was meant to be positional
+        if not arg_string[0] in self.prefix_chars:
+            return None
+
+        # if the option string is present in the parser, return the action
+        if arg_string in self._option_string_actions:
+            action = self._option_string_actions[arg_string]
+            return action, arg_string, None
+
+        # if it's just a single character, it was meant to be positional
+        if len(arg_string) == 1:
+            return None
+
+        # if the option string before the "=" is present, return the action
+        if '=' in arg_string:
+            option_string, explicit_arg = arg_string.split('=', 1)
+            if option_string in self._option_string_actions:
+                action = self._option_string_actions[option_string]
+                return action, option_string, explicit_arg
+
+        # search through all possible prefixes of the option string
+        # and all actions in the parser for possible interpretations
+        option_tuples = self._get_option_tuples(arg_string)
+
+        # if multiple actions match, the option string was ambiguous
+        if len(option_tuples) > 1:
+            options = ', '.join([option_string
+                for action, option_string, explicit_arg in option_tuples])
+            tup = arg_string, options
+            self.error(_('ambiguous option: %s could match %s') % tup)
+
+        # if exactly one action matched, this segmentation is good,
+        # so return the parsed action
+        elif len(option_tuples) == 1:
+            option_tuple, = option_tuples
+            return option_tuple
+
+        # if it was not found as an option, but it looks like a negative
+        # number, it was meant to be positional
+        # unless there are negative-number-like options
+        if self._negative_number_matcher.match(arg_string):
+            if not self._has_negative_number_optionals:
+                return None
+
+        # if it contains a space, it was meant to be a positional
+        if ' ' in arg_string:
+            return None
+
+        # it was meant to be an optional but there is no such option
+        # in this parser (though it might be a valid option in a subparser)
+        return None, arg_string, None
+
+    def _get_option_tuples(self, option_string):
+        result = []
+
+        # option strings starting with two prefix characters are only
+        # split at the '='
+        chars = self.prefix_chars
+        if option_string[0] in chars and option_string[1] in chars:
+            if '=' in option_string:
+                option_prefix, explicit_arg = option_string.split('=', 1)
+            else:
+                option_prefix = option_string
+                explicit_arg = None
+            for option_string in self._option_string_actions:
+                if option_string.startswith(option_prefix):
+                    action = self._option_string_actions[option_string]
+                    tup = action, option_string, explicit_arg
+                    result.append(tup)
+
+        # single character options can be concatenated with their arguments
+        # but multiple character options always have to have their argument
+        # separate
+        elif option_string[0] in chars and option_string[1] not in chars:
+            option_prefix = option_string
+            explicit_arg = None
+            short_option_prefix = option_string[:2]
+            short_explicit_arg = option_string[2:]
+
+            for option_string in self._option_string_actions:
+                if option_string == short_option_prefix:
+                    action = self._option_string_actions[option_string]
+                    tup = action, option_string, short_explicit_arg
+                    result.append(tup)
+                elif option_string.startswith(option_prefix):
+                    action = self._option_string_actions[option_string]
+                    tup = action, option_string, explicit_arg
+                    result.append(tup)
+
+        # shouldn't ever get here
+        else:
+            self.error(_('unexpected option string: %s') % option_string)
+
+        # return the collected option tuples
+        return result
+
+    def _get_nargs_pattern(self, action):
+        # in all examples below, we have to allow for '--' args
+        # which are represented as '-' in the pattern
+        nargs = action.nargs
+
+        # the default (None) is assumed to be a single argument
+        if nargs is None:
+            nargs_pattern = '(-*A-*)'
+
+        # allow zero or one arguments
+        elif nargs == OPTIONAL:
+            nargs_pattern = '(-*A?-*)'
+
+        # allow zero or more arguments
+        elif nargs == ZERO_OR_MORE:
+            nargs_pattern = '(-*[A-]*)'
+
+        # allow one or more arguments
+        elif nargs == ONE_OR_MORE:
+            nargs_pattern = '(-*A[A-]*)'
+
+        # allow any number of options or arguments
+        elif nargs == REMAINDER:
+            nargs_pattern = '([-AO]*)'
+
+        # allow one argument followed by any number of options or arguments
+        elif nargs == PARSER:
+            nargs_pattern = '(-*A[-AO]*)'
+
+        # all others should be integers
+        else:
+            nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
+
+        # if this is an optional action, -- is not allowed
+        if action.option_strings:
+            nargs_pattern = nargs_pattern.replace('-*', '')
+            nargs_pattern = nargs_pattern.replace('-', '')
+
+        # return the pattern
+        return nargs_pattern
+
+    # ========================
+    # Value conversion methods
+    # ========================
+    def _get_values(self, action, arg_strings):
+        # for everything but PARSER, REMAINDER args, strip out first '--'
+        if action.nargs not in [PARSER, REMAINDER]:
+            try:
+                arg_strings.remove('--')
+            except ValueError:
+                pass
+
+        # optional argument produces a default when not present
+        if not arg_strings and action.nargs == OPTIONAL:
+            if action.option_strings:
+                value = action.const
+            else:
+                value = action.default
+            if isinstance(value, basestring):
+                value = self._get_value(action, value)
+                self._check_value(action, value)
+
+        # when nargs='*' on a positional, if there were no command-line
+        # args, use the default if it is anything other than None
+        elif (not arg_strings and action.nargs == ZERO_OR_MORE and
+              not action.option_strings):
+            if action.default is not None:
+                value = action.default
+            else:
+                value = arg_strings
+            self._check_value(action, value)
+
+        # single argument or optional argument produces a single value
+        elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
+            arg_string, = arg_strings
+            value = self._get_value(action, arg_string)
+            self._check_value(action, value)
+
+        # REMAINDER arguments convert all values, checking none
+        elif action.nargs == REMAINDER:
+            value = [self._get_value(action, v) for v in arg_strings]
+
+        # PARSER arguments convert all values, but check only the first
+        elif action.nargs == PARSER:
+            value = [self._get_value(action, v) for v in arg_strings]
+            self._check_value(action, value[0])
+
+        # all other types of nargs produce a list
+        else:
+            value = [self._get_value(action, v) for v in arg_strings]
+            for v in value:
+                self._check_value(action, v)
+
+        # return the converted value
+        return value
+
+    def _get_value(self, action, arg_string):
+        type_func = self._registry_get('type', action.type, action.type)
+        if not _callable(type_func):
+            msg = _('%r is not callable')
+            raise ArgumentError(action, msg % type_func)
+
+        # convert the value to the appropriate type
+        try:
+            result = type_func(arg_string)
+
+        # ArgumentTypeErrors indicate errors
+        except ArgumentTypeError:
+            name = getattr(action.type, '__name__', repr(action.type))
+            msg = str(_sys.exc_info()[1])
+            raise ArgumentError(action, msg)
+
+        # TypeErrors or ValueErrors also indicate errors
+        except (TypeError, ValueError):
+            name = getattr(action.type, '__name__', repr(action.type))
+            msg = _('invalid %s value: %r')
+            raise ArgumentError(action, msg % (name, arg_string))
+
+        # return the converted value
+        return result
+
+    def _check_value(self, action, value):
+        # converted value must be one of the choices (if specified)
+        if action.choices is not None and value not in action.choices:
+            tup = value, ', '.join(map(repr, action.choices))
+            msg = _('invalid choice: %r (choose from %s)') % tup
+            raise ArgumentError(action, msg)
+
+    # =======================
+    # Help-formatting methods
+    # =======================
+    def format_usage(self):
+        formatter = self._get_formatter()
+        formatter.add_usage(self.usage, self._actions,
+                            self._mutually_exclusive_groups)
+        return formatter.format_help()
+
+    def format_help(self):
+        formatter = self._get_formatter()
+
+        # usage
+        formatter.add_usage(self.usage, self._actions,
+                            self._mutually_exclusive_groups)
+
+        # description
+        formatter.add_text(self.description)
+
+        # positionals, optionals and user-defined groups
+        for action_group in self._action_groups:
+            formatter.start_section(action_group.title)
+            formatter.add_text(action_group.description)
+            formatter.add_arguments(action_group._group_actions)
+            formatter.end_section()
+
+        # epilog
+        formatter.add_text(self.epilog)
+
+        # determine help from format above
+        return formatter.format_help()
+
+    def format_version(self):
+        import warnings
+        warnings.warn(
+            'The format_version method is deprecated -- the "version" '
+            'argument to ArgumentParser is no longer supported.',
+            DeprecationWarning)
+        formatter = self._get_formatter()
+        formatter.add_text(self.version)
+        return formatter.format_help()
+
+    def _get_formatter(self):
+        return self.formatter_class(prog=self.prog)
+
+    # =====================
+    # Help-printing methods
+    # =====================
+    def print_usage(self, file=None):
+        if file is None:
+            file = _sys.stdout
+        self._print_message(self.format_usage(), file)
+
+    def print_help(self, file=None):
+        if file is None:
+            file = _sys.stdout
+        self._print_message(self.format_help(), file)
+
+    def print_version(self, file=None):
+        import warnings
+        warnings.warn(
+            'The print_version method is deprecated -- the "version" '
+            'argument to ArgumentParser is no longer supported.',
+            DeprecationWarning)
+        self._print_message(self.format_version(), file)
+
+    def _print_message(self, message, file=None):
+        if message:
+            if file is None:
+                file = _sys.stderr
+            file.write(message)
+
+    # ===============
+    # Exiting methods
+    # ===============
+    def exit(self, status=0, message=None):
+        if message:
+            self._print_message(message, _sys.stderr)
+        _sys.exit(status)
+
+    def error(self, message):
+        """error(message: string)
+
+        Prints a usage message incorporating the message to stderr and
+        exits.
+
+        If you override this in a subclass, it should not return -- it
+        should either exit or raise an exception.
+        """
+        self.print_usage(_sys.stderr)
+        self.exit(2, _('%s: error: %s\n') % (self.prog, message))
diff --git a/src/main/resources/PythonLibs/ast.py b/src/main/resources/PythonLibs/ast.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd5dfdba676d97d6b45ddab30fcf8e7169faea0c
--- /dev/null
+++ b/src/main/resources/PythonLibs/ast.py
@@ -0,0 +1,311 @@
+# -*- coding: utf-8 -*-
+"""
+    ast
+    ~~~
+
+    The `ast` module helps Python applications to process trees of the Python
+    abstract syntax grammar.  The abstract syntax itself might change with
+    each Python release; this module helps to find out programmatically what
+    the current grammar looks like and allows modifications of it.
+
+    An abstract syntax tree can be generated by passing `ast.PyCF_ONLY_AST` as
+    a flag to the `compile()` builtin function or by using the `parse()`
+    function from this module.  The result will be a tree of objects whose
+    classes all inherit from `ast.AST`.
+
+    A modified abstract syntax tree can be compiled into a Python code object
+    using the built-in `compile()` function.
+
+    Additionally various helper functions are provided that make working with
+    the trees simpler.  The main intention of the helper functions and this
+    module in general is to provide an easy to use interface for libraries
+    that work tightly with the python syntax (template engines for example).
+
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: Python License.
+"""
+from _ast import *
+from _ast import __version__
+
+
+def parse(source, filename='<unknown>', mode='exec'):
+    """
+    Parse the source into an AST node.
+    Equivalent to compile(source, filename, mode, PyCF_ONLY_AST).
+    """
+    return compile(source, filename, mode, PyCF_ONLY_AST)
+
+
+def literal_eval(node_or_string):
+    """
+    Safely evaluate an expression node or a string containing a Python
+    expression.  The string or node provided may only consist of the following
+    Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
+    and None.
+    """
+    _safe_names = {'None': None, 'True': True, 'False': False}
+    if isinstance(node_or_string, basestring):
+        node_or_string = parse(node_or_string, mode='eval')
+    if isinstance(node_or_string, Expression):
+        node_or_string = node_or_string.body
+    def _convert(node):
+        if isinstance(node, Str):
+            return node.s
+        elif isinstance(node, Num):
+            return node.n
+        elif isinstance(node, Tuple):
+            return tuple(map(_convert, node.elts))
+        elif isinstance(node, List):
+            return list(map(_convert, node.elts))
+        elif isinstance(node, Dict):
+            return dict((_convert(k), _convert(v)) for k, v
+                        in zip(node.keys, node.values))
+        elif isinstance(node, Name):
+            if node.id in _safe_names:
+                return _safe_names[node.id]
+        elif isinstance(node, BinOp) and \
+             isinstance(node.op, (Add, Sub)) and \
+             isinstance(node.right, Num) and \
+             isinstance(node.right.n, complex) and \
+             isinstance(node.left, Num) and \
+             isinstance(node.left.n, (int, long, float)):
+            left = node.left.n
+            right = node.right.n
+            if isinstance(node.op, Add):
+                return left + right
+            else:
+                return left - right
+        raise ValueError('malformed string')
+    return _convert(node_or_string)
+
+
+def dump(node, annotate_fields=True, include_attributes=False):
+    """
+    Return a formatted dump of the tree in *node*.  This is mainly useful for
+    debugging purposes.  The returned string will show the names and the values
+    for fields.  This makes the code impossible to evaluate, so if evaluation is
+    wanted *annotate_fields* must be set to False.  Attributes such as line
+    numbers and column offsets are not dumped by default.  If this is wanted,
+    *include_attributes* can be set to True.
+    """
+    def _format(node):
+        if isinstance(node, AST):
+            fields = [(a, _format(b)) for a, b in iter_fields(node)]
+            rv = '%s(%s' % (node.__class__.__name__, ', '.join(
+                ('%s=%s' % field for field in fields)
+                if annotate_fields else
+                (b for a, b in fields)
+            ))
+            if include_attributes and node._attributes:
+                rv += fields and ', ' or ' '
+                rv += ', '.join('%s=%s' % (a, _format(getattr(node, a)))
+                                for a in node._attributes)
+            return rv + ')'
+        elif isinstance(node, list):
+            return '[%s]' % ', '.join(_format(x) for x in node)
+        return repr(node)
+    if not isinstance(node, AST):
+        raise TypeError('expected AST, got %r' % node.__class__.__name__)
+    return _format(node)
+
+
+def copy_location(new_node, old_node):
+    """
+    Copy source location (`lineno` and `col_offset` attributes) from
+    *old_node* to *new_node* if possible, and return *new_node*.
+    """
+    for attr in 'lineno', 'col_offset':
+        if attr in old_node._attributes and attr in new_node._attributes \
+           and hasattr(old_node, attr):
+            setattr(new_node, attr, getattr(old_node, attr))
+    return new_node
+
+
+def fix_missing_locations(node):
+    """
+    When you compile a node tree with compile(), the compiler expects lineno and
+    col_offset attributes for every node that supports them.  This is rather
+    tedious to fill in for generated nodes, so this helper adds these attributes
+    recursively where not already set, by setting them to the values of the
+    parent node.  It works recursively starting at *node*.
+    """
+    def _fix(node, lineno, col_offset):
+        if 'lineno' in node._attributes:
+            if not hasattr(node, 'lineno'):
+                node.lineno = lineno
+            else:
+                lineno = node.lineno
+        if 'col_offset' in node._attributes:
+            if not hasattr(node, 'col_offset'):
+                node.col_offset = col_offset
+            else:
+                col_offset = node.col_offset
+        for child in iter_child_nodes(node):
+            _fix(child, lineno, col_offset)
+    _fix(node, 1, 0)
+    return node
+
+
+def increment_lineno(node, n=1):
+    """
+    Increment the line number of each node in the tree starting at *node* by *n*.
+    This is useful to "move code" to a different location in a file.
+    """
+    for child in walk(node):
+        if 'lineno' in child._attributes:
+            child.lineno = getattr(child, 'lineno', 0) + n
+    return node
+
+
+def iter_fields(node):
+    """
+    Yield a tuple of ``(fieldname, value)`` for each field in ``node._fields``
+    that is present on *node*.
+    """
+    for field in node._fields:
+        try:
+            yield field, getattr(node, field)
+        except AttributeError:
+            pass
+
+
+def iter_child_nodes(node):
+    """
+    Yield all direct child nodes of *node*, that is, all fields that are nodes
+    and all items of fields that are lists of nodes.
+    """
+    for name, field in iter_fields(node):
+        if isinstance(field, AST):
+            yield field
+        elif isinstance(field, list):
+            for item in field:
+                if isinstance(item, AST):
+                    yield item
+
+
+def get_docstring(node, clean=True):
+    """
+    Return the docstring for the given node or None if no docstring can
+    be found.  If the node provided does not have docstrings a TypeError
+    will be raised.
+    """
+    if not isinstance(node, (FunctionDef, ClassDef, Module)):
+        raise TypeError("%r can't have docstrings" % node.__class__.__name__)
+    if node.body and isinstance(node.body[0], Expr) and \
+       isinstance(node.body[0].value, Str):
+        if clean:
+            import inspect
+            return inspect.cleandoc(node.body[0].value.s)
+        return node.body[0].value.s
+
+
+def walk(node):
+    """
+    Recursively yield all descendant nodes in the tree starting at *node*
+    (including *node* itself), in no specified order.  This is useful if you
+    only want to modify nodes in place and don't care about the context.
+    """
+    from collections import deque
+    todo = deque([node])
+    while todo:
+        node = todo.popleft()
+        todo.extend(iter_child_nodes(node))
+        yield node
+
+
+class NodeVisitor(object):
+    """
+    A node visitor base class that walks the abstract syntax tree and calls a
+    visitor function for every node found.  This function may return a value
+    which is forwarded by the `visit` method.
+
+    This class is meant to be subclassed, with the subclass adding visitor
+    methods.
+
+    Per default the visitor functions for the nodes are ``'visit_'`` +
+    class name of the node.  So a `TryFinally` node visit function would
+    be `visit_TryFinally`.  This behavior can be changed by overriding
+    the `visit` method.  If no visitor function exists for a node
+    (return value `None`) the `generic_visit` visitor is used instead.
+
+    Don't use the `NodeVisitor` if you want to apply changes to nodes during
+    traversing.  For this a special visitor exists (`NodeTransformer`) that
+    allows modifications.
+    """
+
+    def visit(self, node):
+        """Visit a node."""
+        method = 'visit_' + node.__class__.__name__
+        visitor = getattr(self, method, self.generic_visit)
+        return visitor(node)
+
+    def generic_visit(self, node):
+        """Called if no explicit visitor function exists for a node."""
+        for field, value in iter_fields(node):
+            if isinstance(value, list):
+                for item in value:
+                    if isinstance(item, AST):
+                        self.visit(item)
+            elif isinstance(value, AST):
+                self.visit(value)
+
+
+class NodeTransformer(NodeVisitor):
+    """
+    A :class:`NodeVisitor` subclass that walks the abstract syntax tree and
+    allows modification of nodes.
+
+    The `NodeTransformer` will walk the AST and use the return value of the
+    visitor methods to replace or remove the old node.  If the return value of
+    the visitor method is ``None``, the node will be removed from its location,
+    otherwise it is replaced with the return value.  The return value may be the
+    original node in which case no replacement takes place.
+
+    Here is an example transformer that rewrites all occurrences of name lookups
+    (``foo``) to ``data['foo']``::
+
+       class RewriteName(NodeTransformer):
+
+           def visit_Name(self, node):
+               return copy_location(Subscript(
+                   value=Name(id='data', ctx=Load()),
+                   slice=Index(value=Str(s=node.id)),
+                   ctx=node.ctx
+               ), node)
+
+    Keep in mind that if the node you're operating on has child nodes you must
+    either transform the child nodes yourself or call the :meth:`generic_visit`
+    method for the node first.
+
+    For nodes that were part of a collection of statements (that applies to all
+    statement nodes), the visitor may also return a list of nodes rather than
+    just a single node.
+
+    Usually you use the transformer like this::
+
+       node = YourTransformer().visit(node)
+    """
+
+    def generic_visit(self, node):
+        for field, old_value in iter_fields(node):
+            old_value = getattr(node, field, None)
+            if isinstance(old_value, list):
+                new_values = []
+                for value in old_value:
+                    if isinstance(value, AST):
+                        value = self.visit(value)
+                        if value is None:
+                            continue
+                        elif not isinstance(value, AST):
+                            new_values.extend(value)
+                            continue
+                    new_values.append(value)
+                old_value[:] = new_values
+            elif isinstance(old_value, AST):
+                new_node = self.visit(old_value)
+                if new_node is None:
+                    delattr(node, field)
+                else:
+                    setattr(node, field, new_node)
+        return node
diff --git a/src/main/resources/PythonLibs/asynchat.py b/src/main/resources/PythonLibs/asynchat.py
new file mode 100644
index 0000000000000000000000000000000000000000..6f99ba1063c85e48dae1c7f9a15965edcec4db61
--- /dev/null
+++ b/src/main/resources/PythonLibs/asynchat.py
@@ -0,0 +1,295 @@
+# -*- Mode: Python; tab-width: 4 -*-
+#       Id: asynchat.py,v 2.26 2000/09/07 22:29:26 rushing Exp
+#       Author: Sam Rushing <rushing@nightmare.com>
+
+# ======================================================================
+# Copyright 1996 by Sam Rushing
+#
+#                         All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appear in all
+# copies and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of Sam
+# Rushing not be used in advertising or publicity pertaining to
+# distribution of the software without specific, written prior
+# permission.
+#
+# SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+# NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+# ======================================================================
+
+r"""A class supporting chat-style (command/response) protocols.
+
+This class adds support for 'chat' style protocols - where one side
+sends a 'command', and the other sends a response (examples would be
+the common internet protocols - smtp, nntp, ftp, etc..).
+
+The handle_read() method looks at the input stream for the current
+'terminator' (usually '\r\n' for single-line responses, '\r\n.\r\n'
+for multi-line output), calling self.found_terminator() on its
+receipt.
+
+for example:
+Say you build an async nntp client using this class.  At the start
+of the connection, you'll have self.terminator set to '\r\n', in
+order to process the single-line greeting.  Just before issuing a
+'LIST' command you'll set it to '\r\n.\r\n'.  The output of the LIST
+command will be accumulated (using your own 'collect_incoming_data'
+method) up to the terminator, and then control will be returned to
+you - by calling your self.found_terminator() method.
+"""
+
+import socket
+import asyncore
+from collections import deque
+
+class async_chat (asyncore.dispatcher):
+    """This is an abstract class.  You must derive from this class, and add
+    the two methods collect_incoming_data() and found_terminator()"""
+
+    # these are overridable defaults
+
+    ac_in_buffer_size       = 4096
+    ac_out_buffer_size      = 4096
+
+    def __init__ (self, conn=None):
+        self.ac_in_buffer = ''
+        self.ac_out_buffer = ''
+        self.producer_fifo = fifo()
+        asyncore.dispatcher.__init__ (self, conn)
+
+    def collect_incoming_data(self, data):
+        raise NotImplementedError, "must be implemented in subclass"
+
+    def found_terminator(self):
+        raise NotImplementedError, "must be implemented in subclass"
+
+    def set_terminator (self, term):
+        "Set the input delimiter.  Can be a fixed string of any length, an integer, or None"
+        self.terminator = term
+
+    def get_terminator (self):
+        return self.terminator
+
+    # grab some more data from the socket,
+    # throw it to the collector method,
+    # check for the terminator,
+    # if found, transition to the next state.
+
+    def handle_read (self):
+
+        try:
+            data = self.recv (self.ac_in_buffer_size)
+        except socket.error, why:
+            self.handle_error()
+            return
+
+        self.ac_in_buffer = self.ac_in_buffer + data
+
+        # Continue to search for self.terminator in self.ac_in_buffer,
+        # while calling self.collect_incoming_data.  The while loop
+        # is necessary because we might read several data+terminator
+        # combos with a single recv(1024).
+
+        while self.ac_in_buffer:
+            lb = len(self.ac_in_buffer)
+            terminator = self.get_terminator()
+            if not terminator:
+                # no terminator, collect it all
+                self.collect_incoming_data (self.ac_in_buffer)
+                self.ac_in_buffer = ''
+            elif isinstance(terminator, int) or isinstance(terminator, long):
+                # numeric terminator
+                n = terminator
+                if lb < n:
+                    self.collect_incoming_data (self.ac_in_buffer)
+                    self.ac_in_buffer = ''
+                    self.terminator = self.terminator - lb
+                else:
+                    self.collect_incoming_data (self.ac_in_buffer[:n])
+                    self.ac_in_buffer = self.ac_in_buffer[n:]
+                    self.terminator = 0
+                    self.found_terminator()
+            else:
+                # 3 cases:
+                # 1) end of buffer matches terminator exactly:
+                #    collect data, transition
+                # 2) end of buffer matches some prefix:
+                #    collect data to the prefix
+                # 3) end of buffer does not match any prefix:
+                #    collect data
+                terminator_len = len(terminator)
+                index = self.ac_in_buffer.find(terminator)
+                if index != -1:
+                    # we found the terminator
+                    if index > 0:
+                        # don't bother reporting the empty string (source of subtle bugs)
+                        self.collect_incoming_data (self.ac_in_buffer[:index])
+                    self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:]
+                    # This does the Right Thing if the terminator is changed here.
+                    self.found_terminator()
+                else:
+                    # check for a prefix of the terminator
+                    index = find_prefix_at_end (self.ac_in_buffer, terminator)
+                    if index:
+                        if index != lb:
+                            # we found a prefix, collect up to the prefix
+                            self.collect_incoming_data (self.ac_in_buffer[:-index])
+                            self.ac_in_buffer = self.ac_in_buffer[-index:]
+                        break
+                    else:
+                        # no prefix, collect it all
+                        self.collect_incoming_data (self.ac_in_buffer)
+                        self.ac_in_buffer = ''
+
+    def handle_write (self):
+        self.initiate_send ()
+
+    def handle_close (self):
+        self.close()
+
+    def push (self, data):
+        self.producer_fifo.push (simple_producer (data))
+        self.initiate_send()
+
+    def push_with_producer (self, producer):
+        self.producer_fifo.push (producer)
+        self.initiate_send()
+
+    def readable (self):
+        "predicate for inclusion in the readable for select()"
+        return (len(self.ac_in_buffer) <= self.ac_in_buffer_size)
+
+    def writable (self):
+        "predicate for inclusion in the writable for select()"
+        # return len(self.ac_out_buffer) or len(self.producer_fifo) or (not self.connected)
+        # this is about twice as fast, though not as clear.
+        return not (
+                (self.ac_out_buffer == '') and
+                self.producer_fifo.is_empty() and
+                self.connected
+                )
+
+    def close_when_done (self):
+        "automatically close this channel once the outgoing queue is empty"
+        self.producer_fifo.push (None)
+
+    # refill the outgoing buffer by calling the more() method
+    # of the first producer in the queue
+    def refill_buffer (self):
+        while 1:
+            if len(self.producer_fifo):
+                p = self.producer_fifo.first()
+                # a 'None' in the producer fifo is a sentinel,
+                # telling us to close the channel.
+                if p is None:
+                    if not self.ac_out_buffer:
+                        self.producer_fifo.pop()
+                        self.close()
+                    return
+                elif isinstance(p, str):
+                    self.producer_fifo.pop()
+                    self.ac_out_buffer = self.ac_out_buffer + p
+                    return
+                data = p.more()
+                if data:
+                    self.ac_out_buffer = self.ac_out_buffer + data
+                    return
+                else:
+                    self.producer_fifo.pop()
+            else:
+                return
+
+    def initiate_send (self):
+        obs = self.ac_out_buffer_size
+        # try to refill the buffer
+        if (len (self.ac_out_buffer) < obs):
+            self.refill_buffer()
+
+        if self.ac_out_buffer and self.connected:
+            # try to send the buffer
+            try:
+                num_sent = self.send (self.ac_out_buffer[:obs])
+                if num_sent:
+                    self.ac_out_buffer = self.ac_out_buffer[num_sent:]
+
+            except socket.error, why:
+                self.handle_error()
+                return
+
+    def discard_buffers (self):
+        # Emergencies only!
+        self.ac_in_buffer = ''
+        self.ac_out_buffer = ''
+        while self.producer_fifo:
+            self.producer_fifo.pop()
+
+
+class simple_producer:
+
+    def __init__ (self, data, buffer_size=512):
+        self.data = data
+        self.buffer_size = buffer_size
+
+    def more (self):
+        if len (self.data) > self.buffer_size:
+            result = self.data[:self.buffer_size]
+            self.data = self.data[self.buffer_size:]
+            return result
+        else:
+            result = self.data
+            self.data = ''
+            return result
+
+class fifo:
+    def __init__ (self, list=None):
+        if not list:
+            self.list = deque()
+        else:
+            self.list = deque(list)
+
+    def __len__ (self):
+        return len(self.list)
+
+    def is_empty (self):
+        return not self.list
+
+    def first (self):
+        return self.list[0]
+
+    def push (self, data):
+        self.list.append(data)
+
+    def pop (self):
+        if self.list:
+            return (1, self.list.popleft())
+        else:
+            return (0, None)
+
+# Given 'haystack', see if any prefix of 'needle' is at its end.  This
+# assumes an exact match has already been checked.  Return the number of
+# characters matched.
+# for example:
+# f_p_a_e ("qwerty\r", "\r\n") => 1
+# f_p_a_e ("qwertydkjf", "\r\n") => 0
+# f_p_a_e ("qwerty\r\n", "\r\n") => <undefined>
+
+# this could maybe be made faster with a computed regex?
+# [answer: no; circa Python-2.0, Jan 2001]
+# new python:   28961/s
+# old python:   18307/s
+# re:        12820/s
+# regex:     14035/s
+
+def find_prefix_at_end (haystack, needle):
+    l = len(needle) - 1
+    while l and not haystack.endswith(needle[:l]):
+        l -= 1
+    return l
diff --git a/src/main/resources/PythonLibs/asyncore.py b/src/main/resources/PythonLibs/asyncore.py
new file mode 100644
index 0000000000000000000000000000000000000000..84ec6a8cdafbe77d13028eb69d9a661bbd3c9080
--- /dev/null
+++ b/src/main/resources/PythonLibs/asyncore.py
@@ -0,0 +1,705 @@
+# -*- Mode: Python -*-
+#   Id: asyncore.py,v 2.51 2000/09/07 22:29:26 rushing Exp
+#   Author: Sam Rushing <rushing@nightmare.com>
+
+# ======================================================================
+# Copyright 1996 by Sam Rushing
+#
+#                         All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appear in all
+# copies and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of Sam
+# Rushing not be used in advertising or publicity pertaining to
+# distribution of the software without specific, written prior
+# permission.
+#
+# SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+# NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+# ======================================================================
+
+"""Basic infrastructure for asynchronous socket service clients and servers.
+
+There are only two ways to have a program on a single processor do "more
+than one thing at a time".  Multi-threaded programming is the simplest and
+most popular way to do it, but there is another very different technique,
+that lets you have nearly all the advantages of multi-threading, without
+actually using multiple threads. it's really only practical if your program
+is largely I/O bound. If your program is CPU bound, then pre-emptive
+scheduled threads are probably what you really need. Network servers are
+rarely CPU-bound, however.
+
+If your operating system supports the select() system call in its I/O
+library (and nearly all do), then you can use it to juggle multiple
+communication channels at once; doing other work while your I/O is taking
+place in the "background."  Although this strategy can seem strange and
+complex, especially at first, it is in many ways easier to understand and
+control than multi-threaded programming. The module documented here solves
+many of the difficult problems for you, making the task of building
+sophisticated high-performance network servers and clients a snap.
+"""
+
+import select
+import socket
+import sys
+import time
+import warnings
+
+import os
+from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
+     ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
+     errorcode
+
+_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE,
+                           EBADF))
+
+try:
+    socket_map
+except NameError:
+    socket_map = {}
+
+def _strerror(err):
+    try:
+        return os.strerror(err)
+    except (ValueError, OverflowError, NameError):
+        if err in errorcode:
+            return errorcode[err]
+        return "Unknown error %s" %err
+
+class ExitNow(Exception):
+    pass
+
+_reraised_exceptions = (ExitNow, KeyboardInterrupt, SystemExit)
+
+def read(obj):
+    try:
+        obj.handle_read_event()
+    except _reraised_exceptions:
+        raise
+    except:
+        obj.handle_error()
+
+def write(obj):
+    try:
+        obj.handle_write_event()
+    except _reraised_exceptions:
+        raise
+    except:
+        obj.handle_error()
+
+def _exception(obj):
+    try:
+        obj.handle_expt_event()
+    except _reraised_exceptions:
+        raise
+    except:
+        obj.handle_error()
+
+def readwrite(obj, flags):
+    try:
+        if flags & select.POLLIN:
+            obj.handle_read_event()
+        if flags & select.POLLOUT:
+            obj.handle_write_event()
+        if flags & select.POLLPRI:
+            obj.handle_expt_event()
+        if flags & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
+            obj.handle_close()
+    except socket.error, e:
+        if e.args[0] not in _DISCONNECTED:
+            obj.handle_error()
+        else:
+            obj.handle_close()
+    except _reraised_exceptions:
+        raise
+    except:
+        obj.handle_error()
+
+def poll(timeout=0.0, map=None):
+    if map is None:
+        map = socket_map
+    if map:
+        r = []; w = []; e = []
+        for fd, obj in map.items():
+            is_r = obj.readable()
+            is_w = obj.writable()
+            if is_r:
+                r.append(fd)
+            # accepting sockets should not be writable
+            if is_w and not obj.accepting:
+                w.append(fd)
+            if is_r or is_w:
+                e.append(fd)
+        if [] == r == w == e:
+            time.sleep(timeout)
+            return
+
+        try:
+            r, w, e = select.select(r, w, e, timeout)
+        except select.error, err:
+            if err.args[0] != EINTR:
+                raise
+            else:
+                return
+
+        for fd in r:
+            obj = map.get(fd)
+            if obj is None:
+                continue
+            read(obj)
+
+        for fd in w:
+            obj = map.get(fd)
+            if obj is None:
+                continue
+            write(obj)
+
+        for fd in e:
+            obj = map.get(fd)
+            if obj is None:
+                continue
+            _exception(obj)
+
+def poll2(timeout=0.0, map=None):
+    # Use the poll() support added to the select module in Python 2.0
+    if map is None:
+        map = socket_map
+    if timeout is not None:
+        # timeout is in milliseconds
+        timeout = int(timeout*1000)
+    pollster = select.poll()
+    if map:
+        for fd, obj in map.items():
+            flags = 0
+            if obj.readable():
+                flags |= select.POLLIN | select.POLLPRI
+            # accepting sockets should not be writable
+            if obj.writable() and not obj.accepting:
+                flags |= select.POLLOUT
+            if flags:
+                # Only check for exceptions if object was either readable
+                # or writable.
+                flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL
+                pollster.register(fd, flags)
+        try:
+            r = pollster.poll(timeout)
+        except select.error, err:
+            if err.args[0] != EINTR:
+                raise
+            r = []
+        for fd, flags in r:
+            obj = map.get(fd)
+            if obj is None:
+                continue
+            readwrite(obj, flags)
+
+poll3 = poll2                           # Alias for backward compatibility
+
+def jython_poll_fun(timeout=0.0, map=None):
+    # On jython, select.poll() is the mechanism to use,
+    # select.select is implemented on top of it.
+    # Also, we have to use a cache of such objects, because of problems with frequent 
+    # creation and destruction  of such objects on windows
+    # "select() crashes with IOException": http://bugs.jython.org/issue1291
+    # So this function is basically the same function as poll2 above, except
+    # with the select.poll() functionality wrapped in a try..finally clause.
+    if map is None:
+        map = socket_map
+    if timeout is not None:
+        # timeout is in milliseconds
+        timeout = int(timeout*1000)
+    if map:
+        try:
+            pollster = select._poll_object_cache.get_poll_object()
+            for fd, obj in map.items():
+                flags = 0
+                if obj.readable():
+                    flags |= select.POLLIN | select.POLLPRI
+                # accepting sockets should not be writable
+                if obj.writable() and not obj.accepting:
+                    flags |= select.POLLOUT
+                if flags:
+                    # Only check for exceptions if object was either readable
+                    # or writable.
+                    flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL
+                    pollster.register(obj, flags)
+            try:
+                r = pollster.poll(timeout)
+            except select.error, err:
+                if err.args[0] != EINTR:
+                    raise
+                r = []
+            for obj, flags in r:
+                # obj = map.get(fd)
+                if obj is None:
+                    continue
+                readwrite(obj, flags)
+        finally:
+            select._poll_object_cache.release_poll_object(pollster)
+
+def loop(timeout=30.0, use_poll=False, map=None, count=None):
+    if map is None:
+        map = socket_map
+
+    if use_poll and hasattr(select, 'poll'):
+        poll_fun = poll2
+    else:
+        poll_fun = poll
+    if sys.platform.startswith('java'):
+        poll_fun = jython_poll_fun
+
+    if count is None:
+        while map:
+            poll_fun(timeout, map)
+
+    else:
+        while map and count > 0:
+            poll_fun(timeout, map)
+            count = count - 1
+
+class dispatcher:
+
+    debug = False
+    connected = False
+    accepting = False
+    connecting = False
+    closing = False
+    addr = None
+    ignore_log_types = frozenset(['warning'])
+
+    def __init__(self, sock=None, map=None):
+        if map is None:
+            self._map = socket_map
+        else:
+            self._map = map
+
+        self._fileno = None
+
+        if sock:
+            # Set to nonblocking just to make sure for cases where we
+            # get a socket from a blocking source.
+            sock.setblocking(0)
+            self.set_socket(sock, map)
+            self.connected = True
+            # The constructor no longer requires that the socket
+            # passed be connected.
+            try:
+                self.addr = sock.getpeername()
+            except socket.error, err:
+                if err.args[0] in (ENOTCONN, EINVAL):
+                    # To handle the case where we got an unconnected
+                    # socket.
+                    self.connected = False
+                else:
+                    # The socket is broken in some unknown way, alert
+                    # the user and remove it from the map (to prevent
+                    # polling of broken sockets).
+                    self.del_channel(map)
+                    raise
+        else:
+            self.socket = None
+
+    def __repr__(self):
+        status = [self.__class__.__module__+"."+self.__class__.__name__]
+        if self.accepting and self.addr:
+            status.append('listening')
+        elif self.connected:
+            status.append('connected')
+        if self.addr is not None:
+            try:
+                status.append('%s:%d' % self.addr)
+            except TypeError:
+                status.append(repr(self.addr))
+        return '<%s at %#x>' % (' '.join(status), id(self))
+
+    __str__ = __repr__
+
+    def add_channel(self, map=None):
+        #self.log_info('adding channel %s' % self)
+        if map is None:
+            map = self._map
+        map[self._fileno] = self
+
+    def del_channel(self, map=None):
+        fd = self._fileno
+        if map is None:
+            map = self._map
+        if fd in map:
+            #self.log_info('closing channel %d:%s' % (fd, self))
+            del map[fd]
+        self._fileno = None
+
+    def create_socket(self, family, type):
+        self.family_and_type = family, type
+        sock = socket.socket(family, type)
+        sock.setblocking(0)
+        self.set_socket(sock)
+
+    def set_socket(self, sock, map=None):
+        self.socket = sock
+##        self.__dict__['socket'] = sock
+        # On jython, the socket object itself is what is watchable.
+        # http://mail.python.org/pipermail/python-dev/2007-May/073443.html
+        self._fileno = sock
+        self.add_channel(map)
+
+    def set_reuse_addr(self):
+        # try to re-use a server port if possible
+        try:
+            self.socket.setsockopt(
+                socket.SOL_SOCKET, socket.SO_REUSEADDR,
+                self.socket.getsockopt(socket.SOL_SOCKET,
+                                       socket.SO_REUSEADDR) | 1
+                )
+        except socket.error:
+            pass
+
+    # ==================================================
+    # predicates for select()
+    # these are used as filters for the lists of sockets
+    # to pass to select().
+    # ==================================================
+
+    def readable(self):
+        return True
+
+    def writable(self):
+        return True
+
+    # ==================================================
+    # socket object methods.
+    # ==================================================
+
+    def listen(self, num):
+        self.accepting = True
+        if os.name == 'nt' and num > 5:
+            num = 5
+        return self.socket.listen(num)
+
+    def bind(self, addr):
+        self.addr = addr
+        return self.socket.bind(addr)
+
+    def connect(self, address):
+        self.connected = False
+        self.connecting = True
+        err = self.socket.connect_ex(address)
+        if err in (EINPROGRESS, EALREADY, EWOULDBLOCK) \
+        or err == EINVAL and os.name in ('nt', 'ce'):
+            self.addr = address
+            return
+        if err in (0, EISCONN):
+            self.addr = address
+            self.handle_connect_event()
+        else:
+            raise socket.error(err, errorcode[err])
+
+    def accept(self):
+        # XXX can return either an address pair or None
+        try:
+            conn, addr = self.socket.accept()
+        except TypeError:
+            return None
+        except socket.error as why:
+            if why.args[0] in (EWOULDBLOCK, ECONNABORTED, EAGAIN):
+                return None
+            else:
+                raise
+        else:
+            return conn, addr
+
+    def send(self, data):
+        try:
+            result = self.socket.send(data)
+            return result
+        except socket.error, why:
+            if why.args[0] == EWOULDBLOCK:
+                return 0
+            elif why.args[0] in _DISCONNECTED:
+                self.handle_close()
+                return 0
+            else:
+                raise
+
+    def recv(self, buffer_size):
+        try:
+            data = self.socket.recv(buffer_size)
+            if not data:
+                # a closed connection is indicated by signaling
+                # a read condition, and having recv() return 0.
+                self.handle_close()
+                return ''
+            else:
+                return data
+        except socket.error, why:
+            # winsock sometimes throws ENOTCONN
+            if why.args[0] in _DISCONNECTED:
+                self.handle_close()
+                return ''
+            else:
+                raise
+
+    def close(self):
+        self.connected = False
+        self.accepting = False
+        self.connecting = False
+        self.del_channel()
+        try:
+            self.socket.close()
+        except socket.error, why:
+            if why.args[0] not in (ENOTCONN, EBADF):
+                raise
+
+    # cheap inheritance, used to pass all other attribute
+    # references to the underlying socket object.
+    def __getattr__(self, attr):
+        try:
+            retattr = getattr(self.socket, attr)
+        except AttributeError:
+            raise AttributeError("%s instance has no attribute '%s'"
+                                 %(self.__class__.__name__, attr))
+        else:
+            msg = "%(me)s.%(attr)s is deprecated. Use %(me)s.socket.%(attr)s " \
+                  "instead." % {'me': self.__class__.__name__, 'attr':attr}
+            warnings.warn(msg, DeprecationWarning, stacklevel=2)
+            return retattr
+
+    # log and log_info may be overridden to provide more sophisticated
+    # logging and warning methods. In general, log is for 'hit' logging
+    # and 'log_info' is for informational, warning and error logging.
+
+    def log(self, message):
+        sys.stderr.write('log: %s\n' % str(message))
+
+    def log_info(self, message, type='info'):
+        if type not in self.ignore_log_types:
+            print '%s: %s' % (type, message)
+
+    def handle_read_event(self):
+        if self.accepting:
+            # accepting sockets are never connected, they "spawn" new
+            # sockets that are connected
+            self.handle_accept()
+        elif not self.connected:
+            if self.connecting:
+                self.handle_connect_event()
+            self.handle_read()
+        else:
+            self.handle_read()
+
+    def handle_connect_event(self):
+        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
+        if err != 0:
+            raise socket.error(err, _strerror(err))
+        self.handle_connect()
+        self.connected = True
+        self.connecting = False
+
+    def handle_write_event(self):
+        if self.accepting:
+            # Accepting sockets shouldn't get a write event.
+            # We will pretend it didn't happen.
+            return
+
+        if not self.connected:
+            if self.connecting:
+                self.handle_connect_event()
+        self.handle_write()
+
+    def handle_expt_event(self):
+        # handle_expt_event() is called if there might be an error on the
+        # socket, or if there is OOB data
+        # check for the error condition first
+        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
+        if err != 0:
+            # we can get here when select.select() says that there is an
+            # exceptional condition on the socket
+            # since there is an error, we'll go ahead and close the socket
+            # like we would in a subclassed handle_read() that received no
+            # data
+            self.handle_close()
+        else:
+            self.handle_expt()
+
+    def handle_error(self):
+        nil, t, v, tbinfo = compact_traceback()
+
+        # sometimes a user repr method will crash.
+        try:
+            self_repr = repr(self)
+        except:
+            self_repr = '<__repr__(self) failed for object at %0x>' % id(self)
+
+        self.log_info(
+            'uncaptured python exception, closing channel %s (%s:%s %s)' % (
+                self_repr,
+                t,
+                v,
+                tbinfo
+                ),
+            'error'
+            )
+        self.handle_close()
+
+    def handle_expt(self):
+        self.log_info('unhandled incoming priority event', 'warning')
+
+    def handle_read(self):
+        self.log_info('unhandled read event', 'warning')
+
+    def handle_write(self):
+        self.log_info('unhandled write event', 'warning')
+
+    def handle_connect(self):
+        self.log_info('unhandled connect event', 'warning')
+
+    def handle_accept(self):
+        self.log_info('unhandled accept event', 'warning')
+
+    def handle_close(self):
+        self.log_info('unhandled close event', 'warning')
+        self.close()
+
+# ---------------------------------------------------------------------------
+# adds simple buffered output capability, useful for simple clients.
+# [for more sophisticated usage use asynchat.async_chat]
+# ---------------------------------------------------------------------------
+
+class dispatcher_with_send(dispatcher):
+
+    def __init__(self, sock=None, map=None):
+        dispatcher.__init__(self, sock, map)
+        self.out_buffer = ''
+
+    def initiate_send(self):
+        num_sent = 0
+        num_sent = dispatcher.send(self, self.out_buffer[:512])
+        self.out_buffer = self.out_buffer[num_sent:]
+
+    def handle_write(self):
+        self.initiate_send()
+
+    def writable(self):
+        return (not self.connected) or len(self.out_buffer)
+
+    def send(self, data):
+        if self.debug:
+            self.log_info('sending %s' % repr(data))
+        self.out_buffer = self.out_buffer + data
+        self.initiate_send()
+
+# ---------------------------------------------------------------------------
+# used for debugging.
+# ---------------------------------------------------------------------------
+
+def compact_traceback():
+    t, v, tb = sys.exc_info()
+    tbinfo = []
+    if not tb: # Must have a traceback
+        raise AssertionError("traceback does not exist")
+    while tb:
+        tbinfo.append((
+            tb.tb_frame.f_code.co_filename,
+            tb.tb_frame.f_code.co_name,
+            str(tb.tb_lineno)
+            ))
+        tb = tb.tb_next
+
+    # just to be safe
+    del tb
+
+    file, function, line = tbinfo[-1]
+    info = ' '.join(['[%s|%s|%s]' % x for x in tbinfo])
+    return (file, function, line), t, v, info
+
+def close_all(map=None, ignore_all=False):
+    if map is None:
+        map = socket_map
+    for x in map.values():
+        try:
+            x.close()
+        except OSError, x:
+            if x.args[0] == EBADF:
+                pass
+            elif not ignore_all:
+                raise
+        except _reraised_exceptions:
+            raise
+        except:
+            if not ignore_all:
+                raise
+    map.clear()
+
+# Asynchronous File I/O:
+#
+# After a little research (reading man pages on various unixen, and
+# digging through the linux kernel), I've determined that select()
+# isn't meant for doing asynchronous file i/o.
+# Heartening, though - reading linux/mm/filemap.c shows that linux
+# supports asynchronous read-ahead.  So _MOST_ of the time, the data
+# will be sitting in memory for us already when we go to read it.
+#
+# What other OS's (besides NT) support async file i/o?  [VMS?]
+#
+# Regardless, this is useful for pipes, and stdin/stdout...
+
+if os.name == 'posix':
+    import fcntl
+
+    class file_wrapper:
+        # Here we override just enough to make a file
+        # look like a socket for the purposes of asyncore.
+        # The passed fd is automatically os.dup()'d
+
+        def __init__(self, fd):
+            self.fd = os.dup(fd)
+
+        def recv(self, *args):
+            return os.read(self.fd, *args)
+
+        def send(self, *args):
+            return os.write(self.fd, *args)
+
+        def getsockopt(self, level, optname, buflen=None):
+            if (level == socket.SOL_SOCKET and
+                optname == socket.SO_ERROR and
+                not buflen):
+                return 0
+            raise NotImplementedError("Only asyncore specific behaviour "
+                                      "implemented.")
+
+        read = recv
+        write = send
+
+        def close(self):
+            os.close(self.fd)
+
+        def fileno(self):
+            return self.fd
+
+    class file_dispatcher(dispatcher):
+
+        def __init__(self, fd, map=None):
+            dispatcher.__init__(self, None, map)
+            self.connected = True
+            try:
+                fd = fd.fileno()
+            except AttributeError:
+                pass
+            self.set_file(fd)
+            # set it to non-blocking mode
+            flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
+            flags = flags | os.O_NONBLOCK
+            fcntl.fcntl(fd, fcntl.F_SETFL, flags)
+
+        def set_file(self, fd):
+            self.socket = file_wrapper(fd)
+            self._fileno = self.socket.fileno()
+            self.add_channel()
diff --git a/src/main/resources/PythonLibs/atexit.py b/src/main/resources/PythonLibs/atexit.py
new file mode 100644
index 0000000000000000000000000000000000000000..93fddf7f99a4473f971474745a74330059150010
--- /dev/null
+++ b/src/main/resources/PythonLibs/atexit.py
@@ -0,0 +1,65 @@
+"""
+atexit.py - allow programmer to define multiple exit functions to be executed
+upon normal program termination.
+
+One public function, register, is defined.
+"""
+
+__all__ = ["register"]
+
+import sys
+
+_exithandlers = []
+def _run_exitfuncs():
+    """run any registered exit functions
+
+    _exithandlers is traversed in reverse order so functions are executed
+    last in, first out.
+    """
+
+    exc_info = None
+    while _exithandlers:
+        func, targs, kargs = _exithandlers.pop()
+        try:
+            func(*targs, **kargs)
+        except SystemExit:
+            exc_info = sys.exc_info()
+        except:
+            import traceback
+            print >> sys.stderr, "Error in atexit._run_exitfuncs:"
+            traceback.print_exc()
+            exc_info = sys.exc_info()
+
+    if exc_info is not None:
+        raise exc_info[0], exc_info[1], exc_info[2]
+
+
+def register(func, *targs, **kargs):
+    """register a function to be executed upon normal program termination
+
+    func - function to be called at exit
+    targs - optional arguments to pass to func
+    kargs - optional keyword arguments to pass to func
+
+    func is returned to facilitate usage as a decorator.
+    """
+    _exithandlers.append((func, targs, kargs))
+    return func
+
+if hasattr(sys, "exitfunc"):
+    # Assume it's another registered exit function - append it to our list
+    register(sys.exitfunc)
+sys.exitfunc = _run_exitfuncs
+
+if __name__ == "__main__":
+    def x1():
+        print "running x1"
+    def x2(n):
+        print "running x2(%r)" % (n,)
+    def x3(n, kwd=None):
+        print "running x3(%r, kwd=%r)" % (n, kwd)
+
+    register(x1)
+    register(x2, 12)
+    register(x3, 5, "bar")
+    register(x3, "no kwd args")
diff --git a/src/main/resources/PythonLibs/base64.py b/src/main/resources/PythonLibs/base64.py
new file mode 100644
index 0000000000000000000000000000000000000000..85204dd022ab467e3b34d4cbdae1b6b0b05fea1b
--- /dev/null
+++ b/src/main/resources/PythonLibs/base64.py
@@ -0,0 +1,360 @@
+#! /usr/bin/env python
+
+"""RFC 3548: Base16, Base32, Base64 Data Encodings"""
+
+# Modified 04-Oct-1995 by Jack Jansen to use binascii module
+# Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support
+
+import re
+import struct
+import binascii
+
+
+__all__ = [
+    # Legacy interface exports traditional RFC 1521 Base64 encodings
+    'encode', 'decode', 'encodestring', 'decodestring',
+    # Generalized interface for other encodings
+    'b64encode', 'b64decode', 'b32encode', 'b32decode',
+    'b16encode', 'b16decode',
+    # Standard Base64 encoding
+    'standard_b64encode', 'standard_b64decode',
+    # Some common Base64 alternatives.  As referenced by RFC 3458, see thread
+    # starting at:
+    #
+    # http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html
+    'urlsafe_b64encode', 'urlsafe_b64decode',
+    ]
+
+_translation = [chr(_x) for _x in range(256)]
+EMPTYSTRING = ''
+
+
+def _translate(s, altchars):
+    translation = _translation[:]
+    for k, v in altchars.items():
+        translation[ord(k)] = v
+    return s.translate(''.join(translation))
+
+
+
+# Base64 encoding/decoding uses binascii
+
+def b64encode(s, altchars=None):
+    """Encode a string using Base64.
+
+    s is the string to encode.  Optional altchars must be a string of at least
+    length 2 (additional characters are ignored) which specifies an
+    alternative alphabet for the '+' and '/' characters.  This allows an
+    application to e.g. generate url or filesystem safe Base64 strings.
+
+    The encoded string is returned.
+    """
+    # Strip off the trailing newline
+    encoded = binascii.b2a_base64(s)[:-1]
+    if altchars is not None:
+        return _translate(encoded, {'+': altchars[0], '/': altchars[1]})
+    return encoded
+
+
+def b64decode(s, altchars=None):
+    """Decode a Base64 encoded string.
+
+    s is the string to decode.  Optional altchars must be a string of at least
+    length 2 (additional characters are ignored) which specifies the
+    alternative alphabet used instead of the '+' and '/' characters.
+
+    The decoded string is returned.  A TypeError is raised if s were
+    incorrectly padded or if there are non-alphabet characters present in the
+    string.
+    """
+    if altchars is not None:
+        s = _translate(s, {altchars[0]: '+', altchars[1]: '/'})
+    try:
+        return binascii.a2b_base64(s)
+    except binascii.Error, msg:
+        # Transform this exception for consistency
+        raise TypeError(msg)
+
+
+def standard_b64encode(s):
+    """Encode a string using the standard Base64 alphabet.
+
+    s is the string to encode.  The encoded string is returned.
+    """
+    return b64encode(s)
+
+def standard_b64decode(s):
+    """Decode a string encoded with the standard Base64 alphabet.
+
+    s is the string to decode.  The decoded string is returned.  A TypeError
+    is raised if the string is incorrectly padded or if there are non-alphabet
+    characters present in the string.
+    """
+    return b64decode(s)
+
+def urlsafe_b64encode(s):
+    """Encode a string using a url-safe Base64 alphabet.
+
+    s is the string to encode.  The encoded string is returned.  The alphabet
+    uses '-' instead of '+' and '_' instead of '/'.
+    """
+    return b64encode(s, '-_')
+
+def urlsafe_b64decode(s):
+    """Decode a string encoded with the standard Base64 alphabet.
+
+    s is the string to decode.  The decoded string is returned.  A TypeError
+    is raised if the string is incorrectly padded or if there are non-alphabet
+    characters present in the string.
+
+    The alphabet uses '-' instead of '+' and '_' instead of '/'.
+    """
+    return b64decode(s, '-_')
+
+
+
+# Base32 encoding/decoding must be done in Python
+_b32alphabet = {
+    0: 'A',  9: 'J', 18: 'S', 27: '3',
+    1: 'B', 10: 'K', 19: 'T', 28: '4',
+    2: 'C', 11: 'L', 20: 'U', 29: '5',
+    3: 'D', 12: 'M', 21: 'V', 30: '6',
+    4: 'E', 13: 'N', 22: 'W', 31: '7',
+    5: 'F', 14: 'O', 23: 'X',
+    6: 'G', 15: 'P', 24: 'Y',
+    7: 'H', 16: 'Q', 25: 'Z',
+    8: 'I', 17: 'R', 26: '2',
+    }
+
+_b32tab = _b32alphabet.items()
+_b32tab.sort()
+_b32tab = [v for k, v in _b32tab]
+_b32rev = dict([(v, long(k)) for k, v in _b32alphabet.items()])
+
+
+def b32encode(s):
+    """Encode a string using Base32.
+
+    s is the string to encode.  The encoded string is returned.
+    """
+    parts = []
+    quanta, leftover = divmod(len(s), 5)
+    # Pad the last quantum with zero bits if necessary
+    if leftover:
+        s += ('\0' * (5 - leftover))
+        quanta += 1
+    for i in range(quanta):
+        # c1 and c2 are 16 bits wide, c3 is 8 bits wide.  The intent of this
+        # code is to process the 40 bits in units of 5 bits.  So we take the 1
+        # leftover bit of c1 and tack it onto c2.  Then we take the 2 leftover
+        # bits of c2 and tack them onto c3.  The shifts and masks are intended
+        # to give us values of exactly 5 bits in width.
+        c1, c2, c3 = struct.unpack('!HHB', s[i*5:(i+1)*5])
+        c2 += (c1 & 1) << 16 # 17 bits wide
+        c3 += (c2 & 3) << 8  # 10 bits wide
+        parts.extend([_b32tab[c1 >> 11],         # bits 1 - 5
+                      _b32tab[(c1 >> 6) & 0x1f], # bits 6 - 10
+                      _b32tab[(c1 >> 1) & 0x1f], # bits 11 - 15
+                      _b32tab[c2 >> 12],         # bits 16 - 20 (1 - 5)
+                      _b32tab[(c2 >> 7) & 0x1f], # bits 21 - 25 (6 - 10)
+                      _b32tab[(c2 >> 2) & 0x1f], # bits 26 - 30 (11 - 15)
+                      _b32tab[c3 >> 5],          # bits 31 - 35 (1 - 5)
+                      _b32tab[c3 & 0x1f],        # bits 36 - 40 (1 - 5)
+                      ])
+    encoded = EMPTYSTRING.join(parts)
+    # Adjust for any leftover partial quanta
+    if leftover == 1:
+        return encoded[:-6] + '======'
+    elif leftover == 2:
+        return encoded[:-4] + '===='
+    elif leftover == 3:
+        return encoded[:-3] + '==='
+    elif leftover == 4:
+        return encoded[:-1] + '='
+    return encoded
+
+
+def b32decode(s, casefold=False, map01=None):
+    """Decode a Base32 encoded string.
+
+    s is the string to decode.  Optional casefold is a flag specifying whether
+    a lowercase alphabet is acceptable as input.  For security purposes, the
+    default is False.
+
+    RFC 3548 allows for optional mapping of the digit 0 (zero) to the letter O
+    (oh), and for optional mapping of the digit 1 (one) to either the letter I
+    (eye) or letter L (el).  The optional argument map01 when not None,
+    specifies which letter the digit 1 should be mapped to (when map01 is not
+    None, the digit 0 is always mapped to the letter O).  For security
+    purposes the default is None, so that 0 and 1 are not allowed in the
+    input.
+
+    The decoded string is returned.  A TypeError is raised if s were
+    incorrectly padded or if there are non-alphabet characters present in the
+    string.
+    """
+    quanta, leftover = divmod(len(s), 8)
+    if leftover:
+        raise TypeError('Incorrect padding')
+    # Handle section 2.4 zero and one mapping.  The flag map01 will be either
+    # False, or the character to map the digit 1 (one) to.  It should be
+    # either L (el) or I (eye).
+    if map01:
+        s = _translate(s, {'0': 'O', '1': map01})
+    if casefold:
+        s = s.upper()
+    # Strip off pad characters from the right.  We need to count the pad
+    # characters because this will tell us how many null bytes to remove from
+    # the end of the decoded string.
+    padchars = 0
+    mo = re.search('(?P<pad>[=]*)$', s)
+    if mo:
+        padchars = len(mo.group('pad'))
+        if padchars > 0:
+            s = s[:-padchars]
+    # Now decode the full quanta
+    parts = []
+    acc = 0
+    shift = 35
+    for c in s:
+        val = _b32rev.get(c)
+        if val is None:
+            raise TypeError('Non-base32 digit found')
+        acc += _b32rev[c] << shift
+        shift -= 5
+        if shift < 0:
+            parts.append(binascii.unhexlify('%010x' % acc))
+            acc = 0
+            shift = 35
+    # Process the last, partial quanta
+    last = binascii.unhexlify('%010x' % acc)
+    if padchars == 0:
+        last = ''                       # No characters
+    elif padchars == 1:
+        last = last[:-1]
+    elif padchars == 3:
+        last = last[:-2]
+    elif padchars == 4:
+        last = last[:-3]
+    elif padchars == 6:
+        last = last[:-4]
+    else:
+        raise TypeError('Incorrect padding')
+    parts.append(last)
+    return EMPTYSTRING.join(parts)
+
+
+
+# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns
+# lowercase.  The RFC also recommends against accepting input case
+# insensitively.
+def b16encode(s):
+    """Encode a string using Base16.
+
+    s is the string to encode.  The encoded string is returned.
+    """
+    return binascii.hexlify(s).upper()
+
+
+def b16decode(s, casefold=False):
+    """Decode a Base16 encoded string.
+
+    s is the string to decode.  Optional casefold is a flag specifying whether
+    a lowercase alphabet is acceptable as input.  For security purposes, the
+    default is False.
+
+    The decoded string is returned.  A TypeError is raised if s were
+    incorrectly padded or if there are non-alphabet characters present in the
+    string.
+    """
+    if casefold:
+        s = s.upper()
+    if re.search('[^0-9A-F]', s):
+        raise TypeError('Non-base16 digit found')
+    return binascii.unhexlify(s)
+
+
+
+# Legacy interface.  This code could be cleaned up since I don't believe
+# binascii has any line length limitations.  It just doesn't seem worth it
+# though.
+
+MAXLINESIZE = 76 # Excluding the CRLF
+MAXBINSIZE = (MAXLINESIZE//4)*3
+
+def encode(input, output):
+    """Encode a file."""
+    while True:
+        s = input.read(MAXBINSIZE)
+        if not s:
+            break
+        while len(s) < MAXBINSIZE:
+            ns = input.read(MAXBINSIZE-len(s))
+            if not ns:
+                break
+            s += ns
+        line = binascii.b2a_base64(s)
+        output.write(line)
+
+
+def decode(input, output):
+    """Decode a file."""
+    while True:
+        line = input.readline()
+        if not line:
+            break
+        s = binascii.a2b_base64(line)
+        output.write(s)
+
+
+def encodestring(s):
+    """Encode a string into multiple lines of base-64 data."""
+    pieces = []
+    for i in range(0, len(s), MAXBINSIZE):
+        chunk = s[i : i + MAXBINSIZE]
+        pieces.append(binascii.b2a_base64(chunk))
+    return "".join(pieces)
+
+
+def decodestring(s):
+    """Decode a string."""
+    return binascii.a2b_base64(s)
+
+
+
+# Useable as a script...
+def test():
+    """Small test program"""
+    import sys, getopt
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'deut')
+    except getopt.error, msg:
+        sys.stdout = sys.stderr
+        print msg
+        print """usage: %s [-d|-e|-u|-t] [file|-]
+        -d, -u: decode
+        -e: encode (default)
+        -t: encode and decode string 'Aladdin:open sesame'"""%sys.argv[0]
+        sys.exit(2)
+    func = encode
+    for o, a in opts:
+        if o == '-e': func = encode
+        if o == '-d': func = decode
+        if o == '-u': func = decode
+        if o == '-t': test1(); return
+    if args and args[0] != '-':
+        with open(args[0], 'rb') as f:
+            func(f, sys.stdout)
+    else:
+        func(sys.stdin, sys.stdout)
+
+
+def test1():
+    s0 = "Aladdin:open sesame"
+    s1 = encodestring(s0)
+    s2 = decodestring(s1)
+    print s0, repr(s1), s2
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/bdb.py b/src/main/resources/PythonLibs/bdb.py
new file mode 100644
index 0000000000000000000000000000000000000000..59440a99a0fab025d1dcf8dd1610f56e1729b149
--- /dev/null
+++ b/src/main/resources/PythonLibs/bdb.py
@@ -0,0 +1,645 @@
+"""Debugger basics"""
+
+import fnmatch
+import sys
+import os
+import types
+
+__all__ = ["BdbQuit","Bdb","Breakpoint"]
+
+class BdbQuit(Exception):
+    """Exception to give up completely"""
+
+
+class Bdb:
+
+    """Generic Python debugger base class.
+
+    This class takes care of details of the trace facility;
+    a derived class should implement user interaction.
+    The standard debugger class (pdb.Pdb) is an example.
+    """
+
+    def __init__(self, skip=None):
+        self.skip = set(skip) if skip else None
+        self.breaks = {}
+        self.fncache = {}
+        self.frame_returning = None
+
+    def canonic(self, filename):
+        if filename == "<" + filename[1:-1] + ">":
+            return filename
+        canonic = self.fncache.get(filename)
+        if not canonic:
+            canonic = os.path.abspath(filename)
+            canonic = os.path.normcase(canonic)
+            self.fncache[filename] = canonic
+        return canonic
+
+    def reset(self):
+        import linecache
+        linecache.checkcache()
+        self.botframe = None
+        self._set_stopinfo(None, None)
+
+    def trace_dispatch(self, frame, event, arg):
+        if self.quitting:
+            return # None
+        if event == 'line':
+            return self.dispatch_line(frame)
+        if event == 'call':
+            return self.dispatch_call(frame, arg)
+        if event == 'return':
+            return self.dispatch_return(frame, arg)
+        if event == 'exception':
+            return self.dispatch_exception(frame, arg)
+        if event == 'c_call':
+            return self.trace_dispatch
+        if event == 'c_exception':
+            return self.trace_dispatch
+        if event == 'c_return':
+            return self.trace_dispatch
+        print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event)
+        return self.trace_dispatch
+
+    def dispatch_line(self, frame):
+        if self.stop_here(frame) or self.break_here(frame):
+            self.user_line(frame)
+            if self.quitting: raise BdbQuit
+        return self.trace_dispatch
+
+    def dispatch_call(self, frame, arg):
+        # XXX 'arg' is no longer used
+        if self.botframe is None:
+            # First call of dispatch since reset()
+            self.botframe = frame.f_back # (CT) Note that this may also be None!
+            return self.trace_dispatch
+        if not (self.stop_here(frame) or self.break_anywhere(frame)):
+            # No need to trace this function
+            return # None
+        self.user_call(frame, arg)
+        if self.quitting: raise BdbQuit
+        return self.trace_dispatch
+
+    def dispatch_return(self, frame, arg):
+        if self.stop_here(frame) or frame == self.returnframe:
+            try:
+                self.frame_returning = frame
+                self.user_return(frame, arg)
+            finally:
+                self.frame_returning = None
+            if self.quitting: raise BdbQuit
+        return self.trace_dispatch
+
+    def dispatch_exception(self, frame, arg):
+        if self.stop_here(frame):
+            self.user_exception(frame, arg)
+            if self.quitting: raise BdbQuit
+        return self.trace_dispatch
+
+    # Normally derived classes don't override the following
+    # methods, but they may if they want to redefine the
+    # definition of stopping and breakpoints.
+
+    def is_skipped_module(self, module_name):
+        for pattern in self.skip:
+            if fnmatch.fnmatch(module_name, pattern):
+                return True
+        return False
+
+    def stop_here(self, frame):
+        # (CT) stopframe may now also be None, see dispatch_call.
+        # (CT) the former test for None is therefore removed from here.
+        if self.skip and \
+               self.is_skipped_module(frame.f_globals.get('__name__')):
+            return False
+        if frame is self.stopframe:
+            if self.stoplineno == -1:
+                return False
+            return frame.f_lineno >= self.stoplineno
+        while frame is not None and frame is not self.stopframe:
+            if frame is self.botframe:
+                return True
+            frame = frame.f_back
+        return False
+
+    def break_here(self, frame):
+        filename = self.canonic(frame.f_code.co_filename)
+        if not filename in self.breaks:
+            return False
+        lineno = frame.f_lineno
+        if not lineno in self.breaks[filename]:
+            # The line itself has no breakpoint, but maybe the line is the
+            # first line of a function with breakpoint set by function name.
+            lineno = frame.f_code.co_firstlineno
+            if not lineno in self.breaks[filename]:
+                return False
+
+        # flag says ok to delete temp. bp
+        (bp, flag) = effective(filename, lineno, frame)
+        if bp:
+            self.currentbp = bp.number
+            if (flag and bp.temporary):
+                self.do_clear(str(bp.number))
+            return True
+        else:
+            return False
+
+    def do_clear(self, arg):
+        raise NotImplementedError, "subclass of bdb must implement do_clear()"
+
+    def break_anywhere(self, frame):
+        return self.canonic(frame.f_code.co_filename) in self.breaks
+
+    # Derived classes should override the user_* methods
+    # to gain control.
+
+    def user_call(self, frame, argument_list):
+        """This method is called when there is the remote possibility
+        that we ever need to stop in this function."""
+        pass
+
+    def user_line(self, frame):
+        """This method is called when we stop or break at this line."""
+        pass
+
+    def user_return(self, frame, return_value):
+        """This method is called when a return trap is set here."""
+        pass
+
+    def user_exception(self, frame, exc_info):
+        exc_type, exc_value, exc_traceback = exc_info
+        """This method is called if an exception occurs,
+        but only if we are to stop at or just below this level."""
+        pass
+
+    def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
+        self.stopframe = stopframe
+        self.returnframe = returnframe
+        self.quitting = 0
+        # stoplineno >= 0 means: stop at line >= the stoplineno
+        # stoplineno -1 means: don't stop at all
+        self.stoplineno = stoplineno
+
+    # Derived classes and clients can call the following methods
+    # to affect the stepping state.
+
+    def set_until(self, frame): #the name "until" is borrowed from gdb
+        """Stop when the line with the line no greater than the current one is
+        reached or when returning from current frame"""
+        self._set_stopinfo(frame, frame, frame.f_lineno+1)
+
+    def set_step(self):
+        """Stop after one line of code."""
+        # Issue #13183: pdb skips frames after hitting a breakpoint and running
+        # step commands.
+        # Restore the trace function in the caller (that may not have been set
+        # for performance reasons) when returning from the current frame.
+        if self.frame_returning:
+            caller_frame = self.frame_returning.f_back
+            if caller_frame and not caller_frame.f_trace:
+                caller_frame.f_trace = self.trace_dispatch
+        self._set_stopinfo(None, None)
+
+    def set_next(self, frame):
+        """Stop on the next line in or below the given frame."""
+        self._set_stopinfo(frame, None)
+
+    def set_return(self, frame):
+        """Stop when returning from the given frame."""
+        self._set_stopinfo(frame.f_back, frame)
+
+    def set_trace(self, frame=None):
+        """Start debugging from `frame`.
+
+        If frame is not specified, debugging starts from caller's frame.
+        """
+        if frame is None:
+            frame = sys._getframe().f_back
+        self.reset()
+        while frame:
+            frame.f_trace = self.trace_dispatch
+            self.botframe = frame
+            frame = frame.f_back
+        self.set_step()
+        sys.settrace(self.trace_dispatch)
+
+    def set_continue(self):
+        # Don't stop except at breakpoints or when finished
+        self._set_stopinfo(self.botframe, None, -1)
+        if not self.breaks:
+            # no breakpoints; run without debugger overhead
+            sys.settrace(None)
+            frame = sys._getframe().f_back
+            while frame and frame is not self.botframe:
+                del frame.f_trace
+                frame = frame.f_back
+
+    def set_quit(self):
+        self.stopframe = self.botframe
+        self.returnframe = None
+        self.quitting = 1
+        sys.settrace(None)
+
+    # Derived classes and clients can call the following methods
+    # to manipulate breakpoints.  These methods return an
+    # error message is something went wrong, None if all is well.
+    # Set_break prints out the breakpoint line and file:lineno.
+    # Call self.get_*break*() to see the breakpoints or better
+    # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
+
+    def set_break(self, filename, lineno, temporary=0, cond = None,
+                  funcname=None):
+        filename = self.canonic(filename)
+        import linecache # Import as late as possible
+        line = linecache.getline(filename, lineno)
+        if not line:
+            return 'Line %s:%d does not exist' % (filename,
+                                   lineno)
+        if not filename in self.breaks:
+            self.breaks[filename] = []
+        list = self.breaks[filename]
+        if not lineno in list:
+            list.append(lineno)
+        bp = Breakpoint(filename, lineno, temporary, cond, funcname)
+
+    def _prune_breaks(self, filename, lineno):
+        if (filename, lineno) not in Breakpoint.bplist:
+            self.breaks[filename].remove(lineno)
+        if not self.breaks[filename]:
+            del self.breaks[filename]
+
+    def clear_break(self, filename, lineno):
+        filename = self.canonic(filename)
+        if not filename in self.breaks:
+            return 'There are no breakpoints in %s' % filename
+        if lineno not in self.breaks[filename]:
+            return 'There is no breakpoint at %s:%d' % (filename,
+                                    lineno)
+        # If there's only one bp in the list for that file,line
+        # pair, then remove the breaks entry
+        for bp in Breakpoint.bplist[filename, lineno][:]:
+            bp.deleteMe()
+        self._prune_breaks(filename, lineno)
+
+    def clear_bpbynumber(self, arg):
+        try:
+            number = int(arg)
+        except:
+            return 'Non-numeric breakpoint number (%s)' % arg
+        try:
+            bp = Breakpoint.bpbynumber[number]
+        except IndexError:
+            return 'Breakpoint number (%d) out of range' % number
+        if not bp:
+            return 'Breakpoint (%d) already deleted' % number
+        bp.deleteMe()
+        self._prune_breaks(bp.file, bp.line)
+
+    def clear_all_file_breaks(self, filename):
+        filename = self.canonic(filename)
+        if not filename in self.breaks:
+            return 'There are no breakpoints in %s' % filename
+        for line in self.breaks[filename]:
+            blist = Breakpoint.bplist[filename, line]
+            for bp in blist:
+                bp.deleteMe()
+        del self.breaks[filename]
+
+    def clear_all_breaks(self):
+        if not self.breaks:
+            return 'There are no breakpoints'
+        for bp in Breakpoint.bpbynumber:
+            if bp:
+                bp.deleteMe()
+        self.breaks = {}
+
+    def get_break(self, filename, lineno):
+        filename = self.canonic(filename)
+        return filename in self.breaks and \
+            lineno in self.breaks[filename]
+
+    def get_breaks(self, filename, lineno):
+        filename = self.canonic(filename)
+        return filename in self.breaks and \
+            lineno in self.breaks[filename] and \
+            Breakpoint.bplist[filename, lineno] or []
+
+    def get_file_breaks(self, filename):
+        filename = self.canonic(filename)
+        if filename in self.breaks:
+            return self.breaks[filename]
+        else:
+            return []
+
+    def get_all_breaks(self):
+        return self.breaks
+
+    # Derived classes and clients can call the following method
+    # to get a data structure representing a stack trace.
+
+    def get_stack(self, f, t):
+        stack = []
+        if t and t.tb_frame is f:
+            t = t.tb_next
+        while f is not None:
+            stack.append((f, f.f_lineno))
+            if f is self.botframe:
+                break
+            f = f.f_back
+        stack.reverse()
+        i = max(0, len(stack) - 1)
+        while t is not None:
+            stack.append((t.tb_frame, t.tb_lineno))
+            t = t.tb_next
+        if f is None:
+            i = max(0, len(stack) - 1)
+        return stack, i
+
+    #
+
+    def format_stack_entry(self, frame_lineno, lprefix=': '):
+        import linecache, repr
+        frame, lineno = frame_lineno
+        filename = self.canonic(frame.f_code.co_filename)
+        s = '%s(%r)' % (filename, lineno)
+        if frame.f_code.co_name:
+            s = s + frame.f_code.co_name
+        else:
+            s = s + "<lambda>"
+        if '__args__' in frame.f_locals:
+            args = frame.f_locals['__args__']
+        else:
+            args = None
+        if args:
+            s = s + repr.repr(args)
+        else:
+            s = s + '()'
+        if '__return__' in frame.f_locals:
+            rv = frame.f_locals['__return__']
+            s = s + '->'
+            s = s + repr.repr(rv)
+        line = linecache.getline(filename, lineno, frame.f_globals)
+        if line: s = s + lprefix + line.strip()
+        return s
+
+    # The following two methods can be called by clients to use
+    # a debugger to debug a statement, given as a string.
+
+    def run(self, cmd, globals=None, locals=None):
+        if globals is None:
+            import __main__
+            globals = __main__.__dict__
+        if locals is None:
+            locals = globals
+        self.reset()
+        sys.settrace(self.trace_dispatch)
+        if not isinstance(cmd, types.CodeType):
+            cmd = cmd+'\n'
+        try:
+            exec cmd in globals, locals
+        except BdbQuit:
+            pass
+        finally:
+            self.quitting = 1
+            sys.settrace(None)
+
+    def runeval(self, expr, globals=None, locals=None):
+        if globals is None:
+            import __main__
+            globals = __main__.__dict__
+        if locals is None:
+            locals = globals
+        self.reset()
+        sys.settrace(self.trace_dispatch)
+        if not isinstance(expr, types.CodeType):
+            expr = expr+'\n'
+        try:
+            return eval(expr, globals, locals)
+        except BdbQuit:
+            pass
+        finally:
+            self.quitting = 1
+            sys.settrace(None)
+
+    def runctx(self, cmd, globals, locals):
+        # B/W compatibility
+        self.run(cmd, globals, locals)
+
+    # This method is more useful to debug a single function call.
+
+    def runcall(self, func, *args, **kwds):
+        self.reset()
+        sys.settrace(self.trace_dispatch)
+        res = None
+        try:
+            res = func(*args, **kwds)
+        except BdbQuit:
+            pass
+        finally:
+            self.quitting = 1
+            sys.settrace(None)
+        return res
+
+
+def set_trace():
+    Bdb().set_trace()
+
+
+class Breakpoint:
+
+    """Breakpoint class
+
+    Implements temporary breakpoints, ignore counts, disabling and
+    (re)-enabling, and conditionals.
+
+    Breakpoints are indexed by number through bpbynumber and by
+    the file,line tuple using bplist.  The former points to a
+    single instance of class Breakpoint.  The latter points to a
+    list of such instances since there may be more than one
+    breakpoint per line.
+
+    """
+
+    # XXX Keeping state in the class is a mistake -- this means
+    # you cannot have more than one active Bdb instance.
+
+    next = 1        # Next bp to be assigned
+    bplist = {}     # indexed by (file, lineno) tuple
+    bpbynumber = [None] # Each entry is None or an instance of Bpt
+                # index 0 is unused, except for marking an
+                # effective break .... see effective()
+
+    def __init__(self, file, line, temporary=0, cond=None, funcname=None):
+        self.funcname = funcname
+        # Needed if funcname is not None.
+        self.func_first_executable_line = None
+        self.file = file    # This better be in canonical form!
+        self.line = line
+        self.temporary = temporary
+        self.cond = cond
+        self.enabled = 1
+        self.ignore = 0
+        self.hits = 0
+        self.number = Breakpoint.next
+        Breakpoint.next = Breakpoint.next + 1
+        # Build the two lists
+        self.bpbynumber.append(self)
+        if (file, line) in self.bplist:
+            self.bplist[file, line].append(self)
+        else:
+            self.bplist[file, line] = [self]
+
+
+    def deleteMe(self):
+        index = (self.file, self.line)
+        self.bpbynumber[self.number] = None   # No longer in list
+        self.bplist[index].remove(self)
+        if not self.bplist[index]:
+            # No more bp for this f:l combo
+            del self.bplist[index]
+
+    def enable(self):
+        self.enabled = 1
+
+    def disable(self):
+        self.enabled = 0
+
+    def bpprint(self, out=None):
+        if out is None:
+            out = sys.stdout
+        if self.temporary:
+            disp = 'del  '
+        else:
+            disp = 'keep '
+        if self.enabled:
+            disp = disp + 'yes  '
+        else:
+            disp = disp + 'no   '
+        print >>out, '%-4dbreakpoint   %s at %s:%d' % (self.number, disp,
+                                                       self.file, self.line)
+        if self.cond:
+            print >>out, '\tstop only if %s' % (self.cond,)
+        if self.ignore:
+            print >>out, '\tignore next %d hits' % (self.ignore)
+        if (self.hits):
+            if (self.hits > 1): ss = 's'
+            else: ss = ''
+            print >>out, ('\tbreakpoint already hit %d time%s' %
+                          (self.hits, ss))
+
+# -----------end of Breakpoint class----------
+
+def checkfuncname(b, frame):
+    """Check whether we should break here because of `b.funcname`."""
+    if not b.funcname:
+        # Breakpoint was set via line number.
+        if b.line != frame.f_lineno:
+            # Breakpoint was set at a line with a def statement and the function
+            # defined is called: don't break.
+            return False
+        return True
+
+    # Breakpoint set via function name.
+
+    if frame.f_code.co_name != b.funcname:
+        # It's not a function call, but rather execution of def statement.
+        return False
+
+    # We are in the right frame.
+    if not b.func_first_executable_line:
+        # The function is entered for the 1st time.
+        b.func_first_executable_line = frame.f_lineno
+
+    if  b.func_first_executable_line != frame.f_lineno:
+        # But we are not at the first line number: don't break.
+        return False
+    return True
+
+# Determines if there is an effective (active) breakpoint at this
+# line of code.  Returns breakpoint number or 0 if none
+def effective(file, line, frame):
+    """Determine which breakpoint for this file:line is to be acted upon.
+
+    Called only if we know there is a bpt at this
+    location.  Returns breakpoint that was triggered and a flag
+    that indicates if it is ok to delete a temporary bp.
+
+    """
+    possibles = Breakpoint.bplist[file,line]
+    for i in range(0, len(possibles)):
+        b = possibles[i]
+        if b.enabled == 0:
+            continue
+        if not checkfuncname(b, frame):
+            continue
+        # Count every hit when bp is enabled
+        b.hits = b.hits + 1
+        if not b.cond:
+            # If unconditional, and ignoring,
+            # go on to next, else break
+            if b.ignore > 0:
+                b.ignore = b.ignore -1
+                continue
+            else:
+                # breakpoint and marker that's ok
+                # to delete if temporary
+                return (b,1)
+        else:
+            # Conditional bp.
+            # Ignore count applies only to those bpt hits where the
+            # condition evaluates to true.
+            try:
+                val = eval(b.cond, frame.f_globals,
+                       frame.f_locals)
+                if val:
+                    if b.ignore > 0:
+                        b.ignore = b.ignore -1
+                        # continue
+                    else:
+                        return (b,1)
+                # else:
+                #   continue
+            except:
+                # if eval fails, most conservative
+                # thing is to stop on breakpoint
+                # regardless of ignore count.
+                # Don't delete temporary,
+                # as another hint to user.
+                return (b,0)
+    return (None, None)
+
+# -------------------- testing --------------------
+
+class Tdb(Bdb):
+    def user_call(self, frame, args):
+        name = frame.f_code.co_name
+        if not name: name = '???'
+        print '+++ call', name, args
+    def user_line(self, frame):
+        import linecache
+        name = frame.f_code.co_name
+        if not name: name = '???'
+        fn = self.canonic(frame.f_code.co_filename)
+        line = linecache.getline(fn, frame.f_lineno, frame.f_globals)
+        print '+++', fn, frame.f_lineno, name, ':', line.strip()
+    def user_return(self, frame, retval):
+        print '+++ return', retval
+    def user_exception(self, frame, exc_stuff):
+        print '+++ exception', exc_stuff
+        self.set_continue()
+
+def foo(n):
+    print 'foo(', n, ')'
+    x = bar(n*10)
+    print 'bar returned', x
+
+def bar(a):
+    print 'bar(', a, ')'
+    return a/2
+
+def test():
+    t = Tdb()
+    t.run('import bdb; bdb.foo(10)')
+
+# end
diff --git a/src/main/resources/PythonLibs/binhex.py b/src/main/resources/PythonLibs/binhex.py
new file mode 100644
index 0000000000000000000000000000000000000000..8abc9f3e14c17a2f7421e8a7472993bb686047f4
--- /dev/null
+++ b/src/main/resources/PythonLibs/binhex.py
@@ -0,0 +1,508 @@
+"""Macintosh binhex compression/decompression.
+
+easy interface:
+binhex(inputfilename, outputfilename)
+hexbin(inputfilename, outputfilename)
+"""
+
+#
+# Jack Jansen, CWI, August 1995.
+#
+# The module is supposed to be as compatible as possible. Especially the
+# easy interface should work "as expected" on any platform.
+# XXXX Note: currently, textfiles appear in mac-form on all platforms.
+# We seem to lack a simple character-translate in python.
+# (we should probably use ISO-Latin-1 on all but the mac platform).
+# XXXX The simple routines are too simple: they expect to hold the complete
+# files in-core. Should be fixed.
+# XXXX It would be nice to handle AppleDouble format on unix
+# (for servers serving macs).
+# XXXX I don't understand what happens when you get 0x90 times the same byte on
+# input. The resulting code (xx 90 90) would appear to be interpreted as an
+# escaped *value* of 0x90. All coders I've seen appear to ignore this nicety...
+#
+import sys
+import os
+import struct
+import binascii
+
+__all__ = ["binhex","hexbin","Error"]
+
+class Error(Exception):
+    pass
+
+# States (what have we written)
+[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3)
+
+# Various constants
+REASONABLY_LARGE=32768  # Minimal amount we pass the rle-coder
+LINELEN=64
+RUNCHAR=chr(0x90)   # run-length introducer
+
+#
+# This code is no longer byte-order dependent
+
+#
+# Workarounds for non-mac machines.
+try:
+    from Carbon.File import FSSpec, FInfo
+    from MacOS import openrf
+
+    def getfileinfo(name):
+        finfo = FSSpec(name).FSpGetFInfo()
+        dir, file = os.path.split(name)
+        # XXX Get resource/data sizes
+        fp = open(name, 'rb')
+        fp.seek(0, 2)
+        dlen = fp.tell()
+        fp = openrf(name, '*rb')
+        fp.seek(0, 2)
+        rlen = fp.tell()
+        return file, finfo, dlen, rlen
+
+    def openrsrc(name, *mode):
+        if not mode:
+            mode = '*rb'
+        else:
+            mode = '*' + mode[0]
+        return openrf(name, mode)
+
+except ImportError:
+    #
+    # Glue code for non-macintosh usage
+    #
+
+    class FInfo:
+        def __init__(self):
+            self.Type = '????'
+            self.Creator = '????'
+            self.Flags = 0
+
+    def getfileinfo(name):
+        finfo = FInfo()
+        # Quick check for textfile
+        fp = open(name)
+        data = open(name).read(256)
+        for c in data:
+            if not c.isspace() and (c<' ' or ord(c) > 0x7f):
+                break
+        else:
+            finfo.Type = 'TEXT'
+        fp.seek(0, 2)
+        dsize = fp.tell()
+        fp.close()
+        dir, file = os.path.split(name)
+        file = file.replace(':', '-', 1)
+        return file, finfo, dsize, 0
+
+    class openrsrc:
+        def __init__(self, *args):
+            pass
+
+        def read(self, *args):
+            return ''
+
+        def write(self, *args):
+            pass
+
+        def close(self):
+            pass
+
+class _Hqxcoderengine:
+    """Write data to the coder in 3-byte chunks"""
+
+    def __init__(self, ofp):
+        self.ofp = ofp
+        self.data = ''
+        self.hqxdata = ''
+        self.linelen = LINELEN-1
+
+    def write(self, data):
+        self.data = self.data + data
+        datalen = len(self.data)
+        todo = (datalen//3)*3
+        data = self.data[:todo]
+        self.data = self.data[todo:]
+        if not data:
+            return
+        self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
+        self._flush(0)
+
+    def _flush(self, force):
+        first = 0
+        while first <= len(self.hqxdata)-self.linelen:
+            last = first + self.linelen
+            self.ofp.write(self.hqxdata[first:last]+'\n')
+            self.linelen = LINELEN
+            first = last
+        self.hqxdata = self.hqxdata[first:]
+        if force:
+            self.ofp.write(self.hqxdata + ':\n')
+
+    def close(self):
+        if self.data:
+            self.hqxdata = \
+                 self.hqxdata + binascii.b2a_hqx(self.data)
+        self._flush(1)
+        self.ofp.close()
+        del self.ofp
+
+class _Rlecoderengine:
+    """Write data to the RLE-coder in suitably large chunks"""
+
+    def __init__(self, ofp):
+        self.ofp = ofp
+        self.data = ''
+
+    def write(self, data):
+        self.data = self.data + data
+        if len(self.data) < REASONABLY_LARGE:
+            return
+        rledata = binascii.rlecode_hqx(self.data)
+        self.ofp.write(rledata)
+        self.data = ''
+
+    def close(self):
+        if self.data:
+            rledata = binascii.rlecode_hqx(self.data)
+            self.ofp.write(rledata)
+        self.ofp.close()
+        del self.ofp
+
+class BinHex:
+    def __init__(self, name_finfo_dlen_rlen, ofp):
+        name, finfo, dlen, rlen = name_finfo_dlen_rlen
+        if type(ofp) == type(''):
+            ofname = ofp
+            ofp = open(ofname, 'w')
+        ofp.write('(This file must be converted with BinHex 4.0)\n\n:')
+        hqxer = _Hqxcoderengine(ofp)
+        self.ofp = _Rlecoderengine(hqxer)
+        self.crc = 0
+        if finfo is None:
+            finfo = FInfo()
+        self.dlen = dlen
+        self.rlen = rlen
+        self._writeinfo(name, finfo)
+        self.state = _DID_HEADER
+
+    def _writeinfo(self, name, finfo):
+        nl = len(name)
+        if nl > 63:
+            raise Error, 'Filename too long'
+        d = chr(nl) + name + '\0'
+        d2 = finfo.Type + finfo.Creator
+
+        # Force all structs to be packed with big-endian
+        d3 = struct.pack('>h', finfo.Flags)
+        d4 = struct.pack('>ii', self.dlen, self.rlen)
+        info = d + d2 + d3 + d4
+        self._write(info)
+        self._writecrc()
+
+    def _write(self, data):
+        self.crc = binascii.crc_hqx(data, self.crc)
+        self.ofp.write(data)
+
+    def _writecrc(self):
+        # XXXX Should this be here??
+        # self.crc = binascii.crc_hqx('\0\0', self.crc)
+        if self.crc < 0:
+            fmt = '>h'
+        else:
+            fmt = '>H'
+        self.ofp.write(struct.pack(fmt, self.crc))
+        self.crc = 0
+
+    def write(self, data):
+        if self.state != _DID_HEADER:
+            raise Error, 'Writing data at the wrong time'
+        self.dlen = self.dlen - len(data)
+        self._write(data)
+
+    def close_data(self):
+        if self.dlen != 0:
+            raise Error, 'Incorrect data size, diff=%r' % (self.rlen,)
+        self._writecrc()
+        self.state = _DID_DATA
+
+    def write_rsrc(self, data):
+        if self.state < _DID_DATA:
+            self.close_data()
+        if self.state != _DID_DATA:
+            raise Error, 'Writing resource data at the wrong time'
+        self.rlen = self.rlen - len(data)
+        self._write(data)
+
+    def close(self):
+        if self.state < _DID_DATA:
+            self.close_data()
+        if self.state != _DID_DATA:
+            raise Error, 'Close at the wrong time'
+        if self.rlen != 0:
+            raise Error, \
+                  "Incorrect resource-datasize, diff=%r" % (self.rlen,)
+        self._writecrc()
+        self.ofp.close()
+        self.state = None
+        del self.ofp
+
+def binhex(inp, out):
+    """(infilename, outfilename) - Create binhex-encoded copy of a file"""
+    finfo = getfileinfo(inp)
+    ofp = BinHex(finfo, out)
+
+    ifp = open(inp, 'rb')
+    # XXXX Do textfile translation on non-mac systems
+    while 1:
+        d = ifp.read(128000)
+        if not d: break
+        ofp.write(d)
+    ofp.close_data()
+    ifp.close()
+
+    ifp = openrsrc(inp, 'rb')
+    while 1:
+        d = ifp.read(128000)
+        if not d: break
+        ofp.write_rsrc(d)
+    ofp.close()
+    ifp.close()
+
+class _Hqxdecoderengine:
+    """Read data via the decoder in 4-byte chunks"""
+
+    def __init__(self, ifp):
+        self.ifp = ifp
+        self.eof = 0
+
+    def read(self, totalwtd):
+        """Read at least wtd bytes (or until EOF)"""
+        decdata = ''
+        wtd = totalwtd
+        #
+        # The loop here is convoluted, since we don't really now how
+        # much to decode: there may be newlines in the incoming data.
+        while wtd > 0:
+            if self.eof: return decdata
+            wtd = ((wtd+2)//3)*4
+            data = self.ifp.read(wtd)
+            #
+            # Next problem: there may not be a complete number of
+            # bytes in what we pass to a2b. Solve by yet another
+            # loop.
+            #
+            while 1:
+                try:
+                    decdatacur, self.eof = \
+                            binascii.a2b_hqx(data)
+                    break
+                except binascii.Incomplete:
+                    pass
+                newdata = self.ifp.read(1)
+                if not newdata:
+                    raise Error, \
+                          'Premature EOF on binhex file'
+                data = data + newdata
+            decdata = decdata + decdatacur
+            wtd = totalwtd - len(decdata)
+            if not decdata and not self.eof:
+                raise Error, 'Premature EOF on binhex file'
+        return decdata
+
+    def close(self):
+        self.ifp.close()
+
+class _Rledecoderengine:
+    """Read data via the RLE-coder"""
+
+    def __init__(self, ifp):
+        self.ifp = ifp
+        self.pre_buffer = ''
+        self.post_buffer = ''
+        self.eof = 0
+
+    def read(self, wtd):
+        if wtd > len(self.post_buffer):
+            self._fill(wtd-len(self.post_buffer))
+        rv = self.post_buffer[:wtd]
+        self.post_buffer = self.post_buffer[wtd:]
+        return rv
+
+    def _fill(self, wtd):
+        self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+4)
+        if self.ifp.eof:
+            self.post_buffer = self.post_buffer + \
+                binascii.rledecode_hqx(self.pre_buffer)
+            self.pre_buffer = ''
+            return
+
+        #
+        # Obfuscated code ahead. We have to take care that we don't
+        # end up with an orphaned RUNCHAR later on. So, we keep a couple
+        # of bytes in the buffer, depending on what the end of
+        # the buffer looks like:
+        # '\220\0\220' - Keep 3 bytes: repeated \220 (escaped as \220\0)
+        # '?\220' - Keep 2 bytes: repeated something-else
+        # '\220\0' - Escaped \220: Keep 2 bytes.
+        # '?\220?' - Complete repeat sequence: decode all
+        # otherwise: keep 1 byte.
+        #
+        mark = len(self.pre_buffer)
+        if self.pre_buffer[-3:] == RUNCHAR + '\0' + RUNCHAR:
+            mark = mark - 3
+        elif self.pre_buffer[-1] == RUNCHAR:
+            mark = mark - 2
+        elif self.pre_buffer[-2:] == RUNCHAR + '\0':
+            mark = mark - 2
+        elif self.pre_buffer[-2] == RUNCHAR:
+            pass # Decode all
+        else:
+            mark = mark - 1
+
+        self.post_buffer = self.post_buffer + \
+            binascii.rledecode_hqx(self.pre_buffer[:mark])
+        self.pre_buffer = self.pre_buffer[mark:]
+
+    def close(self):
+        self.ifp.close()
+
+class HexBin:
+    def __init__(self, ifp):
+        if type(ifp) == type(''):
+            ifp = open(ifp)
+        #
+        # Find initial colon.
+        #
+        while 1:
+            ch = ifp.read(1)
+            if not ch:
+                raise Error, "No binhex data found"
+            # Cater for \r\n terminated lines (which show up as \n\r, hence
+            # all lines start with \r)
+            if ch == '\r':
+                continue
+            if ch == ':':
+                break
+            if ch != '\n':
+                dummy = ifp.readline()
+
+        hqxifp = _Hqxdecoderengine(ifp)
+        self.ifp = _Rledecoderengine(hqxifp)
+        self.crc = 0
+        self._readheader()
+
+    def _read(self, len):
+        data = self.ifp.read(len)
+        self.crc = binascii.crc_hqx(data, self.crc)
+        return data
+
+    def _checkcrc(self):
+        filecrc = struct.unpack('>h', self.ifp.read(2))[0] & 0xffff
+        #self.crc = binascii.crc_hqx('\0\0', self.crc)
+        # XXXX Is this needed??
+        self.crc = self.crc & 0xffff
+        if filecrc != self.crc:
+            raise Error, 'CRC error, computed %x, read %x' \
+                  %(self.crc, filecrc)
+        self.crc = 0
+
+    def _readheader(self):
+        len = self._read(1)
+        fname = self._read(ord(len))
+        rest = self._read(1+4+4+2+4+4)
+        self._checkcrc()
+
+        type = rest[1:5]
+        creator = rest[5:9]
+        flags = struct.unpack('>h', rest[9:11])[0]
+        self.dlen = struct.unpack('>l', rest[11:15])[0]
+        self.rlen = struct.unpack('>l', rest[15:19])[0]
+
+        self.FName = fname
+        self.FInfo = FInfo()
+        self.FInfo.Creator = creator
+        self.FInfo.Type = type
+        self.FInfo.Flags = flags
+
+        self.state = _DID_HEADER
+
+    def read(self, *n):
+        if self.state != _DID_HEADER:
+            raise Error, 'Read data at wrong time'
+        if n:
+            n = n[0]
+            n = min(n, self.dlen)
+        else:
+            n = self.dlen
+        rv = ''
+        while len(rv) < n:
+            rv = rv + self._read(n-len(rv))
+        self.dlen = self.dlen - n
+        return rv
+
+    def close_data(self):
+        if self.state != _DID_HEADER:
+            raise Error, 'close_data at wrong time'
+        if self.dlen:
+            dummy = self._read(self.dlen)
+        self._checkcrc()
+        self.state = _DID_DATA
+
+    def read_rsrc(self, *n):
+        if self.state == _DID_HEADER:
+            self.close_data()
+        if self.state != _DID_DATA:
+            raise Error, 'Read resource data at wrong time'
+        if n:
+            n = n[0]
+            n = min(n, self.rlen)
+        else:
+            n = self.rlen
+        self.rlen = self.rlen - n
+        return self._read(n)
+
+    def close(self):
+        if self.rlen:
+            dummy = self.read_rsrc(self.rlen)
+        self._checkcrc()
+        self.state = _DID_RSRC
+        self.ifp.close()
+
+def hexbin(inp, out):
+    """(infilename, outfilename) - Decode binhexed file"""
+    ifp = HexBin(inp)
+    finfo = ifp.FInfo
+    if not out:
+        out = ifp.FName
+
+    ofp = open(out, 'wb')
+    # XXXX Do translation on non-mac systems
+    while 1:
+        d = ifp.read(128000)
+        if not d: break
+        ofp.write(d)
+    ofp.close()
+    ifp.close_data()
+
+    d = ifp.read_rsrc(128000)
+    if d:
+        ofp = openrsrc(out, 'wb')
+        ofp.write(d)
+        while 1:
+            d = ifp.read_rsrc(128000)
+            if not d: break
+            ofp.write(d)
+        ofp.close()
+
+    ifp.close()
+
+def _test():
+    fname = sys.argv[1]
+    binhex(fname, fname+'.hqx')
+    hexbin(fname+'.hqx', fname+'.viahqx')
+    #hexbin(fname, fname+'.unpacked')
+    sys.exit(1)
+
+if __name__ == '__main__':
+    _test()
diff --git a/src/main/resources/PythonLibs/bisect.py b/src/main/resources/PythonLibs/bisect.py
new file mode 100644
index 0000000000000000000000000000000000000000..4a4d05255e5810d5f918cd2176f915046d25e672
--- /dev/null
+++ b/src/main/resources/PythonLibs/bisect.py
@@ -0,0 +1,92 @@
+"""Bisection algorithms."""
+
+def insort_right(a, x, lo=0, hi=None):
+    """Insert item x in list a, and keep it sorted assuming a is sorted.
+
+    If x is already in a, insert it to the right of the rightmost x.
+
+    Optional args lo (default 0) and hi (default len(a)) bound the
+    slice of a to be searched.
+    """
+
+    if lo < 0:
+        raise ValueError('lo must be non-negative')
+    if hi is None:
+        hi = len(a)
+    while lo < hi:
+        mid = (lo+hi)//2
+        if x < a[mid]: hi = mid
+        else: lo = mid+1
+    a.insert(lo, x)
+
+insort = insort_right   # backward compatibility
+
+def bisect_right(a, x, lo=0, hi=None):
+    """Return the index where to insert item x in list a, assuming a is sorted.
+
+    The return value i is such that all e in a[:i] have e <= x, and all e in
+    a[i:] have e > x.  So if x already appears in the list, a.insert(x) will
+    insert just after the rightmost x already there.
+
+    Optional args lo (default 0) and hi (default len(a)) bound the
+    slice of a to be searched.
+    """
+
+    if lo < 0:
+        raise ValueError('lo must be non-negative')
+    if hi is None:
+        hi = len(a)
+    while lo < hi:
+        mid = (lo+hi)//2
+        if x < a[mid]: hi = mid
+        else: lo = mid+1
+    return lo
+
+bisect = bisect_right   # backward compatibility
+
+def insort_left(a, x, lo=0, hi=None):
+    """Insert item x in list a, and keep it sorted assuming a is sorted.
+
+    If x is already in a, insert it to the left of the leftmost x.
+
+    Optional args lo (default 0) and hi (default len(a)) bound the
+    slice of a to be searched.
+    """
+
+    if lo < 0:
+        raise ValueError('lo must be non-negative')
+    if hi is None:
+        hi = len(a)
+    while lo < hi:
+        mid = (lo+hi)//2
+        if a[mid] < x: lo = mid+1
+        else: hi = mid
+    a.insert(lo, x)
+
+
+def bisect_left(a, x, lo=0, hi=None):
+    """Return the index where to insert item x in list a, assuming a is sorted.
+
+    The return value i is such that all e in a[:i] have e < x, and all e in
+    a[i:] have e >= x.  So if x already appears in the list, a.insert(x) will
+    insert just before the leftmost x already there.
+
+    Optional args lo (default 0) and hi (default len(a)) bound the
+    slice of a to be searched.
+    """
+
+    if lo < 0:
+        raise ValueError('lo must be non-negative')
+    if hi is None:
+        hi = len(a)
+    while lo < hi:
+        mid = (lo+hi)//2
+        if a[mid] < x: lo = mid+1
+        else: hi = mid
+    return lo
+
+# Overwrite above definitions with a fast C implementation
+try:
+    from _bisect import *
+except ImportError:
+    pass
diff --git a/src/main/resources/PythonLibs/calendar.py b/src/main/resources/PythonLibs/calendar.py
new file mode 100644
index 0000000000000000000000000000000000000000..441b2f576bc31097a03f10b4897b7f77c545ee32
--- /dev/null
+++ b/src/main/resources/PythonLibs/calendar.py
@@ -0,0 +1,713 @@
+"""Calendar printing functions
+
+Note when comparing these calendars to the ones printed by cal(1): By
+default, these calendars have Monday as the first day of the week, and
+Sunday as the last (the European convention). Use setfirstweekday() to
+set the first day of the week (0=Monday, 6=Sunday)."""
+
+import sys
+import datetime
+import locale as _locale
+
+__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
+           "firstweekday", "isleap", "leapdays", "weekday", "monthrange",
+           "monthcalendar", "prmonth", "month", "prcal", "calendar",
+           "timegm", "month_name", "month_abbr", "day_name", "day_abbr"]
+
+# Exception raised for bad input (with string parameter for details)
+error = ValueError
+
+# Exceptions raised for bad input
+class IllegalMonthError(ValueError):
+    def __init__(self, month):
+        self.month = month
+    def __str__(self):
+        return "bad month number %r; must be 1-12" % self.month
+
+
+class IllegalWeekdayError(ValueError):
+    def __init__(self, weekday):
+        self.weekday = weekday
+    def __str__(self):
+        return "bad weekday number %r; must be 0 (Monday) to 6 (Sunday)" % self.weekday
+
+
+# Constants for months referenced later
+January = 1
+February = 2
+
+# Number of days per month (except for February in leap years)
+mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+# This module used to have hard-coded lists of day and month names, as
+# English strings.  The classes following emulate a read-only version of
+# that, but supply localized names.  Note that the values are computed
+# fresh on each call, in case the user changes locale between calls.
+
+class _localized_month:
+
+    _months = [datetime.date(2001, i+1, 1).strftime for i in range(12)]
+    _months.insert(0, lambda x: "")
+
+    def __init__(self, format):
+        self.format = format
+
+    def __getitem__(self, i):
+        funcs = self._months[i]
+        if isinstance(i, slice):
+            return [f(self.format) for f in funcs]
+        else:
+            return funcs(self.format)
+
+    def __len__(self):
+        return 13
+
+
+class _localized_day:
+
+    # January 1, 2001, was a Monday.
+    _days = [datetime.date(2001, 1, i+1).strftime for i in range(7)]
+
+    def __init__(self, format):
+        self.format = format
+
+    def __getitem__(self, i):
+        funcs = self._days[i]
+        if isinstance(i, slice):
+            return [f(self.format) for f in funcs]
+        else:
+            return funcs(self.format)
+
+    def __len__(self):
+        return 7
+
+
+# Full and abbreviated names of weekdays
+day_name = _localized_day('%A')
+day_abbr = _localized_day('%a')
+
+# Full and abbreviated names of months (1-based arrays!!!)
+month_name = _localized_month('%B')
+month_abbr = _localized_month('%b')
+
+# Constants for weekdays
+(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)
+
+
+def isleap(year):
+    """Return True for leap years, False for non-leap years."""
+    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
+
+
+def leapdays(y1, y2):
+    """Return number of leap years in range [y1, y2).
+       Assume y1 <= y2."""
+    y1 -= 1
+    y2 -= 1
+    return (y2//4 - y1//4) - (y2//100 - y1//100) + (y2//400 - y1//400)
+
+
+def weekday(year, month, day):
+    """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12),
+       day (1-31)."""
+    return datetime.date(year, month, day).weekday()
+
+
+def monthrange(year, month):
+    """Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for
+       year, month."""
+    if not 1 <= month <= 12:
+        raise IllegalMonthError(month)
+    day1 = weekday(year, month, 1)
+    ndays = mdays[month] + (month == February and isleap(year))
+    return day1, ndays
+
+
+class Calendar(object):
+    """
+    Base calendar class. This class doesn't do any formatting. It simply
+    provides data to subclasses.
+    """
+
+    def __init__(self, firstweekday=0):
+        self.firstweekday = firstweekday # 0 = Monday, 6 = Sunday
+
+    def getfirstweekday(self):
+        return self._firstweekday % 7
+
+    def setfirstweekday(self, firstweekday):
+        self._firstweekday = firstweekday
+
+    firstweekday = property(getfirstweekday, setfirstweekday)
+
+    def iterweekdays(self):
+        """
+        Return a iterator for one week of weekday numbers starting with the
+        configured first one.
+        """
+        for i in range(self.firstweekday, self.firstweekday + 7):
+            yield i%7
+
+    def itermonthdates(self, year, month):
+        """
+        Return an iterator for one month. The iterator will yield datetime.date
+        values and will always iterate through complete weeks, so it will yield
+        dates outside the specified month.
+        """
+        date = datetime.date(year, month, 1)
+        # Go back to the beginning of the week
+        days = (date.weekday() - self.firstweekday) % 7
+        date -= datetime.timedelta(days=days)
+        oneday = datetime.timedelta(days=1)
+        while True:
+            yield date
+            try:
+                date += oneday
+            except OverflowError:
+                # Adding one day could fail after datetime.MAXYEAR
+                break
+            if date.month != month and date.weekday() == self.firstweekday:
+                break
+
+    def itermonthdays2(self, year, month):
+        """
+        Like itermonthdates(), but will yield (day number, weekday number)
+        tuples. For days outside the specified month the day number is 0.
+        """
+        for date in self.itermonthdates(year, month):
+            if date.month != month:
+                yield (0, date.weekday())
+            else:
+                yield (date.day, date.weekday())
+
+    def itermonthdays(self, year, month):
+        """
+        Like itermonthdates(), but will yield day numbers. For days outside
+        the specified month the day number is 0.
+        """
+        for date in self.itermonthdates(year, month):
+            if date.month != month:
+                yield 0
+            else:
+                yield date.day
+
+    def monthdatescalendar(self, year, month):
+        """
+        Return a matrix (list of lists) representing a month's calendar.
+        Each row represents a week; week entries are datetime.date values.
+        """
+        dates = list(self.itermonthdates(year, month))
+        return [ dates[i:i+7] for i in range(0, len(dates), 7) ]
+
+    def monthdays2calendar(self, year, month):
+        """
+        Return a matrix representing a month's calendar.
+        Each row represents a week; week entries are
+        (day number, weekday number) tuples. Day numbers outside this month
+        are zero.
+        """
+        days = list(self.itermonthdays2(year, month))
+        return [ days[i:i+7] for i in range(0, len(days), 7) ]
+
+    def monthdayscalendar(self, year, month):
+        """
+        Return a matrix representing a month's calendar.
+        Each row represents a week; days outside this month are zero.
+        """
+        days = list(self.itermonthdays(year, month))
+        return [ days[i:i+7] for i in range(0, len(days), 7) ]
+
+    def yeardatescalendar(self, year, width=3):
+        """
+        Return the data for the specified year ready for formatting. The return
+        value is a list of month rows. Each month row contains upto width months.
+        Each month contains between 4 and 6 weeks and each week contains 1-7
+        days. Days are datetime.date objects.
+        """
+        months = [
+            self.monthdatescalendar(year, i)
+            for i in range(January, January+12)
+        ]
+        return [months[i:i+width] for i in range(0, len(months), width) ]
+
+    def yeardays2calendar(self, year, width=3):
+        """
+        Return the data for the specified year ready for formatting (similar to
+        yeardatescalendar()). Entries in the week lists are
+        (day number, weekday number) tuples. Day numbers outside this month are
+        zero.
+        """
+        months = [
+            self.monthdays2calendar(year, i)
+            for i in range(January, January+12)
+        ]
+        return [months[i:i+width] for i in range(0, len(months), width) ]
+
+    def yeardayscalendar(self, year, width=3):
+        """
+        Return the data for the specified year ready for formatting (similar to
+        yeardatescalendar()). Entries in the week lists are day numbers.
+        Day numbers outside this month are zero.
+        """
+        months = [
+            self.monthdayscalendar(year, i)
+            for i in range(January, January+12)
+        ]
+        return [months[i:i+width] for i in range(0, len(months), width) ]
+
+
+class TextCalendar(Calendar):
+    """
+    Subclass of Calendar that outputs a calendar as a simple plain text
+    similar to the UNIX program cal.
+    """
+
+    def prweek(self, theweek, width):
+        """
+        Print a single week (no newline).
+        """
+        print self.formatweek(theweek, width),
+
+    def formatday(self, day, weekday, width):
+        """
+        Returns a formatted day.
+        """
+        if day == 0:
+            s = ''
+        else:
+            s = '%2i' % day             # right-align single-digit days
+        return s.center(width)
+
+    def formatweek(self, theweek, width):
+        """
+        Returns a single week in a string (no newline).
+        """
+        return ' '.join(self.formatday(d, wd, width) for (d, wd) in theweek)
+
+    def formatweekday(self, day, width):
+        """
+        Returns a formatted week day name.
+        """
+        if width >= 9:
+            names = day_name
+        else:
+            names = day_abbr
+        return names[day][:width].center(width)
+
+    def formatweekheader(self, width):
+        """
+        Return a header for a week.
+        """
+        return ' '.join(self.formatweekday(i, width) for i in self.iterweekdays())
+
+    def formatmonthname(self, theyear, themonth, width, withyear=True):
+        """
+        Return a formatted month name.
+        """
+        s = month_name[themonth]
+        if withyear:
+            s = "%s %r" % (s, theyear)
+        return s.center(width)
+
+    def prmonth(self, theyear, themonth, w=0, l=0):
+        """
+        Print a month's calendar.
+        """
+        print self.formatmonth(theyear, themonth, w, l),
+
+    def formatmonth(self, theyear, themonth, w=0, l=0):
+        """
+        Return a month's calendar string (multi-line).
+        """
+        w = max(2, w)
+        l = max(1, l)
+        s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1)
+        s = s.rstrip()
+        s += '\n' * l
+        s += self.formatweekheader(w).rstrip()
+        s += '\n' * l
+        for week in self.monthdays2calendar(theyear, themonth):
+            s += self.formatweek(week, w).rstrip()
+            s += '\n' * l
+        return s
+
+    def formatyear(self, theyear, w=2, l=1, c=6, m=3):
+        """
+        Returns a year's calendar as a multi-line string.
+        """
+        w = max(2, w)
+        l = max(1, l)
+        c = max(2, c)
+        colwidth = (w + 1) * 7 - 1
+        v = []
+        a = v.append
+        a(repr(theyear).center(colwidth*m+c*(m-1)).rstrip())
+        a('\n'*l)
+        header = self.formatweekheader(w)
+        for (i, row) in enumerate(self.yeardays2calendar(theyear, m)):
+            # months in this row
+            months = range(m*i+1, min(m*(i+1)+1, 13))
+            a('\n'*l)
+            names = (self.formatmonthname(theyear, k, colwidth, False)
+                     for k in months)
+            a(formatstring(names, colwidth, c).rstrip())
+            a('\n'*l)
+            headers = (header for k in months)
+            a(formatstring(headers, colwidth, c).rstrip())
+            a('\n'*l)
+            # max number of weeks for this row
+            height = max(len(cal) for cal in row)
+            for j in range(height):
+                weeks = []
+                for cal in row:
+                    if j >= len(cal):
+                        weeks.append('')
+                    else:
+                        weeks.append(self.formatweek(cal[j], w))
+                a(formatstring(weeks, colwidth, c).rstrip())
+                a('\n' * l)
+        return ''.join(v)
+
+    def pryear(self, theyear, w=0, l=0, c=6, m=3):
+        """Print a year's calendar."""
+        print self.formatyear(theyear, w, l, c, m)
+
+
+class HTMLCalendar(Calendar):
+    """
+    This calendar returns complete HTML pages.
+    """
+
+    # CSS classes for the day <td>s
+    cssclasses = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
+
+    def formatday(self, day, weekday):
+        """
+        Return a day as a table cell.
+        """
+        if day == 0:
+            return '<td class="noday">&nbsp;</td>' # day outside month
+        else:
+            return '<td class="%s">%d</td>' % (self.cssclasses[weekday], day)
+
+    def formatweek(self, theweek):
+        """
+        Return a complete week as a table row.
+        """
+        s = ''.join(self.formatday(d, wd) for (d, wd) in theweek)
+        return '<tr>%s</tr>' % s
+
+    def formatweekday(self, day):
+        """
+        Return a weekday name as a table header.
+        """
+        return '<th class="%s">%s</th>' % (self.cssclasses[day], day_abbr[day])
+
+    def formatweekheader(self):
+        """
+        Return a header for a week as a table row.
+        """
+        s = ''.join(self.formatweekday(i) for i in self.iterweekdays())
+        return '<tr>%s</tr>' % s
+
+    def formatmonthname(self, theyear, themonth, withyear=True):
+        """
+        Return a month name as a table row.
+        """
+        if withyear:
+            s = '%s %s' % (month_name[themonth], theyear)
+        else:
+            s = '%s' % month_name[themonth]
+        return '<tr><th colspan="7" class="month">%s</th></tr>' % s
+
+    def formatmonth(self, theyear, themonth, withyear=True):
+        """
+        Return a formatted month as a table.
+        """
+        v = []
+        a = v.append
+        a('<table border="0" cellpadding="0" cellspacing="0" class="month">')
+        a('\n')
+        a(self.formatmonthname(theyear, themonth, withyear=withyear))
+        a('\n')
+        a(self.formatweekheader())
+        a('\n')
+        for week in self.monthdays2calendar(theyear, themonth):
+            a(self.formatweek(week))
+            a('\n')
+        a('</table>')
+        a('\n')
+        return ''.join(v)
+
+    def formatyear(self, theyear, width=3):
+        """
+        Return a formatted year as a table of tables.
+        """
+        v = []
+        a = v.append
+        width = max(width, 1)
+        a('<table border="0" cellpadding="0" cellspacing="0" class="year">')
+        a('\n')
+        a('<tr><th colspan="%d" class="year">%s</th></tr>' % (width, theyear))
+        for i in range(January, January+12, width):
+            # months in this row
+            months = range(i, min(i+width, 13))
+            a('<tr>')
+            for m in months:
+                a('<td>')
+                a(self.formatmonth(theyear, m, withyear=False))
+                a('</td>')
+            a('</tr>')
+        a('</table>')
+        return ''.join(v)
+
+    def formatyearpage(self, theyear, width=3, css='calendar.css', encoding=None):
+        """
+        Return a formatted year as a complete HTML page.
+        """
+        if encoding is None:
+            encoding = sys.getdefaultencoding()
+        v = []
+        a = v.append
+        a('<?xml version="1.0" encoding="%s"?>\n' % encoding)
+        a('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n')
+        a('<html>\n')
+        a('<head>\n')
+        a('<meta http-equiv="Content-Type" content="text/html; charset=%s" />\n' % encoding)
+        if css is not None:
+            a('<link rel="stylesheet" type="text/css" href="%s" />\n' % css)
+        a('<title>Calendar for %d</title>\n' % theyear)
+        a('</head>\n')
+        a('<body>\n')
+        a(self.formatyear(theyear, width))
+        a('</body>\n')
+        a('</html>\n')
+        return ''.join(v).encode(encoding, "xmlcharrefreplace")
+
+
+class TimeEncoding:
+    def __init__(self, locale):
+        self.locale = locale
+
+    def __enter__(self):
+        self.oldlocale = _locale.getlocale(_locale.LC_TIME)
+        _locale.setlocale(_locale.LC_TIME, self.locale)
+        return _locale.getlocale(_locale.LC_TIME)[1]
+
+    def __exit__(self, *args):
+        _locale.setlocale(_locale.LC_TIME, self.oldlocale)
+
+
+class LocaleTextCalendar(TextCalendar):
+    """
+    This class can be passed a locale name in the constructor and will return
+    month and weekday names in the specified locale. If this locale includes
+    an encoding all strings containing month and weekday names will be returned
+    as unicode.
+    """
+
+    def __init__(self, firstweekday=0, locale=None):
+        TextCalendar.__init__(self, firstweekday)
+        if locale is None:
+            locale = _locale.getdefaultlocale()
+        self.locale = locale
+
+    def formatweekday(self, day, width):
+        with TimeEncoding(self.locale) as encoding:
+            if width >= 9:
+                names = day_name
+            else:
+                names = day_abbr
+            name = names[day]
+            if encoding is not None:
+                name = name.decode(encoding)
+            return name[:width].center(width)
+
+    def formatmonthname(self, theyear, themonth, width, withyear=True):
+        with TimeEncoding(self.locale) as encoding:
+            s = month_name[themonth]
+            if encoding is not None:
+                s = s.decode(encoding)
+            if withyear:
+                s = "%s %r" % (s, theyear)
+            return s.center(width)
+
+
+class LocaleHTMLCalendar(HTMLCalendar):
+    """
+    This class can be passed a locale name in the constructor and will return
+    month and weekday names in the specified locale. If this locale includes
+    an encoding all strings containing month and weekday names will be returned
+    as unicode.
+    """
+    def __init__(self, firstweekday=0, locale=None):
+        HTMLCalendar.__init__(self, firstweekday)
+        if locale is None:
+            locale = _locale.getdefaultlocale()
+        self.locale = locale
+
+    def formatweekday(self, day):
+        with TimeEncoding(self.locale) as encoding:
+            s = day_abbr[day]
+            if encoding is not None:
+                s = s.decode(encoding)
+            return '<th class="%s">%s</th>' % (self.cssclasses[day], s)
+
+    def formatmonthname(self, theyear, themonth, withyear=True):
+        with TimeEncoding(self.locale) as encoding:
+            s = month_name[themonth]
+            if encoding is not None:
+                s = s.decode(encoding)
+            if withyear:
+                s = '%s %s' % (s, theyear)
+            return '<tr><th colspan="7" class="month">%s</th></tr>' % s
+
+
+# Support for old module level interface
+c = TextCalendar()
+
+firstweekday = c.getfirstweekday
+
+def setfirstweekday(firstweekday):
+    try:
+        firstweekday.__index__
+    except AttributeError:
+        raise IllegalWeekdayError(firstweekday)
+    if not MONDAY <= firstweekday <= SUNDAY:
+        raise IllegalWeekdayError(firstweekday)
+    c.firstweekday = firstweekday
+
+monthcalendar = c.monthdayscalendar
+prweek = c.prweek
+week = c.formatweek
+weekheader = c.formatweekheader
+prmonth = c.prmonth
+month = c.formatmonth
+calendar = c.formatyear
+prcal = c.pryear
+
+
+# Spacing of month columns for multi-column year calendar
+_colwidth = 7*3 - 1         # Amount printed by prweek()
+_spacing = 6                # Number of spaces between columns
+
+
+def format(cols, colwidth=_colwidth, spacing=_spacing):
+    """Prints multi-column formatting for year calendars"""
+    print formatstring(cols, colwidth, spacing)
+
+
+def formatstring(cols, colwidth=_colwidth, spacing=_spacing):
+    """Returns a string formatted from n strings, centered within n columns."""
+    spacing *= ' '
+    return spacing.join(c.center(colwidth) for c in cols)
+
+
+EPOCH = 1970
+_EPOCH_ORD = datetime.date(EPOCH, 1, 1).toordinal()
+
+
+def timegm(tuple):
+    """Unrelated but handy function to calculate Unix timestamp from GMT."""
+    year, month, day, hour, minute, second = tuple[:6]
+    days = datetime.date(year, month, 1).toordinal() - _EPOCH_ORD + day - 1
+    hours = days*24 + hour
+    minutes = hours*60 + minute
+    seconds = minutes*60 + second
+    return seconds
+
+
+def main(args):
+    import optparse
+    parser = optparse.OptionParser(usage="usage: %prog [options] [year [month]]")
+    parser.add_option(
+        "-w", "--width",
+        dest="width", type="int", default=2,
+        help="width of date column (default 2, text only)"
+    )
+    parser.add_option(
+        "-l", "--lines",
+        dest="lines", type="int", default=1,
+        help="number of lines for each week (default 1, text only)"
+    )
+    parser.add_option(
+        "-s", "--spacing",
+        dest="spacing", type="int", default=6,
+        help="spacing between months (default 6, text only)"
+    )
+    parser.add_option(
+        "-m", "--months",
+        dest="months", type="int", default=3,
+        help="months per row (default 3, text only)"
+    )
+    parser.add_option(
+        "-c", "--css",
+        dest="css", default="calendar.css",
+        help="CSS to use for page (html only)"
+    )
+    parser.add_option(
+        "-L", "--locale",
+        dest="locale", default=None,
+        help="locale to be used from month and weekday names"
+    )
+    parser.add_option(
+        "-e", "--encoding",
+        dest="encoding", default=None,
+        help="Encoding to use for output"
+    )
+    parser.add_option(
+        "-t", "--type",
+        dest="type", default="text",
+        choices=("text", "html"),
+        help="output type (text or html)"
+    )
+
+    (options, args) = parser.parse_args(args)
+
+    if options.locale and not options.encoding:
+        parser.error("if --locale is specified --encoding is required")
+        sys.exit(1)
+
+    locale = options.locale, options.encoding
+
+    if options.type == "html":
+        if options.locale:
+            cal = LocaleHTMLCalendar(locale=locale)
+        else:
+            cal = HTMLCalendar()
+        encoding = options.encoding
+        if encoding is None:
+            encoding = sys.getdefaultencoding()
+        optdict = dict(encoding=encoding, css=options.css)
+        if len(args) == 1:
+            print cal.formatyearpage(datetime.date.today().year, **optdict)
+        elif len(args) == 2:
+            print cal.formatyearpage(int(args[1]), **optdict)
+        else:
+            parser.error("incorrect number of arguments")
+            sys.exit(1)
+    else:
+        if options.locale:
+            cal = LocaleTextCalendar(locale=locale)
+        else:
+            cal = TextCalendar()
+        optdict = dict(w=options.width, l=options.lines)
+        if len(args) != 3:
+            optdict["c"] = options.spacing
+            optdict["m"] = options.months
+        if len(args) == 1:
+            result = cal.formatyear(datetime.date.today().year, **optdict)
+        elif len(args) == 2:
+            result = cal.formatyear(int(args[1]), **optdict)
+        elif len(args) == 3:
+            result = cal.formatmonth(int(args[1]), int(args[2]), **optdict)
+        else:
+            parser.error("incorrect number of arguments")
+            sys.exit(1)
+        if options.encoding:
+            result = result.encode(options.encoding)
+        print result
+
+
+if __name__ == "__main__":
+    main(sys.argv)
diff --git a/src/main/resources/PythonLibs/cgi.py b/src/main/resources/PythonLibs/cgi.py
new file mode 100644
index 0000000000000000000000000000000000000000..67079db0d81a7cdb9d130f1a0c316b6468d453a0
--- /dev/null
+++ b/src/main/resources/PythonLibs/cgi.py
@@ -0,0 +1,1050 @@
+#! /usr/local/bin/python
+
+# NOTE: the above "/usr/local/bin/python" is NOT a mistake.  It is
+# intentionally NOT "/usr/bin/env python".  On many systems
+# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI
+# scripts, and /usr/local/bin is the default directory where Python is
+# installed, so /usr/bin/env would be unable to find python.  Granted,
+# binary installations by Linux vendors often install Python in
+# /usr/bin.  So let those vendors patch cgi.py to match their choice
+# of installation.
+
+"""Support module for CGI (Common Gateway Interface) scripts.
+
+This module defines a number of utilities for use by CGI scripts
+written in Python.
+"""
+
+# XXX Perhaps there should be a slimmed version that doesn't contain
+# all those backwards compatible and debugging classes and functions?
+
+# History
+# -------
+#
+# Michael McLay started this module.  Steve Majewski changed the
+# interface to SvFormContentDict and FormContentDict.  The multipart
+# parsing was inspired by code submitted by Andreas Paepcke.  Guido van
+# Rossum rewrote, reformatted and documented the module and is currently
+# responsible for its maintenance.
+#
+
+__version__ = "2.6"
+
+
+# Imports
+# =======
+
+from operator import attrgetter
+import sys
+import os
+import UserDict
+import urlparse
+
+from warnings import filterwarnings, catch_warnings, warn
+with catch_warnings():
+    if sys.py3kwarning:
+        filterwarnings("ignore", ".*mimetools has been removed",
+                       DeprecationWarning)
+        filterwarnings("ignore", ".*rfc822 has been removed",
+                       DeprecationWarning)
+    import mimetools
+    import rfc822
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+__all__ = ["MiniFieldStorage", "FieldStorage", "FormContentDict",
+           "SvFormContentDict", "InterpFormContentDict", "FormContent",
+           "parse", "parse_qs", "parse_qsl", "parse_multipart",
+           "parse_header", "print_exception", "print_environ",
+           "print_form", "print_directory", "print_arguments",
+           "print_environ_usage", "escape"]
+
+# Logging support
+# ===============
+
+logfile = ""            # Filename to log to, if not empty
+logfp = None            # File object to log to, if not None
+
+def initlog(*allargs):
+    """Write a log message, if there is a log file.
+
+    Even though this function is called initlog(), you should always
+    use log(); log is a variable that is set either to initlog
+    (initially), to dolog (once the log file has been opened), or to
+    nolog (when logging is disabled).
+
+    The first argument is a format string; the remaining arguments (if
+    any) are arguments to the % operator, so e.g.
+        log("%s: %s", "a", "b")
+    will write "a: b" to the log file, followed by a newline.
+
+    If the global logfp is not None, it should be a file object to
+    which log data is written.
+
+    If the global logfp is None, the global logfile may be a string
+    giving a filename to open, in append mode.  This file should be
+    world writable!!!  If the file can't be opened, logging is
+    silently disabled (since there is no safe place where we could
+    send an error message).
+
+    """
+    global logfp, log
+    if logfile and not logfp:
+        try:
+            logfp = open(logfile, "a")
+        except IOError:
+            pass
+    if not logfp:
+        log = nolog
+    else:
+        log = dolog
+    log(*allargs)
+
+def dolog(fmt, *args):
+    """Write a log message to the log file.  See initlog() for docs."""
+    logfp.write(fmt%args + "\n")
+
+def nolog(*allargs):
+    """Dummy function, assigned to log when logging is disabled."""
+    pass
+
+log = initlog           # The current logging function
+
+
+# Parsing functions
+# =================
+
+# Maximum input we will accept when REQUEST_METHOD is POST
+# 0 ==> unlimited input
+maxlen = 0
+
+def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
+    """Parse a query in the environment or from a file (default stdin)
+
+        Arguments, all optional:
+
+        fp              : file pointer; default: sys.stdin
+
+        environ         : environment dictionary; default: os.environ
+
+        keep_blank_values: flag indicating whether blank values in
+            percent-encoded forms should be treated as blank strings.
+            A true value indicates that blanks should be retained as
+            blank strings.  The default false value indicates that
+            blank values are to be ignored and treated as if they were
+            not included.
+
+        strict_parsing: flag indicating what to do with parsing errors.
+            If false (the default), errors are silently ignored.
+            If true, errors raise a ValueError exception.
+    """
+    if fp is None:
+        fp = sys.stdin
+    if not 'REQUEST_METHOD' in environ:
+        environ['REQUEST_METHOD'] = 'GET'       # For testing stand-alone
+    if environ['REQUEST_METHOD'] == 'POST':
+        ctype, pdict = parse_header(environ['CONTENT_TYPE'])
+        if ctype == 'multipart/form-data':
+            return parse_multipart(fp, pdict)
+        elif ctype == 'application/x-www-form-urlencoded':
+            clength = int(environ['CONTENT_LENGTH'])
+            if maxlen and clength > maxlen:
+                raise ValueError, 'Maximum content length exceeded'
+            qs = fp.read(clength)
+        else:
+            qs = ''                     # Unknown content-type
+        if 'QUERY_STRING' in environ:
+            if qs: qs = qs + '&'
+            qs = qs + environ['QUERY_STRING']
+        elif sys.argv[1:]:
+            if qs: qs = qs + '&'
+            qs = qs + sys.argv[1]
+        environ['QUERY_STRING'] = qs    # XXX Shouldn't, really
+    elif 'QUERY_STRING' in environ:
+        qs = environ['QUERY_STRING']
+    else:
+        if sys.argv[1:]:
+            qs = sys.argv[1]
+        else:
+            qs = ""
+        environ['QUERY_STRING'] = qs    # XXX Shouldn't, really
+    return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
+
+
+# parse query string function called from urlparse,
+# this is done in order to maintain backward compatiblity.
+
+def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
+    """Parse a query given as a string argument."""
+    warn("cgi.parse_qs is deprecated, use urlparse.parse_qs instead",
+         PendingDeprecationWarning, 2)
+    return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
+
+
+def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
+    """Parse a query given as a string argument."""
+    warn("cgi.parse_qsl is deprecated, use urlparse.parse_qsl instead",
+         PendingDeprecationWarning, 2)
+    return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing)
+
+def parse_multipart(fp, pdict):
+    """Parse multipart input.
+
+    Arguments:
+    fp   : input file
+    pdict: dictionary containing other parameters of content-type header
+
+    Returns a dictionary just like parse_qs(): keys are the field names, each
+    value is a list of values for that field.  This is easy to use but not
+    much good if you are expecting megabytes to be uploaded -- in that case,
+    use the FieldStorage class instead which is much more flexible.  Note
+    that content-type is the raw, unparsed contents of the content-type
+    header.
+
+    XXX This does not parse nested multipart parts -- use FieldStorage for
+    that.
+
+    XXX This should really be subsumed by FieldStorage altogether -- no
+    point in having two implementations of the same parsing algorithm.
+    Also, FieldStorage protects itself better against certain DoS attacks
+    by limiting the size of the data read in one chunk.  The API here
+    does not support that kind of protection.  This also affects parse()
+    since it can call parse_multipart().
+
+    """
+    boundary = ""
+    if 'boundary' in pdict:
+        boundary = pdict['boundary']
+    if not valid_boundary(boundary):
+        raise ValueError,  ('Invalid boundary in multipart form: %r'
+                            % (boundary,))
+
+    nextpart = "--" + boundary
+    lastpart = "--" + boundary + "--"
+    partdict = {}
+    terminator = ""
+
+    while terminator != lastpart:
+        bytes = -1
+        data = None
+        if terminator:
+            # At start of next part.  Read headers first.
+            headers = mimetools.Message(fp)
+            clength = headers.getheader('content-length')
+            if clength:
+                try:
+                    bytes = int(clength)
+                except ValueError:
+                    pass
+            if bytes > 0:
+                if maxlen and bytes > maxlen:
+                    raise ValueError, 'Maximum content length exceeded'
+                data = fp.read(bytes)
+            else:
+                data = ""
+        # Read lines until end of part.
+        lines = []
+        while 1:
+            line = fp.readline()
+            if not line:
+                terminator = lastpart # End outer loop
+                break
+            if line[:2] == "--":
+                terminator = line.strip()
+                if terminator in (nextpart, lastpart):
+                    break
+            lines.append(line)
+        # Done with part.
+        if data is None:
+            continue
+        if bytes < 0:
+            if lines:
+                # Strip final line terminator
+                line = lines[-1]
+                if line[-2:] == "\r\n":
+                    line = line[:-2]
+                elif line[-1:] == "\n":
+                    line = line[:-1]
+                lines[-1] = line
+                data = "".join(lines)
+        line = headers['content-disposition']
+        if not line:
+            continue
+        key, params = parse_header(line)
+        if key != 'form-data':
+            continue
+        if 'name' in params:
+            name = params['name']
+        else:
+            continue
+        if name in partdict:
+            partdict[name].append(data)
+        else:
+            partdict[name] = [data]
+
+    return partdict
+
+
+def _parseparam(s):
+    while s[:1] == ';':
+        s = s[1:]
+        end = s.find(';')
+        while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
+            end = s.find(';', end + 1)
+        if end < 0:
+            end = len(s)
+        f = s[:end]
+        yield f.strip()
+        s = s[end:]
+
+def parse_header(line):
+    """Parse a Content-type like header.
+
+    Return the main content-type and a dictionary of options.
+
+    """
+    parts = _parseparam(';' + line)
+    key = parts.next()
+    pdict = {}
+    for p in parts:
+        i = p.find('=')
+        if i >= 0:
+            name = p[:i].strip().lower()
+            value = p[i+1:].strip()
+            if len(value) >= 2 and value[0] == value[-1] == '"':
+                value = value[1:-1]
+                value = value.replace('\\\\', '\\').replace('\\"', '"')
+            pdict[name] = value
+    return key, pdict
+
+
+# Classes for field storage
+# =========================
+
+class MiniFieldStorage:
+
+    """Like FieldStorage, for use when no file uploads are possible."""
+
+    # Dummy attributes
+    filename = None
+    list = None
+    type = None
+    file = None
+    type_options = {}
+    disposition = None
+    disposition_options = {}
+    headers = {}
+
+    def __init__(self, name, value):
+        """Constructor from field name and value."""
+        self.name = name
+        self.value = value
+        # self.file = StringIO(value)
+
+    def __repr__(self):
+        """Return printable representation."""
+        return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
+
+
+class FieldStorage:
+
+    """Store a sequence of fields, reading multipart/form-data.
+
+    This class provides naming, typing, files stored on disk, and
+    more.  At the top level, it is accessible like a dictionary, whose
+    keys are the field names.  (Note: None can occur as a field name.)
+    The items are either a Python list (if there's multiple values) or
+    another FieldStorage or MiniFieldStorage object.  If it's a single
+    object, it has the following attributes:
+
+    name: the field name, if specified; otherwise None
+
+    filename: the filename, if specified; otherwise None; this is the
+        client side filename, *not* the file name on which it is
+        stored (that's a temporary file you don't deal with)
+
+    value: the value as a *string*; for file uploads, this
+        transparently reads the file every time you request the value
+
+    file: the file(-like) object from which you can read the data;
+        None if the data is stored a simple string
+
+    type: the content-type, or None if not specified
+
+    type_options: dictionary of options specified on the content-type
+        line
+
+    disposition: content-disposition, or None if not specified
+
+    disposition_options: dictionary of corresponding options
+
+    headers: a dictionary(-like) object (sometimes rfc822.Message or a
+        subclass thereof) containing *all* headers
+
+    The class is subclassable, mostly for the purpose of overriding
+    the make_file() method, which is called internally to come up with
+    a file open for reading and writing.  This makes it possible to
+    override the default choice of storing all files in a temporary
+    directory and unlinking them as soon as they have been opened.
+
+    """
+
+    def __init__(self, fp=None, headers=None, outerboundary="",
+                 environ=os.environ, keep_blank_values=0, strict_parsing=0):
+        """Constructor.  Read multipart/* until last part.
+
+        Arguments, all optional:
+
+        fp              : file pointer; default: sys.stdin
+            (not used when the request method is GET)
+
+        headers         : header dictionary-like object; default:
+            taken from environ as per CGI spec
+
+        outerboundary   : terminating multipart boundary
+            (for internal use only)
+
+        environ         : environment dictionary; default: os.environ
+
+        keep_blank_values: flag indicating whether blank values in
+            percent-encoded forms should be treated as blank strings.
+            A true value indicates that blanks should be retained as
+            blank strings.  The default false value indicates that
+            blank values are to be ignored and treated as if they were
+            not included.
+
+        strict_parsing: flag indicating what to do with parsing errors.
+            If false (the default), errors are silently ignored.
+            If true, errors raise a ValueError exception.
+
+        """
+        method = 'GET'
+        self.keep_blank_values = keep_blank_values
+        self.strict_parsing = strict_parsing
+        if 'REQUEST_METHOD' in environ:
+            method = environ['REQUEST_METHOD'].upper()
+        self.qs_on_post = None
+        if method == 'GET' or method == 'HEAD':
+            if 'QUERY_STRING' in environ:
+                qs = environ['QUERY_STRING']
+            elif sys.argv[1:]:
+                qs = sys.argv[1]
+            else:
+                qs = ""
+            fp = StringIO(qs)
+            if headers is None:
+                headers = {'content-type':
+                           "application/x-www-form-urlencoded"}
+        if headers is None:
+            headers = {}
+            if method == 'POST':
+                # Set default content-type for POST to what's traditional
+                headers['content-type'] = "application/x-www-form-urlencoded"
+            if 'CONTENT_TYPE' in environ:
+                headers['content-type'] = environ['CONTENT_TYPE']
+            if 'QUERY_STRING' in environ:
+                self.qs_on_post = environ['QUERY_STRING']
+            if 'CONTENT_LENGTH' in environ:
+                headers['content-length'] = environ['CONTENT_LENGTH']
+        self.fp = fp or sys.stdin
+        self.headers = headers
+        self.outerboundary = outerboundary
+
+        # Process content-disposition header
+        cdisp, pdict = "", {}
+        if 'content-disposition' in self.headers:
+            cdisp, pdict = parse_header(self.headers['content-disposition'])
+        self.disposition = cdisp
+        self.disposition_options = pdict
+        self.name = None
+        if 'name' in pdict:
+            self.name = pdict['name']
+        self.filename = None
+        if 'filename' in pdict:
+            self.filename = pdict['filename']
+
+        # Process content-type header
+        #
+        # Honor any existing content-type header.  But if there is no
+        # content-type header, use some sensible defaults.  Assume
+        # outerboundary is "" at the outer level, but something non-false
+        # inside a multi-part.  The default for an inner part is text/plain,
+        # but for an outer part it should be urlencoded.  This should catch
+        # bogus clients which erroneously forget to include a content-type
+        # header.
+        #
+        # See below for what we do if there does exist a content-type header,
+        # but it happens to be something we don't understand.
+        if 'content-type' in self.headers:
+            ctype, pdict = parse_header(self.headers['content-type'])
+        elif self.outerboundary or method != 'POST':
+            ctype, pdict = "text/plain", {}
+        else:
+            ctype, pdict = 'application/x-www-form-urlencoded', {}
+        self.type = ctype
+        self.type_options = pdict
+        self.innerboundary = ""
+        if 'boundary' in pdict:
+            self.innerboundary = pdict['boundary']
+        clen = -1
+        if 'content-length' in self.headers:
+            try:
+                clen = int(self.headers['content-length'])
+            except ValueError:
+                pass
+            if maxlen and clen > maxlen:
+                raise ValueError, 'Maximum content length exceeded'
+        self.length = clen
+
+        self.list = self.file = None
+        self.done = 0
+        if ctype == 'application/x-www-form-urlencoded':
+            self.read_urlencoded()
+        elif ctype[:10] == 'multipart/':
+            self.read_multi(environ, keep_blank_values, strict_parsing)
+        else:
+            self.read_single()
+
+    def __repr__(self):
+        """Return a printable representation."""
+        return "FieldStorage(%r, %r, %r)" % (
+                self.name, self.filename, self.value)
+
+    def __iter__(self):
+        return iter(self.keys())
+
+    def __getattr__(self, name):
+        if name != 'value':
+            raise AttributeError, name
+        if self.file:
+            self.file.seek(0)
+            value = self.file.read()
+            self.file.seek(0)
+        elif self.list is not None:
+            value = self.list
+        else:
+            value = None
+        return value
+
+    def __getitem__(self, key):
+        """Dictionary style indexing."""
+        if self.list is None:
+            raise TypeError, "not indexable"
+        found = []
+        for item in self.list:
+            if item.name == key: found.append(item)
+        if not found:
+            raise KeyError, key
+        if len(found) == 1:
+            return found[0]
+        else:
+            return found
+
+    def getvalue(self, key, default=None):
+        """Dictionary style get() method, including 'value' lookup."""
+        if key in self:
+            value = self[key]
+            if type(value) is type([]):
+                return map(attrgetter('value'), value)
+            else:
+                return value.value
+        else:
+            return default
+
+    def getfirst(self, key, default=None):
+        """ Return the first value received."""
+        if key in self:
+            value = self[key]
+            if type(value) is type([]):
+                return value[0].value
+            else:
+                return value.value
+        else:
+            return default
+
+    def getlist(self, key):
+        """ Return list of received values."""
+        if key in self:
+            value = self[key]
+            if type(value) is type([]):
+                return map(attrgetter('value'), value)
+            else:
+                return [value.value]
+        else:
+            return []
+
+    def keys(self):
+        """Dictionary style keys() method."""
+        if self.list is None:
+            raise TypeError, "not indexable"
+        return list(set(item.name for item in self.list))
+
+    def has_key(self, key):
+        """Dictionary style has_key() method."""
+        if self.list is None:
+            raise TypeError, "not indexable"
+        return any(item.name == key for item in self.list)
+
+    def __contains__(self, key):
+        """Dictionary style __contains__ method."""
+        if self.list is None:
+            raise TypeError, "not indexable"
+        return any(item.name == key for item in self.list)
+
+    def __len__(self):
+        """Dictionary style len(x) support."""
+        return len(self.keys())
+
+    def __nonzero__(self):
+        return bool(self.list)
+
+    def read_urlencoded(self):
+        """Internal: read data in query string format."""
+        qs = self.fp.read(self.length)
+        if self.qs_on_post:
+            qs += '&' + self.qs_on_post
+        self.list = list = []
+        for key, value in urlparse.parse_qsl(qs, self.keep_blank_values,
+                                            self.strict_parsing):
+            list.append(MiniFieldStorage(key, value))
+        self.skip_lines()
+
+    FieldStorageClass = None
+
+    def read_multi(self, environ, keep_blank_values, strict_parsing):
+        """Internal: read a part that is itself multipart."""
+        ib = self.innerboundary
+        if not valid_boundary(ib):
+            raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
+        self.list = []
+        if self.qs_on_post:
+            for key, value in urlparse.parse_qsl(self.qs_on_post,
+                                self.keep_blank_values, self.strict_parsing):
+                self.list.append(MiniFieldStorage(key, value))
+            FieldStorageClass = None
+
+        klass = self.FieldStorageClass or self.__class__
+        part = klass(self.fp, {}, ib,
+                     environ, keep_blank_values, strict_parsing)
+        # Throw first part away
+        while not part.done:
+            headers = rfc822.Message(self.fp)
+            part = klass(self.fp, headers, ib,
+                         environ, keep_blank_values, strict_parsing)
+            self.list.append(part)
+        self.skip_lines()
+
+    def read_single(self):
+        """Internal: read an atomic part."""
+        if self.length >= 0:
+            self.read_binary()
+            self.skip_lines()
+        else:
+            self.read_lines()
+        self.file.seek(0)
+
+    bufsize = 8*1024            # I/O buffering size for copy to file
+
+    def read_binary(self):
+        """Internal: read binary data."""
+        self.file = self.make_file('b')
+        todo = self.length
+        if todo >= 0:
+            while todo > 0:
+                data = self.fp.read(min(todo, self.bufsize))
+                if not data:
+                    self.done = -1
+                    break
+                self.file.write(data)
+                todo = todo - len(data)
+
+    def read_lines(self):
+        """Internal: read lines until EOF or outerboundary."""
+        self.file = self.__file = StringIO()
+        if self.outerboundary:
+            self.read_lines_to_outerboundary()
+        else:
+            self.read_lines_to_eof()
+
+    def __write(self, line):
+        if self.__file is not None:
+            if self.__file.tell() + len(line) > 1000:
+                self.file = self.make_file('')
+                self.file.write(self.__file.getvalue())
+                self.__file = None
+        self.file.write(line)
+
+    def read_lines_to_eof(self):
+        """Internal: read lines until EOF."""
+        while 1:
+            line = self.fp.readline(1<<16)
+            if not line:
+                self.done = -1
+                break
+            self.__write(line)
+
+    def read_lines_to_outerboundary(self):
+        """Internal: read lines until outerboundary."""
+        next = "--" + self.outerboundary
+        last = next + "--"
+        delim = ""
+        last_line_lfend = True
+        while 1:
+            line = self.fp.readline(1<<16)
+            if not line:
+                self.done = -1
+                break
+            if line[:2] == "--" and last_line_lfend:
+                strippedline = line.strip()
+                if strippedline == next:
+                    break
+                if strippedline == last:
+                    self.done = 1
+                    break
+            odelim = delim
+            if line[-2:] == "\r\n":
+                delim = "\r\n"
+                line = line[:-2]
+                last_line_lfend = True
+            elif line[-1] == "\n":
+                delim = "\n"
+                line = line[:-1]
+                last_line_lfend = True
+            else:
+                delim = ""
+                last_line_lfend = False
+            self.__write(odelim + line)
+
+    def skip_lines(self):
+        """Internal: skip lines until outer boundary if defined."""
+        if not self.outerboundary or self.done:
+            return
+        next = "--" + self.outerboundary
+        last = next + "--"
+        last_line_lfend = True
+        while 1:
+            line = self.fp.readline(1<<16)
+            if not line:
+                self.done = -1
+                break
+            if line[:2] == "--" and last_line_lfend:
+                strippedline = line.strip()
+                if strippedline == next:
+                    break
+                if strippedline == last:
+                    self.done = 1
+                    break
+            last_line_lfend = line.endswith('\n')
+
+    def make_file(self, binary=None):
+        """Overridable: return a readable & writable file.
+
+        The file will be used as follows:
+        - data is written to it
+        - seek(0)
+        - data is read from it
+
+        The 'binary' argument is unused -- the file is always opened
+        in binary mode.
+
+        This version opens a temporary file for reading and writing,
+        and immediately deletes (unlinks) it.  The trick (on Unix!) is
+        that the file can still be used, but it can't be opened by
+        another process, and it will automatically be deleted when it
+        is closed or when the current process terminates.
+
+        If you want a more permanent file, you derive a class which
+        overrides this method.  If you want a visible temporary file
+        that is nevertheless automatically deleted when the script
+        terminates, try defining a __del__ method in a derived class
+        which unlinks the temporary files you have created.
+
+        """
+        import tempfile
+        return tempfile.TemporaryFile("w+b")
+
+
+
+# Backwards Compatibility Classes
+# ===============================
+
+class FormContentDict(UserDict.UserDict):
+    """Form content as dictionary with a list of values per field.
+
+    form = FormContentDict()
+
+    form[key] -> [value, value, ...]
+    key in form -> Boolean
+    form.keys() -> [key, key, ...]
+    form.values() -> [[val, val, ...], [val, val, ...], ...]
+    form.items() ->  [(key, [val, val, ...]), (key, [val, val, ...]), ...]
+    form.dict == {key: [val, val, ...], ...}
+
+    """
+    def __init__(self, environ=os.environ, keep_blank_values=0, strict_parsing=0):
+        self.dict = self.data = parse(environ=environ,
+                                      keep_blank_values=keep_blank_values,
+                                      strict_parsing=strict_parsing)
+        self.query_string = environ['QUERY_STRING']
+
+
+class SvFormContentDict(FormContentDict):
+    """Form content as dictionary expecting a single value per field.
+
+    If you only expect a single value for each field, then form[key]
+    will return that single value.  It will raise an IndexError if
+    that expectation is not true.  If you expect a field to have
+    possible multiple values, than you can use form.getlist(key) to
+    get all of the values.  values() and items() are a compromise:
+    they return single strings where there is a single value, and
+    lists of strings otherwise.
+
+    """
+    def __getitem__(self, key):
+        if len(self.dict[key]) > 1:
+            raise IndexError, 'expecting a single value'
+        return self.dict[key][0]
+    def getlist(self, key):
+        return self.dict[key]
+    def values(self):
+        result = []
+        for value in self.dict.values():
+            if len(value) == 1:
+                result.append(value[0])
+            else: result.append(value)
+        return result
+    def items(self):
+        result = []
+        for key, value in self.dict.items():
+            if len(value) == 1:
+                result.append((key, value[0]))
+            else: result.append((key, value))
+        return result
+
+
+class InterpFormContentDict(SvFormContentDict):
+    """This class is present for backwards compatibility only."""
+    def __getitem__(self, key):
+        v = SvFormContentDict.__getitem__(self, key)
+        if v[0] in '0123456789+-.':
+            try: return int(v)
+            except ValueError:
+                try: return float(v)
+                except ValueError: pass
+        return v.strip()
+    def values(self):
+        result = []
+        for key in self.keys():
+            try:
+                result.append(self[key])
+            except IndexError:
+                result.append(self.dict[key])
+        return result
+    def items(self):
+        result = []
+        for key in self.keys():
+            try:
+                result.append((key, self[key]))
+            except IndexError:
+                result.append((key, self.dict[key]))
+        return result
+
+
+class FormContent(FormContentDict):
+    """This class is present for backwards compatibility only."""
+    def values(self, key):
+        if key in self.dict :return self.dict[key]
+        else: return None
+    def indexed_value(self, key, location):
+        if key in self.dict:
+            if len(self.dict[key]) > location:
+                return self.dict[key][location]
+            else: return None
+        else: return None
+    def value(self, key):
+        if key in self.dict: return self.dict[key][0]
+        else: return None
+    def length(self, key):
+        return len(self.dict[key])
+    def stripped(self, key):
+        if key in self.dict: return self.dict[key][0].strip()
+        else: return None
+    def pars(self):
+        return self.dict
+
+
+# Test/debug code
+# ===============
+
+def test(environ=os.environ):
+    """Robust test CGI script, usable as main program.
+
+    Write minimal HTTP headers and dump all information provided to
+    the script in HTML form.
+
+    """
+    print "Content-type: text/html"
+    print
+    sys.stderr = sys.stdout
+    try:
+        form = FieldStorage()   # Replace with other classes to test those
+        print_directory()
+        print_arguments()
+        print_form(form)
+        print_environ(environ)
+        print_environ_usage()
+        def f():
+            exec "testing print_exception() -- <I>italics?</I>"
+        def g(f=f):
+            f()
+        print "<H3>What follows is a test, not an actual exception:</H3>"
+        g()
+    except:
+        print_exception()
+
+    print "<H1>Second try with a small maxlen...</H1>"
+
+    global maxlen
+    maxlen = 50
+    try:
+        form = FieldStorage()   # Replace with other classes to test those
+        print_directory()
+        print_arguments()
+        print_form(form)
+        print_environ(environ)
+    except:
+        print_exception()
+
+def print_exception(type=None, value=None, tb=None, limit=None):
+    if type is None:
+        type, value, tb = sys.exc_info()
+    import traceback
+    print
+    print "<H3>Traceback (most recent call last):</H3>"
+    list = traceback.format_tb(tb, limit) + \
+           traceback.format_exception_only(type, value)
+    print "<PRE>%s<B>%s</B></PRE>" % (
+        escape("".join(list[:-1])),
+        escape(list[-1]),
+        )
+    del tb
+
+def print_environ(environ=os.environ):
+    """Dump the shell environment as HTML."""
+    keys = environ.keys()
+    keys.sort()
+    print
+    print "<H3>Shell Environment:</H3>"
+    print "<DL>"
+    for key in keys:
+        print "<DT>", escape(key), "<DD>", escape(environ[key])
+    print "</DL>"
+    print
+
+def print_form(form):
+    """Dump the contents of a form as HTML."""
+    keys = form.keys()
+    keys.sort()
+    print
+    print "<H3>Form Contents:</H3>"
+    if not keys:
+        print "<P>No form fields."
+    print "<DL>"
+    for key in keys:
+        print "<DT>" + escape(key) + ":",
+        value = form[key]
+        print "<i>" + escape(repr(type(value))) + "</i>"
+        print "<DD>" + escape(repr(value))
+    print "</DL>"
+    print
+
+def print_directory():
+    """Dump the current directory as HTML."""
+    print
+    print "<H3>Current Working Directory:</H3>"
+    try:
+        pwd = os.getcwd()
+    except os.error, msg:
+        print "os.error:", escape(str(msg))
+    else:
+        print escape(pwd)
+    print
+
+def print_arguments():
+    print
+    print "<H3>Command Line Arguments:</H3>"
+    print
+    print sys.argv
+    print
+
+def print_environ_usage():
+    """Dump a list of environment variables used by CGI as HTML."""
+    print """
+<H3>These environment variables could have been set:</H3>
+<UL>
+<LI>AUTH_TYPE
+<LI>CONTENT_LENGTH
+<LI>CONTENT_TYPE
+<LI>DATE_GMT
+<LI>DATE_LOCAL
+<LI>DOCUMENT_NAME
+<LI>DOCUMENT_ROOT
+<LI>DOCUMENT_URI
+<LI>GATEWAY_INTERFACE
+<LI>LAST_MODIFIED
+<LI>PATH
+<LI>PATH_INFO
+<LI>PATH_TRANSLATED
+<LI>QUERY_STRING
+<LI>REMOTE_ADDR
+<LI>REMOTE_HOST
+<LI>REMOTE_IDENT
+<LI>REMOTE_USER
+<LI>REQUEST_METHOD
+<LI>SCRIPT_NAME
+<LI>SERVER_NAME
+<LI>SERVER_PORT
+<LI>SERVER_PROTOCOL
+<LI>SERVER_ROOT
+<LI>SERVER_SOFTWARE
+</UL>
+In addition, HTTP headers sent by the server may be passed in the
+environment as well.  Here are some common variable names:
+<UL>
+<LI>HTTP_ACCEPT
+<LI>HTTP_CONNECTION
+<LI>HTTP_HOST
+<LI>HTTP_PRAGMA
+<LI>HTTP_REFERER
+<LI>HTTP_USER_AGENT
+</UL>
+"""
+
+
+# Utilities
+# =========
+
+def escape(s, quote=None):
+    '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
+    If the optional flag quote is true, the quotation mark character (")
+    is also translated.'''
+    s = s.replace("&", "&amp;") # Must be done first!
+    s = s.replace("<", "&lt;")
+    s = s.replace(">", "&gt;")
+    if quote:
+        s = s.replace('"', "&quot;")
+    return s
+
+def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
+    import re
+    return re.match(_vb_pattern, s)
+
+# Invoke mainline
+# ===============
+
+# Call test() when this file is run as a script (not imported as a module)
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/cgitb.py b/src/main/resources/PythonLibs/cgitb.py
new file mode 100644
index 0000000000000000000000000000000000000000..8acc4b75fe3b384c144ed14c23626188948612e4
--- /dev/null
+++ b/src/main/resources/PythonLibs/cgitb.py
@@ -0,0 +1,323 @@
+"""More comprehensive traceback formatting for Python scripts.
+
+To enable this module, do:
+
+    import cgitb; cgitb.enable()
+
+at the top of your script.  The optional arguments to enable() are:
+
+    display     - if true, tracebacks are displayed in the web browser
+    logdir      - if set, tracebacks are written to files in this directory
+    context     - number of lines of source code to show for each stack frame
+    format      - 'text' or 'html' controls the output format
+
+By default, tracebacks are displayed but not saved, the context is 5 lines
+and the output format is 'html' (for backwards compatibility with the
+original use of this module)
+
+Alternatively, if you have caught an exception and want cgitb to display it
+for you, call cgitb.handler().  The optional argument to handler() is a
+3-item tuple (etype, evalue, etb) just like the value of sys.exc_info().
+The default handler displays output as HTML.
+
+"""
+import inspect
+import keyword
+import linecache
+import os
+import pydoc
+import sys
+import tempfile
+import time
+import tokenize
+import traceback
+import types
+
+def reset():
+    """Return a string that resets the CGI and browser to a known state."""
+    return '''<!--: spam
+Content-Type: text/html
+
+<body bgcolor="#f0f0f8"><font color="#f0f0f8" size="-5"> -->
+<body bgcolor="#f0f0f8"><font color="#f0f0f8" size="-5"> --> -->
+</font> </font> </font> </script> </object> </blockquote> </pre>
+</table> </table> </table> </table> </table> </font> </font> </font>'''
+
+__UNDEF__ = []                          # a special sentinel object
+def small(text):
+    if text:
+        return '<small>' + text + '</small>'
+    else:
+        return ''
+
+def strong(text):
+    if text:
+        return '<strong>' + text + '</strong>'
+    else:
+        return ''
+
+def grey(text):
+    if text:
+        return '<font color="#909090">' + text + '</font>'
+    else:
+        return ''
+
+def lookup(name, frame, locals):
+    """Find the value for a given name in the given environment."""
+    if name in locals:
+        return 'local', locals[name]
+    if name in frame.f_globals:
+        return 'global', frame.f_globals[name]
+    if '__builtins__' in frame.f_globals:
+        builtins = frame.f_globals['__builtins__']
+        if type(builtins) is type({}):
+            if name in builtins:
+                return 'builtin', builtins[name]
+        else:
+            if hasattr(builtins, name):
+                return 'builtin', getattr(builtins, name)
+    return None, __UNDEF__
+
+def scanvars(reader, frame, locals):
+    """Scan one logical line of Python and look up values of variables used."""
+    vars, lasttoken, parent, prefix, value = [], None, None, '', __UNDEF__
+    for ttype, token, start, end, line in tokenize.generate_tokens(reader):
+        if ttype == tokenize.NEWLINE: break
+        if ttype == tokenize.NAME and token not in keyword.kwlist:
+            if lasttoken == '.':
+                if parent is not __UNDEF__:
+                    value = getattr(parent, token, __UNDEF__)
+                    vars.append((prefix + token, prefix, value))
+            else:
+                where, value = lookup(token, frame, locals)
+                vars.append((token, where, value))
+        elif token == '.':
+            prefix += lasttoken + '.'
+            parent = value
+        else:
+            parent, prefix = None, ''
+        lasttoken = token
+    return vars
+
+def html(einfo, context=5):
+    """Return a nice HTML document describing a given traceback."""
+    etype, evalue, etb = einfo
+    if type(etype) is types.ClassType:
+        etype = etype.__name__
+    pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
+    date = time.ctime(time.time())
+    head = '<body bgcolor="#f0f0f8">' + pydoc.html.heading(
+        '<big><big>%s</big></big>' %
+        strong(pydoc.html.escape(str(etype))),
+        '#ffffff', '#6622aa', pyver + '<br>' + date) + '''
+<p>A problem occurred in a Python script.  Here is the sequence of
+function calls leading up to the error, in the order they occurred.</p>'''
+
+    indent = '<tt>' + small('&nbsp;' * 5) + '&nbsp;</tt>'
+    frames = []
+    records = inspect.getinnerframes(etb, context)
+    for frame, file, lnum, func, lines, index in records:
+        if file:
+            file = os.path.abspath(file)
+            link = '<a href="file://%s">%s</a>' % (file, pydoc.html.escape(file))
+        else:
+            file = link = '?'
+        args, varargs, varkw, locals = inspect.getargvalues(frame)
+        call = ''
+        if func != '?':
+            call = 'in ' + strong(func) + \
+                inspect.formatargvalues(args, varargs, varkw, locals,
+                    formatvalue=lambda value: '=' + pydoc.html.repr(value))
+
+        highlight = {}
+        def reader(lnum=[lnum]):
+            highlight[lnum[0]] = 1
+            try: return linecache.getline(file, lnum[0])
+            finally: lnum[0] += 1
+        vars = scanvars(reader, frame, locals)
+
+        rows = ['<tr><td bgcolor="#d8bbff">%s%s %s</td></tr>' %
+                ('<big>&nbsp;</big>', link, call)]
+        if index is not None:
+            i = lnum - index
+            for line in lines:
+                num = small('&nbsp;' * (5-len(str(i))) + str(i)) + '&nbsp;'
+                if i in highlight:
+                    line = '<tt>=&gt;%s%s</tt>' % (num, pydoc.html.preformat(line))
+                    rows.append('<tr><td bgcolor="#ffccee">%s</td></tr>' % line)
+                else:
+                    line = '<tt>&nbsp;&nbsp;%s%s</tt>' % (num, pydoc.html.preformat(line))
+                    rows.append('<tr><td>%s</td></tr>' % grey(line))
+                i += 1
+
+        done, dump = {}, []
+        for name, where, value in vars:
+            if name in done: continue
+            done[name] = 1
+            if value is not __UNDEF__:
+                if where in ('global', 'builtin'):
+                    name = ('<em>%s</em> ' % where) + strong(name)
+                elif where == 'local':
+                    name = strong(name)
+                else:
+                    name = where + strong(name.split('.')[-1])
+                dump.append('%s&nbsp;= %s' % (name, pydoc.html.repr(value)))
+            else:
+                dump.append(name + ' <em>undefined</em>')
+
+        rows.append('<tr><td>%s</td></tr>' % small(grey(', '.join(dump))))
+        frames.append('''
+<table width="100%%" cellspacing=0 cellpadding=0 border=0>
+%s</table>''' % '\n'.join(rows))
+
+    exception = ['<p>%s: %s' % (strong(pydoc.html.escape(str(etype))),
+                                pydoc.html.escape(str(evalue)))]
+    if isinstance(evalue, BaseException):
+        for name in dir(evalue):
+            if name[:1] == '_': continue
+            value = pydoc.html.repr(getattr(evalue, name))
+            exception.append('\n<br>%s%s&nbsp;=\n%s' % (indent, name, value))
+
+    return head + ''.join(frames) + ''.join(exception) + '''
+
+
+<!-- The above is a description of an error in a Python program, formatted
+     for a Web browser because the 'cgitb' module was enabled.  In case you
+     are not reading this in a Web browser, here is the original traceback:
+
+%s
+-->
+''' % pydoc.html.escape(
+          ''.join(traceback.format_exception(etype, evalue, etb)))
+
+def text(einfo, context=5):
+    """Return a plain text document describing a given traceback."""
+    etype, evalue, etb = einfo
+    if type(etype) is types.ClassType:
+        etype = etype.__name__
+    pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
+    date = time.ctime(time.time())
+    head = "%s\n%s\n%s\n" % (str(etype), pyver, date) + '''
+A problem occurred in a Python script.  Here is the sequence of
+function calls leading up to the error, in the order they occurred.
+'''
+
+    frames = []
+    records = inspect.getinnerframes(etb, context)
+    for frame, file, lnum, func, lines, index in records:
+        file = file and os.path.abspath(file) or '?'
+        args, varargs, varkw, locals = inspect.getargvalues(frame)
+        call = ''
+        if func != '?':
+            call = 'in ' + func + \
+                inspect.formatargvalues(args, varargs, varkw, locals,
+                    formatvalue=lambda value: '=' + pydoc.text.repr(value))
+
+        highlight = {}
+        def reader(lnum=[lnum]):
+            highlight[lnum[0]] = 1
+            try: return linecache.getline(file, lnum[0])
+            finally: lnum[0] += 1
+        vars = scanvars(reader, frame, locals)
+
+        rows = [' %s %s' % (file, call)]
+        if index is not None:
+            i = lnum - index
+            for line in lines:
+                num = '%5d ' % i
+                rows.append(num+line.rstrip())
+                i += 1
+
+        done, dump = {}, []
+        for name, where, value in vars:
+            if name in done: continue
+            done[name] = 1
+            if value is not __UNDEF__:
+                if where == 'global': name = 'global ' + name
+                elif where != 'local': name = where + name.split('.')[-1]
+                dump.append('%s = %s' % (name, pydoc.text.repr(value)))
+            else:
+                dump.append(name + ' undefined')
+
+        rows.append('\n'.join(dump))
+        frames.append('\n%s\n' % '\n'.join(rows))
+
+    exception = ['%s: %s' % (str(etype), str(evalue))]
+    if isinstance(evalue, BaseException):
+        for name in dir(evalue):
+            value = pydoc.text.repr(getattr(evalue, name))
+            exception.append('\n%s%s = %s' % (" "*4, name, value))
+
+    return head + ''.join(frames) + ''.join(exception) + '''
+
+The above is a description of an error in a Python program.  Here is
+the original traceback:
+
+%s
+''' % ''.join(traceback.format_exception(etype, evalue, etb))
+
+class Hook:
+    """A hook to replace sys.excepthook that shows tracebacks in HTML."""
+
+    def __init__(self, display=1, logdir=None, context=5, file=None,
+                 format="html"):
+        self.display = display          # send tracebacks to browser if true
+        self.logdir = logdir            # log tracebacks to files if not None
+        self.context = context          # number of source code lines per frame
+        self.file = file or sys.stdout  # place to send the output
+        self.format = format
+
+    def __call__(self, etype, evalue, etb):
+        self.handle((etype, evalue, etb))
+
+    def handle(self, info=None):
+        info = info or sys.exc_info()
+        if self.format == "html":
+            self.file.write(reset())
+
+        formatter = (self.format=="html") and html or text
+        plain = False
+        try:
+            doc = formatter(info, self.context)
+        except:                         # just in case something goes wrong
+            doc = ''.join(traceback.format_exception(*info))
+            plain = True
+
+        if self.display:
+            if plain:
+                doc = doc.replace('&', '&amp;').replace('<', '&lt;')
+                self.file.write('<pre>' + doc + '</pre>\n')
+            else:
+                self.file.write(doc + '\n')
+        else:
+            self.file.write('<p>A problem occurred in a Python script.\n')
+
+        if self.logdir is not None:
+            suffix = ['.txt', '.html'][self.format=="html"]
+            (fd, path) = tempfile.mkstemp(suffix=suffix, dir=self.logdir)
+
+            try:
+                file = os.fdopen(fd, 'w')
+                file.write(doc)
+                file.close()
+                msg = '%s contains the description of this error.' % path
+            except:
+                msg = 'Tried to save traceback to %s, but failed.' % path
+
+            if self.format == 'html':
+                self.file.write('<p>%s</p>\n' % msg)
+            else:
+                self.file.write(msg + '\n')
+        try:
+            self.file.flush()
+        except: pass
+
+handler = Hook().handle
+def enable(display=1, logdir=None, context=5, format="html"):
+    """Install an exception handler that formats tracebacks as HTML.
+
+    The optional argument 'display' can be set to 0 to suppress sending the
+    traceback to the browser, and 'logdir' can be set to a directory to cause
+    tracebacks to be written to files there."""
+    sys.excepthook = Hook(display=display, logdir=logdir,
+                          context=context, format=format)
diff --git a/src/main/resources/PythonLibs/chunk.py b/src/main/resources/PythonLibs/chunk.py
new file mode 100644
index 0000000000000000000000000000000000000000..a8fbc1051f3e44794427408fa0c4dbc89b3c9103
--- /dev/null
+++ b/src/main/resources/PythonLibs/chunk.py
@@ -0,0 +1,167 @@
+"""Simple class to read IFF chunks.
+
+An IFF chunk (used in formats such as AIFF, TIFF, RMFF (RealMedia File
+Format)) has the following structure:
+
++----------------+
+| ID (4 bytes)   |
++----------------+
+| size (4 bytes) |
++----------------+
+| data           |
+| ...            |
++----------------+
+
+The ID is a 4-byte string which identifies the type of chunk.
+
+The size field (a 32-bit value, encoded using big-endian byte order)
+gives the size of the whole chunk, including the 8-byte header.
+
+Usually an IFF-type file consists of one or more chunks.  The proposed
+usage of the Chunk class defined here is to instantiate an instance at
+the start of each chunk and read from the instance until it reaches
+the end, after which a new instance can be instantiated.  At the end
+of the file, creating a new instance will fail with a EOFError
+exception.
+
+Usage:
+while True:
+    try:
+        chunk = Chunk(file)
+    except EOFError:
+        break
+    chunktype = chunk.getname()
+    while True:
+        data = chunk.read(nbytes)
+        if not data:
+            pass
+        # do something with data
+
+The interface is file-like.  The implemented methods are:
+read, close, seek, tell, isatty.
+Extra methods are: skip() (called by close, skips to the end of the chunk),
+getname() (returns the name (ID) of the chunk)
+
+The __init__ method has one required argument, a file-like object
+(including a chunk instance), and one optional argument, a flag which
+specifies whether or not chunks are aligned on 2-byte boundaries.  The
+default is 1, i.e. aligned.
+"""
+
+class Chunk:
+    def __init__(self, file, align=True, bigendian=True, inclheader=False):
+        import struct
+        self.closed = False
+        self.align = align      # whether to align to word (2-byte) boundaries
+        if bigendian:
+            strflag = '>'
+        else:
+            strflag = '<'
+        self.file = file
+        self.chunkname = file.read(4)
+        if len(self.chunkname) < 4:
+            raise EOFError
+        try:
+            self.chunksize = struct.unpack(strflag+'L', file.read(4))[0]
+        except struct.error:
+            raise EOFError
+        if inclheader:
+            self.chunksize = self.chunksize - 8 # subtract header
+        self.size_read = 0
+        try:
+            self.offset = self.file.tell()
+        except (AttributeError, IOError):
+            self.seekable = False
+        else:
+            self.seekable = True
+
+    def getname(self):
+        """Return the name (ID) of the current chunk."""
+        return self.chunkname
+
+    def getsize(self):
+        """Return the size of the current chunk."""
+        return self.chunksize
+
+    def close(self):
+        if not self.closed:
+            self.skip()
+            self.closed = True
+
+    def isatty(self):
+        if self.closed:
+            raise ValueError, "I/O operation on closed file"
+        return False
+
+    def seek(self, pos, whence=0):
+        """Seek to specified position into the chunk.
+        Default position is 0 (start of chunk).
+        If the file is not seekable, this will result in an error.
+        """
+
+        if self.closed:
+            raise ValueError, "I/O operation on closed file"
+        if not self.seekable:
+            raise IOError, "cannot seek"
+        if whence == 1:
+            pos = pos + self.size_read
+        elif whence == 2:
+            pos = pos + self.chunksize
+        if pos < 0 or pos > self.chunksize:
+            raise RuntimeError
+        self.file.seek(self.offset + pos, 0)
+        self.size_read = pos
+
+    def tell(self):
+        if self.closed:
+            raise ValueError, "I/O operation on closed file"
+        return self.size_read
+
+    def read(self, size=-1):
+        """Read at most size bytes from the chunk.
+        If size is omitted or negative, read until the end
+        of the chunk.
+        """
+
+        if self.closed:
+            raise ValueError, "I/O operation on closed file"
+        if self.size_read >= self.chunksize:
+            return ''
+        if size < 0:
+            size = self.chunksize - self.size_read
+        if size > self.chunksize - self.size_read:
+            size = self.chunksize - self.size_read
+        data = self.file.read(size)
+        self.size_read = self.size_read + len(data)
+        if self.size_read == self.chunksize and \
+           self.align and \
+           (self.chunksize & 1):
+            dummy = self.file.read(1)
+            self.size_read = self.size_read + len(dummy)
+        return data
+
+    def skip(self):
+        """Skip the rest of the chunk.
+        If you are not interested in the contents of the chunk,
+        this method should be called so that the file points to
+        the start of the next chunk.
+        """
+
+        if self.closed:
+            raise ValueError, "I/O operation on closed file"
+        if self.seekable:
+            try:
+                n = self.chunksize - self.size_read
+                # maybe fix alignment
+                if self.align and (self.chunksize & 1):
+                    n = n + 1
+                self.file.seek(n, 1)
+                self.size_read = self.size_read + n
+                return
+            except IOError:
+                pass
+        while self.size_read < self.chunksize:
+            n = min(8192, self.chunksize - self.size_read)
+            dummy = self.read(n)
+            if not dummy:
+                raise EOFError
diff --git a/src/main/resources/PythonLibs/cmd.py b/src/main/resources/PythonLibs/cmd.py
new file mode 100644
index 0000000000000000000000000000000000000000..05ba7e3bc6b724b59dc5ddd45e0c8e1cb178deba
--- /dev/null
+++ b/src/main/resources/PythonLibs/cmd.py
@@ -0,0 +1,404 @@
+"""A generic class to build line-oriented command interpreters.
+
+Interpreters constructed with this class obey the following conventions:
+
+1. End of file on input is processed as the command 'EOF'.
+2. A command is parsed out of each line by collecting the prefix composed
+   of characters in the identchars member.
+3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method
+   is passed a single argument consisting of the remainder of the line.
+4. Typing an empty line repeats the last command.  (Actually, it calls the
+   method `emptyline', which may be overridden in a subclass.)
+5. There is a predefined `help' method.  Given an argument `topic', it
+   calls the command `help_topic'.  With no arguments, it lists all topics
+   with defined help_ functions, broken into up to three topics; documented
+   commands, miscellaneous help topics, and undocumented commands.
+6. The command '?' is a synonym for `help'.  The command '!' is a synonym
+   for `shell', if a do_shell method exists.
+7. If completion is enabled, completing commands will be done automatically,
+   and completing of commands args is done by calling complete_foo() with
+   arguments text, line, begidx, endidx.  text is string we are matching
+   against, all returned matches must begin with it.  line is the current
+   input line (lstripped), begidx and endidx are the beginning and end
+   indexes of the text being matched, which could be used to provide
+   different completion depending upon which position the argument is in.
+
+The `default' method may be overridden to intercept commands for which there
+is no do_ method.
+
+The `completedefault' method may be overridden to intercept completions for
+commands that have no complete_ method.
+
+The data member `self.ruler' sets the character used to draw separator lines
+in the help messages.  If empty, no ruler line is drawn.  It defaults to "=".
+
+If the value of `self.intro' is nonempty when the cmdloop method is called,
+it is printed out on interpreter startup.  This value may be overridden
+via an optional argument to the cmdloop() method.
+
+The data members `self.doc_header', `self.misc_header', and
+`self.undoc_header' set the headers used for the help function's
+listings of documented functions, miscellaneous topics, and undocumented
+functions respectively.
+
+These interpreters use raw_input; thus, if the readline module is loaded,
+they automatically support Emacs-like command history and editing features.
+"""
+
+import string
+
+__all__ = ["Cmd"]
+
+PROMPT = '(Cmd) '
+IDENTCHARS = string.ascii_letters + string.digits + '_'
+
+class Cmd:
+    """A simple framework for writing line-oriented command interpreters.
+
+    These are often useful for test harnesses, administrative tools, and
+    prototypes that will later be wrapped in a more sophisticated interface.
+
+    A Cmd instance or subclass instance is a line-oriented interpreter
+    framework.  There is no good reason to instantiate Cmd itself; rather,
+    it's useful as a superclass of an interpreter class you define yourself
+    in order to inherit Cmd's methods and encapsulate action methods.
+
+    """
+    prompt = PROMPT
+    identchars = IDENTCHARS
+    ruler = '='
+    lastcmd = ''
+    intro = None
+    doc_leader = ""
+    doc_header = "Documented commands (type help <topic>):"
+    misc_header = "Miscellaneous help topics:"
+    undoc_header = "Undocumented commands:"
+    nohelp = "*** No help on %s"
+    use_rawinput = 1
+
+    def __init__(self, completekey='tab', stdin=None, stdout=None):
+        """Instantiate a line-oriented interpreter framework.
+
+        The optional argument 'completekey' is the readline name of a
+        completion key; it defaults to the Tab key. If completekey is
+        not None and the readline module is available, command completion
+        is done automatically. The optional arguments stdin and stdout
+        specify alternate input and output file objects; if not specified,
+        sys.stdin and sys.stdout are used.
+
+        """
+        import sys
+        if stdin is not None:
+            self.stdin = stdin
+        else:
+            self.stdin = sys.stdin
+        if stdout is not None:
+            self.stdout = stdout
+        else:
+            self.stdout = sys.stdout
+        self.cmdqueue = []
+        self.completekey = completekey
+
+    def cmdloop(self, intro=None):
+        """Repeatedly issue a prompt, accept input, parse an initial prefix
+        off the received input, and dispatch to action methods, passing them
+        the remainder of the line as argument.
+
+        """
+
+        self.preloop()
+        if self.use_rawinput and self.completekey:
+            try:
+                import readline
+                self.old_completer = readline.get_completer()
+                readline.set_completer(self.complete)
+                readline.parse_and_bind(self.completekey+": complete")
+            except ImportError:
+                pass
+        try:
+            if intro is not None:
+                self.intro = intro
+            if self.intro:
+                self.stdout.write(str(self.intro)+"\n")
+            stop = None
+            while not stop:
+                if self.cmdqueue:
+                    line = self.cmdqueue.pop(0)
+                else:
+                    if self.use_rawinput:
+                        try:
+                            line = raw_input(self.prompt)
+                        except EOFError:
+                            line = 'EOF'
+                    else:
+                        self.stdout.write(self.prompt)
+                        self.stdout.flush()
+                        line = self.stdin.readline()
+                        if not len(line):
+                            line = 'EOF'
+                        else:
+                            line = line.rstrip('\r\n')
+                line = self.precmd(line)
+                stop = self.onecmd(line)
+                stop = self.postcmd(stop, line)
+            self.postloop()
+        finally:
+            if self.use_rawinput and self.completekey:
+                try:
+                    import readline
+                    readline.set_completer(self.old_completer)
+                except ImportError:
+                    pass
+
+
+    def precmd(self, line):
+        """Hook method executed just before the command line is
+        interpreted, but after the input prompt is generated and issued.
+
+        """
+        return line
+
+    def postcmd(self, stop, line):
+        """Hook method executed just after a command dispatch is finished."""
+        return stop
+
+    def preloop(self):
+        """Hook method executed once when the cmdloop() method is called."""
+        pass
+
+    def postloop(self):
+        """Hook method executed once when the cmdloop() method is about to
+        return.
+
+        """
+        pass
+
+    def parseline(self, line):
+        """Parse the line into a command name and a string containing
+        the arguments.  Returns a tuple containing (command, args, line).
+        'command' and 'args' may be None if the line couldn't be parsed.
+        """
+        line = line.strip()
+        if not line:
+            return None, None, line
+        elif line[0] == '?':
+            line = 'help ' + line[1:]
+        elif line[0] == '!':
+            if hasattr(self, 'do_shell'):
+                line = 'shell ' + line[1:]
+            else:
+                return None, None, line
+        i, n = 0, len(line)
+        while i < n and line[i] in self.identchars: i = i+1
+        cmd, arg = line[:i], line[i:].strip()
+        return cmd, arg, line
+
+    def onecmd(self, line):
+        """Interpret the argument as though it had been typed in response
+        to the prompt.
+
+        This may be overridden, but should not normally need to be;
+        see the precmd() and postcmd() methods for useful execution hooks.
+        The return value is a flag indicating whether interpretation of
+        commands by the interpreter should stop.
+
+        """
+        cmd, arg, line = self.parseline(line)
+        if not line:
+            return self.emptyline()
+        if cmd is None:
+            return self.default(line)
+        self.lastcmd = line
+        if line == 'EOF' :
+            self.lastcmd = ''
+        if cmd == '':
+            return self.default(line)
+        else:
+            try:
+                func = getattr(self, 'do_' + cmd)
+            except AttributeError:
+                return self.default(line)
+            return func(arg)
+
+    def emptyline(self):
+        """Called when an empty line is entered in response to the prompt.
+
+        If this method is not overridden, it repeats the last nonempty
+        command entered.
+
+        """
+        if self.lastcmd:
+            return self.onecmd(self.lastcmd)
+
+    def default(self, line):
+        """Called on an input line when the command prefix is not recognized.
+
+        If this method is not overridden, it prints an error message and
+        returns.
+
+        """
+        self.stdout.write('*** Unknown syntax: %s\n'%line)
+
+    def completedefault(self, *ignored):
+        """Method called to complete an input line when no command-specific
+        complete_*() method is available.
+
+        By default, it returns an empty list.
+
+        """
+        return []
+
+    def completenames(self, text, *ignored):
+        dotext = 'do_'+text
+        return [a[3:] for a in self.get_names() if a.startswith(dotext)]
+
+    def complete(self, text, state):
+        """Return the next possible completion for 'text'.
+
+        If a command has not been entered, then complete against command list.
+        Otherwise try to call complete_<command> to get list of completions.
+        """
+        if state == 0:
+            import readline
+            origline = readline.get_line_buffer()
+            line = origline.lstrip()
+            stripped = len(origline) - len(line)
+            begidx = readline.get_begidx() - stripped
+            endidx = readline.get_endidx() - stripped
+            if begidx>0:
+                cmd, args, foo = self.parseline(line)
+                if cmd == '':
+                    compfunc = self.completedefault
+                else:
+                    try:
+                        compfunc = getattr(self, 'complete_' + cmd)
+                    except AttributeError:
+                        compfunc = self.completedefault
+            else:
+                compfunc = self.completenames
+            self.completion_matches = compfunc(text, line, begidx, endidx)
+        try:
+            return self.completion_matches[state]
+        except IndexError:
+            return None
+
+    def get_names(self):
+        # This method used to pull in base class attributes
+        # at a time dir() didn't do it yet.
+        return dir(self.__class__)
+
+    def complete_help(self, *args):
+        commands = set(self.completenames(*args))
+        topics = set(a[5:] for a in self.get_names()
+                     if a.startswith('help_' + args[0]))
+        return list(commands | topics)
+
+    def do_help(self, arg):
+        'List available commands with "help" or detailed help with "help cmd".'
+        if arg:
+            # XXX check arg syntax
+            try:
+                func = getattr(self, 'help_' + arg)
+            except AttributeError:
+                try:
+                    doc=getattr(self, 'do_' + arg).__doc__
+                    if doc:
+                        self.stdout.write("%s\n"%str(doc))
+                        return
+                except AttributeError:
+                    pass
+                self.stdout.write("%s\n"%str(self.nohelp % (arg,)))
+                return
+            func()
+        else:
+            names = self.get_names()
+            cmds_doc = []
+            cmds_undoc = []
+            help = {}
+            for name in names:
+                if name[:5] == 'help_':
+                    help[name[5:]]=1
+            names.sort()
+            # There can be duplicates if routines overridden
+            prevname = ''
+            for name in names:
+                if name[:3] == 'do_':
+                    if name == prevname:
+                        continue
+                    prevname = name
+                    cmd=name[3:]
+                    if cmd in help:
+                        cmds_doc.append(cmd)
+                        del help[cmd]
+                    elif getattr(self, name).__doc__:
+                        cmds_doc.append(cmd)
+                    else:
+                        cmds_undoc.append(cmd)
+            self.stdout.write("%s\n"%str(self.doc_leader))
+            self.print_topics(self.doc_header,   cmds_doc,   15,80)
+            self.print_topics(self.misc_header,  help.keys(),15,80)
+            self.print_topics(self.undoc_header, cmds_undoc, 15,80)
+
+    def print_topics(self, header, cmds, cmdlen, maxcol):
+        if cmds:
+            self.stdout.write("%s\n"%str(header))
+            if self.ruler:
+                self.stdout.write("%s\n"%str(self.ruler * len(header)))
+            self.columnize(cmds, maxcol-1)
+            self.stdout.write("\n")
+
+    def columnize(self, list, displaywidth=80):
+        """Display a list of strings as a compact set of columns.
+
+        Each column is only as wide as necessary.
+        Columns are separated by two spaces (one was not legible enough).
+        """
+        if not list:
+            self.stdout.write("<empty>\n")
+            return
+        nonstrings = [i for i in range(len(list))
+                        if not isinstance(list[i], str)]
+        if nonstrings:
+            raise TypeError, ("list[i] not a string for i in %s" %
+                              ", ".join(map(str, nonstrings)))
+        size = len(list)
+        if size == 1:
+            self.stdout.write('%s\n'%str(list[0]))
+            return
+        # Try every row count from 1 upwards
+        for nrows in range(1, len(list)):
+            ncols = (size+nrows-1) // nrows
+            colwidths = []
+            totwidth = -2
+            for col in range(ncols):
+                colwidth = 0
+                for row in range(nrows):
+                    i = row + nrows*col
+                    if i >= size:
+                        break
+                    x = list[i]
+                    colwidth = max(colwidth, len(x))
+                colwidths.append(colwidth)
+                totwidth += colwidth + 2
+                if totwidth > displaywidth:
+                    break
+            if totwidth <= displaywidth:
+                break
+        else:
+            nrows = len(list)
+            ncols = 1
+            colwidths = [0]
+        for row in range(nrows):
+            texts = []
+            for col in range(ncols):
+                i = row + nrows*col
+                if i >= size:
+                    x = ""
+                else:
+                    x = list[i]
+                texts.append(x)
+            while texts and not texts[-1]:
+                del texts[-1]
+            for col in range(len(texts)):
+                texts[col] = texts[col].ljust(colwidths[col])
+            self.stdout.write("%s\n"%str("  ".join(texts)))
diff --git a/src/main/resources/PythonLibs/code.py b/src/main/resources/PythonLibs/code.py
new file mode 100644
index 0000000000000000000000000000000000000000..3b39d1b346f9092f9459e37470f4af1de8df8678
--- /dev/null
+++ b/src/main/resources/PythonLibs/code.py
@@ -0,0 +1,310 @@
+"""Utilities needed to emulate Python's interactive interpreter.
+
+"""
+
+# Inspired by similar code by Jeff Epler and Fredrik Lundh.
+
+
+import sys
+import traceback
+from codeop import CommandCompiler, compile_command
+
+__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact",
+           "compile_command"]
+
+def softspace(file, newvalue):
+    oldvalue = 0
+    try:
+        oldvalue = file.softspace
+    except AttributeError:
+        pass
+    try:
+        file.softspace = newvalue
+    except (AttributeError, TypeError):
+        # "attribute-less object" or "read-only attributes"
+        pass
+    return oldvalue
+
+class InteractiveInterpreter:
+    """Base class for InteractiveConsole.
+
+    This class deals with parsing and interpreter state (the user's
+    namespace); it doesn't deal with input buffering or prompting or
+    input file naming (the filename is always passed in explicitly).
+
+    """
+
+    def __init__(self, locals=None):
+        """Constructor.
+
+        The optional 'locals' argument specifies the dictionary in
+        which code will be executed; it defaults to a newly created
+        dictionary with key "__name__" set to "__console__" and key
+        "__doc__" set to None.
+
+        """
+        if locals is None:
+            locals = {"__name__": "__console__", "__doc__": None}
+        self.locals = locals
+        self.compile = CommandCompiler()
+
+    def runsource(self, source, filename="<input>", symbol="single"):
+        """Compile and run some source in the interpreter.
+
+        Arguments are as for compile_command().
+
+        One several things can happen:
+
+        1) The input is incorrect; compile_command() raised an
+        exception (SyntaxError or OverflowError).  A syntax traceback
+        will be printed by calling the showsyntaxerror() method.
+
+        2) The input is incomplete, and more input is required;
+        compile_command() returned None.  Nothing happens.
+
+        3) The input is complete; compile_command() returned a code
+        object.  The code is executed by calling self.runcode() (which
+        also handles run-time exceptions, except for SystemExit).
+
+        The return value is True in case 2, False in the other cases (unless
+        an exception is raised).  The return value can be used to
+        decide whether to use sys.ps1 or sys.ps2 to prompt the next
+        line.
+
+        """
+        try:
+            code = self.compile(source, filename, symbol)
+        except (OverflowError, SyntaxError, ValueError):
+            # Case 1
+            self.showsyntaxerror(filename)
+            return False
+
+        if code is None:
+            # Case 2
+            return True
+
+        # Case 3
+        self.runcode(code)
+        return False
+
+    def runcode(self, code):
+        """Execute a code object.
+
+        When an exception occurs, self.showtraceback() is called to
+        display a traceback.  All exceptions are caught except
+        SystemExit, which is reraised.
+
+        A note about KeyboardInterrupt: this exception may occur
+        elsewhere in this code, and may not always be caught.  The
+        caller should be prepared to deal with it.
+
+        """
+        try:
+            exec code in self.locals
+        except SystemExit:
+            raise
+        except:
+            self.showtraceback()
+        else:
+            if softspace(sys.stdout, 0):
+                print
+
+    def showsyntaxerror(self, filename=None):
+        """Display the syntax error that just occurred.
+
+        This doesn't display a stack trace because there isn't one.
+
+        If a filename is given, it is stuffed in the exception instead
+        of what was there before (because Python's parser always uses
+        "<string>" when reading from a string).
+
+        The output is written by self.write(), below.
+
+        """
+        type, value, sys.last_traceback = sys.exc_info()
+        sys.last_type = type
+        sys.last_value = value
+        if filename and type is SyntaxError:
+            # Work hard to stuff the correct filename in the exception
+            try:
+                msg, (dummy_filename, lineno, offset, line) = value
+            except:
+                # Not the format we expect; leave it alone
+                pass
+            else:
+                # Stuff in the right filename
+                value = SyntaxError(msg, (filename, lineno, offset, line))
+                sys.last_value = value
+        list = traceback.format_exception_only(type, value)
+        map(self.write, list)
+
+    def showtraceback(self):
+        """Display the exception that just occurred.
+
+        We remove the first stack item because it is our own code.
+
+        The output is written by self.write(), below.
+
+        """
+        try:
+            type, value, tb = sys.exc_info()
+            sys.last_type = type
+            sys.last_value = value
+            sys.last_traceback = tb
+            tblist = traceback.extract_tb(tb)
+            del tblist[:1]
+            list = traceback.format_list(tblist)
+            if list:
+                list.insert(0, "Traceback (most recent call last):\n")
+            list[len(list):] = traceback.format_exception_only(type, value)
+        finally:
+            tblist = tb = None
+        map(self.write, list)
+
+    def write(self, data):
+        """Write a string.
+
+        The base implementation writes to sys.stderr; a subclass may
+        replace this with a different implementation.
+
+        """
+        sys.stderr.write(data)
+
+
+class InteractiveConsole(InteractiveInterpreter):
+    """Closely emulate the behavior of the interactive Python interpreter.
+
+    This class builds on InteractiveInterpreter and adds prompting
+    using the familiar sys.ps1 and sys.ps2, and input buffering.
+
+    """
+
+    def __init__(self, locals=None, filename="<console>"):
+        """Constructor.
+
+        The optional locals argument will be passed to the
+        InteractiveInterpreter base class.
+
+        The optional filename argument should specify the (file)name
+        of the input stream; it will show up in tracebacks.
+
+        """
+        InteractiveInterpreter.__init__(self, locals)
+        self.filename = filename
+        self.resetbuffer()
+
+    def resetbuffer(self):
+        """Reset the input buffer."""
+        self.buffer = []
+
+    def interact(self, banner=None):
+        """Closely emulate the interactive Python console.
+
+        The optional banner argument specify the banner to print
+        before the first interaction; by default it prints a banner
+        similar to the one printed by the real Python interpreter,
+        followed by the current class name in parentheses (so as not
+        to confuse this with the real interpreter -- since it's so
+        close!).
+
+        """
+        try:
+            sys.ps1
+        except AttributeError:
+            sys.ps1 = ">>> "
+        try:
+            sys.ps2
+        except AttributeError:
+            sys.ps2 = "... "
+        cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
+        if banner is None:
+            self.write("Python %s on %s\n%s\n(%s)\n" %
+                       (sys.version, sys.platform, cprt,
+                        self.__class__.__name__))
+        else:
+            self.write("%s\n" % str(banner))
+        more = 0
+        while 1:
+            try:
+                if more:
+                    prompt = sys.ps2
+                else:
+                    prompt = sys.ps1
+                try:
+                    line = self.raw_input(prompt)
+                    # Can be None if sys.stdin was redefined
+                    encoding = getattr(sys.stdin, "encoding", None)
+                    if encoding and not isinstance(line, unicode):
+                        line = line.decode(encoding)
+                except EOFError:
+                    self.write("\n")
+                    break
+                else:
+                    more = self.push(line)
+            except KeyboardInterrupt:
+                self.write("\nKeyboardInterrupt\n")
+                self.resetbuffer()
+                more = 0
+
+    def push(self, line):
+        """Push a line to the interpreter.
+
+        The line should not have a trailing newline; it may have
+        internal newlines.  The line is appended to a buffer and the
+        interpreter's runsource() method is called with the
+        concatenated contents of the buffer as source.  If this
+        indicates that the command was executed or invalid, the buffer
+        is reset; otherwise, the command is incomplete, and the buffer
+        is left as it was after the line was appended.  The return
+        value is 1 if more input is required, 0 if the line was dealt
+        with in some way (this is the same as runsource()).
+
+        """
+        self.buffer.append(line)
+        source = "\n".join(self.buffer)
+        more = self.runsource(source, self.filename)
+        if not more:
+            self.resetbuffer()
+        return more
+
+    def raw_input(self, prompt=""):
+        """Write a prompt and read a line.
+
+        The returned line does not include the trailing newline.
+        When the user enters the EOF key sequence, EOFError is raised.
+
+        The base implementation uses the built-in function
+        raw_input(); a subclass may replace this with a different
+        implementation.
+
+        """
+        return raw_input(prompt)
+
+
+def interact(banner=None, readfunc=None, local=None):
+    """Closely emulate the interactive Python interpreter.
+
+    This is a backwards compatible interface to the InteractiveConsole
+    class.  When readfunc is not specified, it attempts to import the
+    readline module to enable GNU readline if it is available.
+
+    Arguments (all optional, all default to None):
+
+    banner -- passed to InteractiveConsole.interact()
+    readfunc -- if not None, replaces InteractiveConsole.raw_input()
+    local -- passed to InteractiveInterpreter.__init__()
+
+    """
+    console = InteractiveConsole(local)
+    if readfunc is not None:
+        console.raw_input = readfunc
+    else:
+        try:
+            import readline
+        except ImportError:
+            pass
+    console.interact(banner)
+
+
+if __name__ == "__main__":
+    interact()
diff --git a/src/main/resources/PythonLibs/codecs.py b/src/main/resources/PythonLibs/codecs.py
new file mode 100644
index 0000000000000000000000000000000000000000..f4cd60a14f2fd846ae8942d411e73b10ae829084
--- /dev/null
+++ b/src/main/resources/PythonLibs/codecs.py
@@ -0,0 +1,1098 @@
+""" codecs -- Python Codec Registry, API and helpers.
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""#"
+
+import __builtin__, sys
+
+### Registry and builtin stateless codec functions
+
+try:
+    from _codecs import *
+except ImportError, why:
+    raise SystemError('Failed to load the builtin codecs: %s' % why)
+
+__all__ = ["register", "lookup", "open", "EncodedFile", "BOM", "BOM_BE",
+           "BOM_LE", "BOM32_BE", "BOM32_LE", "BOM64_BE", "BOM64_LE",
+           "BOM_UTF8", "BOM_UTF16", "BOM_UTF16_LE", "BOM_UTF16_BE",
+           "BOM_UTF32", "BOM_UTF32_LE", "BOM_UTF32_BE",
+           "strict_errors", "ignore_errors", "replace_errors",
+           "xmlcharrefreplace_errors",
+           "register_error", "lookup_error"]
+
+### Constants
+
+#
+# Byte Order Mark (BOM = ZERO WIDTH NO-BREAK SPACE = U+FEFF)
+# and its possible byte string values
+# for UTF8/UTF16/UTF32 output and little/big endian machines
+#
+
+# UTF-8
+BOM_UTF8 = '\xef\xbb\xbf'
+
+# UTF-16, little endian
+BOM_LE = BOM_UTF16_LE = '\xff\xfe'
+
+# UTF-16, big endian
+BOM_BE = BOM_UTF16_BE = '\xfe\xff'
+
+# UTF-32, little endian
+BOM_UTF32_LE = '\xff\xfe\x00\x00'
+
+# UTF-32, big endian
+BOM_UTF32_BE = '\x00\x00\xfe\xff'
+
+if sys.byteorder == 'little':
+
+    # UTF-16, native endianness
+    BOM = BOM_UTF16 = BOM_UTF16_LE
+
+    # UTF-32, native endianness
+    BOM_UTF32 = BOM_UTF32_LE
+
+else:
+
+    # UTF-16, native endianness
+    BOM = BOM_UTF16 = BOM_UTF16_BE
+
+    # UTF-32, native endianness
+    BOM_UTF32 = BOM_UTF32_BE
+
+# Old broken names (don't use in new code)
+BOM32_LE = BOM_UTF16_LE
+BOM32_BE = BOM_UTF16_BE
+BOM64_LE = BOM_UTF32_LE
+BOM64_BE = BOM_UTF32_BE
+
+
+### Codec base classes (defining the API)
+
+class CodecInfo(tuple):
+
+    def __new__(cls, encode, decode, streamreader=None, streamwriter=None,
+        incrementalencoder=None, incrementaldecoder=None, name=None):
+        self = tuple.__new__(cls, (encode, decode, streamreader, streamwriter))
+        self.name = name
+        self.encode = encode
+        self.decode = decode
+        self.incrementalencoder = incrementalencoder
+        self.incrementaldecoder = incrementaldecoder
+        self.streamwriter = streamwriter
+        self.streamreader = streamreader
+        return self
+
+    def __repr__(self):
+        return "<%s.%s object for encoding %s at 0x%x>" % (self.__class__.__module__, self.__class__.__name__, self.name, id(self))
+
+class Codec:
+
+    """ Defines the interface for stateless encoders/decoders.
+
+        The .encode()/.decode() methods may use different error
+        handling schemes by providing the errors argument. These
+        string values are predefined:
+
+         'strict' - raise a ValueError error (or a subclass)
+         'ignore' - ignore the character and continue with the next
+         'replace' - replace with a suitable replacement character;
+                    Python will use the official U+FFFD REPLACEMENT
+                    CHARACTER for the builtin Unicode codecs on
+                    decoding and '?' on encoding.
+         'xmlcharrefreplace' - Replace with the appropriate XML
+                               character reference (only for encoding).
+         'backslashreplace'  - Replace with backslashed escape sequences
+                               (only for encoding).
+
+        The set of allowed values can be extended via register_error.
+
+    """
+    def encode(self, input, errors='strict'):
+
+        """ Encodes the object input and returns a tuple (output
+            object, length consumed).
+
+            errors defines the error handling to apply. It defaults to
+            'strict' handling.
+
+            The method may not store state in the Codec instance. Use
+            StreamCodec for codecs which have to keep state in order to
+            make encoding/decoding efficient.
+
+            The encoder must be able to handle zero length input and
+            return an empty object of the output object type in this
+            situation.
+
+        """
+        raise NotImplementedError
+
+    def decode(self, input, errors='strict'):
+
+        """ Decodes the object input and returns a tuple (output
+            object, length consumed).
+
+            input must be an object which provides the bf_getreadbuf
+            buffer slot. Python strings, buffer objects and memory
+            mapped files are examples of objects providing this slot.
+
+            errors defines the error handling to apply. It defaults to
+            'strict' handling.
+
+            The method may not store state in the Codec instance. Use
+            StreamCodec for codecs which have to keep state in order to
+            make encoding/decoding efficient.
+
+            The decoder must be able to handle zero length input and
+            return an empty object of the output object type in this
+            situation.
+
+        """
+        raise NotImplementedError
+
+class IncrementalEncoder(object):
+    """
+    An IncrementalEncoder encodes an input in multiple steps. The input can be
+    passed piece by piece to the encode() method. The IncrementalEncoder remembers
+    the state of the Encoding process between calls to encode().
+    """
+    def __init__(self, errors='strict'):
+        """
+        Creates an IncrementalEncoder instance.
+
+        The IncrementalEncoder may use different error handling schemes by
+        providing the errors keyword argument. See the module docstring
+        for a list of possible values.
+        """
+        self.errors = errors
+        self.buffer = ""
+
+    def encode(self, input, final=False):
+        """
+        Encodes input and returns the resulting object.
+        """
+        raise NotImplementedError
+
+    def reset(self):
+        """
+        Resets the encoder to the initial state.
+        """
+
+    def getstate(self):
+        """
+        Return the current state of the encoder.
+        """
+        return 0
+
+    def setstate(self, state):
+        """
+        Set the current state of the encoder. state must have been
+        returned by getstate().
+        """
+
+class BufferedIncrementalEncoder(IncrementalEncoder):
+    """
+    This subclass of IncrementalEncoder can be used as the baseclass for an
+    incremental encoder if the encoder must keep some of the output in a
+    buffer between calls to encode().
+    """
+    def __init__(self, errors='strict'):
+        IncrementalEncoder.__init__(self, errors)
+        self.buffer = "" # unencoded input that is kept between calls to encode()
+
+    def _buffer_encode(self, input, errors, final):
+        # Overwrite this method in subclasses: It must encode input
+        # and return an (output, length consumed) tuple
+        raise NotImplementedError
+
+    def encode(self, input, final=False):
+        # encode input (taking the buffer into account)
+        data = self.buffer + input
+        (result, consumed) = self._buffer_encode(data, self.errors, final)
+        # keep unencoded input until the next call
+        self.buffer = data[consumed:]
+        return result
+
+    def reset(self):
+        IncrementalEncoder.reset(self)
+        self.buffer = ""
+
+    def getstate(self):
+        return self.buffer or 0
+
+    def setstate(self, state):
+        self.buffer = state or ""
+
+class IncrementalDecoder(object):
+    """
+    An IncrementalDecoder decodes an input in multiple steps. The input can be
+    passed piece by piece to the decode() method. The IncrementalDecoder
+    remembers the state of the decoding process between calls to decode().
+    """
+    def __init__(self, errors='strict'):
+        """
+        Creates a IncrementalDecoder instance.
+
+        The IncrementalDecoder may use different error handling schemes by
+        providing the errors keyword argument. See the module docstring
+        for a list of possible values.
+        """
+        self.errors = errors
+
+    def decode(self, input, final=False):
+        """
+        Decodes input and returns the resulting object.
+        """
+        raise NotImplementedError
+
+    def reset(self):
+        """
+        Resets the decoder to the initial state.
+        """
+
+    def getstate(self):
+        """
+        Return the current state of the decoder.
+
+        This must be a (buffered_input, additional_state_info) tuple.
+        buffered_input must be a bytes object containing bytes that
+        were passed to decode() that have not yet been converted.
+        additional_state_info must be a non-negative integer
+        representing the state of the decoder WITHOUT yet having
+        processed the contents of buffered_input.  In the initial state
+        and after reset(), getstate() must return (b"", 0).
+        """
+        return (b"", 0)
+
+    def setstate(self, state):
+        """
+        Set the current state of the decoder.
+
+        state must have been returned by getstate().  The effect of
+        setstate((b"", 0)) must be equivalent to reset().
+        """
+
+class BufferedIncrementalDecoder(IncrementalDecoder):
+    """
+    This subclass of IncrementalDecoder can be used as the baseclass for an
+    incremental decoder if the decoder must be able to handle incomplete byte
+    sequences.
+    """
+    def __init__(self, errors='strict'):
+        IncrementalDecoder.__init__(self, errors)
+        self.buffer = "" # undecoded input that is kept between calls to decode()
+
+    def _buffer_decode(self, input, errors, final):
+        # Overwrite this method in subclasses: It must decode input
+        # and return an (output, length consumed) tuple
+        raise NotImplementedError
+
+    def decode(self, input, final=False):
+        # decode input (taking the buffer into account)
+        data = self.buffer + input
+        (result, consumed) = self._buffer_decode(data, self.errors, final)
+        # keep undecoded input until the next call
+        self.buffer = data[consumed:]
+        return result
+
+    def reset(self):
+        IncrementalDecoder.reset(self)
+        self.buffer = ""
+
+    def getstate(self):
+        # additional state info is always 0
+        return (self.buffer, 0)
+
+    def setstate(self, state):
+        # ignore additional state info
+        self.buffer = state[0]
+
+#
+# The StreamWriter and StreamReader class provide generic working
+# interfaces which can be used to implement new encoding submodules
+# very easily. See encodings/utf_8.py for an example on how this is
+# done.
+#
+
+class StreamWriter(Codec):
+
+    def __init__(self, stream, errors='strict'):
+
+        """ Creates a StreamWriter instance.
+
+            stream must be a file-like object open for writing
+            (binary) data.
+
+            The StreamWriter may use different error handling
+            schemes by providing the errors keyword argument. These
+            parameters are predefined:
+
+             'strict' - raise a ValueError (or a subclass)
+             'ignore' - ignore the character and continue with the next
+             'replace'- replace with a suitable replacement character
+             'xmlcharrefreplace' - Replace with the appropriate XML
+                                   character reference.
+             'backslashreplace'  - Replace with backslashed escape
+                                   sequences (only for encoding).
+
+            The set of allowed parameter values can be extended via
+            register_error.
+        """
+        self.stream = stream
+        self.errors = errors
+
+    def write(self, object):
+
+        """ Writes the object's contents encoded to self.stream.
+        """
+        data, consumed = self.encode(object, self.errors)
+        self.stream.write(data)
+
+    def writelines(self, list):
+
+        """ Writes the concatenated list of strings to the stream
+            using .write().
+        """
+        self.write(''.join(list))
+
+    def reset(self):
+
+        """ Flushes and resets the codec buffers used for keeping state.
+
+            Calling this method should ensure that the data on the
+            output is put into a clean state, that allows appending
+            of new fresh data without having to rescan the whole
+            stream to recover state.
+
+        """
+        pass
+
+    def seek(self, offset, whence=0):
+        self.stream.seek(offset, whence)
+        if whence == 0 and offset == 0:
+            self.reset()
+
+    def __getattr__(self, name,
+                    getattr=getattr):
+
+        """ Inherit all other methods from the underlying stream.
+        """
+        return getattr(self.stream, name)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, tb):
+        self.stream.close()
+
+###
+
+class StreamReader(Codec):
+
+    def __init__(self, stream, errors='strict'):
+
+        """ Creates a StreamReader instance.
+
+            stream must be a file-like object open for reading
+            (binary) data.
+
+            The StreamReader may use different error handling
+            schemes by providing the errors keyword argument. These
+            parameters are predefined:
+
+             'strict' - raise a ValueError (or a subclass)
+             'ignore' - ignore the character and continue with the next
+             'replace'- replace with a suitable replacement character;
+
+            The set of allowed parameter values can be extended via
+            register_error.
+        """
+        self.stream = stream
+        self.errors = errors
+        self.bytebuffer = ""
+        # For str->str decoding this will stay a str
+        # For str->unicode decoding the first read will promote it to unicode
+        self.charbuffer = ""
+        self.linebuffer = None
+
+    def decode(self, input, errors='strict'):
+        raise NotImplementedError
+
+    def read(self, size=-1, chars=-1, firstline=False):
+
+        """ Decodes data from the stream self.stream and returns the
+            resulting object.
+
+            chars indicates the number of characters to read from the
+            stream. read() will never return more than chars
+            characters, but it might return less, if there are not enough
+            characters available.
+
+            size indicates the approximate maximum number of bytes to
+            read from the stream for decoding purposes. The decoder
+            can modify this setting as appropriate. The default value
+            -1 indicates to read and decode as much as possible.  size
+            is intended to prevent having to decode huge files in one
+            step.
+
+            If firstline is true, and a UnicodeDecodeError happens
+            after the first line terminator in the input only the first line
+            will be returned, the rest of the input will be kept until the
+            next call to read().
+
+            The method should use a greedy read strategy meaning that
+            it should read as much data as is allowed within the
+            definition of the encoding and the given size, e.g.  if
+            optional encoding endings or state markers are available
+            on the stream, these should be read too.
+        """
+        # If we have lines cached, first merge them back into characters
+        if self.linebuffer:
+            self.charbuffer = "".join(self.linebuffer)
+            self.linebuffer = None
+
+        # read until we get the required number of characters (if available)
+        while True:
+            # can the request can be satisfied from the character buffer?
+            if chars < 0:
+                if size < 0:
+                    if self.charbuffer:
+                        break
+                elif len(self.charbuffer) >= size:
+                    break
+            else:
+                if len(self.charbuffer) >= chars:
+                    break
+            # we need more data
+            if size < 0:
+                newdata = self.stream.read()
+            else:
+                newdata = self.stream.read(size)
+            # decode bytes (those remaining from the last call included)
+            data = self.bytebuffer + newdata
+            try:
+                newchars, decodedbytes = self.decode(data, self.errors)
+            except UnicodeDecodeError, exc:
+                if firstline:
+                    newchars, decodedbytes = self.decode(data[:exc.start], self.errors)
+                    lines = newchars.splitlines(True)
+                    if len(lines)<=1:
+                        raise
+                else:
+                    raise
+            # keep undecoded bytes until the next call
+            self.bytebuffer = data[decodedbytes:]
+            # put new characters in the character buffer
+            self.charbuffer += newchars
+            # there was no data available
+            if not newdata:
+                break
+        if chars < 0:
+            # Return everything we've got
+            result = self.charbuffer
+            self.charbuffer = ""
+        else:
+            # Return the first chars characters
+            result = self.charbuffer[:chars]
+            self.charbuffer = self.charbuffer[chars:]
+        return result
+
+    def readline(self, size=None, keepends=True):
+
+        """ Read one line from the input stream and return the
+            decoded data.
+
+            size, if given, is passed as size argument to the
+            read() method.
+
+        """
+        # If we have lines cached from an earlier read, return
+        # them unconditionally
+        if self.linebuffer:
+            line = self.linebuffer[0]
+            del self.linebuffer[0]
+            if len(self.linebuffer) == 1:
+                # revert to charbuffer mode; we might need more data
+                # next time
+                self.charbuffer = self.linebuffer[0]
+                self.linebuffer = None
+            if not keepends:
+                line = line.splitlines(False)[0]
+            return line
+
+        readsize = size or 72
+        line = ""
+        # If size is given, we call read() only once
+        while True:
+            data = self.read(readsize, firstline=True)
+            if data:
+                # If we're at a "\r" read one extra character (which might
+                # be a "\n") to get a proper line ending. If the stream is
+                # temporarily exhausted we return the wrong line ending.
+                if data.endswith("\r"):
+                    data += self.read(size=1, chars=1)
+
+            line += data
+            lines = line.splitlines(True)
+            if lines:
+                if len(lines) > 1:
+                    # More than one line result; the first line is a full line
+                    # to return
+                    line = lines[0]
+                    del lines[0]
+                    if len(lines) > 1:
+                        # cache the remaining lines
+                        lines[-1] += self.charbuffer
+                        self.linebuffer = lines
+                        self.charbuffer = None
+                    else:
+                        # only one remaining line, put it back into charbuffer
+                        self.charbuffer = lines[0] + self.charbuffer
+                    if not keepends:
+                        line = line.splitlines(False)[0]
+                    break
+                line0withend = lines[0]
+                line0withoutend = lines[0].splitlines(False)[0]
+                if line0withend != line0withoutend: # We really have a line end
+                    # Put the rest back together and keep it until the next call
+                    self.charbuffer = "".join(lines[1:]) + self.charbuffer
+                    if keepends:
+                        line = line0withend
+                    else:
+                        line = line0withoutend
+                    break
+            # we didn't get anything or this was our only try
+            if not data or size is not None:
+                if line and not keepends:
+                    line = line.splitlines(False)[0]
+                break
+            if readsize<8000:
+                readsize *= 2
+        return line
+
+    def readlines(self, sizehint=None, keepends=True):
+
+        """ Read all lines available on the input stream
+            and return them as list of lines.
+
+            Line breaks are implemented using the codec's decoder
+            method and are included in the list entries.
+
+            sizehint, if given, is ignored since there is no efficient
+            way to finding the true end-of-line.
+
+        """
+        data = self.read()
+        return data.splitlines(keepends)
+
+    def reset(self):
+
+        """ Resets the codec buffers used for keeping state.
+
+            Note that no stream repositioning should take place.
+            This method is primarily intended to be able to recover
+            from decoding errors.
+
+        """
+        self.bytebuffer = ""
+        self.charbuffer = u""
+        self.linebuffer = None
+
+    def seek(self, offset, whence=0):
+        """ Set the input stream's current position.
+
+            Resets the codec buffers used for keeping state.
+        """
+        self.stream.seek(offset, whence)
+        self.reset()
+
+    def next(self):
+
+        """ Return the next decoded line from the input stream."""
+        line = self.readline()
+        if line:
+            return line
+        raise StopIteration
+
+    def __iter__(self):
+        return self
+
+    def __getattr__(self, name,
+                    getattr=getattr):
+
+        """ Inherit all other methods from the underlying stream.
+        """
+        return getattr(self.stream, name)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, tb):
+        self.stream.close()
+
+###
+
+class StreamReaderWriter:
+
+    """ StreamReaderWriter instances allow wrapping streams which
+        work in both read and write modes.
+
+        The design is such that one can use the factory functions
+        returned by the codec.lookup() function to construct the
+        instance.
+
+    """
+    # Optional attributes set by the file wrappers below
+    encoding = 'unknown'
+
+    def __init__(self, stream, Reader, Writer, errors='strict'):
+
+        """ Creates a StreamReaderWriter instance.
+
+            stream must be a Stream-like object.
+
+            Reader, Writer must be factory functions or classes
+            providing the StreamReader, StreamWriter interface resp.
+
+            Error handling is done in the same way as defined for the
+            StreamWriter/Readers.
+
+        """
+        self.stream = stream
+        self.reader = Reader(stream, errors)
+        self.writer = Writer(stream, errors)
+        self.errors = errors
+
+    def read(self, size=-1):
+
+        return self.reader.read(size)
+
+    def readline(self, size=None):
+
+        return self.reader.readline(size)
+
+    def readlines(self, sizehint=None):
+
+        return self.reader.readlines(sizehint)
+
+    def next(self):
+
+        """ Return the next decoded line from the input stream."""
+        return self.reader.next()
+
+    def __iter__(self):
+        return self
+
+    def write(self, data):
+
+        return self.writer.write(data)
+
+    def writelines(self, list):
+
+        return self.writer.writelines(list)
+
+    def reset(self):
+
+        self.reader.reset()
+        self.writer.reset()
+
+    def seek(self, offset, whence=0):
+        self.stream.seek(offset, whence)
+        self.reader.reset()
+        if whence == 0 and offset == 0:
+            self.writer.reset()
+
+    def __getattr__(self, name,
+                    getattr=getattr):
+
+        """ Inherit all other methods from the underlying stream.
+        """
+        return getattr(self.stream, name)
+
+    # these are needed to make "with codecs.open(...)" work properly
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, tb):
+        self.stream.close()
+
+###
+
+class StreamRecoder:
+
+    """ StreamRecoder instances provide a frontend - backend
+        view of encoding data.
+
+        They use the complete set of APIs returned by the
+        codecs.lookup() function to implement their task.
+
+        Data written to the stream is first decoded into an
+        intermediate format (which is dependent on the given codec
+        combination) and then written to the stream using an instance
+        of the provided Writer class.
+
+        In the other direction, data is read from the stream using a
+        Reader instance and then return encoded data to the caller.
+
+    """
+    # Optional attributes set by the file wrappers below
+    data_encoding = 'unknown'
+    file_encoding = 'unknown'
+
+    def __init__(self, stream, encode, decode, Reader, Writer,
+                 errors='strict'):
+
+        """ Creates a StreamRecoder instance which implements a two-way
+            conversion: encode and decode work on the frontend (the
+            input to .read() and output of .write()) while
+            Reader and Writer work on the backend (reading and
+            writing to the stream).
+
+            You can use these objects to do transparent direct
+            recodings from e.g. latin-1 to utf-8 and back.
+
+            stream must be a file-like object.
+
+            encode, decode must adhere to the Codec interface, Reader,
+            Writer must be factory functions or classes providing the
+            StreamReader, StreamWriter interface resp.
+
+            encode and decode are needed for the frontend translation,
+            Reader and Writer for the backend translation. Unicode is
+            used as intermediate encoding.
+
+            Error handling is done in the same way as defined for the
+            StreamWriter/Readers.
+
+        """
+        self.stream = stream
+        self.encode = encode
+        self.decode = decode
+        self.reader = Reader(stream, errors)
+        self.writer = Writer(stream, errors)
+        self.errors = errors
+
+    def read(self, size=-1):
+
+        data = self.reader.read(size)
+        data, bytesencoded = self.encode(data, self.errors)
+        return data
+
+    def readline(self, size=None):
+
+        if size is None:
+            data = self.reader.readline()
+        else:
+            data = self.reader.readline(size)
+        data, bytesencoded = self.encode(data, self.errors)
+        return data
+
+    def readlines(self, sizehint=None):
+
+        data = self.reader.read()
+        data, bytesencoded = self.encode(data, self.errors)
+        return data.splitlines(1)
+
+    def next(self):
+
+        """ Return the next decoded line from the input stream."""
+        data = self.reader.next()
+        data, bytesencoded = self.encode(data, self.errors)
+        return data
+
+    def __iter__(self):
+        return self
+
+    def write(self, data):
+
+        data, bytesdecoded = self.decode(data, self.errors)
+        return self.writer.write(data)
+
+    def writelines(self, list):
+
+        data = ''.join(list)
+        data, bytesdecoded = self.decode(data, self.errors)
+        return self.writer.write(data)
+
+    def reset(self):
+
+        self.reader.reset()
+        self.writer.reset()
+
+    def __getattr__(self, name,
+                    getattr=getattr):
+
+        """ Inherit all other methods from the underlying stream.
+        """
+        return getattr(self.stream, name)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, tb):
+        self.stream.close()
+
+### Shortcuts
+
+def open(filename, mode='rb', encoding=None, errors='strict', buffering=1):
+
+    """ Open an encoded file using the given mode and return
+        a wrapped version providing transparent encoding/decoding.
+
+        Note: The wrapped version will only accept the object format
+        defined by the codecs, i.e. Unicode objects for most builtin
+        codecs. Output is also codec dependent and will usually be
+        Unicode as well.
+
+        Files are always opened in binary mode, even if no binary mode
+        was specified. This is done to avoid data loss due to encodings
+        using 8-bit values. The default file mode is 'rb' meaning to
+        open the file in binary read mode.
+
+        encoding specifies the encoding which is to be used for the
+        file.
+
+        errors may be given to define the error handling. It defaults
+        to 'strict' which causes ValueErrors to be raised in case an
+        encoding error occurs.
+
+        buffering has the same meaning as for the builtin open() API.
+        It defaults to line buffered.
+
+        The returned wrapped file object provides an extra attribute
+        .encoding which allows querying the used encoding. This
+        attribute is only available if an encoding was specified as
+        parameter.
+
+    """
+    if encoding is not None:
+        if 'U' in mode:
+            # No automatic conversion of '\n' is done on reading and writing
+            mode = mode.strip().replace('U', '')
+            if mode[:1] not in set('rwa'):
+                mode = 'r' + mode
+        if 'b' not in mode:
+            # Force opening of the file in binary mode
+            mode = mode + 'b'
+    file = __builtin__.open(filename, mode, buffering)
+    if encoding is None:
+        return file
+    info = lookup(encoding)
+    srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors)
+    # Add attributes to simplify introspection
+    srw.encoding = encoding
+    return srw
+
+def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'):
+
+    """ Return a wrapped version of file which provides transparent
+        encoding translation.
+
+        Strings written to the wrapped file are interpreted according
+        to the given data_encoding and then written to the original
+        file as string using file_encoding. The intermediate encoding
+        will usually be Unicode but depends on the specified codecs.
+
+        Strings are read from the file using file_encoding and then
+        passed back to the caller as string using data_encoding.
+
+        If file_encoding is not given, it defaults to data_encoding.
+
+        errors may be given to define the error handling. It defaults
+        to 'strict' which causes ValueErrors to be raised in case an
+        encoding error occurs.
+
+        The returned wrapped file object provides two extra attributes
+        .data_encoding and .file_encoding which reflect the given
+        parameters of the same name. The attributes can be used for
+        introspection by Python programs.
+
+    """
+    if file_encoding is None:
+        file_encoding = data_encoding
+    data_info = lookup(data_encoding)
+    file_info = lookup(file_encoding)
+    sr = StreamRecoder(file, data_info.encode, data_info.decode,
+                       file_info.streamreader, file_info.streamwriter, errors)
+    # Add attributes to simplify introspection
+    sr.data_encoding = data_encoding
+    sr.file_encoding = file_encoding
+    return sr
+
+### Helpers for codec lookup
+
+def getencoder(encoding):
+
+    """ Lookup up the codec for the given encoding and return
+        its encoder function.
+
+        Raises a LookupError in case the encoding cannot be found.
+
+    """
+    return lookup(encoding).encode
+
+def getdecoder(encoding):
+
+    """ Lookup up the codec for the given encoding and return
+        its decoder function.
+
+        Raises a LookupError in case the encoding cannot be found.
+
+    """
+    return lookup(encoding).decode
+
+def getincrementalencoder(encoding):
+
+    """ Lookup up the codec for the given encoding and return
+        its IncrementalEncoder class or factory function.
+
+        Raises a LookupError in case the encoding cannot be found
+        or the codecs doesn't provide an incremental encoder.
+
+    """
+    encoder = lookup(encoding).incrementalencoder
+    if encoder is None:
+        raise LookupError(encoding)
+    return encoder
+
+def getincrementaldecoder(encoding):
+
+    """ Lookup up the codec for the given encoding and return
+        its IncrementalDecoder class or factory function.
+
+        Raises a LookupError in case the encoding cannot be found
+        or the codecs doesn't provide an incremental decoder.
+
+    """
+    decoder = lookup(encoding).incrementaldecoder
+    if decoder is None:
+        raise LookupError(encoding)
+    return decoder
+
+def getreader(encoding):
+
+    """ Lookup up the codec for the given encoding and return
+        its StreamReader class or factory function.
+
+        Raises a LookupError in case the encoding cannot be found.
+
+    """
+    return lookup(encoding).streamreader
+
+def getwriter(encoding):
+
+    """ Lookup up the codec for the given encoding and return
+        its StreamWriter class or factory function.
+
+        Raises a LookupError in case the encoding cannot be found.
+
+    """
+    return lookup(encoding).streamwriter
+
+def iterencode(iterator, encoding, errors='strict', **kwargs):
+    """
+    Encoding iterator.
+
+    Encodes the input strings from the iterator using a IncrementalEncoder.
+
+    errors and kwargs are passed through to the IncrementalEncoder
+    constructor.
+    """
+    encoder = getincrementalencoder(encoding)(errors, **kwargs)
+    for input in iterator:
+        output = encoder.encode(input)
+        if output:
+            yield output
+    output = encoder.encode("", True)
+    if output:
+        yield output
+
+def iterdecode(iterator, encoding, errors='strict', **kwargs):
+    """
+    Decoding iterator.
+
+    Decodes the input strings from the iterator using a IncrementalDecoder.
+
+    errors and kwargs are passed through to the IncrementalDecoder
+    constructor.
+    """
+    decoder = getincrementaldecoder(encoding)(errors, **kwargs)
+    for input in iterator:
+        output = decoder.decode(input)
+        if output:
+            yield output
+    output = decoder.decode("", True)
+    if output:
+        yield output
+
+### Helpers for charmap-based codecs
+
+def make_identity_dict(rng):
+
+    """ make_identity_dict(rng) -> dict
+
+        Return a dictionary where elements of the rng sequence are
+        mapped to themselves.
+
+    """
+    res = {}
+    for i in rng:
+        res[i]=i
+    return res
+
+def make_encoding_map(decoding_map):
+
+    """ Creates an encoding map from a decoding map.
+
+        If a target mapping in the decoding map occurs multiple
+        times, then that target is mapped to None (undefined mapping),
+        causing an exception when encountered by the charmap codec
+        during translation.
+
+        One example where this happens is cp875.py which decodes
+        multiple character to \u001a.
+
+    """
+    m = {}
+    for k,v in decoding_map.items():
+        if not v in m:
+            m[v] = k
+        else:
+            m[v] = None
+    return m
+
+### error handlers
+
+try:
+    strict_errors = lookup_error("strict")
+    ignore_errors = lookup_error("ignore")
+    replace_errors = lookup_error("replace")
+    xmlcharrefreplace_errors = lookup_error("xmlcharrefreplace")
+    backslashreplace_errors = lookup_error("backslashreplace")
+except LookupError:
+    # In --disable-unicode builds, these error handler are missing
+    strict_errors = None
+    ignore_errors = None
+    replace_errors = None
+    xmlcharrefreplace_errors = None
+    backslashreplace_errors = None
+
+# Tell modulefinder that using codecs probably needs the encodings
+# package
+_false = 0
+if _false:
+    import encodings
+
+### Tests
+
+if __name__ == '__main__':
+
+    # Make stdout translate Latin-1 output into UTF-8 output
+    sys.stdout = EncodedFile(sys.stdout, 'latin-1', 'utf-8')
+
+    # Have stdin translate Latin-1 input into UTF-8 input
+    sys.stdin = EncodedFile(sys.stdin, 'utf-8', 'latin-1')
diff --git a/src/main/resources/PythonLibs/codeop.py b/src/main/resources/PythonLibs/codeop.py
new file mode 100644
index 0000000000000000000000000000000000000000..5c9f5e0b14797da31ff3bc6b198d69db7d3adff8
--- /dev/null
+++ b/src/main/resources/PythonLibs/codeop.py
@@ -0,0 +1,134 @@
+r"""Utilities to compile possibly incomplete Python source code.
+
+This module provides two interfaces, broadly similar to the builtin
+function compile(), that take progam text, a filename and a 'mode'
+and:
+
+- Return a code object if the command is complete and valid
+- Return None if the command is incomplete
+- Raise SyntaxError, ValueError or OverflowError if the command is a
+  syntax error (OverflowError and ValueError can be produced by
+  malformed literals).
+
+Approach:
+
+First, check if the source consists entirely of blank lines and
+comments; if so, replace it with 'pass', because the built-in
+parser doesn't always do the right thing for these.
+
+Compile three times: as is, with \n, and with \n\n appended.  If it
+compiles as is, it's complete.  If it compiles with one \n appended,
+we expect more.  If it doesn't compile either way, we compare the
+error we get when compiling with \n or \n\n appended.  If the errors
+are the same, the code is broken.  But if the errors are different, we
+expect more.  Not intuitive; not even guaranteed to hold in future
+releases; but this matches the compiler's behavior from Python 1.4
+through 2.2, at least.
+
+Caveat:
+
+It is possible (but not likely) that the parser stops parsing with a
+successful outcome before reaching the end of the source; in this
+case, trailing symbols may be ignored instead of causing an error.
+For example, a backslash followed by two newlines may be followed by
+arbitrary garbage.  This will be fixed once the API for the parser is
+better.
+
+The two interfaces are:
+
+compile_command(source, filename, symbol):
+
+    Compiles a single command in the manner described above.
+
+CommandCompiler():
+
+    Instances of this class have __call__ methods identical in
+    signature to compile_command; the difference is that if the
+    instance compiles program text containing a __future__ statement,
+    the instance 'remembers' and compiles all subsequent program texts
+    with the statement in force.
+
+The module also provides another class:
+
+Compile():
+
+    Instances of this class act like the built-in function compile,
+    but with 'memory' in the sense described above.
+"""
+
+# import internals, not guaranteed interface
+from org.python.core import Py,CompilerFlags,CompileMode
+from org.python.core.CompilerFlags import PyCF_DONT_IMPLY_DEDENT
+
+# public interface
+
+__all__ = ["compile_command", "Compile", "CommandCompiler"]
+
+def compile_command(source, filename="<input>", symbol="single"):
+    r"""Compile a command and determine whether it is incomplete.
+
+    Arguments:
+
+    source -- the source string; may contain \n characters
+    filename -- optional filename from which source was read; default
+                "<input>"
+    symbol -- optional grammar start symbol; "single" (default) or "eval"
+
+    Return value / exceptions raised:
+
+    - Return a code object if the command is complete and valid
+    - Return None if the command is incomplete
+    - Raise SyntaxError, ValueError or OverflowError if the command is a
+      syntax error (OverflowError and ValueError can be produced by
+      malformed literals).
+    """
+    if symbol not in ['single','eval']:
+        raise ValueError,"symbol arg must be either single or eval"
+    symbol = CompileMode.getMode(symbol)
+    return Py.compile_command_flags(source,filename,symbol,Py.getCompilerFlags(),0)
+
+class Compile:
+    """Instances of this class behave much like the built-in compile
+    function, but if one is used to compile text containing a future
+    statement, it "remembers" and compiles all subsequent program texts
+    with the statement in force."""
+    def __init__(self):
+        self._cflags = CompilerFlags()
+
+    def __call__(self, source, filename, symbol):
+        symbol = CompileMode.getMode(symbol)
+        return Py.compile_flags(source, filename, symbol, self._cflags)
+
+class CommandCompiler:
+    """Instances of this class have __call__ methods identical in
+    signature to compile_command; the difference is that if the
+    instance compiles program text containing a __future__ statement,
+    the instance 'remembers' and compiles all subsequent program texts
+    with the statement in force."""
+
+    def __init__(self,):
+        self._cflags = CompilerFlags()
+
+    def __call__(self, source, filename="<input>", symbol="single"):
+        r"""Compile a command and determine whether it is incomplete.
+
+        Arguments:
+
+        source -- the source string; may contain \n characters
+        filename -- optional filename from which source was read;
+                    default "<input>"
+        symbol -- optional grammar start symbol; "single" (default) or
+                  "eval"
+
+        Return value / exceptions raised:
+
+        - Return a code object if the command is complete and valid
+        - Return None if the command is incomplete
+        - Raise SyntaxError, ValueError or OverflowError if the command is a
+          syntax error (OverflowError and ValueError can be produced by
+          malformed literals).
+        """
+        if symbol not in ['single','eval']:
+            raise ValueError,"symbol arg must be either single or eval"
+        symbol = CompileMode.getMode(symbol)
+        return Py.compile_command_flags(source,filename,symbol,self._cflags,0)
diff --git a/src/main/resources/PythonLibs/collections.py b/src/main/resources/PythonLibs/collections.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0922412d7fd553680588efbf911c529e5b3af73
--- /dev/null
+++ b/src/main/resources/PythonLibs/collections.py
@@ -0,0 +1,695 @@
+__all__ = ['Counter', 'deque', 'defaultdict', 'namedtuple', 'OrderedDict']
+# For bootstrapping reasons, the collection ABCs are defined in _abcoll.py.
+# They should however be considered an integral part of collections.py.
+from _abcoll import *
+import _abcoll
+__all__ += _abcoll.__all__
+
+from _collections import deque, defaultdict
+from operator import itemgetter as _itemgetter, eq as _eq
+from keyword import iskeyword as _iskeyword
+import sys as _sys
+import heapq as _heapq
+from itertools import repeat as _repeat, chain as _chain, starmap as _starmap
+from itertools import imap as _imap
+
+try:
+    from thread import get_ident as _get_ident
+except ImportError:
+    from dummy_thread import get_ident as _get_ident
+
+
+################################################################################
+### OrderedDict
+################################################################################
+
+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 regular dictionaries.
+
+    # The internal self.__map dict 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.  The signature is the same as
+        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 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]
+        return 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 gets
+        # 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                        # update link_prev[NEXT]
+        link_next[0] = link_prev                        # update link_next[PREV]
+
+    def __iter__(self):
+        'od.__iter__() <==> iter(od)'
+        # Traverse the linked list in order.
+        root = self.__root
+        curr = root[1]                                  # start at the first node
+        while curr is not root:
+            yield curr[2]                               # yield the curr[KEY]
+            curr = curr[1]                              # move to next node
+
+    def __reversed__(self):
+        'od.__reversed__() <==> reversed(od)'
+        # Traverse the linked list in reverse order.
+        root = self.__root
+        curr = root[0]                                  # start at the last node
+        while curr is not root:
+            yield curr[2]                               # yield the curr[KEY]
+            curr = curr[0]                              # move to previous node
+
+    def clear(self):
+        'od.clear() -> None.  Remove all items from od.'
+        root = self.__root
+        root[:] = [root, root, None]
+        self.__map.clear()
+        dict.clear(self)
+
+    # -- 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) pairs in od'
+        for k in self:
+            yield (k, self[k])
+
+    update = MutableMapping.update
+
+    __update = update # let subclasses override update without breaking __init__
+
+    __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 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')
+        key = next(reversed(self) if last else iter(self))
+        value = self.pop(key)
+        return key, value
+
+    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__, 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.
+        If not specified, the value defaults to None.
+
+        '''
+        self = cls()
+        for key in iterable:
+            self[key] = value
+        return self
+
+    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 dict.__eq__(self, other) and all(_imap(_eq, self, other))
+        return dict.__eq__(self, other)
+
+    def __ne__(self, other):
+        'od.__ne__(y) <==> od!=y'
+        return not self == other
+
+    # -- the following methods support python 3.x style dictionary views --
+
+    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)
+
+
+################################################################################
+### namedtuple
+################################################################################
+
+_class_template = '''\
+class {typename}(tuple):
+    '{typename}({arg_list})'
+
+    __slots__ = ()
+
+    _fields = {field_names!r}
+
+    def __new__(_cls, {arg_list}):
+        'Create new instance of {typename}({arg_list})'
+        return _tuple.__new__(_cls, ({arg_list}))
+
+    @classmethod
+    def _make(cls, iterable, new=tuple.__new__, len=len):
+        'Make a new {typename} object from a sequence or iterable'
+        result = new(cls, iterable)
+        if len(result) != {num_fields:d}:
+            raise TypeError('Expected {num_fields:d} arguments, got %d' % len(result))
+        return result
+
+    def __repr__(self):
+        'Return a nicely formatted representation string'
+        return '{typename}({repr_fmt})' % self
+
+    def _asdict(self):
+        'Return a new OrderedDict which maps field names to their values'
+        return OrderedDict(zip(self._fields, self))
+
+    __dict__ = property(_asdict)
+
+    def _replace(_self, **kwds):
+        'Return a new {typename} object replacing specified fields with new values'
+        result = _self._make(map(kwds.pop, {field_names!r}, _self))
+        if kwds:
+            raise ValueError('Got unexpected field names: %r' % kwds.keys())
+        return result
+
+    def __getnewargs__(self):
+        'Return self as a plain tuple.  Used by copy and pickle.'
+        return tuple(self)
+
+{field_defs}
+'''
+
+_repr_template = '{name}=%r'
+
+_field_template = '''\
+    {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}')
+'''
+
+def namedtuple(typename, field_names, verbose=False, rename=False):
+    """Returns a new subclass of tuple with named fields.
+
+    >>> Point = namedtuple('Point', ['x', 'y'])
+    >>> Point.__doc__                   # docstring for the new class
+    'Point(x, y)'
+    >>> p = Point(11, y=22)             # instantiate with positional args or keywords
+    >>> p[0] + p[1]                     # indexable like a plain tuple
+    33
+    >>> x, y = p                        # unpack like a regular tuple
+    >>> x, y
+    (11, 22)
+    >>> p.x + p.y                       # fields also accessable by name
+    33
+    >>> d = p._asdict()                 # convert to a dictionary
+    >>> d['x']
+    11
+    >>> Point(**d)                      # convert from a dictionary
+    Point(x=11, y=22)
+    >>> p._replace(x=100)               # _replace() is like str.replace() but targets named fields
+    Point(x=100, y=22)
+
+    """
+
+    # Validate the field names.  At the user's option, either generate an error
+    # message or automatically replace the field name with a valid name.
+    if isinstance(field_names, basestring):
+        field_names = field_names.replace(',', ' ').split()
+    field_names = map(str, field_names)
+    if rename:
+        seen = set()
+        for index, name in enumerate(field_names):
+            if (not all(c.isalnum() or c=='_' for c in name)
+                or _iskeyword(name)
+                or not name
+                or name[0].isdigit()
+                or name.startswith('_')
+                or name in seen):
+                field_names[index] = '_%d' % index
+            seen.add(name)
+    for name in [typename] + field_names:
+        if not all(c.isalnum() or c=='_' for c in name):
+            raise ValueError('Type names and field names can only contain '
+                             'alphanumeric characters and underscores: %r' % name)
+        if _iskeyword(name):
+            raise ValueError('Type names and field names cannot be a '
+                             'keyword: %r' % name)
+        if name[0].isdigit():
+            raise ValueError('Type names and field names cannot start with '
+                             'a number: %r' % name)
+    seen = set()
+    for name in field_names:
+        if name.startswith('_') and not rename:
+            raise ValueError('Field names cannot start with an underscore: '
+                             '%r' % name)
+        if name in seen:
+            raise ValueError('Encountered duplicate field name: %r' % name)
+        seen.add(name)
+
+    # Fill-in the class template
+    class_definition = _class_template.format(
+        typename = typename,
+        field_names = tuple(field_names),
+        num_fields = len(field_names),
+        arg_list = repr(tuple(field_names)).replace("'", "")[1:-1],
+        repr_fmt = ', '.join(_repr_template.format(name=name)
+                             for name in field_names),
+        field_defs = '\n'.join(_field_template.format(index=index, name=name)
+                               for index, name in enumerate(field_names))
+    )
+    if verbose:
+        print class_definition
+
+    # Execute the template string in a temporary namespace and support
+    # tracing utilities by setting a value for frame.f_globals['__name__']
+    namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
+                     OrderedDict=OrderedDict, _property=property, _tuple=tuple)
+    try:
+        exec class_definition in namespace
+    except SyntaxError as e:
+        raise SyntaxError(e.message + ':\n' + class_definition)
+    result = namespace[typename]
+
+    # For pickling to work, the __module__ variable needs to be set to the frame
+    # where the named tuple is created.  Bypass this step in enviroments where
+    # sys._getframe is not defined (Jython for example) or sys._getframe is not
+    # defined for arguments greater than 0 (IronPython).
+    try:
+        result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
+    except (AttributeError, ValueError):
+        pass
+
+    return result
+
+
+########################################################################
+###  Counter
+########################################################################
+
+class Counter(dict):
+    '''Dict subclass for counting hashable items.  Sometimes called a bag
+    or multiset.  Elements are stored as dictionary keys and their counts
+    are stored as dictionary values.
+
+    >>> c = Counter('abcdeabcdabcaba')  # count elements from a string
+
+    >>> c.most_common(3)                # three most common elements
+    [('a', 5), ('b', 4), ('c', 3)]
+    >>> sorted(c)                       # list all unique elements
+    ['a', 'b', 'c', 'd', 'e']
+    >>> ''.join(sorted(c.elements()))   # list elements with repetitions
+    'aaaaabbbbcccdde'
+    >>> sum(c.values())                 # total of all counts
+    15
+
+    >>> c['a']                          # count of letter 'a'
+    5
+    >>> for elem in 'shazam':           # update counts from an iterable
+    ...     c[elem] += 1                # by adding 1 to each element's count
+    >>> c['a']                          # now there are seven 'a'
+    7
+    >>> del c['b']                      # remove all 'b'
+    >>> c['b']                          # now there are zero 'b'
+    0
+
+    >>> d = Counter('simsalabim')       # make another counter
+    >>> c.update(d)                     # add in the second counter
+    >>> c['a']                          # now there are nine 'a'
+    9
+
+    >>> c.clear()                       # empty the counter
+    >>> c
+    Counter()
+
+    Note:  If a count is set to zero or reduced to zero, it will remain
+    in the counter until the entry is deleted or the counter is cleared:
+
+    >>> c = Counter('aaabbc')
+    >>> c['b'] -= 2                     # reduce the count of 'b' by two
+    >>> c.most_common()                 # 'b' is still in, but its count is zero
+    [('a', 3), ('c', 1), ('b', 0)]
+
+    '''
+    # References:
+    #   http://en.wikipedia.org/wiki/Multiset
+    #   http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
+    #   http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
+    #   http://code.activestate.com/recipes/259174/
+    #   Knuth, TAOCP Vol. II section 4.6.3
+
+    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
+
+        '''
+        super(Counter, self).__init__()
+        self.update(iterable, **kwds)
+
+    def __missing__(self, key):
+        'The count of elements not in the Counter is zero.'
+        # Needed so that self[missing_item] does not raise KeyError
+        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('abcdeabcdabcaba').most_common(3)
+        [('a', 5), ('b', 4), ('c', 3)]
+
+        '''
+        # Emulate Bag.sortedByCount from Smalltalk
+        if n is None:
+            return sorted(self.iteritems(), key=_itemgetter(1), reverse=True)
+        return _heapq.nlargest(n, self.iteritems(), 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']
+
+        # Knuth's example for prime factors of 1836:  2**2 * 3**3 * 17**1
+        >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
+        >>> product = 1
+        >>> for factor in prime_factors.elements():     # loop over factors
+        ...     product *= factor                       # and multiply them
+        >>> product
+        1836
+
+        Note, if an element's count has been set to zero or is a negative
+        number, elements() will ignore it.
+
+        '''
+        # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
+        return _chain.from_iterable(_starmap(_repeat, self.iteritems()))
+
+    # Override dict methods where necessary
+
+    @classmethod
+    def fromkeys(cls, iterable, v=None):
+        # There is no equivalent method for counters because setting v=1
+        # means that no element can have a count greater than one.
+        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
+
+        '''
+        # The regular dict.update() operation makes no sense here because the
+        # replace behavior results in the some of original untouched counts
+        # being mixed-in with all of the other counts for a mismash that
+        # doesn't have a straight-forward interpretation in most counting
+        # contexts.  Instead, we implement straight-addition.  Both the inputs
+        # and outputs are allowed to contain zero and negative counts.
+
+        if iterable is not None:
+            if isinstance(iterable, Mapping):
+                if self:
+                    self_get = self.get
+                    for elem, count in iterable.iteritems():
+                        self[elem] = self_get(elem, 0) + count
+                else:
+                    super(Counter, self).update(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 subtract(self, iterable=None, **kwds):
+        '''Like dict.update() but subtracts counts instead of replacing them.
+        Counts can be reduced below zero.  Both the inputs and outputs are
+        allowed to contain zero and negative counts.
+
+        Source can be an iterable, a dictionary, or another Counter instance.
+
+        >>> c = Counter('which')
+        >>> c.subtract('witch')             # subtract elements from another iterable
+        >>> c.subtract(Counter('watch'))    # subtract elements from another counter
+        >>> c['h']                          # 2 in which, minus 1 in witch, minus 1 in watch
+        0
+        >>> c['w']                          # 1 in which, minus 1 in witch, minus 1 in watch
+        -1
+
+        '''
+        if iterable is not None:
+            self_get = self.get
+            if isinstance(iterable, Mapping):
+                for elem, count in iterable.items():
+                    self[elem] = self_get(elem, 0) - count
+            else:
+                for elem in iterable:
+                    self[elem] = self_get(elem, 0) - 1
+        if kwds:
+            self.subtract(kwds)
+
+    def copy(self):
+        'Return a shallow copy.'
+        return self.__class__(self)
+
+    def __reduce__(self):
+        return self.__class__, (dict(self),)
+
+    def __delitem__(self, elem):
+        'Like dict.__delitem__() but does not raise KeyError for missing values.'
+        if elem in self:
+            super(Counter, self).__delitem__(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, count in self.items():
+            newcount = count + other[elem]
+            if newcount > 0:
+                result[elem] = newcount
+        for elem, count in other.items():
+            if elem not in self and count > 0:
+                result[elem] = count
+        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, count in self.items():
+            newcount = count - other[elem]
+            if newcount > 0:
+                result[elem] = newcount
+        for elem, count in other.items():
+            if elem not in self and count < 0:
+                result[elem] = 0 - count
+        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
+        result = Counter()
+        for elem, count in self.items():
+            other_count = other[elem]
+            newcount = other_count if count < other_count else count
+            if newcount > 0:
+                result[elem] = newcount
+        for elem, count in other.items():
+            if elem not in self and count > 0:
+                result[elem] = count
+        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
+        result = Counter()
+        for elem, count in self.items():
+            other_count = other[elem]
+            newcount = count if count < other_count else other_count
+            if newcount > 0:
+                result[elem] = newcount
+        return result
+
+
+if __name__ == '__main__':
+    # verify that instances can be pickled
+    from cPickle import loads, dumps
+    Point = namedtuple('Point', 'x, y', True)
+    p = Point(x=10, y=20)
+    assert p == loads(dumps(p))
+
+    # test and demonstrate ability to override methods
+    class Point(namedtuple('Point', 'x y')):
+        __slots__ = ()
+        @property
+        def hypot(self):
+            return (self.x ** 2 + self.y ** 2) ** 0.5
+        def __str__(self):
+            return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)
+
+    for p in Point(3, 4), Point(14, 5/7.):
+        print p
+
+    class Point(namedtuple('Point', 'x y')):
+        'Point class with optimized _make() and _replace() without error-checking'
+        __slots__ = ()
+        _make = classmethod(tuple.__new__)
+        def _replace(self, _map=map, **kwds):
+            return self._make(_map(kwds.get, ('x', 'y'), self))
+
+    print Point(11, 22)._replace(x=100)
+
+    Point3D = namedtuple('Point3D', Point._fields + ('z',))
+    print Point3D.__doc__
+
+    import doctest
+    TestResults = namedtuple('TestResults', 'failed attempted')
+    print TestResults(*doctest.testmod())
diff --git a/src/main/resources/PythonLibs/colorsys.py b/src/main/resources/PythonLibs/colorsys.py
new file mode 100644
index 0000000000000000000000000000000000000000..a6c0cf6a4639e73e3aee9d66a52619d74dfb0d45
--- /dev/null
+++ b/src/main/resources/PythonLibs/colorsys.py
@@ -0,0 +1,156 @@
+"""Conversion functions between RGB and other color systems.
+
+This modules provides two functions for each color system ABC:
+
+  rgb_to_abc(r, g, b) --> a, b, c
+  abc_to_rgb(a, b, c) --> r, g, b
+
+All inputs and outputs are triples of floats in the range [0.0...1.0]
+(with the exception of I and Q, which covers a slightly larger range).
+Inputs outside the valid range may cause exceptions or invalid outputs.
+
+Supported color systems:
+RGB: Red, Green, Blue components
+YIQ: Luminance, Chrominance (used by composite video signals)
+HLS: Hue, Luminance, Saturation
+HSV: Hue, Saturation, Value
+"""
+
+# References:
+# http://en.wikipedia.org/wiki/YIQ
+# http://en.wikipedia.org/wiki/HLS_color_space
+# http://en.wikipedia.org/wiki/HSV_color_space
+
+__all__ = ["rgb_to_yiq","yiq_to_rgb","rgb_to_hls","hls_to_rgb",
+           "rgb_to_hsv","hsv_to_rgb"]
+
+# Some floating point constants
+
+ONE_THIRD = 1.0/3.0
+ONE_SIXTH = 1.0/6.0
+TWO_THIRD = 2.0/3.0
+
+# YIQ: used by composite video signals (linear combinations of RGB)
+# Y: perceived grey level (0.0 == black, 1.0 == white)
+# I, Q: color components
+
+def rgb_to_yiq(r, g, b):
+    y = 0.30*r + 0.59*g + 0.11*b
+    i = 0.60*r - 0.28*g - 0.32*b
+    q = 0.21*r - 0.52*g + 0.31*b
+    return (y, i, q)
+
+def yiq_to_rgb(y, i, q):
+    r = y + 0.948262*i + 0.624013*q
+    g = y - 0.276066*i - 0.639810*q
+    b = y - 1.105450*i + 1.729860*q
+    if r < 0.0:
+        r = 0.0
+    if g < 0.0:
+        g = 0.0
+    if b < 0.0:
+        b = 0.0
+    if r > 1.0:
+        r = 1.0
+    if g > 1.0:
+        g = 1.0
+    if b > 1.0:
+        b = 1.0
+    return (r, g, b)
+
+
+# HLS: Hue, Luminance, Saturation
+# H: position in the spectrum
+# L: color lightness
+# S: color saturation
+
+def rgb_to_hls(r, g, b):
+    maxc = max(r, g, b)
+    minc = min(r, g, b)
+    # XXX Can optimize (maxc+minc) and (maxc-minc)
+    l = (minc+maxc)/2.0
+    if minc == maxc:
+        return 0.0, l, 0.0
+    if l <= 0.5:
+        s = (maxc-minc) / (maxc+minc)
+    else:
+        s = (maxc-minc) / (2.0-maxc-minc)
+    rc = (maxc-r) / (maxc-minc)
+    gc = (maxc-g) / (maxc-minc)
+    bc = (maxc-b) / (maxc-minc)
+    if r == maxc:
+        h = bc-gc
+    elif g == maxc:
+        h = 2.0+rc-bc
+    else:
+        h = 4.0+gc-rc
+    h = (h/6.0) % 1.0
+    return h, l, s
+
+def hls_to_rgb(h, l, s):
+    if s == 0.0:
+        return l, l, l
+    if l <= 0.5:
+        m2 = l * (1.0+s)
+    else:
+        m2 = l+s-(l*s)
+    m1 = 2.0*l - m2
+    return (_v(m1, m2, h+ONE_THIRD), _v(m1, m2, h), _v(m1, m2, h-ONE_THIRD))
+
+def _v(m1, m2, hue):
+    hue = hue % 1.0
+    if hue < ONE_SIXTH:
+        return m1 + (m2-m1)*hue*6.0
+    if hue < 0.5:
+        return m2
+    if hue < TWO_THIRD:
+        return m1 + (m2-m1)*(TWO_THIRD-hue)*6.0
+    return m1
+
+
+# HSV: Hue, Saturation, Value
+# H: position in the spectrum
+# S: color saturation ("purity")
+# V: color brightness
+
+def rgb_to_hsv(r, g, b):
+    maxc = max(r, g, b)
+    minc = min(r, g, b)
+    v = maxc
+    if minc == maxc:
+        return 0.0, 0.0, v
+    s = (maxc-minc) / maxc
+    rc = (maxc-r) / (maxc-minc)
+    gc = (maxc-g) / (maxc-minc)
+    bc = (maxc-b) / (maxc-minc)
+    if r == maxc:
+        h = bc-gc
+    elif g == maxc:
+        h = 2.0+rc-bc
+    else:
+        h = 4.0+gc-rc
+    h = (h/6.0) % 1.0
+    return h, s, v
+
+def hsv_to_rgb(h, s, v):
+    if s == 0.0:
+        return v, v, v
+    i = int(h*6.0) # XXX assume int() truncates!
+    f = (h*6.0) - i
+    p = v*(1.0 - s)
+    q = v*(1.0 - s*f)
+    t = v*(1.0 - s*(1.0-f))
+    i = i%6
+    if i == 0:
+        return v, t, p
+    if i == 1:
+        return q, v, p
+    if i == 2:
+        return p, v, t
+    if i == 3:
+        return p, q, v
+    if i == 4:
+        return t, p, v
+    if i == 5:
+        return v, p, q
+    # Cannot get here
diff --git a/src/main/resources/PythonLibs/commands.py b/src/main/resources/PythonLibs/commands.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0e8dd5fe930105085a283e7aa38dc00e1582a99
--- /dev/null
+++ b/src/main/resources/PythonLibs/commands.py
@@ -0,0 +1,90 @@
+"""Execute shell commands via os.popen() and return status, output.
+
+Interface summary:
+
+       import commands
+
+       outtext = commands.getoutput(cmd)
+       (exitstatus, outtext) = commands.getstatusoutput(cmd)
+       outtext = commands.getstatus(file)  # returns output of "ls -ld file"
+
+A trailing newline is removed from the output string.
+
+Encapsulates the basic operation:
+
+      pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
+      text = pipe.read()
+      sts = pipe.close()
+
+ [Note:  it would be nice to add functions to interpret the exit status.]
+"""
+from warnings import warnpy3k
+warnpy3k("the commands module has been removed in Python 3.0; "
+         "use the subprocess module instead", stacklevel=2)
+del warnpy3k
+
+__all__ = ["getstatusoutput","getoutput","getstatus"]
+
+# Module 'commands'
+#
+# Various tools for executing commands and looking at their output and status.
+#
+# NB This only works (and is only relevant) for UNIX.
+
+
+# Get 'ls -l' status for an object into a string
+#
+def getstatus(file):
+    """Return output of "ls -ld <file>" in a string."""
+    import warnings
+    warnings.warn("commands.getstatus() is deprecated", DeprecationWarning, 2)
+    return getoutput('ls -ld' + mkarg(file))
+
+
+# Get the output from a shell command into a string.
+# The exit status is ignored; a trailing newline is stripped.
+# Assume the command will work with '{ ... ; } 2>&1' around it..
+#
+def getoutput(cmd):
+    """Return output (stdout or stderr) of executing cmd in a shell."""
+    return getstatusoutput(cmd)[1]
+
+
+# Ditto but preserving the exit status.
+# Returns a pair (sts, output)
+#
+def getstatusoutput(cmd):
+    """Return (status, output) of executing cmd in a shell."""
+    import os
+    pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
+    text = pipe.read()
+    sts = pipe.close()
+    if sts is None: sts = 0
+    if text[-1:] == '\n': text = text[:-1]
+    return sts, text
+
+
+# Make command argument from directory and pathname (prefix space, add quotes).
+#
+def mk2arg(head, x):
+    import os
+    return mkarg(os.path.join(head, x))
+
+
+# Make a shell command argument from a string.
+# Return a string beginning with a space followed by a shell-quoted
+# version of the argument.
+# Two strategies: enclose in single quotes if it contains none;
+# otherwise, enclose in double quotes and prefix quotable characters
+# with backslash.
+#
+def mkarg(x):
+    if '\'' not in x:
+        return ' \'' + x + '\''
+    s = ' "'
+    for c in x:
+        if c in '\\$"`':
+            s = s + '\\'
+        s = s + c
+    s = s + '"'
+    return s
diff --git a/src/main/resources/PythonLibs/compileall.py b/src/main/resources/PythonLibs/compileall.py
new file mode 100644
index 0000000000000000000000000000000000000000..5cfa8bed3f9fa509df5d60360cddf5d5cdd0b3f0
--- /dev/null
+++ b/src/main/resources/PythonLibs/compileall.py
@@ -0,0 +1,227 @@
+"""Module/script to byte-compile all .py files to .pyc (or .pyo) files.
+
+When called as a script with arguments, this compiles the directories
+given as arguments recursively; the -l option prevents it from
+recursing into directories.
+
+Without arguments, if compiles all modules on sys.path, without
+recursing into subdirectories.  (Even though it should do so for
+packages -- for now, you'll have to deal with packages separately.)
+
+See module py_compile for details of the actual byte-compilation.
+"""
+import os
+import sys
+import py_compile
+import struct
+import imp
+
+__all__ = ["compile_dir","compile_file","compile_path"]
+
+def compile_dir(dir, maxlevels=10, ddir=None,
+                force=0, rx=None, quiet=0):
+    """Byte-compile all modules in the given directory tree.
+
+    Arguments (only dir is required):
+
+    dir:       the directory to byte-compile
+    maxlevels: maximum recursion level (default 10)
+    ddir:      the directory that will be prepended to the path to the
+               file as it is compiled into each byte-code file.
+    force:     if 1, force compilation, even if timestamps are up-to-date
+    quiet:     if 1, be quiet during compilation
+    """
+    if not quiet:
+        print 'Listing', dir, '...'
+    try:
+        names = os.listdir(dir)
+    except os.error:
+        print "Can't list", dir
+        names = []
+    names.sort()
+    success = 1
+    for name in names:
+        fullname = os.path.join(dir, name)
+        if ddir is not None:
+            dfile = os.path.join(ddir, name)
+        else:
+            dfile = None
+        if not os.path.isdir(fullname):
+            if not compile_file(fullname, ddir, force, rx, quiet):
+                success = 0
+        elif maxlevels > 0 and \
+             name != os.curdir and name != os.pardir and \
+             os.path.isdir(fullname) and \
+             not os.path.islink(fullname):
+            if not compile_dir(fullname, maxlevels - 1, dfile, force, rx,
+                               quiet):
+                success = 0
+    return success
+
+def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):
+    """Byte-compile one file.
+
+    Arguments (only fullname is required):
+
+    fullname:  the file to byte-compile
+    ddir:      if given, the directory name compiled in to the
+               byte-code file.
+    force:     if 1, force compilation, even if timestamps are up-to-date
+    quiet:     if 1, be quiet during compilation
+    """
+    success = 1
+    name = os.path.basename(fullname)
+    if ddir is not None:
+        dfile = os.path.join(ddir, name)
+    else:
+        dfile = None
+    if rx is not None:
+        mo = rx.search(fullname)
+        if mo:
+            return success
+    if os.path.isfile(fullname):
+        head, tail = name[:-3], name[-3:]
+        if tail == '.py':
+            if not force:
+                try:
+                    mtime = int(os.stat(fullname).st_mtime)
+                    expect = struct.pack('<4sl', imp.get_magic(), mtime)
+                    cfile = fullname + (__debug__ and 'c' or 'o')
+                    with open(cfile, 'rb') as chandle:
+                        actual = chandle.read(8)
+                    if expect == actual:
+                        return success
+                except IOError:
+                    pass
+            if not quiet:
+                print 'Compiling', fullname, '...'
+            try:
+                ok = py_compile.compile(fullname, None, dfile, True)
+            except py_compile.PyCompileError,err:
+                if quiet:
+                    print 'Compiling', fullname, '...'
+                print err.msg
+                success = 0
+            except IOError, e:
+                print "Sorry", e
+                success = 0
+            else:
+                if ok == 0:
+                    success = 0
+    return success
+
+def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0):
+    """Byte-compile all module on sys.path.
+
+    Arguments (all optional):
+
+    skip_curdir: if true, skip current directory (default true)
+    maxlevels:   max recursion level (default 0)
+    force: as for compile_dir() (default 0)
+    quiet: as for compile_dir() (default 0)
+    """
+    success = 1
+    for dir in sys.path:
+        if (not dir or dir == os.curdir) and skip_curdir:
+            print 'Skipping current directory'
+        else:
+            success = success and compile_dir(dir, maxlevels, None,
+                                              force, quiet=quiet)
+    return success
+
+def expand_args(args, flist):
+    """read names in flist and append to args"""
+    expanded = args[:]
+    if flist:
+        try:
+            if flist == '-':
+                fd = sys.stdin
+            else:
+                fd = open(flist)
+            while 1:
+                line = fd.readline()
+                if not line:
+                    break
+                expanded.append(line[:-1])
+        except IOError:
+            print "Error reading file list %s" % flist
+            raise
+    return expanded
+
+def main():
+    """Script main program."""
+    import getopt
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:')
+    except getopt.error, msg:
+        print msg
+        print "usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \
+              "[-x regexp] [-i list] [directory|file ...]"
+        print
+        print "arguments: zero or more file and directory names to compile; " \
+              "if no arguments given, "
+        print "           defaults to the equivalent of -l sys.path"
+        print
+        print "options:"
+        print "-l: don't recurse into subdirectories"
+        print "-f: force rebuild even if timestamps are up-to-date"
+        print "-q: output only error messages"
+        print "-d destdir: directory to prepend to file paths for use in " \
+              "compile-time tracebacks and in"
+        print "            runtime tracebacks in cases where the source " \
+              "file is unavailable"
+        print "-x regexp: skip files matching the regular expression regexp; " \
+              "the regexp is searched for"
+        print "           in the full path of each file considered for " \
+              "compilation"
+        print "-i file: add all the files and directories listed in file to " \
+              "the list considered for"
+        print '         compilation; if "-", names are read from stdin'
+
+        sys.exit(2)
+    maxlevels = 10
+    ddir = None
+    force = 0
+    quiet = 0
+    rx = None
+    flist = None
+    for o, a in opts:
+        if o == '-l': maxlevels = 0
+        if o == '-d': ddir = a
+        if o == '-f': force = 1
+        if o == '-q': quiet = 1
+        if o == '-x':
+            import re
+            rx = re.compile(a)
+        if o == '-i': flist = a
+    if ddir:
+        if len(args) != 1 and not os.path.isdir(args[0]):
+            print "-d destdir require exactly one directory argument"
+            sys.exit(2)
+    success = 1
+    try:
+        if args or flist:
+            try:
+                if flist:
+                    args = expand_args(args, flist)
+            except IOError:
+                success = 0
+            if success:
+                for arg in args:
+                    if os.path.isdir(arg):
+                        if not compile_dir(arg, maxlevels, ddir,
+                                           force, rx, quiet):
+                            success = 0
+                    else:
+                        if not compile_file(arg, ddir, force, rx, quiet):
+                            success = 0
+        else:
+            success = compile_path()
+    except KeyboardInterrupt:
+        print "\n[interrupted]"
+        success = 0
+    return success
+
+if __name__ == '__main__':
+    exit_status = int(not main())
+    sys.exit(exit_status)
diff --git a/src/main/resources/PythonLibs/compiler/__init__.py b/src/main/resources/PythonLibs/compiler/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..2a6f64fa5092dce6221c3f6bdeebdfefbc2d3249
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/__init__.py
@@ -0,0 +1,31 @@
+"""Package for parsing and compiling Python source code
+
+There are several functions defined at the top level that are imported
+from modules contained in the package.
+
+parse(buf, mode="exec") -> AST
+    Converts a string containing Python source code to an abstract
+    syntax tree (AST).  The AST is defined in compiler.ast.
+
+parseFile(path) -> AST
+    The same as parse(open(path))
+
+walk(ast, visitor, verbose=None)
+    Does a pre-order walk over the ast using the visitor instance.
+    See compiler.visitor for details.
+
+compile(source, filename, mode, flags=None, dont_inherit=None)
+    Returns a code object.  A replacement for the builtin compile() function.
+
+compileFile(filename)
+    Generates a .pyc file by compiling filename.
+"""
+
+import warnings
+
+warnings.warn("The compiler package is deprecated and removed in Python 3.x.",
+              DeprecationWarning, stacklevel=2)
+
+from compiler.transformer import parse, parseFile
+from compiler.visitor import walk
+from compiler.pycodegen import compile, compileFile
diff --git a/src/main/resources/PythonLibs/compiler/ast.py b/src/main/resources/PythonLibs/compiler/ast.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c3fc161d39f9faabfa6a390f0b281669f321096
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/ast.py
@@ -0,0 +1,1419 @@
+"""Python abstract syntax node definitions
+
+This file is automatically generated by Tools/compiler/astgen.py
+"""
+from compiler.consts import CO_VARARGS, CO_VARKEYWORDS
+
+def flatten(seq):
+    l = []
+    for elt in seq:
+        t = type(elt)
+        if t is tuple or t is list:
+            for elt2 in flatten(elt):
+                l.append(elt2)
+        else:
+            l.append(elt)
+    return l
+
+def flatten_nodes(seq):
+    return [n for n in flatten(seq) if isinstance(n, Node)]
+
+nodes = {}
+
+class Node:
+    """Abstract base class for ast nodes."""
+    def getChildren(self):
+        pass # implemented by subclasses
+    def __iter__(self):
+        for n in self.getChildren():
+            yield n
+    def asList(self): # for backwards compatibility
+        return self.getChildren()
+    def getChildNodes(self):
+        pass # implemented by subclasses
+
+class EmptyNode(Node):
+    pass
+
+class Expression(Node):
+    # Expression is an artificial node class to support "eval"
+    nodes["expression"] = "Expression"
+    def __init__(self, node):
+        self.node = node
+
+    def getChildren(self):
+        return self.node,
+
+    def getChildNodes(self):
+        return self.node,
+
+    def __repr__(self):
+        return "Expression(%s)" % (repr(self.node))
+
+class Add(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Add((%s, %s))" % (repr(self.left), repr(self.right))
+
+class And(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "And(%s)" % (repr(self.nodes),)
+
+class AssAttr(Node):
+    def __init__(self, expr, attrname, flags, lineno=None):
+        self.expr = expr
+        self.attrname = attrname
+        self.flags = flags
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.expr, self.attrname, self.flags
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags))
+
+class AssList(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "AssList(%s)" % (repr(self.nodes),)
+
+class AssName(Node):
+    def __init__(self, name, flags, lineno=None):
+        self.name = name
+        self.flags = flags
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.name, self.flags
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "AssName(%s, %s)" % (repr(self.name), repr(self.flags))
+
+class AssTuple(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "AssTuple(%s)" % (repr(self.nodes),)
+
+class Assert(Node):
+    def __init__(self, test, fail, lineno=None):
+        self.test = test
+        self.fail = fail
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.test)
+        children.append(self.fail)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.test)
+        if self.fail is not None:
+            nodelist.append(self.fail)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Assert(%s, %s)" % (repr(self.test), repr(self.fail))
+
+class Assign(Node):
+    def __init__(self, nodes, expr, lineno=None):
+        self.nodes = nodes
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        children.append(self.expr)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        nodelist.append(self.expr)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr))
+
+class AugAssign(Node):
+    def __init__(self, node, op, expr, lineno=None):
+        self.node = node
+        self.op = op
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.node, self.op, self.expr
+
+    def getChildNodes(self):
+        return self.node, self.expr
+
+    def __repr__(self):
+        return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr))
+
+class Backquote(Node):
+    def __init__(self, expr, lineno=None):
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Backquote(%s)" % (repr(self.expr),)
+
+class Bitand(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Bitand(%s)" % (repr(self.nodes),)
+
+class Bitor(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Bitor(%s)" % (repr(self.nodes),)
+
+class Bitxor(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Bitxor(%s)" % (repr(self.nodes),)
+
+class Break(Node):
+    def __init__(self, lineno=None):
+        self.lineno = lineno
+
+    def getChildren(self):
+        return ()
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Break()"
+
+class CallFunc(Node):
+    def __init__(self, node, args, star_args = None, dstar_args = None, lineno=None):
+        self.node = node
+        self.args = args
+        self.star_args = star_args
+        self.dstar_args = dstar_args
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.node)
+        children.extend(flatten(self.args))
+        children.append(self.star_args)
+        children.append(self.dstar_args)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.node)
+        nodelist.extend(flatten_nodes(self.args))
+        if self.star_args is not None:
+            nodelist.append(self.star_args)
+        if self.dstar_args is not None:
+            nodelist.append(self.dstar_args)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args))
+
+class Class(Node):
+    def __init__(self, name, bases, doc, code, decorators = None, lineno=None):
+        self.name = name
+        self.bases = bases
+        self.doc = doc
+        self.code = code
+        self.decorators = decorators
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.name)
+        children.extend(flatten(self.bases))
+        children.append(self.doc)
+        children.append(self.code)
+        children.append(self.decorators)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.bases))
+        nodelist.append(self.code)
+        if self.decorators is not None:
+            nodelist.append(self.decorators)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Class(%s, %s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code), repr(self.decorators))
+
+class Compare(Node):
+    def __init__(self, expr, ops, lineno=None):
+        self.expr = expr
+        self.ops = ops
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.extend(flatten(self.ops))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        nodelist.extend(flatten_nodes(self.ops))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops))
+
+class Const(Node):
+    def __init__(self, value, lineno=None):
+        self.value = value
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.value,
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Const(%s)" % (repr(self.value),)
+
+class Continue(Node):
+    def __init__(self, lineno=None):
+        self.lineno = lineno
+
+    def getChildren(self):
+        return ()
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Continue()"
+
+class Decorators(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Decorators(%s)" % (repr(self.nodes),)
+
+class Dict(Node):
+    def __init__(self, items, lineno=None):
+        self.items = items
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.items))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.items))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Dict(%s)" % (repr(self.items),)
+
+class Discard(Node):
+    def __init__(self, expr, lineno=None):
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Discard(%s)" % (repr(self.expr),)
+
+class Div(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Div((%s, %s))" % (repr(self.left), repr(self.right))
+
+class Ellipsis(Node):
+    def __init__(self, lineno=None):
+        self.lineno = lineno
+
+    def getChildren(self):
+        return ()
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Ellipsis()"
+
+class Exec(Node):
+    def __init__(self, expr, locals, globals, lineno=None):
+        self.expr = expr
+        self.locals = locals
+        self.globals = globals
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.append(self.locals)
+        children.append(self.globals)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        if self.locals is not None:
+            nodelist.append(self.locals)
+        if self.globals is not None:
+            nodelist.append(self.globals)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals))
+
+class FloorDiv(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right))
+
+class For(Node):
+    def __init__(self, assign, list, body, else_, lineno=None):
+        self.assign = assign
+        self.list = list
+        self.body = body
+        self.else_ = else_
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.assign)
+        children.append(self.list)
+        children.append(self.body)
+        children.append(self.else_)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.assign)
+        nodelist.append(self.list)
+        nodelist.append(self.body)
+        if self.else_ is not None:
+            nodelist.append(self.else_)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_))
+
+class From(Node):
+    def __init__(self, modname, names, level, lineno=None):
+        self.modname = modname
+        self.names = names
+        self.level = level
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.modname, self.names, self.level
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
+
+class Function(Node):
+    def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None):
+        self.decorators = decorators
+        self.name = name
+        self.argnames = argnames
+        self.defaults = defaults
+        self.flags = flags
+        self.doc = doc
+        self.code = code
+        self.lineno = lineno
+        self.varargs = self.kwargs = None
+        if flags & CO_VARARGS:
+            self.varargs = 1
+        if flags & CO_VARKEYWORDS:
+            self.kwargs = 1
+
+
+    def getChildren(self):
+        children = []
+        children.append(self.decorators)
+        children.append(self.name)
+        children.append(self.argnames)
+        children.extend(flatten(self.defaults))
+        children.append(self.flags)
+        children.append(self.doc)
+        children.append(self.code)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        if self.decorators is not None:
+            nodelist.append(self.decorators)
+        nodelist.extend(flatten_nodes(self.defaults))
+        nodelist.append(self.code)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code))
+
+class GenExpr(Node):
+    def __init__(self, code, lineno=None):
+        self.code = code
+        self.lineno = lineno
+        self.argnames = ['.0']
+        self.varargs = self.kwargs = None
+
+
+    def getChildren(self):
+        return self.code,
+
+    def getChildNodes(self):
+        return self.code,
+
+    def __repr__(self):
+        return "GenExpr(%s)" % (repr(self.code),)
+
+class GenExprFor(Node):
+    def __init__(self, assign, iter, ifs, lineno=None):
+        self.assign = assign
+        self.iter = iter
+        self.ifs = ifs
+        self.lineno = lineno
+        self.is_outmost = False
+
+    def getChildren(self):
+        children = []
+        children.append(self.assign)
+        children.append(self.iter)
+        children.extend(flatten(self.ifs))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.assign)
+        nodelist.append(self.iter)
+        nodelist.extend(flatten_nodes(self.ifs))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs))
+
+class GenExprIf(Node):
+    def __init__(self, test, lineno=None):
+        self.test = test
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.test,
+
+    def getChildNodes(self):
+        return self.test,
+
+    def __repr__(self):
+        return "GenExprIf(%s)" % (repr(self.test),)
+
+class GenExprInner(Node):
+    def __init__(self, expr, quals, lineno=None):
+        self.expr = expr
+        self.quals = quals
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.extend(flatten(self.quals))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        nodelist.extend(flatten_nodes(self.quals))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals))
+
+class Getattr(Node):
+    def __init__(self, expr, attrname, lineno=None):
+        self.expr = expr
+        self.attrname = attrname
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.expr, self.attrname
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname))
+
+class Global(Node):
+    def __init__(self, names, lineno=None):
+        self.names = names
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.names,
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Global(%s)" % (repr(self.names),)
+
+class If(Node):
+    def __init__(self, tests, else_, lineno=None):
+        self.tests = tests
+        self.else_ = else_
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.tests))
+        children.append(self.else_)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.tests))
+        if self.else_ is not None:
+            nodelist.append(self.else_)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "If(%s, %s)" % (repr(self.tests), repr(self.else_))
+
+class IfExp(Node):
+    def __init__(self, test, then, else_, lineno=None):
+        self.test = test
+        self.then = then
+        self.else_ = else_
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.test, self.then, self.else_
+
+    def getChildNodes(self):
+        return self.test, self.then, self.else_
+
+    def __repr__(self):
+        return "IfExp(%s, %s, %s)" % (repr(self.test), repr(self.then), repr(self.else_))
+
+class Import(Node):
+    def __init__(self, names, lineno=None):
+        self.names = names
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.names,
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Import(%s)" % (repr(self.names),)
+
+class Invert(Node):
+    def __init__(self, expr, lineno=None):
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Invert(%s)" % (repr(self.expr),)
+
+class Keyword(Node):
+    def __init__(self, name, expr, lineno=None):
+        self.name = name
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.name, self.expr
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
+
+class Lambda(Node):
+    def __init__(self, argnames, defaults, flags, code, lineno=None):
+        self.argnames = argnames
+        self.defaults = defaults
+        self.flags = flags
+        self.code = code
+        self.lineno = lineno
+        self.varargs = self.kwargs = None
+        if flags & CO_VARARGS:
+            self.varargs = 1
+        if flags & CO_VARKEYWORDS:
+            self.kwargs = 1
+
+
+    def getChildren(self):
+        children = []
+        children.append(self.argnames)
+        children.extend(flatten(self.defaults))
+        children.append(self.flags)
+        children.append(self.code)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.defaults))
+        nodelist.append(self.code)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code))
+
+class LeftShift(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right))
+
+class List(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "List(%s)" % (repr(self.nodes),)
+
+class ListComp(Node):
+    def __init__(self, expr, quals, lineno=None):
+        self.expr = expr
+        self.quals = quals
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.extend(flatten(self.quals))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        nodelist.extend(flatten_nodes(self.quals))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals))
+
+class ListCompFor(Node):
+    def __init__(self, assign, list, ifs, lineno=None):
+        self.assign = assign
+        self.list = list
+        self.ifs = ifs
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.assign)
+        children.append(self.list)
+        children.extend(flatten(self.ifs))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.assign)
+        nodelist.append(self.list)
+        nodelist.extend(flatten_nodes(self.ifs))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs))
+
+class ListCompIf(Node):
+    def __init__(self, test, lineno=None):
+        self.test = test
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.test,
+
+    def getChildNodes(self):
+        return self.test,
+
+    def __repr__(self):
+        return "ListCompIf(%s)" % (repr(self.test),)
+
+class SetComp(Node):
+    def __init__(self, expr, quals, lineno=None):
+        self.expr = expr
+        self.quals = quals
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.extend(flatten(self.quals))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        nodelist.extend(flatten_nodes(self.quals))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "SetComp(%s, %s)" % (repr(self.expr), repr(self.quals))
+
+class DictComp(Node):
+    def __init__(self, key, value, quals, lineno=None):
+        self.key = key
+        self.value = value
+        self.quals = quals
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.key)
+        children.append(self.value)
+        children.extend(flatten(self.quals))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.key)
+        nodelist.append(self.value)
+        nodelist.extend(flatten_nodes(self.quals))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "DictComp(%s, %s, %s)" % (repr(self.key), repr(self.value), repr(self.quals))
+
+class Mod(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Mod((%s, %s))" % (repr(self.left), repr(self.right))
+
+class Module(Node):
+    def __init__(self, doc, node, lineno=None):
+        self.doc = doc
+        self.node = node
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.doc, self.node
+
+    def getChildNodes(self):
+        return self.node,
+
+    def __repr__(self):
+        return "Module(%s, %s)" % (repr(self.doc), repr(self.node))
+
+class Mul(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Mul((%s, %s))" % (repr(self.left), repr(self.right))
+
+class Name(Node):
+    def __init__(self, name, lineno=None):
+        self.name = name
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.name,
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Name(%s)" % (repr(self.name),)
+
+class Not(Node):
+    def __init__(self, expr, lineno=None):
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Not(%s)" % (repr(self.expr),)
+
+class Or(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Or(%s)" % (repr(self.nodes),)
+
+class Pass(Node):
+    def __init__(self, lineno=None):
+        self.lineno = lineno
+
+    def getChildren(self):
+        return ()
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Pass()"
+
+class Power(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Power((%s, %s))" % (repr(self.left), repr(self.right))
+
+class Print(Node):
+    def __init__(self, nodes, dest, lineno=None):
+        self.nodes = nodes
+        self.dest = dest
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        children.append(self.dest)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        if self.dest is not None:
+            nodelist.append(self.dest)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest))
+
+class Printnl(Node):
+    def __init__(self, nodes, dest, lineno=None):
+        self.nodes = nodes
+        self.dest = dest
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        children.append(self.dest)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        if self.dest is not None:
+            nodelist.append(self.dest)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest))
+
+class Raise(Node):
+    def __init__(self, expr1, expr2, expr3, lineno=None):
+        self.expr1 = expr1
+        self.expr2 = expr2
+        self.expr3 = expr3
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr1)
+        children.append(self.expr2)
+        children.append(self.expr3)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        if self.expr1 is not None:
+            nodelist.append(self.expr1)
+        if self.expr2 is not None:
+            nodelist.append(self.expr2)
+        if self.expr3 is not None:
+            nodelist.append(self.expr3)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3))
+
+class Return(Node):
+    def __init__(self, value, lineno=None):
+        self.value = value
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.value,
+
+    def getChildNodes(self):
+        return self.value,
+
+    def __repr__(self):
+        return "Return(%s)" % (repr(self.value),)
+
+class RightShift(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "RightShift((%s, %s))" % (repr(self.left), repr(self.right))
+
+class Set(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Set(%s)" % (repr(self.nodes),)
+
+class Slice(Node):
+    def __init__(self, expr, flags, lower, upper, lineno=None):
+        self.expr = expr
+        self.flags = flags
+        self.lower = lower
+        self.upper = upper
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.append(self.flags)
+        children.append(self.lower)
+        children.append(self.upper)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        if self.lower is not None:
+            nodelist.append(self.lower)
+        if self.upper is not None:
+            nodelist.append(self.upper)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper))
+
+class Sliceobj(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Sliceobj(%s)" % (repr(self.nodes),)
+
+class Stmt(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Stmt(%s)" % (repr(self.nodes),)
+
+class Sub(Node):
+    def __init__(self, leftright, lineno=None):
+        self.left = leftright[0]
+        self.right = leftright[1]
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Sub((%s, %s))" % (repr(self.left), repr(self.right))
+
+class Subscript(Node):
+    def __init__(self, expr, flags, subs, lineno=None):
+        self.expr = expr
+        self.flags = flags
+        self.subs = subs
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.append(self.flags)
+        children.extend(flatten(self.subs))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        nodelist.extend(flatten_nodes(self.subs))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs))
+
+class TryExcept(Node):
+    def __init__(self, body, handlers, else_, lineno=None):
+        self.body = body
+        self.handlers = handlers
+        self.else_ = else_
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.body)
+        children.extend(flatten(self.handlers))
+        children.append(self.else_)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.body)
+        nodelist.extend(flatten_nodes(self.handlers))
+        if self.else_ is not None:
+            nodelist.append(self.else_)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_))
+
+class TryFinally(Node):
+    def __init__(self, body, final, lineno=None):
+        self.body = body
+        self.final = final
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.body, self.final
+
+    def getChildNodes(self):
+        return self.body, self.final
+
+    def __repr__(self):
+        return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final))
+
+class Tuple(Node):
+    def __init__(self, nodes, lineno=None):
+        self.nodes = nodes
+        self.lineno = lineno
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Tuple(%s)" % (repr(self.nodes),)
+
+class UnaryAdd(Node):
+    def __init__(self, expr, lineno=None):
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "UnaryAdd(%s)" % (repr(self.expr),)
+
+class UnarySub(Node):
+    def __init__(self, expr, lineno=None):
+        self.expr = expr
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "UnarySub(%s)" % (repr(self.expr),)
+
+class While(Node):
+    def __init__(self, test, body, else_, lineno=None):
+        self.test = test
+        self.body = body
+        self.else_ = else_
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.test)
+        children.append(self.body)
+        children.append(self.else_)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.test)
+        nodelist.append(self.body)
+        if self.else_ is not None:
+            nodelist.append(self.else_)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_))
+
+class With(Node):
+    def __init__(self, expr, vars, body, lineno=None):
+        self.expr = expr
+        self.vars = vars
+        self.body = body
+        self.lineno = lineno
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.append(self.vars)
+        children.append(self.body)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        if self.vars is not None:
+            nodelist.append(self.vars)
+        nodelist.append(self.body)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "With(%s, %s, %s)" % (repr(self.expr), repr(self.vars), repr(self.body))
+
+class Yield(Node):
+    def __init__(self, value, lineno=None):
+        self.value = value
+        self.lineno = lineno
+
+    def getChildren(self):
+        return self.value,
+
+    def getChildNodes(self):
+        return self.value,
+
+    def __repr__(self):
+        return "Yield(%s)" % (repr(self.value),)
+
+for name, obj in globals().items():
+    if isinstance(obj, type) and issubclass(obj, Node):
+        nodes[name.lower()] = obj
diff --git a/src/main/resources/PythonLibs/compiler/consts.py b/src/main/resources/PythonLibs/compiler/consts.py
new file mode 100644
index 0000000000000000000000000000000000000000..c60b1d0b4f6ffc5339459ae58e5e01f888a92eae
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/consts.py
@@ -0,0 +1,23 @@
+# operation flags
+OP_ASSIGN = 'OP_ASSIGN'
+OP_DELETE = 'OP_DELETE'
+OP_APPLY = 'OP_APPLY'
+
+SC_LOCAL = 1
+SC_GLOBAL_IMPLICIT = 2
+SC_GLOBAL_EXPLICIT = 3
+SC_FREE = 4
+SC_CELL = 5
+SC_UNKNOWN = 6
+
+CO_OPTIMIZED = 0x0001
+CO_NEWLOCALS = 0x0002
+CO_VARARGS = 0x0004
+CO_VARKEYWORDS = 0x0008
+CO_NESTED = 0x0010
+CO_GENERATOR = 0x0020
+CO_GENERATOR_ALLOWED = 0
+CO_FUTURE_DIVISION = 0x2000
+CO_FUTURE_ABSIMPORT = 0x4000
+CO_FUTURE_WITH_STATEMENT = 0x8000
+CO_FUTURE_PRINT_FUNCTION = 0x10000
diff --git a/src/main/resources/PythonLibs/compiler/future.py b/src/main/resources/PythonLibs/compiler/future.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd5e5dfb37427b29f1841b86cd23874e12fff6f7
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/future.py
@@ -0,0 +1,74 @@
+"""Parser for future statements
+
+"""
+
+from compiler import ast, walk
+
+def is_future(stmt):
+    """Return true if statement is a well-formed future statement"""
+    if not isinstance(stmt, ast.From):
+        return 0
+    if stmt.modname == "__future__":
+        return 1
+    else:
+        return 0
+
+class FutureParser:
+
+    features = ("nested_scopes", "generators", "division",
+                "absolute_import", "with_statement", "print_function",
+                "unicode_literals")
+
+    def __init__(self):
+        self.found = {} # set
+
+    def visitModule(self, node):
+        stmt = node.node
+        for s in stmt.nodes:
+            if not self.check_stmt(s):
+                break
+
+    def check_stmt(self, stmt):
+        if is_future(stmt):
+            for name, asname in stmt.names:
+                if name in self.features:
+                    self.found[name] = 1
+                else:
+                    raise SyntaxError, \
+                          "future feature %s is not defined" % name
+            stmt.valid_future = 1
+            return 1
+        return 0
+
+    def get_features(self):
+        """Return list of features enabled by future statements"""
+        return self.found.keys()
+
+class BadFutureParser:
+    """Check for invalid future statements"""
+
+    def visitFrom(self, node):
+        if hasattr(node, 'valid_future'):
+            return
+        if node.modname != "__future__":
+            return
+        raise SyntaxError, "invalid future statement " + repr(node)
+
+def find_futures(node):
+    p1 = FutureParser()
+    p2 = BadFutureParser()
+    walk(node, p1)
+    walk(node, p2)
+    return p1.get_features()
+
+if __name__ == "__main__":
+    import sys
+    from compiler import parseFile, walk
+
+    for file in sys.argv[1:]:
+        print file
+        tree = parseFile(file)
+        v = FutureParser()
+        walk(tree, v)
+        print v.found
+        print
diff --git a/src/main/resources/PythonLibs/compiler/misc.py b/src/main/resources/PythonLibs/compiler/misc.py
new file mode 100644
index 0000000000000000000000000000000000000000..588c7fbd5aed9ed0bce255c07c5ff8ac8436187b
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/misc.py
@@ -0,0 +1,73 @@
+
+def flatten(tup):
+    elts = []
+    for elt in tup:
+        if isinstance(elt, tuple):
+            elts = elts + flatten(elt)
+        else:
+            elts.append(elt)
+    return elts
+
+class Set:
+    def __init__(self):
+        self.elts = {}
+    def __len__(self):
+        return len(self.elts)
+    def __contains__(self, elt):
+        return elt in self.elts
+    def add(self, elt):
+        self.elts[elt] = elt
+    def elements(self):
+        return self.elts.keys()
+    def has_elt(self, elt):
+        return elt in self.elts
+    def remove(self, elt):
+        del self.elts[elt]
+    def copy(self):
+        c = Set()
+        c.elts.update(self.elts)
+        return c
+
+class Stack:
+    def __init__(self):
+        self.stack = []
+        self.pop = self.stack.pop
+    def __len__(self):
+        return len(self.stack)
+    def push(self, elt):
+        self.stack.append(elt)
+    def top(self):
+        return self.stack[-1]
+    def __getitem__(self, index): # needed by visitContinue()
+        return self.stack[index]
+
+MANGLE_LEN = 256 # magic constant from compile.c
+
+def mangle(name, klass):
+    if not name.startswith('__'):
+        return name
+    if len(name) + 2 >= MANGLE_LEN:
+        return name
+    if name.endswith('__'):
+        return name
+    try:
+        i = 0
+        while klass[i] == '_':
+            i = i + 1
+    except IndexError:
+        return name
+    klass = klass[i:]
+
+    tlen = len(klass) + len(name)
+    if tlen > MANGLE_LEN:
+        klass = klass[:MANGLE_LEN-tlen]
+
+    return "_%s%s" % (klass, name)
+
+def set_filename(filename, tree):
+    """Set the filename attribute to filename on every node in tree"""
+    worklist = [tree]
+    while worklist:
+        node = worklist.pop(0)
+        node.filename = filename
+        worklist.extend(node.getChildNodes())
diff --git a/src/main/resources/PythonLibs/compiler/pyassem.py b/src/main/resources/PythonLibs/compiler/pyassem.py
new file mode 100644
index 0000000000000000000000000000000000000000..286be0c8c7d02616d804cafbeea17912e3ccd0d8
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/pyassem.py
@@ -0,0 +1,763 @@
+"""A flow graph representation for Python bytecode"""
+
+import dis
+import types
+import sys
+
+from compiler import misc
+from compiler.consts \
+     import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS
+
+class FlowGraph:
+    def __init__(self):
+        self.current = self.entry = Block()
+        self.exit = Block("exit")
+        self.blocks = misc.Set()
+        self.blocks.add(self.entry)
+        self.blocks.add(self.exit)
+
+    def startBlock(self, block):
+        if self._debug:
+            if self.current:
+                print "end", repr(self.current)
+                print "    next", self.current.next
+                print "    prev", self.current.prev
+                print "   ", self.current.get_children()
+            print repr(block)
+        self.current = block
+
+    def nextBlock(self, block=None):
+        # XXX think we need to specify when there is implicit transfer
+        # from one block to the next.  might be better to represent this
+        # with explicit JUMP_ABSOLUTE instructions that are optimized
+        # out when they are unnecessary.
+        #
+        # I think this strategy works: each block has a child
+        # designated as "next" which is returned as the last of the
+        # children.  because the nodes in a graph are emitted in
+        # reverse post order, the "next" block will always be emitted
+        # immediately after its parent.
+        # Worry: maintaining this invariant could be tricky
+        if block is None:
+            block = self.newBlock()
+
+        # Note: If the current block ends with an unconditional control
+        # transfer, then it is techically incorrect to add an implicit
+        # transfer to the block graph. Doing so results in code generation
+        # for unreachable blocks.  That doesn't appear to be very common
+        # with Python code and since the built-in compiler doesn't optimize
+        # it out we don't either.
+        self.current.addNext(block)
+        self.startBlock(block)
+
+    def newBlock(self):
+        b = Block()
+        self.blocks.add(b)
+        return b
+
+    def startExitBlock(self):
+        self.startBlock(self.exit)
+
+    _debug = 0
+
+    def _enable_debug(self):
+        self._debug = 1
+
+    def _disable_debug(self):
+        self._debug = 0
+
+    def emit(self, *inst):
+        if self._debug:
+            print "\t", inst
+        if len(inst) == 2 and isinstance(inst[1], Block):
+            self.current.addOutEdge(inst[1])
+        self.current.emit(inst)
+
+    def getBlocksInOrder(self):
+        """Return the blocks in reverse postorder
+
+        i.e. each node appears before all of its successors
+        """
+        order = order_blocks(self.entry, self.exit)
+        return order
+
+    def getBlocks(self):
+        return self.blocks.elements()
+
+    def getRoot(self):
+        """Return nodes appropriate for use with dominator"""
+        return self.entry
+
+    def getContainedGraphs(self):
+        l = []
+        for b in self.getBlocks():
+            l.extend(b.getContainedGraphs())
+        return l
+
+
+def order_blocks(start_block, exit_block):
+    """Order blocks so that they are emitted in the right order"""
+    # Rules:
+    # - when a block has a next block, the next block must be emitted just after
+    # - when a block has followers (relative jumps), it must be emitted before
+    #   them
+    # - all reachable blocks must be emitted
+    order = []
+
+    # Find all the blocks to be emitted.
+    remaining = set()
+    todo = [start_block]
+    while todo:
+        b = todo.pop()
+        if b in remaining:
+            continue
+        remaining.add(b)
+        for c in b.get_children():
+            if c not in remaining:
+                todo.append(c)
+
+    # A block is dominated by another block if that block must be emitted
+    # before it.
+    dominators = {}
+    for b in remaining:
+        if __debug__ and b.next:
+            assert b is b.next[0].prev[0], (b, b.next)
+        # Make sure every block appears in dominators, even if no
+        # other block must precede it.
+        dominators.setdefault(b, set())
+        # preceeding blocks dominate following blocks
+        for c in b.get_followers():
+            while 1:
+                dominators.setdefault(c, set()).add(b)
+                # Any block that has a next pointer leading to c is also
+                # dominated because the whole chain will be emitted at once.
+                # Walk backwards and add them all.
+                if c.prev and c.prev[0] is not b:
+                    c = c.prev[0]
+                else:
+                    break
+
+    def find_next():
+        # Find a block that can be emitted next.
+        for b in remaining:
+            for c in dominators[b]:
+                if c in remaining:
+                    break # can't emit yet, dominated by a remaining block
+            else:
+                return b
+        assert 0, 'circular dependency, cannot find next block'
+
+    b = start_block
+    while 1:
+        order.append(b)
+        remaining.discard(b)
+        if b.next:
+            b = b.next[0]
+            continue
+        elif b is not exit_block and not b.has_unconditional_transfer():
+            order.append(exit_block)
+        if not remaining:
+            break
+        b = find_next()
+    return order
+
+
+class Block:
+    _count = 0
+
+    def __init__(self, label=''):
+        self.insts = []
+        self.outEdges = set()
+        self.label = label
+        self.bid = Block._count
+        self.next = []
+        self.prev = []
+        Block._count = Block._count + 1
+
+    def __repr__(self):
+        if self.label:
+            return "<block %s id=%d>" % (self.label, self.bid)
+        else:
+            return "<block id=%d>" % (self.bid)
+
+    def __str__(self):
+        insts = map(str, self.insts)
+        return "<block %s %d:\n%s>" % (self.label, self.bid,
+                                       '\n'.join(insts))
+
+    def emit(self, inst):
+        op = inst[0]
+        self.insts.append(inst)
+
+    def getInstructions(self):
+        return self.insts
+
+    def addOutEdge(self, block):
+        self.outEdges.add(block)
+
+    def addNext(self, block):
+        self.next.append(block)
+        assert len(self.next) == 1, map(str, self.next)
+        block.prev.append(self)
+        assert len(block.prev) == 1, map(str, block.prev)
+
+    _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS',
+                        'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP',
+                        )
+
+    def has_unconditional_transfer(self):
+        """Returns True if there is an unconditional transfer to an other block
+        at the end of this block. This means there is no risk for the bytecode
+        executer to go past this block's bytecode."""
+        try:
+            op, arg = self.insts[-1]
+        except (IndexError, ValueError):
+            return
+        return op in self._uncond_transfer
+
+    def get_children(self):
+        return list(self.outEdges) + self.next
+
+    def get_followers(self):
+        """Get the whole list of followers, including the next block."""
+        followers = set(self.next)
+        # Blocks that must be emitted *after* this one, because of
+        # bytecode offsets (e.g. relative jumps) pointing to them.
+        for inst in self.insts:
+            if inst[0] in PyFlowGraph.hasjrel:
+                followers.add(inst[1])
+        return followers
+
+    def getContainedGraphs(self):
+        """Return all graphs contained within this block.
+
+        For example, a MAKE_FUNCTION block will contain a reference to
+        the graph for the function body.
+        """
+        contained = []
+        for inst in self.insts:
+            if len(inst) == 1:
+                continue
+            op = inst[1]
+            if hasattr(op, 'graph'):
+                contained.append(op.graph)
+        return contained
+
+# flags for code objects
+
+# the FlowGraph is transformed in place; it exists in one of these states
+RAW = "RAW"
+FLAT = "FLAT"
+CONV = "CONV"
+DONE = "DONE"
+
+class PyFlowGraph(FlowGraph):
+    super_init = FlowGraph.__init__
+
+    def __init__(self, name, filename, args=(), optimized=0, klass=None):
+        self.super_init()
+        self.name = name
+        self.filename = filename
+        self.docstring = None
+        self.args = args # XXX
+        self.argcount = getArgCount(args)
+        self.klass = klass
+        if optimized:
+            self.flags = CO_OPTIMIZED | CO_NEWLOCALS
+        else:
+            self.flags = 0
+        self.consts = []
+        self.names = []
+        # Free variables found by the symbol table scan, including
+        # variables used only in nested scopes, are included here.
+        self.freevars = []
+        self.cellvars = []
+        # The closure list is used to track the order of cell
+        # variables and free variables in the resulting code object.
+        # The offsets used by LOAD_CLOSURE/LOAD_DEREF refer to both
+        # kinds of variables.
+        self.closure = []
+        self.varnames = list(args) or []
+        for i in range(len(self.varnames)):
+            var = self.varnames[i]
+            if isinstance(var, TupleArg):
+                self.varnames[i] = var.getName()
+        self.stage = RAW
+
+    def setDocstring(self, doc):
+        self.docstring = doc
+
+    def setFlag(self, flag):
+        self.flags = self.flags | flag
+        if flag == CO_VARARGS:
+            self.argcount = self.argcount - 1
+
+    def checkFlag(self, flag):
+        if self.flags & flag:
+            return 1
+
+    def setFreeVars(self, names):
+        self.freevars = list(names)
+
+    def setCellVars(self, names):
+        self.cellvars = names
+
+    def getCode(self):
+        """Get a Python code object"""
+        assert self.stage == RAW
+        self.computeStackDepth()
+        self.flattenGraph()
+        assert self.stage == FLAT
+        self.convertArgs()
+        assert self.stage == CONV
+        self.makeByteCode()
+        assert self.stage == DONE
+        return self.newCodeObject()
+
+    def dump(self, io=None):
+        if io:
+            save = sys.stdout
+            sys.stdout = io
+        pc = 0
+        for t in self.insts:
+            opname = t[0]
+            if opname == "SET_LINENO":
+                print
+            if len(t) == 1:
+                print "\t", "%3d" % pc, opname
+                pc = pc + 1
+            else:
+                print "\t", "%3d" % pc, opname, t[1]
+                pc = pc + 3
+        if io:
+            sys.stdout = save
+
+    def computeStackDepth(self):
+        """Compute the max stack depth.
+
+        Approach is to compute the stack effect of each basic block.
+        Then find the path through the code with the largest total
+        effect.
+        """
+        depth = {}
+        exit = None
+        for b in self.getBlocks():
+            depth[b] = findDepth(b.getInstructions())
+
+        seen = {}
+
+        def max_depth(b, d):
+            if b in seen:
+                return d
+            seen[b] = 1
+            d = d + depth[b]
+            children = b.get_children()
+            if children:
+                return max([max_depth(c, d) for c in children])
+            else:
+                if not b.label == "exit":
+                    return max_depth(self.exit, d)
+                else:
+                    return d
+
+        self.stacksize = max_depth(self.entry, 0)
+
+    def flattenGraph(self):
+        """Arrange the blocks in order and resolve jumps"""
+        assert self.stage == RAW
+        self.insts = insts = []
+        pc = 0
+        begin = {}
+        end = {}
+        for b in self.getBlocksInOrder():
+            begin[b] = pc
+            for inst in b.getInstructions():
+                insts.append(inst)
+                if len(inst) == 1:
+                    pc = pc + 1
+                elif inst[0] != "SET_LINENO":
+                    # arg takes 2 bytes
+                    pc = pc + 3
+            end[b] = pc
+        pc = 0
+        for i in range(len(insts)):
+            inst = insts[i]
+            if len(inst) == 1:
+                pc = pc + 1
+            elif inst[0] != "SET_LINENO":
+                pc = pc + 3
+            opname = inst[0]
+            if opname in self.hasjrel:
+                oparg = inst[1]
+                offset = begin[oparg] - pc
+                insts[i] = opname, offset
+            elif opname in self.hasjabs:
+                insts[i] = opname, begin[inst[1]]
+        self.stage = FLAT
+
+    hasjrel = set()
+    for i in dis.hasjrel:
+        hasjrel.add(dis.opname[i])
+    hasjabs = set()
+    for i in dis.hasjabs:
+        hasjabs.add(dis.opname[i])
+
+    def convertArgs(self):
+        """Convert arguments from symbolic to concrete form"""
+        assert self.stage == FLAT
+        self.consts.insert(0, self.docstring)
+        self.sort_cellvars()
+        for i in range(len(self.insts)):
+            t = self.insts[i]
+            if len(t) == 2:
+                opname, oparg = t
+                conv = self._converters.get(opname, None)
+                if conv:
+                    self.insts[i] = opname, conv(self, oparg)
+        self.stage = CONV
+
+    def sort_cellvars(self):
+        """Sort cellvars in the order of varnames and prune from freevars.
+        """
+        cells = {}
+        for name in self.cellvars:
+            cells[name] = 1
+        self.cellvars = [name for name in self.varnames
+                         if name in cells]
+        for name in self.cellvars:
+            del cells[name]
+        self.cellvars = self.cellvars + cells.keys()
+        self.closure = self.cellvars + self.freevars
+
+    def _lookupName(self, name, list):
+        """Return index of name in list, appending if necessary
+
+        This routine uses a list instead of a dictionary, because a
+        dictionary can't store two different keys if the keys have the
+        same value but different types, e.g. 2 and 2L.  The compiler
+        must treat these two separately, so it does an explicit type
+        comparison before comparing the values.
+        """
+        t = type(name)
+        for i in range(len(list)):
+            if t == type(list[i]) and list[i] == name:
+                return i
+        end = len(list)
+        list.append(name)
+        return end
+
+    _converters = {}
+    def _convert_LOAD_CONST(self, arg):
+        if hasattr(arg, 'getCode'):
+            arg = arg.getCode()
+        return self._lookupName(arg, self.consts)
+
+    def _convert_LOAD_FAST(self, arg):
+        self._lookupName(arg, self.names)
+        return self._lookupName(arg, self.varnames)
+    _convert_STORE_FAST = _convert_LOAD_FAST
+    _convert_DELETE_FAST = _convert_LOAD_FAST
+
+    def _convert_LOAD_NAME(self, arg):
+        if self.klass is None:
+            self._lookupName(arg, self.varnames)
+        return self._lookupName(arg, self.names)
+
+    def _convert_NAME(self, arg):
+        if self.klass is None:
+            self._lookupName(arg, self.varnames)
+        return self._lookupName(arg, self.names)
+    _convert_STORE_NAME = _convert_NAME
+    _convert_DELETE_NAME = _convert_NAME
+    _convert_IMPORT_NAME = _convert_NAME
+    _convert_IMPORT_FROM = _convert_NAME
+    _convert_STORE_ATTR = _convert_NAME
+    _convert_LOAD_ATTR = _convert_NAME
+    _convert_DELETE_ATTR = _convert_NAME
+    _convert_LOAD_GLOBAL = _convert_NAME
+    _convert_STORE_GLOBAL = _convert_NAME
+    _convert_DELETE_GLOBAL = _convert_NAME
+
+    def _convert_DEREF(self, arg):
+        self._lookupName(arg, self.names)
+        self._lookupName(arg, self.varnames)
+        return self._lookupName(arg, self.closure)
+    _convert_LOAD_DEREF = _convert_DEREF
+    _convert_STORE_DEREF = _convert_DEREF
+
+    def _convert_LOAD_CLOSURE(self, arg):
+        self._lookupName(arg, self.varnames)
+        return self._lookupName(arg, self.closure)
+
+    _cmp = list(dis.cmp_op)
+    def _convert_COMPARE_OP(self, arg):
+        return self._cmp.index(arg)
+
+    # similarly for other opcodes...
+
+    for name, obj in locals().items():
+        if name[:9] == "_convert_":
+            opname = name[9:]
+            _converters[opname] = obj
+    del name, obj, opname
+
+    def makeByteCode(self):
+        assert self.stage == CONV
+        self.lnotab = lnotab = LineAddrTable()
+        for t in self.insts:
+            opname = t[0]
+            if len(t) == 1:
+                lnotab.addCode(self.opnum[opname])
+            else:
+                oparg = t[1]
+                if opname == "SET_LINENO":
+                    lnotab.nextLine(oparg)
+                    continue
+                hi, lo = twobyte(oparg)
+                try:
+                    lnotab.addCode(self.opnum[opname], lo, hi)
+                except ValueError:
+                    print opname, oparg
+                    print self.opnum[opname], lo, hi
+                    raise
+        self.stage = DONE
+
+    opnum = {}
+    for num in range(len(dis.opname)):
+        opnum[dis.opname[num]] = num
+    del num
+
+    def newCodeObject(self):
+        assert self.stage == DONE
+        if (self.flags & CO_NEWLOCALS) == 0:
+            nlocals = 0
+        else:
+            nlocals = len(self.varnames)
+        argcount = self.argcount
+        if self.flags & CO_VARKEYWORDS:
+            argcount = argcount - 1
+        return types.CodeType(argcount, nlocals, self.stacksize, self.flags,
+                        self.lnotab.getCode(), self.getConsts(),
+                        tuple(self.names), tuple(self.varnames),
+                        self.filename, self.name, self.lnotab.firstline,
+                        self.lnotab.getTable(), tuple(self.freevars),
+                        tuple(self.cellvars))
+
+    def getConsts(self):
+        """Return a tuple for the const slot of the code object
+
+        Must convert references to code (MAKE_FUNCTION) to code
+        objects recursively.
+        """
+        l = []
+        for elt in self.consts:
+            if isinstance(elt, PyFlowGraph):
+                elt = elt.getCode()
+            l.append(elt)
+        return tuple(l)
+
+def isJump(opname):
+    if opname[:4] == 'JUMP':
+        return 1
+
+class TupleArg:
+    """Helper for marking func defs with nested tuples in arglist"""
+    def __init__(self, count, names):
+        self.count = count
+        self.names = names
+    def __repr__(self):
+        return "TupleArg(%s, %s)" % (self.count, self.names)
+    def getName(self):
+        return ".%d" % self.count
+
+def getArgCount(args):
+    argcount = len(args)
+    if args:
+        for arg in args:
+            if isinstance(arg, TupleArg):
+                numNames = len(misc.flatten(arg.names))
+                argcount = argcount - numNames
+    return argcount
+
+def twobyte(val):
+    """Convert an int argument into high and low bytes"""
+    assert isinstance(val, int)
+    return divmod(val, 256)
+
+class LineAddrTable:
+    """lnotab
+
+    This class builds the lnotab, which is documented in compile.c.
+    Here's a brief recap:
+
+    For each SET_LINENO instruction after the first one, two bytes are
+    added to lnotab.  (In some cases, multiple two-byte entries are
+    added.)  The first byte is the distance in bytes between the
+    instruction for the last SET_LINENO and the current SET_LINENO.
+    The second byte is offset in line numbers.  If either offset is
+    greater than 255, multiple two-byte entries are added -- see
+    compile.c for the delicate details.
+    """
+
+    def __init__(self):
+        self.code = []
+        self.codeOffset = 0
+        self.firstline = 0
+        self.lastline = 0
+        self.lastoff = 0
+        self.lnotab = []
+
+    def addCode(self, *args):
+        for arg in args:
+            self.code.append(chr(arg))
+        self.codeOffset = self.codeOffset + len(args)
+
+    def nextLine(self, lineno):
+        if self.firstline == 0:
+            self.firstline = lineno
+            self.lastline = lineno
+        else:
+            # compute deltas
+            addr = self.codeOffset - self.lastoff
+            line = lineno - self.lastline
+            # Python assumes that lineno always increases with
+            # increasing bytecode address (lnotab is unsigned char).
+            # Depending on when SET_LINENO instructions are emitted
+            # this is not always true.  Consider the code:
+            #     a = (1,
+            #          b)
+            # In the bytecode stream, the assignment to "a" occurs
+            # after the loading of "b".  This works with the C Python
+            # compiler because it only generates a SET_LINENO instruction
+            # for the assignment.
+            if line >= 0:
+                push = self.lnotab.append
+                while addr > 255:
+                    push(255); push(0)
+                    addr -= 255
+                while line > 255:
+                    push(addr); push(255)
+                    line -= 255
+                    addr = 0
+                if addr > 0 or line > 0:
+                    push(addr); push(line)
+                self.lastline = lineno
+                self.lastoff = self.codeOffset
+
+    def getCode(self):
+        return ''.join(self.code)
+
+    def getTable(self):
+        return ''.join(map(chr, self.lnotab))
+
+class StackDepthTracker:
+    # XXX 1. need to keep track of stack depth on jumps
+    # XXX 2. at least partly as a result, this code is broken
+
+    def findDepth(self, insts, debug=0):
+        depth = 0
+        maxDepth = 0
+        for i in insts:
+            opname = i[0]
+            if debug:
+                print i,
+            delta = self.effect.get(opname, None)
+            if delta is not None:
+                depth = depth + delta
+            else:
+                # now check patterns
+                for pat, pat_delta in self.patterns:
+                    if opname[:len(pat)] == pat:
+                        delta = pat_delta
+                        depth = depth + delta
+                        break
+                # if we still haven't found a match
+                if delta is None:
+                    meth = getattr(self, opname, None)
+                    if meth is not None:
+                        depth = depth + meth(i[1])
+            if depth > maxDepth:
+                maxDepth = depth
+            if debug:
+                print depth, maxDepth
+        return maxDepth
+
+    effect = {
+        'POP_TOP': -1,
+        'DUP_TOP': 1,
+        'LIST_APPEND': -1,
+        'SET_ADD': -1,
+        'MAP_ADD': -2,
+        'SLICE+1': -1,
+        'SLICE+2': -1,
+        'SLICE+3': -2,
+        'STORE_SLICE+0': -1,
+        'STORE_SLICE+1': -2,
+        'STORE_SLICE+2': -2,
+        'STORE_SLICE+3': -3,
+        'DELETE_SLICE+0': -1,
+        'DELETE_SLICE+1': -2,
+        'DELETE_SLICE+2': -2,
+        'DELETE_SLICE+3': -3,
+        'STORE_SUBSCR': -3,
+        'DELETE_SUBSCR': -2,
+        # PRINT_EXPR?
+        'PRINT_ITEM': -1,
+        'RETURN_VALUE': -1,
+        'YIELD_VALUE': -1,
+        'EXEC_STMT': -3,
+        'BUILD_CLASS': -2,
+        'STORE_NAME': -1,
+        'STORE_ATTR': -2,
+        'DELETE_ATTR': -1,
+        'STORE_GLOBAL': -1,
+        'BUILD_MAP': 1,
+        'COMPARE_OP': -1,
+        'STORE_FAST': -1,
+        'IMPORT_STAR': -1,
+        'IMPORT_NAME': -1,
+        'IMPORT_FROM': 1,
+        'LOAD_ATTR': 0, # unlike other loads
+        # close enough...
+        'SETUP_EXCEPT': 3,
+        'SETUP_FINALLY': 3,
+        'FOR_ITER': 1,
+        'WITH_CLEANUP': -1,
+        }
+    # use pattern match
+    patterns = [
+        ('BINARY_', -1),
+        ('LOAD_', 1),
+        ]
+
+    def UNPACK_SEQUENCE(self, count):
+        return count-1
+    def BUILD_TUPLE(self, count):
+        return -count+1
+    def BUILD_LIST(self, count):
+        return -count+1
+    def BUILD_SET(self, count):
+        return -count+1
+    def CALL_FUNCTION(self, argc):
+        hi, lo = divmod(argc, 256)
+        return -(lo + hi * 2)
+    def CALL_FUNCTION_VAR(self, argc):
+        return self.CALL_FUNCTION(argc)-1
+    def CALL_FUNCTION_KW(self, argc):
+        return self.CALL_FUNCTION(argc)-1
+    def CALL_FUNCTION_VAR_KW(self, argc):
+        return self.CALL_FUNCTION(argc)-2
+    def MAKE_FUNCTION(self, argc):
+        return -argc
+    def MAKE_CLOSURE(self, argc):
+        # XXX need to account for free variables too!
+        return -argc
+    def BUILD_SLICE(self, argc):
+        if argc == 2:
+            return -1
+        elif argc == 3:
+            return -2
+    def DUP_TOPX(self, argc):
+        return argc
+
+findDepth = StackDepthTracker().findDepth
diff --git a/src/main/resources/PythonLibs/compiler/pycodegen.py b/src/main/resources/PythonLibs/compiler/pycodegen.py
new file mode 100644
index 0000000000000000000000000000000000000000..4eebd286578a8f3a6326f60d8cb406286658a5b4
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/pycodegen.py
@@ -0,0 +1,1546 @@
+import imp
+import os
+import marshal
+import struct
+import sys
+from cStringIO import StringIO
+is_jython = sys.platform.startswith('java')
+
+from compiler import ast, parse, walk, syntax
+from compiler import misc, future, symbols
+from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \
+     SC_FREE, SC_CELL
+from compiler.consts import (CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,
+     CO_NESTED, CO_GENERATOR, CO_FUTURE_DIVISION,
+     CO_FUTURE_ABSIMPORT, CO_FUTURE_WITH_STATEMENT, CO_FUTURE_PRINT_FUNCTION)
+if not is_jython:
+    from compiler.pyassem import TupleArg
+else:
+    TupleArg = None
+
+# XXX The version-specific code can go, since this code only works with 2.x.
+# Do we have Python 1.x or Python 2.x?
+try:
+    VERSION = sys.version_info[0]
+except AttributeError:
+    VERSION = 1
+
+callfunc_opcode_info = {
+    # (Have *args, Have **args) : opcode
+    (0,0) : "CALL_FUNCTION",
+    (1,0) : "CALL_FUNCTION_VAR",
+    (0,1) : "CALL_FUNCTION_KW",
+    (1,1) : "CALL_FUNCTION_VAR_KW",
+}
+
+LOOP = 1
+EXCEPT = 2
+TRY_FINALLY = 3
+END_FINALLY = 4
+
+def compileFile(filename, display=0):
+    f = open(filename, 'U')
+    buf = f.read()
+    f.close()
+    mod = Module(buf, filename)
+    try:
+        mod.compile(display)
+    except SyntaxError:
+        raise
+    else:
+        f = open(filename + "c", "wb")
+        mod.dump(f)
+        f.close()
+
+if is_jython:
+    # use __builtin__ compile
+    compile = compile
+else:
+    def compile(source, filename, mode, flags=None, dont_inherit=None):
+        """Replacement for builtin compile() function"""
+        if flags is not None or dont_inherit is not None:
+            raise RuntimeError, "not implemented yet"
+
+        if mode == "single":
+            gen = Interactive(source, filename)
+        elif mode == "exec":
+            gen = Module(source, filename)
+        elif mode == "eval":
+            gen = Expression(source, filename)
+        else:
+            raise ValueError("compile() 3rd arg must be 'exec' or "
+                             "'eval' or 'single'")
+        gen.compile()
+        return gen.code
+
+class AbstractCompileMode:
+
+    mode = None # defined by subclass
+
+    def __init__(self, source, filename):
+        self.source = source
+        self.filename = filename
+        self.code = None
+
+    def _get_tree(self):
+        tree = parse(self.source, self.mode)
+        misc.set_filename(self.filename, tree)
+        syntax.check(tree)
+        return tree
+
+    def compile(self):
+        pass # implemented by subclass
+
+    def getCode(self):
+        return self.code
+
+class Expression(AbstractCompileMode):
+
+    mode = "eval"
+
+    def compile(self):
+        tree = self._get_tree()
+        gen = ExpressionCodeGenerator(tree)
+        self.code = gen.getCode()
+
+class Interactive(AbstractCompileMode):
+
+    mode = "single"
+
+    def compile(self):
+        tree = self._get_tree()
+        gen = InteractiveCodeGenerator(tree)
+        self.code = gen.getCode()
+
+class Module(AbstractCompileMode):
+
+    mode = "exec"
+
+    def compile(self, display=0):
+        tree = self._get_tree()
+        gen = ModuleCodeGenerator(tree)
+        if display:
+            import pprint
+            print pprint.pprint(tree)
+        self.code = gen.getCode()
+
+    def dump(self, f):
+        f.write(self.getPycHeader())
+        marshal.dump(self.code, f)
+
+    MAGIC = None if is_jython else imp.get_magic()
+
+    def getPycHeader(self):
+        # compile.c uses marshal to write a long directly, with
+        # calling the interface that would also generate a 1-byte code
+        # to indicate the type of the value.  simplest way to get the
+        # same effect is to call marshal and then skip the code.
+        mtime = os.path.getmtime(self.filename)
+        mtime = struct.pack('<i', mtime)
+        return self.MAGIC + mtime
+
+class LocalNameFinder:
+    """Find local names in scope"""
+    def __init__(self, names=()):
+        self.names = misc.Set()
+        self.globals = misc.Set()
+        for name in names:
+            self.names.add(name)
+
+    # XXX list comprehensions and for loops
+
+    def getLocals(self):
+        for elt in self.globals.elements():
+            if self.names.has_elt(elt):
+                self.names.remove(elt)
+        return self.names
+
+    def visitDict(self, node):
+        pass
+
+    def visitGlobal(self, node):
+        for name in node.names:
+            self.globals.add(name)
+
+    def visitFunction(self, node):
+        self.names.add(node.name)
+
+    def visitLambda(self, node):
+        pass
+
+    def visitImport(self, node):
+        for name, alias in node.names:
+            self.names.add(alias or name)
+
+    def visitFrom(self, node):
+        for name, alias in node.names:
+            self.names.add(alias or name)
+
+    def visitClass(self, node):
+        self.names.add(node.name)
+
+    def visitAssName(self, node):
+        self.names.add(node.name)
+
+def is_constant_false(node):
+    if isinstance(node, ast.Const):
+        if not node.value:
+            return 1
+    return 0
+
+class CodeGenerator:
+    """Defines basic code generator for Python bytecode
+
+    This class is an abstract base class.  Concrete subclasses must
+    define an __init__() that defines self.graph and then calls the
+    __init__() defined in this class.
+
+    The concrete class must also define the class attributes
+    NameFinder, FunctionGen, and ClassGen.  These attributes can be
+    defined in the initClass() method, which is a hook for
+    initializing these methods after all the classes have been
+    defined.
+    """
+
+    optimized = 0 # is namespace access optimized?
+    __initialized = None
+    class_name = None # provide default for instance variable
+
+    def __init__(self):
+        if self.__initialized is None:
+            self.initClass()
+            self.__class__.__initialized = 1
+        self.checkClass()
+        self.locals = misc.Stack()
+        self.setups = misc.Stack()
+        self.last_lineno = None
+        self._setupGraphDelegation()
+        self._div_op = "BINARY_DIVIDE"
+
+        # XXX set flags based on future features
+        futures = self.get_module().futures
+        for feature in futures:
+            if feature == "division":
+                self.graph.setFlag(CO_FUTURE_DIVISION)
+                self._div_op = "BINARY_TRUE_DIVIDE"
+            elif feature == "absolute_import":
+                self.graph.setFlag(CO_FUTURE_ABSIMPORT)
+            elif feature == "with_statement":
+                self.graph.setFlag(CO_FUTURE_WITH_STATEMENT)
+            elif feature == "print_function":
+                self.graph.setFlag(CO_FUTURE_PRINT_FUNCTION)
+
+    def initClass(self):
+        """This method is called once for each class"""
+
+    def checkClass(self):
+        """Verify that class is constructed correctly"""
+        try:
+            assert hasattr(self, 'graph')
+            assert getattr(self, 'NameFinder')
+            assert getattr(self, 'FunctionGen')
+            assert getattr(self, 'ClassGen')
+        except AssertionError, msg:
+            intro = "Bad class construction for %s" % self.__class__.__name__
+            raise AssertionError, intro
+
+    def _setupGraphDelegation(self):
+        self.emit = self.graph.emit
+        self.newBlock = self.graph.newBlock
+        self.startBlock = self.graph.startBlock
+        self.nextBlock = self.graph.nextBlock
+        self.setDocstring = self.graph.setDocstring
+
+    def getCode(self):
+        """Return a code object"""
+        return self.graph.getCode()
+
+    def mangle(self, name):
+        if self.class_name is not None:
+            return misc.mangle(name, self.class_name)
+        else:
+            return name
+
+    def parseSymbols(self, tree):
+        s = symbols.SymbolVisitor()
+        walk(tree, s)
+        return s.scopes
+
+    def get_module(self):
+        raise RuntimeError, "should be implemented by subclasses"
+
+    # Next five methods handle name access
+
+    def isLocalName(self, name):
+        return self.locals.top().has_elt(name)
+
+    def storeName(self, name):
+        self._nameOp('STORE', name)
+
+    def loadName(self, name):
+        self._nameOp('LOAD', name)
+
+    def delName(self, name):
+        self._nameOp('DELETE', name)
+
+    def _nameOp(self, prefix, name):
+        name = self.mangle(name)
+        scope = self.scope.check_name(name)
+        if scope == SC_LOCAL:
+            if not self.optimized:
+                self.emit(prefix + '_NAME', name)
+            else:
+                self.emit(prefix + '_FAST', name)
+        elif scope == SC_GLOBAL_EXPLICT:
+            self.emit(prefix + '_GLOBAL', name)
+        elif scope == SC_GLOBAL_IMPLICIT:
+            if not self.optimized:
+                self.emit(prefix + '_NAME', name)
+            else:
+                self.emit(prefix + '_GLOBAL', name)
+        elif scope == SC_FREE or scope == SC_CELL:
+            self.emit(prefix + '_DEREF', name)
+        else:
+            raise RuntimeError, "unsupported scope for var %s: %d" % \
+                  (name, scope)
+
+    def _implicitNameOp(self, prefix, name):
+        """Emit name ops for names generated implicitly by for loops
+
+        The interpreter generates names that start with a period or
+        dollar sign.  The symbol table ignores these names because
+        they aren't present in the program text.
+        """
+        if self.optimized:
+            self.emit(prefix + '_FAST', name)
+        else:
+            self.emit(prefix + '_NAME', name)
+
+    # The set_lineno() function and the explicit emit() calls for
+    # SET_LINENO below are only used to generate the line number table.
+    # As of Python 2.3, the interpreter does not have a SET_LINENO
+    # instruction.  pyassem treats SET_LINENO opcodes as a special case.
+
+    def set_lineno(self, node, force=False):
+        """Emit SET_LINENO if necessary.
+
+        The instruction is considered necessary if the node has a
+        lineno attribute and it is different than the last lineno
+        emitted.
+
+        Returns true if SET_LINENO was emitted.
+
+        There are no rules for when an AST node should have a lineno
+        attribute.  The transformer and AST code need to be reviewed
+        and a consistent policy implemented and documented.  Until
+        then, this method works around missing line numbers.
+        """
+        lineno = getattr(node, 'lineno', None)
+        if lineno is not None and (lineno != self.last_lineno
+                                   or force):
+            self.emit('SET_LINENO', lineno)
+            self.last_lineno = lineno
+            return True
+        return False
+
+    # The first few visitor methods handle nodes that generator new
+    # code objects.  They use class attributes to determine what
+    # specialized code generators to use.
+
+    NameFinder = LocalNameFinder
+    FunctionGen = None
+    ClassGen = None
+
+    def visitModule(self, node):
+        self.scopes = self.parseSymbols(node)
+        self.scope = self.scopes[node]
+        self.emit('SET_LINENO', 0)
+        if node.doc:
+            self.emit('LOAD_CONST', node.doc)
+            self.storeName('__doc__')
+        lnf = walk(node.node, self.NameFinder(), verbose=0)
+        self.locals.push(lnf.getLocals())
+        self.visit(node.node)
+        self.emit('LOAD_CONST', None)
+        self.emit('RETURN_VALUE')
+
+    def visitExpression(self, node):
+        self.set_lineno(node)
+        self.scopes = self.parseSymbols(node)
+        self.scope = self.scopes[node]
+        self.visit(node.node)
+        self.emit('RETURN_VALUE')
+
+    def visitFunction(self, node):
+        self._visitFuncOrLambda(node, isLambda=0)
+        if node.doc:
+            self.setDocstring(node.doc)
+        self.storeName(node.name)
+
+    def visitLambda(self, node):
+        self._visitFuncOrLambda(node, isLambda=1)
+
+    def _visitFuncOrLambda(self, node, isLambda=0):
+        if not isLambda and node.decorators:
+            for decorator in node.decorators.nodes:
+                self.visit(decorator)
+            ndecorators = len(node.decorators.nodes)
+        else:
+            ndecorators = 0
+
+        gen = self.FunctionGen(node, self.scopes, isLambda,
+                               self.class_name, self.get_module())
+        walk(node.code, gen)
+        gen.finish()
+        self.set_lineno(node)
+        for default in node.defaults:
+            self.visit(default)
+        self._makeClosure(gen, len(node.defaults))
+        for i in range(ndecorators):
+            self.emit('CALL_FUNCTION', 1)
+
+    def visitClass(self, node):
+        gen = self.ClassGen(node, self.scopes,
+                            self.get_module())
+        walk(node.code, gen)
+        gen.finish()
+        self.set_lineno(node)
+        self.emit('LOAD_CONST', node.name)
+        for base in node.bases:
+            self.visit(base)
+        self.emit('BUILD_TUPLE', len(node.bases))
+        self._makeClosure(gen, 0)
+        self.emit('CALL_FUNCTION', 0)
+        self.emit('BUILD_CLASS')
+        self.storeName(node.name)
+
+    # The rest are standard visitor methods
+
+    # The next few implement control-flow statements
+
+    def visitIf(self, node):
+        end = self.newBlock()
+        numtests = len(node.tests)
+        for i in range(numtests):
+            test, suite = node.tests[i]
+            if is_constant_false(test):
+                # XXX will need to check generator stuff here
+                continue
+            self.set_lineno(test)
+            self.visit(test)
+            nextTest = self.newBlock()
+            self.emit('JUMP_IF_FALSE', nextTest)
+            self.nextBlock()
+            self.emit('POP_TOP')
+            self.visit(suite)
+            self.emit('JUMP_FORWARD', end)
+            self.startBlock(nextTest)
+            self.emit('POP_TOP')
+        if node.else_:
+            self.visit(node.else_)
+        self.nextBlock(end)
+
+    def visitWhile(self, node):
+        self.set_lineno(node)
+
+        loop = self.newBlock()
+        else_ = self.newBlock()
+
+        after = self.newBlock()
+        self.emit('SETUP_LOOP', after)
+
+        self.nextBlock(loop)
+        self.setups.push((LOOP, loop))
+
+        self.set_lineno(node, force=True)
+        self.visit(node.test)
+        self.emit('JUMP_IF_FALSE', else_ or after)
+
+        self.nextBlock()
+        self.emit('POP_TOP')
+        self.visit(node.body)
+        self.emit('JUMP_ABSOLUTE', loop)
+
+        self.startBlock(else_) # or just the POPs if not else clause
+        self.emit('POP_TOP')
+        self.emit('POP_BLOCK')
+        self.setups.pop()
+        if node.else_:
+            self.visit(node.else_)
+        self.nextBlock(after)
+
+    def visitFor(self, node):
+        start = self.newBlock()
+        anchor = self.newBlock()
+        after = self.newBlock()
+        self.setups.push((LOOP, start))
+
+        self.set_lineno(node)
+        self.emit('SETUP_LOOP', after)
+        self.visit(node.list)
+        self.emit('GET_ITER')
+
+        self.nextBlock(start)
+        self.set_lineno(node, force=1)
+        self.emit('FOR_ITER', anchor)
+        self.visit(node.assign)
+        self.visit(node.body)
+        self.emit('JUMP_ABSOLUTE', start)
+        self.nextBlock(anchor)
+        self.emit('POP_BLOCK')
+        self.setups.pop()
+        if node.else_:
+            self.visit(node.else_)
+        self.nextBlock(after)
+
+    def visitBreak(self, node):
+        if not self.setups:
+            raise SyntaxError, "'break' outside loop (%s, %d)" % \
+                  (node.filename, node.lineno)
+        self.set_lineno(node)
+        self.emit('BREAK_LOOP')
+
+    def visitContinue(self, node):
+        if not self.setups:
+            raise SyntaxError, "'continue' outside loop (%s, %d)" % \
+                  (node.filename, node.lineno)
+        kind, block = self.setups.top()
+        if kind == LOOP:
+            self.set_lineno(node)
+            self.emit('JUMP_ABSOLUTE', block)
+            self.nextBlock()
+        elif kind == EXCEPT or kind == TRY_FINALLY:
+            self.set_lineno(node)
+            # find the block that starts the loop
+            top = len(self.setups)
+            while top > 0:
+                top = top - 1
+                kind, loop_block = self.setups[top]
+                if kind == LOOP:
+                    break
+            if kind != LOOP:
+                raise SyntaxError, "'continue' outside loop (%s, %d)" % \
+                      (node.filename, node.lineno)
+            self.emit('CONTINUE_LOOP', loop_block)
+            self.nextBlock()
+        elif kind == END_FINALLY:
+            msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
+            raise SyntaxError, msg % (node.filename, node.lineno)
+
+    def visitTest(self, node, jump):
+        end = self.newBlock()
+        for child in node.nodes[:-1]:
+            self.visit(child)
+            self.emit(jump, end)
+            self.nextBlock()
+            self.emit('POP_TOP')
+        self.visit(node.nodes[-1])
+        self.nextBlock(end)
+
+    def visitAnd(self, node):
+        self.visitTest(node, 'JUMP_IF_FALSE')
+
+    def visitOr(self, node):
+        self.visitTest(node, 'JUMP_IF_TRUE')
+
+    def visitIfExp(self, node):
+        endblock = self.newBlock()
+        elseblock = self.newBlock()
+        self.visit(node.test)
+        self.emit('JUMP_IF_FALSE', elseblock)
+        self.emit('POP_TOP')
+        self.visit(node.then)
+        self.emit('JUMP_FORWARD', endblock)
+        self.nextBlock(elseblock)
+        self.emit('POP_TOP')
+        self.visit(node.else_)
+        self.nextBlock(endblock)
+
+    def visitCompare(self, node):
+        self.visit(node.expr)
+        cleanup = self.newBlock()
+        for op, code in node.ops[:-1]:
+            self.visit(code)
+            self.emit('DUP_TOP')
+            self.emit('ROT_THREE')
+            self.emit('COMPARE_OP', op)
+            self.emit('JUMP_IF_FALSE', cleanup)
+            self.nextBlock()
+            self.emit('POP_TOP')
+        # now do the last comparison
+        if node.ops:
+            op, code = node.ops[-1]
+            self.visit(code)
+            self.emit('COMPARE_OP', op)
+        if len(node.ops) > 1:
+            end = self.newBlock()
+            self.emit('JUMP_FORWARD', end)
+            self.startBlock(cleanup)
+            self.emit('ROT_TWO')
+            self.emit('POP_TOP')
+            self.nextBlock(end)
+
+    # list comprehensions
+    __list_count = 0
+
+    def visitListComp(self, node):
+        self.set_lineno(node)
+        # setup list
+        append = "$append%d" % self.__list_count
+        self.__list_count = self.__list_count + 1
+        self.emit('BUILD_LIST', 0)
+        self.emit('DUP_TOP')
+        self.emit('LOAD_ATTR', 'append')
+        self._implicitNameOp('STORE', append)
+
+        stack = []
+        for i, for_ in zip(range(len(node.quals)), node.quals):
+            start, anchor = self.visit(for_)
+            cont = None
+            for if_ in for_.ifs:
+                if cont is None:
+                    cont = self.newBlock()
+                self.visit(if_, cont)
+            stack.insert(0, (start, cont, anchor))
+
+        self._implicitNameOp('LOAD', append)
+        self.visit(node.expr)
+        self.emit('CALL_FUNCTION', 1)
+        self.emit('POP_TOP')
+
+        for start, cont, anchor in stack:
+            if cont:
+                skip_one = self.newBlock()
+                self.emit('JUMP_FORWARD', skip_one)
+                self.startBlock(cont)
+                self.emit('POP_TOP')
+                self.nextBlock(skip_one)
+            self.emit('JUMP_ABSOLUTE', start)
+            self.startBlock(anchor)
+        self._implicitNameOp('DELETE', append)
+
+        self.__list_count = self.__list_count - 1
+
+    def visitListCompFor(self, node):
+        start = self.newBlock()
+        anchor = self.newBlock()
+
+        self.visit(node.list)
+        self.emit('GET_ITER')
+        self.nextBlock(start)
+        self.set_lineno(node, force=True)
+        self.emit('FOR_ITER', anchor)
+        self.nextBlock()
+        self.visit(node.assign)
+        return start, anchor
+
+    def visitListCompIf(self, node, branch):
+        self.set_lineno(node, force=True)
+        self.visit(node.test)
+        self.emit('JUMP_IF_FALSE', branch)
+        self.newBlock()
+        self.emit('POP_TOP')
+
+    def _makeClosure(self, gen, args):
+        frees = gen.scope.get_free_vars()
+        if frees:
+            for name in frees:
+                self.emit('LOAD_CLOSURE', name)
+            self.emit('BUILD_TUPLE', len(frees))
+            self.emit('LOAD_CONST', gen)
+            self.emit('MAKE_CLOSURE', args)
+        else:
+            self.emit('LOAD_CONST', gen)
+            self.emit('MAKE_FUNCTION', args)
+
+    def visitGenExpr(self, node):
+        gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
+                                   self.get_module())
+        walk(node.code, gen)
+        gen.finish()
+        self.set_lineno(node)
+        self._makeClosure(gen, 0)
+        # precomputation of outmost iterable
+        self.visit(node.code.quals[0].iter)
+        self.emit('GET_ITER')
+        self.emit('CALL_FUNCTION', 1)
+
+    def visitGenExprInner(self, node):
+        self.set_lineno(node)
+        # setup list
+
+        stack = []
+        for i, for_ in zip(range(len(node.quals)), node.quals):
+            start, anchor, end = self.visit(for_)
+            cont = None
+            for if_ in for_.ifs:
+                if cont is None:
+                    cont = self.newBlock()
+                self.visit(if_, cont)
+            stack.insert(0, (start, cont, anchor, end))
+
+        self.visit(node.expr)
+        self.emit('YIELD_VALUE')
+        self.emit('POP_TOP')
+
+        for start, cont, anchor, end in stack:
+            if cont:
+                skip_one = self.newBlock()
+                self.emit('JUMP_FORWARD', skip_one)
+                self.startBlock(cont)
+                self.emit('POP_TOP')
+                self.nextBlock(skip_one)
+            self.emit('JUMP_ABSOLUTE', start)
+            self.startBlock(anchor)
+            self.emit('POP_BLOCK')
+            self.setups.pop()
+            self.startBlock(end)
+
+        self.emit('LOAD_CONST', None)
+
+    def visitGenExprFor(self, node):
+        start = self.newBlock()
+        anchor = self.newBlock()
+        end = self.newBlock()
+
+        self.setups.push((LOOP, start))
+        self.emit('SETUP_LOOP', end)
+
+        if node.is_outmost:
+            self.loadName('.0')
+        else:
+            self.visit(node.iter)
+            self.emit('GET_ITER')
+
+        self.nextBlock(start)
+        self.set_lineno(node, force=True)
+        self.emit('FOR_ITER', anchor)
+        self.nextBlock()
+        self.visit(node.assign)
+        return start, anchor, end
+
+    def visitGenExprIf(self, node, branch):
+        self.set_lineno(node, force=True)
+        self.visit(node.test)
+        self.emit('JUMP_IF_FALSE', branch)
+        self.newBlock()
+        self.emit('POP_TOP')
+
+    # exception related
+
+    def visitAssert(self, node):
+        # XXX would be interesting to implement this via a
+        # transformation of the AST before this stage
+        if __debug__:
+            end = self.newBlock()
+            self.set_lineno(node)
+            # XXX AssertionError appears to be special case -- it is always
+            # loaded as a global even if there is a local name.  I guess this
+            # is a sort of renaming op.
+            self.nextBlock()
+            self.visit(node.test)
+            self.emit('JUMP_IF_TRUE', end)
+            self.nextBlock()
+            self.emit('POP_TOP')
+            self.emit('LOAD_GLOBAL', 'AssertionError')
+            if node.fail:
+                self.visit(node.fail)
+                self.emit('RAISE_VARARGS', 2)
+            else:
+                self.emit('RAISE_VARARGS', 1)
+            self.nextBlock(end)
+            self.emit('POP_TOP')
+
+    def visitRaise(self, node):
+        self.set_lineno(node)
+        n = 0
+        if node.expr1:
+            self.visit(node.expr1)
+            n = n + 1
+        if node.expr2:
+            self.visit(node.expr2)
+            n = n + 1
+        if node.expr3:
+            self.visit(node.expr3)
+            n = n + 1
+        self.emit('RAISE_VARARGS', n)
+
+    def visitTryExcept(self, node):
+        body = self.newBlock()
+        handlers = self.newBlock()
+        end = self.newBlock()
+        if node.else_:
+            lElse = self.newBlock()
+        else:
+            lElse = end
+        self.set_lineno(node)
+        self.emit('SETUP_EXCEPT', handlers)
+        self.nextBlock(body)
+        self.setups.push((EXCEPT, body))
+        self.visit(node.body)
+        self.emit('POP_BLOCK')
+        self.setups.pop()
+        self.emit('JUMP_FORWARD', lElse)
+        self.startBlock(handlers)
+
+        last = len(node.handlers) - 1
+        for i in range(len(node.handlers)):
+            expr, target, body = node.handlers[i]
+            self.set_lineno(expr)
+            if expr:
+                self.emit('DUP_TOP')
+                self.visit(expr)
+                self.emit('COMPARE_OP', 'exception match')
+                next = self.newBlock()
+                self.emit('JUMP_IF_FALSE', next)
+                self.nextBlock()
+                self.emit('POP_TOP')
+            self.emit('POP_TOP')
+            if target:
+                self.visit(target)
+            else:
+                self.emit('POP_TOP')
+            self.emit('POP_TOP')
+            self.visit(body)
+            self.emit('JUMP_FORWARD', end)
+            if expr:
+                self.nextBlock(next)
+            else:
+                self.nextBlock()
+            if expr: # XXX
+                self.emit('POP_TOP')
+        self.emit('END_FINALLY')
+        if node.else_:
+            self.nextBlock(lElse)
+            self.visit(node.else_)
+        self.nextBlock(end)
+
+    def visitTryFinally(self, node):
+        body = self.newBlock()
+        final = self.newBlock()
+        self.set_lineno(node)
+        self.emit('SETUP_FINALLY', final)
+        self.nextBlock(body)
+        self.setups.push((TRY_FINALLY, body))
+        self.visit(node.body)
+        self.emit('POP_BLOCK')
+        self.setups.pop()
+        self.emit('LOAD_CONST', None)
+        self.nextBlock(final)
+        self.setups.push((END_FINALLY, final))
+        self.visit(node.final)
+        self.emit('END_FINALLY')
+        self.setups.pop()
+
+    __with_count = 0
+
+    def visitWith(self, node):
+        body = self.newBlock()
+        final = self.newBlock()
+        exitvar = "$exit%d" % self.__with_count
+        valuevar = "$value%d" % self.__with_count
+        self.__with_count += 1
+        self.set_lineno(node)
+        self.visit(node.expr)
+        self.emit('DUP_TOP')
+        self.emit('LOAD_ATTR', '__exit__')
+        self._implicitNameOp('STORE', exitvar)
+        self.emit('LOAD_ATTR', '__enter__')
+        self.emit('CALL_FUNCTION', 0)
+        if node.vars is None:
+            self.emit('POP_TOP')
+        else:
+            self._implicitNameOp('STORE', valuevar)
+        self.emit('SETUP_FINALLY', final)
+        self.nextBlock(body)
+        self.setups.push((TRY_FINALLY, body))
+        if node.vars is not None:
+            self._implicitNameOp('LOAD', valuevar)
+            self._implicitNameOp('DELETE', valuevar)
+            self.visit(node.vars)
+        self.visit(node.body)
+        self.emit('POP_BLOCK')
+        self.setups.pop()
+        self.emit('LOAD_CONST', None)
+        self.nextBlock(final)
+        self.setups.push((END_FINALLY, final))
+        self._implicitNameOp('LOAD', exitvar)
+        self._implicitNameOp('DELETE', exitvar)
+        self.emit('WITH_CLEANUP')
+        self.emit('END_FINALLY')
+        self.setups.pop()
+        self.__with_count -= 1
+
+    # misc
+
+    def visitDiscard(self, node):
+        self.set_lineno(node)
+        self.visit(node.expr)
+        self.emit('POP_TOP')
+
+    def visitConst(self, node):
+        self.emit('LOAD_CONST', node.value)
+
+    def visitKeyword(self, node):
+        self.emit('LOAD_CONST', node.name)
+        self.visit(node.expr)
+
+    def visitGlobal(self, node):
+        # no code to generate
+        pass
+
+    def visitName(self, node):
+        self.set_lineno(node)
+        self.loadName(node.name)
+
+    def visitPass(self, node):
+        self.set_lineno(node)
+
+    def visitImport(self, node):
+        self.set_lineno(node)
+        level = 0 if self.graph.checkFlag(CO_FUTURE_ABSIMPORT) else -1
+        for name, alias in node.names:
+            if VERSION > 1:
+                self.emit('LOAD_CONST', level)
+                self.emit('LOAD_CONST', None)
+            self.emit('IMPORT_NAME', name)
+            mod = name.split(".")[0]
+            if alias:
+                self._resolveDots(name)
+                self.storeName(alias)
+            else:
+                self.storeName(mod)
+
+    def visitFrom(self, node):
+        self.set_lineno(node)
+        level = node.level
+        if level == 0 and not self.graph.checkFlag(CO_FUTURE_ABSIMPORT):
+            level = -1
+        fromlist = map(lambda (name, alias): name, node.names)
+        if VERSION > 1:
+            self.emit('LOAD_CONST', level)
+            self.emit('LOAD_CONST', tuple(fromlist))
+        self.emit('IMPORT_NAME', node.modname)
+        for name, alias in node.names:
+            if VERSION > 1:
+                if name == '*':
+                    self.namespace = 0
+                    self.emit('IMPORT_STAR')
+                    # There can only be one name w/ from ... import *
+                    assert len(node.names) == 1
+                    return
+                else:
+                    self.emit('IMPORT_FROM', name)
+                    self._resolveDots(name)
+                    self.storeName(alias or name)
+            else:
+                self.emit('IMPORT_FROM', name)
+        self.emit('POP_TOP')
+
+    def _resolveDots(self, name):
+        elts = name.split(".")
+        if len(elts) == 1:
+            return
+        for elt in elts[1:]:
+            self.emit('LOAD_ATTR', elt)
+
+    def visitGetattr(self, node):
+        self.visit(node.expr)
+        self.emit('LOAD_ATTR', self.mangle(node.attrname))
+
+    # next five implement assignments
+
+    def visitAssign(self, node):
+        self.set_lineno(node)
+        self.visit(node.expr)
+        dups = len(node.nodes) - 1
+        for i in range(len(node.nodes)):
+            elt = node.nodes[i]
+            if i < dups:
+                self.emit('DUP_TOP')
+            if isinstance(elt, ast.Node):
+                self.visit(elt)
+
+    def visitAssName(self, node):
+        if node.flags == 'OP_ASSIGN':
+            self.storeName(node.name)
+        elif node.flags == 'OP_DELETE':
+            self.set_lineno(node)
+            self.delName(node.name)
+        else:
+            print "oops", node.flags
+
+    def visitAssAttr(self, node):
+        self.visit(node.expr)
+        if node.flags == 'OP_ASSIGN':
+            self.emit('STORE_ATTR', self.mangle(node.attrname))
+        elif node.flags == 'OP_DELETE':
+            self.emit('DELETE_ATTR', self.mangle(node.attrname))
+        else:
+            print "warning: unexpected flags:", node.flags
+            print node
+
+    def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
+        if findOp(node) != 'OP_DELETE':
+            self.emit(op, len(node.nodes))
+        for child in node.nodes:
+            self.visit(child)
+
+    if VERSION > 1:
+        visitAssTuple = _visitAssSequence
+        visitAssList = _visitAssSequence
+    else:
+        def visitAssTuple(self, node):
+            self._visitAssSequence(node, 'UNPACK_TUPLE')
+
+        def visitAssList(self, node):
+            self._visitAssSequence(node, 'UNPACK_LIST')
+
+    # augmented assignment
+
+    def visitAugAssign(self, node):
+        self.set_lineno(node)
+        aug_node = wrap_aug(node.node)
+        self.visit(aug_node, "load")
+        self.visit(node.expr)
+        self.emit(self._augmented_opcode[node.op])
+        self.visit(aug_node, "store")
+
+    _augmented_opcode = {
+        '+=' : 'INPLACE_ADD',
+        '-=' : 'INPLACE_SUBTRACT',
+        '*=' : 'INPLACE_MULTIPLY',
+        '/=' : 'INPLACE_DIVIDE',
+        '//=': 'INPLACE_FLOOR_DIVIDE',
+        '%=' : 'INPLACE_MODULO',
+        '**=': 'INPLACE_POWER',
+        '>>=': 'INPLACE_RSHIFT',
+        '<<=': 'INPLACE_LSHIFT',
+        '&=' : 'INPLACE_AND',
+        '^=' : 'INPLACE_XOR',
+        '|=' : 'INPLACE_OR',
+        }
+
+    def visitAugName(self, node, mode):
+        if mode == "load":
+            self.loadName(node.name)
+        elif mode == "store":
+            self.storeName(node.name)
+
+    def visitAugGetattr(self, node, mode):
+        if mode == "load":
+            self.visit(node.expr)
+            self.emit('DUP_TOP')
+            self.emit('LOAD_ATTR', self.mangle(node.attrname))
+        elif mode == "store":
+            self.emit('ROT_TWO')
+            self.emit('STORE_ATTR', self.mangle(node.attrname))
+
+    def visitAugSlice(self, node, mode):
+        if mode == "load":
+            self.visitSlice(node, 1)
+        elif mode == "store":
+            slice = 0
+            if node.lower:
+                slice = slice | 1
+            if node.upper:
+                slice = slice | 2
+            if slice == 0:
+                self.emit('ROT_TWO')
+            elif slice == 3:
+                self.emit('ROT_FOUR')
+            else:
+                self.emit('ROT_THREE')
+            self.emit('STORE_SLICE+%d' % slice)
+
+    def visitAugSubscript(self, node, mode):
+        if mode == "load":
+            self.visitSubscript(node, 1)
+        elif mode == "store":
+            self.emit('ROT_THREE')
+            self.emit('STORE_SUBSCR')
+
+    def visitExec(self, node):
+        self.visit(node.expr)
+        if node.locals is None:
+            self.emit('LOAD_CONST', None)
+        else:
+            self.visit(node.locals)
+        if node.globals is None:
+            self.emit('DUP_TOP')
+        else:
+            self.visit(node.globals)
+        self.emit('EXEC_STMT')
+
+    def visitCallFunc(self, node):
+        pos = 0
+        kw = 0
+        self.set_lineno(node)
+        self.visit(node.node)
+        for arg in node.args:
+            self.visit(arg)
+            if isinstance(arg, ast.Keyword):
+                kw = kw + 1
+            else:
+                pos = pos + 1
+        if node.star_args is not None:
+            self.visit(node.star_args)
+        if node.dstar_args is not None:
+            self.visit(node.dstar_args)
+        have_star = node.star_args is not None
+        have_dstar = node.dstar_args is not None
+        opcode = callfunc_opcode_info[have_star, have_dstar]
+        self.emit(opcode, kw << 8 | pos)
+
+    def visitPrint(self, node, newline=0):
+        self.set_lineno(node)
+        if node.dest:
+            self.visit(node.dest)
+        for child in node.nodes:
+            if node.dest:
+                self.emit('DUP_TOP')
+            self.visit(child)
+            if node.dest:
+                self.emit('ROT_TWO')
+                self.emit('PRINT_ITEM_TO')
+            else:
+                self.emit('PRINT_ITEM')
+        if node.dest and not newline:
+            self.emit('POP_TOP')
+
+    def visitPrintnl(self, node):
+        self.visitPrint(node, newline=1)
+        if node.dest:
+            self.emit('PRINT_NEWLINE_TO')
+        else:
+            self.emit('PRINT_NEWLINE')
+
+    def visitReturn(self, node):
+        self.set_lineno(node)
+        self.visit(node.value)
+        self.emit('RETURN_VALUE')
+
+    def visitYield(self, node):
+        self.set_lineno(node)
+        self.visit(node.value)
+        self.emit('YIELD_VALUE')
+
+    # slice and subscript stuff
+
+    def visitSlice(self, node, aug_flag=None):
+        # aug_flag is used by visitAugSlice
+        self.visit(node.expr)
+        slice = 0
+        if node.lower:
+            self.visit(node.lower)
+            slice = slice | 1
+        if node.upper:
+            self.visit(node.upper)
+            slice = slice | 2
+        if aug_flag:
+            if slice == 0:
+                self.emit('DUP_TOP')
+            elif slice == 3:
+                self.emit('DUP_TOPX', 3)
+            else:
+                self.emit('DUP_TOPX', 2)
+        if node.flags == 'OP_APPLY':
+            self.emit('SLICE+%d' % slice)
+        elif node.flags == 'OP_ASSIGN':
+            self.emit('STORE_SLICE+%d' % slice)
+        elif node.flags == 'OP_DELETE':
+            self.emit('DELETE_SLICE+%d' % slice)
+        else:
+            print "weird slice", node.flags
+            raise
+
+    def visitSubscript(self, node, aug_flag=None):
+        self.visit(node.expr)
+        for sub in node.subs:
+            self.visit(sub)
+        if len(node.subs) > 1:
+            self.emit('BUILD_TUPLE', len(node.subs))
+        if aug_flag:
+            self.emit('DUP_TOPX', 2)
+        if node.flags == 'OP_APPLY':
+            self.emit('BINARY_SUBSCR')
+        elif node.flags == 'OP_ASSIGN':
+            self.emit('STORE_SUBSCR')
+        elif node.flags == 'OP_DELETE':
+            self.emit('DELETE_SUBSCR')
+
+    # binary ops
+
+    def binaryOp(self, node, op):
+        self.visit(node.left)
+        self.visit(node.right)
+        self.emit(op)
+
+    def visitAdd(self, node):
+        return self.binaryOp(node, 'BINARY_ADD')
+
+    def visitSub(self, node):
+        return self.binaryOp(node, 'BINARY_SUBTRACT')
+
+    def visitMul(self, node):
+        return self.binaryOp(node, 'BINARY_MULTIPLY')
+
+    def visitDiv(self, node):
+        return self.binaryOp(node, self._div_op)
+
+    def visitFloorDiv(self, node):
+        return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
+
+    def visitMod(self, node):
+        return self.binaryOp(node, 'BINARY_MODULO')
+
+    def visitPower(self, node):
+        return self.binaryOp(node, 'BINARY_POWER')
+
+    def visitLeftShift(self, node):
+        return self.binaryOp(node, 'BINARY_LSHIFT')
+
+    def visitRightShift(self, node):
+        return self.binaryOp(node, 'BINARY_RSHIFT')
+
+    # unary ops
+
+    def unaryOp(self, node, op):
+        self.visit(node.expr)
+        self.emit(op)
+
+    def visitInvert(self, node):
+        return self.unaryOp(node, 'UNARY_INVERT')
+
+    def visitUnarySub(self, node):
+        return self.unaryOp(node, 'UNARY_NEGATIVE')
+
+    def visitUnaryAdd(self, node):
+        return self.unaryOp(node, 'UNARY_POSITIVE')
+
+    def visitUnaryInvert(self, node):
+        return self.unaryOp(node, 'UNARY_INVERT')
+
+    def visitNot(self, node):
+        return self.unaryOp(node, 'UNARY_NOT')
+
+    def visitBackquote(self, node):
+        return self.unaryOp(node, 'UNARY_CONVERT')
+
+    # bit ops
+
+    def bitOp(self, nodes, op):
+        self.visit(nodes[0])
+        for node in nodes[1:]:
+            self.visit(node)
+            self.emit(op)
+
+    def visitBitand(self, node):
+        return self.bitOp(node.nodes, 'BINARY_AND')
+
+    def visitBitor(self, node):
+        return self.bitOp(node.nodes, 'BINARY_OR')
+
+    def visitBitxor(self, node):
+        return self.bitOp(node.nodes, 'BINARY_XOR')
+
+    # object constructors
+
+    def visitEllipsis(self, node):
+        self.emit('LOAD_CONST', Ellipsis)
+
+    def visitTuple(self, node):
+        self.set_lineno(node)
+        for elt in node.nodes:
+            self.visit(elt)
+        self.emit('BUILD_TUPLE', len(node.nodes))
+
+    def visitList(self, node):
+        self.set_lineno(node)
+        for elt in node.nodes:
+            self.visit(elt)
+        self.emit('BUILD_LIST', len(node.nodes))
+
+    def visitSliceobj(self, node):
+        for child in node.nodes:
+            self.visit(child)
+        self.emit('BUILD_SLICE', len(node.nodes))
+
+    def visitDict(self, node):
+        self.set_lineno(node)
+        self.emit('BUILD_MAP', 0)
+        for k, v in node.items:
+            self.emit('DUP_TOP')
+            self.visit(k)
+            self.visit(v)
+            self.emit('ROT_THREE')
+            self.emit('STORE_SUBSCR')
+
+class NestedScopeMixin:
+    """Defines initClass() for nested scoping (Python 2.2-compatible)"""
+    def initClass(self):
+        self.__class__.NameFinder = LocalNameFinder
+        self.__class__.FunctionGen = FunctionCodeGenerator
+        self.__class__.ClassGen = ClassCodeGenerator
+
+class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
+    __super_init = CodeGenerator.__init__
+
+    scopes = None
+
+    def __init__(self, tree):
+        self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
+        self.futures = future.find_futures(tree)
+        self.__super_init()
+        walk(tree, self)
+
+    def get_module(self):
+        return self
+
+class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
+    __super_init = CodeGenerator.__init__
+
+    scopes = None
+    futures = ()
+
+    def __init__(self, tree):
+        self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
+        self.__super_init()
+        walk(tree, self)
+
+    def get_module(self):
+        return self
+
+class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
+
+    __super_init = CodeGenerator.__init__
+
+    scopes = None
+    futures = ()
+
+    def __init__(self, tree):
+        self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
+        self.__super_init()
+        self.set_lineno(tree)
+        walk(tree, self)
+        self.emit('RETURN_VALUE')
+
+    def get_module(self):
+        return self
+
+    def visitDiscard(self, node):
+        # XXX Discard means it's an expression.  Perhaps this is a bad
+        # name.
+        self.visit(node.expr)
+        self.emit('PRINT_EXPR')
+
+class AbstractFunctionCode:
+    optimized = 1
+    lambdaCount = 0
+
+    def __init__(self, func, scopes, isLambda, class_name, mod):
+        self.class_name = class_name
+        self.module = mod
+        if isLambda:
+            klass = FunctionCodeGenerator
+            name = "<lambda.%d>" % klass.lambdaCount
+            klass.lambdaCount = klass.lambdaCount + 1
+        else:
+            name = func.name
+
+        args, hasTupleArg = generateArgList(func.argnames)
+        self.graph = pyassem.PyFlowGraph(name, func.filename, args,
+                                         optimized=1)
+        self.isLambda = isLambda
+        self.super_init()
+
+        if not isLambda and func.doc:
+            self.setDocstring(func.doc)
+
+        lnf = walk(func.code, self.NameFinder(args), verbose=0)
+        self.locals.push(lnf.getLocals())
+        if func.varargs:
+            self.graph.setFlag(CO_VARARGS)
+        if func.kwargs:
+            self.graph.setFlag(CO_VARKEYWORDS)
+        self.set_lineno(func)
+        if hasTupleArg:
+            self.generateArgUnpack(func.argnames)
+
+    def get_module(self):
+        return self.module
+
+    def finish(self):
+        self.graph.startExitBlock()
+        if not self.isLambda:
+            self.emit('LOAD_CONST', None)
+        self.emit('RETURN_VALUE')
+
+    def generateArgUnpack(self, args):
+        for i in range(len(args)):
+            arg = args[i]
+            if isinstance(arg, tuple):
+                self.emit('LOAD_FAST', '.%d' % (i * 2))
+                self.unpackSequence(arg)
+
+    def unpackSequence(self, tup):
+        if VERSION > 1:
+            self.emit('UNPACK_SEQUENCE', len(tup))
+        else:
+            self.emit('UNPACK_TUPLE', len(tup))
+        for elt in tup:
+            if isinstance(elt, tuple):
+                self.unpackSequence(elt)
+            else:
+                self._nameOp('STORE', elt)
+
+    unpackTuple = unpackSequence
+
+class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
+                            CodeGenerator):
+    super_init = CodeGenerator.__init__ # call be other init
+    scopes = None
+
+    __super_init = AbstractFunctionCode.__init__
+
+    def __init__(self, func, scopes, isLambda, class_name, mod):
+        self.scopes = scopes
+        self.scope = scopes[func]
+        self.__super_init(func, scopes, isLambda, class_name, mod)
+        self.graph.setFreeVars(self.scope.get_free_vars())
+        self.graph.setCellVars(self.scope.get_cell_vars())
+        if self.scope.generator is not None:
+            self.graph.setFlag(CO_GENERATOR)
+
+class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
+                           CodeGenerator):
+    super_init = CodeGenerator.__init__ # call be other init
+    scopes = None
+
+    __super_init = AbstractFunctionCode.__init__
+
+    def __init__(self, gexp, scopes, class_name, mod):
+        self.scopes = scopes
+        self.scope = scopes[gexp]
+        self.__super_init(gexp, scopes, 1, class_name, mod)
+        self.graph.setFreeVars(self.scope.get_free_vars())
+        self.graph.setCellVars(self.scope.get_cell_vars())
+        self.graph.setFlag(CO_GENERATOR)
+
+class AbstractClassCode:
+
+    def __init__(self, klass, scopes, module):
+        self.class_name = klass.name
+        self.module = module
+        self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
+                                           optimized=0, klass=1)
+        self.super_init()
+        lnf = walk(klass.code, self.NameFinder(), verbose=0)
+        self.locals.push(lnf.getLocals())
+        self.graph.setFlag(CO_NEWLOCALS)
+        if klass.doc:
+            self.setDocstring(klass.doc)
+
+    def get_module(self):
+        return self.module
+
+    def finish(self):
+        self.graph.startExitBlock()
+        self.emit('LOAD_LOCALS')
+        self.emit('RETURN_VALUE')
+
+class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
+    super_init = CodeGenerator.__init__
+    scopes = None
+
+    __super_init = AbstractClassCode.__init__
+
+    def __init__(self, klass, scopes, module):
+        self.scopes = scopes
+        self.scope = scopes[klass]
+        self.__super_init(klass, scopes, module)
+        self.graph.setFreeVars(self.scope.get_free_vars())
+        self.graph.setCellVars(self.scope.get_cell_vars())
+        self.set_lineno(klass)
+        self.emit("LOAD_GLOBAL", "__name__")
+        self.storeName("__module__")
+        if klass.doc:
+            self.emit("LOAD_CONST", klass.doc)
+            self.storeName('__doc__')
+
+def generateArgList(arglist):
+    """Generate an arg list marking TupleArgs"""
+    args = []
+    extra = []
+    count = 0
+    for i in range(len(arglist)):
+        elt = arglist[i]
+        if isinstance(elt, str):
+            args.append(elt)
+        elif isinstance(elt, tuple):
+            args.append(TupleArg(i * 2, elt))
+            extra.extend(misc.flatten(elt))
+            count = count + 1
+        else:
+            raise ValueError, "unexpect argument type:", elt
+    return args + extra, count
+
+def findOp(node):
+    """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
+    v = OpFinder()
+    walk(node, v, verbose=0)
+    return v.op
+
+class OpFinder:
+    def __init__(self):
+        self.op = None
+    def visitAssName(self, node):
+        if self.op is None:
+            self.op = node.flags
+        elif self.op != node.flags:
+            raise ValueError, "mixed ops in stmt"
+    visitAssAttr = visitAssName
+    visitSubscript = visitAssName
+
+class Delegator:
+    """Base class to support delegation for augmented assignment nodes
+
+    To generator code for augmented assignments, we use the following
+    wrapper classes.  In visitAugAssign, the left-hand expression node
+    is visited twice.  The first time the visit uses the normal method
+    for that node .  The second time the visit uses a different method
+    that generates the appropriate code to perform the assignment.
+    These delegator classes wrap the original AST nodes in order to
+    support the variant visit methods.
+    """
+    def __init__(self, obj):
+        self.obj = obj
+
+    def __getattr__(self, attr):
+        return getattr(self.obj, attr)
+
+class AugGetattr(Delegator):
+    pass
+
+class AugName(Delegator):
+    pass
+
+class AugSlice(Delegator):
+    pass
+
+class AugSubscript(Delegator):
+    pass
+
+wrapper = {
+    ast.Getattr: AugGetattr,
+    ast.Name: AugName,
+    ast.Slice: AugSlice,
+    ast.Subscript: AugSubscript,
+    }
+
+def wrap_aug(node):
+    return wrapper[node.__class__](node)
+
+if __name__ == "__main__":
+    for file in sys.argv[1:]:
+        compileFile(file)
diff --git a/src/main/resources/PythonLibs/compiler/symbols.py b/src/main/resources/PythonLibs/compiler/symbols.py
new file mode 100644
index 0000000000000000000000000000000000000000..afeec501538fd652f78b6fcb6ec24c34bad62aa8
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/symbols.py
@@ -0,0 +1,462 @@
+"""Module symbol-table generator"""
+
+from compiler import ast
+from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \
+    SC_FREE, SC_CELL, SC_UNKNOWN
+from compiler.misc import mangle
+import types
+
+
+import sys
+
+MANGLE_LEN = 256
+
+class Scope:
+    # XXX how much information do I need about each name?
+    def __init__(self, name, module, klass=None):
+        self.name = name
+        self.module = module
+        self.defs = {}
+        self.uses = {}
+        self.globals = {}
+        self.params = {}
+        self.frees = {}
+        self.cells = {}
+        self.children = []
+        # nested is true if the class could contain free variables,
+        # i.e. if it is nested within another function.
+        self.nested = None
+        self.generator = None
+        self.klass = None
+        if klass is not None:
+            for i in range(len(klass)):
+                if klass[i] != '_':
+                    self.klass = klass[i:]
+                    break
+
+    def __repr__(self):
+        return "<%s: %s>" % (self.__class__.__name__, self.name)
+
+    def mangle(self, name):
+        if self.klass is None:
+            return name
+        return mangle(name, self.klass)
+
+    def add_def(self, name):
+        self.defs[self.mangle(name)] = 1
+
+    def add_use(self, name):
+        self.uses[self.mangle(name)] = 1
+
+    def add_global(self, name):
+        name = self.mangle(name)
+        if name in self.uses or name in self.defs:
+            pass # XXX warn about global following def/use
+        if name in self.params:
+            raise SyntaxError, "%s in %s is global and parameter" % \
+                  (name, self.name)
+        self.globals[name] = 1
+        self.module.add_def(name)
+
+    def add_param(self, name):
+        name = self.mangle(name)
+        self.defs[name] = 1
+        self.params[name] = 1
+
+    def get_names(self):
+        d = {}
+        d.update(self.defs)
+        d.update(self.uses)
+        d.update(self.globals)
+        return d.keys()
+
+    def add_child(self, child):
+        self.children.append(child)
+
+    def get_children(self):
+        return self.children
+
+    def DEBUG(self):
+        print >> sys.stderr, self.name, self.nested and "nested" or ""
+        print >> sys.stderr, "\tglobals: ", self.globals
+        print >> sys.stderr, "\tcells: ", self.cells
+        print >> sys.stderr, "\tdefs: ", self.defs
+        print >> sys.stderr, "\tuses: ", self.uses
+        print >> sys.stderr, "\tfrees:", self.frees
+
+    def check_name(self, name):
+        """Return scope of name.
+
+        The scope of a name could be LOCAL, GLOBAL, FREE, or CELL.
+        """
+        if name in self.globals:
+            return SC_GLOBAL_EXPLICIT
+        if name in self.cells:
+            return SC_CELL
+        if name in self.defs:
+            return SC_LOCAL
+        if self.nested and (name in self.frees or name in self.uses):
+            return SC_FREE
+        if self.nested:
+            return SC_UNKNOWN
+        else:
+            return SC_GLOBAL_IMPLICIT
+
+    def get_free_vars(self):
+        if not self.nested:
+            return ()
+        free = {}
+        free.update(self.frees)
+        for name in self.uses.keys():
+            if name not in self.defs and name not in self.globals:
+                free[name] = 1
+        return free.keys()
+
+    def handle_children(self):
+        for child in self.children:
+            frees = child.get_free_vars()
+            globals = self.add_frees(frees)
+            for name in globals:
+                child.force_global(name)
+
+    def force_global(self, name):
+        """Force name to be global in scope.
+
+        Some child of the current node had a free reference to name.
+        When the child was processed, it was labelled a free
+        variable.  Now that all its enclosing scope have been
+        processed, the name is known to be a global or builtin.  So
+        walk back down the child chain and set the name to be global
+        rather than free.
+
+        Be careful to stop if a child does not think the name is
+        free.
+        """
+        self.globals[name] = 1
+        if name in self.frees:
+            del self.frees[name]
+        for child in self.children:
+            if child.check_name(name) == SC_FREE:
+                child.force_global(name)
+
+    def add_frees(self, names):
+        """Process list of free vars from nested scope.
+
+        Returns a list of names that are either 1) declared global in the
+        parent or 2) undefined in a top-level parent.  In either case,
+        the nested scope should treat them as globals.
+        """
+        child_globals = []
+        for name in names:
+            sc = self.check_name(name)
+            if self.nested:
+                if sc == SC_UNKNOWN or sc == SC_FREE \
+                   or isinstance(self, ClassScope):
+                    self.frees[name] = 1
+                elif sc == SC_GLOBAL_IMPLICIT:
+                    child_globals.append(name)
+                elif isinstance(self, FunctionScope) and sc == SC_LOCAL:
+                    self.cells[name] = 1
+                elif sc != SC_CELL:
+                    child_globals.append(name)
+            else:
+                if sc == SC_LOCAL:
+                    self.cells[name] = 1
+                elif sc != SC_CELL:
+                    child_globals.append(name)
+        return child_globals
+
+    def get_cell_vars(self):
+        return self.cells.keys()
+
+class ModuleScope(Scope):
+    __super_init = Scope.__init__
+
+    def __init__(self):
+        self.__super_init("global", self)
+
+class FunctionScope(Scope):
+    pass
+
+class GenExprScope(Scope):
+    __super_init = Scope.__init__
+
+    __counter = 1
+
+    def __init__(self, module, klass=None):
+        i = self.__counter
+        self.__counter += 1
+        self.__super_init("generator expression<%d>"%i, module, klass)
+        self.add_param('.0')
+
+    def get_names(self):
+        keys = Scope.get_names(self)
+        return keys
+
+class LambdaScope(FunctionScope):
+    __super_init = Scope.__init__
+
+    __counter = 1
+
+    def __init__(self, module, klass=None):
+        i = self.__counter
+        self.__counter += 1
+        self.__super_init("lambda.%d" % i, module, klass)
+
+class ClassScope(Scope):
+    __super_init = Scope.__init__
+
+    def __init__(self, name, module):
+        self.__super_init(name, module, name)
+
+class SymbolVisitor:
+    def __init__(self):
+        self.scopes = {}
+        self.klass = None
+
+    # node that define new scopes
+
+    def visitModule(self, node):
+        scope = self.module = self.scopes[node] = ModuleScope()
+        self.visit(node.node, scope)
+
+    visitExpression = visitModule
+
+    def visitFunction(self, node, parent):
+        if node.decorators:
+            self.visit(node.decorators, parent)
+        parent.add_def(node.name)
+        for n in node.defaults:
+            self.visit(n, parent)
+        scope = FunctionScope(node.name, self.module, self.klass)
+        if parent.nested or isinstance(parent, FunctionScope):
+            scope.nested = 1
+        self.scopes[node] = scope
+        self._do_args(scope, node.argnames)
+        self.visit(node.code, scope)
+        self.handle_free_vars(scope, parent)
+
+    def visitGenExpr(self, node, parent):
+        scope = GenExprScope(self.module, self.klass);
+        if parent.nested or isinstance(parent, FunctionScope) \
+                or isinstance(parent, GenExprScope):
+            scope.nested = 1
+
+        self.scopes[node] = scope
+        self.visit(node.code, scope)
+
+        self.handle_free_vars(scope, parent)
+
+    def visitGenExprInner(self, node, scope):
+        for genfor in node.quals:
+            self.visit(genfor, scope)
+
+        self.visit(node.expr, scope)
+
+    def visitGenExprFor(self, node, scope):
+        self.visit(node.assign, scope, 1)
+        self.visit(node.iter, scope)
+        for if_ in node.ifs:
+            self.visit(if_, scope)
+
+    def visitGenExprIf(self, node, scope):
+        self.visit(node.test, scope)
+
+    def visitLambda(self, node, parent, assign=0):
+        # Lambda is an expression, so it could appear in an expression
+        # context where assign is passed.  The transformer should catch
+        # any code that has a lambda on the left-hand side.
+        assert not assign
+
+        for n in node.defaults:
+            self.visit(n, parent)
+        scope = LambdaScope(self.module, self.klass)
+        if parent.nested or isinstance(parent, FunctionScope):
+            scope.nested = 1
+        self.scopes[node] = scope
+        self._do_args(scope, node.argnames)
+        self.visit(node.code, scope)
+        self.handle_free_vars(scope, parent)
+
+    def _do_args(self, scope, args):
+        for name in args:
+            if type(name) == types.TupleType:
+                self._do_args(scope, name)
+            else:
+                scope.add_param(name)
+
+    def handle_free_vars(self, scope, parent):
+        parent.add_child(scope)
+        scope.handle_children()
+
+    def visitClass(self, node, parent):
+        parent.add_def(node.name)
+        for n in node.bases:
+            self.visit(n, parent)
+        scope = ClassScope(node.name, self.module)
+        if parent.nested or isinstance(parent, FunctionScope):
+            scope.nested = 1
+        if node.doc is not None:
+            scope.add_def('__doc__')
+        scope.add_def('__module__')
+        self.scopes[node] = scope
+        prev = self.klass
+        self.klass = node.name
+        self.visit(node.code, scope)
+        self.klass = prev
+        self.handle_free_vars(scope, parent)
+
+    # name can be a def or a use
+
+    # XXX a few calls and nodes expect a third "assign" arg that is
+    # true if the name is being used as an assignment.  only
+    # expressions contained within statements may have the assign arg.
+
+    def visitName(self, node, scope, assign=0):
+        if assign:
+            scope.add_def(node.name)
+        else:
+            scope.add_use(node.name)
+
+    # operations that bind new names
+
+    def visitFor(self, node, scope):
+        self.visit(node.assign, scope, 1)
+        self.visit(node.list, scope)
+        self.visit(node.body, scope)
+        if node.else_:
+            self.visit(node.else_, scope)
+
+    def visitFrom(self, node, scope):
+        for name, asname in node.names:
+            if name == "*":
+                continue
+            scope.add_def(asname or name)
+
+    def visitImport(self, node, scope):
+        for name, asname in node.names:
+            i = name.find(".")
+            if i > -1:
+                name = name[:i]
+            scope.add_def(asname or name)
+
+    def visitGlobal(self, node, scope):
+        for name in node.names:
+            scope.add_global(name)
+
+    def visitAssign(self, node, scope):
+        """Propagate assignment flag down to child nodes.
+
+        The Assign node doesn't itself contains the variables being
+        assigned to.  Instead, the children in node.nodes are visited
+        with the assign flag set to true.  When the names occur in
+        those nodes, they are marked as defs.
+
+        Some names that occur in an assignment target are not bound by
+        the assignment, e.g. a name occurring inside a slice.  The
+        visitor handles these nodes specially; they do not propagate
+        the assign flag to their children.
+        """
+        for n in node.nodes:
+            self.visit(n, scope, 1)
+        self.visit(node.expr, scope)
+
+    def visitAssName(self, node, scope, assign=1):
+        scope.add_def(node.name)
+
+    def visitAssAttr(self, node, scope, assign=0):
+        self.visit(node.expr, scope, 0)
+
+    def visitSubscript(self, node, scope, assign=0):
+        self.visit(node.expr, scope, 0)
+        for n in node.subs:
+            self.visit(n, scope, 0)
+
+    def visitSlice(self, node, scope, assign=0):
+        self.visit(node.expr, scope, 0)
+        if node.lower:
+            self.visit(node.lower, scope, 0)
+        if node.upper:
+            self.visit(node.upper, scope, 0)
+
+    def visitAugAssign(self, node, scope):
+        # If the LHS is a name, then this counts as assignment.
+        # Otherwise, it's just use.
+        self.visit(node.node, scope)
+        if isinstance(node.node, ast.Name):
+            self.visit(node.node, scope, 1) # XXX worry about this
+        self.visit(node.expr, scope)
+
+    # prune if statements if tests are false
+
+    _const_types = types.StringType, types.IntType, types.FloatType
+
+    def visitIf(self, node, scope):
+        for test, body in node.tests:
+            if isinstance(test, ast.Const):
+                if type(test.value) in self._const_types:
+                    if not test.value:
+                        continue
+            self.visit(test, scope)
+            self.visit(body, scope)
+        if node.else_:
+            self.visit(node.else_, scope)
+
+    # a yield statement signals a generator
+
+    def visitYield(self, node, scope):
+        scope.generator = 1
+        self.visit(node.value, scope)
+
+def list_eq(l1, l2):
+    return sorted(l1) == sorted(l2)
+
+if __name__ == "__main__":
+    import sys
+    from compiler import parseFile, walk
+    import symtable
+
+    def get_names(syms):
+        return [s for s in [s.get_name() for s in syms.get_symbols()]
+                if not (s.startswith('_[') or s.startswith('.'))]
+
+    for file in sys.argv[1:]:
+        print file
+        f = open(file)
+        buf = f.read()
+        f.close()
+        syms = symtable.symtable(buf, file, "exec")
+        mod_names = get_names(syms)
+        tree = parseFile(file)
+        s = SymbolVisitor()
+        walk(tree, s)
+
+        # compare module-level symbols
+        names2 = s.scopes[tree].get_names()
+
+        if not list_eq(mod_names, names2):
+            print
+            print "oops", file
+            print sorted(mod_names)
+            print sorted(names2)
+            sys.exit(-1)
+
+        d = {}
+        d.update(s.scopes)
+        del d[tree]
+        scopes = d.values()
+        del d
+
+        for s in syms.get_symbols():
+            if s.is_namespace():
+                l = [sc for sc in scopes
+                     if sc.name == s.get_name()]
+                if len(l) > 1:
+                    print "skipping", s.get_name()
+                else:
+                    if not list_eq(get_names(s.get_namespace()),
+                                   l[0].get_names()):
+                        print s.get_name()
+                        print sorted(get_names(s.get_namespace()))
+                        print sorted(l[0].get_names())
+                        sys.exit(-1)
diff --git a/src/main/resources/PythonLibs/compiler/syntax.py b/src/main/resources/PythonLibs/compiler/syntax.py
new file mode 100644
index 0000000000000000000000000000000000000000..a45d9c2cf6f3f797f5ba3fbc883cfeecc1290fb1
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/syntax.py
@@ -0,0 +1,46 @@
+"""Check for errs in the AST.
+
+The Python parser does not catch all syntax errors.  Others, like
+assignments with invalid targets, are caught in the code generation
+phase.
+
+The compiler package catches some errors in the transformer module.
+But it seems clearer to write checkers that use the AST to detect
+errors.
+"""
+
+from compiler import ast, walk
+
+def check(tree, multi=None):
+    v = SyntaxErrorChecker(multi)
+    walk(tree, v)
+    return v.errors
+
+class SyntaxErrorChecker:
+    """A visitor to find syntax errors in the AST."""
+
+    def __init__(self, multi=None):
+        """Create new visitor object.
+
+        If optional argument multi is not None, then print messages
+        for each error rather than raising a SyntaxError for the
+        first.
+        """
+        self.multi = multi
+        self.errors = 0
+
+    def error(self, node, msg):
+        self.errors = self.errors + 1
+        if self.multi is not None:
+            print "%s:%s: %s" % (node.filename, node.lineno, msg)
+        else:
+            raise SyntaxError, "%s (%s:%s)" % (msg, node.filename, node.lineno)
+
+    def visitAssign(self, node):
+        # the transformer module handles many of these
+        pass
+##        for target in node.nodes:
+##            if isinstance(target, ast.AssList):
+##                if target.lineno is None:
+##                    target.lineno = node.lineno
+##                self.error(target, "can't assign to list comprehension")
diff --git a/src/main/resources/PythonLibs/compiler/transformer.py b/src/main/resources/PythonLibs/compiler/transformer.py
new file mode 100644
index 0000000000000000000000000000000000000000..fefa1a8f8b42e5cfcd4daade726378deffea990a
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/transformer.py
@@ -0,0 +1,1491 @@
+"""Parse tree transformation module.
+
+Transforms Python source code into an abstract syntax tree (AST)
+defined in the ast module.
+
+The simplest ways to invoke this module are via parse and parseFile.
+parse(buf) -> AST
+parseFile(path) -> AST
+"""
+
+# Original version written by Greg Stein (gstein@lyra.org)
+#                         and Bill Tutt (rassilon@lima.mudlib.org)
+# February 1997.
+#
+# Modifications and improvements for Python 2.0 by Jeremy Hylton and
+# Mark Hammond
+#
+# Some fixes to try to have correct line number on almost all nodes
+# (except Module, Discard and Stmt) added by Sylvain Thenault
+#
+# Portions of this file are:
+# Copyright (C) 1997-1998 Greg Stein. All Rights Reserved.
+#
+# This module is provided under a BSD-ish license. See
+#   http://www.opensource.org/licenses/bsd-license.html
+# and replace OWNER, ORGANIZATION, and YEAR as appropriate.
+
+from compiler.ast import *
+import symbol
+import token
+import sys
+if not sys.platform.startswith('java'):
+    import parser
+
+class WalkerError(StandardError):
+    pass
+
+from compiler.consts import CO_VARARGS, CO_VARKEYWORDS
+from compiler.consts import OP_ASSIGN, OP_DELETE, OP_APPLY
+
+def parseFile(path):
+    f = open(path, "U")
+    # XXX The parser API tolerates files without a trailing newline,
+    # but not strings without a trailing newline.  Always add an extra
+    # newline to the file contents, since we're going through the string
+    # version of the API.
+    src = f.read() + "\n"
+    f.close()
+    return parse(src)
+
+def parse(buf, mode="exec"):
+    if mode == "exec" or mode == "single":
+        return Transformer().parsesuite(buf)
+    elif mode == "eval":
+        return Transformer().parseexpr(buf)
+    else:
+        raise ValueError("compile() arg 3 must be"
+                         " 'exec' or 'eval' or 'single'")
+
+def asList(nodes):
+    l = []
+    for item in nodes:
+        if hasattr(item, "asList"):
+            l.append(item.asList())
+        else:
+            if type(item) is type( (None, None) ):
+                l.append(tuple(asList(item)))
+            elif type(item) is type( [] ):
+                l.append(asList(item))
+            else:
+                l.append(item)
+    return l
+
+def extractLineNo(ast):
+    if not isinstance(ast[1], tuple):
+        # get a terminal node
+        return ast[2]
+    for child in ast[1:]:
+        if isinstance(child, tuple):
+            lineno = extractLineNo(child)
+            if lineno is not None:
+                return lineno
+
+def Node(*args):
+    kind = args[0]
+    if nodes.has_key(kind):
+        try:
+            return nodes[kind](*args[1:])
+        except TypeError:
+            print nodes[kind], len(args), args
+            raise
+    else:
+        raise WalkerError, "Can't find appropriate Node type: %s" % str(args)
+        #return apply(ast.Node, args)
+
+class Transformer:
+    """Utility object for transforming Python parse trees.
+
+    Exposes the following methods:
+        tree = transform(ast_tree)
+        tree = parsesuite(text)
+        tree = parseexpr(text)
+        tree = parsefile(fileob | filename)
+    """
+
+    def __init__(self):
+        self._dispatch = {}
+        for value, name in symbol.sym_name.items():
+            if hasattr(self, name):
+                self._dispatch[value] = getattr(self, name)
+        self._dispatch[token.NEWLINE] = self.com_NEWLINE
+        self._atom_dispatch = {token.LPAR: self.atom_lpar,
+                               token.LSQB: self.atom_lsqb,
+                               token.LBRACE: self.atom_lbrace,
+                               token.BACKQUOTE: self.atom_backquote,
+                               token.NUMBER: self.atom_number,
+                               token.STRING: self.atom_string,
+                               token.NAME: self.atom_name,
+                               }
+        self.encoding = None
+
+    def transform(self, tree):
+        """Transform an AST into a modified parse tree."""
+        if not (isinstance(tree, tuple) or isinstance(tree, list)):
+            tree = parser.ast2tuple(tree, line_info=1)
+        return self.compile_node(tree)
+
+    def parsesuite(self, text):
+        """Return a modified parse tree for the given suite text."""
+        return self.transform(parser.suite(text))
+
+    def parseexpr(self, text):
+        """Return a modified parse tree for the given expression text."""
+        return self.transform(parser.expr(text))
+
+    def parsefile(self, file):
+        """Return a modified parse tree for the contents of the given file."""
+        if type(file) == type(''):
+            file = open(file)
+        return self.parsesuite(file.read())
+
+    # --------------------------------------------------------------
+    #
+    # PRIVATE METHODS
+    #
+
+    def compile_node(self, node):
+        ### emit a line-number node?
+        n = node[0]
+
+        if n == symbol.encoding_decl:
+            self.encoding = node[2]
+            node = node[1]
+            n = node[0]
+
+        if n == symbol.single_input:
+            return self.single_input(node[1:])
+        if n == symbol.file_input:
+            return self.file_input(node[1:])
+        if n == symbol.eval_input:
+            return self.eval_input(node[1:])
+        if n == symbol.lambdef:
+            return self.lambdef(node[1:])
+        if n == symbol.funcdef:
+            return self.funcdef(node[1:])
+        if n == symbol.classdef:
+            return self.classdef(node[1:])
+
+        raise WalkerError, ('unexpected node type', n)
+
+    def single_input(self, node):
+        ### do we want to do anything about being "interactive" ?
+
+        # NEWLINE | simple_stmt | compound_stmt NEWLINE
+        n = node[0][0]
+        if n != token.NEWLINE:
+            return self.com_stmt(node[0])
+
+        return Pass()
+
+    def file_input(self, nodelist):
+        doc = self.get_docstring(nodelist, symbol.file_input)
+        if doc is not None:
+            i = 1
+        else:
+            i = 0
+        stmts = []
+        for node in nodelist[i:]:
+            if node[0] != token.ENDMARKER and node[0] != token.NEWLINE:
+                self.com_append_stmt(stmts, node)
+        return Module(doc, Stmt(stmts))
+
+    def eval_input(self, nodelist):
+        # from the built-in function input()
+        ### is this sufficient?
+        return Expression(self.com_node(nodelist[0]))
+
+    def decorator_name(self, nodelist):
+        listlen = len(nodelist)
+        assert listlen >= 1 and listlen % 2 == 1
+
+        item = self.atom_name(nodelist)
+        i = 1
+        while i < listlen:
+            assert nodelist[i][0] == token.DOT
+            assert nodelist[i + 1][0] == token.NAME
+            item = Getattr(item, nodelist[i + 1][1])
+            i += 2
+
+        return item
+
+    def decorator(self, nodelist):
+        # '@' dotted_name [ '(' [arglist] ')' ]
+        assert len(nodelist) in (3, 5, 6)
+        assert nodelist[0][0] == token.AT
+        assert nodelist[-1][0] == token.NEWLINE
+
+        assert nodelist[1][0] == symbol.dotted_name
+        funcname = self.decorator_name(nodelist[1][1:])
+
+        if len(nodelist) > 3:
+            assert nodelist[2][0] == token.LPAR
+            expr = self.com_call_function(funcname, nodelist[3])
+        else:
+            expr = funcname
+
+        return expr
+
+    def decorators(self, nodelist):
+        # decorators: decorator ([NEWLINE] decorator)* NEWLINE
+        items = []
+        for dec_nodelist in nodelist:
+            assert dec_nodelist[0] == symbol.decorator
+            items.append(self.decorator(dec_nodelist[1:]))
+        return Decorators(items)
+
+    def funcdef(self, nodelist):
+        #                    -6   -5    -4         -3  -2    -1
+        # funcdef: [decorators] 'def' NAME parameters ':' suite
+        # parameters: '(' [varargslist] ')'
+
+        if len(nodelist) == 6:
+            assert nodelist[0][0] == symbol.decorators
+            decorators = self.decorators(nodelist[0][1:])
+        else:
+            assert len(nodelist) == 5
+            decorators = None
+
+        lineno = nodelist[-4][2]
+        name = nodelist[-4][1]
+        args = nodelist[-3][2]
+
+        if args[0] == symbol.varargslist:
+            names, defaults, flags = self.com_arglist(args[1:])
+        else:
+            names = defaults = ()
+            flags = 0
+        doc = self.get_docstring(nodelist[-1])
+
+        # code for function
+        code = self.com_node(nodelist[-1])
+
+        if doc is not None:
+            assert isinstance(code, Stmt)
+            assert isinstance(code.nodes[0], Discard)
+            del code.nodes[0]
+        return Function(decorators, name, names, defaults, flags, doc, code,
+                     lineno=lineno)
+
+    def lambdef(self, nodelist):
+        # lambdef: 'lambda' [varargslist] ':' test
+        if nodelist[2][0] == symbol.varargslist:
+            names, defaults, flags = self.com_arglist(nodelist[2][1:])
+        else:
+            names = defaults = ()
+            flags = 0
+
+        # code for lambda
+        code = self.com_node(nodelist[-1])
+
+        return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
+    old_lambdef = lambdef
+
+    def classdef(self, nodelist):
+        # classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
+
+        name = nodelist[1][1]
+        doc = self.get_docstring(nodelist[-1])
+        if nodelist[2][0] == token.COLON:
+            bases = []
+        elif nodelist[3][0] == token.RPAR:
+            bases = []
+        else:
+            bases = self.com_bases(nodelist[3])
+
+        # code for class
+        code = self.com_node(nodelist[-1])
+
+        if doc is not None:
+            assert isinstance(code, Stmt)
+            assert isinstance(code.nodes[0], Discard)
+            del code.nodes[0]
+
+        return Class(name, bases, doc, code, lineno=nodelist[1][2])
+
+    def stmt(self, nodelist):
+        return self.com_stmt(nodelist[0])
+
+    small_stmt = stmt
+    flow_stmt = stmt
+    compound_stmt = stmt
+
+    def simple_stmt(self, nodelist):
+        # small_stmt (';' small_stmt)* [';'] NEWLINE
+        stmts = []
+        for i in range(0, len(nodelist), 2):
+            self.com_append_stmt(stmts, nodelist[i])
+        return Stmt(stmts)
+
+    def parameters(self, nodelist):
+        raise WalkerError
+
+    def varargslist(self, nodelist):
+        raise WalkerError
+
+    def fpdef(self, nodelist):
+        raise WalkerError
+
+    def fplist(self, nodelist):
+        raise WalkerError
+
+    def dotted_name(self, nodelist):
+        raise WalkerError
+
+    def comp_op(self, nodelist):
+        raise WalkerError
+
+    def trailer(self, nodelist):
+        raise WalkerError
+
+    def sliceop(self, nodelist):
+        raise WalkerError
+
+    def argument(self, nodelist):
+        raise WalkerError
+
+    # --------------------------------------------------------------
+    #
+    # STATEMENT NODES  (invoked by com_node())
+    #
+
+    def expr_stmt(self, nodelist):
+        # augassign testlist | testlist ('=' testlist)*
+        en = nodelist[-1]
+        exprNode = self.lookup_node(en)(en[1:])
+        if len(nodelist) == 1:
+            return Discard(exprNode, lineno=exprNode.lineno)
+        if nodelist[1][0] == token.EQUAL:
+            nodesl = []
+            for i in range(0, len(nodelist) - 2, 2):
+                nodesl.append(self.com_assign(nodelist[i], OP_ASSIGN))
+            return Assign(nodesl, exprNode, lineno=nodelist[1][2])
+        else:
+            lval = self.com_augassign(nodelist[0])
+            op = self.com_augassign_op(nodelist[1])
+            return AugAssign(lval, op[1], exprNode, lineno=op[2])
+        raise WalkerError, "can't get here"
+
+    def print_stmt(self, nodelist):
+        # print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ])
+        items = []
+        if len(nodelist) == 1:
+            start = 1
+            dest = None
+        elif nodelist[1][0] == token.RIGHTSHIFT:
+            assert len(nodelist) == 3 \
+                   or nodelist[3][0] == token.COMMA
+            dest = self.com_node(nodelist[2])
+            start = 4
+        else:
+            dest = None
+            start = 1
+        for i in range(start, len(nodelist), 2):
+            items.append(self.com_node(nodelist[i]))
+        if nodelist[-1][0] == token.COMMA:
+            return Print(items, dest, lineno=nodelist[0][2])
+        return Printnl(items, dest, lineno=nodelist[0][2])
+
+    def del_stmt(self, nodelist):
+        return self.com_assign(nodelist[1], OP_DELETE)
+
+    def pass_stmt(self, nodelist):
+        return Pass(lineno=nodelist[0][2])
+
+    def break_stmt(self, nodelist):
+        return Break(lineno=nodelist[0][2])
+
+    def continue_stmt(self, nodelist):
+        return Continue(lineno=nodelist[0][2])
+
+    def return_stmt(self, nodelist):
+        # return: [testlist]
+        if len(nodelist) < 2:
+            return Return(Const(None), lineno=nodelist[0][2])
+        return Return(self.com_node(nodelist[1]), lineno=nodelist[0][2])
+
+    def yield_stmt(self, nodelist):
+        expr = self.com_node(nodelist[0])
+        return Discard(expr, lineno=expr.lineno)
+
+    def yield_expr(self, nodelist):
+        if len(nodelist) > 1:
+            value = self.com_node(nodelist[1])
+        else:
+            value = Const(None)
+        return Yield(value, lineno=nodelist[0][2])
+
+    def raise_stmt(self, nodelist):
+        # raise: [test [',' test [',' test]]]
+        if len(nodelist) > 5:
+            expr3 = self.com_node(nodelist[5])
+        else:
+            expr3 = None
+        if len(nodelist) > 3:
+            expr2 = self.com_node(nodelist[3])
+        else:
+            expr2 = None
+        if len(nodelist) > 1:
+            expr1 = self.com_node(nodelist[1])
+        else:
+            expr1 = None
+        return Raise(expr1, expr2, expr3, lineno=nodelist[0][2])
+
+    def import_stmt(self, nodelist):
+        # import_stmt: import_name | import_from
+        assert len(nodelist) == 1
+        return self.com_node(nodelist[0])
+
+    def import_name(self, nodelist):
+        # import_name: 'import' dotted_as_names
+        return Import(self.com_dotted_as_names(nodelist[1]),
+                      lineno=nodelist[0][2])
+
+    def import_from(self, nodelist):
+        # import_from: 'from' ('.'* dotted_name | '.') 'import' ('*' |
+        #    '(' import_as_names ')' | import_as_names)
+        assert nodelist[0][1] == 'from'
+        idx = 1
+        while nodelist[idx][1] == '.':
+            idx += 1
+        level = idx - 1
+        if nodelist[idx][0] == symbol.dotted_name:
+            fromname = self.com_dotted_name(nodelist[idx])
+            idx += 1
+        else:
+            fromname = ""
+        assert nodelist[idx][1] == 'import'
+        if nodelist[idx + 1][0] == token.STAR:
+            return From(fromname, [('*', None)], level,
+                        lineno=nodelist[0][2])
+        else:
+            node = nodelist[idx + 1 + (nodelist[idx + 1][0] == token.LPAR)]
+            return From(fromname, self.com_import_as_names(node), level,
+                        lineno=nodelist[0][2])
+
+    def global_stmt(self, nodelist):
+        # global: NAME (',' NAME)*
+        names = []
+        for i in range(1, len(nodelist), 2):
+            names.append(nodelist[i][1])
+        return Global(names, lineno=nodelist[0][2])
+
+    def exec_stmt(self, nodelist):
+        # exec_stmt: 'exec' expr ['in' expr [',' expr]]
+        expr1 = self.com_node(nodelist[1])
+        if len(nodelist) >= 4:
+            expr2 = self.com_node(nodelist[3])
+            if len(nodelist) >= 6:
+                expr3 = self.com_node(nodelist[5])
+            else:
+                expr3 = None
+        else:
+            expr2 = expr3 = None
+
+        return Exec(expr1, expr2, expr3, lineno=nodelist[0][2])
+
+    def assert_stmt(self, nodelist):
+        # 'assert': test, [',' test]
+        expr1 = self.com_node(nodelist[1])
+        if (len(nodelist) == 4):
+            expr2 = self.com_node(nodelist[3])
+        else:
+            expr2 = None
+        return Assert(expr1, expr2, lineno=nodelist[0][2])
+
+    def if_stmt(self, nodelist):
+        # if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+        tests = []
+        for i in range(0, len(nodelist) - 3, 4):
+            testNode = self.com_node(nodelist[i + 1])
+            suiteNode = self.com_node(nodelist[i + 3])
+            tests.append((testNode, suiteNode))
+
+        if len(nodelist) % 4 == 3:
+            elseNode = self.com_node(nodelist[-1])
+##      elseNode.lineno = nodelist[-1][1][2]
+        else:
+            elseNode = None
+        return If(tests, elseNode, lineno=nodelist[0][2])
+
+    def while_stmt(self, nodelist):
+        # 'while' test ':' suite ['else' ':' suite]
+
+        testNode = self.com_node(nodelist[1])
+        bodyNode = self.com_node(nodelist[3])
+
+        if len(nodelist) > 4:
+            elseNode = self.com_node(nodelist[6])
+        else:
+            elseNode = None
+
+        return While(testNode, bodyNode, elseNode, lineno=nodelist[0][2])
+
+    def for_stmt(self, nodelist):
+        # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
+
+        assignNode = self.com_assign(nodelist[1], OP_ASSIGN)
+        listNode = self.com_node(nodelist[3])
+        bodyNode = self.com_node(nodelist[5])
+
+        if len(nodelist) > 8:
+            elseNode = self.com_node(nodelist[8])
+        else:
+            elseNode = None
+
+        return For(assignNode, listNode, bodyNode, elseNode,
+                   lineno=nodelist[0][2])
+
+    def try_stmt(self, nodelist):
+        return self.com_try_except_finally(nodelist)
+
+    def with_stmt(self, nodelist):
+        return self.com_with(nodelist)
+
+    def with_var(self, nodelist):
+        return self.com_with_var(nodelist)
+
+    def suite(self, nodelist):
+        # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
+        if len(nodelist) == 1:
+            return self.com_stmt(nodelist[0])
+
+        stmts = []
+        for node in nodelist:
+            if node[0] == symbol.stmt:
+                self.com_append_stmt(stmts, node)
+        return Stmt(stmts)
+
+    # --------------------------------------------------------------
+    #
+    # EXPRESSION NODES  (invoked by com_node())
+    #
+
+    def testlist(self, nodelist):
+        # testlist: expr (',' expr)* [',']
+        # testlist_safe: test [(',' test)+ [',']]
+        # exprlist: expr (',' expr)* [',']
+        return self.com_binary(Tuple, nodelist)
+
+    testlist_safe = testlist # XXX
+    testlist1 = testlist
+    exprlist = testlist
+
+    def testlist_gexp(self, nodelist):
+        if len(nodelist) == 2 and nodelist[1][0] == symbol.gen_for:
+            test = self.com_node(nodelist[0])
+            return self.com_generator_expression(test, nodelist[1])
+        return self.testlist(nodelist)
+
+    def test(self, nodelist):
+        # or_test ['if' or_test 'else' test] | lambdef
+        if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
+            return self.lambdef(nodelist[0])
+        then = self.com_node(nodelist[0])
+        if len(nodelist) > 1:
+            assert len(nodelist) == 5
+            assert nodelist[1][1] == 'if'
+            assert nodelist[3][1] == 'else'
+            test = self.com_node(nodelist[2])
+            else_ = self.com_node(nodelist[4])
+            return IfExp(test, then, else_, lineno=nodelist[1][2])
+        return then
+
+    def or_test(self, nodelist):
+        # and_test ('or' and_test)* | lambdef
+        if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
+            return self.lambdef(nodelist[0])
+        return self.com_binary(Or, nodelist)
+    old_test = or_test
+
+    def and_test(self, nodelist):
+        # not_test ('and' not_test)*
+        return self.com_binary(And, nodelist)
+
+    def not_test(self, nodelist):
+        # 'not' not_test | comparison
+        result = self.com_node(nodelist[-1])
+        if len(nodelist) == 2:
+            return Not(result, lineno=nodelist[0][2])
+        return result
+
+    def comparison(self, nodelist):
+        # comparison: expr (comp_op expr)*
+        node = self.com_node(nodelist[0])
+        if len(nodelist) == 1:
+            return node
+
+        results = []
+        for i in range(2, len(nodelist), 2):
+            nl = nodelist[i-1]
+
+            # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
+            #          | 'in' | 'not' 'in' | 'is' | 'is' 'not'
+            n = nl[1]
+            if n[0] == token.NAME:
+                type = n[1]
+                if len(nl) == 3:
+                    if type == 'not':
+                        type = 'not in'
+                    else:
+                        type = 'is not'
+            else:
+                type = _cmp_types[n[0]]
+
+            lineno = nl[1][2]
+            results.append((type, self.com_node(nodelist[i])))
+
+        # we need a special "compare" node so that we can distinguish
+        #   3 < x < 5   from    (3 < x) < 5
+        # the two have very different semantics and results (note that the
+        # latter form is always true)
+
+        return Compare(node, results, lineno=lineno)
+
+    def expr(self, nodelist):
+        # xor_expr ('|' xor_expr)*
+        return self.com_binary(Bitor, nodelist)
+
+    def xor_expr(self, nodelist):
+        # xor_expr ('^' xor_expr)*
+        return self.com_binary(Bitxor, nodelist)
+
+    def and_expr(self, nodelist):
+        # xor_expr ('&' xor_expr)*
+        return self.com_binary(Bitand, nodelist)
+
+    def shift_expr(self, nodelist):
+        # shift_expr ('<<'|'>>' shift_expr)*
+        node = self.com_node(nodelist[0])
+        for i in range(2, len(nodelist), 2):
+            right = self.com_node(nodelist[i])
+            if nodelist[i-1][0] == token.LEFTSHIFT:
+                node = LeftShift([node, right], lineno=nodelist[1][2])
+            elif nodelist[i-1][0] == token.RIGHTSHIFT:
+                node = RightShift([node, right], lineno=nodelist[1][2])
+            else:
+                raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
+        return node
+
+    def arith_expr(self, nodelist):
+        node = self.com_node(nodelist[0])
+        for i in range(2, len(nodelist), 2):
+            right = self.com_node(nodelist[i])
+            if nodelist[i-1][0] == token.PLUS:
+                node = Add([node, right], lineno=nodelist[1][2])
+            elif nodelist[i-1][0] == token.MINUS:
+                node = Sub([node, right], lineno=nodelist[1][2])
+            else:
+                raise ValueError, "unexpected token: %s" % nodelist[i-1][0]
+        return node
+
+    def term(self, nodelist):
+        node = self.com_node(nodelist[0])
+        for i in range(2, len(nodelist), 2):
+            right = self.com_node(nodelist[i])
+            t = nodelist[i-1][0]
+            if t == token.STAR:
+                node = Mul([node, right])
+            elif t == token.SLASH:
+                node = Div([node, right])
+            elif t == token.PERCENT:
+                node = Mod([node, right])
+            elif t == token.DOUBLESLASH:
+                node = FloorDiv([node, right])
+            else:
+                raise ValueError, "unexpected token: %s" % t
+            node.lineno = nodelist[1][2]
+        return node
+
+    def factor(self, nodelist):
+        elt = nodelist[0]
+        t = elt[0]
+        node = self.lookup_node(nodelist[-1])(nodelist[-1][1:])
+        # need to handle (unary op)constant here...
+        if t == token.PLUS:
+            return UnaryAdd(node, lineno=elt[2])
+        elif t == token.MINUS:
+            return UnarySub(node, lineno=elt[2])
+        elif t == token.TILDE:
+            node = Invert(node, lineno=elt[2])
+        return node
+
+    def power(self, nodelist):
+        # power: atom trailer* ('**' factor)*
+        node = self.com_node(nodelist[0])
+        for i in range(1, len(nodelist)):
+            elt = nodelist[i]
+            if elt[0] == token.DOUBLESTAR:
+                return Power([node, self.com_node(nodelist[i+1])],
+                             lineno=elt[2])
+
+            node = self.com_apply_trailer(node, elt)
+
+        return node
+
+    def atom(self, nodelist):
+        return self._atom_dispatch[nodelist[0][0]](nodelist)
+
+    def atom_lpar(self, nodelist):
+        if nodelist[1][0] == token.RPAR:
+            return Tuple((), lineno=nodelist[0][2])
+        return self.com_node(nodelist[1])
+
+    def atom_lsqb(self, nodelist):
+        if nodelist[1][0] == token.RSQB:
+            return List((), lineno=nodelist[0][2])
+        return self.com_list_constructor(nodelist[1])
+
+    def atom_lbrace(self, nodelist):
+        if nodelist[1][0] == token.RBRACE:
+            return Dict((), lineno=nodelist[0][2])
+        return self.com_dictmaker(nodelist[1])
+
+    def atom_backquote(self, nodelist):
+        return Backquote(self.com_node(nodelist[1]))
+
+    def atom_number(self, nodelist):
+        ### need to verify this matches compile.c
+        k = eval(nodelist[0][1])
+        return Const(k, lineno=nodelist[0][2])
+
+    def decode_literal(self, lit):
+        if self.encoding:
+            # this is particularly fragile & a bit of a
+            # hack... changes in compile.c:parsestr and
+            # tokenizer.c must be reflected here.
+            if self.encoding not in ['utf-8', 'iso-8859-1']:
+                lit = unicode(lit, 'utf-8').encode(self.encoding)
+            return eval("# coding: %s\n%s" % (self.encoding, lit))
+        else:
+            return eval(lit)
+
+    def atom_string(self, nodelist):
+        k = ''
+        for node in nodelist:
+            k += self.decode_literal(node[1])
+        return Const(k, lineno=nodelist[0][2])
+
+    def atom_name(self, nodelist):
+        return Name(nodelist[0][1], lineno=nodelist[0][2])
+
+    # --------------------------------------------------------------
+    #
+    # INTERNAL PARSING UTILITIES
+    #
+
+    # The use of com_node() introduces a lot of extra stack frames,
+    # enough to cause a stack overflow compiling test.test_parser with
+    # the standard interpreter recursionlimit.  The com_node() is a
+    # convenience function that hides the dispatch details, but comes
+    # at a very high cost.  It is more efficient to dispatch directly
+    # in the callers.  In these cases, use lookup_node() and call the
+    # dispatched node directly.
+
+    def lookup_node(self, node):
+        return self._dispatch[node[0]]
+
+    def com_node(self, node):
+        # Note: compile.c has handling in com_node for del_stmt, pass_stmt,
+        #       break_stmt, stmt, small_stmt, flow_stmt, simple_stmt,
+        #       and compound_stmt.
+        #       We'll just dispatch them.
+        return self._dispatch[node[0]](node[1:])
+
+    def com_NEWLINE(self, *args):
+        # A ';' at the end of a line can make a NEWLINE token appear
+        # here, Render it harmless. (genc discards ('discard',
+        # ('const', xxxx)) Nodes)
+        return Discard(Const(None))
+
+    def com_arglist(self, nodelist):
+        # varargslist:
+        #     (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
+        #   | fpdef ['=' test] (',' fpdef ['=' test])* [',']
+        # fpdef: NAME | '(' fplist ')'
+        # fplist: fpdef (',' fpdef)* [',']
+        names = []
+        defaults = []
+        flags = 0
+
+        i = 0
+        while i < len(nodelist):
+            node = nodelist[i]
+            if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
+                if node[0] == token.STAR:
+                    node = nodelist[i+1]
+                    if node[0] == token.NAME:
+                        names.append(node[1])
+                        flags = flags | CO_VARARGS
+                        i = i + 3
+
+                if i < len(nodelist):
+                    # should be DOUBLESTAR
+                    t = nodelist[i][0]
+                    if t == token.DOUBLESTAR:
+                        node = nodelist[i+1]
+                    else:
+                        raise ValueError, "unexpected token: %s" % t
+                    names.append(node[1])
+                    flags = flags | CO_VARKEYWORDS
+
+                break
+
+            # fpdef: NAME | '(' fplist ')'
+            names.append(self.com_fpdef(node))
+
+            i = i + 1
+            if i < len(nodelist) and nodelist[i][0] == token.EQUAL:
+                defaults.append(self.com_node(nodelist[i + 1]))
+                i = i + 2
+            elif len(defaults):
+                # we have already seen an argument with default, but here
+                # came one without
+                raise SyntaxError, "non-default argument follows default argument"
+
+            # skip the comma
+            i = i + 1
+
+        return names, defaults, flags
+
+    def com_fpdef(self, node):
+        # fpdef: NAME | '(' fplist ')'
+        if node[1][0] == token.LPAR:
+            return self.com_fplist(node[2])
+        return node[1][1]
+
+    def com_fplist(self, node):
+        # fplist: fpdef (',' fpdef)* [',']
+        if len(node) == 2:
+            return self.com_fpdef(node[1])
+        list = []
+        for i in range(1, len(node), 2):
+            list.append(self.com_fpdef(node[i]))
+        return tuple(list)
+
+    def com_dotted_name(self, node):
+        # String together the dotted names and return the string
+        name = ""
+        for n in node:
+            if type(n) == type(()) and n[0] == 1:
+                name = name + n[1] + '.'
+        return name[:-1]
+
+    def com_dotted_as_name(self, node):
+        assert node[0] == symbol.dotted_as_name
+        node = node[1:]
+        dot = self.com_dotted_name(node[0][1:])
+        if len(node) == 1:
+            return dot, None
+        assert node[1][1] == 'as'
+        assert node[2][0] == token.NAME
+        return dot, node[2][1]
+
+    def com_dotted_as_names(self, node):
+        assert node[0] == symbol.dotted_as_names
+        node = node[1:]
+        names = [self.com_dotted_as_name(node[0])]
+        for i in range(2, len(node), 2):
+            names.append(self.com_dotted_as_name(node[i]))
+        return names
+
+    def com_import_as_name(self, node):
+        assert node[0] == symbol.import_as_name
+        node = node[1:]
+        assert node[0][0] == token.NAME
+        if len(node) == 1:
+            return node[0][1], None
+        assert node[1][1] == 'as', node
+        assert node[2][0] == token.NAME
+        return node[0][1], node[2][1]
+
+    def com_import_as_names(self, node):
+        assert node[0] == symbol.import_as_names
+        node = node[1:]
+        names = [self.com_import_as_name(node[0])]
+        for i in range(2, len(node), 2):
+            names.append(self.com_import_as_name(node[i]))
+        return names
+
+    def com_bases(self, node):
+        bases = []
+        for i in range(1, len(node), 2):
+            bases.append(self.com_node(node[i]))
+        return bases
+
+    def com_try_except_finally(self, nodelist):
+        # ('try' ':' suite
+        #  ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite]
+        #   | 'finally' ':' suite))
+
+        if nodelist[3][0] == token.NAME:
+            # first clause is a finally clause: only try-finally
+            return TryFinally(self.com_node(nodelist[2]),
+                              self.com_node(nodelist[5]),
+                              lineno=nodelist[0][2])
+
+        #tryexcept:  [TryNode, [except_clauses], elseNode)]
+        clauses = []
+        elseNode = None
+        finallyNode = None
+        for i in range(3, len(nodelist), 3):
+            node = nodelist[i]
+            if node[0] == symbol.except_clause:
+                # except_clause: 'except' [expr [',' expr]] */
+                if len(node) > 2:
+                    expr1 = self.com_node(node[2])
+                    if len(node) > 4:
+                        expr2 = self.com_assign(node[4], OP_ASSIGN)
+                    else:
+                        expr2 = None
+                else:
+                    expr1 = expr2 = None
+                clauses.append((expr1, expr2, self.com_node(nodelist[i+2])))
+
+            if node[0] == token.NAME:
+                if node[1] == 'else':
+                    elseNode = self.com_node(nodelist[i+2])
+                elif node[1] == 'finally':
+                    finallyNode = self.com_node(nodelist[i+2])
+        try_except = TryExcept(self.com_node(nodelist[2]), clauses, elseNode,
+                               lineno=nodelist[0][2])
+        if finallyNode:
+            return TryFinally(try_except, finallyNode, lineno=nodelist[0][2])
+        else:
+            return try_except
+
+    def com_with(self, nodelist):
+        # with_stmt: 'with' expr [with_var] ':' suite
+        expr = self.com_node(nodelist[1])
+        body = self.com_node(nodelist[-1])
+        if nodelist[2][0] == token.COLON:
+            var = None
+        else:
+            var = self.com_assign(nodelist[2][2], OP_ASSIGN)
+        return With(expr, var, body, lineno=nodelist[0][2])
+
+    def com_with_var(self, nodelist):
+        # with_var: 'as' expr
+        return self.com_node(nodelist[1])
+
+    def com_augassign_op(self, node):
+        assert node[0] == symbol.augassign
+        return node[1]
+
+    def com_augassign(self, node):
+        """Return node suitable for lvalue of augmented assignment
+
+        Names, slices, and attributes are the only allowable nodes.
+        """
+        l = self.com_node(node)
+        if l.__class__ in (Name, Slice, Subscript, Getattr):
+            return l
+        raise SyntaxError, "can't assign to %s" % l.__class__.__name__
+
+    def com_assign(self, node, assigning):
+        # return a node suitable for use as an "lvalue"
+        # loop to avoid trivial recursion
+        while 1:
+            t = node[0]
+            if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_gexp):
+                if len(node) > 2:
+                    return self.com_assign_tuple(node, assigning)
+                node = node[1]
+            elif t in _assign_types:
+                if len(node) > 2:
+                    raise SyntaxError, "can't assign to operator"
+                node = node[1]
+            elif t == symbol.power:
+                if node[1][0] != symbol.atom:
+                    raise SyntaxError, "can't assign to operator"
+                if len(node) > 2:
+                    primary = self.com_node(node[1])
+                    for i in range(2, len(node)-1):
+                        ch = node[i]
+                        if ch[0] == token.DOUBLESTAR:
+                            raise SyntaxError, "can't assign to operator"
+                        primary = self.com_apply_trailer(primary, ch)
+                    return self.com_assign_trailer(primary, node[-1],
+                                                   assigning)
+                node = node[1]
+            elif t == symbol.atom:
+                t = node[1][0]
+                if t == token.LPAR:
+                    node = node[2]
+                    if node[0] == token.RPAR:
+                        raise SyntaxError, "can't assign to ()"
+                elif t == token.LSQB:
+                    node = node[2]
+                    if node[0] == token.RSQB:
+                        raise SyntaxError, "can't assign to []"
+                    return self.com_assign_list(node, assigning)
+                elif t == token.NAME:
+                    return self.com_assign_name(node[1], assigning)
+                else:
+                    raise SyntaxError, "can't assign to literal"
+            else:
+                raise SyntaxError, "bad assignment (%s)" % t
+
+    def com_assign_tuple(self, node, assigning):
+        assigns = []
+        for i in range(1, len(node), 2):
+            assigns.append(self.com_assign(node[i], assigning))
+        return AssTuple(assigns, lineno=extractLineNo(node))
+
+    def com_assign_list(self, node, assigning):
+        assigns = []
+        for i in range(1, len(node), 2):
+            if i + 1 < len(node):
+                if node[i + 1][0] == symbol.list_for:
+                    raise SyntaxError, "can't assign to list comprehension"
+                assert node[i + 1][0] == token.COMMA, node[i + 1]
+            assigns.append(self.com_assign(node[i], assigning))
+        return AssList(assigns, lineno=extractLineNo(node))
+
+    def com_assign_name(self, node, assigning):
+        return AssName(node[1], assigning, lineno=node[2])
+
+    def com_assign_trailer(self, primary, node, assigning):
+        t = node[1][0]
+        if t == token.DOT:
+            return self.com_assign_attr(primary, node[2], assigning)
+        if t == token.LSQB:
+            return self.com_subscriptlist(primary, node[2], assigning)
+        if t == token.LPAR:
+            raise SyntaxError, "can't assign to function call"
+        raise SyntaxError, "unknown trailer type: %s" % t
+
+    def com_assign_attr(self, primary, node, assigning):
+        return AssAttr(primary, node[1], assigning, lineno=node[-1])
+
+    def com_binary(self, constructor, nodelist):
+        "Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])."
+        l = len(nodelist)
+        if l == 1:
+            n = nodelist[0]
+            return self.lookup_node(n)(n[1:])
+        items = []
+        for i in range(0, l, 2):
+            n = nodelist[i]
+            items.append(self.lookup_node(n)(n[1:]))
+        return constructor(items, lineno=extractLineNo(nodelist))
+
+    def com_stmt(self, node):
+        result = self.lookup_node(node)(node[1:])
+        assert result is not None
+        if isinstance(result, Stmt):
+            return result
+        return Stmt([result])
+
+    def com_append_stmt(self, stmts, node):
+        result = self.lookup_node(node)(node[1:])
+        assert result is not None
+        if isinstance(result, Stmt):
+            stmts.extend(result.nodes)
+        else:
+            stmts.append(result)
+
+    if hasattr(symbol, 'list_for'):
+        def com_list_constructor(self, nodelist):
+            # listmaker: test ( list_for | (',' test)* [','] )
+            values = []
+            for i in range(1, len(nodelist)):
+                if nodelist[i][0] == symbol.list_for:
+                    assert len(nodelist[i:]) == 1
+                    return self.com_list_comprehension(values[0],
+                                                       nodelist[i])
+                elif nodelist[i][0] == token.COMMA:
+                    continue
+                values.append(self.com_node(nodelist[i]))
+            return List(values, lineno=values[0].lineno)
+
+        def com_list_comprehension(self, expr, node):
+            # list_iter: list_for | list_if
+            # list_for: 'for' exprlist 'in' testlist [list_iter]
+            # list_if: 'if' test [list_iter]
+
+            # XXX should raise SyntaxError for assignment
+
+            lineno = node[1][2]
+            fors = []
+            while node:
+                t = node[1][1]
+                if t == 'for':
+                    assignNode = self.com_assign(node[2], OP_ASSIGN)
+                    listNode = self.com_node(node[4])
+                    newfor = ListCompFor(assignNode, listNode, [])
+                    newfor.lineno = node[1][2]
+                    fors.append(newfor)
+                    if len(node) == 5:
+                        node = None
+                    else:
+                        node = self.com_list_iter(node[5])
+                elif t == 'if':
+                    test = self.com_node(node[2])
+                    newif = ListCompIf(test, lineno=node[1][2])
+                    newfor.ifs.append(newif)
+                    if len(node) == 3:
+                        node = None
+                    else:
+                        node = self.com_list_iter(node[3])
+                else:
+                    raise SyntaxError, \
+                          ("unexpected list comprehension element: %s %d"
+                           % (node, lineno))
+            return ListComp(expr, fors, lineno=lineno)
+
+        def com_list_iter(self, node):
+            assert node[0] == symbol.list_iter
+            return node[1]
+    else:
+        def com_list_constructor(self, nodelist):
+            values = []
+            for i in range(1, len(nodelist), 2):
+                values.append(self.com_node(nodelist[i]))
+            return List(values, lineno=values[0].lineno)
+
+    if hasattr(symbol, 'gen_for'):
+        def com_generator_expression(self, expr, node):
+            # gen_iter: gen_for | gen_if
+            # gen_for: 'for' exprlist 'in' test [gen_iter]
+            # gen_if: 'if' test [gen_iter]
+
+            lineno = node[1][2]
+            fors = []
+            while node:
+                t = node[1][1]
+                if t == 'for':
+                    assignNode = self.com_assign(node[2], OP_ASSIGN)
+                    genNode = self.com_node(node[4])
+                    newfor = GenExprFor(assignNode, genNode, [],
+                                        lineno=node[1][2])
+                    fors.append(newfor)
+                    if (len(node)) == 5:
+                        node = None
+                    else:
+                        node = self.com_gen_iter(node[5])
+                elif t == 'if':
+                    test = self.com_node(node[2])
+                    newif = GenExprIf(test, lineno=node[1][2])
+                    newfor.ifs.append(newif)
+                    if len(node) == 3:
+                        node = None
+                    else:
+                        node = self.com_gen_iter(node[3])
+                else:
+                    raise SyntaxError, \
+                            ("unexpected generator expression element: %s %d"
+                             % (node, lineno))
+            fors[0].is_outmost = True
+            return GenExpr(GenExprInner(expr, fors), lineno=lineno)
+
+        def com_gen_iter(self, node):
+            assert node[0] == symbol.gen_iter
+            return node[1]
+
+    def com_dictmaker(self, nodelist):
+        # dictmaker: test ':' test (',' test ':' value)* [',']
+        items = []
+        for i in range(1, len(nodelist), 4):
+            items.append((self.com_node(nodelist[i]),
+                          self.com_node(nodelist[i+2])))
+        return Dict(items, lineno=items[0][0].lineno)
+
+    def com_apply_trailer(self, primaryNode, nodelist):
+        t = nodelist[1][0]
+        if t == token.LPAR:
+            return self.com_call_function(primaryNode, nodelist[2])
+        if t == token.DOT:
+            return self.com_select_member(primaryNode, nodelist[2])
+        if t == token.LSQB:
+            return self.com_subscriptlist(primaryNode, nodelist[2], OP_APPLY)
+
+        raise SyntaxError, 'unknown node type: %s' % t
+
+    def com_select_member(self, primaryNode, nodelist):
+        if nodelist[0] != token.NAME:
+            raise SyntaxError, "member must be a name"
+        return Getattr(primaryNode, nodelist[1], lineno=nodelist[2])
+
+    def com_call_function(self, primaryNode, nodelist):
+        if nodelist[0] == token.RPAR:
+            return CallFunc(primaryNode, [], lineno=extractLineNo(nodelist))
+        args = []
+        kw = 0
+        len_nodelist = len(nodelist)
+        for i in range(1, len_nodelist, 2):
+            node = nodelist[i]
+            if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
+                break
+            kw, result = self.com_argument(node, kw)
+
+            if len_nodelist != 2 and isinstance(result, GenExpr) \
+               and len(node) == 3 and node[2][0] == symbol.gen_for:
+                # allow f(x for x in y), but reject f(x for x in y, 1)
+                # should use f((x for x in y), 1) instead of f(x for x in y, 1)
+                raise SyntaxError, 'generator expression needs parenthesis'
+
+            args.append(result)
+        else:
+            # No broken by star arg, so skip the last one we processed.
+            i = i + 1
+        if i < len_nodelist and nodelist[i][0] == token.COMMA:
+            # need to accept an application that looks like "f(a, b,)"
+            i = i + 1
+        star_node = dstar_node = None
+        while i < len_nodelist:
+            tok = nodelist[i]
+            ch = nodelist[i+1]
+            i = i + 3
+            if tok[0]==token.STAR:
+                if star_node is not None:
+                    raise SyntaxError, 'already have the varargs indentifier'
+                star_node = self.com_node(ch)
+            elif tok[0]==token.DOUBLESTAR:
+                if dstar_node is not None:
+                    raise SyntaxError, 'already have the kwargs indentifier'
+                dstar_node = self.com_node(ch)
+            else:
+                raise SyntaxError, 'unknown node type: %s' % tok
+        return CallFunc(primaryNode, args, star_node, dstar_node,
+                        lineno=extractLineNo(nodelist))
+
+    def com_argument(self, nodelist, kw):
+        if len(nodelist) == 3 and nodelist[2][0] == symbol.gen_for:
+            test = self.com_node(nodelist[1])
+            return 0, self.com_generator_expression(test, nodelist[2])
+        if len(nodelist) == 2:
+            if kw:
+                raise SyntaxError, "non-keyword arg after keyword arg"
+            return 0, self.com_node(nodelist[1])
+        result = self.com_node(nodelist[3])
+        n = nodelist[1]
+        while len(n) == 2 and n[0] != token.NAME:
+            n = n[1]
+        if n[0] != token.NAME:
+            raise SyntaxError, "keyword can't be an expression (%s)"%n[0]
+        node = Keyword(n[1], result, lineno=n[2])
+        return 1, node
+
+    def com_subscriptlist(self, primary, nodelist, assigning):
+        # slicing:      simple_slicing | extended_slicing
+        # simple_slicing:   primary "[" short_slice "]"
+        # extended_slicing: primary "[" slice_list "]"
+        # slice_list:   slice_item ("," slice_item)* [","]
+
+        # backwards compat slice for '[i:j]'
+        if len(nodelist) == 2:
+            sub = nodelist[1]
+            if (sub[1][0] == token.COLON or \
+                            (len(sub) > 2 and sub[2][0] == token.COLON)) and \
+                            sub[-1][0] != symbol.sliceop:
+                return self.com_slice(primary, sub, assigning)
+
+        subscripts = []
+        for i in range(1, len(nodelist), 2):
+            subscripts.append(self.com_subscript(nodelist[i]))
+        return Subscript(primary, assigning, subscripts,
+                         lineno=extractLineNo(nodelist))
+
+    def com_subscript(self, node):
+        # slice_item: expression | proper_slice | ellipsis
+        ch = node[1]
+        t = ch[0]
+        if t == token.DOT and node[2][0] == token.DOT:
+            return Ellipsis()
+        if t == token.COLON or len(node) > 2:
+            return self.com_sliceobj(node)
+        return self.com_node(ch)
+
+    def com_sliceobj(self, node):
+        # proper_slice: short_slice | long_slice
+        # short_slice:  [lower_bound] ":" [upper_bound]
+        # long_slice:   short_slice ":" [stride]
+        # lower_bound:  expression
+        # upper_bound:  expression
+        # stride:       expression
+        #
+        # Note: a stride may be further slicing...
+
+        items = []
+
+        if node[1][0] == token.COLON:
+            items.append(Const(None))
+            i = 2
+        else:
+            items.append(self.com_node(node[1]))
+            # i == 2 is a COLON
+            i = 3
+
+        if i < len(node) and node[i][0] == symbol.test:
+            items.append(self.com_node(node[i]))
+            i = i + 1
+        else:
+            items.append(Const(None))
+
+        # a short_slice has been built. look for long_slice now by looking
+        # for strides...
+        for j in range(i, len(node)):
+            ch = node[j]
+            if len(ch) == 2:
+                items.append(Const(None))
+            else:
+                items.append(self.com_node(ch[2]))
+        return Sliceobj(items, lineno=extractLineNo(node))
+
+    def com_slice(self, primary, node, assigning):
+        # short_slice:  [lower_bound] ":" [upper_bound]
+        lower = upper = None
+        if len(node) == 3:
+            if node[1][0] == token.COLON:
+                upper = self.com_node(node[2])
+            else:
+                lower = self.com_node(node[1])
+        elif len(node) == 4:
+            lower = self.com_node(node[1])
+            upper = self.com_node(node[3])
+        return Slice(primary, assigning, lower, upper,
+                     lineno=extractLineNo(node))
+
+    def get_docstring(self, node, n=None):
+        if n is None:
+            n = node[0]
+            node = node[1:]
+        if n == symbol.suite:
+            if len(node) == 1:
+                return self.get_docstring(node[0])
+            for sub in node:
+                if sub[0] == symbol.stmt:
+                    return self.get_docstring(sub)
+            return None
+        if n == symbol.file_input:
+            for sub in node:
+                if sub[0] == symbol.stmt:
+                    return self.get_docstring(sub)
+            return None
+        if n == symbol.atom:
+            if node[0][0] == token.STRING:
+                s = ''
+                for t in node:
+                    s = s + eval(t[1])
+                return s
+            return None
+        if n == symbol.stmt or n == symbol.simple_stmt \
+           or n == symbol.small_stmt:
+            return self.get_docstring(node[0])
+        if n in _doc_nodes and len(node) == 1:
+            return self.get_docstring(node[0])
+        return None
+
+
+_doc_nodes = [
+    symbol.expr_stmt,
+    symbol.testlist,
+    symbol.testlist_safe,
+    symbol.test,
+    symbol.or_test,
+    symbol.and_test,
+    symbol.not_test,
+    symbol.comparison,
+    symbol.expr,
+    symbol.xor_expr,
+    symbol.and_expr,
+    symbol.shift_expr,
+    symbol.arith_expr,
+    symbol.term,
+    symbol.factor,
+    symbol.power,
+    ]
+
+# comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
+#             | 'in' | 'not' 'in' | 'is' | 'is' 'not'
+_cmp_types = {
+    token.LESS : '<',
+    token.GREATER : '>',
+    token.EQEQUAL : '==',
+    token.EQUAL : '==',
+    token.LESSEQUAL : '<=',
+    token.GREATEREQUAL : '>=',
+    token.NOTEQUAL : '!=',
+    }
+
+_legal_node_types = [
+    symbol.funcdef,
+    symbol.classdef,
+    symbol.stmt,
+    symbol.small_stmt,
+    symbol.flow_stmt,
+    symbol.simple_stmt,
+    symbol.compound_stmt,
+    symbol.expr_stmt,
+    symbol.print_stmt,
+    symbol.del_stmt,
+    symbol.pass_stmt,
+    symbol.break_stmt,
+    symbol.continue_stmt,
+    symbol.return_stmt,
+    symbol.raise_stmt,
+    symbol.import_stmt,
+    symbol.global_stmt,
+    symbol.exec_stmt,
+    symbol.assert_stmt,
+    symbol.if_stmt,
+    symbol.while_stmt,
+    symbol.for_stmt,
+    symbol.try_stmt,
+    symbol.with_stmt,
+    symbol.suite,
+    symbol.testlist,
+    symbol.testlist_safe,
+    symbol.test,
+    symbol.and_test,
+    symbol.not_test,
+    symbol.comparison,
+    symbol.exprlist,
+    symbol.expr,
+    symbol.xor_expr,
+    symbol.and_expr,
+    symbol.shift_expr,
+    symbol.arith_expr,
+    symbol.term,
+    symbol.factor,
+    symbol.power,
+    symbol.atom,
+    ]
+
+if hasattr(symbol, 'yield_stmt'):
+    _legal_node_types.append(symbol.yield_stmt)
+if hasattr(symbol, 'yield_expr'):
+    _legal_node_types.append(symbol.yield_expr)
+
+_assign_types = [
+    symbol.test,
+    symbol.or_test,
+    symbol.and_test,
+    symbol.not_test,
+    symbol.comparison,
+    symbol.expr,
+    symbol.xor_expr,
+    symbol.and_expr,
+    symbol.shift_expr,
+    symbol.arith_expr,
+    symbol.term,
+    symbol.factor,
+    ]
+
+_names = {}
+for k, v in symbol.sym_name.items():
+    _names[k] = v
+for k, v in token.tok_name.items():
+    _names[k] = v
+
+def debug_tree(tree):
+    l = []
+    for elt in tree:
+        if isinstance(elt, int):
+            l.append(_names.get(elt, elt))
+        elif isinstance(elt, str):
+            l.append(elt)
+        else:
+            l.append(debug_tree(elt))
+    return l
diff --git a/src/main/resources/PythonLibs/compiler/visitor.py b/src/main/resources/PythonLibs/compiler/visitor.py
new file mode 100644
index 0000000000000000000000000000000000000000..f10f56011a3ec629c1b8cdb695b4ffbbbfefce35
--- /dev/null
+++ b/src/main/resources/PythonLibs/compiler/visitor.py
@@ -0,0 +1,113 @@
+from compiler import ast
+
+# XXX should probably rename ASTVisitor to ASTWalker
+# XXX can it be made even more generic?
+
+class ASTVisitor:
+    """Performs a depth-first walk of the AST
+
+    The ASTVisitor will walk the AST, performing either a preorder or
+    postorder traversal depending on which method is called.
+
+    methods:
+    preorder(tree, visitor)
+    postorder(tree, visitor)
+        tree: an instance of ast.Node
+        visitor: an instance with visitXXX methods
+
+    The ASTVisitor is responsible for walking over the tree in the
+    correct order.  For each node, it checks the visitor argument for
+    a method named 'visitNodeType' where NodeType is the name of the
+    node's class, e.g. Class.  If the method exists, it is called
+    with the node as its sole argument.
+
+    The visitor method for a particular node type can control how
+    child nodes are visited during a preorder walk.  (It can't control
+    the order during a postorder walk, because it is called _after_
+    the walk has occurred.)  The ASTVisitor modifies the visitor
+    argument by adding a visit method to the visitor; this method can
+    be used to visit a child node of arbitrary type.
+    """
+
+    VERBOSE = 0
+
+    def __init__(self):
+        self.node = None
+        self._cache = {}
+
+    def default(self, node, *args):
+        for child in node.getChildNodes():
+            self.dispatch(child, *args)
+
+    def dispatch(self, node, *args):
+        self.node = node
+        klass = node.__class__
+        meth = self._cache.get(klass, None)
+        if meth is None:
+            className = klass.__name__
+            meth = getattr(self.visitor, 'visit' + className, self.default)
+            self._cache[klass] = meth
+##        if self.VERBOSE > 0:
+##            className = klass.__name__
+##            if self.VERBOSE == 1:
+##                if meth == 0:
+##                    print "dispatch", className
+##            else:
+##                print "dispatch", className, (meth and meth.__name__ or '')
+        return meth(node, *args)
+
+    def preorder(self, tree, visitor, *args):
+        """Do preorder walk of tree using visitor"""
+        self.visitor = visitor
+        visitor.visit = self.dispatch
+        self.dispatch(tree, *args) # XXX *args make sense?
+
+class ExampleASTVisitor(ASTVisitor):
+    """Prints examples of the nodes that aren't visited
+
+    This visitor-driver is only useful for development, when it's
+    helpful to develop a visitor incrementally, and get feedback on what
+    you still have to do.
+    """
+    examples = {}
+
+    def dispatch(self, node, *args):
+        self.node = node
+        meth = self._cache.get(node.__class__, None)
+        className = node.__class__.__name__
+        if meth is None:
+            meth = getattr(self.visitor, 'visit' + className, 0)
+            self._cache[node.__class__] = meth
+        if self.VERBOSE > 1:
+            print "dispatch", className, (meth and meth.__name__ or '')
+        if meth:
+            meth(node, *args)
+        elif self.VERBOSE > 0:
+            klass = node.__class__
+            if klass not in self.examples:
+                self.examples[klass] = klass
+                print
+                print self.visitor
+                print klass
+                for attr in dir(node):
+                    if attr[0] != '_':
+                        print "\t", "%-12.12s" % attr, getattr(node, attr)
+                print
+            return self.default(node, *args)
+
+# XXX this is an API change
+
+_walker = ASTVisitor
+def walk(tree, visitor, walker=None, verbose=None):
+    if walker is None:
+        walker = _walker()
+    if verbose is not None:
+        walker.VERBOSE = verbose
+    walker.preorder(tree, visitor)
+    return walker.visitor
+
+def dumpNode(node):
+    print node.__class__
+    for attr in dir(node):
+        if attr[0] != '_':
+            print "\t", "%-10.10s" % attr, getattr(node, attr)
diff --git a/src/main/resources/PythonLibs/contextlib.py b/src/main/resources/PythonLibs/contextlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..f05205b01c2f7c0d63b6b6026e888ffbcd176ef4
--- /dev/null
+++ b/src/main/resources/PythonLibs/contextlib.py
@@ -0,0 +1,154 @@
+"""Utilities for with-statement contexts.  See PEP 343."""
+
+import sys
+from functools import wraps
+from warnings import warn
+
+__all__ = ["contextmanager", "nested", "closing"]
+
+class GeneratorContextManager(object):
+    """Helper for @contextmanager decorator."""
+
+    def __init__(self, gen):
+        self.gen = gen
+
+    def __enter__(self):
+        try:
+            return self.gen.next()
+        except StopIteration:
+            raise RuntimeError("generator didn't yield")
+
+    def __exit__(self, type, value, traceback):
+        if type is None:
+            try:
+                self.gen.next()
+            except StopIteration:
+                return
+            else:
+                raise RuntimeError("generator didn't stop")
+        else:
+            if value is None:
+                # Need to force instantiation so we can reliably
+                # tell if we get the same exception back
+                value = type()
+            try:
+                self.gen.throw(type, value, traceback)
+                raise RuntimeError("generator didn't stop after throw()")
+            except StopIteration, exc:
+                # Suppress the exception *unless* it's the same exception that
+                # was passed to throw().  This prevents a StopIteration
+                # raised inside the "with" statement from being suppressed
+                return exc is not value
+            except:
+                # only re-raise if it's *not* the exception that was
+                # passed to throw(), because __exit__() must not raise
+                # an exception unless __exit__() itself failed.  But throw()
+                # has to raise the exception to signal propagation, so this
+                # fixes the impedance mismatch between the throw() protocol
+                # and the __exit__() protocol.
+                #
+                if sys.exc_info()[1] is not value:
+                    raise
+
+
+def contextmanager(func):
+    """@contextmanager decorator.
+
+    Typical usage:
+
+        @contextmanager
+        def some_generator(<arguments>):
+            <setup>
+            try:
+                yield <value>
+            finally:
+                <cleanup>
+
+    This makes this:
+
+        with some_generator(<arguments>) as <variable>:
+            <body>
+
+    equivalent to this:
+
+        <setup>
+        try:
+            <variable> = <value>
+            <body>
+        finally:
+            <cleanup>
+
+    """
+    @wraps(func)
+    def helper(*args, **kwds):
+        return GeneratorContextManager(func(*args, **kwds))
+    return helper
+
+
+@contextmanager
+def nested(*managers):
+    """Combine multiple context managers into a single nested context manager.
+
+   This function has been deprecated in favour of the multiple manager form
+   of the with statement.
+
+   The one advantage of this function over the multiple manager form of the
+   with statement is that argument unpacking allows it to be
+   used with a variable number of context managers as follows:
+
+      with nested(*managers):
+          do_something()
+
+    """
+    warn("With-statements now directly support multiple context managers",
+         DeprecationWarning, 3)
+    exits = []
+    vars = []
+    exc = (None, None, None)
+    try:
+        for mgr in managers:
+            exit = mgr.__exit__
+            enter = mgr.__enter__
+            vars.append(enter())
+            exits.append(exit)
+        yield vars
+    except:
+        exc = sys.exc_info()
+    finally:
+        while exits:
+            exit = exits.pop()
+            try:
+                if exit(*exc):
+                    exc = (None, None, None)
+            except:
+                exc = sys.exc_info()
+        if exc != (None, None, None):
+            # Don't rely on sys.exc_info() still containing
+            # the right information. Another exception may
+            # have been raised and caught by an exit method
+            raise exc[0], exc[1], exc[2]
+
+
+class closing(object):
+    """Context to automatically close something at the end of a block.
+
+    Code like this:
+
+        with closing(<module>.open(<arguments>)) as f:
+            <block>
+
+    is equivalent to this:
+
+        f = <module>.open(<arguments>)
+        try:
+            <block>
+        finally:
+            f.close()
+
+    """
+    def __init__(self, thing):
+        self.thing = thing
+    def __enter__(self):
+        return self.thing
+    def __exit__(self, *exc_info):
+        self.thing.close()
diff --git a/src/main/resources/PythonLibs/cookielib.py b/src/main/resources/PythonLibs/cookielib.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9c8d2f84bd87d0f4383a3792d4ec0bee05ec850
--- /dev/null
+++ b/src/main/resources/PythonLibs/cookielib.py
@@ -0,0 +1,1794 @@
+r"""HTTP cookie handling for web clients.
+
+This module has (now fairly distant) origins in Gisle Aas' Perl module
+HTTP::Cookies, from the libwww-perl library.
+
+Docstrings, comments and debug strings in this code refer to the
+attributes of the HTTP cookie system as cookie-attributes, to distinguish
+them clearly from Python attributes.
+
+Class diagram (note that BSDDBCookieJar and the MSIE* classes are not
+distributed with the Python standard library, but are available from
+http://wwwsearch.sf.net/):
+
+                        CookieJar____
+                        /     \      \
+            FileCookieJar      \      \
+             /    |   \         \      \
+ MozillaCookieJar | LWPCookieJar \      \
+                  |               |      \
+                  |   ---MSIEBase |       \
+                  |  /      |     |        \
+                  | /   MSIEDBCookieJar BSDDBCookieJar
+                  |/
+               MSIECookieJar
+
+"""
+
+__all__ = ['Cookie', 'CookieJar', 'CookiePolicy', 'DefaultCookiePolicy',
+           'FileCookieJar', 'LWPCookieJar', 'lwp_cookie_str', 'LoadError',
+           'MozillaCookieJar']
+
+import re, urlparse, copy, time, urllib
+try:
+    import threading as _threading
+except ImportError:
+    import dummy_threading as _threading
+import httplib  # only for the default HTTP port
+from calendar import timegm
+
+debug = False   # set to True to enable debugging via the logging module
+logger = None
+
+def _debug(*args):
+    if not debug:
+        return
+    global logger
+    if not logger:
+        import logging
+        logger = logging.getLogger("cookielib")
+    return logger.debug(*args)
+
+
+DEFAULT_HTTP_PORT = str(httplib.HTTP_PORT)
+MISSING_FILENAME_TEXT = ("a filename was not supplied (nor was the CookieJar "
+                         "instance initialised with one)")
+
+def _warn_unhandled_exception():
+    # There are a few catch-all except: statements in this module, for
+    # catching input that's bad in unexpected ways.  Warn if any
+    # exceptions are caught there.
+    import warnings, traceback, StringIO
+    f = StringIO.StringIO()
+    traceback.print_exc(None, f)
+    msg = f.getvalue()
+    warnings.warn("cookielib bug!\n%s" % msg, stacklevel=2)
+
+
+# Date/time conversion
+# -----------------------------------------------------------------------------
+
+EPOCH_YEAR = 1970
+def _timegm(tt):
+    year, month, mday, hour, min, sec = tt[:6]
+    if ((year >= EPOCH_YEAR) and (1 <= month <= 12) and (1 <= mday <= 31) and
+        (0 <= hour <= 24) and (0 <= min <= 59) and (0 <= sec <= 61)):
+        return timegm(tt)
+    else:
+        return None
+
+DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
+MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
+          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+MONTHS_LOWER = []
+for month in MONTHS: MONTHS_LOWER.append(month.lower())
+
+def time2isoz(t=None):
+    """Return a string representing time in seconds since epoch, t.
+
+    If the function is called without an argument, it will use the current
+    time.
+
+    The format of the returned string is like "YYYY-MM-DD hh:mm:ssZ",
+    representing Universal Time (UTC, aka GMT).  An example of this format is:
+
+    1994-11-24 08:49:37Z
+
+    """
+    if t is None: t = time.time()
+    year, mon, mday, hour, min, sec = time.gmtime(t)[:6]
+    return "%04d-%02d-%02d %02d:%02d:%02dZ" % (
+        year, mon, mday, hour, min, sec)
+
+def time2netscape(t=None):
+    """Return a string representing time in seconds since epoch, t.
+
+    If the function is called without an argument, it will use the current
+    time.
+
+    The format of the returned string is like this:
+
+    Wed, DD-Mon-YYYY HH:MM:SS GMT
+
+    """
+    if t is None: t = time.time()
+    year, mon, mday, hour, min, sec, wday = time.gmtime(t)[:7]
+    return "%s %02d-%s-%04d %02d:%02d:%02d GMT" % (
+        DAYS[wday], mday, MONTHS[mon-1], year, hour, min, sec)
+
+
+UTC_ZONES = {"GMT": None, "UTC": None, "UT": None, "Z": None}
+
+TIMEZONE_RE = re.compile(r"^([-+])?(\d\d?):?(\d\d)?$")
+def offset_from_tz_string(tz):
+    offset = None
+    if tz in UTC_ZONES:
+        offset = 0
+    else:
+        m = TIMEZONE_RE.search(tz)
+        if m:
+            offset = 3600 * int(m.group(2))
+            if m.group(3):
+                offset = offset + 60 * int(m.group(3))
+            if m.group(1) == '-':
+                offset = -offset
+    return offset
+
+def _str2time(day, mon, yr, hr, min, sec, tz):
+    # translate month name to number
+    # month numbers start with 1 (January)
+    try:
+        mon = MONTHS_LOWER.index(mon.lower())+1
+    except ValueError:
+        # maybe it's already a number
+        try:
+            imon = int(mon)
+        except ValueError:
+            return None
+        if 1 <= imon <= 12:
+            mon = imon
+        else:
+            return None
+
+    # make sure clock elements are defined
+    if hr is None: hr = 0
+    if min is None: min = 0
+    if sec is None: sec = 0
+
+    yr = int(yr)
+    day = int(day)
+    hr = int(hr)
+    min = int(min)
+    sec = int(sec)
+
+    if yr < 1000:
+        # find "obvious" year
+        cur_yr = time.localtime(time.time())[0]
+        m = cur_yr % 100
+        tmp = yr
+        yr = yr + cur_yr - m
+        m = m - tmp
+        if abs(m) > 50:
+            if m > 0: yr = yr + 100
+            else: yr = yr - 100
+
+    # convert UTC time tuple to seconds since epoch (not timezone-adjusted)
+    t = _timegm((yr, mon, day, hr, min, sec, tz))
+
+    if t is not None:
+        # adjust time using timezone string, to get absolute time since epoch
+        if tz is None:
+            tz = "UTC"
+        tz = tz.upper()
+        offset = offset_from_tz_string(tz)
+        if offset is None:
+            return None
+        t = t - offset
+
+    return t
+
+STRICT_DATE_RE = re.compile(
+    r"^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) "
+    "(\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$")
+WEEKDAY_RE = re.compile(
+    r"^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*", re.I)
+LOOSE_HTTP_DATE_RE = re.compile(
+    r"""^
+    (\d\d?)            # day
+       (?:\s+|[-\/])
+    (\w+)              # month
+        (?:\s+|[-\/])
+    (\d+)              # year
+    (?:
+          (?:\s+|:)    # separator before clock
+       (\d\d?):(\d\d)  # hour:min
+       (?::(\d\d))?    # optional seconds
+    )?                 # optional clock
+       \s*
+    ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone
+       \s*
+    (?:\(\w+\))?       # ASCII representation of timezone in parens.
+       \s*$""", re.X)
+def http2time(text):
+    """Returns time in seconds since epoch of time represented by a string.
+
+    Return value is an integer.
+
+    None is returned if the format of str is unrecognized, the time is outside
+    the representable range, or the timezone string is not recognized.  If the
+    string contains no timezone, UTC is assumed.
+
+    The timezone in the string may be numerical (like "-0800" or "+0100") or a
+    string timezone (like "UTC", "GMT", "BST" or "EST").  Currently, only the
+    timezone strings equivalent to UTC (zero offset) are known to the function.
+
+    The function loosely parses the following formats:
+
+    Wed, 09 Feb 1994 22:23:32 GMT       -- HTTP format
+    Tuesday, 08-Feb-94 14:15:29 GMT     -- old rfc850 HTTP format
+    Tuesday, 08-Feb-1994 14:15:29 GMT   -- broken rfc850 HTTP format
+    09 Feb 1994 22:23:32 GMT            -- HTTP format (no weekday)
+    08-Feb-94 14:15:29 GMT              -- rfc850 format (no weekday)
+    08-Feb-1994 14:15:29 GMT            -- broken rfc850 format (no weekday)
+
+    The parser ignores leading and trailing whitespace.  The time may be
+    absent.
+
+    If the year is given with only 2 digits, the function will select the
+    century that makes the year closest to the current date.
+
+    """
+    # fast exit for strictly conforming string
+    m = STRICT_DATE_RE.search(text)
+    if m:
+        g = m.groups()
+        mon = MONTHS_LOWER.index(g[1].lower()) + 1
+        tt = (int(g[2]), mon, int(g[0]),
+              int(g[3]), int(g[4]), float(g[5]))
+        return _timegm(tt)
+
+    # No, we need some messy parsing...
+
+    # clean up
+    text = text.lstrip()
+    text = WEEKDAY_RE.sub("", text, 1)  # Useless weekday
+
+    # tz is time zone specifier string
+    day, mon, yr, hr, min, sec, tz = [None]*7
+
+    # loose regexp parse
+    m = LOOSE_HTTP_DATE_RE.search(text)
+    if m is not None:
+        day, mon, yr, hr, min, sec, tz = m.groups()
+    else:
+        return None  # bad format
+
+    return _str2time(day, mon, yr, hr, min, sec, tz)
+
+ISO_DATE_RE = re.compile(
+    """^
+    (\d{4})              # year
+       [-\/]?
+    (\d\d?)              # numerical month
+       [-\/]?
+    (\d\d?)              # day
+   (?:
+         (?:\s+|[-:Tt])  # separator before clock
+      (\d\d?):?(\d\d)    # hour:min
+      (?::?(\d\d(?:\.\d*)?))?  # optional seconds (and fractional)
+   )?                    # optional clock
+      \s*
+   ([-+]?\d\d?:?(:?\d\d)?
+    |Z|z)?               # timezone  (Z is "zero meridian", i.e. GMT)
+      \s*$""", re.X)
+def iso2time(text):
+    """
+    As for http2time, but parses the ISO 8601 formats:
+
+    1994-02-03 14:15:29 -0100    -- ISO 8601 format
+    1994-02-03 14:15:29          -- zone is optional
+    1994-02-03                   -- only date
+    1994-02-03T14:15:29          -- Use T as separator
+    19940203T141529Z             -- ISO 8601 compact format
+    19940203                     -- only date
+
+    """
+    # clean up
+    text = text.lstrip()
+
+    # tz is time zone specifier string
+    day, mon, yr, hr, min, sec, tz = [None]*7
+
+    # loose regexp parse
+    m = ISO_DATE_RE.search(text)
+    if m is not None:
+        # XXX there's an extra bit of the timezone I'm ignoring here: is
+        #   this the right thing to do?
+        yr, mon, day, hr, min, sec, tz, _ = m.groups()
+    else:
+        return None  # bad format
+
+    return _str2time(day, mon, yr, hr, min, sec, tz)
+
+
+# Header parsing
+# -----------------------------------------------------------------------------
+
+def unmatched(match):
+    """Return unmatched part of re.Match object."""
+    start, end = match.span(0)
+    return match.string[:start]+match.string[end:]
+
+HEADER_TOKEN_RE =        re.compile(r"^\s*([^=\s;,]+)")
+HEADER_QUOTED_VALUE_RE = re.compile(r"^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"")
+HEADER_VALUE_RE =        re.compile(r"^\s*=\s*([^\s;,]*)")
+HEADER_ESCAPE_RE = re.compile(r"\\(.)")
+def split_header_words(header_values):
+    r"""Parse header values into a list of lists containing key,value pairs.
+
+    The function knows how to deal with ",", ";" and "=" as well as quoted
+    values after "=".  A list of space separated tokens are parsed as if they
+    were separated by ";".
+
+    If the header_values passed as argument contains multiple values, then they
+    are treated as if they were a single value separated by comma ",".
+
+    This means that this function is useful for parsing header fields that
+    follow this syntax (BNF as from the HTTP/1.1 specification, but we relax
+    the requirement for tokens).
+
+      headers           = #header
+      header            = (token | parameter) *( [";"] (token | parameter))
+
+      token             = 1*<any CHAR except CTLs or separators>
+      separators        = "(" | ")" | "<" | ">" | "@"
+                        | "," | ";" | ":" | "\" | <">
+                        | "/" | "[" | "]" | "?" | "="
+                        | "{" | "}" | SP | HT
+
+      quoted-string     = ( <"> *(qdtext | quoted-pair ) <"> )
+      qdtext            = <any TEXT except <">>
+      quoted-pair       = "\" CHAR
+
+      parameter         = attribute "=" value
+      attribute         = token
+      value             = token | quoted-string
+
+    Each header is represented by a list of key/value pairs.  The value for a
+    simple token (not part of a parameter) is None.  Syntactically incorrect
+    headers will not necessarily be parsed as you would want.
+
+    This is easier to describe with some examples:
+
+    >>> split_header_words(['foo="bar"; port="80,81"; discard, bar=baz'])
+    [[('foo', 'bar'), ('port', '80,81'), ('discard', None)], [('bar', 'baz')]]
+    >>> split_header_words(['text/html; charset="iso-8859-1"'])
+    [[('text/html', None), ('charset', 'iso-8859-1')]]
+    >>> split_header_words([r'Basic realm="\"foo\bar\""'])
+    [[('Basic', None), ('realm', '"foobar"')]]
+
+    """
+    assert not isinstance(header_values, basestring)
+    result = []
+    for text in header_values:
+        orig_text = text
+        pairs = []
+        while text:
+            m = HEADER_TOKEN_RE.search(text)
+            if m:
+                text = unmatched(m)
+                name = m.group(1)
+                m = HEADER_QUOTED_VALUE_RE.search(text)
+                if m:  # quoted value
+                    text = unmatched(m)
+                    value = m.group(1)
+                    value = HEADER_ESCAPE_RE.sub(r"\1", value)
+                else:
+                    m = HEADER_VALUE_RE.search(text)
+                    if m:  # unquoted value
+                        text = unmatched(m)
+                        value = m.group(1)
+                        value = value.rstrip()
+                    else:
+                        # no value, a lone token
+                        value = None
+                pairs.append((name, value))
+            elif text.lstrip().startswith(","):
+                # concatenated headers, as per RFC 2616 section 4.2
+                text = text.lstrip()[1:]
+                if pairs: result.append(pairs)
+                pairs = []
+            else:
+                # skip junk
+                non_junk, nr_junk_chars = re.subn("^[=\s;]*", "", text)
+                assert nr_junk_chars > 0, (
+                    "split_header_words bug: '%s', '%s', %s" %
+                    (orig_text, text, pairs))
+                text = non_junk
+        if pairs: result.append(pairs)
+    return result
+
+HEADER_JOIN_ESCAPE_RE = re.compile(r"([\"\\])")
+def join_header_words(lists):
+    """Do the inverse (almost) of the conversion done by split_header_words.
+
+    Takes a list of lists of (key, value) pairs and produces a single header
+    value.  Attribute values are quoted if needed.
+
+    >>> join_header_words([[("text/plain", None), ("charset", "iso-8859/1")]])
+    'text/plain; charset="iso-8859/1"'
+    >>> join_header_words([[("text/plain", None)], [("charset", "iso-8859/1")]])
+    'text/plain, charset="iso-8859/1"'
+
+    """
+    headers = []
+    for pairs in lists:
+        attr = []
+        for k, v in pairs:
+            if v is not None:
+                if not re.search(r"^\w+$", v):
+                    v = HEADER_JOIN_ESCAPE_RE.sub(r"\\\1", v)  # escape " and \
+                    v = '"%s"' % v
+                k = "%s=%s" % (k, v)
+            attr.append(k)
+        if attr: headers.append("; ".join(attr))
+    return ", ".join(headers)
+
+def _strip_quotes(text):
+    if text.startswith('"'):
+        text = text[1:]
+    if text.endswith('"'):
+        text = text[:-1]
+    return text
+
+def parse_ns_headers(ns_headers):
+    """Ad-hoc parser for Netscape protocol cookie-attributes.
+
+    The old Netscape cookie format for Set-Cookie can for instance contain
+    an unquoted "," in the expires field, so we have to use this ad-hoc
+    parser instead of split_header_words.
+
+    XXX This may not make the best possible effort to parse all the crap
+    that Netscape Cookie headers contain.  Ronald Tschalar's HTTPClient
+    parser is probably better, so could do worse than following that if
+    this ever gives any trouble.
+
+    Currently, this is also used for parsing RFC 2109 cookies.
+
+    """
+    known_attrs = ("expires", "domain", "path", "secure",
+                   # RFC 2109 attrs (may turn up in Netscape cookies, too)
+                   "version", "port", "max-age")
+
+    result = []
+    for ns_header in ns_headers:
+        pairs = []
+        version_set = False
+        for ii, param in enumerate(re.split(r";\s*", ns_header)):
+            param = param.rstrip()
+            if param == "": continue
+            if "=" not in param:
+                k, v = param, None
+            else:
+                k, v = re.split(r"\s*=\s*", param, 1)
+                k = k.lstrip()
+            if ii != 0:
+                lc = k.lower()
+                if lc in known_attrs:
+                    k = lc
+                if k == "version":
+                    # This is an RFC 2109 cookie.
+                    v = _strip_quotes(v)
+                    version_set = True
+                if k == "expires":
+                    # convert expires date to seconds since epoch
+                    v = http2time(_strip_quotes(v))  # None if invalid
+            pairs.append((k, v))
+
+        if pairs:
+            if not version_set:
+                pairs.append(("version", "0"))
+            result.append(pairs)
+
+    return result
+
+
+IPV4_RE = re.compile(r"\.\d+$")
+def is_HDN(text):
+    """Return True if text is a host domain name."""
+    # XXX
+    # This may well be wrong.  Which RFC is HDN defined in, if any (for
+    #  the purposes of RFC 2965)?
+    # For the current implementation, what about IPv6?  Remember to look
+    #  at other uses of IPV4_RE also, if change this.
+    if IPV4_RE.search(text):
+        return False
+    if text == "":
+        return False
+    if text[0] == "." or text[-1] == ".":
+        return False
+    return True
+
+def domain_match(A, B):
+    """Return True if domain A domain-matches domain B, according to RFC 2965.
+
+    A and B may be host domain names or IP addresses.
+
+    RFC 2965, section 1:
+
+    Host names can be specified either as an IP address or a HDN string.
+    Sometimes we compare one host name with another.  (Such comparisons SHALL
+    be case-insensitive.)  Host A's name domain-matches host B's if
+
+         *  their host name strings string-compare equal; or
+
+         * A is a HDN string and has the form NB, where N is a non-empty
+            name string, B has the form .B', and B' is a HDN string.  (So,
+            x.y.com domain-matches .Y.com but not Y.com.)
+
+    Note that domain-match is not a commutative operation: a.b.c.com
+    domain-matches .c.com, but not the reverse.
+
+    """
+    # Note that, if A or B are IP addresses, the only relevant part of the
+    # definition of the domain-match algorithm is the direct string-compare.
+    A = A.lower()
+    B = B.lower()
+    if A == B:
+        return True
+    if not is_HDN(A):
+        return False
+    i = A.rfind(B)
+    if i == -1 or i == 0:
+        # A does not have form NB, or N is the empty string
+        return False
+    if not B.startswith("."):
+        return False
+    if not is_HDN(B[1:]):
+        return False
+    return True
+
+def liberal_is_HDN(text):
+    """Return True if text is a sort-of-like a host domain name.
+
+    For accepting/blocking domains.
+
+    """
+    if IPV4_RE.search(text):
+        return False
+    return True
+
+def user_domain_match(A, B):
+    """For blocking/accepting domains.
+
+    A and B may be host domain names or IP addresses.
+
+    """
+    A = A.lower()
+    B = B.lower()
+    if not (liberal_is_HDN(A) and liberal_is_HDN(B)):
+        if A == B:
+            # equal IP addresses
+            return True
+        return False
+    initial_dot = B.startswith(".")
+    if initial_dot and A.endswith(B):
+        return True
+    if not initial_dot and A == B:
+        return True
+    return False
+
+cut_port_re = re.compile(r":\d+$")
+def request_host(request):
+    """Return request-host, as defined by RFC 2965.
+
+    Variation from RFC: returned value is lowercased, for convenient
+    comparison.
+
+    """
+    url = request.get_full_url()
+    host = urlparse.urlparse(url)[1]
+    if host == "":
+        host = request.get_header("Host", "")
+
+    # remove port, if present
+    host = cut_port_re.sub("", host, 1)
+    return host.lower()
+
+def eff_request_host(request):
+    """Return a tuple (request-host, effective request-host name).
+
+    As defined by RFC 2965, except both are lowercased.
+
+    """
+    erhn = req_host = request_host(request)
+    if req_host.find(".") == -1 and not IPV4_RE.search(req_host):
+        erhn = req_host + ".local"
+    return req_host, erhn
+
+def request_path(request):
+    """Path component of request-URI, as defined by RFC 2965."""
+    url = request.get_full_url()
+    parts = urlparse.urlsplit(url)
+    path = escape_path(parts.path)
+    if not path.startswith("/"):
+        # fix bad RFC 2396 absoluteURI
+        path = "/" + path
+    return path
+
+def request_port(request):
+    host = request.get_host()
+    i = host.find(':')
+    if i >= 0:
+        port = host[i+1:]
+        try:
+            int(port)
+        except ValueError:
+            _debug("nonnumeric port: '%s'", port)
+            return None
+    else:
+        port = DEFAULT_HTTP_PORT
+    return port
+
+# Characters in addition to A-Z, a-z, 0-9, '_', '.', and '-' that don't
+# need to be escaped to form a valid HTTP URL (RFCs 2396 and 1738).
+HTTP_PATH_SAFE = "%/;:@&=+$,!~*'()"
+ESCAPED_CHAR_RE = re.compile(r"%([0-9a-fA-F][0-9a-fA-F])")
+def uppercase_escaped_char(match):
+    return "%%%s" % match.group(1).upper()
+def escape_path(path):
+    """Escape any invalid characters in HTTP URL, and uppercase all escapes."""
+    # There's no knowing what character encoding was used to create URLs
+    # containing %-escapes, but since we have to pick one to escape invalid
+    # path characters, we pick UTF-8, as recommended in the HTML 4.0
+    # specification:
+    # http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.2.1
+    # And here, kind of: draft-fielding-uri-rfc2396bis-03
+    # (And in draft IRI specification: draft-duerst-iri-05)
+    # (And here, for new URI schemes: RFC 2718)
+    if isinstance(path, unicode):
+        path = path.encode("utf-8")
+    path = urllib.quote(path, HTTP_PATH_SAFE)
+    path = ESCAPED_CHAR_RE.sub(uppercase_escaped_char, path)
+    return path
+
+def reach(h):
+    """Return reach of host h, as defined by RFC 2965, section 1.
+
+    The reach R of a host name H is defined as follows:
+
+       *  If
+
+          -  H is the host domain name of a host; and,
+
+          -  H has the form A.B; and
+
+          -  A has no embedded (that is, interior) dots; and
+
+          -  B has at least one embedded dot, or B is the string "local".
+             then the reach of H is .B.
+
+       *  Otherwise, the reach of H is H.
+
+    >>> reach("www.acme.com")
+    '.acme.com'
+    >>> reach("acme.com")
+    'acme.com'
+    >>> reach("acme.local")
+    '.local'
+
+    """
+    i = h.find(".")
+    if i >= 0:
+        #a = h[:i]  # this line is only here to show what a is
+        b = h[i+1:]
+        i = b.find(".")
+        if is_HDN(h) and (i >= 0 or b == "local"):
+            return "."+b
+    return h
+
+def is_third_party(request):
+    """
+
+    RFC 2965, section 3.3.6:
+
+        An unverifiable transaction is to a third-party host if its request-
+        host U does not domain-match the reach R of the request-host O in the
+        origin transaction.
+
+    """
+    req_host = request_host(request)
+    if not domain_match(req_host, reach(request.get_origin_req_host())):
+        return True
+    else:
+        return False
+
+
+class Cookie:
+    """HTTP Cookie.
+
+    This class represents both Netscape and RFC 2965 cookies.
+
+    This is deliberately a very simple class.  It just holds attributes.  It's
+    possible to construct Cookie instances that don't comply with the cookie
+    standards.  CookieJar.make_cookies is the factory function for Cookie
+    objects -- it deals with cookie parsing, supplying defaults, and
+    normalising to the representation used in this class.  CookiePolicy is
+    responsible for checking them to see whether they should be accepted from
+    and returned to the server.
+
+    Note that the port may be present in the headers, but unspecified ("Port"
+    rather than"Port=80", for example); if this is the case, port is None.
+
+    """
+
+    def __init__(self, version, name, value,
+                 port, port_specified,
+                 domain, domain_specified, domain_initial_dot,
+                 path, path_specified,
+                 secure,
+                 expires,
+                 discard,
+                 comment,
+                 comment_url,
+                 rest,
+                 rfc2109=False,
+                 ):
+
+        if version is not None: version = int(version)
+        if expires is not None: expires = int(expires)
+        if port is None and port_specified is True:
+            raise ValueError("if port is None, port_specified must be false")
+
+        self.version = version
+        self.name = name
+        self.value = value
+        self.port = port
+        self.port_specified = port_specified
+        # normalise case, as per RFC 2965 section 3.3.3
+        self.domain = domain.lower()
+        self.domain_specified = domain_specified
+        # Sigh.  We need to know whether the domain given in the
+        # cookie-attribute had an initial dot, in order to follow RFC 2965
+        # (as clarified in draft errata).  Needed for the returned $Domain
+        # value.
+        self.domain_initial_dot = domain_initial_dot
+        self.path = path
+        self.path_specified = path_specified
+        self.secure = secure
+        self.expires = expires
+        self.discard = discard
+        self.comment = comment
+        self.comment_url = comment_url
+        self.rfc2109 = rfc2109
+
+        self._rest = copy.copy(rest)
+
+    def has_nonstandard_attr(self, name):
+        return name in self._rest
+    def get_nonstandard_attr(self, name, default=None):
+        return self._rest.get(name, default)
+    def set_nonstandard_attr(self, name, value):
+        self._rest[name] = value
+
+    def is_expired(self, now=None):
+        if now is None: now = time.time()
+        if (self.expires is not None) and (self.expires <= now):
+            return True
+        return False
+
+    def __str__(self):
+        if self.port is None: p = ""
+        else: p = ":"+self.port
+        limit = self.domain + p + self.path
+        if self.value is not None:
+            namevalue = "%s=%s" % (self.name, self.value)
+        else:
+            namevalue = self.name
+        return "<Cookie %s for %s>" % (namevalue, limit)
+
+    def __repr__(self):
+        args = []
+        for name in ("version", "name", "value",
+                     "port", "port_specified",
+                     "domain", "domain_specified", "domain_initial_dot",
+                     "path", "path_specified",
+                     "secure", "expires", "discard", "comment", "comment_url",
+                     ):
+            attr = getattr(self, name)
+            args.append("%s=%s" % (name, repr(attr)))
+        args.append("rest=%s" % repr(self._rest))
+        args.append("rfc2109=%s" % repr(self.rfc2109))
+        return "Cookie(%s)" % ", ".join(args)
+
+
+class CookiePolicy:
+    """Defines which cookies get accepted from and returned to server.
+
+    May also modify cookies, though this is probably a bad idea.
+
+    The subclass DefaultCookiePolicy defines the standard rules for Netscape
+    and RFC 2965 cookies -- override that if you want a customised policy.
+
+    """
+    def set_ok(self, cookie, request):
+        """Return true if (and only if) cookie should be accepted from server.
+
+        Currently, pre-expired cookies never get this far -- the CookieJar
+        class deletes such cookies itself.
+
+        """
+        raise NotImplementedError()
+
+    def return_ok(self, cookie, request):
+        """Return true if (and only if) cookie should be returned to server."""
+        raise NotImplementedError()
+
+    def domain_return_ok(self, domain, request):
+        """Return false if cookies should not be returned, given cookie domain.
+        """
+        return True
+
+    def path_return_ok(self, path, request):
+        """Return false if cookies should not be returned, given cookie path.
+        """
+        return True
+
+
+class DefaultCookiePolicy(CookiePolicy):
+    """Implements the standard rules for accepting and returning cookies."""
+
+    DomainStrictNoDots = 1
+    DomainStrictNonDomain = 2
+    DomainRFC2965Match = 4
+
+    DomainLiberal = 0
+    DomainStrict = DomainStrictNoDots|DomainStrictNonDomain
+
+    def __init__(self,
+                 blocked_domains=None, allowed_domains=None,
+                 netscape=True, rfc2965=False,
+                 rfc2109_as_netscape=None,
+                 hide_cookie2=False,
+                 strict_domain=False,
+                 strict_rfc2965_unverifiable=True,
+                 strict_ns_unverifiable=False,
+                 strict_ns_domain=DomainLiberal,
+                 strict_ns_set_initial_dollar=False,
+                 strict_ns_set_path=False,
+                 ):
+        """Constructor arguments should be passed as keyword arguments only."""
+        self.netscape = netscape
+        self.rfc2965 = rfc2965
+        self.rfc2109_as_netscape = rfc2109_as_netscape
+        self.hide_cookie2 = hide_cookie2
+        self.strict_domain = strict_domain
+        self.strict_rfc2965_unverifiable = strict_rfc2965_unverifiable
+        self.strict_ns_unverifiable = strict_ns_unverifiable
+        self.strict_ns_domain = strict_ns_domain
+        self.strict_ns_set_initial_dollar = strict_ns_set_initial_dollar
+        self.strict_ns_set_path = strict_ns_set_path
+
+        if blocked_domains is not None:
+            self._blocked_domains = tuple(blocked_domains)
+        else:
+            self._blocked_domains = ()
+
+        if allowed_domains is not None:
+            allowed_domains = tuple(allowed_domains)
+        self._allowed_domains = allowed_domains
+
+    def blocked_domains(self):
+        """Return the sequence of blocked domains (as a tuple)."""
+        return self._blocked_domains
+    def set_blocked_domains(self, blocked_domains):
+        """Set the sequence of blocked domains."""
+        self._blocked_domains = tuple(blocked_domains)
+
+    def is_blocked(self, domain):
+        for blocked_domain in self._blocked_domains:
+            if user_domain_match(domain, blocked_domain):
+                return True
+        return False
+
+    def allowed_domains(self):
+        """Return None, or the sequence of allowed domains (as a tuple)."""
+        return self._allowed_domains
+    def set_allowed_domains(self, allowed_domains):
+        """Set the sequence of allowed domains, or None."""
+        if allowed_domains is not None:
+            allowed_domains = tuple(allowed_domains)
+        self._allowed_domains = allowed_domains
+
+    def is_not_allowed(self, domain):
+        if self._allowed_domains is None:
+            return False
+        for allowed_domain in self._allowed_domains:
+            if user_domain_match(domain, allowed_domain):
+                return False
+        return True
+
+    def set_ok(self, cookie, request):
+        """
+        If you override .set_ok(), be sure to call this method.  If it returns
+        false, so should your subclass (assuming your subclass wants to be more
+        strict about which cookies to accept).
+
+        """
+        _debug(" - checking cookie %s=%s", cookie.name, cookie.value)
+
+        assert cookie.name is not None
+
+        for n in "version", "verifiability", "name", "path", "domain", "port":
+            fn_name = "set_ok_"+n
+            fn = getattr(self, fn_name)
+            if not fn(cookie, request):
+                return False
+
+        return True
+
+    def set_ok_version(self, cookie, request):
+        if cookie.version is None:
+            # Version is always set to 0 by parse_ns_headers if it's a Netscape
+            # cookie, so this must be an invalid RFC 2965 cookie.
+            _debug("   Set-Cookie2 without version attribute (%s=%s)",
+                   cookie.name, cookie.value)
+            return False
+        if cookie.version > 0 and not self.rfc2965:
+            _debug("   RFC 2965 cookies are switched off")
+            return False
+        elif cookie.version == 0 and not self.netscape:
+            _debug("   Netscape cookies are switched off")
+            return False
+        return True
+
+    def set_ok_verifiability(self, cookie, request):
+        if request.is_unverifiable() and is_third_party(request):
+            if cookie.version > 0 and self.strict_rfc2965_unverifiable:
+                _debug("   third-party RFC 2965 cookie during "
+                             "unverifiable transaction")
+                return False
+            elif cookie.version == 0 and self.strict_ns_unverifiable:
+                _debug("   third-party Netscape cookie during "
+                             "unverifiable transaction")
+                return False
+        return True
+
+    def set_ok_name(self, cookie, request):
+        # Try and stop servers setting V0 cookies designed to hack other
+        # servers that know both V0 and V1 protocols.
+        if (cookie.version == 0 and self.strict_ns_set_initial_dollar and
+            cookie.name.startswith("$")):
+            _debug("   illegal name (starts with '$'): '%s'", cookie.name)
+            return False
+        return True
+
+    def set_ok_path(self, cookie, request):
+        if cookie.path_specified:
+            req_path = request_path(request)
+            if ((cookie.version > 0 or
+                 (cookie.version == 0 and self.strict_ns_set_path)) and
+                not req_path.startswith(cookie.path)):
+                _debug("   path attribute %s is not a prefix of request "
+                       "path %s", cookie.path, req_path)
+                return False
+        return True
+
+    def set_ok_domain(self, cookie, request):
+        if self.is_blocked(cookie.domain):
+            _debug("   domain %s is in user block-list", cookie.domain)
+            return False
+        if self.is_not_allowed(cookie.domain):
+            _debug("   domain %s is not in user allow-list", cookie.domain)
+            return False
+        if cookie.domain_specified:
+            req_host, erhn = eff_request_host(request)
+            domain = cookie.domain
+            if self.strict_domain and (domain.count(".") >= 2):
+                # XXX This should probably be compared with the Konqueror
+                # (kcookiejar.cpp) and Mozilla implementations, but it's a
+                # losing battle.
+                i = domain.rfind(".")
+                j = domain.rfind(".", 0, i)
+                if j == 0:  # domain like .foo.bar
+                    tld = domain[i+1:]
+                    sld = domain[j+1:i]
+                    if sld.lower() in ("co", "ac", "com", "edu", "org", "net",
+                       "gov", "mil", "int", "aero", "biz", "cat", "coop",
+                       "info", "jobs", "mobi", "museum", "name", "pro",
+                       "travel", "eu") and len(tld) == 2:
+                        # domain like .co.uk
+                        _debug("   country-code second level domain %s", domain)
+                        return False
+            if domain.startswith("."):
+                undotted_domain = domain[1:]
+            else:
+                undotted_domain = domain
+            embedded_dots = (undotted_domain.find(".") >= 0)
+            if not embedded_dots and domain != ".local":
+                _debug("   non-local domain %s contains no embedded dot",
+                       domain)
+                return False
+            if cookie.version == 0:
+                if (not erhn.endswith(domain) and
+                    (not erhn.startswith(".") and
+                     not ("."+erhn).endswith(domain))):
+                    _debug("   effective request-host %s (even with added "
+                           "initial dot) does not end with %s",
+                           erhn, domain)
+                    return False
+            if (cookie.version > 0 or
+                (self.strict_ns_domain & self.DomainRFC2965Match)):
+                if not domain_match(erhn, domain):
+                    _debug("   effective request-host %s does not domain-match "
+                           "%s", erhn, domain)
+                    return False
+            if (cookie.version > 0 or
+                (self.strict_ns_domain & self.DomainStrictNoDots)):
+                host_prefix = req_host[:-len(domain)]
+                if (host_prefix.find(".") >= 0 and
+                    not IPV4_RE.search(req_host)):
+                    _debug("   host prefix %s for domain %s contains a dot",
+                           host_prefix, domain)
+                    return False
+        return True
+
+    def set_ok_port(self, cookie, request):
+        if cookie.port_specified:
+            req_port = request_port(request)
+            if req_port is None:
+                req_port = "80"
+            else:
+                req_port = str(req_port)
+            for p in cookie.port.split(","):
+                try:
+                    int(p)
+                except ValueError:
+                    _debug("   bad port %s (not numeric)", p)
+                    return False
+                if p == req_port:
+                    break
+            else:
+                _debug("   request port (%s) not found in %s",
+                       req_port, cookie.port)
+                return False
+        return True
+
+    def return_ok(self, cookie, request):
+        """
+        If you override .return_ok(), be sure to call this method.  If it
+        returns false, so should your subclass (assuming your subclass wants to
+        be more strict about which cookies to return).
+
+        """
+        # Path has already been checked by .path_return_ok(), and domain
+        # blocking done by .domain_return_ok().
+        _debug(" - checking cookie %s=%s", cookie.name, cookie.value)
+
+        for n in "version", "verifiability", "secure", "expires", "port", "domain":
+            fn_name = "return_ok_"+n
+            fn = getattr(self, fn_name)
+            if not fn(cookie, request):
+                return False
+        return True
+
+    def return_ok_version(self, cookie, request):
+        if cookie.version > 0 and not self.rfc2965:
+            _debug("   RFC 2965 cookies are switched off")
+            return False
+        elif cookie.version == 0 and not self.netscape:
+            _debug("   Netscape cookies are switched off")
+            return False
+        return True
+
+    def return_ok_verifiability(self, cookie, request):
+        if request.is_unverifiable() and is_third_party(request):
+            if cookie.version > 0 and self.strict_rfc2965_unverifiable:
+                _debug("   third-party RFC 2965 cookie during unverifiable "
+                       "transaction")
+                return False
+            elif cookie.version == 0 and self.strict_ns_unverifiable:
+                _debug("   third-party Netscape cookie during unverifiable "
+                       "transaction")
+                return False
+        return True
+
+    def return_ok_secure(self, cookie, request):
+        if cookie.secure and request.get_type() != "https":
+            _debug("   secure cookie with non-secure request")
+            return False
+        return True
+
+    def return_ok_expires(self, cookie, request):
+        if cookie.is_expired(self._now):
+            _debug("   cookie expired")
+            return False
+        return True
+
+    def return_ok_port(self, cookie, request):
+        if cookie.port:
+            req_port = request_port(request)
+            if req_port is None:
+                req_port = "80"
+            for p in cookie.port.split(","):
+                if p == req_port:
+                    break
+            else:
+                _debug("   request port %s does not match cookie port %s",
+                       req_port, cookie.port)
+                return False
+        return True
+
+    def return_ok_domain(self, cookie, request):
+        req_host, erhn = eff_request_host(request)
+        domain = cookie.domain
+
+        # strict check of non-domain cookies: Mozilla does this, MSIE5 doesn't
+        if (cookie.version == 0 and
+            (self.strict_ns_domain & self.DomainStrictNonDomain) and
+            not cookie.domain_specified and domain != erhn):
+            _debug("   cookie with unspecified domain does not string-compare "
+                   "equal to request domain")
+            return False
+
+        if cookie.version > 0 and not domain_match(erhn, domain):
+            _debug("   effective request-host name %s does not domain-match "
+                   "RFC 2965 cookie domain %s", erhn, domain)
+            return False
+        if cookie.version == 0 and not ("."+erhn).endswith(domain):
+            _debug("   request-host %s does not match Netscape cookie domain "
+                   "%s", req_host, domain)
+            return False
+        return True
+
+    def domain_return_ok(self, domain, request):
+        # Liberal check of.  This is here as an optimization to avoid
+        # having to load lots of MSIE cookie files unless necessary.
+        req_host, erhn = eff_request_host(request)
+        if not req_host.startswith("."):
+            req_host = "."+req_host
+        if not erhn.startswith("."):
+            erhn = "."+erhn
+        if not (req_host.endswith(domain) or erhn.endswith(domain)):
+            #_debug("   request domain %s does not match cookie domain %s",
+            #       req_host, domain)
+            return False
+
+        if self.is_blocked(domain):
+            _debug("   domain %s is in user block-list", domain)
+            return False
+        if self.is_not_allowed(domain):
+            _debug("   domain %s is not in user allow-list", domain)
+            return False
+
+        return True
+
+    def path_return_ok(self, path, request):
+        _debug("- checking cookie path=%s", path)
+        req_path = request_path(request)
+        if not req_path.startswith(path):
+            _debug("  %s does not path-match %s", req_path, path)
+            return False
+        return True
+
+
+def vals_sorted_by_key(adict):
+    keys = adict.keys()
+    keys.sort()
+    return map(adict.get, keys)
+
+def deepvalues(mapping):
+    """Iterates over nested mapping, depth-first, in sorted order by key."""
+    values = vals_sorted_by_key(mapping)
+    for obj in values:
+        mapping = False
+        try:
+            obj.items
+        except AttributeError:
+            pass
+        else:
+            mapping = True
+            for subobj in deepvalues(obj):
+                yield subobj
+        if not mapping:
+            yield obj
+
+
+# Used as second parameter to dict.get() method, to distinguish absent
+# dict key from one with a None value.
+class Absent: pass
+
+class CookieJar:
+    """Collection of HTTP cookies.
+
+    You may not need to know about this class: try
+    urllib2.build_opener(HTTPCookieProcessor).open(url).
+
+    """
+
+    non_word_re = re.compile(r"\W")
+    quote_re = re.compile(r"([\"\\])")
+    strict_domain_re = re.compile(r"\.?[^.]*")
+    domain_re = re.compile(r"[^.]*")
+    dots_re = re.compile(r"^\.+")
+
+    magic_re = r"^\#LWP-Cookies-(\d+\.\d+)"
+
+    def __init__(self, policy=None):
+        if policy is None:
+            policy = DefaultCookiePolicy()
+        self._policy = policy
+
+        self._cookies_lock = _threading.RLock()
+        self._cookies = {}
+
+    def set_policy(self, policy):
+        self._policy = policy
+
+    def _cookies_for_domain(self, domain, request):
+        cookies = []
+        if not self._policy.domain_return_ok(domain, request):
+            return []
+        _debug("Checking %s for cookies to return", domain)
+        cookies_by_path = self._cookies[domain]
+        for path in cookies_by_path.keys():
+            if not self._policy.path_return_ok(path, request):
+                continue
+            cookies_by_name = cookies_by_path[path]
+            for cookie in cookies_by_name.values():
+                if not self._policy.return_ok(cookie, request):
+                    _debug("   not returning cookie")
+                    continue
+                _debug("   it's a match")
+                cookies.append(cookie)
+        return cookies
+
+    def _cookies_for_request(self, request):
+        """Return a list of cookies to be returned to server."""
+        cookies = []
+        for domain in self._cookies.keys():
+            cookies.extend(self._cookies_for_domain(domain, request))
+        return cookies
+
+    def _cookie_attrs(self, cookies):
+        """Return a list of cookie-attributes to be returned to server.
+
+        like ['foo="bar"; $Path="/"', ...]
+
+        The $Version attribute is also added when appropriate (currently only
+        once per request).
+
+        """
+        # add cookies in order of most specific (ie. longest) path first
+        cookies.sort(key=lambda arg: len(arg.path), reverse=True)
+
+        version_set = False
+
+        attrs = []
+        for cookie in cookies:
+            # set version of Cookie header
+            # XXX
+            # What should it be if multiple matching Set-Cookie headers have
+            #  different versions themselves?
+            # Answer: there is no answer; was supposed to be settled by
+            #  RFC 2965 errata, but that may never appear...
+            version = cookie.version
+            if not version_set:
+                version_set = True
+                if version > 0:
+                    attrs.append("$Version=%s" % version)
+
+            # quote cookie value if necessary
+            # (not for Netscape protocol, which already has any quotes
+            #  intact, due to the poorly-specified Netscape Cookie: syntax)
+            if ((cookie.value is not None) and
+                self.non_word_re.search(cookie.value) and version > 0):
+                value = self.quote_re.sub(r"\\\1", cookie.value)
+            else:
+                value = cookie.value
+
+            # add cookie-attributes to be returned in Cookie header
+            if cookie.value is None:
+                attrs.append(cookie.name)
+            else:
+                attrs.append("%s=%s" % (cookie.name, value))
+            if version > 0:
+                if cookie.path_specified:
+                    attrs.append('$Path="%s"' % cookie.path)
+                if cookie.domain.startswith("."):
+                    domain = cookie.domain
+                    if (not cookie.domain_initial_dot and
+                        domain.startswith(".")):
+                        domain = domain[1:]
+                    attrs.append('$Domain="%s"' % domain)
+                if cookie.port is not None:
+                    p = "$Port"
+                    if cookie.port_specified:
+                        p = p + ('="%s"' % cookie.port)
+                    attrs.append(p)
+
+        return attrs
+
+    def add_cookie_header(self, request):
+        """Add correct Cookie: header to request (urllib2.Request object).
+
+        The Cookie2 header is also added unless policy.hide_cookie2 is true.
+
+        """
+        _debug("add_cookie_header")
+        self._cookies_lock.acquire()
+        try:
+
+            self._policy._now = self._now = int(time.time())
+
+            cookies = self._cookies_for_request(request)
+
+            attrs = self._cookie_attrs(cookies)
+            if attrs:
+                if not request.has_header("Cookie"):
+                    request.add_unredirected_header(
+                        "Cookie", "; ".join(attrs))
+
+            # if necessary, advertise that we know RFC 2965
+            if (self._policy.rfc2965 and not self._policy.hide_cookie2 and
+                not request.has_header("Cookie2")):
+                for cookie in cookies:
+                    if cookie.version != 1:
+                        request.add_unredirected_header("Cookie2", '$Version="1"')
+                        break
+
+        finally:
+            self._cookies_lock.release()
+
+        self.clear_expired_cookies()
+
+    def _normalized_cookie_tuples(self, attrs_set):
+        """Return list of tuples containing normalised cookie information.
+
+        attrs_set is the list of lists of key,value pairs extracted from
+        the Set-Cookie or Set-Cookie2 headers.
+
+        Tuples are name, value, standard, rest, where name and value are the
+        cookie name and value, standard is a dictionary containing the standard
+        cookie-attributes (discard, secure, version, expires or max-age,
+        domain, path and port) and rest is a dictionary containing the rest of
+        the cookie-attributes.
+
+        """
+        cookie_tuples = []
+
+        boolean_attrs = "discard", "secure"
+        value_attrs = ("version",
+                       "expires", "max-age",
+                       "domain", "path", "port",
+                       "comment", "commenturl")
+
+        for cookie_attrs in attrs_set:
+            name, value = cookie_attrs[0]
+
+            # Build dictionary of standard cookie-attributes (standard) and
+            # dictionary of other cookie-attributes (rest).
+
+            # Note: expiry time is normalised to seconds since epoch.  V0
+            # cookies should have the Expires cookie-attribute, and V1 cookies
+            # should have Max-Age, but since V1 includes RFC 2109 cookies (and
+            # since V0 cookies may be a mish-mash of Netscape and RFC 2109), we
+            # accept either (but prefer Max-Age).
+            max_age_set = False
+
+            bad_cookie = False
+
+            standard = {}
+            rest = {}
+            for k, v in cookie_attrs[1:]:
+                lc = k.lower()
+                # don't lose case distinction for unknown fields
+                if lc in value_attrs or lc in boolean_attrs:
+                    k = lc
+                if k in boolean_attrs and v is None:
+                    # boolean cookie-attribute is present, but has no value
+                    # (like "discard", rather than "port=80")
+                    v = True
+                if k in standard:
+                    # only first value is significant
+                    continue
+                if k == "domain":
+                    if v is None:
+                        _debug("   missing value for domain attribute")
+                        bad_cookie = True
+                        break
+                    # RFC 2965 section 3.3.3
+                    v = v.lower()
+                if k == "expires":
+                    if max_age_set:
+                        # Prefer max-age to expires (like Mozilla)
+                        continue
+                    if v is None:
+                        _debug("   missing or invalid value for expires "
+                              "attribute: treating as session cookie")
+                        continue
+                if k == "max-age":
+                    max_age_set = True
+                    try:
+                        v = int(v)
+                    except ValueError:
+                        _debug("   missing or invalid (non-numeric) value for "
+                              "max-age attribute")
+                        bad_cookie = True
+                        break
+                    # convert RFC 2965 Max-Age to seconds since epoch
+                    # XXX Strictly you're supposed to follow RFC 2616
+                    #   age-calculation rules.  Remember that zero Max-Age is a
+                    #   is a request to discard (old and new) cookie, though.
+                    k = "expires"
+                    v = self._now + v
+                if (k in value_attrs) or (k in boolean_attrs):
+                    if (v is None and
+                        k not in ("port", "comment", "commenturl")):
+                        _debug("   missing value for %s attribute" % k)
+                        bad_cookie = True
+                        break
+                    standard[k] = v
+                else:
+                    rest[k] = v
+
+            if bad_cookie:
+                continue
+
+            cookie_tuples.append((name, value, standard, rest))
+
+        return cookie_tuples
+
+    def _cookie_from_cookie_tuple(self, tup, request):
+        # standard is dict of standard cookie-attributes, rest is dict of the
+        # rest of them
+        name, value, standard, rest = tup
+
+        domain = standard.get("domain", Absent)
+        path = standard.get("path", Absent)
+        port = standard.get("port", Absent)
+        expires = standard.get("expires", Absent)
+
+        # set the easy defaults
+        version = standard.get("version", None)
+        if version is not None:
+            try:
+                version = int(version)
+            except ValueError:
+                return None  # invalid version, ignore cookie
+        secure = standard.get("secure", False)
+        # (discard is also set if expires is Absent)
+        discard = standard.get("discard", False)
+        comment = standard.get("comment", None)
+        comment_url = standard.get("commenturl", None)
+
+        # set default path
+        if path is not Absent and path != "":
+            path_specified = True
+            path = escape_path(path)
+        else:
+            path_specified = False
+            path = request_path(request)
+            i = path.rfind("/")
+            if i != -1:
+                if version == 0:
+                    # Netscape spec parts company from reality here
+                    path = path[:i]
+                else:
+                    path = path[:i+1]
+            if len(path) == 0: path = "/"
+
+        # set default domain
+        domain_specified = domain is not Absent
+        # but first we have to remember whether it starts with a dot
+        domain_initial_dot = False
+        if domain_specified:
+            domain_initial_dot = bool(domain.startswith("."))
+        if domain is Absent:
+            req_host, erhn = eff_request_host(request)
+            domain = erhn
+        elif not domain.startswith("."):
+            domain = "."+domain
+
+        # set default port
+        port_specified = False
+        if port is not Absent:
+            if port is None:
+                # Port attr present, but has no value: default to request port.
+                # Cookie should then only be sent back on that port.
+                port = request_port(request)
+            else:
+                port_specified = True
+                port = re.sub(r"\s+", "", port)
+        else:
+            # No port attr present.  Cookie can be sent back on any port.
+            port = None
+
+        # set default expires and discard
+        if expires is Absent:
+            expires = None
+            discard = True
+        elif expires <= self._now:
+            # Expiry date in past is request to delete cookie.  This can't be
+            # in DefaultCookiePolicy, because can't delete cookies there.
+            try:
+                self.clear(domain, path, name)
+            except KeyError:
+                pass
+            _debug("Expiring cookie, domain='%s', path='%s', name='%s'",
+                   domain, path, name)
+            return None
+
+        return Cookie(version,
+                      name, value,
+                      port, port_specified,
+                      domain, domain_specified, domain_initial_dot,
+                      path, path_specified,
+                      secure,
+                      expires,
+                      discard,
+                      comment,
+                      comment_url,
+                      rest)
+
+    def _cookies_from_attrs_set(self, attrs_set, request):
+        cookie_tuples = self._normalized_cookie_tuples(attrs_set)
+
+        cookies = []
+        for tup in cookie_tuples:
+            cookie = self._cookie_from_cookie_tuple(tup, request)
+            if cookie: cookies.append(cookie)
+        return cookies
+
+    def _process_rfc2109_cookies(self, cookies):
+        rfc2109_as_ns = getattr(self._policy, 'rfc2109_as_netscape', None)
+        if rfc2109_as_ns is None:
+            rfc2109_as_ns = not self._policy.rfc2965
+        for cookie in cookies:
+            if cookie.version == 1:
+                cookie.rfc2109 = True
+                if rfc2109_as_ns:
+                    # treat 2109 cookies as Netscape cookies rather than
+                    # as RFC2965 cookies
+                    cookie.version = 0
+
+    def make_cookies(self, response, request):
+        """Return sequence of Cookie objects extracted from response object."""
+        # get cookie-attributes for RFC 2965 and Netscape protocols
+        headers = response.info()
+        rfc2965_hdrs = headers.getheaders("Set-Cookie2")
+        ns_hdrs = headers.getheaders("Set-Cookie")
+
+        rfc2965 = self._policy.rfc2965
+        netscape = self._policy.netscape
+
+        if ((not rfc2965_hdrs and not ns_hdrs) or
+            (not ns_hdrs and not rfc2965) or
+            (not rfc2965_hdrs and not netscape) or
+            (not netscape and not rfc2965)):
+            return []  # no relevant cookie headers: quick exit
+
+        try:
+            cookies = self._cookies_from_attrs_set(
+                split_header_words(rfc2965_hdrs), request)
+        except Exception:
+            _warn_unhandled_exception()
+            cookies = []
+
+        if ns_hdrs and netscape:
+            try:
+                # RFC 2109 and Netscape cookies
+                ns_cookies = self._cookies_from_attrs_set(
+                    parse_ns_headers(ns_hdrs), request)
+            except Exception:
+                _warn_unhandled_exception()
+                ns_cookies = []
+            self._process_rfc2109_cookies(ns_cookies)
+
+            # Look for Netscape cookies (from Set-Cookie headers) that match
+            # corresponding RFC 2965 cookies (from Set-Cookie2 headers).
+            # For each match, keep the RFC 2965 cookie and ignore the Netscape
+            # cookie (RFC 2965 section 9.1).  Actually, RFC 2109 cookies are
+            # bundled in with the Netscape cookies for this purpose, which is
+            # reasonable behaviour.
+            if rfc2965:
+                lookup = {}
+                for cookie in cookies:
+                    lookup[(cookie.domain, cookie.path, cookie.name)] = None
+
+                def no_matching_rfc2965(ns_cookie, lookup=lookup):
+                    key = ns_cookie.domain, ns_cookie.path, ns_cookie.name
+                    return key not in lookup
+                ns_cookies = filter(no_matching_rfc2965, ns_cookies)
+
+            if ns_cookies:
+                cookies.extend(ns_cookies)
+
+        return cookies
+
+    def set_cookie_if_ok(self, cookie, request):
+        """Set a cookie if policy says it's OK to do so."""
+        self._cookies_lock.acquire()
+        try:
+            self._policy._now = self._now = int(time.time())
+
+            if self._policy.set_ok(cookie, request):
+                self.set_cookie(cookie)
+
+
+        finally:
+            self._cookies_lock.release()
+
+    def set_cookie(self, cookie):
+        """Set a cookie, without checking whether or not it should be set."""
+        c = self._cookies
+        self._cookies_lock.acquire()
+        try:
+            if cookie.domain not in c: c[cookie.domain] = {}
+            c2 = c[cookie.domain]
+            if cookie.path not in c2: c2[cookie.path] = {}
+            c3 = c2[cookie.path]
+            c3[cookie.name] = cookie
+        finally:
+            self._cookies_lock.release()
+
+    def extract_cookies(self, response, request):
+        """Extract cookies from response, where allowable given the request."""
+        _debug("extract_cookies: %s", response.info())
+        self._cookies_lock.acquire()
+        try:
+            self._policy._now = self._now = int(time.time())
+
+            for cookie in self.make_cookies(response, request):
+                if self._policy.set_ok(cookie, request):
+                    _debug(" setting cookie: %s", cookie)
+                    self.set_cookie(cookie)
+        finally:
+            self._cookies_lock.release()
+
+    def clear(self, domain=None, path=None, name=None):
+        """Clear some cookies.
+
+        Invoking this method without arguments will clear all cookies.  If
+        given a single argument, only cookies belonging to that domain will be
+        removed.  If given two arguments, cookies belonging to the specified
+        path within that domain are removed.  If given three arguments, then
+        the cookie with the specified name, path and domain is removed.
+
+        Raises KeyError if no matching cookie exists.
+
+        """
+        if name is not None:
+            if (domain is None) or (path is None):
+                raise ValueError(
+                    "domain and path must be given to remove a cookie by name")
+            del self._cookies[domain][path][name]
+        elif path is not None:
+            if domain is None:
+                raise ValueError(
+                    "domain must be given to remove cookies by path")
+            del self._cookies[domain][path]
+        elif domain is not None:
+            del self._cookies[domain]
+        else:
+            self._cookies = {}
+
+    def clear_session_cookies(self):
+        """Discard all session cookies.
+
+        Note that the .save() method won't save session cookies anyway, unless
+        you ask otherwise by passing a true ignore_discard argument.
+
+        """
+        self._cookies_lock.acquire()
+        try:
+            for cookie in self:
+                if cookie.discard:
+                    self.clear(cookie.domain, cookie.path, cookie.name)
+        finally:
+            self._cookies_lock.release()
+
+    def clear_expired_cookies(self):
+        """Discard all expired cookies.
+
+        You probably don't need to call this method: expired cookies are never
+        sent back to the server (provided you're using DefaultCookiePolicy),
+        this method is called by CookieJar itself every so often, and the
+        .save() method won't save expired cookies anyway (unless you ask
+        otherwise by passing a true ignore_expires argument).
+
+        """
+        self._cookies_lock.acquire()
+        try:
+            now = time.time()
+            for cookie in self:
+                if cookie.is_expired(now):
+                    self.clear(cookie.domain, cookie.path, cookie.name)
+        finally:
+            self._cookies_lock.release()
+
+    def __iter__(self):
+        return deepvalues(self._cookies)
+
+    def __len__(self):
+        """Return number of contained cookies."""
+        i = 0
+        for cookie in self: i = i + 1
+        return i
+
+    def __repr__(self):
+        r = []
+        for cookie in self: r.append(repr(cookie))
+        return "<%s[%s]>" % (self.__class__, ", ".join(r))
+
+    def __str__(self):
+        r = []
+        for cookie in self: r.append(str(cookie))
+        return "<%s[%s]>" % (self.__class__, ", ".join(r))
+
+
+# derives from IOError for backwards-compatibility with Python 2.4.0
+class LoadError(IOError): pass
+
+class FileCookieJar(CookieJar):
+    """CookieJar that can be loaded from and saved to a file."""
+
+    def __init__(self, filename=None, delayload=False, policy=None):
+        """
+        Cookies are NOT loaded from the named file until either the .load() or
+        .revert() method is called.
+
+        """
+        CookieJar.__init__(self, policy)
+        if filename is not None:
+            try:
+                filename+""
+            except:
+                raise ValueError("filename must be string-like")
+        self.filename = filename
+        self.delayload = bool(delayload)
+
+    def save(self, filename=None, ignore_discard=False, ignore_expires=False):
+        """Save cookies to a file."""
+        raise NotImplementedError()
+
+    def load(self, filename=None, ignore_discard=False, ignore_expires=False):
+        """Load cookies from a file."""
+        if filename is None:
+            if self.filename is not None: filename = self.filename
+            else: raise ValueError(MISSING_FILENAME_TEXT)
+
+        f = open(filename)
+        try:
+            self._really_load(f, filename, ignore_discard, ignore_expires)
+        finally:
+            f.close()
+
+    def revert(self, filename=None,
+               ignore_discard=False, ignore_expires=False):
+        """Clear all cookies and reload cookies from a saved file.
+
+        Raises LoadError (or IOError) if reversion is not successful; the
+        object's state will not be altered if this happens.
+
+        """
+        if filename is None:
+            if self.filename is not None: filename = self.filename
+            else: raise ValueError(MISSING_FILENAME_TEXT)
+
+        self._cookies_lock.acquire()
+        try:
+
+            old_state = copy.deepcopy(self._cookies)
+            self._cookies = {}
+            try:
+                self.load(filename, ignore_discard, ignore_expires)
+            except (LoadError, IOError):
+                self._cookies = old_state
+                raise
+
+        finally:
+            self._cookies_lock.release()
+
+from _LWPCookieJar import LWPCookieJar, lwp_cookie_str
+from _MozillaCookieJar import MozillaCookieJar
diff --git a/src/main/resources/PythonLibs/copy.py b/src/main/resources/PythonLibs/copy.py
new file mode 100644
index 0000000000000000000000000000000000000000..c227a2e5c7cb740230652b5b871c74367b6b370d
--- /dev/null
+++ b/src/main/resources/PythonLibs/copy.py
@@ -0,0 +1,433 @@
+"""Generic (shallow and deep) copying operations.
+
+Interface summary:
+
+        import copy
+
+        x = copy.copy(y)        # make a shallow copy of y
+        x = copy.deepcopy(y)    # make a deep copy of y
+
+For module specific errors, copy.Error is raised.
+
+The difference between shallow and deep copying is only relevant for
+compound objects (objects that contain other objects, like lists or
+class instances).
+
+- A shallow copy constructs a new compound object and then (to the
+  extent possible) inserts *the same objects* into it that the
+  original contains.
+
+- A deep copy constructs a new compound object and then, recursively,
+  inserts *copies* into it of the objects found in the original.
+
+Two problems often exist with deep copy operations that don't exist
+with shallow copy operations:
+
+ a) recursive objects (compound objects that, directly or indirectly,
+    contain a reference to themselves) may cause a recursive loop
+
+ b) because deep copy copies *everything* it may copy too much, e.g.
+    administrative data structures that should be shared even between
+    copies
+
+Python's deep copy operation avoids these problems by:
+
+ a) keeping a table of objects already copied during the current
+    copying pass
+
+ b) letting user-defined classes override the copying operation or the
+    set of components copied
+
+This version does not copy types like module, class, function, method,
+nor stack trace, stack frame, nor file, socket, window, nor array, nor
+any similar types.
+
+Classes can use the same interfaces to control copying that they use
+to control pickling: they can define methods called __getinitargs__(),
+__getstate__() and __setstate__().  See the documentation for module
+"pickle" for information on these methods.
+"""
+
+import types
+import weakref
+from copy_reg import dispatch_table
+
+class Error(Exception):
+    pass
+error = Error   # backward compatibility
+
+try:
+    from org.python.core import PyStringMap
+except ImportError:
+    PyStringMap = None
+
+__all__ = ["Error", "copy", "deepcopy"]
+
+def copy(x):
+    """Shallow copy operation on arbitrary Python objects.
+
+    See the module's __doc__ string for more info.
+    """
+
+    cls = type(x)
+
+    copier = _copy_dispatch.get(cls)
+    if copier:
+        return copier(x)
+
+    copier = getattr(cls, "__copy__", None)
+    if copier:
+        return copier(x)
+
+    reductor = dispatch_table.get(cls)
+    if reductor:
+        rv = reductor(x)
+    else:
+        reductor = getattr(x, "__reduce_ex__", None)
+        if reductor:
+            rv = reductor(2)
+        else:
+            reductor = getattr(x, "__reduce__", None)
+            if reductor:
+                rv = reductor()
+            else:
+                raise Error("un(shallow)copyable object of type %s" % cls)
+
+    return _reconstruct(x, rv, 0)
+
+
+_copy_dispatch = d = {}
+
+def _copy_immutable(x):
+    return x
+for t in (type(None), int, long, float, bool, str, tuple,
+          frozenset, type, xrange, types.ClassType,
+          types.BuiltinFunctionType, type(Ellipsis),
+          types.FunctionType, weakref.ref):
+    d[t] = _copy_immutable
+for name in ("ComplexType", "UnicodeType", "CodeType"):
+    t = getattr(types, name, None)
+    if t is not None:
+        d[t] = _copy_immutable
+
+def _copy_with_constructor(x):
+    return type(x)(x)
+for t in (list, dict, set):
+    d[t] = _copy_with_constructor
+
+def _copy_with_copy_method(x):
+    return x.copy()
+if PyStringMap is not None:
+    d[PyStringMap] = _copy_with_copy_method
+
+def _copy_inst(x):
+    if hasattr(x, '__copy__'):
+        return x.__copy__()
+    if hasattr(x, '__getinitargs__'):
+        args = x.__getinitargs__()
+        y = x.__class__(*args)
+    else:
+        y = _EmptyClass()
+        y.__class__ = x.__class__
+    if hasattr(x, '__getstate__'):
+        state = x.__getstate__()
+    else:
+        state = x.__dict__
+    if hasattr(y, '__setstate__'):
+        y.__setstate__(state)
+    else:
+        y.__dict__.update(state)
+    return y
+d[types.InstanceType] = _copy_inst
+
+del d
+
+def deepcopy(x, memo=None, _nil=[]):
+    """Deep copy operation on arbitrary Python objects.
+
+    See the module's __doc__ string for more info.
+    """
+
+    if memo is None:
+        memo = {}
+
+    d = id(x)
+    y = memo.get(d, _nil)
+    if y is not _nil:
+        return y
+
+    cls = type(x)
+
+    copier = _deepcopy_dispatch.get(cls)
+    if copier:
+        y = copier(x, memo)
+    else:
+        try:
+            issc = issubclass(cls, type)
+        except TypeError: # cls is not a class (old Boost; see SF #502085)
+            issc = 0
+        if issc:
+            y = _deepcopy_atomic(x, memo)
+        else:
+            copier = getattr(x, "__deepcopy__", None)
+            if copier:
+                y = copier(memo)
+            else:
+                reductor = dispatch_table.get(cls)
+                if reductor:
+                    rv = reductor(x)
+                else:
+                    reductor = getattr(x, "__reduce_ex__", None)
+                    if reductor:
+                        rv = reductor(2)
+                    else:
+                        reductor = getattr(x, "__reduce__", None)
+                        if reductor:
+                            rv = reductor()
+                        else:
+                            raise Error(
+                                "un(deep)copyable object of type %s" % cls)
+                y = _reconstruct(x, rv, 1, memo)
+
+    memo[d] = y
+    _keep_alive(x, memo) # Make sure x lives at least as long as d
+    return y
+
+_deepcopy_dispatch = d = {}
+
+def _deepcopy_atomic(x, memo):
+    return x
+d[type(None)] = _deepcopy_atomic
+d[type(Ellipsis)] = _deepcopy_atomic
+d[int] = _deepcopy_atomic
+d[long] = _deepcopy_atomic
+d[float] = _deepcopy_atomic
+d[bool] = _deepcopy_atomic
+try:
+    d[complex] = _deepcopy_atomic
+except NameError:
+    pass
+d[str] = _deepcopy_atomic
+try:
+    d[unicode] = _deepcopy_atomic
+except NameError:
+    pass
+try:
+    d[types.CodeType] = _deepcopy_atomic
+except AttributeError:
+    pass
+d[type] = _deepcopy_atomic
+d[xrange] = _deepcopy_atomic
+d[types.ClassType] = _deepcopy_atomic
+d[types.BuiltinFunctionType] = _deepcopy_atomic
+d[types.FunctionType] = _deepcopy_atomic
+d[weakref.ref] = _deepcopy_atomic
+
+def _deepcopy_list(x, memo):
+    y = []
+    memo[id(x)] = y
+    for a in x:
+        y.append(deepcopy(a, memo))
+    return y
+d[list] = _deepcopy_list
+
+def _deepcopy_tuple(x, memo):
+    y = []
+    for a in x:
+        y.append(deepcopy(a, memo))
+    d = id(x)
+    try:
+        return memo[d]
+    except KeyError:
+        pass
+    for i in range(len(x)):
+        if x[i] is not y[i]:
+            y = tuple(y)
+            break
+    else:
+        y = x
+    memo[d] = y
+    return y
+d[tuple] = _deepcopy_tuple
+
+def _deepcopy_dict(x, memo):
+    y = {}
+    memo[id(x)] = y
+    for key, value in x.iteritems():
+        y[deepcopy(key, memo)] = deepcopy(value, memo)
+    return y
+d[dict] = _deepcopy_dict
+if PyStringMap is not None:
+    d[PyStringMap] = _deepcopy_dict
+
+def _deepcopy_method(x, memo): # Copy instance methods
+    return type(x)(x.im_func, deepcopy(x.im_self, memo), x.im_class)
+_deepcopy_dispatch[types.MethodType] = _deepcopy_method
+
+def _keep_alive(x, memo):
+    """Keeps a reference to the object x in the memo.
+
+    Because we remember objects by their id, we have
+    to assure that possibly temporary objects are kept
+    alive by referencing them.
+    We store a reference at the id of the memo, which should
+    normally not be used unless someone tries to deepcopy
+    the memo itself...
+    """
+    try:
+        memo[id(memo)].append(x)
+    except KeyError:
+        # aha, this is the first one :-)
+        memo[id(memo)]=[x]
+
+def _deepcopy_inst(x, memo):
+    if hasattr(x, '__deepcopy__'):
+        return x.__deepcopy__(memo)
+    if hasattr(x, '__getinitargs__'):
+        args = x.__getinitargs__()
+        args = deepcopy(args, memo)
+        y = x.__class__(*args)
+    else:
+        y = _EmptyClass()
+        y.__class__ = x.__class__
+    memo[id(x)] = y
+    if hasattr(x, '__getstate__'):
+        state = x.__getstate__()
+    else:
+        state = x.__dict__
+    state = deepcopy(state, memo)
+    if hasattr(y, '__setstate__'):
+        y.__setstate__(state)
+    else:
+        y.__dict__.update(state)
+    return y
+d[types.InstanceType] = _deepcopy_inst
+
+def _reconstruct(x, info, deep, memo=None):
+    if isinstance(info, str):
+        return x
+    assert isinstance(info, tuple)
+    if memo is None:
+        memo = {}
+    n = len(info)
+    assert n in (2, 3, 4, 5)
+    callable, args = info[:2]
+    if n > 2:
+        state = info[2]
+    else:
+        state = {}
+    if n > 3:
+        listiter = info[3]
+    else:
+        listiter = None
+    if n > 4:
+        dictiter = info[4]
+    else:
+        dictiter = None
+    if deep:
+        args = deepcopy(args, memo)
+    y = callable(*args)
+    memo[id(x)] = y
+
+    if state:
+        if deep:
+            state = deepcopy(state, memo)
+        if hasattr(y, '__setstate__'):
+            y.__setstate__(state)
+        else:
+            if isinstance(state, tuple) and len(state) == 2:
+                state, slotstate = state
+            else:
+                slotstate = None
+            if state is not None:
+                y.__dict__.update(state)
+            if slotstate is not None:
+                for key, value in slotstate.iteritems():
+                    setattr(y, key, value)
+
+    if listiter is not None:
+        for item in listiter:
+            if deep:
+                item = deepcopy(item, memo)
+            y.append(item)
+    if dictiter is not None:
+        for key, value in dictiter:
+            if deep:
+                key = deepcopy(key, memo)
+                value = deepcopy(value, memo)
+            y[key] = value
+    return y
+
+del d
+
+del types
+
+# Helper for instance creation without calling __init__
+class _EmptyClass:
+    pass
+
+def _test():
+    l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
+         {'abc': 'ABC'}, (), [], {}]
+    l1 = copy(l)
+    print l1==l
+    l1 = map(copy, l)
+    print l1==l
+    l1 = deepcopy(l)
+    print l1==l
+    class C:
+        def __init__(self, arg=None):
+            self.a = 1
+            self.arg = arg
+            if __name__ == '__main__':
+                import sys
+                file = sys.argv[0]
+            else:
+                file = __file__
+            self.fp = open(file)
+            self.fp.close()
+        def __getstate__(self):
+            return {'a': self.a, 'arg': self.arg}
+        def __setstate__(self, state):
+            for key, value in state.iteritems():
+                setattr(self, key, value)
+        def __deepcopy__(self, memo=None):
+            new = self.__class__(deepcopy(self.arg, memo))
+            new.a = self.a
+            return new
+    c = C('argument sketch')
+    l.append(c)
+    l2 = copy(l)
+    print l == l2
+    print l
+    print l2
+    l2 = deepcopy(l)
+    print l == l2
+    print l
+    print l2
+    l.append({l[1]: l, 'xyz': l[2]})
+    l3 = copy(l)
+    import repr
+    print map(repr.repr, l)
+    print map(repr.repr, l1)
+    print map(repr.repr, l2)
+    print map(repr.repr, l3)
+    l3 = deepcopy(l)
+    import repr
+    print map(repr.repr, l)
+    print map(repr.repr, l1)
+    print map(repr.repr, l2)
+    print map(repr.repr, l3)
+    class odict(dict):
+        def __init__(self, d = {}):
+            self.a = 99
+            dict.__init__(self, d)
+        def __setitem__(self, k, i):
+            dict.__setitem__(self, k, i)
+            self.a
+    o = odict({"A" : "B"})
+    x = deepcopy(o)
+    print(o, x)
+
+if __name__ == '__main__':
+    _test()
diff --git a/src/main/resources/PythonLibs/copy_reg.py b/src/main/resources/PythonLibs/copy_reg.py
new file mode 100644
index 0000000000000000000000000000000000000000..db1715092c5dcd0eb1e1a22c0957ee04851b6076
--- /dev/null
+++ b/src/main/resources/PythonLibs/copy_reg.py
@@ -0,0 +1,201 @@
+"""Helper to provide extensibility for pickle/cPickle.
+
+This is only useful to add pickle support for extension types defined in
+C, not for instances of user-defined classes.
+"""
+
+from types import ClassType as _ClassType
+
+__all__ = ["pickle", "constructor",
+           "add_extension", "remove_extension", "clear_extension_cache"]
+
+dispatch_table = {}
+
+def pickle(ob_type, pickle_function, constructor_ob=None):
+    if type(ob_type) is _ClassType:
+        raise TypeError("copy_reg is not intended for use with classes")
+
+    if not hasattr(pickle_function, '__call__'):
+        raise TypeError("reduction functions must be callable")
+    dispatch_table[ob_type] = pickle_function
+
+    # The constructor_ob function is a vestige of safe for unpickling.
+    # There is no reason for the caller to pass it anymore.
+    if constructor_ob is not None:
+        constructor(constructor_ob)
+
+def constructor(object):
+    if not hasattr(object, '__call__'):
+        raise TypeError("constructors must be callable")
+
+# Example: provide pickling support for complex numbers.
+
+try:
+    complex
+except NameError:
+    pass
+else:
+
+    def pickle_complex(c):
+        return complex, (c.real, c.imag)
+
+    pickle(complex, pickle_complex, complex)
+
+# Support for pickling new-style objects
+
+def _reconstructor(cls, base, state):
+    if base is object:
+        obj = object.__new__(cls)
+    else:
+        obj = base.__new__(cls, state)
+        if base.__init__ != object.__init__:
+            base.__init__(obj, state)
+    return obj
+
+_HEAPTYPE = 1<<9
+
+# Python code for object.__reduce_ex__ for protocols 0 and 1
+
+def _reduce_ex(self, proto):
+    assert proto < 2
+    for base in self.__class__.__mro__:
+        if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE:
+            break
+    else:
+        base = object # not really reachable
+    if base is object:
+        state = None
+    else:
+        if base is self.__class__:
+            raise TypeError, "can't pickle %s objects" % base.__name__
+        state = base(self)
+    args = (self.__class__, base, state)
+    try:
+        getstate = self.__getstate__
+    except AttributeError:
+        if getattr(self, "__slots__", None):
+            raise TypeError("a class that defines __slots__ without "
+                            "defining __getstate__ cannot be pickled")
+        try:
+            dict = self.__dict__
+        except AttributeError:
+            dict = None
+    else:
+        dict = getstate()
+    if dict:
+        return _reconstructor, args, dict
+    else:
+        return _reconstructor, args
+
+# Helper for __reduce_ex__ protocol 2
+
+def __newobj__(cls, *args):
+    return cls.__new__(cls, *args)
+
+def _slotnames(cls):
+    """Return a list of slot names for a given class.
+
+    This needs to find slots defined by the class and its bases, so we
+    can't simply return the __slots__ attribute.  We must walk down
+    the Method Resolution Order and concatenate the __slots__ of each
+    class found there.  (This assumes classes don't modify their
+    __slots__ attribute to misrepresent their slots after the class is
+    defined.)
+    """
+
+    # Get the value from a cache in the class if possible
+    names = cls.__dict__.get("__slotnames__")
+    if names is not None:
+        return names
+
+    # Not cached -- calculate the value
+    names = []
+    if not hasattr(cls, "__slots__"):
+        # This class has no slots
+        pass
+    else:
+        # Slots found -- gather slot names from all base classes
+        for c in cls.__mro__:
+            if "__slots__" in c.__dict__:
+                slots = c.__dict__['__slots__']
+                # if class has a single slot, it can be given as a string
+                if isinstance(slots, basestring):
+                    slots = (slots,)
+                for name in slots:
+                    # special descriptors
+                    if name in ("__dict__", "__weakref__"):
+                        continue
+                    # mangled names
+                    elif name.startswith('__') and not name.endswith('__'):
+                        names.append('_%s%s' % (c.__name__, name))
+                    else:
+                        names.append(name)
+
+    # Cache the outcome in the class if at all possible
+    try:
+        cls.__slotnames__ = names
+    except:
+        pass # But don't die if we can't
+
+    return names
+
+# A registry of extension codes.  This is an ad-hoc compression
+# mechanism.  Whenever a global reference to <module>, <name> is about
+# to be pickled, the (<module>, <name>) tuple is looked up here to see
+# if it is a registered extension code for it.  Extension codes are
+# universal, so that the meaning of a pickle does not depend on
+# context.  (There are also some codes reserved for local use that
+# don't have this restriction.)  Codes are positive ints; 0 is
+# reserved.
+
+_extension_registry = {}                # key -> code
+_inverted_registry = {}                 # code -> key
+_extension_cache = {}                   # code -> object
+# Don't ever rebind those names:  cPickle grabs a reference to them when
+# it's initialized, and won't see a rebinding.
+
+def add_extension(module, name, code):
+    """Register an extension code."""
+    code = int(code)
+    if not 1 <= code <= 0x7fffffff:
+        raise ValueError, "code out of range"
+    key = (module, name)
+    if (_extension_registry.get(key) == code and
+        _inverted_registry.get(code) == key):
+        return # Redundant registrations are benign
+    if key in _extension_registry:
+        raise ValueError("key %s is already registered with code %s" %
+                         (key, _extension_registry[key]))
+    if code in _inverted_registry:
+        raise ValueError("code %s is already in use for key %s" %
+                         (code, _inverted_registry[code]))
+    _extension_registry[key] = code
+    _inverted_registry[code] = key
+
+def remove_extension(module, name, code):
+    """Unregister an extension code.  For testing only."""
+    key = (module, name)
+    if (_extension_registry.get(key) != code or
+        _inverted_registry.get(code) != key):
+        raise ValueError("key %s is not registered with code %s" %
+                         (key, code))
+    del _extension_registry[key]
+    del _inverted_registry[code]
+    if code in _extension_cache:
+        del _extension_cache[code]
+
+def clear_extension_cache():
+    _extension_cache.clear()
+
+# Standard extension code assignments
+
+# Reserved ranges
+
+# First  Last Count  Purpose
+#     1   127   127  Reserved for Python standard library
+#   128   191    64  Reserved for Zope
+#   192   239    48  Reserved for 3rd parties
+#   240   255    16  Reserved for private use (will never be assigned)
+#   256   Inf   Inf  Reserved for future assignment
+
+# Extension codes are assigned by the Python Software Foundation.
diff --git a/src/main/resources/PythonLibs/csv.py b/src/main/resources/PythonLibs/csv.py
new file mode 100644
index 0000000000000000000000000000000000000000..984ed7e581b9a7ac15d47f4711081d06de1e67cf
--- /dev/null
+++ b/src/main/resources/PythonLibs/csv.py
@@ -0,0 +1,451 @@
+
+"""
+csv.py - read/write/investigate CSV files
+"""
+
+import re
+from functools import reduce
+from _csv import Error, __version__, writer, reader, register_dialect, \
+                 unregister_dialect, get_dialect, list_dialects, \
+                 field_size_limit, \
+                 QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, \
+                 __doc__
+from _csv import Dialect as _Dialect
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+__all__ = [ "QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_NONE",
+            "Error", "Dialect", "__doc__", "excel", "excel_tab",
+            "field_size_limit", "reader", "writer",
+            "register_dialect", "get_dialect", "list_dialects", "Sniffer",
+            "unregister_dialect", "__version__", "DictReader", "DictWriter" ]
+
+class Dialect:
+    """Describe an Excel dialect.
+
+    This must be subclassed (see csv.excel).  Valid attributes are:
+    delimiter, quotechar, escapechar, doublequote, skipinitialspace,
+    lineterminator, quoting.
+
+    """
+    _name = ""
+    _valid = False
+    # placeholders
+    delimiter = None
+    quotechar = None
+    escapechar = None
+    doublequote = None
+    skipinitialspace = None
+    lineterminator = None
+    quoting = None
+
+    def __init__(self):
+        if self.__class__ != Dialect:
+            self._valid = True
+        self._validate()
+
+    def _validate(self):
+        try:
+            _Dialect(self)
+        except TypeError, e:
+            # We do this for compatibility with py2.3
+            raise Error(str(e))
+
+class excel(Dialect):
+    """Describe the usual properties of Excel-generated CSV files."""
+    delimiter = ','
+    quotechar = '"'
+    doublequote = True
+    skipinitialspace = False
+    lineterminator = '\r\n'
+    quoting = QUOTE_MINIMAL
+register_dialect("excel", excel)
+
+class excel_tab(excel):
+    """Describe the usual properties of Excel-generated TAB-delimited files."""
+    delimiter = '\t'
+register_dialect("excel-tab", excel_tab)
+
+
+class DictReader:
+    def __init__(self, f, fieldnames=None, restkey=None, restval=None,
+                 dialect="excel", *args, **kwds):
+        self._fieldnames = fieldnames   # list of keys for the dict
+        self.restkey = restkey          # key to catch long rows
+        self.restval = restval          # default value for short rows
+        self.reader = reader(f, dialect, *args, **kwds)
+        self.dialect = dialect
+        self.line_num = 0
+
+    def __iter__(self):
+        return self
+
+    @property
+    def fieldnames(self):
+        if self._fieldnames is None:
+            try:
+                self._fieldnames = self.reader.next()
+            except StopIteration:
+                pass
+        self.line_num = self.reader.line_num
+        return self._fieldnames
+
+    @fieldnames.setter
+    def fieldnames(self, value):
+        self._fieldnames = value
+
+    def next(self):
+        if self.line_num == 0:
+            # Used only for its side effect.
+            self.fieldnames
+        row = self.reader.next()
+        self.line_num = self.reader.line_num
+
+        # unlike the basic reader, we prefer not to return blanks,
+        # because we will typically wind up with a dict full of None
+        # values
+        while row == []:
+            row = self.reader.next()
+        d = dict(zip(self.fieldnames, row))
+        lf = len(self.fieldnames)
+        lr = len(row)
+        if lf < lr:
+            d[self.restkey] = row[lf:]
+        elif lf > lr:
+            for key in self.fieldnames[lr:]:
+                d[key] = self.restval
+        return d
+
+
+class DictWriter:
+    def __init__(self, f, fieldnames, restval="", extrasaction="raise",
+                 dialect="excel", *args, **kwds):
+        self.fieldnames = fieldnames    # list of keys for the dict
+        self.restval = restval          # for writing short dicts
+        if extrasaction.lower() not in ("raise", "ignore"):
+            raise ValueError, \
+                  ("extrasaction (%s) must be 'raise' or 'ignore'" %
+                   extrasaction)
+        self.extrasaction = extrasaction
+        self.writer = writer(f, dialect, *args, **kwds)
+
+    def writeheader(self):
+        header = dict(zip(self.fieldnames, self.fieldnames))
+        self.writerow(header)
+
+    def _dict_to_list(self, rowdict):
+        if self.extrasaction == "raise":
+            wrong_fields = [k for k in rowdict if k not in self.fieldnames]
+            if wrong_fields:
+                raise ValueError("dict contains fields not in fieldnames: " +
+                                 ", ".join(wrong_fields))
+        return [rowdict.get(key, self.restval) for key in self.fieldnames]
+
+    def writerow(self, rowdict):
+        return self.writer.writerow(self._dict_to_list(rowdict))
+
+    def writerows(self, rowdicts):
+        rows = []
+        for rowdict in rowdicts:
+            rows.append(self._dict_to_list(rowdict))
+        return self.writer.writerows(rows)
+
+# Guard Sniffer's type checking against builds that exclude complex()
+try:
+    complex
+except NameError:
+    complex = float
+
+class Sniffer:
+    '''
+    "Sniffs" the format of a CSV file (i.e. delimiter, quotechar)
+    Returns a Dialect object.
+    '''
+    def __init__(self):
+        # in case there is more than one possible delimiter
+        self.preferred = [',', '\t', ';', ' ', ':']
+
+
+    def sniff(self, sample, delimiters=None):
+        """
+        Returns a dialect (or None) corresponding to the sample
+        """
+
+        quotechar, doublequote, delimiter, skipinitialspace = \
+                   self._guess_quote_and_delimiter(sample, delimiters)
+        if not delimiter:
+            delimiter, skipinitialspace = self._guess_delimiter(sample,
+                                                                delimiters)
+
+        if not delimiter:
+            raise Error, "Could not determine delimiter"
+
+        class dialect(Dialect):
+            _name = "sniffed"
+            lineterminator = '\r\n'
+            quoting = QUOTE_MINIMAL
+            # escapechar = ''
+
+        dialect.doublequote = doublequote
+        dialect.delimiter = delimiter
+        # _csv.reader won't accept a quotechar of ''
+        dialect.quotechar = quotechar or '"'
+        dialect.skipinitialspace = skipinitialspace
+
+        return dialect
+
+
+    def _guess_quote_and_delimiter(self, data, delimiters):
+        """
+        Looks for text enclosed between two identical quotes
+        (the probable quotechar) which are preceded and followed
+        by the same character (the probable delimiter).
+        For example:
+                         ,'some text',
+        The quote with the most wins, same with the delimiter.
+        If there is no quotechar the delimiter can't be determined
+        this way.
+        """
+
+        matches = []
+        for restr in ('(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?P=delim)', # ,".*?",
+                      '(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)',   #  ".*?",
+                      '(?P<delim>>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)',  # ,".*?"
+                      '(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?:$|\n)'):                            #  ".*?" (no delim, no space)
+            regexp = re.compile(restr, re.DOTALL | re.MULTILINE)
+            matches = regexp.findall(data)
+            if matches:
+                break
+
+        if not matches:
+            # (quotechar, doublequote, delimiter, skipinitialspace)
+            return ('', False, None, 0)
+        quotes = {}
+        delims = {}
+        spaces = 0
+        for m in matches:
+            n = regexp.groupindex['quote'] - 1
+            key = m[n]
+            if key:
+                quotes[key] = quotes.get(key, 0) + 1
+            try:
+                n = regexp.groupindex['delim'] - 1
+                key = m[n]
+            except KeyError:
+                continue
+            if key and (delimiters is None or key in delimiters):
+                delims[key] = delims.get(key, 0) + 1
+            try:
+                n = regexp.groupindex['space'] - 1
+            except KeyError:
+                continue
+            if m[n]:
+                spaces += 1
+
+        quotechar = reduce(lambda a, b, quotes = quotes:
+                           (quotes[a] > quotes[b]) and a or b, quotes.keys())
+
+        if delims:
+            delim = reduce(lambda a, b, delims = delims:
+                           (delims[a] > delims[b]) and a or b, delims.keys())
+            skipinitialspace = delims[delim] == spaces
+            if delim == '\n': # most likely a file with a single column
+                delim = ''
+        else:
+            # there is *no* delimiter, it's a single column of quoted data
+            delim = ''
+            skipinitialspace = 0
+
+        # if we see an extra quote between delimiters, we've got a
+        # double quoted format
+        dq_regexp = re.compile(r"((%(delim)s)|^)\W*%(quote)s[^%(delim)s\n]*%(quote)s[^%(delim)s\n]*%(quote)s\W*((%(delim)s)|$)" % \
+                               {'delim':delim, 'quote':quotechar}, re.MULTILINE)
+
+
+
+        if dq_regexp.search(data):
+            doublequote = True
+        else:
+            doublequote = False
+
+        return (quotechar, doublequote, delim, skipinitialspace)
+
+
+    def _guess_delimiter(self, data, delimiters):
+        """
+        The delimiter /should/ occur the same number of times on
+        each row. However, due to malformed data, it may not. We don't want
+        an all or nothing approach, so we allow for small variations in this
+        number.
+          1) build a table of the frequency of each character on every line.
+          2) build a table of frequencies of this frequency (meta-frequency?),
+             e.g.  'x occurred 5 times in 10 rows, 6 times in 1000 rows,
+             7 times in 2 rows'
+          3) use the mode of the meta-frequency to determine the /expected/
+             frequency for that character
+          4) find out how often the character actually meets that goal
+          5) the character that best meets its goal is the delimiter
+        For performance reasons, the data is evaluated in chunks, so it can
+        try and evaluate the smallest portion of the data possible, evaluating
+        additional chunks as necessary.
+        """
+
+        data = filter(None, data.split('\n'))
+
+        ascii = [chr(c) for c in range(127)] # 7-bit ASCII
+
+        # build frequency tables
+        chunkLength = min(10, len(data))
+        iteration = 0
+        charFrequency = {}
+        modes = {}
+        delims = {}
+        start, end = 0, min(chunkLength, len(data))
+        while start < len(data):
+            iteration += 1
+            for line in data[start:end]:
+                for char in ascii:
+                    metaFrequency = charFrequency.get(char, {})
+                    # must count even if frequency is 0
+                    freq = line.count(char)
+                    # value is the mode
+                    metaFrequency[freq] = metaFrequency.get(freq, 0) + 1
+                    charFrequency[char] = metaFrequency
+
+            for char in charFrequency.keys():
+                items = charFrequency[char].items()
+                if len(items) == 1 and items[0][0] == 0:
+                    continue
+                # get the mode of the frequencies
+                if len(items) > 1:
+                    modes[char] = reduce(lambda a, b: a[1] > b[1] and a or b,
+                                         items)
+                    # adjust the mode - subtract the sum of all
+                    # other frequencies
+                    items.remove(modes[char])
+                    modes[char] = (modes[char][0], modes[char][1]
+                                   - reduce(lambda a, b: (0, a[1] + b[1]),
+                                            items)[1])
+                else:
+                    modes[char] = items[0]
+
+            # build a list of possible delimiters
+            modeList = modes.items()
+            total = float(chunkLength * iteration)
+            # (rows of consistent data) / (number of rows) = 100%
+            consistency = 1.0
+            # minimum consistency threshold
+            threshold = 0.9
+            while len(delims) == 0 and consistency >= threshold:
+                for k, v in modeList:
+                    if v[0] > 0 and v[1] > 0:
+                        if ((v[1]/total) >= consistency and
+                            (delimiters is None or k in delimiters)):
+                            delims[k] = v
+                consistency -= 0.01
+
+            if len(delims) == 1:
+                delim = delims.keys()[0]
+                skipinitialspace = (data[0].count(delim) ==
+                                    data[0].count("%c " % delim))
+                return (delim, skipinitialspace)
+
+            # analyze another chunkLength lines
+            start = end
+            end += chunkLength
+
+        if not delims:
+            return ('', 0)
+
+        # if there's more than one, fall back to a 'preferred' list
+        if len(delims) > 1:
+            for d in self.preferred:
+                if d in delims.keys():
+                    skipinitialspace = (data[0].count(d) ==
+                                        data[0].count("%c " % d))
+                    return (d, skipinitialspace)
+
+        # nothing else indicates a preference, pick the character that
+        # dominates(?)
+        items = [(v,k) for (k,v) in delims.items()]
+        items.sort()
+        delim = items[-1][1]
+
+        skipinitialspace = (data[0].count(delim) ==
+                            data[0].count("%c " % delim))
+        return (delim, skipinitialspace)
+
+
+    def has_header(self, sample):
+        # Creates a dictionary of types of data in each column. If any
+        # column is of a single type (say, integers), *except* for the first
+        # row, then the first row is presumed to be labels. If the type
+        # can't be determined, it is assumed to be a string in which case
+        # the length of the string is the determining factor: if all of the
+        # rows except for the first are the same length, it's a header.
+        # Finally, a 'vote' is taken at the end for each column, adding or
+        # subtracting from the likelihood of the first row being a header.
+
+        rdr = reader(StringIO(sample), self.sniff(sample))
+
+        header = rdr.next() # assume first row is header
+
+        columns = len(header)
+        columnTypes = {}
+        for i in range(columns): columnTypes[i] = None
+
+        checked = 0
+        for row in rdr:
+            # arbitrary number of rows to check, to keep it sane
+            if checked > 20:
+                break
+            checked += 1
+
+            if len(row) != columns:
+                continue # skip rows that have irregular number of columns
+
+            for col in columnTypes.keys():
+
+                for thisType in [int, long, float, complex]:
+                    try:
+                        thisType(row[col])
+                        break
+                    except (ValueError, OverflowError):
+                        pass
+                else:
+                    # fallback to length of string
+                    thisType = len(row[col])
+
+                # treat longs as ints
+                if thisType == long:
+                    thisType = int
+
+                if thisType != columnTypes[col]:
+                    if columnTypes[col] is None: # add new column type
+                        columnTypes[col] = thisType
+                    else:
+                        # type is inconsistent, remove column from
+                        # consideration
+                        del columnTypes[col]
+
+        # finally, compare results against first row and "vote"
+        # on whether it's a header
+        hasHeader = 0
+        for col, colType in columnTypes.items():
+            if type(colType) == type(0): # it's a length
+                if len(header[col]) != colType:
+                    hasHeader += 1
+                else:
+                    hasHeader -= 1
+            else: # attempt typecast
+                try:
+                    colType(header[col])
+                except (ValueError, TypeError):
+                    hasHeader += 1
+                else:
+                    hasHeader -= 1
+
+        return hasHeader > 0
diff --git a/src/main/resources/PythonLibs/ctypes/__init__.py b/src/main/resources/PythonLibs/ctypes/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..c153bdc1e1e98f73b63fb1b42c37e3e377f91599
--- /dev/null
+++ b/src/main/resources/PythonLibs/ctypes/__init__.py
@@ -0,0 +1,291 @@
+import jffi
+
+__version__ = "0.0.1"
+
+_TypeMap = {
+    'b': jffi.Type.BYTE,
+    'B': jffi.Type.UBYTE,
+    'h': jffi.Type.SHORT,
+    'H': jffi.Type.USHORT,
+    'i': jffi.Type.INT,
+    'I': jffi.Type.UINT,
+    'l': jffi.Type.LONG,
+    'L': jffi.Type.ULONG,
+    'q': jffi.Type.LONGLONG,
+    'Q': jffi.Type.ULONGLONG,
+    'f': jffi.Type.FLOAT,
+    'd': jffi.Type.DOUBLE,
+    '?': jffi.Type.BOOL,
+    'z': jffi.Type.STRING,
+    'P': jffi.Type.POINTER
+}
+
+class _CTypeMetaClass(type):
+
+    def __new__(cls, name, bases, dict):
+        return type.__new__(cls, name, bases, dict)
+
+    def __mul__(self, len):
+        dict = { '_jffi_type': jffi.Type.Array(self, len) }
+
+        # Look back up the stack frame to find out the module this new type is declared in
+        import inspect
+        mod = inspect.getmodule(inspect.stack()[1][0])
+        if mod is None:
+            name = "__main__"
+        else:
+            name = mod.__name__
+        dict["__module__"] = name
+        return type("%s_Array_%d" % (self.__name__, len), (jffi.ArrayCData, _ArrayCData, _CData), dict)
+
+class _CData(object):
+    @classmethod
+    def in_dll(self, lib, name):
+        return self.from_address(lib[name])
+
+    @classmethod
+    def size(self):
+        return self._jffi_type.size()
+
+class _ScalarCData(jffi.ScalarCData, _CData):
+    __metaclass__ = _CTypeMetaClass
+
+    
+class _ArrayCData(object):
+    def __len__(self):
+        return self._jffi_type.length
+
+class _StructLayoutBuilder(object):
+    def __init__(self, union = False):
+        self.size = 0
+        self.offset = 0
+        self.fields = []
+        self.union = union
+
+    def align(self, offset, align):
+        return align + ((offset - 1) & ~(align - 1));
+
+    def add_fields(self, fields):
+        for f in fields:
+            self.add_field(f)
+        return self
+
+    def add_field(self, f):
+        if not issubclass(f[1], _ScalarCData):
+            raise RuntimeError("non-scalar fields not supported")
+
+        if len(f) != 2:
+            raise RuntimeError("structs with bitfields not supported")
+
+        self.offset = self.align(self.offset, alignment(f[1]))
+        self.fields.append(jffi.StructLayout.ScalarField(f[0], f[1], self.offset))
+        if not self.union:
+            self.offset += sizeof(f[1])
+        self.size = max(self.offset, sizeof(f[1]))
+
+        return self
+
+    def build(self):
+        return jffi.StructLayout(fields = self.fields, union = self.union)
+
+class _AggregateMetaClass(type):
+    @staticmethod
+    def __new_aggregate__(cls, name, bases, dict, union = False):
+        if dict.has_key('_fields_'):
+            layout = dict['_jffi_type'] = _StructLayoutBuilder(union).add_fields(dict['_fields_']).build()
+            # make all fields accessible via .foo
+            for f in dict['_fields_']:
+                dict[f[0]] = layout[f[0]]
+            dict['__fields_'] = dict['_fields_']
+        else:
+            dict['__fields_'] = []
+        if dict.has_key('_pack_'):
+            raise NotImplementedError("struct packing not implemented")
+        if dict.has_key('_anonymous_'):
+            raise NotImplementedError("anonymous fields not implemented")
+
+        return type.__new__(cls, name, bases, dict)
+
+    def get_fields(self):
+        return self.__fields_
+
+    def set_fields(self, fields):
+        layout = _StructLayoutBuilder(union = issubclass(Union, self)).add_fields(fields).build()
+        self.__fields_ = fields
+        self._jffi_type = layout
+        # make all fields accessible via .foo
+        for f in fields:
+            setattr(self, f[0], layout[f[0]])
+
+    _fields_ = property(get_fields, set_fields)
+    # Make _pack_ and _anonymous_ throw errors if anyone tries to use them
+    _pack_ = property(None)
+    _anonymous_ = property(None)
+
+class _StructMetaClass(_AggregateMetaClass):
+    def __new__(cls, name, bases, dict):
+        return _AggregateMetaClass.__new_aggregate__(cls, name, bases, dict, union = False)
+
+class _UnionMetaClass(_AggregateMetaClass):
+    def __new__(cls, name, bases, dict):
+        return _AggregateMetaClass.__new_aggregate__(cls, name, bases, dict, union = True)
+
+class Structure(jffi.Structure, _CData):
+    __metaclass__ = _StructMetaClass
+
+class Union(jffi.Structure, _CData):
+    __metaclass__ = _UnionMetaClass
+
+def sizeof(type):
+    if hasattr(type, '_jffi_type'):
+        return type._jffi_type.size()
+    else:
+        raise TypeError("this type has no size")
+
+def alignment(type):
+    return type._jffi_type.alignment()
+
+def addressof(cdata):
+    return cdata.address()
+
+def byref(cdata, offset = 0):
+    return cdata.byref(offset)
+
+def pointer(cdata):
+    return cdata.pointer(POINTER(cdata.__class__))
+
+memmove = jffi.memmove
+memset = jffi.memset
+
+_pointer_type_cache = {}
+def POINTER(ctype):
+    # If a pointer class for the C type has been created, re-use it
+    if _pointer_type_cache.has_key(ctype):
+        return _pointer_type_cache[ctype]
+
+    # Create a new class for this particular C type
+    dict = { '_jffi_type': jffi.Type.Pointer(ctype) }
+    # Look back up the stack frame to find out the module this new type is declared in
+    import inspect
+    mod = inspect.getmodule(inspect.stack()[1][0])
+    if mod is None:
+        name = "__main__"
+    else:
+        name = mod.__name__
+    dict["__module__"] = name
+
+    ptype = type("LP_%s" % (ctype.__name__,), (jffi.PointerCData, _CData), dict)
+    _pointer_type_cache[ctype] = ptype
+    return ptype
+
+class c_bool(_ScalarCData):
+    _type_ = '?'
+    _jffi_type = jffi.Type.BOOL
+
+class c_byte(_ScalarCData):
+    _type_ = 'b'
+    _jffi_type = jffi.Type.BYTE
+
+class c_ubyte(_ScalarCData):
+    _type_ = 'B'
+    _jffi_type = jffi.Type.UBYTE
+
+class c_short(_ScalarCData):
+    _type_ = 'h'
+    _jffi_type = jffi.Type.SHORT
+
+class c_ushort(_ScalarCData):
+    _type_ = 'H'
+    _jffi_type = jffi.Type.USHORT
+
+class c_int(_ScalarCData):
+    _type_ = 'i'
+    _jffi_type = jffi.Type.INT
+
+class c_uint(_ScalarCData):
+    _type_ = 'I'
+    _jffi_type = jffi.Type.UINT
+
+class c_longlong(_ScalarCData):
+    _type_ = 'q'
+    _jffi_type = jffi.Type.LONGLONG
+
+class c_ulonglong(_ScalarCData):
+    _type_ = 'Q'
+    _jffi_type = jffi.Type.ULONGLONG
+
+class c_long(_ScalarCData):
+    _type_ = 'l'
+    _jffi_type = jffi.Type.LONG
+
+class c_ulong(_ScalarCData):
+    _type_ = 'L'
+    _jffi_type = jffi.Type.ULONG
+
+class c_float(_ScalarCData):
+    _type_ = 'f'
+    _jffi_type = jffi.Type.FLOAT
+
+class c_double(_ScalarCData):
+    _type_ = 'd'
+    _jffi_type = jffi.Type.DOUBLE
+
+c_int8 = c_byte
+c_uint8 = c_ubyte
+c_int16 = c_short
+c_uint16 = c_ushort
+c_int32 = c_int
+c_uint32 = c_uint
+c_int64 = c_longlong
+c_uint64 = c_ulonglong
+
+c_size_t = c_ulong
+c_ssize_t = c_long
+
+class c_char_p(jffi.StringCData, _CData):
+    _type_ = 'z'
+    _jffi_type = jffi.Type.STRING
+
+class c_void_p(_ScalarCData):
+    _type_ = 'P'
+    _jffi_type = jffi.Type.POINTER
+
+class _Function(jffi.Function):
+    _restype = c_int
+    _argtypes = None
+
+
+class CDLL:
+    DEFAULT_MODE = jffi.RTLD_GLOBAL | jffi.RTLD_LAZY
+
+    def __init__(self, name, mode = DEFAULT_MODE, handle = None):
+        self._handle = jffi.dlopen(name, mode)
+
+    def __getattr__(self, name):
+        if name.startswith('__') and name.endswith('__'):
+            raise AttributeError, name
+        func = self.__getitem__(name)
+        setattr(self, name, func)
+        return func
+
+    def __getitem__(self, name):
+        return _Function(self._handle.find_symbol(name))
+
+class LibraryLoader(object):
+    def __init__(self, dlltype):
+        self._dlltype = dlltype
+
+    def __getattr__(self, name):
+        if name[0] == '_':
+            raise AttributeError(name)
+        dll = self._dlltype(name)
+        setattr(self, name, dll)
+        return dll
+
+    def __getitem__(self, name):
+        return getattr(self, name)
+
+    def LoadLibrary(self, name):
+        return self._dlltype(name)
+
+cdll = LibraryLoader(CDLL)
diff --git a/src/main/resources/PythonLibs/datetime.py b/src/main/resources/PythonLibs/datetime.py
new file mode 100644
index 0000000000000000000000000000000000000000..894f941390e20d24fd930d5a9aeaf2fb93a47987
--- /dev/null
+++ b/src/main/resources/PythonLibs/datetime.py
@@ -0,0 +1,2074 @@
+"""Concrete date/time and related types -- prototype implemented in Python.
+
+See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
+
+See also http://dir.yahoo.com/Reference/calendars/
+
+For a primer on DST, including many current DST rules, see
+http://webexhibits.org/daylightsaving/
+
+For more about DST than you ever wanted to know, see
+ftp://elsie.nci.nih.gov/pub/
+
+Sources for time zone and DST data: http://www.twinsun.com/tz/tz-link.htm
+
+This was originally copied from the sandbox of the CPython CVS repository.
+Thanks to Tim Peters for suggesting using it.
+"""
+
+import time as _time
+import math as _math
+import sys as _sys
+
+if _sys.platform.startswith('java'):
+    from java.lang import Object
+    from java.sql import Date, Timestamp, Time
+    from java.util import Calendar
+    from org.python.core import Py
+
+
+MINYEAR = 1
+MAXYEAR = 9999
+
+# Utility functions, adapted from Python's Demo/classes/Dates.py, which
+# also assumes the current Gregorian calendar indefinitely extended in
+# both directions.  Difference:  Dates.py calls January 1 of year 0 day
+# number 1.  The code here calls January 1 of year 1 day number 1.  This is
+# to match the definition of the "proleptic Gregorian" calendar in Dershowitz
+# and Reingold's "Calendrical Calculations", where it's the base calendar
+# for all computations.  See the book for algorithms for converting between
+# proleptic Gregorian ordinals and many other calendar systems.
+
+_DAYS_IN_MONTH = [None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+_DAYS_BEFORE_MONTH = [None]
+dbm = 0
+for dim in _DAYS_IN_MONTH[1:]:
+    _DAYS_BEFORE_MONTH.append(dbm)
+    dbm += dim
+del dbm, dim
+
+def _is_leap(year):
+    "year -> 1 if leap year, else 0."
+    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
+
+def _days_in_year(year):
+    "year -> number of days in year (366 if a leap year, else 365)."
+    return 365 + _is_leap(year)
+
+def _days_before_year(year):
+    "year -> number of days before January 1st of year."
+    y = year - 1
+    return y*365 + y//4 - y//100 + y//400
+
+def _days_in_month(year, month):
+    "year, month -> number of days in that month in that year."
+    assert 1 <= month <= 12, month
+    if month == 2 and _is_leap(year):
+        return 29
+    return _DAYS_IN_MONTH[month]
+
+def _days_before_month(year, month):
+    "year, month -> number of days in year preceeding first day of month."
+    if not 1 <= month <= 12:
+        raise ValueError('month must be in 1..12', month)
+    return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year))
+
+def _ymd2ord(year, month, day):
+    "year, month, day -> ordinal, considering 01-Jan-0001 as day 1."
+    if not 1 <= month <= 12:
+        raise ValueError('month must be in 1..12', month)
+    dim = _days_in_month(year, month)
+    if not 1 <= day <= dim:
+        raise ValueError('day must be in 1..%d' % dim, day)
+    return (_days_before_year(year) +
+            _days_before_month(year, month) +
+            day)
+
+_DI400Y = _days_before_year(401)    # number of days in 400 years
+_DI100Y = _days_before_year(101)    #    "    "   "   " 100   "
+_DI4Y   = _days_before_year(5)      #    "    "   "   "   4   "
+
+# A 4-year cycle has an extra leap day over what we'd get from pasting
+# together 4 single years.
+assert _DI4Y == 4 * 365 + 1
+
+# Similarly, a 400-year cycle has an extra leap day over what we'd get from
+# pasting together 4 100-year cycles.
+assert _DI400Y == 4 * _DI100Y + 1
+
+# OTOH, a 100-year cycle has one fewer leap day than we'd get from
+# pasting together 25 4-year cycles.
+assert _DI100Y == 25 * _DI4Y - 1
+
+def _ord2ymd(n):
+    "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
+
+    # n is a 1-based index, starting at 1-Jan-1.  The pattern of leap years
+    # repeats exactly every 400 years.  The basic strategy is to find the
+    # closest 400-year boundary at or before n, then work with the offset
+    # from that boundary to n.  Life is much clearer if we subtract 1 from
+    # n first -- then the values of n at 400-year boundaries are exactly
+    # those divisible by _DI400Y:
+    #
+    #     D  M   Y            n              n-1
+    #     -- --- ----        ----------     ----------------
+    #     31 Dec -400        -_DI400Y       -_DI400Y -1
+    #      1 Jan -399         -_DI400Y +1   -_DI400Y      400-year boundary
+    #     ...
+    #     30 Dec  000        -1             -2
+    #     31 Dec  000         0             -1
+    #      1 Jan  001         1              0            400-year boundary
+    #      2 Jan  001         2              1
+    #      3 Jan  001         3              2
+    #     ...
+    #     31 Dec  400         _DI400Y        _DI400Y -1
+    #      1 Jan  401         _DI400Y +1     _DI400Y      400-year boundary
+    n -= 1
+    n400, n = divmod(n, _DI400Y)
+    year = n400 * 400 + 1   # ..., -399, 1, 401, ...
+
+    # Now n is the (non-negative) offset, in days, from January 1 of year, to
+    # the desired date.  Now compute how many 100-year cycles precede n.
+    # Note that it's possible for n100 to equal 4!  In that case 4 full
+    # 100-year cycles precede the desired day, which implies the desired
+    # day is December 31 at the end of a 400-year cycle.
+    n100, n = divmod(n, _DI100Y)
+
+    # Now compute how many 4-year cycles precede it.
+    n4, n = divmod(n, _DI4Y)
+
+    # And now how many single years.  Again n1 can be 4, and again meaning
+    # that the desired day is December 31 at the end of the 4-year cycle.
+    n1, n = divmod(n, 365)
+
+    year += n100 * 100 + n4 * 4 + n1
+    if n1 == 4 or n100 == 4:
+        assert n == 0
+        return year-1, 12, 31
+
+    # Now the year is correct, and n is the offset from January 1.  We find
+    # the month via an estimate that's either exact or one too large.
+    leapyear = n1 == 3 and (n4 != 24 or n100 == 3)
+    assert leapyear == _is_leap(year)
+    month = (n + 50) >> 5
+    preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear)
+    if preceding > n:  # estimate is too large
+        month -= 1
+        preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear)
+    n -= preceding
+    assert 0 <= n < _days_in_month(year, month)
+
+    # Now the year and month are correct, and n is the offset from the
+    # start of that month:  we're done!
+    return year, month, n+1
+
+# Month and day names.  For localized versions, see the calendar module.
+_MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+_DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
+
+
+def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
+    wday = (_ymd2ord(y, m, d) + 6) % 7
+    dnum = _days_before_month(y, m) + d
+    return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
+
+def _format_time(hh, mm, ss, us):
+    # Skip trailing microseconds when us==0.
+    result = "%02d:%02d:%02d" % (hh, mm, ss)
+    if us:
+        result += ".%06d" % us
+    return result
+
+# Correctly substitute for %z and %Z escapes in strftime formats.
+def _wrap_strftime(object, format, timetuple):
+    year = timetuple[0]
+    if year < 1900:
+        raise ValueError("year=%d is before 1900; the datetime strftime() "
+                         "methods require year >= 1900" % year)
+    # Don't call _utcoffset() or tzname() unless actually needed.
+    zreplace = None # the string to use for %z
+    Zreplace = None # the string to use for %Z
+
+    # Scan format for %z and %Z escapes, replacing as needed.
+    newformat = []
+    push = newformat.append
+    i, n = 0, len(format)
+    while i < n:
+        ch = format[i]
+        i += 1
+        if ch == '%':
+            if i < n:
+                ch = format[i]
+                i += 1
+                if ch == 'z':
+                    if zreplace is None:
+                        zreplace = ""
+                        if hasattr(object, "_utcoffset"):
+                            offset = object._utcoffset()
+                            if offset is not None:
+                                sign = '+'
+                                if offset < 0:
+                                    offset = -offset
+                                    sign = '-'
+                                h, m = divmod(offset, 60)
+                                zreplace = '%c%02d%02d' % (sign, h, m)
+                    assert '%' not in zreplace
+                    newformat.append(zreplace)
+                elif ch == 'Z':
+                    if Zreplace is None:
+                        Zreplace = ""
+                        if hasattr(object, "tzname"):
+                            s = object.tzname()
+                            if s is not None:
+                                # strftime is going to have at this: escape %
+                                Zreplace = s.replace('%', '%%')
+                    newformat.append(Zreplace)
+                else:
+                    push('%')
+                    push(ch)
+            else:
+                push('%')
+        else:
+            push(ch)
+    newformat = "".join(newformat)
+    return _time.strftime(newformat, timetuple)
+
+def _call_tzinfo_method(tzinfo, methname, tzinfoarg):
+    if tzinfo is None:
+        return None
+    return getattr(tzinfo, methname)(tzinfoarg)
+
+# Just raise TypeError if the arg isn't None or a string.
+def _check_tzname(name):
+    if name is not None and not isinstance(name, str):
+        raise TypeError("tzinfo.tzname() must return None or string, "
+                        "not '%s'" % type(name))
+
+# name is the offset-producing method, "utcoffset" or "dst".
+# offset is what it returned.
+# If offset isn't None or timedelta, raises TypeError.
+# If offset is None, returns None.
+# Else offset is checked for being in range, and a whole # of minutes.
+# If it is, its integer value is returned.  Else ValueError is raised.
+def _check_utc_offset(name, offset):
+    assert name in ("utcoffset", "dst")
+    if offset is None:
+        return None
+    if not isinstance(offset, timedelta):
+        raise TypeError("tzinfo.%s() must return None "
+                        "or timedelta, not '%s'" % (name, type(offset)))
+    days = offset.days
+    if days < -1 or days > 0:
+        offset = 1440  # trigger out-of-range
+    else:
+        seconds = days * 86400 + offset.seconds
+        minutes, seconds = divmod(seconds, 60)
+        if seconds or offset.microseconds:
+            raise ValueError("tzinfo.%s() must return a whole number "
+                             "of minutes" % name)
+        offset = minutes
+    if -1440 < offset < 1440:
+        return offset
+    raise ValueError("%s()=%d, must be in -1439..1439" % (name, offset))
+
+def _check_date_fields(year, month, day):
+    if not MINYEAR <= year <= MAXYEAR:
+        raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
+    if not 1 <= month <= 12:
+        raise ValueError('month must be in 1..12', month)
+    dim = _days_in_month(year, month)
+    if not 1 <= day <= dim:
+        raise ValueError('day must be in 1..%d' % dim, day)
+
+def _check_time_fields(hour, minute, second, microsecond):
+    if not 0 <= hour <= 23:
+        raise ValueError('hour must be in 0..23', hour)
+    if not 0 <= minute <= 59:
+        raise ValueError('minute must be in 0..59', minute)
+    if not 0 <= second <= 59:
+        raise ValueError('second must be in 0..59', second)
+    if not 0 <= microsecond <= 999999:
+        raise ValueError('microsecond must be in 0..999999', microsecond)
+
+def _check_tzinfo_arg(tz):
+    if tz is not None and not isinstance(tz, tzinfo):
+        raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
+
+
+# Notes on comparison:  In general, datetime module comparison operators raise
+# TypeError when they don't know how to do a comparison themself.  If they
+# returned NotImplemented instead, comparison could (silently) fall back to
+# the default compare-objects-by-comparing-their-memory-addresses strategy,
+# and that's not helpful.  There are two exceptions:
+#
+# 1. For date and datetime, if the other object has a "timetuple" attr,
+#    NotImplemented is returned.  This is a hook to allow other kinds of
+#    datetime-like objects a chance to intercept the comparison.
+#
+# 2. Else __eq__ and __ne__ return False and True, respectively.  This is
+#    so opertaions like
+#
+#        x == y
+#        x != y
+#        x in sequence
+#        x not in sequence
+#        dict[x] = y
+#
+#    don't raise annoying TypeErrors just because a datetime object
+#    is part of a heterogeneous collection.  If there's no known way to
+#    compare X to a datetime, saying they're not equal is reasonable.
+
+def _cmperror(x, y):
+    raise TypeError("can't compare '%s' to '%s'" % (
+                    type(x).__name__, type(y).__name__))
+
+# This is a start at a struct tm workalike.  Goals:
+#
+# + Works the same way across platforms.
+# + Handles all the fields datetime needs handled, without 1970-2038 glitches.
+#
+# Note:  I suspect it's best if this flavor of tm does *not* try to
+# second-guess timezones or DST.  Instead fold whatever adjustments you want
+# into the minutes argument (and the constructor will normalize).
+
+_ORD1970 = _ymd2ord(1970, 1, 1) # base ordinal for UNIX epoch
+
+class tmxxx:
+
+    ordinal = None
+
+    def __init__(self, year, month, day, hour=0, minute=0, second=0,
+                 microsecond=0):
+        # Normalize all the inputs, and store the normalized values.
+        if not 0 <= microsecond <= 999999:
+            carry, microsecond = divmod(microsecond, 1000000)
+            second += carry
+        if not 0 <= second <= 59:
+            carry, second = divmod(second, 60)
+            minute += carry
+        if not 0 <= minute <= 59:
+            carry, minute = divmod(minute, 60)
+            hour += carry
+        if not 0 <= hour <= 23:
+            carry, hour = divmod(hour, 24)
+            day += carry
+
+        # That was easy.  Now it gets muddy:  the proper range for day
+        # can't be determined without knowing the correct month and year,
+        # but if day is, e.g., plus or minus a million, the current month
+        # and year values make no sense (and may also be out of bounds
+        # themselves).
+        # Saying 12 months == 1 year should be non-controversial.
+        if not 1 <= month <= 12:
+            carry, month = divmod(month-1, 12)
+            year += carry
+            month += 1
+            assert 1 <= month <= 12
+
+        # Now only day can be out of bounds (year may also be out of bounds
+        # for a datetime object, but we don't care about that here).
+        # If day is out of bounds, what to do is arguable, but at least the
+        # method here is principled and explainable.
+        dim = _days_in_month(year, month)
+        if not 1 <= day <= dim:
+            # Move day-1 days from the first of the month.  First try to
+            # get off cheap if we're only one day out of range (adjustments
+            # for timezone alone can't be worse than that).
+            if day == 0:    # move back a day
+                month -= 1
+                if month > 0:
+                    day = _days_in_month(year, month)
+                else:
+                    year, month, day = year-1, 12, 31
+            elif day == dim + 1:    # move forward a day
+                month += 1
+                day = 1
+                if month > 12:
+                    month = 1
+                    year += 1
+            else:
+                self.ordinal = _ymd2ord(year, month, 1) + (day - 1)
+                year, month, day = _ord2ymd(self.ordinal)
+
+        self.year, self.month, self.day = year, month, day
+        self.hour, self.minute, self.second = hour, minute, second
+        self.microsecond = microsecond
+
+    def toordinal(self):
+        """Return proleptic Gregorian ordinal for the year, month and day.
+
+        January 1 of year 1 is day 1.  Only the year, month and day values
+        contribute to the result.
+        """
+        if self.ordinal is None:
+            self.ordinal = _ymd2ord(self.year, self.month, self.day)
+        return self.ordinal
+
+    def time(self):
+        "Return Unixish timestamp, as a float (assuming UTC)."
+        days = self.toordinal() - _ORD1970   # convert to UNIX epoch
+        seconds = ((days * 24. + self.hour)*60. + self.minute)*60.
+        return seconds + self.second + self.microsecond / 1e6
+
+    def ctime(self):
+        "Return ctime() style string."
+        weekday = self.toordinal() % 7 or 7
+        return "%s %s %2d %02d:%02d:%02d %04d" % (
+            _DAYNAMES[weekday],
+            _MONTHNAMES[self.month],
+            self.day,
+            self.hour, self.minute, self.second,
+            self.year)
+
+class timedelta(object):
+    """Represent the difference between two datetime objects.
+
+    Supported operators:
+
+    - add, subtract timedelta
+    - unary plus, minus, abs
+    - compare to timedelta
+    - multiply, divide by int/long
+
+    In addition, datetime supports subtraction of two datetime objects
+    returning a timedelta, and addition or subtraction of a datetime
+    and a timedelta giving a datetime.
+
+    Representation: (days, seconds, microseconds).  Why?  Because I
+    felt like it.
+    """
+
+    def __new__(cls, days=0, seconds=0, microseconds=0,
+                # XXX The following should only be used as keyword args:
+                milliseconds=0, minutes=0, hours=0, weeks=0):
+        # Doing this efficiently and accurately in C is going to be difficult
+        # and error-prone, due to ubiquitous overflow possibilities, and that
+        # C double doesn't have enough bits of precision to represent
+        # microseconds over 10K years faithfully.  The code here tries to make
+        # explicit where go-fast assumptions can be relied on, in order to
+        # guide the C implementation; it's way more convoluted than speed-
+        # ignoring auto-overflow-to-long idiomatic Python could be.
+
+        # XXX Check that all inputs are ints, longs or floats.
+
+        # Final values, all integer.
+        # s and us fit in 32-bit signed ints; d isn't bounded.
+        d = s = us = 0
+
+        # Normalize everything to days, seconds, microseconds.
+        days += weeks*7
+        seconds += minutes*60 + hours*3600
+        microseconds += milliseconds*1000
+
+        # Get rid of all fractions, and normalize s and us.
+        # Take a deep breath <wink>.
+        if isinstance(days, float):
+            dayfrac, days = _math.modf(days)
+            daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.))
+            assert daysecondswhole == int(daysecondswhole)  # can't overflow
+            s = int(daysecondswhole)
+            assert days == long(days)
+            d = long(days)
+        else:
+            daysecondsfrac = 0.0
+            d = days
+        assert isinstance(daysecondsfrac, float)
+        assert abs(daysecondsfrac) <= 1.0
+        assert isinstance(d, (int, long))
+        assert abs(s) <= 24 * 3600
+        # days isn't referenced again before redefinition
+
+        if isinstance(seconds, float):
+            secondsfrac, seconds = _math.modf(seconds)
+            assert seconds == long(seconds)
+            seconds = long(seconds)
+            secondsfrac += daysecondsfrac
+            assert abs(secondsfrac) <= 2.0
+        else:
+            secondsfrac = daysecondsfrac
+        # daysecondsfrac isn't referenced again
+        assert isinstance(secondsfrac, float)
+        assert abs(secondsfrac) <= 2.0
+
+        assert isinstance(seconds, (int, long))
+        days, seconds = divmod(seconds, 24*3600)
+        d += days
+        s += int(seconds)    # can't overflow
+        assert isinstance(s, int)
+        assert abs(s) <= 2 * 24 * 3600
+        # seconds isn't referenced again before redefinition
+
+        usdouble = secondsfrac * 1e6
+        assert abs(usdouble) < 2.1e6    # exact value not critical
+        # secondsfrac isn't referenced again
+
+        if isinstance(microseconds, float):
+            microseconds += usdouble
+            microseconds = round(microseconds)
+            seconds, microseconds = divmod(microseconds, 1e6)
+            assert microseconds == int(microseconds)
+            assert seconds == long(seconds)
+            days, seconds = divmod(seconds, 24.*3600.)
+            assert days == long(days)
+            assert seconds == int(seconds)
+            d += long(days)
+            s += int(seconds)   # can't overflow
+            assert isinstance(s, int)
+            assert abs(s) <= 3 * 24 * 3600
+        else:
+            seconds, microseconds = divmod(microseconds, 1000000)
+            days, seconds = divmod(seconds, 24*3600)
+            d += days
+            s += int(seconds)    # can't overflow
+            assert isinstance(s, int)
+            assert abs(s) <= 3 * 24 * 3600
+            microseconds = float(microseconds)
+            microseconds += usdouble
+            microseconds = round(microseconds)
+        assert abs(s) <= 3 * 24 * 3600
+        assert abs(microseconds) < 3.1e6
+
+        # Just a little bit of carrying possible for microseconds and seconds.
+        assert isinstance(microseconds, float)
+        assert int(microseconds) == microseconds
+        us = int(microseconds)
+        seconds, us = divmod(us, 1000000)
+        s += seconds    # cant't overflow
+        assert isinstance(s, int)
+        days, s = divmod(s, 24*3600)
+        d += days
+
+        assert isinstance(d, (int, long))
+        assert isinstance(s, int) and 0 <= s < 24*3600
+        assert isinstance(us, int) and 0 <= us < 1000000
+
+        self = object.__new__(cls)
+
+        self.__days = d
+        self.__seconds = s
+        self.__microseconds = us
+        if abs(d) > 999999999:
+            raise OverflowError("timedelta # of days is too large: %d" % d)
+
+        return self
+
+    def __repr__(self):
+        if self.__microseconds:
+            return "%s(%d, %d, %d)" % ('datetime.' + self.__class__.__name__,
+                                       self.__days,
+                                       self.__seconds,
+                                       self.__microseconds)
+        if self.__seconds:
+            return "%s(%d, %d)" % ('datetime.' + self.__class__.__name__,
+                                   self.__days,
+                                   self.__seconds)
+        return "%s(%d)" % ('datetime.' + self.__class__.__name__, self.__days)
+
+    def __str__(self):
+        mm, ss = divmod(self.__seconds, 60)
+        hh, mm = divmod(mm, 60)
+        s = "%d:%02d:%02d" % (hh, mm, ss)
+        if self.__days:
+            def plural(n):
+                return n, abs(n) != 1 and "s" or ""
+            s = ("%d day%s, " % plural(self.__days)) + s
+        if self.__microseconds:
+            s = s + ".%06d" % self.__microseconds
+        return s
+
+    days = property(lambda self: self.__days, doc="days")
+    seconds = property(lambda self: self.__seconds, doc="seconds")
+    microseconds = property(lambda self: self.__microseconds,
+                            doc="microseconds")
+
+    def __add__(self, other):
+        if isinstance(other, timedelta):
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+            return timedelta(self.__days + other.__days,
+                             self.__seconds + other.__seconds,
+                             self.__microseconds + other.__microseconds)
+        return NotImplemented
+
+    __radd__ = __add__
+
+    def __sub__(self, other):
+        if isinstance(other, timedelta):
+            return self + -other
+        return NotImplemented
+
+    def __rsub__(self, other):
+        if isinstance(other, timedelta):
+            return -self + other
+        return NotImplemented
+
+    def __neg__(self):
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+        return timedelta(-self.__days,
+                         -self.__seconds,
+                         -self.__microseconds)
+
+    def __pos__(self):
+        return self
+
+    def __abs__(self):
+        if self.__days < 0:
+            return -self
+        else:
+            return self
+
+    def __mul__(self, other):
+        if isinstance(other, (int, long)):
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+            return timedelta(self.__days * other,
+                             self.__seconds * other,
+                             self.__microseconds * other)
+        return NotImplemented
+
+    __rmul__ = __mul__
+
+    def __div__(self, other):
+        if isinstance(other, (int, long)):
+            usec = ((self.__days * (24*3600L) + self.__seconds) * 1000000 +
+                    self.__microseconds)
+            return timedelta(0, 0, usec // other)
+        return NotImplemented
+
+    __floordiv__ = __div__
+
+    # Comparisons.
+
+    def __eq__(self, other):
+        if isinstance(other, timedelta):
+            return self.__cmp(other) == 0
+        else:
+            return False
+
+    def __ne__(self, other):
+        if isinstance(other, timedelta):
+            return self.__cmp(other) != 0
+        else:
+            return True
+
+    def __le__(self, other):
+        if isinstance(other, timedelta):
+            return self.__cmp(other) <= 0
+        else:
+            _cmperror(self, other)
+
+    def __lt__(self, other):
+        if isinstance(other, timedelta):
+            return self.__cmp(other) < 0
+        else:
+            _cmperror(self, other)
+
+    def __ge__(self, other):
+        if isinstance(other, timedelta):
+            return self.__cmp(other) >= 0
+        else:
+            _cmperror(self, other)
+
+    def __gt__(self, other):
+        if isinstance(other, timedelta):
+            return self.__cmp(other) > 0
+        else:
+            _cmperror(self, other)
+
+    def __cmp(self, other):
+        assert isinstance(other, timedelta)
+        return cmp(self.__getstate(), other.__getstate())
+
+    def __hash__(self):
+        return hash(self.__getstate())
+
+    def __nonzero__(self):
+        return (self.__days != 0 or
+                self.__seconds != 0 or
+                self.__microseconds != 0)
+
+    # Pickle support.
+
+    __safe_for_unpickling__ = True      # For Python 2.2
+
+    def __getstate(self):
+        return (self.__days, self.__seconds, self.__microseconds)
+
+    def __reduce__(self):
+        return (self.__class__, self.__getstate())
+
+timedelta.min = timedelta(-999999999)
+timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
+                          microseconds=999999)
+timedelta.resolution = timedelta(microseconds=1)
+
+class date(object):
+    """Concrete date type.
+
+    Constructors:
+
+    __new__()
+    fromtimestamp()
+    today()
+    fromordinal()
+
+    Operators:
+
+    __repr__, __str__
+    __cmp__, __hash__
+    __add__, __radd__, __sub__ (add/radd only with timedelta arg)
+
+    Methods:
+
+    timetuple()
+    toordinal()
+    weekday()
+    isoweekday(), isocalendar(), isoformat()
+    ctime()
+    strftime()
+
+    Properties (readonly):
+    year, month, day
+    """
+
+    def __new__(cls, year, month=None, day=None):
+        """Constructor.
+
+        Arguments:
+
+        year, month, day (required, base 1)
+        """
+        if isinstance(year, str):
+            # Pickle support
+            self = object.__new__(cls)
+            self.__setstate(year)
+            return self
+        _check_date_fields(year, month, day)
+        self = object.__new__(cls)
+        self.__year = year
+        self.__month = month
+        self.__day = day
+        return self
+
+    # Additional constructors
+
+    def fromtimestamp(cls, t):
+        "Construct a date from a POSIX timestamp (like time.time())."
+        y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
+        return cls(y, m, d)
+    fromtimestamp = classmethod(fromtimestamp)
+
+    def today(cls):
+        "Construct a date from time.time()."
+        t = _time.time()
+        return cls.fromtimestamp(t)
+    today = classmethod(today)
+
+    def fromordinal(cls, n):
+        """Contruct a date from a proleptic Gregorian ordinal.
+
+        January 1 of year 1 is day 1.  Only the year, month and day are
+        non-zero in the result.
+        """
+        y, m, d = _ord2ymd(n)
+        return cls(y, m, d)
+    fromordinal = classmethod(fromordinal)
+
+    # Conversions to string
+
+    def __repr__(self):
+        "Convert to formal string, for repr()."
+        return "%s(%d, %d, %d)" % ('datetime.' + self.__class__.__name__,
+                                   self.__year,
+                                   self.__month,
+                                   self.__day)
+    # XXX These shouldn't depend on time.localtime(), because that
+    # clips the usable dates to [1970 .. 2038).  At least ctime() is
+    # easily done without using strftime() -- that's better too because
+    # strftime("%c", ...) is locale specific.
+
+    def ctime(self):
+        "Format a la ctime()."
+        return tmxxx(self.__year, self.__month, self.__day).ctime()
+
+    def strftime(self, fmt):
+        "Format using strftime()."
+        return _wrap_strftime(self, fmt, self.timetuple())
+
+    def isoformat(self):
+        """Return the date formatted according to ISO.
+
+        This is 'YYYY-MM-DD'.
+
+        References:
+        - http://www.w3.org/TR/NOTE-datetime
+        - http://www.cl.cam.ac.uk/~mgk25/iso-time.html
+        """
+        return "%04d-%02d-%02d" % (self.__year, self.__month, self.__day)
+
+    __str__ = isoformat
+
+    # Read-only field accessors
+    year = property(lambda self: self.__year,
+                    doc="year (%d-%d)" % (MINYEAR, MAXYEAR))
+    month = property(lambda self: self.__month, doc="month (1-12)")
+    day = property(lambda self: self.__day, doc="day (1-31)")
+
+    # Standard conversions, __cmp__, __hash__ (and helpers)
+
+    def timetuple(self):
+        "Return local time tuple compatible with time.localtime()."
+        return _build_struct_time(self.__year, self.__month, self.__day,
+                                  0, 0, 0, -1)
+
+    def toordinal(self):
+        """Return proleptic Gregorian ordinal for the year, month and day.
+
+        January 1 of year 1 is day 1.  Only the year, month and day values
+        contribute to the result.
+        """
+        return _ymd2ord(self.__year, self.__month, self.__day)
+
+    def replace(self, year=None, month=None, day=None):
+        """Return a new date with new values for the specified fields."""
+        if year is None:
+            year = self.__year
+        if month is None:
+            month = self.__month
+        if day is None:
+            day = self.__day
+        _check_date_fields(year, month, day)
+        return date(year, month, day)
+
+    # Comparisons.
+
+    def __eq__(self, other):
+        if isinstance(other, date):
+            return self.__cmp(other) == 0
+        elif hasattr(other, "timetuple"):
+            return NotImplemented
+        else:
+            return False
+
+    def __ne__(self, other):
+        if isinstance(other, date):
+            return self.__cmp(other) != 0
+        elif hasattr(other, "timetuple"):
+            return NotImplemented
+        else:
+            return True
+
+    def __le__(self, other):
+        if isinstance(other, date):
+            return self.__cmp(other) <= 0
+        elif hasattr(other, "timetuple"):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __lt__(self, other):
+        if isinstance(other, date):
+            return self.__cmp(other) < 0
+        elif hasattr(other, "timetuple"):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __ge__(self, other):
+        if isinstance(other, date):
+            return self.__cmp(other) >= 0
+        elif hasattr(other, "timetuple"):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __gt__(self, other):
+        if isinstance(other, date):
+            return self.__cmp(other) > 0
+        elif hasattr(other, "timetuple"):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __cmp(self, other):
+        assert isinstance(other, date)
+        y, m, d = self.__year, self.__month, self.__day
+        y2, m2, d2 = other.__year, other.__month, other.__day
+        return cmp((y, m, d), (y2, m2, d2))
+
+    def __hash__(self):
+        "Hash."
+        return hash(self.__getstate())
+
+    # Computations
+
+    def _checkOverflow(self, year):
+        if not MINYEAR <= year <= MAXYEAR:
+            raise OverflowError("date +/-: result year %d not in %d..%d" %
+                                (year, MINYEAR, MAXYEAR))
+
+    def __add__(self, other):
+        "Add a date to a timedelta."
+        if isinstance(other, timedelta):
+            t = tmxxx(self.__year,
+                      self.__month,
+                      self.__day + other.days)
+            self._checkOverflow(t.year)
+            result = date(t.year, t.month, t.day)
+            return result
+        raise TypeError
+        # XXX Should be 'return NotImplemented', but there's a bug in 2.2...
+
+    __radd__ = __add__
+
+    def __sub__(self, other):
+        """Subtract two dates, or a date and a timedelta."""
+        if isinstance(other, timedelta):
+            return self + timedelta(-other.days)
+        if isinstance(other, date):
+            days1 = self.toordinal()
+            days2 = other.toordinal()
+            return timedelta(days1 - days2)
+        return NotImplemented
+
+    def weekday(self):
+        "Return day of the week, where Monday == 0 ... Sunday == 6."
+        return (self.toordinal() + 6) % 7
+
+    # Day-of-the-week and week-of-the-year, according to ISO
+
+    def isoweekday(self):
+        "Return day of the week, where Monday == 1 ... Sunday == 7."
+        # 1-Jan-0001 is a Monday
+        return self.toordinal() % 7 or 7
+
+    def isocalendar(self):
+        """Return a 3-tuple containing ISO year, week number, and weekday.
+
+        The first ISO week of the year is the (Mon-Sun) week
+        containing the year's first Thursday; everything else derives
+        from that.
+
+        The first week is 1; Monday is 1 ... Sunday is 7.
+
+        ISO calendar algorithm taken from
+        http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
+        """
+        year = self.__year
+        week1monday = _isoweek1monday(year)
+        today = _ymd2ord(self.__year, self.__month, self.__day)
+        # Internally, week and day have origin 0
+        week, day = divmod(today - week1monday, 7)
+        if week < 0:
+            year -= 1
+            week1monday = _isoweek1monday(year)
+            week, day = divmod(today - week1monday, 7)
+        elif week >= 52:
+            if today >= _isoweek1monday(year+1):
+                year += 1
+                week = 0
+        return year, week+1, day+1
+
+    # Pickle support.
+
+    __safe_for_unpickling__ = True      # For Python 2.2
+
+    def __getstate(self):
+        yhi, ylo = divmod(self.__year, 256)
+        return ("%c%c%c%c" % (yhi, ylo, self.__month, self.__day), )
+
+    def __setstate(self, string):
+        if len(string) != 4 or not (1 <= ord(string[2]) <= 12):
+            raise TypeError("not enough arguments")
+        yhi, ylo, self.__month, self.__day = map(ord, string)
+        self.__year = yhi * 256 + ylo
+
+    def __reduce__(self):
+        return (self.__class__, self.__getstate())
+
+    if _sys.platform.startswith('java'):
+        def __tojava__(self, java_class):
+            if java_class not in (Calendar, Date, Object):
+                return Py.NoConversion
+
+            calendar = Calendar.getInstance()
+            calendar.clear()
+            calendar.set(self.year, self.month - 1, self.day)
+            if java_class == Calendar:
+                return calendar
+            else:
+                return Date(calendar.getTimeInMillis())
+
+
+_date_class = date  # so functions w/ args named "date" can get at the class
+
+date.min = date(1, 1, 1)
+date.max = date(9999, 12, 31)
+date.resolution = timedelta(days=1)
+
+class tzinfo(object):
+    """Abstract base class for time zone info classes.
+
+    Subclasses must override the name(), utcoffset() and dst() methods.
+    """
+
+    def tzname(self, dt):
+        "datetime -> string name of time zone."
+        raise NotImplementedError("tzinfo subclass must override tzname()")
+
+    def utcoffset(self, dt):
+        "datetime -> minutes east of UTC (negative for west of UTC)"
+        raise NotImplementedError("tzinfo subclass must override utcoffset()")
+
+    def dst(self, dt):
+        """datetime -> DST offset in minutes east of UTC.
+
+        Return 0 if DST not in effect.  utcoffset() must include the DST
+        offset.
+        """
+        raise NotImplementedError("tzinfo subclass must override dst()")
+
+    def fromutc(self, dt):
+        "datetime in UTC -> datetime in local time."
+
+        if not isinstance(dt, datetime):
+            raise TypeError("fromutc() requires a datetime argument")
+        if dt.tzinfo is not self:
+            raise ValueError("dt.tzinfo is not self")
+
+        dtoff = dt.utcoffset()
+        if dtoff is None:
+            raise ValueError("fromutc() requires a non-None utcoffset() "
+                             "result")
+
+        # See the long comment block at the end of this file for an
+        # explanation of this algorithm.
+        dtdst = dt.dst()
+        if dtdst is None:
+            raise ValueError("fromutc() requires a non-None dst() result")
+        delta = dtoff - dtdst
+        if delta:
+            dt += delta
+            dtdst = dt.dst()
+            if dtdst is None:
+                raise ValueError("fromutc(): dt.dst gave inconsistent "
+                                 "results; cannot convert")
+        if dtdst:
+            return dt + dtdst
+        else:
+            return dt
+
+    # Pickle support.
+
+    __safe_for_unpickling__ = True      # For Python 2.2
+
+    def __reduce__(self):
+        getinitargs = getattr(self, "__getinitargs__", None)
+        if getinitargs:
+            args = getinitargs()
+        else:
+            args = ()
+        getstate = getattr(self, "__getstate__", None)
+        if getstate:
+            state = getstate()
+        else:
+            state = getattr(self, "__dict__", None) or None
+        if state is None:
+            return (self.__class__, args)
+        else:
+            return (self.__class__, args, state)
+
+_tzinfo_class = tzinfo   # so functions w/ args named "tinfo" can get at it
+
+class time(object):
+    """Time with time zone.
+
+    Constructors:
+
+    __new__()
+
+    Operators:
+
+    __repr__, __str__
+    __cmp__, __hash__
+
+    Methods:
+
+    strftime()
+    isoformat()
+    utcoffset()
+    tzname()
+    dst()
+
+    Properties (readonly):
+    hour, minute, second, microsecond, tzinfo
+    """
+
+    def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
+        """Constructor.
+
+        Arguments:
+
+        hour, minute (required)
+        second, microsecond (default to zero)
+        tzinfo (default to None)
+        """
+        self = object.__new__(cls)
+        if isinstance(hour, str):
+            # Pickle support
+            self.__setstate(hour, minute or None)
+            return self
+        _check_tzinfo_arg(tzinfo)
+        _check_time_fields(hour, minute, second, microsecond)
+        self.__hour = hour
+        self.__minute = minute
+        self.__second = second
+        self.__microsecond = microsecond
+        self._tzinfo = tzinfo
+        return self
+
+    # Read-only field accessors
+    hour = property(lambda self: self.__hour, doc="hour (0-23)")
+    minute = property(lambda self: self.__minute, doc="minute (0-59)")
+    second = property(lambda self: self.__second, doc="second (0-59)")
+    microsecond = property(lambda self: self.__microsecond,
+                           doc="microsecond (0-999999)")
+    tzinfo = property(lambda self: self._tzinfo, doc="timezone info object")
+
+    # Standard conversions, __hash__ (and helpers)
+
+    # Comparisons.
+
+    def __eq__(self, other):
+        if isinstance(other, time):
+            return self.__cmp(other) == 0
+        else:
+            return False
+
+    def __ne__(self, other):
+        if isinstance(other, time):
+            return self.__cmp(other) != 0
+        else:
+            return True
+
+    def __le__(self, other):
+        if isinstance(other, time):
+            return self.__cmp(other) <= 0
+        else:
+            _cmperror(self, other)
+
+    def __lt__(self, other):
+        if isinstance(other, time):
+            return self.__cmp(other) < 0
+        else:
+            _cmperror(self, other)
+
+    def __ge__(self, other):
+        if isinstance(other, time):
+            return self.__cmp(other) >= 0
+        else:
+            _cmperror(self, other)
+
+    def __gt__(self, other):
+        if isinstance(other, time):
+            return self.__cmp(other) > 0
+        else:
+            _cmperror(self, other)
+
+    def __cmp(self, other):
+        assert isinstance(other, time)
+        mytz = self._tzinfo
+        ottz = other._tzinfo
+        myoff = otoff = None
+
+        if mytz is ottz:
+            base_compare = True
+        else:
+            myoff = self._utcoffset()
+            otoff = other._utcoffset()
+            base_compare = myoff == otoff
+
+        if base_compare:
+            return cmp((self.__hour, self.__minute, self.__second,
+                        self.__microsecond),
+                       (other.__hour, other.__minute, other.__second,
+                        other.__microsecond))
+        if myoff is None or otoff is None:
+            # XXX Buggy in 2.2.2.
+            raise TypeError("cannot compare naive and aware times")
+        myhhmm = self.__hour * 60 + self.__minute - myoff
+        othhmm = other.__hour * 60 + other.__minute - otoff
+        return cmp((myhhmm, self.__second, self.__microsecond),
+                   (othhmm, other.__second, other.__microsecond))
+
+    def __hash__(self):
+        """Hash."""
+        tzoff = self._utcoffset()
+        if not tzoff: # zero or None
+            return hash(self.__getstate()[0])
+        h, m = divmod(self.hour * 60 + self.minute - tzoff, 60)
+        if 0 <= h < 24:
+            return hash(time(h, m, self.second, self.microsecond))
+        return hash((h, m, self.second, self.microsecond))
+
+    # Conversion to string
+
+    def _tzstr(self, sep=":"):
+        """Return formatted timezone offset (+xx:xx) or None."""
+        off = self._utcoffset()
+        if off is not None:
+            if off < 0:
+                sign = "-"
+                off = -off
+            else:
+                sign = "+"
+            hh, mm = divmod(off, 60)
+            assert 0 <= hh < 24
+            off = "%s%02d%s%02d" % (sign, hh, sep, mm)
+        return off
+
+    def __repr__(self):
+        """Convert to formal string, for repr()."""
+        if self.__microsecond != 0:
+            s = ", %d, %d" % (self.__second, self.__microsecond)
+        elif self.__second != 0:
+            s = ", %d" % self.__second
+        else:
+            s = ""
+        s= "%s(%d, %d%s)" % ('datetime.' + self.__class__.__name__,
+                             self.__hour, self.__minute, s)
+        if self._tzinfo is not None:
+            assert s[-1:] == ")"
+            s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
+        return s
+
+    def isoformat(self):
+        """Return the time formatted according to ISO.
+
+        This is 'HH:MM:SS.mmmmmm+zz:zz', or 'HH:MM:SS+zz:zz' if
+        self.microsecond == 0.
+        """
+        s = _format_time(self.__hour, self.__minute, self.__second,
+                         self.__microsecond)
+        tz = self._tzstr()
+        if tz:
+            s += tz
+        return s
+
+    __str__ = isoformat
+
+    def strftime(self, fmt):
+        """Format using strftime().  The date part of the timestamp passed
+        to underlying strftime should not be used.
+        """
+        # The year must be >= 1900 else Python's strftime implementation
+        # can raise a bogus exception.
+        timetuple = (1900, 1, 1,
+                     self.__hour, self.__minute, self.__second,
+                     0, 1, -1)
+        return _wrap_strftime(self, fmt, timetuple)
+
+    # Timezone functions
+
+    def utcoffset(self):
+        """Return the timezone offset in minutes east of UTC (negative west of
+        UTC)."""
+        offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None)
+        offset = _check_utc_offset("utcoffset", offset)
+        if offset is not None:
+            offset = timedelta(minutes=offset)
+        return offset
+
+    # Return an integer (or None) instead of a timedelta (or None).
+    def _utcoffset(self):
+        offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None)
+        offset = _check_utc_offset("utcoffset", offset)
+        return offset
+
+    def tzname(self):
+        """Return the timezone name.
+
+        Note that the name is 100% informational -- there's no requirement that
+        it mean anything in particular. For example, "GMT", "UTC", "-500",
+        "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
+        """
+        name = _call_tzinfo_method(self._tzinfo, "tzname", None)
+        _check_tzname(name)
+        return name
+
+    def dst(self):
+        """Return 0 if DST is not in effect, or the DST offset (in minutes
+        eastward) if DST is in effect.
+
+        This is purely informational; the DST offset has already been added to
+        the UTC offset returned by utcoffset() if applicable, so there's no
+        need to consult dst() unless you're interested in displaying the DST
+        info.
+        """
+        offset = _call_tzinfo_method(self._tzinfo, "dst", None)
+        offset = _check_utc_offset("dst", offset)
+        if offset is not None:
+            offset = timedelta(minutes=offset)
+        return offset
+
+    def replace(self, hour=None, minute=None, second=None, microsecond=None,
+                tzinfo=True):
+        """Return a new time with new values for the specified fields."""
+        if hour is None:
+            hour = self.hour
+        if minute is None:
+            minute = self.minute
+        if second is None:
+            second = self.second
+        if microsecond is None:
+            microsecond = self.microsecond
+        if tzinfo is True:
+            tzinfo = self.tzinfo
+        _check_time_fields(hour, minute, second, microsecond)
+        _check_tzinfo_arg(tzinfo)
+        return time(hour, minute, second, microsecond, tzinfo)
+
+    # Return an integer (or None) instead of a timedelta (or None).
+    def _dst(self):
+        offset = _call_tzinfo_method(self._tzinfo, "dst", None)
+        offset = _check_utc_offset("dst", offset)
+        return offset
+
+    def __nonzero__(self):
+        if self.second or self.microsecond:
+            return 1
+        offset = self._utcoffset() or 0
+        return self.hour * 60 + self.minute - offset != 0
+
+    # Pickle support.
+
+    __safe_for_unpickling__ = True      # For Python 2.2
+
+    def __getstate(self):
+        us2, us3 = divmod(self.__microsecond, 256)
+        us1, us2 = divmod(us2, 256)
+        basestate = ("%c" * 6) % (self.__hour, self.__minute, self.__second,
+                                  us1, us2, us3)
+        if self._tzinfo is None:
+            return (basestate,)
+        else:
+            return (basestate, self._tzinfo)
+
+    def __setstate(self, string, tzinfo):
+        if len(string) != 6 or ord(string[0]) >= 24:
+            raise TypeError("an integer is required")
+        self.__hour, self.__minute, self.__second, us1, us2, us3 = \
+                                                            map(ord, string)
+        self.__microsecond = (((us1 << 8) | us2) << 8) | us3
+        self._tzinfo = tzinfo
+
+    def __reduce__(self):
+        return (time, self.__getstate())
+
+    if _sys.platform.startswith('java'):
+        def __tojava__(self, java_class):
+            # TODO, if self.tzinfo is not None, convert time to UTC
+            if java_class not in (Calendar, Time, Object):
+                return Py.NoConversion
+
+            calendar = Calendar.getInstance()
+            calendar.clear()
+            calendar.set(Calendar.HOUR_OF_DAY, self.hour)
+            calendar.set(Calendar.MINUTE, self.minute)
+            calendar.set(Calendar.SECOND, self.second)
+            calendar.set(Calendar.MILLISECOND, self.microsecond // 1000)
+            if java_class == Calendar:
+                return calendar
+            else:
+                return Time(calendar.getTimeInMillis())
+
+
+_time_class = time  # so functions w/ args named "time" can get at the class
+
+time.min = time(0, 0, 0)
+time.max = time(23, 59, 59, 999999)
+time.resolution = timedelta(microseconds=1)
+
+class datetime(date):
+
+    # XXX needs docstrings
+    # See http://www.zope.org/Members/fdrake/DateTimeWiki/TimeZoneInfo
+
+    def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
+                microsecond=0, tzinfo=None):
+        if isinstance(year, str):
+            # Pickle support
+            self = date.__new__(cls, year[:4])
+            self.__setstate(year, month)
+            return self
+        _check_tzinfo_arg(tzinfo)
+        _check_time_fields(hour, minute, second, microsecond)
+        self = date.__new__(cls, year, month, day)
+        # XXX This duplicates __year, __month, __day for convenience :-(
+        self.__year = year
+        self.__month = month
+        self.__day = day
+        self.__hour = hour
+        self.__minute = minute
+        self.__second = second
+        self.__microsecond = microsecond
+        self._tzinfo = tzinfo
+        return self
+
+    # Read-only field accessors
+    hour = property(lambda self: self.__hour, doc="hour (0-23)")
+    minute = property(lambda self: self.__minute, doc="minute (0-59)")
+    second = property(lambda self: self.__second, doc="second (0-59)")
+    microsecond = property(lambda self: self.__microsecond,
+                           doc="microsecond (0-999999)")
+    tzinfo = property(lambda self: self._tzinfo, doc="timezone info object")
+
+    def fromtimestamp(cls, t, tz=None):
+        """Construct a datetime from a POSIX timestamp (like time.time()).
+
+        A timezone info object may be passed in as well.
+        """
+
+        _check_tzinfo_arg(tz)
+        if tz is None:
+            converter = _time.localtime
+        else:
+            converter = _time.gmtime
+        y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
+        us = int((t % 1.0) * 1000000)
+
+        if us == 1000001 or us == 999999:
+            us = 0
+            rounded = True
+        else:
+            rounded = False
+
+        ss = min(ss, 59)    # clamp out leap seconds if the platform has them
+        result = cls(y, m, d, hh, mm, ss, us, tz)
+        if rounded:
+            result += timedelta(seconds=1)
+        if tz is not None:
+            result = tz.fromutc(result)
+        return result
+    fromtimestamp = classmethod(fromtimestamp)
+
+    def utcfromtimestamp(cls, t):
+        "Construct a UTC datetime from a POSIX timestamp (like time.time())."
+        y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t)
+        us = int((t % 1.0) * 1000000)
+        ss = min(ss, 59)    # clamp out leap seconds if the platform has them
+        return cls(y, m, d, hh, mm, ss, us)
+    utcfromtimestamp = classmethod(utcfromtimestamp)
+
+    # XXX This is supposed to do better than we *can* do by using time.time(),
+    # XXX if the platform supports a more accurate way.  The C implementation
+    # XXX uses gettimeofday on platforms that have it, but that isn't
+    # XXX available from Python.  So now() may return different results
+    # XXX across the implementations.
+    def now(cls, tz=None):
+        "Construct a datetime from time.time() and optional time zone info."
+        t = _time.time()
+        return cls.fromtimestamp(t, tz)
+    now = classmethod(now)
+
+    def utcnow(cls):
+        "Construct a UTC datetime from time.time()."
+        t = _time.time()
+        return cls.utcfromtimestamp(t)
+    utcnow = classmethod(utcnow)
+
+    def combine(cls, date, time):
+        "Construct a datetime from a given date and a given time."
+        if not isinstance(date, _date_class):
+            raise TypeError("date argument must be a date instance")
+        if not isinstance(time, _time_class):
+            raise TypeError("time argument must be a time instance")
+        return cls(date.year, date.month, date.day,
+                   time.hour, time.minute, time.second, time.microsecond,
+                   time.tzinfo)
+    combine = classmethod(combine)
+
+    def strptime(cls, date_string, format):
+        """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
+
+        The year, month and day arguments are required. tzinfo may be None, or an
+        instance of a tzinfo subclass. The remaining arguments may be ints or longs."""
+        return cls(*(_time.strptime(date_string, format))[0:6])
+
+    strptime = classmethod(strptime)
+
+    def timetuple(self):
+        "Return local time tuple compatible with time.localtime()."
+        dst = self._dst()
+        if dst is None:
+            dst = -1
+        elif dst:
+            dst = 1
+        return _build_struct_time(self.year, self.month, self.day,
+                                  self.hour, self.minute, self.second,
+                                  dst)
+
+    def utctimetuple(self):
+        "Return UTC time tuple compatible with time.gmtime()."
+        y, m, d = self.year, self.month, self.day
+        hh, mm, ss = self.hour, self.minute, self.second
+        offset = self._utcoffset()
+        if offset:  # neither None nor 0
+            tm = tmxxx(y, m, d, hh, mm - offset)
+            y, m, d = tm.year, tm.month, tm.day
+            hh, mm = tm.hour, tm.minute
+        return _build_struct_time(y, m, d, hh, mm, ss, 0)
+
+    def date(self):
+        "Return the date part."
+        return date(self.__year, self.__month, self.__day)
+
+    def time(self):
+        "Return the time part, with tzinfo None."
+        return time(self.hour, self.minute, self.second, self.microsecond)
+
+    def timetz(self):
+        "Return the time part, with same tzinfo."
+        return time(self.hour, self.minute, self.second, self.microsecond,
+                    self._tzinfo)
+
+    def replace(self, year=None, month=None, day=None, hour=None,
+                minute=None, second=None, microsecond=None, tzinfo=True):
+        """Return a new datetime with new values for the specified fields."""
+        if year is None:
+            year = self.year
+        if month is None:
+            month = self.month
+        if day is None:
+            day = self.day
+        if hour is None:
+            hour = self.hour
+        if minute is None:
+            minute = self.minute
+        if second is None:
+            second = self.second
+        if microsecond is None:
+            microsecond = self.microsecond
+        if tzinfo is True:
+            tzinfo = self.tzinfo
+        _check_date_fields(year, month, day)
+        _check_time_fields(hour, minute, second, microsecond)
+        _check_tzinfo_arg(tzinfo)
+        return datetime(year, month, day, hour, minute, second,
+                          microsecond, tzinfo)
+
+    def astimezone(self, tz):
+        if not isinstance(tz, tzinfo):
+            raise TypeError("tz argument must be an instance of tzinfo")
+
+        mytz = self.tzinfo
+        if mytz is None:
+            raise ValueError("astimezone() requires an aware datetime")
+
+        if tz is mytz:
+            return self
+
+        # Convert self to UTC, and attach the new time zone object.
+        myoffset = self.utcoffset()
+        if myoffset is None:
+            raise ValueError("astimezone() requires an aware datetime")
+        utc = (self - myoffset).replace(tzinfo=tz)
+
+        # Convert from UTC to tz's local time.
+        return tz.fromutc(utc)
+
+    # Ways to produce a string.
+
+    def ctime(self):
+        "Format a la ctime()."
+        t = tmxxx(self.__year, self.__month, self.__day, self.__hour,
+                  self.__minute, self.__second)
+        return t.ctime()
+
+    def isoformat(self, sep='T'):
+        """Return the time formatted according to ISO.
+
+        This is 'YYYY-MM-DD HH:MM:SS.mmmmmm', or 'YYYY-MM-DD HH:MM:SS' if
+        self.microsecond == 0.
+
+        If self.tzinfo is not None, the UTC offset is also attached, giving
+        'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM' or 'YYYY-MM-DD HH:MM:SS+HH:MM'.
+
+        Optional argument sep specifies the separator between date and
+        time, default 'T'.
+        """
+        s = ("%04d-%02d-%02d%c" % (self.__year, self.__month, self.__day,
+                                  sep) +
+                _format_time(self.__hour, self.__minute, self.__second,
+                             self.__microsecond))
+        off = self._utcoffset()
+        if off is not None:
+            if off < 0:
+                sign = "-"
+                off = -off
+            else:
+                sign = "+"
+            hh, mm = divmod(off, 60)
+            s += "%s%02d:%02d" % (sign, hh, mm)
+        return s
+
+    def __repr__(self):
+        "Convert to formal string, for repr()."
+        L = [self.__year, self.__month, self.__day, # These are never zero
+             self.__hour, self.__minute, self.__second, self.__microsecond]
+        if L[-1] == 0:
+            del L[-1]
+        if L[-1] == 0:
+            del L[-1]
+        s = ", ".join(map(str, L))
+        s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
+        if self._tzinfo is not None:
+            assert s[-1:] == ")"
+            s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
+        return s
+
+    def __str__(self):
+        "Convert to string, for str()."
+        return self.isoformat(sep=' ')
+
+    def utcoffset(self):
+        """Return the timezone offset in minutes east of UTC (negative west of
+        UTC)."""
+        offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self)
+        offset = _check_utc_offset("utcoffset", offset)
+        if offset is not None:
+            offset = timedelta(minutes=offset)
+        return offset
+
+    # Return an integer (or None) instead of a timedelta (or None).
+    def _utcoffset(self):
+        offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self)
+        offset = _check_utc_offset("utcoffset", offset)
+        return offset
+
+    def tzname(self):
+        """Return the timezone name.
+
+        Note that the name is 100% informational -- there's no requirement that
+        it mean anything in particular. For example, "GMT", "UTC", "-500",
+        "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
+        """
+        name = _call_tzinfo_method(self._tzinfo, "tzname", self)
+        _check_tzname(name)
+        return name
+
+    def dst(self):
+        """Return 0 if DST is not in effect, or the DST offset (in minutes
+        eastward) if DST is in effect.
+
+        This is purely informational; the DST offset has already been added to
+        the UTC offset returned by utcoffset() if applicable, so there's no
+        need to consult dst() unless you're interested in displaying the DST
+        info.
+        """
+        offset = _call_tzinfo_method(self._tzinfo, "dst", self)
+        offset = _check_utc_offset("dst", offset)
+        if offset is not None:
+            offset = timedelta(minutes=offset)
+        return offset
+
+    # Return an integer (or None) instead of a timedelta (or None).1573
+    def _dst(self):
+        offset = _call_tzinfo_method(self._tzinfo, "dst", self)
+        offset = _check_utc_offset("dst", offset)
+        return offset
+
+    # Comparisons.
+
+    def __eq__(self, other):
+        if isinstance(other, datetime):
+            return self.__cmp(other) == 0
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
+            return NotImplemented
+        else:
+            return False
+
+    def __ne__(self, other):
+        if isinstance(other, datetime):
+            return self.__cmp(other) != 0
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
+            return NotImplemented
+        else:
+            return True
+
+    def __le__(self, other):
+        if isinstance(other, datetime):
+            return self.__cmp(other) <= 0
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __lt__(self, other):
+        if isinstance(other, datetime):
+            return self.__cmp(other) < 0
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __ge__(self, other):
+        if isinstance(other, datetime):
+            return self.__cmp(other) >= 0
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __gt__(self, other):
+        if isinstance(other, datetime):
+            return self.__cmp(other) > 0
+        elif hasattr(other, "timetuple") and not isinstance(other, date):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __cmp(self, other):
+        assert isinstance(other, datetime)
+        mytz = self._tzinfo
+        ottz = other._tzinfo
+        myoff = otoff = None
+
+        if mytz is ottz:
+            base_compare = True
+        else:
+            if mytz is not None:
+                myoff = self._utcoffset()
+            if ottz is not None:
+                otoff = other._utcoffset()
+            base_compare = myoff == otoff
+
+        if base_compare:
+            return cmp((self.__year, self.__month, self.__day,
+                        self.__hour, self.__minute, self.__second,
+                        self.__microsecond),
+                       (other.__year, other.__month, other.__day,
+                        other.__hour, other.__minute, other.__second,
+                        other.__microsecond))
+        if myoff is None or otoff is None:
+            # XXX Buggy in 2.2.2.
+            raise TypeError("cannot compare naive and aware datetimes")
+        # XXX What follows could be done more efficiently...
+        diff = self - other     # this will take offsets into account
+        if diff.days < 0:
+            return -1
+        return diff and 1 or 0
+
+    def __add__(self, other):
+        "Add a datetime and a timedelta."
+        if not isinstance(other, timedelta):
+            return NotImplemented
+        t = tmxxx(self.__year,
+                  self.__month,
+                  self.__day + other.days,
+                  self.__hour,
+                  self.__minute,
+                  self.__second + other.seconds,
+                  self.__microsecond + other.microseconds)
+        self._checkOverflow(t.year)
+        result = datetime(t.year, t.month, t.day,
+                                t.hour, t.minute, t.second,
+                                t.microsecond, tzinfo=self._tzinfo)
+        return result
+
+    __radd__ = __add__
+
+    def __sub__(self, other):
+        "Subtract two datetimes, or a datetime and a timedelta."
+        if not isinstance(other, datetime):
+            if isinstance(other, timedelta):
+                return self + -other
+            return NotImplemented
+
+        days1 = self.toordinal()
+        days2 = other.toordinal()
+        secs1 = self.__second + self.__minute * 60 + self.__hour * 3600
+        secs2 = other.__second + other.__minute * 60 + other.__hour * 3600
+        base = timedelta(days1 - days2,
+                         secs1 - secs2,
+                         self.__microsecond - other.__microsecond)
+        if self._tzinfo is other._tzinfo:
+            return base
+        myoff = self._utcoffset()
+        otoff = other._utcoffset()
+        if myoff == otoff:
+            return base
+        if myoff is None or otoff is None:
+            raise TypeError, "cannot mix naive and timezone-aware time"
+        return base + timedelta(minutes = otoff-myoff)
+
+    def __hash__(self):
+        tzoff = self._utcoffset()
+        if tzoff is None:
+            return hash(self.__getstate()[0])
+        days = _ymd2ord(self.year, self.month, self.day)
+        seconds = self.hour * 3600 + (self.minute - tzoff) * 60 + self.second
+        return hash(timedelta(days, seconds, self.microsecond))
+
+    # Pickle support.
+
+    __safe_for_unpickling__ = True      # For Python 2.2
+
+    def __getstate(self):
+        yhi, ylo = divmod(self.__year, 256)
+        us2, us3 = divmod(self.__microsecond, 256)
+        us1, us2 = divmod(us2, 256)
+        basestate = ("%c" * 10) % (yhi, ylo, self.__month, self.__day,
+                                   self.__hour, self.__minute, self.__second,
+                                   us1, us2, us3)
+        if self._tzinfo is None:
+            return (basestate,)
+        else:
+            return (basestate, self._tzinfo)
+
+    def __setstate(self, string, tzinfo):
+        (yhi, ylo, self.__month, self.__day, self.__hour,
+         self.__minute, self.__second, us1, us2, us3) = map(ord, string)
+        self.__year = yhi * 256 + ylo
+        self.__microsecond = (((us1 << 8) | us2) << 8) | us3
+        self._tzinfo = tzinfo
+
+    def __reduce__(self):
+        return (self.__class__, self.__getstate())
+
+    if _sys.platform.startswith('java'):
+        def __tojava__(self, java_class):
+            # TODO, if self.tzinfo is not None, convert time to UTC
+            if java_class not in (Calendar, Timestamp, Object):
+                return Py.NoConversion
+
+            calendar = Calendar.getInstance()
+            calendar.clear()
+            calendar.set(self.year, self.month - 1, self.day,
+                         self.hour, self.minute, self.second)
+
+            if java_class == Calendar:
+                calendar.set(Calendar.MILLISECOND, self.microsecond // 1000)
+                return calendar
+            else:
+                timestamp = Timestamp(calendar.getTimeInMillis())
+                timestamp.setNanos(self.microsecond * 1000)
+                return timestamp
+
+
+datetime.min = datetime(1, 1, 1)
+datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
+datetime.resolution = timedelta(microseconds=1)
+
+
+def _isoweek1monday(year):
+    # Helper to calculate the day number of the Monday starting week 1
+    # XXX This could be done more efficiently
+    THURSDAY = 3
+    firstday = _ymd2ord(year, 1, 1)
+    firstweekday = (firstday + 6) % 7 # See weekday() above
+    week1monday = firstday - firstweekday
+    if firstweekday > THURSDAY:
+        week1monday += 7
+    return week1monday
+
+"""
+Some time zone algebra.  For a datetime x, let
+    x.n = x stripped of its timezone -- its naive time.
+    x.o = x.utcoffset(), and assuming that doesn't raise an exception or
+          return None
+    x.d = x.dst(), and assuming that doesn't raise an exception or
+          return None
+    x.s = x's standard offset, x.o - x.d
+
+Now some derived rules, where k is a duration (timedelta).
+
+1. x.o = x.s + x.d
+   This follows from the definition of x.s.
+
+2. If x and y have the same tzinfo member, x.s = y.s.
+   This is actually a requirement, an assumption we need to make about
+   sane tzinfo classes.
+
+3. The naive UTC time corresponding to x is x.n - x.o.
+   This is again a requirement for a sane tzinfo class.
+
+4. (x+k).s = x.s
+   This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
+
+5. (x+k).n = x.n + k
+   Again follows from how arithmetic is defined.
+
+Now we can explain tz.fromutc(x).  Let's assume it's an interesting case
+(meaning that the various tzinfo methods exist, and don't blow up or return
+None when called).
+
+The function wants to return a datetime y with timezone tz, equivalent to x.
+x is already in UTC.
+
+By #3, we want
+
+    y.n - y.o = x.n                             [1]
+
+The algorithm starts by attaching tz to x.n, and calling that y.  So
+x.n = y.n at the start.  Then it wants to add a duration k to y, so that [1]
+becomes true; in effect, we want to solve [2] for k:
+
+   (y+k).n - (y+k).o = x.n                      [2]
+
+By #1, this is the same as
+
+   (y+k).n - ((y+k).s + (y+k).d) = x.n          [3]
+
+By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
+Substituting that into [3],
+
+   x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
+   k - (y+k).s - (y+k).d = 0; rearranging,
+   k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
+   k = y.s - (y+k).d
+
+On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
+approximate k by ignoring the (y+k).d term at first.  Note that k can't be
+very large, since all offset-returning methods return a duration of magnitude
+less than 24 hours.  For that reason, if y is firmly in std time, (y+k).d must
+be 0, so ignoring it has no consequence then.
+
+In any case, the new value is
+
+    z = y + y.s                                 [4]
+
+It's helpful to step back at look at [4] from a higher level:  it's simply
+mapping from UTC to tz's standard time.
+
+At this point, if
+
+    z.n - z.o = x.n                             [5]
+
+we have an equivalent time, and are almost done.  The insecurity here is
+at the start of daylight time.  Picture US Eastern for concreteness.  The wall
+time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
+sense then.  The docs ask that an Eastern tzinfo class consider such a time to
+be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
+on the day DST starts.  We want to return the 1:MM EST spelling because that's
+the only spelling that makes sense on the local wall clock.
+
+In fact, if [5] holds at this point, we do have the standard-time spelling,
+but that takes a bit of proof.  We first prove a stronger result.  What's the
+difference between the LHS and RHS of [5]?  Let
+
+    diff = x.n - (z.n - z.o)                    [6]
+
+Now
+    z.n =                       by [4]
+    (y + y.s).n =               by #5
+    y.n + y.s =                 since y.n = x.n
+    x.n + y.s =                 since z and y are have the same tzinfo member,
+                                    y.s = z.s by #2
+    x.n + z.s
+
+Plugging that back into [6] gives
+
+    diff =
+    x.n - ((x.n + z.s) - z.o) =     expanding
+    x.n - x.n - z.s + z.o =         cancelling
+    - z.s + z.o =                   by #2
+    z.d
+
+So diff = z.d.
+
+If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
+spelling we wanted in the endcase described above.  We're done.  Contrarily,
+if z.d = 0, then we have a UTC equivalent, and are also done.
+
+If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
+add to z (in effect, z is in tz's standard time, and we need to shift the
+local clock into tz's daylight time).
+
+Let
+
+    z' = z + z.d = z + diff                     [7]
+
+and we can again ask whether
+
+    z'.n - z'.o = x.n                           [8]
+
+If so, we're done.  If not, the tzinfo class is insane, according to the
+assumptions we've made.  This also requires a bit of proof.  As before, let's
+compute the difference between the LHS and RHS of [8] (and skipping some of
+the justifications for the kinds of substitutions we've done several times
+already):
+
+    diff' = x.n - (z'.n - z'.o) =           replacing z'.n via [7]
+            x.n  - (z.n + diff - z'.o) =    replacing diff via [6]
+            x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
+            x.n - z.n - x.n + z.n - z.o + z'.o =    cancel x.n
+            - z.n + z.n - z.o + z'.o =              cancel z.n
+            - z.o + z'.o =                      #1 twice
+            -z.s - z.d + z'.s + z'.d =          z and z' have same tzinfo
+            z'.d - z.d
+
+So z' is UTC-equivalent to x iff z'.d = z.d at this point.  If they are equal,
+we've found the UTC-equivalent so are done.  In fact, we stop with [7] and
+return z', not bothering to compute z'.d.
+
+How could z.d and z'd differ?  z' = z + z.d [7], so merely moving z' by
+a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
+would have to change the result dst() returns:  we start in DST, and moving
+a little further into it takes us out of DST.
+
+There isn't a sane case where this can happen.  The closest it gets is at
+the end of DST, where there's an hour in UTC with no spelling in a hybrid
+tzinfo class.  In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT.  During
+that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
+UTC) because the docs insist on that, but 0:MM is taken as being in daylight
+time (4:MM UTC).  There is no local time mapping to 5:MM UTC.  The local
+clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
+standard time.  Since that's what the local clock *does*, we want to map both
+UTC hours 5:MM and 6:MM to 1:MM Eastern.  The result is ambiguous
+in local time, but so it goes -- it's the way the local clock works.
+
+When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
+so z=0:MM.  z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
+z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
+(correctly) concludes that z' is not UTC-equivalent to x.
+
+Because we know z.d said z was in daylight time (else [5] would have held and
+we would have stopped then), and we know z.d != z'.d (else [8] would have held
+and we we have stopped then), and there are only 2 possible values dst() can
+return in Eastern, it follows that z'.d must be 0 (which it is in the example,
+but the reasoning doesn't depend on the example -- it depends on there being
+two possible dst() outcomes, one zero and the other non-zero).  Therefore
+z' must be in standard time, and is the spelling we want in this case.
+
+Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
+concerned (because it takes z' as being in standard time rather than the
+daylight time we intend here), but returning it gives the real-life "local
+clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
+tz.
+
+When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
+the 1:MM standard time spelling we want.
+
+So how can this break?  One of the assumptions must be violated.  Two
+possibilities:
+
+1) [2] effectively says that y.s is invariant across all y belong to a given
+   time zone.  This isn't true if, for political reasons or continental drift,
+   a region decides to change its base offset from UTC.
+
+2) There may be versions of "double daylight" time where the tail end of
+   the analysis gives up a step too early.  I haven't thought about that
+   enough to say.
+
+In any case, it's clear that the default fromutc() is strong enough to handle
+"almost all" time zones:  so long as the standard offset is invariant, it
+doesn't matter if daylight time transition points change from year to year, or
+if daylight time is skipped in some years; it doesn't matter how large or
+small dst() may get within its bounds; and it doesn't even matter if some
+perverse time zone returns a negative dst()).  So a breaking case must be
+pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
+"""
diff --git a/src/main/resources/PythonLibs/dbexts.py b/src/main/resources/PythonLibs/dbexts.py
new file mode 100644
index 0000000000000000000000000000000000000000..041331d82058857d403b486aeaaaff64db877842
--- /dev/null
+++ b/src/main/resources/PythonLibs/dbexts.py
@@ -0,0 +1,722 @@
+"""
+This script provides platform independence by wrapping Python
+Database API 2.0 compatible drivers to allow seamless database
+usage across implementations.
+
+In order to use the C version, you need mxODBC and mxDateTime.
+In order to use the Java version, you need zxJDBC.
+
+>>> import dbexts
+>>> d = dbexts.dbexts() # use the default db
+>>> d.isql('select count(*) count from player')
+
+count
+-------
+13569.0
+
+1 row affected
+
+>>> r = d.raw('select count(*) count from player')
+>>> r
+([('count', 3, 17, None, 15, 0, 1)], [(13569.0,)])
+>>>
+
+The configuration file follows the following format in a file name dbexts.ini:
+
+[default]
+name=mysql
+
+[jdbc]
+name=mysql
+url=jdbc:mysql://localhost/ziclix
+user=
+pwd=
+driver=org.gjt.mm.mysql.Driver
+datahandler=com.ziclix.python.sql.handler.MySQLDataHandler
+
+[jdbc]
+name=pg
+url=jdbc:postgresql://localhost:5432/ziclix
+user=bzimmer
+pwd=
+driver=org.postgresql.Driver
+datahandler=com.ziclix.python.sql.handler.PostgresqlDataHandler
+"""
+
+import os, re
+from types import StringType
+
+__author__ = "brian zimmer (bzimmer@ziclix.com)"
+__OS__ = os.name
+
+choose = lambda bool, a, b: (bool and [a] or [b])[0]
+
+def console(rows, headers=()):
+    """Format the results into a list       of strings (one for each row):
+
+    <header>
+    <headersep>
+    <row1>
+    <row2>
+    ...
+
+    headers may be given as list of strings.
+
+    Columns are separated by colsep; the header is separated from
+    the result set by a line of headersep characters.
+
+    The function calls stringify to format the value data into a string.
+    It defaults to calling str() and striping leading and trailing whitespace.
+
+    - copied and modified from mxODBC
+    """
+
+    # Check row entry lengths
+    output = []
+    headers = map(lambda header: header.upper(), list(map(lambda x: x or "", headers)))
+    collen = map(len,headers)
+    output.append(headers)
+    if rows and len(rows) > 0:
+        for row in rows:
+            row = map(lambda x: str(x), row)
+            for i in range(len(row)):
+                entry = row[i]
+                if collen[i] < len(entry):
+                    collen[i] = len(entry)
+            output.append(row)
+    if len(output) == 1:
+        affected = "0 rows affected"
+    elif len(output) == 2:
+        affected = "1 row affected"
+    else:
+        affected = "%d rows affected" % (len(output) - 1)
+
+    # Format output
+    for i in range(len(output)):
+        row = output[i]
+        l = []
+        for j in range(len(row)):
+            l.append('%-*s' % (collen[j],row[j]))
+        output[i] = " | ".join(l)
+
+    # Insert header separator
+    totallen = len(output[0])
+    output[1:1] = ["-"*(totallen/len("-"))]
+    output.append("\n" + affected)
+    return output
+
+def html(rows, headers=()):
+    output = []
+    output.append('<table class="results">')
+    output.append('<tr class="headers">')
+    headers = map(lambda x: '<td class="header">%s</td>' % (x.upper()), list(headers))
+    map(output.append, headers)
+    output.append('</tr>')
+    if rows and len(rows) > 0:
+        for row in rows:
+            output.append('<tr class="row">')
+            row = map(lambda x: '<td class="value">%s</td>' % (x), row)
+            map(output.append, row)
+            output.append('</tr>')
+    output.append('</table>')
+    return output
+
+comments = lambda x: re.compile("{.*?}", re.S).sub("", x, 0)
+
+class mxODBCProxy:
+    """Wraps mxODBC to provide proxy support for zxJDBC's additional parameters."""
+    def __init__(self, c):
+        self.c = c
+    def __getattr__(self, name):
+        if name == "execute":
+            return self.execute
+        elif name == "gettypeinfo":
+            return self.gettypeinfo
+        else:
+            return getattr(self.c, name)
+    def execute(self, sql, params=None, bindings=None, maxrows=None):
+        if params:
+            self.c.execute(sql, params)
+        else:
+            self.c.execute(sql)
+    def gettypeinfo(self, typeid=None):
+        if typeid:
+            self.c.gettypeinfo(typeid)
+
+class executor:
+    """Handles the insertion of values given dynamic data."""
+    def __init__(self, table, cols):
+        self.cols = cols
+        self.table = table
+        if self.cols:
+            self.sql = "insert into %s (%s) values (%s)" % (table, ",".join(self.cols), ",".join(("?",) * len(self.cols)))
+        else:
+            self.sql = "insert into %s values (%%s)" % (table)
+    def execute(self, db, rows, bindings):
+        assert rows and len(rows) > 0, "must have at least one row"
+        if self.cols:
+            sql = self.sql
+        else:
+            sql = self.sql % (",".join(("?",) * len(rows[0])))
+        db.raw(sql, rows, bindings)
+
+def connect(dbname):
+    return dbexts(dbname)
+
+def lookup(dbname):
+    return dbexts(jndiname=dbname)
+
+class dbexts:
+    def __init__(self, dbname=None, cfg=None, formatter=console, autocommit=0, jndiname=None, out=None):
+        self.verbose = 1
+        self.results = []
+        self.headers = []
+        self.autocommit = autocommit
+        self.formatter = formatter
+        self.out = out
+        self.lastrowid = None
+        self.updatecount = None
+
+        if not jndiname:
+            if cfg == None:
+                fn = os.path.join(os.path.split(__file__)[0], "dbexts.ini")
+                if not os.path.exists(fn):
+                    fn = os.path.join(os.environ['HOME'], ".dbexts")
+                self.dbs = IniParser(fn)
+            elif isinstance(cfg, IniParser):
+                self.dbs = cfg
+            else:
+                self.dbs = IniParser(cfg)
+            if dbname == None: dbname = self.dbs[("default", "name")]
+
+        if __OS__ == 'java':
+
+            from com.ziclix.python.sql import zxJDBC
+            database = zxJDBC
+            if not jndiname:
+                t = self.dbs[("jdbc", dbname)]
+                self.dburl, dbuser, dbpwd, jdbcdriver = t['url'], t['user'], t['pwd'], t['driver']
+                if t.has_key('datahandler'):
+                    self.datahandler = []
+                    for dh in t['datahandler'].split(','):
+                        classname = dh.split(".")[-1]
+                        datahandlerclass = __import__(dh, globals(), locals(), classname)
+                        self.datahandler.append(datahandlerclass)
+                keys = [x for x in t.keys() if x not in ['url', 'user', 'pwd', 'driver', 'datahandler', 'name']]
+                props = {}
+                for a in keys:
+                    props[a] = t[a]
+                self.db = apply(database.connect, (self.dburl, dbuser, dbpwd, jdbcdriver), props)
+            else:
+                self.db = database.lookup(jndiname)
+            self.db.autocommit = self.autocommit
+
+        elif __OS__ == 'nt':
+
+            for modname in ["mx.ODBC.Windows", "ODBC.Windows"]:
+                try:
+                    database = __import__(modname, globals(), locals(), "Windows")
+                    break
+                except:
+                    continue
+            else:
+                raise ImportError("unable to find appropriate mxODBC module")
+
+            t = self.dbs[("odbc", dbname)]
+            self.dburl, dbuser, dbpwd = t['url'], t['user'], t['pwd']
+            self.db = database.Connect(self.dburl, dbuser, dbpwd, clear_auto_commit=1)
+
+        self.dbname = dbname
+        for a in database.sqltype.keys():
+            setattr(self, database.sqltype[a], a)
+        for a in dir(database):
+            try:
+                p = getattr(database, a)
+                if issubclass(p, Exception):
+                    setattr(self, a, p)
+            except:
+                continue
+        del database
+
+    def __str__(self):
+        return self.dburl
+
+    def __repr__(self):
+        return self.dburl
+
+    def __getattr__(self, name):
+        if "cfg" == name:
+            return self.dbs.cfg
+        raise AttributeError("'dbexts' object has no attribute '%s'" % (name))
+
+    def close(self):
+        """ close the connection to the database """
+        self.db.close()
+
+    def begin(self, style=None):
+        """ reset ivars and return a new cursor, possibly binding an auxiliary datahandler """
+        self.headers, self.results = [], []
+        if style:
+            c = self.db.cursor(style)
+        else:
+            c = self.db.cursor()
+        if __OS__ == 'java':
+            if hasattr(self, 'datahandler'):
+                for dh in self.datahandler:
+                    c.datahandler = dh(c.datahandler)
+        else:
+            c = mxODBCProxy(c)
+        return c
+
+    def commit(self, cursor=None, close=1):
+        """ commit the cursor and create the result set """
+        if cursor and cursor.description:
+            self.headers = cursor.description
+            self.results = cursor.fetchall()
+            if hasattr(cursor, "nextset"):
+                s = cursor.nextset()
+                while s:
+                    self.results += cursor.fetchall()
+                    s = cursor.nextset()
+        if hasattr(cursor, "lastrowid"):
+            self.lastrowid = cursor.lastrowid
+        if hasattr(cursor, "updatecount"):
+            self.updatecount = cursor.updatecount
+        if not self.autocommit or cursor is None:
+            if not self.db.autocommit:
+                self.db.commit()
+        if cursor and close: cursor.close()
+
+    def rollback(self):
+        """ rollback the cursor """
+        self.db.rollback()
+
+    def prepare(self, sql):
+        """ prepare the sql statement """
+        cur = self.begin()
+        try:
+            return cur.prepare(sql)
+        finally:
+            self.commit(cur)
+
+    def display(self):
+        """ using the formatter, display the results """
+        if self.formatter and self.verbose > 0:
+            res = self.results
+            if res:
+                print >> self.out, ""
+                for a in self.formatter(res, map(lambda x: x[0], self.headers)):
+                    print >> self.out, a
+                print >> self.out, ""
+
+    def __execute__(self, sql, params=None, bindings=None, maxrows=None):
+        """ the primary execution method """
+        cur = self.begin()
+        try:
+            if bindings:
+                cur.execute(sql, params, bindings, maxrows=maxrows)
+            elif params:
+                cur.execute(sql, params, maxrows=maxrows)
+            else:
+                cur.execute(sql, maxrows=maxrows)
+        finally:
+            self.commit(cur, close=isinstance(sql, StringType))
+
+    def isql(self, sql, params=None, bindings=None, maxrows=None):
+        """ execute and display the sql """
+        self.raw(sql, params, bindings, maxrows=maxrows)
+        self.display()
+
+    def raw(self, sql, params=None, bindings=None, delim=None, comments=comments, maxrows=None):
+        """ execute the sql and return a tuple of (headers, results) """
+        if delim:
+            headers = []
+            results = []
+            if type(sql) == type(StringType):
+                if comments: sql = comments(sql)
+                statements = filter(lambda x: len(x) > 0,
+                        map(lambda statement: statement.strip(), sql.split(delim)))
+            else:
+                statements = [sql]
+            for a in statements:
+                self.__execute__(a, params, bindings, maxrows=maxrows)
+                headers.append(self.headers)
+                results.append(self.results)
+            self.headers = headers
+            self.results = results
+        else:
+            self.__execute__(sql, params, bindings, maxrows=maxrows)
+        return (self.headers, self.results)
+
+    def callproc(self, procname, params=None, bindings=None, maxrows=None):
+        """ execute a stored procedure """
+        cur = self.begin()
+        try:
+            cur.callproc(procname, params=params, bindings=bindings, maxrows=maxrows)
+        finally:
+            self.commit(cur)
+        self.display()
+
+    def pk(self, table, owner=None, schema=None):
+        """ display the table's primary keys """
+        cur = self.begin()
+        cur.primarykeys(schema, owner, table)
+        self.commit(cur)
+        self.display()
+
+    def fk(self, primary_table=None, foreign_table=None, owner=None, schema=None):
+        """ display the table's foreign keys """
+        cur = self.begin()
+        if primary_table and foreign_table:
+            cur.foreignkeys(schema, owner, primary_table, schema, owner, foreign_table)
+        elif primary_table:
+            cur.foreignkeys(schema, owner, primary_table, schema, owner, None)
+        elif foreign_table:
+            cur.foreignkeys(schema, owner, None, schema, owner, foreign_table)
+        self.commit(cur)
+        self.display()
+
+    def table(self, table=None, types=("TABLE",), owner=None, schema=None):
+        """If no table argument, displays a list of all tables.  If a table argument,
+        displays the columns of the given table."""
+        cur = self.begin()
+        if table:
+            cur.columns(schema, owner, table, None)
+        else:
+            cur.tables(schema, owner, None, types)
+        self.commit(cur)
+        self.display()
+
+    def proc(self, proc=None, owner=None, schema=None):
+        """If no proc argument, displays a list of all procedures.  If a proc argument,
+        displays the parameters of the given procedure."""
+        cur = self.begin()
+        if proc:
+            cur.procedurecolumns(schema, owner, proc, None)
+        else:
+            cur.procedures(schema, owner, None)
+        self.commit(cur)
+        self.display()
+
+    def stat(self, table, qualifier=None, owner=None, unique=0, accuracy=0):
+        """ display the table's indicies """
+        cur = self.begin()
+        cur.statistics(qualifier, owner, table, unique, accuracy)
+        self.commit(cur)
+        self.display()
+
+    def typeinfo(self, sqltype=None):
+        """ display the types available for the database """
+        cur = self.begin()
+        cur.gettypeinfo(sqltype)
+        self.commit(cur)
+        self.display()
+
+    def tabletypeinfo(self):
+        """ display the table types available for the database """
+        cur = self.begin()
+        cur.gettabletypeinfo()
+        self.commit(cur)
+        self.display()
+
+    def schema(self, table, full=0, sort=1, owner=None):
+        """Displays a Schema object for the table.  If full is true, then generates
+        references to the table in addition to the standard fields.  If sort is true,
+        sort all the items in the schema, else leave them in db dependent order."""
+        print >> self.out, str(Schema(self, table, owner, full, sort))
+
+    def bulkcopy(self, dst, table, include=[], exclude=[], autobatch=0, executor=executor):
+        """Returns a Bulkcopy object using the given table."""
+        if type(dst) == type(""):
+            dst = dbexts(dst, cfg=self.dbs)
+        bcp = Bulkcopy(dst, table, include=include, exclude=exclude, autobatch=autobatch, executor=executor)
+        return bcp
+
+    def bcp(self, src, table, where='(1=1)', params=[], include=[], exclude=[], autobatch=0, executor=executor):
+        """Bulkcopy of rows from a src database to the current database for a given table and where clause."""
+        if type(src) == type(""):
+            src = dbexts(src, cfg=self.dbs)
+        bcp = self.bulkcopy(self, table, include, exclude, autobatch, executor)
+        num = bcp.transfer(src, where, params)
+        return num
+
+    def unload(self, filename, sql, delimiter=",", includeheaders=1):
+        """ Unloads the delimited results of the query to the file specified, optionally including headers. """
+        u = Unload(self, filename, delimiter, includeheaders)
+        u.unload(sql)
+
+class Bulkcopy:
+    """The idea for a bcp class came from http://object-craft.com.au/projects/sybase"""
+    def __init__(self, dst, table, include=[], exclude=[], autobatch=0, executor=executor):
+        self.dst = dst
+        self.table = table
+        self.total = 0
+        self.rows = []
+        self.autobatch = autobatch
+        self.bindings = {}
+
+        include = map(lambda x: x.lower(), include)
+        exclude = map(lambda x: x.lower(), exclude)
+
+        _verbose = self.dst.verbose
+        self.dst.verbose = 0
+        try:
+            self.dst.table(self.table)
+            if self.dst.results:
+                colmap = {}
+                for a in self.dst.results:
+                    colmap[a[3].lower()] = a[4]
+                cols = self.__filter__(colmap.keys(), include, exclude)
+                for a in zip(range(len(cols)), cols):
+                    self.bindings[a[0]] = colmap[a[1]]
+                colmap = None
+            else:
+                cols = self.__filter__(include, include, exclude)
+        finally:
+            self.dst.verbose = _verbose
+
+        self.executor = executor(table, cols)
+
+    def __str__(self):
+        return "[%s].[%s]" % (self.dst, self.table)
+
+    def __repr__(self):
+        return "[%s].[%s]" % (self.dst, self.table)
+
+    def __getattr__(self, name):
+        if name == 'columns':
+            return self.executor.cols
+
+    def __filter__(self, values, include, exclude):
+        cols = map(lambda col: col.lower(), values)
+        if exclude:
+            cols = filter(lambda x, ex=exclude: x not in ex, cols)
+        if include:
+            cols = filter(lambda x, inc=include: x in inc, cols)
+        return cols
+
+    def format(self, column, type):
+        self.bindings[column] = type
+
+    def done(self):
+        if len(self.rows) > 0:
+            return self.batch()
+        return 0
+
+    def batch(self):
+        self.executor.execute(self.dst, self.rows, self.bindings)
+        cnt = len(self.rows)
+        self.total += cnt
+        self.rows = []
+        return cnt
+
+    def rowxfer(self, line):
+        self.rows.append(line)
+        if self.autobatch: self.batch()
+
+    def transfer(self, src, where="(1=1)", params=[]):
+        sql = "select %s from %s where %s" % (", ".join(self.columns), self.table, where)
+        h, d = src.raw(sql, params)
+        if d:
+            map(self.rowxfer, d)
+            return self.done()
+        return 0
+
+class Unload:
+    """Unloads a sql statement to a file with optional formatting of each value."""
+    def __init__(self, db, filename, delimiter=",", includeheaders=1):
+        self.db = db
+        self.filename = filename
+        self.delimiter = delimiter
+        self.includeheaders = includeheaders
+        self.formatters = {}
+
+    def format(self, o):
+        if not o:
+            return ""
+        o = str(o)
+        if o.find(",") != -1:
+            o = "\"\"%s\"\"" % (o)
+        return o
+
+    def unload(self, sql, mode="w"):
+        headers, results = self.db.raw(sql)
+        w = open(self.filename, mode)
+        if self.includeheaders:
+            w.write("%s\n" % (self.delimiter.join(map(lambda x: x[0], headers))))
+        if results:
+            for a in results:
+                w.write("%s\n" % (self.delimiter.join(map(self.format, a))))
+        w.flush()
+        w.close()
+
+class Schema:
+    """Produces a Schema object which represents the database schema for a table"""
+    def __init__(self, db, table, owner=None, full=0, sort=1):
+        self.db = db
+        self.table = table
+        self.owner = owner
+        self.full = full
+        self.sort = sort
+        _verbose = self.db.verbose
+        self.db.verbose = 0
+        try:
+            if table: self.computeschema()
+        finally:
+            self.db.verbose = _verbose
+
+    def computeschema(self):
+        self.db.table(self.table, owner=self.owner)
+        self.columns = []
+        # (column name, type_name, size, nullable)
+        if self.db.results:
+            self.columns = map(lambda x: (x[3], x[5], x[6], x[10]), self.db.results)
+            if self.sort: self.columns.sort(lambda x, y: cmp(x[0], y[0]))
+
+        self.db.fk(None, self.table)
+        # (pk table name, pk column name, fk column name, fk name, pk name)
+        self.imported = []
+        if self.db.results:
+            self.imported = map(lambda x: (x[2], x[3], x[7], x[11], x[12]), self.db.results)
+            if self.sort: self.imported.sort(lambda x, y: cmp(x[2], y[2]))
+
+        self.exported = []
+        if self.full:
+            self.db.fk(self.table, None)
+            # (pk column name, fk table name, fk column name, fk name, pk name)
+            if self.db.results:
+                self.exported = map(lambda x: (x[3], x[6], x[7], x[11], x[12]), self.db.results)
+                if self.sort: self.exported.sort(lambda x, y: cmp(x[1], y[1]))
+
+        self.db.pk(self.table)
+        self.primarykeys = []
+        if self.db.results:
+            # (column name, key_seq, pk name)
+            self.primarykeys = map(lambda x: (x[3], x[4], x[5]), self.db.results)
+            if self.sort: self.primarykeys.sort(lambda x, y: cmp(x[1], y[1]))
+
+        try:
+            self.indices = None
+            self.db.stat(self.table)
+            self.indices = []
+            # (non-unique, name, type, pos, column name, asc)
+            if self.db.results:
+                idxdict = {}
+                # mxODBC returns a row of None's, so filter it out
+                idx = map(lambda x: (x[3], x[5].strip(), x[6], x[7], x[8]), filter(lambda x: x[5], self.db.results))
+                def cckmp(x, y):
+                    c = cmp(x[1], y[1])
+                    if c == 0: c = cmp(x[3], y[3])
+                    return c
+                # sort this regardless, this gets the indicies lined up
+                idx.sort(cckmp)
+                for a in idx:
+                    if not idxdict.has_key(a[1]):
+                        idxdict[a[1]] = []
+                    idxdict[a[1]].append(a)
+                self.indices = idxdict.values()
+                if self.sort: self.indices.sort(lambda x, y: cmp(x[0][1], y[0][1]))
+        except:
+            pass
+
+    def __str__(self):
+        d = []
+        d.append("Table")
+        d.append("  " + self.table)
+        d.append("\nPrimary Keys")
+        for a in self.primarykeys:
+            d.append("  %s {%s}" % (a[0], a[2]))
+        d.append("\nImported (Foreign) Keys")
+        for a in self.imported:
+            d.append("  %s (%s.%s) {%s}" % (a[2], a[0], a[1], a[3]))
+        if self.full:
+            d.append("\nExported (Referenced) Keys")
+            for a in self.exported:
+                d.append("  %s (%s.%s) {%s}" % (a[0], a[1], a[2], a[3]))
+        d.append("\nColumns")
+        for a in self.columns:
+            nullable = choose(a[3], "nullable", "non-nullable")
+            d.append("  %-20s %s(%s), %s" % (a[0], a[1], a[2], nullable))
+        d.append("\nIndices")
+        if self.indices is None:
+            d.append(" (failed)")
+        else:
+            for a in self.indices:
+                unique = choose(a[0][0], "non-unique", "unique")
+                cname = ", ".join(map(lambda x: x[4], a))
+                d.append("  %s index {%s} on (%s)" % (unique, a[0][1], cname))
+        return "\n".join(d)
+
+class IniParser:
+    def __init__(self, cfg, key='name'):
+        self.key = key
+        self.records = {}
+        self.ctypeRE = re.compile("\[(jdbc|odbc|default)\]")
+        self.entryRE = re.compile("([a-zA-Z]+)[ \t]*=[ \t]*(.*)")
+        self.cfg = cfg
+        self.parse()
+
+    def parse(self):
+        fp = open(self.cfg, "r")
+        data = fp.readlines()
+        fp.close()
+        lines = filter(lambda x: len(x) > 0 and x[0] not in ['#', ';'], map(lambda x: x.strip(), data))
+        current = None
+        for i in range(len(lines)):
+            line = lines[i]
+            g = self.ctypeRE.match(line)
+            if g:   # a section header
+                current = {}
+                if not self.records.has_key(g.group(1)):
+                    self.records[g.group(1)] = []
+                self.records[g.group(1)].append(current)
+            else:
+                g = self.entryRE.match(line)
+                if g:
+                    current[g.group(1)] = g.group(2)
+
+    def __getitem__(self, (ctype, skey)):
+        if skey == self.key: return self.records[ctype][0][skey]
+        t = filter(lambda x, p=self.key, s=skey: x[p] == s, self.records[ctype])
+        if not t or len(t) > 1:
+            raise KeyError, "invalid key ('%s', '%s')" % (ctype, skey)
+        return t[0]
+
+def random_table_name(prefix, num_chars):
+    import random
+    d = [prefix, '_']
+    i = 0
+    while i < num_chars:
+        d.append(chr(int(100 * random.random()) % 26 + ord('A')))
+        i += 1
+    return "".join(d)
+
+class ResultSetRow:
+    def __init__(self, rs, row):
+        self.row = row
+        self.rs = rs
+    def __getitem__(self, i):
+        if type(i) == type(""):
+            i = self.rs.index(i)
+        return self.row[i]
+    def __getslice__(self, i, j):
+        if type(i) == type(""): i = self.rs.index(i)
+        if type(j) == type(""): j = self.rs.index(j)
+        return self.row[i:j]
+    def __len__(self):
+        return len(self.row)
+    def __repr__(self):
+        return str(self.row)
+
+class ResultSet:
+    def __init__(self, headers, results=[]):
+        self.headers = map(lambda x: x.upper(), headers)
+        self.results = results
+    def index(self, i):
+        return self.headers.index(i.upper())
+    def __getitem__(self, i):
+        return ResultSetRow(self, self.results[i])
+    def __getslice__(self, i, j):
+        return map(lambda x, rs=self: ResultSetRow(rs, x), self.results[i:j])
+    def __repr__(self):
+        return "<%s instance {cols [%d], rows [%d]} at %s>" % (self.__class__, len(self.headers), len(self.results), id(self))
diff --git a/src/main/resources/PythonLibs/decimal.py b/src/main/resources/PythonLibs/decimal.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d83b498a71bd43580655503004f1d1838eb78cb
--- /dev/null
+++ b/src/main/resources/PythonLibs/decimal.py
@@ -0,0 +1,6163 @@
+# Copyright (c) 2004 Python Software Foundation.
+# All rights reserved.
+
+# Written by Eric Price <eprice at tjhsst.edu>
+#    and Facundo Batista <facundo at taniquetil.com.ar>
+#    and Raymond Hettinger <python at rcn.com>
+#    and Aahz <aahz at pobox.com>
+#    and Tim Peters
+
+# This module is currently Py2.3 compatible and should be kept that way
+# unless a major compelling advantage arises.  IOW, 2.3 compatibility is
+# strongly preferred, but not guaranteed.
+
+# Also, this module should be kept in sync with the latest updates of
+# the IBM specification as it evolves.  Those updates will be treated
+# as bug fixes (deviation from the spec is a compatibility, usability
+# bug) and will be backported.  At this point the spec is stabilizing
+# and the updates are becoming fewer, smaller, and less significant.
+
+"""
+This is a Py2.3 implementation of decimal floating point arithmetic based on
+the General Decimal Arithmetic Specification:
+
+    www2.hursley.ibm.com/decimal/decarith.html
+
+and IEEE standard 854-1987:
+
+    www.cs.berkeley.edu/~ejr/projects/754/private/drafts/854-1987/dir.html
+
+Decimal floating point has finite precision with arbitrarily large bounds.
+
+The purpose of this module is to support arithmetic using familiar
+"schoolhouse" rules and to avoid some of the tricky representation
+issues associated with binary floating point.  The package is especially
+useful for financial applications or for contexts where users have
+expectations that are at odds with binary floating point (for instance,
+in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead
+of the expected Decimal('0.00') returned by decimal floating point).
+
+Here are some examples of using the decimal module:
+
+>>> from decimal import *
+>>> setcontext(ExtendedContext)
+>>> Decimal(0)
+Decimal('0')
+>>> Decimal('1')
+Decimal('1')
+>>> Decimal('-.0123')
+Decimal('-0.0123')
+>>> Decimal(123456)
+Decimal('123456')
+>>> Decimal('123.45e12345678901234567890')
+Decimal('1.2345E+12345678901234567892')
+>>> Decimal('1.33') + Decimal('1.27')
+Decimal('2.60')
+>>> Decimal('12.34') + Decimal('3.87') - Decimal('18.41')
+Decimal('-2.20')
+>>> dig = Decimal(1)
+>>> print dig / Decimal(3)
+0.333333333
+>>> getcontext().prec = 18
+>>> print dig / Decimal(3)
+0.333333333333333333
+>>> print dig.sqrt()
+1
+>>> print Decimal(3).sqrt()
+1.73205080756887729
+>>> print Decimal(3) ** 123
+4.85192780976896427E+58
+>>> inf = Decimal(1) / Decimal(0)
+>>> print inf
+Infinity
+>>> neginf = Decimal(-1) / Decimal(0)
+>>> print neginf
+-Infinity
+>>> print neginf + inf
+NaN
+>>> print neginf * inf
+-Infinity
+>>> print dig / 0
+Infinity
+>>> getcontext().traps[DivisionByZero] = 1
+>>> print dig / 0
+Traceback (most recent call last):
+  ...
+  ...
+  ...
+DivisionByZero: x / 0
+>>> c = Context()
+>>> c.traps[InvalidOperation] = 0
+>>> print c.flags[InvalidOperation]
+0
+>>> c.divide(Decimal(0), Decimal(0))
+Decimal('NaN')
+>>> c.traps[InvalidOperation] = 1
+>>> print c.flags[InvalidOperation]
+1
+>>> c.flags[InvalidOperation] = 0
+>>> print c.flags[InvalidOperation]
+0
+>>> print c.divide(Decimal(0), Decimal(0))
+Traceback (most recent call last):
+  ...
+  ...
+  ...
+InvalidOperation: 0 / 0
+>>> print c.flags[InvalidOperation]
+1
+>>> c.flags[InvalidOperation] = 0
+>>> c.traps[InvalidOperation] = 0
+>>> print c.divide(Decimal(0), Decimal(0))
+NaN
+>>> print c.flags[InvalidOperation]
+1
+>>>
+"""
+
+__all__ = [
+    # Two major classes
+    'Decimal', 'Context',
+
+    # Contexts
+    'DefaultContext', 'BasicContext', 'ExtendedContext',
+
+    # Exceptions
+    'DecimalException', 'Clamped', 'InvalidOperation', 'DivisionByZero',
+    'Inexact', 'Rounded', 'Subnormal', 'Overflow', 'Underflow',
+
+    # Constants for use in setting up contexts
+    'ROUND_DOWN', 'ROUND_HALF_UP', 'ROUND_HALF_EVEN', 'ROUND_CEILING',
+    'ROUND_FLOOR', 'ROUND_UP', 'ROUND_HALF_DOWN', 'ROUND_05UP',
+
+    # Functions for manipulating contexts
+    'setcontext', 'getcontext', 'localcontext'
+]
+
+__version__ = '1.70'    # Highest version of the spec this complies with
+
+import copy as _copy
+import math as _math
+import numbers as _numbers
+
+try:
+    from collections import namedtuple as _namedtuple
+    DecimalTuple = _namedtuple('DecimalTuple', 'sign digits exponent')
+except ImportError:
+    DecimalTuple = lambda *args: args
+
+# Rounding
+ROUND_DOWN = 'ROUND_DOWN'
+ROUND_HALF_UP = 'ROUND_HALF_UP'
+ROUND_HALF_EVEN = 'ROUND_HALF_EVEN'
+ROUND_CEILING = 'ROUND_CEILING'
+ROUND_FLOOR = 'ROUND_FLOOR'
+ROUND_UP = 'ROUND_UP'
+ROUND_HALF_DOWN = 'ROUND_HALF_DOWN'
+ROUND_05UP = 'ROUND_05UP'
+
+# Errors
+
+class DecimalException(ArithmeticError):
+    """Base exception class.
+
+    Used exceptions derive from this.
+    If an exception derives from another exception besides this (such as
+    Underflow (Inexact, Rounded, Subnormal) that indicates that it is only
+    called if the others are present.  This isn't actually used for
+    anything, though.
+
+    handle  -- Called when context._raise_error is called and the
+               trap_enabler is not set.  First argument is self, second is the
+               context.  More arguments can be given, those being after
+               the explanation in _raise_error (For example,
+               context._raise_error(NewError, '(-x)!', self._sign) would
+               call NewError().handle(context, self._sign).)
+
+    To define a new exception, it should be sufficient to have it derive
+    from DecimalException.
+    """
+    def handle(self, context, *args):
+        pass
+
+
+class Clamped(DecimalException):
+    """Exponent of a 0 changed to fit bounds.
+
+    This occurs and signals clamped if the exponent of a result has been
+    altered in order to fit the constraints of a specific concrete
+    representation.  This may occur when the exponent of a zero result would
+    be outside the bounds of a representation, or when a large normal
+    number would have an encoded exponent that cannot be represented.  In
+    this latter case, the exponent is reduced to fit and the corresponding
+    number of zero digits are appended to the coefficient ("fold-down").
+    """
+
+class InvalidOperation(DecimalException):
+    """An invalid operation was performed.
+
+    Various bad things cause this:
+
+    Something creates a signaling NaN
+    -INF + INF
+    0 * (+-)INF
+    (+-)INF / (+-)INF
+    x % 0
+    (+-)INF % x
+    x._rescale( non-integer )
+    sqrt(-x) , x > 0
+    0 ** 0
+    x ** (non-integer)
+    x ** (+-)INF
+    An operand is invalid
+
+    The result of the operation after these is a quiet positive NaN,
+    except when the cause is a signaling NaN, in which case the result is
+    also a quiet NaN, but with the original sign, and an optional
+    diagnostic information.
+    """
+    def handle(self, context, *args):
+        if args:
+            ans = _dec_from_triple(args[0]._sign, args[0]._int, 'n', True)
+            return ans._fix_nan(context)
+        return _NaN
+
+class ConversionSyntax(InvalidOperation):
+    """Trying to convert badly formed string.
+
+    This occurs and signals invalid-operation if an string is being
+    converted to a number and it does not conform to the numeric string
+    syntax.  The result is [0,qNaN].
+    """
+    def handle(self, context, *args):
+        return _NaN
+
+class DivisionByZero(DecimalException, ZeroDivisionError):
+    """Division by 0.
+
+    This occurs and signals division-by-zero if division of a finite number
+    by zero was attempted (during a divide-integer or divide operation, or a
+    power operation with negative right-hand operand), and the dividend was
+    not zero.
+
+    The result of the operation is [sign,inf], where sign is the exclusive
+    or of the signs of the operands for divide, or is 1 for an odd power of
+    -0, for power.
+    """
+
+    def handle(self, context, sign, *args):
+        return _SignedInfinity[sign]
+
+class DivisionImpossible(InvalidOperation):
+    """Cannot perform the division adequately.
+
+    This occurs and signals invalid-operation if the integer result of a
+    divide-integer or remainder operation had too many digits (would be
+    longer than precision).  The result is [0,qNaN].
+    """
+
+    def handle(self, context, *args):
+        return _NaN
+
+class DivisionUndefined(InvalidOperation, ZeroDivisionError):
+    """Undefined result of division.
+
+    This occurs and signals invalid-operation if division by zero was
+    attempted (during a divide-integer, divide, or remainder operation), and
+    the dividend is also zero.  The result is [0,qNaN].
+    """
+
+    def handle(self, context, *args):
+        return _NaN
+
+class Inexact(DecimalException):
+    """Had to round, losing information.
+
+    This occurs and signals inexact whenever the result of an operation is
+    not exact (that is, it needed to be rounded and any discarded digits
+    were non-zero), or if an overflow or underflow condition occurs.  The
+    result in all cases is unchanged.
+
+    The inexact signal may be tested (or trapped) to determine if a given
+    operation (or sequence of operations) was inexact.
+    """
+
+class InvalidContext(InvalidOperation):
+    """Invalid context.  Unknown rounding, for example.
+
+    This occurs and signals invalid-operation if an invalid context was
+    detected during an operation.  This can occur if contexts are not checked
+    on creation and either the precision exceeds the capability of the
+    underlying concrete representation or an unknown or unsupported rounding
+    was specified.  These aspects of the context need only be checked when
+    the values are required to be used.  The result is [0,qNaN].
+    """
+
+    def handle(self, context, *args):
+        return _NaN
+
+class Rounded(DecimalException):
+    """Number got rounded (not  necessarily changed during rounding).
+
+    This occurs and signals rounded whenever the result of an operation is
+    rounded (that is, some zero or non-zero digits were discarded from the
+    coefficient), or if an overflow or underflow condition occurs.  The
+    result in all cases is unchanged.
+
+    The rounded signal may be tested (or trapped) to determine if a given
+    operation (or sequence of operations) caused a loss of precision.
+    """
+
+class Subnormal(DecimalException):
+    """Exponent < Emin before rounding.
+
+    This occurs and signals subnormal whenever the result of a conversion or
+    operation is subnormal (that is, its adjusted exponent is less than
+    Emin, before any rounding).  The result in all cases is unchanged.
+
+    The subnormal signal may be tested (or trapped) to determine if a given
+    or operation (or sequence of operations) yielded a subnormal result.
+    """
+
+class Overflow(Inexact, Rounded):
+    """Numerical overflow.
+
+    This occurs and signals overflow if the adjusted exponent of a result
+    (from a conversion or from an operation that is not an attempt to divide
+    by zero), after rounding, would be greater than the largest value that
+    can be handled by the implementation (the value Emax).
+
+    The result depends on the rounding mode:
+
+    For round-half-up and round-half-even (and for round-half-down and
+    round-up, if implemented), the result of the operation is [sign,inf],
+    where sign is the sign of the intermediate result.  For round-down, the
+    result is the largest finite number that can be represented in the
+    current precision, with the sign of the intermediate result.  For
+    round-ceiling, the result is the same as for round-down if the sign of
+    the intermediate result is 1, or is [0,inf] otherwise.  For round-floor,
+    the result is the same as for round-down if the sign of the intermediate
+    result is 0, or is [1,inf] otherwise.  In all cases, Inexact and Rounded
+    will also be raised.
+    """
+
+    def handle(self, context, sign, *args):
+        if context.rounding in (ROUND_HALF_UP, ROUND_HALF_EVEN,
+                                ROUND_HALF_DOWN, ROUND_UP):
+            return _SignedInfinity[sign]
+        if sign == 0:
+            if context.rounding == ROUND_CEILING:
+                return _SignedInfinity[sign]
+            return _dec_from_triple(sign, '9'*context.prec,
+                            context.Emax-context.prec+1)
+        if sign == 1:
+            if context.rounding == ROUND_FLOOR:
+                return _SignedInfinity[sign]
+            return _dec_from_triple(sign, '9'*context.prec,
+                             context.Emax-context.prec+1)
+
+
+class Underflow(Inexact, Rounded, Subnormal):
+    """Numerical underflow with result rounded to 0.
+
+    This occurs and signals underflow if a result is inexact and the
+    adjusted exponent of the result would be smaller (more negative) than
+    the smallest value that can be handled by the implementation (the value
+    Emin).  That is, the result is both inexact and subnormal.
+
+    The result after an underflow will be a subnormal number rounded, if
+    necessary, so that its exponent is not less than Etiny.  This may result
+    in 0 with the sign of the intermediate result and an exponent of Etiny.
+
+    In all cases, Inexact, Rounded, and Subnormal will also be raised.
+    """
+
+# List of public traps and flags
+_signals = [Clamped, DivisionByZero, Inexact, Overflow, Rounded,
+           Underflow, InvalidOperation, Subnormal]
+
+# Map conditions (per the spec) to signals
+_condition_map = {ConversionSyntax:InvalidOperation,
+                  DivisionImpossible:InvalidOperation,
+                  DivisionUndefined:InvalidOperation,
+                  InvalidContext:InvalidOperation}
+
+##### Context Functions ##################################################
+
+# The getcontext() and setcontext() function manage access to a thread-local
+# current context.  Py2.4 offers direct support for thread locals.  If that
+# is not available, use threading.currentThread() which is slower but will
+# work for older Pythons.  If threads are not part of the build, create a
+# mock threading object with threading.local() returning the module namespace.
+
+try:
+    import threading
+except ImportError:
+    # Python was compiled without threads; create a mock object instead
+    import sys
+    class MockThreading(object):
+        def local(self, sys=sys):
+            return sys.modules[__name__]
+    threading = MockThreading()
+    del sys, MockThreading
+
+try:
+    from java.lang import Object
+    from java.math import BigDecimal
+    from org.python.core import Py
+except ImportError:
+    #Not Jython, ignore.
+    pass
+
+try:
+    threading.local
+
+except AttributeError:
+
+    # To fix reloading, force it to create a new context
+    # Old contexts have different exceptions in their dicts, making problems.
+    if hasattr(threading.currentThread(), '__decimal_context__'):
+        del threading.currentThread().__decimal_context__
+
+    def setcontext(context):
+        """Set this thread's context to context."""
+        if context in (DefaultContext, BasicContext, ExtendedContext):
+            context = context.copy()
+            context.clear_flags()
+        threading.currentThread().__decimal_context__ = context
+
+    def getcontext():
+        """Returns this thread's context.
+
+        If this thread does not yet have a context, returns
+        a new context and sets this thread's context.
+        New contexts are copies of DefaultContext.
+        """
+        try:
+            return threading.currentThread().__decimal_context__
+        except AttributeError:
+            context = Context()
+            threading.currentThread().__decimal_context__ = context
+            return context
+
+else:
+
+    local = threading.local()
+    if hasattr(local, '__decimal_context__'):
+        del local.__decimal_context__
+
+    def getcontext(_local=local):
+        """Returns this thread's context.
+
+        If this thread does not yet have a context, returns
+        a new context and sets this thread's context.
+        New contexts are copies of DefaultContext.
+        """
+        try:
+            return _local.__decimal_context__
+        except AttributeError:
+            context = Context()
+            _local.__decimal_context__ = context
+            return context
+
+    def setcontext(context, _local=local):
+        """Set this thread's context to context."""
+        if context in (DefaultContext, BasicContext, ExtendedContext):
+            context = context.copy()
+            context.clear_flags()
+        _local.__decimal_context__ = context
+
+    del threading, local        # Don't contaminate the namespace
+
+def localcontext(ctx=None):
+    """Return a context manager for a copy of the supplied context
+
+    Uses a copy of the current context if no context is specified
+    The returned context manager creates a local decimal context
+    in a with statement:
+        def sin(x):
+             with localcontext() as ctx:
+                 ctx.prec += 2
+                 # Rest of sin calculation algorithm
+                 # uses a precision 2 greater than normal
+             return +s  # Convert result to normal precision
+
+         def sin(x):
+             with localcontext(ExtendedContext):
+                 # Rest of sin calculation algorithm
+                 # uses the Extended Context from the
+                 # General Decimal Arithmetic Specification
+             return +s  # Convert result to normal context
+
+    >>> setcontext(DefaultContext)
+    >>> print getcontext().prec
+    28
+    >>> with localcontext():
+    ...     ctx = getcontext()
+    ...     ctx.prec += 2
+    ...     print ctx.prec
+    ...
+    30
+    >>> with localcontext(ExtendedContext):
+    ...     print getcontext().prec
+    ...
+    9
+    >>> print getcontext().prec
+    28
+    """
+    if ctx is None: ctx = getcontext()
+    return _ContextManager(ctx)
+
+
+##### Decimal class #######################################################
+
+class Decimal(object):
+    """Floating point class for decimal arithmetic."""
+
+    __slots__ = ('_exp','_int','_sign', '_is_special')
+    # Generally, the value of the Decimal instance is given by
+    #  (-1)**_sign * _int * 10**_exp
+    # Special values are signified by _is_special == True
+
+    # We're immutable, so use __new__ not __init__
+    def __new__(cls, value="0", context=None):
+        """Create a decimal point instance.
+
+        >>> Decimal('3.14')              # string input
+        Decimal('3.14')
+        >>> Decimal((0, (3, 1, 4), -2))  # tuple (sign, digit_tuple, exponent)
+        Decimal('3.14')
+        >>> Decimal(314)                 # int or long
+        Decimal('314')
+        >>> Decimal(Decimal(314))        # another decimal instance
+        Decimal('314')
+        >>> Decimal('  3.14  \\n')        # leading and trailing whitespace okay
+        Decimal('3.14')
+        """
+
+        # Note that the coefficient, self._int, is actually stored as
+        # a string rather than as a tuple of digits.  This speeds up
+        # the "digits to integer" and "integer to digits" conversions
+        # that are used in almost every arithmetic operation on
+        # Decimals.  This is an internal detail: the as_tuple function
+        # and the Decimal constructor still deal with tuples of
+        # digits.
+
+        self = object.__new__(cls)
+
+        # From a string
+        # REs insist on real strings, so we can too.
+        if isinstance(value, basestring):
+            m = _parser(value.strip())
+            if m is None:
+                if context is None:
+                    context = getcontext()
+                return context._raise_error(ConversionSyntax,
+                                "Invalid literal for Decimal: %r" % value)
+
+            if m.group('sign') == "-":
+                self._sign = 1
+            else:
+                self._sign = 0
+            intpart = m.group('int')
+            if intpart is not None:
+                # finite number
+                fracpart = m.group('frac') or ''
+                exp = int(m.group('exp') or '0')
+                self._int = str(int(intpart+fracpart))
+                self._exp = exp - len(fracpart)
+                self._is_special = False
+            else:
+                diag = m.group('diag')
+                if diag is not None:
+                    # NaN
+                    self._int = str(int(diag or '0')).lstrip('0')
+                    if m.group('signal'):
+                        self._exp = 'N'
+                    else:
+                        self._exp = 'n'
+                else:
+                    # infinity
+                    self._int = '0'
+                    self._exp = 'F'
+                self._is_special = True
+            return self
+
+        # From an integer
+        if isinstance(value, (int,long)):
+            if value >= 0:
+                self._sign = 0
+            else:
+                self._sign = 1
+            self._exp = 0
+            self._int = str(abs(value))
+            self._is_special = False
+            return self
+
+        # From another decimal
+        if isinstance(value, Decimal):
+            self._exp  = value._exp
+            self._sign = value._sign
+            self._int  = value._int
+            self._is_special  = value._is_special
+            return self
+
+        # From an internal working value
+        if isinstance(value, _WorkRep):
+            self._sign = value.sign
+            self._int = str(value.int)
+            self._exp = int(value.exp)
+            self._is_special = False
+            return self
+
+        # tuple/list conversion (possibly from as_tuple())
+        if isinstance(value, (list,tuple)):
+            if len(value) != 3:
+                raise ValueError('Invalid tuple size in creation of Decimal '
+                                 'from list or tuple.  The list or tuple '
+                                 'should have exactly three elements.')
+            # process sign.  The isinstance test rejects floats
+            if not (isinstance(value[0], (int, long)) and value[0] in (0,1)):
+                raise ValueError("Invalid sign.  The first value in the tuple "
+                                 "should be an integer; either 0 for a "
+                                 "positive number or 1 for a negative number.")
+            self._sign = value[0]
+            if value[2] == 'F':
+                # infinity: value[1] is ignored
+                self._int = '0'
+                self._exp = value[2]
+                self._is_special = True
+            else:
+                # process and validate the digits in value[1]
+                digits = []
+                for digit in value[1]:
+                    if isinstance(digit, (int, long)) and 0 <= digit <= 9:
+                        # skip leading zeros
+                        if digits or digit != 0:
+                            digits.append(digit)
+                    else:
+                        raise ValueError("The second value in the tuple must "
+                                         "be composed of integers in the range "
+                                         "0 through 9.")
+                if value[2] in ('n', 'N'):
+                    # NaN: digits form the diagnostic
+                    self._int = ''.join(map(str, digits))
+                    self._exp = value[2]
+                    self._is_special = True
+                elif isinstance(value[2], (int, long)):
+                    # finite number: digits give the coefficient
+                    self._int = ''.join(map(str, digits or [0]))
+                    self._exp = value[2]
+                    self._is_special = False
+                else:
+                    raise ValueError("The third value in the tuple must "
+                                     "be an integer, or one of the "
+                                     "strings 'F', 'n', 'N'.")
+            return self
+
+        if isinstance(value, float):
+            value = Decimal.from_float(value)
+            self._exp  = value._exp
+            self._sign = value._sign
+            self._int  = value._int
+            self._is_special  = value._is_special
+            return self
+
+        raise TypeError("Cannot convert %r to Decimal" % value)
+
+    # @classmethod, but @decorator is not valid Python 2.3 syntax, so
+    # don't use it (see notes on Py2.3 compatibility at top of file)
+    def from_float(cls, f):
+        """Converts a float to a decimal number, exactly.
+
+        Note that Decimal.from_float(0.1) is not the same as Decimal('0.1').
+        Since 0.1 is not exactly representable in binary floating point, the
+        value is stored as the nearest representable value which is
+        0x1.999999999999ap-4.  The exact equivalent of the value in decimal
+        is 0.1000000000000000055511151231257827021181583404541015625.
+
+        >>> Decimal.from_float(0.1)
+        Decimal('0.1000000000000000055511151231257827021181583404541015625')
+        >>> Decimal.from_float(float('nan'))
+        Decimal('NaN')
+        >>> Decimal.from_float(float('inf'))
+        Decimal('Infinity')
+        >>> Decimal.from_float(-float('inf'))
+        Decimal('-Infinity')
+        >>> Decimal.from_float(-0.0)
+        Decimal('-0')
+
+        """
+        if isinstance(f, (int, long)):        # handle integer inputs
+            return cls(f)
+        if _math.isinf(f) or _math.isnan(f):  # raises TypeError if not a float
+            return cls(repr(f))
+        if _math.copysign(1.0, f) == 1.0:
+            sign = 0
+        else:
+            sign = 1
+        n, d = abs(f).as_integer_ratio()
+        k = d.bit_length() - 1
+        result = _dec_from_triple(sign, str(n*5**k), -k)
+        if cls is Decimal:
+            return result
+        else:
+            return cls(result)
+    from_float = classmethod(from_float)
+
+    def _isnan(self):
+        """Returns whether the number is not actually one.
+
+        0 if a number
+        1 if NaN
+        2 if sNaN
+        """
+        if self._is_special:
+            exp = self._exp
+            if exp == 'n':
+                return 1
+            elif exp == 'N':
+                return 2
+        return 0
+
+    def _isinfinity(self):
+        """Returns whether the number is infinite
+
+        0 if finite or not a number
+        1 if +INF
+        -1 if -INF
+        """
+        if self._exp == 'F':
+            if self._sign:
+                return -1
+            return 1
+        return 0
+
+    def _check_nans(self, other=None, context=None):
+        """Returns whether the number is not actually one.
+
+        if self, other are sNaN, signal
+        if self, other are NaN return nan
+        return 0
+
+        Done before operations.
+        """
+
+        self_is_nan = self._isnan()
+        if other is None:
+            other_is_nan = False
+        else:
+            other_is_nan = other._isnan()
+
+        if self_is_nan or other_is_nan:
+            if context is None:
+                context = getcontext()
+
+            if self_is_nan == 2:
+                return context._raise_error(InvalidOperation, 'sNaN',
+                                        self)
+            if other_is_nan == 2:
+                return context._raise_error(InvalidOperation, 'sNaN',
+                                        other)
+            if self_is_nan:
+                return self._fix_nan(context)
+
+            return other._fix_nan(context)
+        return 0
+
+    def _compare_check_nans(self, other, context):
+        """Version of _check_nans used for the signaling comparisons
+        compare_signal, __le__, __lt__, __ge__, __gt__.
+
+        Signal InvalidOperation if either self or other is a (quiet
+        or signaling) NaN.  Signaling NaNs take precedence over quiet
+        NaNs.
+
+        Return 0 if neither operand is a NaN.
+
+        """
+        if context is None:
+            context = getcontext()
+
+        if self._is_special or other._is_special:
+            if self.is_snan():
+                return context._raise_error(InvalidOperation,
+                                            'comparison involving sNaN',
+                                            self)
+            elif other.is_snan():
+                return context._raise_error(InvalidOperation,
+                                            'comparison involving sNaN',
+                                            other)
+            elif self.is_qnan():
+                return context._raise_error(InvalidOperation,
+                                            'comparison involving NaN',
+                                            self)
+            elif other.is_qnan():
+                return context._raise_error(InvalidOperation,
+                                            'comparison involving NaN',
+                                            other)
+        return 0
+
+    def __nonzero__(self):
+        """Return True if self is nonzero; otherwise return False.
+
+        NaNs and infinities are considered nonzero.
+        """
+        return self._is_special or self._int != '0'
+
+    def _cmp(self, other):
+        """Compare the two non-NaN decimal instances self and other.
+
+        Returns -1 if self < other, 0 if self == other and 1
+        if self > other.  This routine is for internal use only."""
+
+        if self._is_special or other._is_special:
+            self_inf = self._isinfinity()
+            other_inf = other._isinfinity()
+            if self_inf == other_inf:
+                return 0
+            elif self_inf < other_inf:
+                return -1
+            else:
+                return 1
+
+        # check for zeros;  Decimal('0') == Decimal('-0')
+        if not self:
+            if not other:
+                return 0
+            else:
+                return -((-1)**other._sign)
+        if not other:
+            return (-1)**self._sign
+
+        # If different signs, neg one is less
+        if other._sign < self._sign:
+            return -1
+        if self._sign < other._sign:
+            return 1
+
+        self_adjusted = self.adjusted()
+        other_adjusted = other.adjusted()
+        if self_adjusted == other_adjusted:
+            self_padded = self._int + '0'*(self._exp - other._exp)
+            other_padded = other._int + '0'*(other._exp - self._exp)
+            if self_padded == other_padded:
+                return 0
+            elif self_padded < other_padded:
+                return -(-1)**self._sign
+            else:
+                return (-1)**self._sign
+        elif self_adjusted > other_adjusted:
+            return (-1)**self._sign
+        else: # self_adjusted < other_adjusted
+            return -((-1)**self._sign)
+
+    # Note: The Decimal standard doesn't cover rich comparisons for
+    # Decimals.  In particular, the specification is silent on the
+    # subject of what should happen for a comparison involving a NaN.
+    # We take the following approach:
+    #
+    #   == comparisons involving a quiet NaN always return False
+    #   != comparisons involving a quiet NaN always return True
+    #   == or != comparisons involving a signaling NaN signal
+    #      InvalidOperation, and return False or True as above if the
+    #      InvalidOperation is not trapped.
+    #   <, >, <= and >= comparisons involving a (quiet or signaling)
+    #      NaN signal InvalidOperation, and return False if the
+    #      InvalidOperation is not trapped.
+    #
+    # This behavior is designed to conform as closely as possible to
+    # that specified by IEEE 754.
+
+    def __eq__(self, other, context=None):
+        other = _convert_other(other, allow_float=True)
+        if other is NotImplemented:
+            return other
+        if self._check_nans(other, context):
+            return False
+        return self._cmp(other) == 0
+
+    def __ne__(self, other, context=None):
+        other = _convert_other(other, allow_float=True)
+        if other is NotImplemented:
+            return other
+        if self._check_nans(other, context):
+            return True
+        return self._cmp(other) != 0
+
+    def __lt__(self, other, context=None):
+        other = _convert_other(other, allow_float=True)
+        if other is NotImplemented:
+            return other
+        ans = self._compare_check_nans(other, context)
+        if ans:
+            return False
+        return self._cmp(other) < 0
+
+    def __le__(self, other, context=None):
+        other = _convert_other(other, allow_float=True)
+        if other is NotImplemented:
+            return other
+        ans = self._compare_check_nans(other, context)
+        if ans:
+            return False
+        return self._cmp(other) <= 0
+
+    def __gt__(self, other, context=None):
+        other = _convert_other(other, allow_float=True)
+        if other is NotImplemented:
+            return other
+        ans = self._compare_check_nans(other, context)
+        if ans:
+            return False
+        return self._cmp(other) > 0
+
+    def __ge__(self, other, context=None):
+        other = _convert_other(other, allow_float=True)
+        if other is NotImplemented:
+            return other
+        ans = self._compare_check_nans(other, context)
+        if ans:
+            return False
+        return self._cmp(other) >= 0
+
+    def compare(self, other, context=None):
+        """Compares one to another.
+
+        -1 => a < b
+        0  => a = b
+        1  => a > b
+        NaN => one is NaN
+        Like __cmp__, but returns Decimal instances.
+        """
+        other = _convert_other(other, raiseit=True)
+
+        # Compare(NaN, NaN) = NaN
+        if (self._is_special or other and other._is_special):
+            ans = self._check_nans(other, context)
+            if ans:
+                return ans
+
+        return Decimal(self._cmp(other))
+
+    def __hash__(self):
+        """x.__hash__() <==> hash(x)"""
+        # Decimal integers must hash the same as the ints
+        #
+        # The hash of a nonspecial noninteger Decimal must depend only
+        # on the value of that Decimal, and not on its representation.
+        # For example: hash(Decimal('100E-1')) == hash(Decimal('10')).
+
+        # Equality comparisons involving signaling nans can raise an
+        # exception; since equality checks are implicitly and
+        # unpredictably used when checking set and dict membership, we
+        # prevent signaling nans from being used as set elements or
+        # dict keys by making __hash__ raise an exception.
+        if self._is_special:
+            if self.is_snan():
+                raise TypeError('Cannot hash a signaling NaN value.')
+            elif self.is_nan():
+                # 0 to match hash(float('nan'))
+                return 0
+            else:
+                # values chosen to match hash(float('inf')) and
+                # hash(float('-inf')).
+                if self._sign:
+                    return -271828
+                else:
+                    return 314159
+
+        # In Python 2.7, we're allowing comparisons (but not
+        # arithmetic operations) between floats and Decimals;  so if
+        # a Decimal instance is exactly representable as a float then
+        # its hash should match that of the float.
+        self_as_float = float(self)
+        if Decimal.from_float(self_as_float) == self:
+            return hash(self_as_float)
+
+        if self._isinteger():
+            # We do this differently in Jython due to the different maxint.
+            return hash(long(self.to_integral_value()))
+        # The value of a nonzero nonspecial Decimal instance is
+        # faithfully represented by the triple consisting of its sign,
+        # its adjusted exponent, and its coefficient with trailing
+        # zeros removed.
+        return hash((self._sign,
+                     self._exp+len(self._int),
+                     self._int.rstrip('0')))
+
+    def as_tuple(self):
+        """Represents the number as a triple tuple.
+
+        To show the internals exactly as they are.
+        """
+        return DecimalTuple(self._sign, tuple(map(int, self._int)), self._exp)
+
+    def __repr__(self):
+        """Represents the number as an instance of Decimal."""
+        # Invariant:  eval(repr(d)) == d
+        return "Decimal('%s')" % str(self)
+
+    def __str__(self, eng=False, context=None):
+        """Return string representation of the number in scientific notation.
+
+        Captures all of the information in the underlying representation.
+        """
+
+        sign = ['', '-'][self._sign]
+        if self._is_special:
+            if self._exp == 'F':
+                return sign + 'Infinity'
+            elif self._exp == 'n':
+                return sign + 'NaN' + self._int
+            else: # self._exp == 'N'
+                return sign + 'sNaN' + self._int
+
+        # number of digits of self._int to left of decimal point
+        leftdigits = self._exp + len(self._int)
+
+        # dotplace is number of digits of self._int to the left of the
+        # decimal point in the mantissa of the output string (that is,
+        # after adjusting the exponent)
+        if self._exp <= 0 and leftdigits > -6:
+            # no exponent required
+            dotplace = leftdigits
+        elif not eng:
+            # usual scientific notation: 1 digit on left of the point
+            dotplace = 1
+        elif self._int == '0':
+            # engineering notation, zero
+            dotplace = (leftdigits + 1) % 3 - 1
+        else:
+            # engineering notation, nonzero
+            dotplace = (leftdigits - 1) % 3 + 1
+
+        if dotplace <= 0:
+            intpart = '0'
+            fracpart = '.' + '0'*(-dotplace) + self._int
+        elif dotplace >= len(self._int):
+            intpart = self._int+'0'*(dotplace-len(self._int))
+            fracpart = ''
+        else:
+            intpart = self._int[:dotplace]
+            fracpart = '.' + self._int[dotplace:]
+        if leftdigits == dotplace:
+            exp = ''
+        else:
+            if context is None:
+                context = getcontext()
+            exp = ['e', 'E'][context.capitals] + "%+d" % (leftdigits-dotplace)
+
+        return sign + intpart + fracpart + exp
+
+    def to_eng_string(self, context=None):
+        """Convert to engineering-type string.
+
+        Engineering notation has an exponent which is a multiple of 3, so there
+        are up to 3 digits left of the decimal place.
+
+        Same rules for when in exponential and when as a value as in __str__.
+        """
+        return self.__str__(eng=True, context=context)
+
+    def __neg__(self, context=None):
+        """Returns a copy with the sign switched.
+
+        Rounds, if it has reason.
+        """
+        if self._is_special:
+            ans = self._check_nans(context=context)
+            if ans:
+                return ans
+
+        if not self:
+            # -Decimal('0') is Decimal('0'), not Decimal('-0')
+            ans = self.copy_abs()
+        else:
+            ans = self.copy_negate()
+
+        if context is None:
+            context = getcontext()
+        return ans._fix(context)
+
+    def __pos__(self, context=None):
+        """Returns a copy, unless it is a sNaN.
+
+        Rounds the number (if more then precision digits)
+        """
+        if self._is_special:
+            ans = self._check_nans(context=context)
+            if ans:
+                return ans
+
+        if not self:
+            # + (-0) = 0
+            ans = self.copy_abs()
+        else:
+            ans = Decimal(self)
+
+        if context is None:
+            context = getcontext()
+        return ans._fix(context)
+
+    def __abs__(self, round=True, context=None):
+        """Returns the absolute value of self.
+
+        If the keyword argument 'round' is false, do not round.  The
+        expression self.__abs__(round=False) is equivalent to
+        self.copy_abs().
+        """
+        if not round:
+            return self.copy_abs()
+
+        if self._is_special:
+            ans = self._check_nans(context=context)
+            if ans:
+                return ans
+
+        if self._sign:
+            ans = self.__neg__(context=context)
+        else:
+            ans = self.__pos__(context=context)
+
+        return ans
+
+    def __add__(self, other, context=None):
+        """Returns self + other.
+
+        -INF + INF (or the reverse) cause InvalidOperation errors.
+        """
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+
+        if context is None:
+            context = getcontext()
+
+        if self._is_special or other._is_special:
+            ans = self._check_nans(other, context)
+            if ans:
+                return ans
+
+            if self._isinfinity():
+                # If both INF, same sign => same as both, opposite => error.
+                if self._sign != other._sign and other._isinfinity():
+                    return context._raise_error(InvalidOperation, '-INF + INF')
+                return Decimal(self)
+            if other._isinfinity():
+                return Decimal(other)  # Can't both be infinity here
+
+        exp = min(self._exp, other._exp)
+        negativezero = 0
+        if context.rounding == ROUND_FLOOR and self._sign != other._sign:
+            # If the answer is 0, the sign should be negative, in this case.
+            negativezero = 1
+
+        if not self and not other:
+            sign = min(self._sign, other._sign)
+            if negativezero:
+                sign = 1
+            ans = _dec_from_triple(sign, '0', exp)
+            ans = ans._fix(context)
+            return ans
+        if not self:
+            exp = max(exp, other._exp - context.prec-1)
+            ans = other._rescale(exp, context.rounding)
+            ans = ans._fix(context)
+            return ans
+        if not other:
+            exp = max(exp, self._exp - context.prec-1)
+            ans = self._rescale(exp, context.rounding)
+            ans = ans._fix(context)
+            return ans
+
+        op1 = _WorkRep(self)
+        op2 = _WorkRep(other)
+        op1, op2 = _normalize(op1, op2, context.prec)
+
+        result = _WorkRep()
+        if op1.sign != op2.sign:
+            # Equal and opposite
+            if op1.int == op2.int:
+                ans = _dec_from_triple(negativezero, '0', exp)
+                ans = ans._fix(context)
+                return ans
+            if op1.int < op2.int:
+                op1, op2 = op2, op1
+                # OK, now abs(op1) > abs(op2)
+            if op1.sign == 1:
+                result.sign = 1
+                op1.sign, op2.sign = op2.sign, op1.sign
+            else:
+                result.sign = 0
+                # So we know the sign, and op1 > 0.
+        elif op1.sign == 1:
+            result.sign = 1
+            op1.sign, op2.sign = (0, 0)
+        else:
+            result.sign = 0
+        # Now, op1 > abs(op2) > 0
+
+        if op2.sign == 0:
+            result.int = op1.int + op2.int
+        else:
+            result.int = op1.int - op2.int
+
+        result.exp = op1.exp
+        ans = Decimal(result)
+        ans = ans._fix(context)
+        return ans
+
+    __radd__ = __add__
+
+    def __sub__(self, other, context=None):
+        """Return self - other"""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+
+        if self._is_special or other._is_special:
+            ans = self._check_nans(other, context=context)
+            if ans:
+                return ans
+
+        # self - other is computed as self + other.copy_negate()
+        return self.__add__(other.copy_negate(), context=context)
+
+    def __rsub__(self, other, context=None):
+        """Return other - self"""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+
+        return other.__sub__(self, context=context)
+
+    def __mul__(self, other, context=None):
+        """Return self * other.
+
+        (+-) INF * 0 (or its reverse) raise InvalidOperation.
+        """
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+
+        if context is None:
+            context = getcontext()
+
+        resultsign = self._sign ^ other._sign
+
+        if self._is_special or other._is_special:
+            ans = self._check_nans(other, context)
+            if ans:
+                return ans
+
+            if self._isinfinity():
+                if not other:
+                    return context._raise_error(InvalidOperation, '(+-)INF * 0')
+                return _SignedInfinity[resultsign]
+
+            if other._isinfinity():
+                if not self:
+                    return context._raise_error(InvalidOperation, '0 * (+-)INF')
+                return _SignedInfinity[resultsign]
+
+        resultexp = self._exp + other._exp
+
+        # Special case for multiplying by zero
+        if not self or not other:
+            ans = _dec_from_triple(resultsign, '0', resultexp)
+            # Fixing in case the exponent is out of bounds
+            ans = ans._fix(context)
+            return ans
+
+        # Special case for multiplying by power of 10
+        if self._int == '1':
+            ans = _dec_from_triple(resultsign, other._int, resultexp)
+            ans = ans._fix(context)
+            return ans
+        if other._int == '1':
+            ans = _dec_from_triple(resultsign, self._int, resultexp)
+            ans = ans._fix(context)
+            return ans
+
+        op1 = _WorkRep(self)
+        op2 = _WorkRep(other)
+
+        ans = _dec_from_triple(resultsign, str(op1.int * op2.int), resultexp)
+        ans = ans._fix(context)
+
+        return ans
+    __rmul__ = __mul__
+
+    def __truediv__(self, other, context=None):
+        """Return self / other."""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return NotImplemented
+
+        if context is None:
+            context = getcontext()
+
+        sign = self._sign ^ other._sign
+
+        if self._is_special or other._is_special:
+            ans = self._check_nans(other, context)
+            if ans:
+                return ans
+
+            if self._isinfinity() and other._isinfinity():
+                return context._raise_error(InvalidOperation, '(+-)INF/(+-)INF')
+
+            if self._isinfinity():
+                return _SignedInfinity[sign]
+
+            if other._isinfinity():
+                context._raise_error(Clamped, 'Division by infinity')
+                return _dec_from_triple(sign, '0', context.Etiny())
+
+        # Special cases for zeroes
+        if not other:
+            if not self:
+                return context._raise_error(DivisionUndefined, '0 / 0')
+            return context._raise_error(DivisionByZero, 'x / 0', sign)
+
+        if not self:
+            exp = self._exp - other._exp
+            coeff = 0
+        else:
+            # OK, so neither = 0, INF or NaN
+            shift = len(other._int) - len(self._int) + context.prec + 1
+            exp = self._exp - other._exp - shift
+            op1 = _WorkRep(self)
+            op2 = _WorkRep(other)
+            if shift >= 0:
+                coeff, remainder = divmod(op1.int * 10**shift, op2.int)
+            else:
+                coeff, remainder = divmod(op1.int, op2.int * 10**-shift)
+            if remainder:
+                # result is not exact; adjust to ensure correct rounding
+                if coeff % 5 == 0:
+                    coeff += 1
+            else:
+                # result is exact; get as close to ideal exponent as possible
+                ideal_exp = self._exp - other._exp
+                while exp < ideal_exp and coeff % 10 == 0:
+                    coeff //= 10
+                    exp += 1
+
+        ans = _dec_from_triple(sign, str(coeff), exp)
+        return ans._fix(context)
+
+    def _divide(self, other, context):
+        """Return (self // other, self % other), to context.prec precision.
+
+        Assumes that neither self nor other is a NaN, that self is not
+        infinite and that other is nonzero.
+        """
+        sign = self._sign ^ other._sign
+        if other._isinfinity():
+            ideal_exp = self._exp
+        else:
+            ideal_exp = min(self._exp, other._exp)
+
+        expdiff = self.adjusted() - other.adjusted()
+        if not self or other._isinfinity() or expdiff <= -2:
+            return (_dec_from_triple(sign, '0', 0),
+                    self._rescale(ideal_exp, context.rounding))
+        if expdiff <= context.prec:
+            op1 = _WorkRep(self)
+            op2 = _WorkRep(other)
+            if op1.exp >= op2.exp:
+                op1.int *= 10**(op1.exp - op2.exp)
+            else:
+                op2.int *= 10**(op2.exp - op1.exp)
+            q, r = divmod(op1.int, op2.int)
+            if q < 10**context.prec:
+                return (_dec_from_triple(sign, str(q), 0),
+                        _dec_from_triple(self._sign, str(r), ideal_exp))
+
+        # Here the quotient is too large to be representable
+        ans = context._raise_error(DivisionImpossible,
+                                   'quotient too large in //, % or divmod')
+        return ans, ans
+
+    def __rtruediv__(self, other, context=None):
+        """Swaps self/other and returns __truediv__."""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+        return other.__truediv__(self, context=context)
+
+    __div__ = __truediv__
+    __rdiv__ = __rtruediv__
+
+    def __divmod__(self, other, context=None):
+        """
+        Return (self // other, self % other)
+        """
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+
+        if context is None:
+            context = getcontext()
+
+        ans = self._check_nans(other, context)
+        if ans:
+            return (ans, ans)
+
+        sign = self._sign ^ other._sign
+        if self._isinfinity():
+            if other._isinfinity():
+                ans = context._raise_error(InvalidOperation, 'divmod(INF, INF)')
+                return ans, ans
+            else:
+                return (_SignedInfinity[sign],
+                        context._raise_error(InvalidOperation, 'INF % x'))
+
+        if not other:
+            if not self:
+                ans = context._raise_error(DivisionUndefined, 'divmod(0, 0)')
+                return ans, ans
+            else:
+                return (context._raise_error(DivisionByZero, 'x // 0', sign),
+                        context._raise_error(InvalidOperation, 'x % 0'))
+
+        quotient, remainder = self._divide(other, context)
+        remainder = remainder._fix(context)
+        return quotient, remainder
+
+    def __rdivmod__(self, other, context=None):
+        """Swaps self/other and returns __divmod__."""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+        return other.__divmod__(self, context=context)
+
+    def __mod__(self, other, context=None):
+        """
+        self % other
+        """
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+
+        if context is None:
+            context = getcontext()
+
+        ans = self._check_nans(other, context)
+        if ans:
+            return ans
+
+        if self._isinfinity():
+            return context._raise_error(InvalidOperation, 'INF % x')
+        elif not other:
+            if self:
+                return context._raise_error(InvalidOperation, 'x % 0')
+            else:
+                return context._raise_error(DivisionUndefined, '0 % 0')
+
+        remainder = self._divide(other, context)[1]
+        remainder = remainder._fix(context)
+        return remainder
+
+    def __rmod__(self, other, context=None):
+        """Swaps self/other and returns __mod__."""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+        return other.__mod__(self, context=context)
+
+    def remainder_near(self, other, context=None):
+        """
+        Remainder nearest to 0-  abs(remainder-near) <= other/2
+        """
+        if context is None:
+            context = getcontext()
+
+        other = _convert_other(other, raiseit=True)
+
+        ans = self._check_nans(other, context)
+        if ans:
+            return ans
+
+        # self == +/-infinity -> InvalidOperation
+        if self._isinfinity():
+            return context._raise_error(InvalidOperation,
+                                        'remainder_near(infinity, x)')
+
+        # other == 0 -> either InvalidOperation or DivisionUndefined
+        if not other:
+            if self:
+                return context._raise_error(InvalidOperation,
+                                            'remainder_near(x, 0)')
+            else:
+                return context._raise_error(DivisionUndefined,
+                                            'remainder_near(0, 0)')
+
+        # other = +/-infinity -> remainder = self
+        if other._isinfinity():
+            ans = Decimal(self)
+            return ans._fix(context)
+
+        # self = 0 -> remainder = self, with ideal exponent
+        ideal_exponent = min(self._exp, other._exp)
+        if not self:
+            ans = _dec_from_triple(self._sign, '0', ideal_exponent)
+            return ans._fix(context)
+
+        # catch most cases of large or small quotient
+        expdiff = self.adjusted() - other.adjusted()
+        if expdiff >= context.prec + 1:
+            # expdiff >= prec+1 => abs(self/other) > 10**prec
+            return context._raise_error(DivisionImpossible)
+        if expdiff <= -2:
+            # expdiff <= -2 => abs(self/other) < 0.1
+            ans = self._rescale(ideal_exponent, context.rounding)
+            return ans._fix(context)
+
+        # adjust both arguments to have the same exponent, then divide
+        op1 = _WorkRep(self)
+        op2 = _WorkRep(other)
+        if op1.exp >= op2.exp:
+            op1.int *= 10**(op1.exp - op2.exp)
+        else:
+            op2.int *= 10**(op2.exp - op1.exp)
+        q, r = divmod(op1.int, op2.int)
+        # remainder is r*10**ideal_exponent; other is +/-op2.int *
+        # 10**ideal_exponent.   Apply correction to ensure that
+        # abs(remainder) <= abs(other)/2
+        if 2*r + (q&1) > op2.int:
+            r -= op2.int
+            q += 1
+
+        if q >= 10**context.prec:
+            return context._raise_error(DivisionImpossible)
+
+        # result has same sign as self unless r is negative
+        sign = self._sign
+        if r < 0:
+            sign = 1-sign
+            r = -r
+
+        ans = _dec_from_triple(sign, str(r), ideal_exponent)
+        return ans._fix(context)
+
+    def __floordiv__(self, other, context=None):
+        """self // other"""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+
+        if context is None:
+            context = getcontext()
+
+        ans = self._check_nans(other, context)
+        if ans:
+            return ans
+
+        if self._isinfinity():
+            if other._isinfinity():
+                return context._raise_error(InvalidOperation, 'INF // INF')
+            else:
+                return _SignedInfinity[self._sign ^ other._sign]
+
+        if not other:
+            if self:
+                return context._raise_error(DivisionByZero, 'x // 0',
+                                            self._sign ^ other._sign)
+            else:
+                return context._raise_error(DivisionUndefined, '0 // 0')
+
+        return self._divide(other, context)[0]
+
+    def __rfloordiv__(self, other, context=None):
+        """Swaps self/other and returns __floordiv__."""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+        return other.__floordiv__(self, context=context)
+
+    def __float__(self):
+        """Float representation."""
+        if self._isnan():
+            if self.is_snan():
+                raise ValueError("Cannot convert signaling NaN to float")
+            s = "-nan" if self._sign else "nan"
+        else:
+            s = str(self)
+        return float(s)
+
+    def __int__(self):
+        """Converts self to an int, truncating if necessary."""
+        if self._is_special:
+            if self._isnan():
+                raise ValueError("Cannot convert NaN to integer")
+            elif self._isinfinity():
+                raise OverflowError("Cannot convert infinity to integer")
+        s = (-1)**self._sign
+        if self._exp >= 0:
+            return s*int(self._int)*10**self._exp
+        else:
+            return s*int(self._int[:self._exp] or '0')
+
+    __trunc__ = __int__
+
+    def real(self):
+        return self
+    real = property(real)
+
+    def imag(self):
+        return Decimal(0)
+    imag = property(imag)
+
+    def conjugate(self):
+        return self
+
+    def __complex__(self):
+        return complex(float(self))
+
+    def __long__(self):
+        """Converts to a long.
+
+        Equivalent to long(int(self))
+        """
+        return long(self.__int__())
+
+    def _fix_nan(self, context):
+        """Decapitate the payload of a NaN to fit the context"""
+        payload = self._int
+
+        # maximum length of payload is precision if _clamp=0,
+        # precision-1 if _clamp=1.
+        max_payload_len = context.prec - context._clamp
+        if len(payload) > max_payload_len:
+            payload = payload[len(payload)-max_payload_len:].lstrip('0')
+            return _dec_from_triple(self._sign, payload, self._exp, True)
+        return Decimal(self)
+
+    def _fix(self, context):
+        """Round if it is necessary to keep self within prec precision.
+
+        Rounds and fixes the exponent.  Does not raise on a sNaN.
+
+        Arguments:
+        self - Decimal instance
+        context - context used.
+        """
+
+        if self._is_special:
+            if self._isnan():
+                # decapitate payload if necessary
+                return self._fix_nan(context)
+            else:
+                # self is +/-Infinity; return unaltered
+                return Decimal(self)
+
+        # if self is zero then exponent should be between Etiny and
+        # Emax if _clamp==0, and between Etiny and Etop if _clamp==1.
+        Etiny = context.Etiny()
+        Etop = context.Etop()
+        if not self:
+            exp_max = [context.Emax, Etop][context._clamp]
+            new_exp = min(max(self._exp, Etiny), exp_max)
+            if new_exp != self._exp:
+                context._raise_error(Clamped)
+                return _dec_from_triple(self._sign, '0', new_exp)
+            else:
+                return Decimal(self)
+
+        # exp_min is the smallest allowable exponent of the result,
+        # equal to max(self.adjusted()-context.prec+1, Etiny)
+        exp_min = len(self._int) + self._exp - context.prec
+        if exp_min > Etop:
+            # overflow: exp_min > Etop iff self.adjusted() > Emax
+            ans = context._raise_error(Overflow, 'above Emax', self._sign)
+            context._raise_error(Inexact)
+            context._raise_error(Rounded)
+            return ans
+
+        self_is_subnormal = exp_min < Etiny
+        if self_is_subnormal:
+            exp_min = Etiny
+
+        # round if self has too many digits
+        if self._exp < exp_min:
+            digits = len(self._int) + self._exp - exp_min
+            if digits < 0:
+                self = _dec_from_triple(self._sign, '1', exp_min-1)
+                digits = 0
+            rounding_method = self._pick_rounding_function[context.rounding]
+            changed = getattr(self, rounding_method)(digits)
+            coeff = self._int[:digits] or '0'
+            if changed > 0:
+                coeff = str(int(coeff)+1)
+                if len(coeff) > context.prec:
+                    coeff = coeff[:-1]
+                    exp_min += 1
+
+            # check whether the rounding pushed the exponent out of range
+            if exp_min > Etop:
+                ans = context._raise_error(Overflow, 'above Emax', self._sign)
+            else:
+                ans = _dec_from_triple(self._sign, coeff, exp_min)
+
+            # raise the appropriate signals, taking care to respect
+            # the precedence described in the specification
+            if changed and self_is_subnormal:
+                context._raise_error(Underflow)
+            if self_is_subnormal:
+                context._raise_error(Subnormal)
+            if changed:
+                context._raise_error(Inexact)
+            context._raise_error(Rounded)
+            if not ans:
+                # raise Clamped on underflow to 0
+                context._raise_error(Clamped)
+            return ans
+
+        if self_is_subnormal:
+            context._raise_error(Subnormal)
+
+        # fold down if _clamp == 1 and self has too few digits
+        if context._clamp == 1 and self._exp > Etop:
+            context._raise_error(Clamped)
+            self_padded = self._int + '0'*(self._exp - Etop)
+            return _dec_from_triple(self._sign, self_padded, Etop)
+
+        # here self was representable to begin with; return unchanged
+        return Decimal(self)
+
+    _pick_rounding_function = {}
+
+    # for each of the rounding functions below:
+    #   self is a finite, nonzero Decimal
+    #   prec is an integer satisfying 0 <= prec < len(self._int)
+    #
+    # each function returns either -1, 0, or 1, as follows:
+    #   1 indicates that self should be rounded up (away from zero)
+    #   0 indicates that self should be truncated, and that all the
+    #     digits to be truncated are zeros (so the value is unchanged)
+    #  -1 indicates that there are nonzero digits to be truncated
+
+    def _round_down(self, prec):
+        """Also known as round-towards-0, truncate."""
+        if _all_zeros(self._int, prec):
+            return 0
+        else:
+            return -1
+
+    def _round_up(self, prec):
+        """Rounds away from 0."""
+        return -self._round_down(prec)
+
+    def _round_half_up(self, prec):
+        """Rounds 5 up (away from 0)"""
+        if self._int[prec] in '56789':
+            return 1
+        elif _all_zeros(self._int, prec):
+            return 0
+        else:
+            return -1
+
+    def _round_half_down(self, prec):
+        """Round 5 down"""
+        if _exact_half(self._int, prec):
+            return -1
+        else:
+            return self._round_half_up(prec)
+
+    def _round_half_even(self, prec):
+        """Round 5 to even, rest to nearest."""
+        if _exact_half(self._int, prec) and \
+                (prec == 0 or self._int[prec-1] in '02468'):
+            return -1
+        else:
+            return self._round_half_up(prec)
+
+    def _round_ceiling(self, prec):
+        """Rounds up (not away from 0 if negative.)"""
+        if self._sign:
+            return self._round_down(prec)
+        else:
+            return -self._round_down(prec)
+
+    def _round_floor(self, prec):
+        """Rounds down (not towards 0 if negative)"""
+        if not self._sign:
+            return self._round_down(prec)
+        else:
+            return -self._round_down(prec)
+
+    def _round_05up(self, prec):
+        """Round down unless digit prec-1 is 0 or 5."""
+        if prec and self._int[prec-1] not in '05':
+            return self._round_down(prec)
+        else:
+            return -self._round_down(prec)
+
+    def fma(self, other, third, context=None):
+        """Fused multiply-add.
+
+        Returns self*other+third with no rounding of the intermediate
+        product self*other.
+
+        self and other are multiplied together, with no rounding of
+        the result.  The third operand is then added to the result,
+        and a single final rounding is performed.
+        """
+
+        other = _convert_other(other, raiseit=True)
+
+        # compute product; raise InvalidOperation if either operand is
+        # a signaling NaN or if the product is zero times infinity.
+        if self._is_special or other._is_special:
+            if context is None:
+                context = getcontext()
+            if self._exp == 'N':
+                return context._raise_error(InvalidOperation, 'sNaN', self)
+            if other._exp == 'N':
+                return context._raise_error(InvalidOperation, 'sNaN', other)
+            if self._exp == 'n':
+                product = self
+            elif other._exp == 'n':
+                product = other
+            elif self._exp == 'F':
+                if not other:
+                    return context._raise_error(InvalidOperation,
+                                                'INF * 0 in fma')
+                product = _SignedInfinity[self._sign ^ other._sign]
+            elif other._exp == 'F':
+                if not self:
+                    return context._raise_error(InvalidOperation,
+                                                '0 * INF in fma')
+                product = _SignedInfinity[self._sign ^ other._sign]
+        else:
+            product = _dec_from_triple(self._sign ^ other._sign,
+                                       str(int(self._int) * int(other._int)),
+                                       self._exp + other._exp)
+
+        third = _convert_other(third, raiseit=True)
+        return product.__add__(third, context)
+
+    def _power_modulo(self, other, modulo, context=None):
+        """Three argument version of __pow__"""
+
+        # if can't convert other and modulo to Decimal, raise
+        # TypeError; there's no point returning NotImplemented (no
+        # equivalent of __rpow__ for three argument pow)
+        other = _convert_other(other, raiseit=True)
+        modulo = _convert_other(modulo, raiseit=True)
+
+        if context is None:
+            context = getcontext()
+
+        # deal with NaNs: if there are any sNaNs then first one wins,
+        # (i.e. behaviour for NaNs is identical to that of fma)
+        self_is_nan = self._isnan()
+        other_is_nan = other._isnan()
+        modulo_is_nan = modulo._isnan()
+        if self_is_nan or other_is_nan or modulo_is_nan:
+            if self_is_nan == 2:
+                return context._raise_error(InvalidOperation, 'sNaN',
+                                        self)
+            if other_is_nan == 2:
+                return context._raise_error(InvalidOperation, 'sNaN',
+                                        other)
+            if modulo_is_nan == 2:
+                return context._raise_error(InvalidOperation, 'sNaN',
+                                        modulo)
+            if self_is_nan:
+                return self._fix_nan(context)
+            if other_is_nan:
+                return other._fix_nan(context)
+            return modulo._fix_nan(context)
+
+        # check inputs: we apply same restrictions as Python's pow()
+        if not (self._isinteger() and
+                other._isinteger() and
+                modulo._isinteger()):
+            return context._raise_error(InvalidOperation,
+                                        'pow() 3rd argument not allowed '
+                                        'unless all arguments are integers')
+        if other < 0:
+            return context._raise_error(InvalidOperation,
+                                        'pow() 2nd argument cannot be '
+                                        'negative when 3rd argument specified')
+        if not modulo:
+            return context._raise_error(InvalidOperation,
+                                        'pow() 3rd argument cannot be 0')
+
+        # additional restriction for decimal: the modulus must be less
+        # than 10**prec in absolute value
+        if modulo.adjusted() >= context.prec:
+            return context._raise_error(InvalidOperation,
+                                        'insufficient precision: pow() 3rd '
+                                        'argument must not have more than '
+                                        'precision digits')
+
+        # define 0**0 == NaN, for consistency with two-argument pow
+        # (even though it hurts!)
+        if not other and not self:
+            return context._raise_error(InvalidOperation,
+                                        'at least one of pow() 1st argument '
+                                        'and 2nd argument must be nonzero ;'
+                                        '0**0 is not defined')
+
+        # compute sign of result
+        if other._iseven():
+            sign = 0
+        else:
+            sign = self._sign
+
+        # convert modulo to a Python integer, and self and other to
+        # Decimal integers (i.e. force their exponents to be >= 0)
+        modulo = abs(int(modulo))
+        base = _WorkRep(self.to_integral_value())
+        exponent = _WorkRep(other.to_integral_value())
+
+        # compute result using integer pow()
+        base = (base.int % modulo * pow(10, base.exp, modulo)) % modulo
+        for i in xrange(exponent.exp):
+            base = pow(base, 10, modulo)
+        base = pow(base, exponent.int, modulo)
+
+        return _dec_from_triple(sign, str(base), 0)
+
+    def _power_exact(self, other, p):
+        """Attempt to compute self**other exactly.
+
+        Given Decimals self and other and an integer p, attempt to
+        compute an exact result for the power self**other, with p
+        digits of precision.  Return None if self**other is not
+        exactly representable in p digits.
+
+        Assumes that elimination of special cases has already been
+        performed: self and other must both be nonspecial; self must
+        be positive and not numerically equal to 1; other must be
+        nonzero.  For efficiency, other._exp should not be too large,
+        so that 10**abs(other._exp) is a feasible calculation."""
+
+        # In the comments below, we write x for the value of self and
+        # y for the value of other.  Write x = xc*10**xe and y =
+        # yc*10**ye.
+
+        # The main purpose of this method is to identify the *failure*
+        # of x**y to be exactly representable with as little effort as
+        # possible.  So we look for cheap and easy tests that
+        # eliminate the possibility of x**y being exact.  Only if all
+        # these tests are passed do we go on to actually compute x**y.
+
+        # Here's the main idea.  First normalize both x and y.  We
+        # express y as a rational m/n, with m and n relatively prime
+        # and n>0.  Then for x**y to be exactly representable (at
+        # *any* precision), xc must be the nth power of a positive
+        # integer and xe must be divisible by n.  If m is negative
+        # then additionally xc must be a power of either 2 or 5, hence
+        # a power of 2**n or 5**n.
+        #
+        # There's a limit to how small |y| can be: if y=m/n as above
+        # then:
+        #
+        #  (1) if xc != 1 then for the result to be representable we
+        #      need xc**(1/n) >= 2, and hence also xc**|y| >= 2.  So
+        #      if |y| <= 1/nbits(xc) then xc < 2**nbits(xc) <=
+        #      2**(1/|y|), hence xc**|y| < 2 and the result is not
+        #      representable.
+        #
+        #  (2) if xe != 0, |xe|*(1/n) >= 1, so |xe|*|y| >= 1.  Hence if
+        #      |y| < 1/|xe| then the result is not representable.
+        #
+        # Note that since x is not equal to 1, at least one of (1) and
+        # (2) must apply.  Now |y| < 1/nbits(xc) iff |yc|*nbits(xc) <
+        # 10**-ye iff len(str(|yc|*nbits(xc)) <= -ye.
+        #
+        # There's also a limit to how large y can be, at least if it's
+        # positive: the normalized result will have coefficient xc**y,
+        # so if it's representable then xc**y < 10**p, and y <
+        # p/log10(xc).  Hence if y*log10(xc) >= p then the result is
+        # not exactly representable.
+
+        # if len(str(abs(yc*xe)) <= -ye then abs(yc*xe) < 10**-ye,
+        # so |y| < 1/xe and the result is not representable.
+        # Similarly, len(str(abs(yc)*xc_bits)) <= -ye implies |y|
+        # < 1/nbits(xc).
+
+        x = _WorkRep(self)
+        xc, xe = x.int, x.exp
+        while xc % 10 == 0:
+            xc //= 10
+            xe += 1
+
+        y = _WorkRep(other)
+        yc, ye = y.int, y.exp
+        while yc % 10 == 0:
+            yc //= 10
+            ye += 1
+
+        # case where xc == 1: result is 10**(xe*y), with xe*y
+        # required to be an integer
+        if xc == 1:
+            xe *= yc
+            # result is now 10**(xe * 10**ye);  xe * 10**ye must be integral
+            while xe % 10 == 0:
+                xe //= 10
+                ye += 1
+            if ye < 0:
+                return None
+            exponent = xe * 10**ye
+            if y.sign == 1:
+                exponent = -exponent
+            # if other is a nonnegative integer, use ideal exponent
+            if other._isinteger() and other._sign == 0:
+                ideal_exponent = self._exp*int(other)
+                zeros = min(exponent-ideal_exponent, p-1)
+            else:
+                zeros = 0
+            return _dec_from_triple(0, '1' + '0'*zeros, exponent-zeros)
+
+        # case where y is negative: xc must be either a power
+        # of 2 or a power of 5.
+        if y.sign == 1:
+            last_digit = xc % 10
+            if last_digit in (2,4,6,8):
+                # quick test for power of 2
+                if xc & -xc != xc:
+                    return None
+                # now xc is a power of 2; e is its exponent
+                e = _nbits(xc)-1
+                # find e*y and xe*y; both must be integers
+                if ye >= 0:
+                    y_as_int = yc*10**ye
+                    e = e*y_as_int
+                    xe = xe*y_as_int
+                else:
+                    ten_pow = 10**-ye
+                    e, remainder = divmod(e*yc, ten_pow)
+                    if remainder:
+                        return None
+                    xe, remainder = divmod(xe*yc, ten_pow)
+                    if remainder:
+                        return None
+
+                if e*65 >= p*93: # 93/65 > log(10)/log(5)
+                    return None
+                xc = 5**e
+
+            elif last_digit == 5:
+                # e >= log_5(xc) if xc is a power of 5; we have
+                # equality all the way up to xc=5**2658
+                e = _nbits(xc)*28//65
+                xc, remainder = divmod(5**e, xc)
+                if remainder:
+                    return None
+                while xc % 5 == 0:
+                    xc //= 5
+                    e -= 1
+                if ye >= 0:
+                    y_as_integer = yc*10**ye
+                    e = e*y_as_integer
+                    xe = xe*y_as_integer
+                else:
+                    ten_pow = 10**-ye
+                    e, remainder = divmod(e*yc, ten_pow)
+                    if remainder:
+                        return None
+                    xe, remainder = divmod(xe*yc, ten_pow)
+                    if remainder:
+                        return None
+                if e*3 >= p*10: # 10/3 > log(10)/log(2)
+                    return None
+                xc = 2**e
+            else:
+                return None
+
+            if xc >= 10**p:
+                return None
+            xe = -e-xe
+            return _dec_from_triple(0, str(xc), xe)
+
+        # now y is positive; find m and n such that y = m/n
+        if ye >= 0:
+            m, n = yc*10**ye, 1
+        else:
+            if xe != 0 and len(str(abs(yc*xe))) <= -ye:
+                return None
+            xc_bits = _nbits(xc)
+            if xc != 1 and len(str(abs(yc)*xc_bits)) <= -ye:
+                return None
+            m, n = yc, 10**(-ye)
+            while m % 2 == n % 2 == 0:
+                m //= 2
+                n //= 2
+            while m % 5 == n % 5 == 0:
+                m //= 5
+                n //= 5
+
+        # compute nth root of xc*10**xe
+        if n > 1:
+            # if 1 < xc < 2**n then xc isn't an nth power
+            if xc != 1 and xc_bits <= n:
+                return None
+
+            xe, rem = divmod(xe, n)
+            if rem != 0:
+                return None
+
+            # compute nth root of xc using Newton's method
+            a = 1L << -(-_nbits(xc)//n) # initial estimate
+            while True:
+                q, r = divmod(xc, a**(n-1))
+                if a <= q:
+                    break
+                else:
+                    a = (a*(n-1) + q)//n
+            if not (a == q and r == 0):
+                return None
+            xc = a
+
+        # now xc*10**xe is the nth root of the original xc*10**xe
+        # compute mth power of xc*10**xe
+
+        # if m > p*100//_log10_lb(xc) then m > p/log10(xc), hence xc**m >
+        # 10**p and the result is not representable.
+        if xc > 1 and m > p*100//_log10_lb(xc):
+            return None
+        xc = xc**m
+        xe *= m
+        if xc > 10**p:
+            return None
+
+        # by this point the result *is* exactly representable
+        # adjust the exponent to get as close as possible to the ideal
+        # exponent, if necessary
+        str_xc = str(xc)
+        if other._isinteger() and other._sign == 0:
+            ideal_exponent = self._exp*int(other)
+            zeros = min(xe-ideal_exponent, p-len(str_xc))
+        else:
+            zeros = 0
+        return _dec_from_triple(0, str_xc+'0'*zeros, xe-zeros)
+
+    def __pow__(self, other, modulo=None, context=None):
+        """Return self ** other [ % modulo].
+
+        With two arguments, compute self**other.
+
+        With three arguments, compute (self**other) % modulo.  For the
+        three argument form, the following restrictions on the
+        arguments hold:
+
+         - all three arguments must be integral
+         - other must be nonnegative
+         - either self or other (or both) must be nonzero
+         - modulo must be nonzero and must have at most p digits,
+           where p is the context precision.
+
+        If any of these restrictions is violated the InvalidOperation
+        flag is raised.
+
+        The result of pow(self, other, modulo) is identical to the
+        result that would be obtained by computing (self**other) %
+        modulo with unbounded precision, but is computed more
+        efficiently.  It is always exact.
+        """
+
+        if modulo is not None:
+            return self._power_modulo(other, modulo, context)
+
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+
+        if context is None:
+            context = getcontext()
+
+        # either argument is a NaN => result is NaN
+        ans = self._check_nans(other, context)
+        if ans:
+            return ans
+
+        # 0**0 = NaN (!), x**0 = 1 for nonzero x (including +/-Infinity)
+        if not other:
+            if not self:
+                return context._raise_error(InvalidOperation, '0 ** 0')
+            else:
+                return _One
+
+        # result has sign 1 iff self._sign is 1 and other is an odd integer
+        result_sign = 0
+        if self._sign == 1:
+            if other._isinteger():
+                if not other._iseven():
+                    result_sign = 1
+            else:
+                # -ve**noninteger = NaN
+                # (-0)**noninteger = 0**noninteger
+                if self:
+                    return context._raise_error(InvalidOperation,
+                        'x ** y with x negative and y not an integer')
+            # negate self, without doing any unwanted rounding
+            self = self.copy_negate()
+
+        # 0**(+ve or Inf)= 0; 0**(-ve or -Inf) = Infinity
+        if not self:
+            if other._sign == 0:
+                return _dec_from_triple(result_sign, '0', 0)
+            else:
+                return _SignedInfinity[result_sign]
+
+        # Inf**(+ve or Inf) = Inf; Inf**(-ve or -Inf) = 0
+        if self._isinfinity():
+            if other._sign == 0:
+                return _SignedInfinity[result_sign]
+            else:
+                return _dec_from_triple(result_sign, '0', 0)
+
+        # 1**other = 1, but the choice of exponent and the flags
+        # depend on the exponent of self, and on whether other is a
+        # positive integer, a negative integer, or neither
+        if self == _One:
+            if other._isinteger():
+                # exp = max(self._exp*max(int(other), 0),
+                # 1-context.prec) but evaluating int(other) directly
+                # is dangerous until we know other is small (other
+                # could be 1e999999999)
+                if other._sign == 1:
+                    multiplier = 0
+                elif other > context.prec:
+                    multiplier = context.prec
+                else:
+                    multiplier = int(other)
+
+                exp = self._exp * multiplier
+                if exp < 1-context.prec:
+                    exp = 1-context.prec
+                    context._raise_error(Rounded)
+            else:
+                context._raise_error(Inexact)
+                context._raise_error(Rounded)
+                exp = 1-context.prec
+
+            return _dec_from_triple(result_sign, '1'+'0'*-exp, exp)
+
+        # compute adjusted exponent of self
+        self_adj = self.adjusted()
+
+        # self ** infinity is infinity if self > 1, 0 if self < 1
+        # self ** -infinity is infinity if self < 1, 0 if self > 1
+        if other._isinfinity():
+            if (other._sign == 0) == (self_adj < 0):
+                return _dec_from_triple(result_sign, '0', 0)
+            else:
+                return _SignedInfinity[result_sign]
+
+        # from here on, the result always goes through the call
+        # to _fix at the end of this function.
+        ans = None
+        exact = False
+
+        # crude test to catch cases of extreme overflow/underflow.  If
+        # log10(self)*other >= 10**bound and bound >= len(str(Emax))
+        # then 10**bound >= 10**len(str(Emax)) >= Emax+1 and hence
+        # self**other >= 10**(Emax+1), so overflow occurs.  The test
+        # for underflow is similar.
+        bound = self._log10_exp_bound() + other.adjusted()
+        if (self_adj >= 0) == (other._sign == 0):
+            # self > 1 and other +ve, or self < 1 and other -ve
+            # possibility of overflow
+            if bound >= len(str(context.Emax)):
+                ans = _dec_from_triple(result_sign, '1', context.Emax+1)
+        else:
+            # self > 1 and other -ve, or self < 1 and other +ve
+            # possibility of underflow to 0
+            Etiny = context.Etiny()
+            if bound >= len(str(-Etiny)):
+                ans = _dec_from_triple(result_sign, '1', Etiny-1)
+
+        # try for an exact result with precision +1
+        if ans is None:
+            ans = self._power_exact(other, context.prec + 1)
+            if ans is not None:
+                if result_sign == 1:
+                    ans = _dec_from_triple(1, ans._int, ans._exp)
+                exact = True
+
+        # usual case: inexact result, x**y computed directly as exp(y*log(x))
+        if ans is None:
+            p = context.prec
+            x = _WorkRep(self)
+            xc, xe = x.int, x.exp
+            y = _WorkRep(other)
+            yc, ye = y.int, y.exp
+            if y.sign == 1:
+                yc = -yc
+
+            # compute correctly rounded result:  start with precision +3,
+            # then increase precision until result is unambiguously roundable
+            extra = 3
+            while True:
+                coeff, exp = _dpower(xc, xe, yc, ye, p+extra)
+                if coeff % (5*10**(len(str(coeff))-p-1)):
+                    break
+                extra += 3
+
+            ans = _dec_from_triple(result_sign, str(coeff), exp)
+
+        # unlike exp, ln and log10, the power function respects the
+        # rounding mode; no need to switch to ROUND_HALF_EVEN here
+
+        # There's a difficulty here when 'other' is not an integer and
+        # the result is exact.  In this case, the specification
+        # requires that the Inexact flag be raised (in spite of
+        # exactness), but since the result is exact _fix won't do this
+        # for us.  (Correspondingly, the Underflow signal should also
+        # be raised for subnormal results.)  We can't directly raise
+        # these signals either before or after calling _fix, since
+        # that would violate the precedence for signals.  So we wrap
+        # the ._fix call in a temporary context, and reraise
+        # afterwards.
+        if exact and not other._isinteger():
+            # pad with zeros up to length context.prec+1 if necessary; this
+            # ensures that the Rounded signal will be raised.
+            if len(ans._int) <= context.prec:
+                expdiff = context.prec + 1 - len(ans._int)
+                ans = _dec_from_triple(ans._sign, ans._int+'0'*expdiff,
+                                       ans._exp-expdiff)
+
+            # create a copy of the current context, with cleared flags/traps
+            newcontext = context.copy()
+            newcontext.clear_flags()
+            for exception in _signals:
+                newcontext.traps[exception] = 0
+
+            # round in the new context
+            ans = ans._fix(newcontext)
+
+            # raise Inexact, and if necessary, Underflow
+            newcontext._raise_error(Inexact)
+            if newcontext.flags[Subnormal]:
+                newcontext._raise_error(Underflow)
+
+            # propagate signals to the original context; _fix could
+            # have raised any of Overflow, Underflow, Subnormal,
+            # Inexact, Rounded, Clamped.  Overflow needs the correct
+            # arguments.  Note that the order of the exceptions is
+            # important here.
+            if newcontext.flags[Overflow]:
+                context._raise_error(Overflow, 'above Emax', ans._sign)
+            for exception in Underflow, Subnormal, Inexact, Rounded, Clamped:
+                if newcontext.flags[exception]:
+                    context._raise_error(exception)
+
+        else:
+            ans = ans._fix(context)
+
+        return ans
+
+    def __rpow__(self, other, context=None):
+        """Swaps self/other and returns __pow__."""
+        other = _convert_other(other)
+        if other is NotImplemented:
+            return other
+        return other.__pow__(self, context=context)
+
+    def normalize(self, context=None):
+        """Normalize- strip trailing 0s, change anything equal to 0 to 0e0"""
+
+        if context is None:
+            context = getcontext()
+
+        if self._is_special:
+            ans = self._check_nans(context=context)
+            if ans:
+                return ans
+
+        dup = self._fix(context)
+        if dup._isinfinity():
+            return dup
+
+        if not dup:
+            return _dec_from_triple(dup._sign, '0', 0)
+        exp_max = [context.Emax, context.Etop()][context._clamp]
+        end = len(dup._int)
+        exp = dup._exp
+        while dup._int[end-1] == '0' and exp < exp_max:
+            exp += 1
+            end -= 1
+        return _dec_from_triple(dup._sign, dup._int[:end], exp)
+
+    def quantize(self, exp, rounding=None, context=None, watchexp=True):
+        """Quantize self so its exponent is the same as that of exp.
+
+        Similar to self._rescale(exp._exp) but with error checking.
+        """
+        exp = _convert_other(exp, raiseit=True)
+
+        if context is None:
+            context = getcontext()
+        if rounding is None:
+            rounding = context.rounding
+
+        if self._is_special or exp._is_special:
+            ans = self._check_nans(exp, context)
+            if ans:
+                return ans
+
+            if exp._isinfinity() or self._isinfinity():
+                if exp._isinfinity() and self._isinfinity():
+                    return Decimal(self)  # if both are inf, it is OK
+                return context._raise_error(InvalidOperation,
+                                        'quantize with one INF')
+
+        # if we're not watching exponents, do a simple rescale
+        if not watchexp:
+            ans = self._rescale(exp._exp, rounding)
+            # raise Inexact and Rounded where appropriate
+            if ans._exp > self._exp:
+                context._raise_error(Rounded)
+                if ans != self:
+                    context._raise_error(Inexact)
+            return ans
+
+        # exp._exp should be between Etiny and Emax
+        if not (context.Etiny() <= exp._exp <= context.Emax):
+            return context._raise_error(InvalidOperation,
+                   'target exponent out of bounds in quantize')
+
+        if not self:
+            ans = _dec_from_triple(self._sign, '0', exp._exp)
+            return ans._fix(context)
+
+        self_adjusted = self.adjusted()
+        if self_adjusted > context.Emax:
+            return context._raise_error(InvalidOperation,
+                                        'exponent of quantize result too large for current context')
+        if self_adjusted - exp._exp + 1 > context.prec:
+            return context._raise_error(InvalidOperation,
+                                        'quantize result has too many digits for current context')
+
+        ans = self._rescale(exp._exp, rounding)
+        if ans.adjusted() > context.Emax:
+            return context._raise_error(InvalidOperation,
+                                        'exponent of quantize result too large for current context')
+        if len(ans._int) > context.prec:
+            return context._raise_error(InvalidOperation,
+                                        'quantize result has too many digits for current context')
+
+        # raise appropriate flags
+        if ans and ans.adjusted() < context.Emin:
+            context._raise_error(Subnormal)
+        if ans._exp > self._exp:
+            if ans != self:
+                context._raise_error(Inexact)
+            context._raise_error(Rounded)
+
+        # call to fix takes care of any necessary folddown, and
+        # signals Clamped if necessary
+        ans = ans._fix(context)
+        return ans
+
+    def same_quantum(self, other):
+        """Return True if self and other have the same exponent; otherwise
+        return False.
+
+        If either operand is a special value, the following rules are used:
+           * return True if both operands are infinities
+           * return True if both operands are NaNs
+           * otherwise, return False.
+        """
+        other = _convert_other(other, raiseit=True)
+        if self._is_special or other._is_special:
+            return (self.is_nan() and other.is_nan() or
+                    self.is_infinite() and other.is_infinite())
+        return self._exp == other._exp
+
+    def _rescale(self, exp, rounding):
+        """Rescale self so that the exponent is exp, either by padding with zeros
+        or by truncating digits, using the given rounding mode.
+
+        Specials are returned without change.  This operation is
+        quiet: it raises no flags, and uses no information from the
+        context.
+
+        exp = exp to scale to (an integer)
+        rounding = rounding mode
+        """
+        if self._is_special:
+            return Decimal(self)
+        if not self:
+            return _dec_from_triple(self._sign, '0', exp)
+
+        if self._exp >= exp:
+            # pad answer with zeros if necessary
+            return _dec_from_triple(self._sign,
+                                        self._int + '0'*(self._exp - exp), exp)
+
+        # too many digits; round and lose data.  If self.adjusted() <
+        # exp-1, replace self by 10**(exp-1) before rounding
+        digits = len(self._int) + self._exp - exp
+        if digits < 0:
+            self = _dec_from_triple(self._sign, '1', exp-1)
+            digits = 0
+        this_function = getattr(self, self._pick_rounding_function[rounding])
+        changed = this_function(digits)
+        coeff = self._int[:digits] or '0'
+        if changed == 1:
+            coeff = str(int(coeff)+1)
+        return _dec_from_triple(self._sign, coeff, exp)
+
+    def _round(self, places, rounding):
+        """Round a nonzero, nonspecial Decimal to a fixed number of
+        significant figures, using the given rounding mode.
+
+        Infinities, NaNs and zeros are returned unaltered.
+
+        This operation is quiet: it raises no flags, and uses no
+        information from the context.
+
+        """
+        if places <= 0:
+            raise ValueError("argument should be at least 1 in _round")
+        if self._is_special or not self:
+            return Decimal(self)
+        ans = self._rescale(self.adjusted()+1-places, rounding)
+        # it can happen that the rescale alters the adjusted exponent;
+        # for example when rounding 99.97 to 3 significant figures.
+        # When this happens we end up with an extra 0 at the end of
+        # the number; a second rescale fixes this.
+        if ans.adjusted() != self.adjusted():
+            ans = ans._rescale(ans.adjusted()+1-places, rounding)
+        return ans
+
+    def to_integral_exact(self, rounding=None, context=None):
+        """Rounds to a nearby integer.
+
+        If no rounding mode is specified, take the rounding mode from
+        the context.  This method raises the Rounded and Inexact flags
+        when appropriate.
+
+        See also: to_integral_value, which does exactly the same as
+        this method except that it doesn't raise Inexact or Rounded.
+        """
+        if self._is_special:
+            ans = self._check_nans(context=context)
+            if ans:
+                return ans
+            return Decimal(self)
+        if self._exp >= 0:
+            return Decimal(self)
+        if not self:
+            return _dec_from_triple(self._sign, '0', 0)
+        if context is None:
+            context = getcontext()
+        if rounding is None:
+            rounding = context.rounding
+        ans = self._rescale(0, rounding)
+        if ans != self:
+            context._raise_error(Inexact)
+        context._raise_error(Rounded)
+        return ans
+
+    def to_integral_value(self, rounding=None, context=None):
+        """Rounds to the nearest integer, without raising inexact, rounded."""
+        if context is None:
+            context = getcontext()
+        if rounding is None:
+            rounding = context.rounding
+        if self._is_special:
+            ans = self._check_nans(context=context)
+            if ans:
+                return ans
+            return Decimal(self)
+        if self._exp >= 0:
+            return Decimal(self)
+        else:
+            return self._rescale(0, rounding)
+
+    # the method name changed, but we provide also the old one, for compatibility
+    to_integral = to_integral_value
+
+    def sqrt(self, context=None):
+        """Return the square root of self."""
+        if context is None:
+            context = getcontext()
+
+        if self._is_special:
+            ans = self._check_nans(context=context)
+            if ans:
+                return ans
+
+            if self._isinfinity() and self._sign == 0:
+                return Decimal(self)
+
+        if not self:
+            # exponent = self._exp // 2.  sqrt(-0) = -0
+            ans = _dec_from_triple(self._sign, '0', self._exp // 2)
+            return ans._fix(context)
+
+        if self._sign == 1:
+            return context._raise_error(InvalidOperation, 'sqrt(-x), x > 0')
+
+        # At this point self represents a positive number.  Let p be
+        # the desired precision and express self in the form c*100**e
+        # with c a positive real number and e an integer, c and e
+        # being chosen so that 100**(p-1) <= c < 100**p.  Then the
+        # (exact) square root of self is sqrt(c)*10**e, and 10**(p-1)
+        # <= sqrt(c) < 10**p, so the closest representable Decimal at
+        # precision p is n*10**e where n = round_half_even(sqrt(c)),
+        # the closest integer to sqrt(c) with the even integer chosen
+        # in the case of a tie.
+        #
+        # To ensure correct rounding in all cases, we use the
+        # following trick: we compute the square root to an extra
+        # place (precision p+1 instead of precision p), rounding down.
+        # Then, if the result is inexact and its last digit is 0 or 5,
+        # we increase the last digit to 1 or 6 respectively; if it's
+        # exact we leave the last digit alone.  Now the final round to
+        # p places (or fewer in the case of underflow) will round
+        # correctly and raise the appropriate flags.
+
+        # use an extra digit of precision
+        prec = context.prec+1
+
+        # write argument in the form c*100**e where e = self._exp//2
+        # is the 'ideal' exponent, to be used if the square root is
+        # exactly representable.  l is the number of 'digits' of c in
+        # base 100, so that 100**(l-1) <= c < 100**l.
+        op = _WorkRep(self)
+        e = op.exp >> 1
+        if op.exp & 1:
+            c = op.int * 10
+            l = (len(self._int) >> 1) + 1
+        else:
+            c = op.int
+            l = len(self._int)+1 >> 1
+
+        # rescale so that c has exactly prec base 100 'digits'
+        shift = prec-l
+        if shift >= 0:
+            c *= 100**shift
+            exact = True
+        else:
+            c, remainder = divmod(c, 100**-shift)
+            exact = not remainder
+        e -= shift
+
+        # find n = floor(sqrt(c)) using Newton's method
+        n = 10**prec
+        while True:
+            q = c//n
+            if n <= q:
+                break
+            else:
+                n = n + q >> 1
+        exact = exact and n*n == c
+
+        if exact:
+            # result is exact; rescale to use ideal exponent e
+            if shift >= 0:
+                # assert n % 10**shift == 0
+                n //= 10**shift
+            else:
+                n *= 10**-shift
+            e += shift
+        else:
+            # result is not exact; fix last digit as described above
+            if n % 5 == 0:
+                n += 1
+
+        ans = _dec_from_triple(0, str(n), e)
+
+        # round, and fit to current context
+        context = context._shallow_copy()
+        rounding = context._set_rounding(ROUND_HALF_EVEN)
+        ans = ans._fix(context)
+        context.rounding = rounding
+
+        return ans
+
+    def max(self, other, context=None):
+        """Returns the larger value.
+
+        Like max(self, other) except if one is not a number, returns
+        NaN (and signals if one is sNaN).  Also rounds.
+        """
+        other = _convert_other(other, raiseit=True)
+
+        if context is None:
+            context = getcontext()
+
+        if self._is_special or other._is_special:
+            # If one operand is a quiet NaN and the other is number, then the
+            # number is always returned
+            sn = self._isnan()
+            on = other._isnan()
+            if sn or on:
+                if on == 1 and sn == 0:
+                    return self._fix(context)
+                if sn == 1 and on == 0:
+                    return other._fix(context)
+                return self._check_nans(other, context)
+
+        c = self._cmp(other)
+        if c == 0:
+            # If both operands are finite and equal in numerical value
+            # then an ordering is applied:
+            #
+            # If the signs differ then max returns the operand with the
+            # positive sign and min returns the operand with the negative sign
+            #
+            # If the signs are the same then the exponent is used to select
+            # the result.  This is exactly the ordering used in compare_total.
+            c = self.compare_total(other)
+
+        if c == -1:
+            ans = other
+        else:
+            ans = self
+
+        return ans._fix(context)
+
+    def min(self, other, context=None):
+        """Returns the smaller value.
+
+        Like min(self, other) except if one is not a number, returns
+        NaN (and signals if one is sNaN).  Also rounds.
+        """
+        other = _convert_other(other, raiseit=True)
+
+        if context is None:
+            context = getcontext()
+
+        if self._is_special or other._is_special:
+            # If one operand is a quiet NaN and the other is number, then the
+            # number is always returned
+            sn = self._isnan()
+            on = other._isnan()
+            if sn or on:
+                if on == 1 and sn == 0:
+                    return self._fix(context)
+                if sn == 1 and on == 0:
+                    return other._fix(context)
+                return self._check_nans(other, context)
+
+        c = self._cmp(other)
+        if c == 0:
+            c = self.compare_total(other)
+
+        if c == -1:
+            ans = self
+        else:
+            ans = other
+
+        return ans._fix(context)
+
+    def _isinteger(self):
+        """Returns whether self is an integer"""
+        if self._is_special:
+            return False
+        if self._exp >= 0:
+            return True
+        rest = self._int[self._exp:]
+        return rest == '0'*len(rest)
+
+    def _iseven(self):
+        """Returns True if self is even.  Assumes self is an integer."""
+        if not self or self._exp > 0:
+            return True
+        return self._int[-1+self._exp] in '02468'
+
+    def adjusted(self):
+        """Return the adjusted exponent of self"""
+        try:
+            return self._exp + len(self._int) - 1
+        # If NaN or Infinity, self._exp is string
+        except TypeError:
+            return 0
+
+    def canonical(self, context=None):
+        """Returns the same Decimal object.
+
+        As we do not have different encodings for the same number, the
+        received object already is in its canonical form.
+        """
+        return self
+
+    def compare_signal(self, other, context=None):
+        """Compares self to the other operand numerically.
+
+        It's pretty much like compare(), but all NaNs signal, with signaling
+        NaNs taking precedence over quiet NaNs.
+        """
+        other = _convert_other(other, raiseit = True)
+        ans = self._compare_check_nans(other, context)
+        if ans:
+            return ans
+        return self.compare(other, context=context)
+
+    def compare_total(self, other):
+        """Compares self to other using the abstract representations.
+
+        This is not like the standard compare, which use their numerical
+        value. Note that a total ordering is defined for all possible abstract
+        representations.
+        """
+        other = _convert_other(other, raiseit=True)
+
+        # if one is negative and the other is positive, it's easy
+        if self._sign and not other._sign:
+            return _NegativeOne
+        if not self._sign and other._sign:
+            return _One
+        sign = self._sign
+
+        # let's handle both NaN types
+        self_nan = self._isnan()
+        other_nan = other._isnan()
+        if self_nan or other_nan:
+            if self_nan == other_nan:
+                # compare payloads as though they're integers
+                self_key = len(self._int), self._int
+                other_key = len(other._int), other._int
+                if self_key < other_key:
+                    if sign:
+                        return _One
+                    else:
+                        return _NegativeOne
+                if self_key > other_key:
+                    if sign:
+                        return _NegativeOne
+                    else:
+                        return _One
+                return _Zero
+
+            if sign:
+                if self_nan == 1:
+                    return _NegativeOne
+                if other_nan == 1:
+                    return _One
+                if self_nan == 2:
+                    return _NegativeOne
+                if other_nan == 2:
+                    return _One
+            else:
+                if self_nan == 1:
+                    return _One
+                if other_nan == 1:
+                    return _NegativeOne
+                if self_nan == 2:
+                    return _One
+                if other_nan == 2:
+                    return _NegativeOne
+
+        if self < other:
+            return _NegativeOne
+        if self > other:
+            return _One
+
+        if self._exp < other._exp:
+            if sign:
+                return _One
+            else:
+                return _NegativeOne
+        if self._exp > other._exp:
+            if sign:
+                return _NegativeOne
+            else:
+                return _One
+        return _Zero
+
+
+    def compare_total_mag(self, other):
+        """Compares self to other using abstract repr., ignoring sign.
+
+        Like compare_total, but with operand's sign ignored and assumed to be 0.
+        """
+        other = _convert_other(other, raiseit=True)
+
+        s = self.copy_abs()
+        o = other.copy_abs()
+        return s.compare_total(o)
+
+    def copy_abs(self):
+        """Returns a copy with the sign set to 0. """
+        return _dec_from_triple(0, self._int, self._exp, self._is_special)
+
+    def copy_negate(self):
+        """Returns a copy with the sign inverted."""
+        if self._sign:
+            return _dec_from_triple(0, self._int, self._exp, self._is_special)
+        else:
+            return _dec_from_triple(1, self._int, self._exp, self._is_special)
+
+    def copy_sign(self, other):
+        """Returns self with the sign of other."""
+        other = _convert_other(other, raiseit=True)
+        return _dec_from_triple(other._sign, self._int,
+                                self._exp, self._is_special)
+
+    def exp(self, context=None):
+        """Returns e ** self."""
+
+        if context is None:
+            context = getcontext()
+
+        # exp(NaN) = NaN
+        ans = self._check_nans(context=context)
+        if ans:
+            return ans
+
+        # exp(-Infinity) = 0
+        if self._isinfinity() == -1:
+            return _Zero
+
+        # exp(0) = 1
+        if not self:
+            return _One
+
+        # exp(Infinity) = Infinity
+        if self._isinfinity() == 1:
+            return Decimal(self)
+
+        # the result is now guaranteed to be inexact (the true
+        # mathematical result is transcendental). There's no need to
+        # raise Rounded and Inexact here---they'll always be raised as
+        # a result of the call to _fix.
+        p = context.prec
+        adj = self.adjusted()
+
+        # we only need to do any computation for quite a small range
+        # of adjusted exponents---for example, -29 <= adj <= 10 for
+        # the default context.  For smaller exponent the result is
+        # indistinguishable from 1 at the given precision, while for
+        # larger exponent the result either overflows or underflows.
+        if self._sign == 0 and adj > len(str((context.Emax+1)*3)):
+            # overflow
+            ans = _dec_from_triple(0, '1', context.Emax+1)
+        elif self._sign == 1 and adj > len(str((-context.Etiny()+1)*3)):
+            # underflow to 0
+            ans = _dec_from_triple(0, '1', context.Etiny()-1)
+        elif self._sign == 0 and adj < -p:
+            # p+1 digits; final round will raise correct flags
+            ans = _dec_from_triple(0, '1' + '0'*(p-1) + '1', -p)
+        elif self._sign == 1 and adj < -p-1:
+            # p+1 digits; final round will raise correct flags
+            ans = _dec_from_triple(0, '9'*(p+1), -p-1)
+        # general case
+        else:
+            op = _WorkRep(self)
+            c, e = op.int, op.exp
+            if op.sign == 1:
+                c = -c
+
+            # compute correctly rounded result: increase precision by
+            # 3 digits at a time until we get an unambiguously
+            # roundable result
+            extra = 3
+            while True:
+                coeff, exp = _dexp(c, e, p+extra)
+                if coeff % (5*10**(len(str(coeff))-p-1)):
+                    break
+                extra += 3
+
+            ans = _dec_from_triple(0, str(coeff), exp)
+
+        # at this stage, ans should round correctly with *any*
+        # rounding mode, not just with ROUND_HALF_EVEN
+        context = context._shallow_copy()
+        rounding = context._set_rounding(ROUND_HALF_EVEN)
+        ans = ans._fix(context)
+        context.rounding = rounding
+
+        return ans
+
+    def is_canonical(self):
+        """Return True if self is canonical; otherwise return False.
+
+        Currently, the encoding of a Decimal instance is always
+        canonical, so this method returns True for any Decimal.
+        """
+        return True
+
+    def is_finite(self):
+        """Return True if self is finite; otherwise return False.
+
+        A Decimal instance is considered finite if it is neither
+        infinite nor a NaN.
+        """
+        return not self._is_special
+
+    def is_infinite(self):
+        """Return True if self is infinite; otherwise return False."""
+        return self._exp == 'F'
+
+    def is_nan(self):
+        """Return True if self is a qNaN or sNaN; otherwise return False."""
+        return self._exp in ('n', 'N')
+
+    def is_normal(self, context=None):
+        """Return True if self is a normal number; otherwise return False."""
+        if self._is_special or not self:
+            return False
+        if context is None:
+            context = getcontext()
+        return context.Emin <= self.adjusted()
+
+    def is_qnan(self):
+        """Return True if self is a quiet NaN; otherwise return False."""
+        return self._exp == 'n'
+
+    def is_signed(self):
+        """Return True if self is negative; otherwise return False."""
+        return self._sign == 1
+
+    def is_snan(self):
+        """Return True if self is a signaling NaN; otherwise return False."""
+        return self._exp == 'N'
+
+    def is_subnormal(self, context=None):
+        """Return True if self is subnormal; otherwise return False."""
+        if self._is_special or not self:
+            return False
+        if context is None:
+            context = getcontext()
+        return self.adjusted() < context.Emin
+
+    def is_zero(self):
+        """Return True if self is a zero; otherwise return False."""
+        return not self._is_special and self._int == '0'
+
+    def _ln_exp_bound(self):
+        """Compute a lower bound for the adjusted exponent of self.ln().
+        In other words, compute r such that self.ln() >= 10**r.  Assumes
+        that self is finite and positive and that self != 1.
+        """
+
+        # for 0.1 <= x <= 10 we use the inequalities 1-1/x <= ln(x) <= x-1
+        adj = self._exp + len(self._int) - 1
+        if adj >= 1:
+            # argument >= 10; we use 23/10 = 2.3 as a lower bound for ln(10)
+            return len(str(adj*23//10)) - 1
+        if adj <= -2:
+            # argument <= 0.1
+            return len(str((-1-adj)*23//10)) - 1
+        op = _WorkRep(self)
+        c, e = op.int, op.exp
+        if adj == 0:
+            # 1 < self < 10
+            num = str(c-10**-e)
+            den = str(c)
+            return len(num) - len(den) - (num < den)
+        # adj == -1, 0.1 <= self < 1
+        return e + len(str(10**-e - c)) - 1
+
+
+    def ln(self, context=None):
+        """Returns the natural (base e) logarithm of self."""
+
+        if context is None:
+            context = getcontext()
+
+        # ln(NaN) = NaN
+        ans = self._check_nans(context=context)
+        if ans:
+            return ans
+
+        # ln(0.0) == -Infinity
+        if not self:
+            return _NegativeInfinity
+
+        # ln(Infinity) = Infinity
+        if self._isinfinity() == 1:
+            return _Infinity
+
+        # ln(1.0) == 0.0
+        if self == _One:
+            return _Zero
+
+        # ln(negative) raises InvalidOperation
+        if self._sign == 1:
+            return context._raise_error(InvalidOperation,
+                                        'ln of a negative value')
+
+        # result is irrational, so necessarily inexact
+        op = _WorkRep(self)
+        c, e = op.int, op.exp
+        p = context.prec
+
+        # correctly rounded result: repeatedly increase precision by 3
+        # until we get an unambiguously roundable result
+        places = p - self._ln_exp_bound() + 2 # at least p+3 places
+        while True:
+            coeff = _dlog(c, e, places)
+            # assert len(str(abs(coeff)))-p >= 1
+            if coeff % (5*10**(len(str(abs(coeff)))-p-1)):
+                break
+            places += 3
+        ans = _dec_from_triple(int(coeff<0), str(abs(coeff)), -places)
+
+        context = context._shallow_copy()
+        rounding = context._set_rounding(ROUND_HALF_EVEN)
+        ans = ans._fix(context)
+        context.rounding = rounding
+        return ans
+
+    def _log10_exp_bound(self):
+        """Compute a lower bound for the adjusted exponent of self.log10().
+        In other words, find r such that self.log10() >= 10**r.
+        Assumes that self is finite and positive and that self != 1.
+        """
+
+        # For x >= 10 or x < 0.1 we only need a bound on the integer
+        # part of log10(self), and this comes directly from the
+        # exponent of x.  For 0.1 <= x <= 10 we use the inequalities
+        # 1-1/x <= log(x) <= x-1. If x > 1 we have |log10(x)| >
+        # (1-1/x)/2.31 > 0.  If x < 1 then |log10(x)| > (1-x)/2.31 > 0
+
+        adj = self._exp + len(self._int) - 1
+        if adj >= 1:
+            # self >= 10
+            return len(str(adj))-1
+        if adj <= -2:
+            # self < 0.1
+            return len(str(-1-adj))-1
+        op = _WorkRep(self)
+        c, e = op.int, op.exp
+        if adj == 0:
+            # 1 < self < 10
+            num = str(c-10**-e)
+            den = str(231*c)
+            return len(num) - len(den) - (num < den) + 2
+        # adj == -1, 0.1 <= self < 1
+        num = str(10**-e-c)
+        return len(num) + e - (num < "231") - 1
+
+    def log10(self, context=None):
+        """Returns the base 10 logarithm of self."""
+
+        if context is None:
+            context = getcontext()
+
+        # log10(NaN) = NaN
+        ans = self._check_nans(context=context)
+        if ans:
+            return ans
+
+        # log10(0.0) == -Infinity
+        if not self:
+            return _NegativeInfinity
+
+        # log10(Infinity) = Infinity
+        if self._isinfinity() == 1:
+            return _Infinity
+
+        # log10(negative or -Infinity) raises InvalidOperation
+        if self._sign == 1:
+            return context._raise_error(InvalidOperation,
+                                        'log10 of a negative value')
+
+        # log10(10**n) = n
+        if self._int[0] == '1' and self._int[1:] == '0'*(len(self._int) - 1):
+            # answer may need rounding
+            ans = Decimal(self._exp + len(self._int) - 1)
+        else:
+            # result is irrational, so necessarily inexact
+            op = _WorkRep(self)
+            c, e = op.int, op.exp
+            p = context.prec
+
+            # correctly rounded result: repeatedly increase precision
+            # until result is unambiguously roundable
+            places = p-self._log10_exp_bound()+2
+            while True:
+                coeff = _dlog10(c, e, places)
+                # assert len(str(abs(coeff)))-p >= 1
+                if coeff % (5*10**(len(str(abs(coeff)))-p-1)):
+                    break
+                places += 3
+            ans = _dec_from_triple(int(coeff<0), str(abs(coeff)), -places)
+
+        context = context._shallow_copy()
+        rounding = context._set_rounding(ROUND_HALF_EVEN)
+        ans = ans._fix(context)
+        context.rounding = rounding
+        return ans
+
+    def logb(self, context=None):
+        """ Returns the exponent of the magnitude of self's MSD.
+
+        The result is the integer which is the exponent of the magnitude
+        of the most significant digit of self (as though it were truncated
+        to a single digit while maintaining the value of that digit and
+        without limiting the resulting exponent).
+        """
+        # logb(NaN) = NaN
+        ans = self._check_nans(context=context)
+        if ans:
+            return ans
+
+        if context is None:
+            context = getcontext()
+
+        # logb(+/-Inf) = +Inf
+        if self._isinfinity():
+            return _Infinity
+
+        # logb(0) = -Inf, DivisionByZero
+        if not self:
+            return context._raise_error(DivisionByZero, 'logb(0)', 1)
+
+        # otherwise, simply return the adjusted exponent of self, as a
+        # Decimal.  Note that no attempt is made to fit the result
+        # into the current context.
+        ans = Decimal(self.adjusted())
+        return ans._fix(context)
+
+    def _islogical(self):
+        """Return True if self is a logical operand.
+
+        For being logical, it must be a finite number with a sign of 0,
+        an exponent of 0, and a coefficient whose digits must all be
+        either 0 or 1.
+        """
+        if self._sign != 0 or self._exp != 0:
+            return False
+        for dig in self._int:
+            if dig not in '01':
+                return False
+        return True
+
+    def _fill_logical(self, context, opa, opb):
+        dif = context.prec - len(opa)
+        if dif > 0:
+            opa = '0'*dif + opa
+        elif dif < 0:
+            opa = opa[-context.prec:]
+        dif = context.prec - len(opb)
+        if dif > 0:
+            opb = '0'*dif + opb
+        elif dif < 0:
+            opb = opb[-context.prec:]
+        return opa, opb
+
+    def logical_and(self, other, context=None):
+        """Applies an 'and' operation between self and other's digits."""
+        if context is None:
+            context = getcontext()
+
+        other = _convert_other(other, raiseit=True)
+
+        if not self._islogical() or not other._islogical():
+            return context._raise_error(InvalidOperation)
+
+        # fill to context.prec
+        (opa, opb) = self._fill_logical(context, self._int, other._int)
+
+        # make the operation, and clean starting zeroes
+        result = "".join([str(int(a)&int(b)) for a,b in zip(opa,opb)])
+        return _dec_from_triple(0, result.lstrip('0') or '0', 0)
+
+    def logical_invert(self, context=None):
+        """Invert all its digits."""
+        if context is None:
+            context = getcontext()
+        return self.logical_xor(_dec_from_triple(0,'1'*context.prec,0),
+                                context)
+
+    def logical_or(self, other, context=None):
+        """Applies an 'or' operation between self and other's digits."""
+        if context is None:
+            context = getcontext()
+
+        other = _convert_other(other, raiseit=True)
+
+        if not self._islogical() or not other._islogical():
+            return context._raise_error(InvalidOperation)
+
+        # fill to context.prec
+        (opa, opb) = self._fill_logical(context, self._int, other._int)
+
+        # make the operation, and clean starting zeroes
+        result = "".join([str(int(a)|int(b)) for a,b in zip(opa,opb)])
+        return _dec_from_triple(0, result.lstrip('0') or '0', 0)
+
+    def logical_xor(self, other, context=None):
+        """Applies an 'xor' operation between self and other's digits."""
+        if context is None:
+            context = getcontext()
+
+        other = _convert_other(other, raiseit=True)
+
+        if not self._islogical() or not other._islogical():
+            return context._raise_error(InvalidOperation)
+
+        # fill to context.prec
+        (opa, opb) = self._fill_logical(context, self._int, other._int)
+
+        # make the operation, and clean starting zeroes
+        result = "".join([str(int(a)^int(b)) for a,b in zip(opa,opb)])
+        return _dec_from_triple(0, result.lstrip('0') or '0', 0)
+
+    def max_mag(self, other, context=None):
+        """Compares the values numerically with their sign ignored."""
+        other = _convert_other(other, raiseit=True)
+
+        if context is None:
+            context = getcontext()
+
+        if self._is_special or other._is_special:
+            # If one operand is a quiet NaN and the other is number, then the
+            # number is always returned
+            sn = self._isnan()
+            on = other._isnan()
+            if sn or on:
+                if on == 1 and sn == 0:
+                    return self._fix(context)
+                if sn == 1 and on == 0:
+                    return other._fix(context)
+                return self._check_nans(other, context)
+
+        c = self.copy_abs()._cmp(other.copy_abs())
+        if c == 0:
+            c = self.compare_total(other)
+
+        if c == -1:
+            ans = other
+        else:
+            ans = self
+
+        return ans._fix(context)
+
+    def min_mag(self, other, context=None):
+        """Compares the values numerically with their sign ignored."""
+        other = _convert_other(other, raiseit=True)
+
+        if context is None:
+            context = getcontext()
+
+        if self._is_special or other._is_special:
+            # If one operand is a quiet NaN and the other is number, then the
+            # number is always returned
+            sn = self._isnan()
+            on = other._isnan()
+            if sn or on:
+                if on == 1 and sn == 0:
+                    return self._fix(context)
+                if sn == 1 and on == 0:
+                    return other._fix(context)
+                return self._check_nans(other, context)
+
+        c = self.copy_abs()._cmp(other.copy_abs())
+        if c == 0:
+            c = self.compare_total(other)
+
+        if c == -1:
+            ans = self
+        else:
+            ans = other
+
+        return ans._fix(context)
+
+    def next_minus(self, context=None):
+        """Returns the largest representable number smaller than itself."""
+        if context is None:
+            context = getcontext()
+
+        ans = self._check_nans(context=context)
+        if ans:
+            return ans
+
+        if self._isinfinity() == -1:
+            return _NegativeInfinity
+        if self._isinfinity() == 1:
+            return _dec_from_triple(0, '9'*context.prec, context.Etop())
+
+        context = context.copy()
+        context._set_rounding(ROUND_FLOOR)
+        context._ignore_all_flags()
+        new_self = self._fix(context)
+        if new_self != self:
+            return new_self
+        return self.__sub__(_dec_from_triple(0, '1', context.Etiny()-1),
+                            context)
+
+    def next_plus(self, context=None):
+        """Returns the smallest representable number larger than itself."""
+        if context is None:
+            context = getcontext()
+
+        ans = self._check_nans(context=context)
+        if ans:
+            return ans
+
+        if self._isinfinity() == 1:
+            return _Infinity
+        if self._isinfinity() == -1:
+            return _dec_from_triple(1, '9'*context.prec, context.Etop())
+
+        context = context.copy()
+        context._set_rounding(ROUND_CEILING)
+        context._ignore_all_flags()
+        new_self = self._fix(context)
+        if new_self != self:
+            return new_self
+        return self.__add__(_dec_from_triple(0, '1', context.Etiny()-1),
+                            context)
+
+    def next_toward(self, other, context=None):
+        """Returns the number closest to self, in the direction towards other.
+
+        The result is the closest representable number to self
+        (excluding self) that is in the direction towards other,
+        unless both have the same value.  If the two operands are
+        numerically equal, then the result is a copy of self with the
+        sign set to be the same as the sign of other.
+        """
+        other = _convert_other(other, raiseit=True)
+
+        if context is None:
+            context = getcontext()
+
+        ans = self._check_nans(other, context)
+        if ans:
+            return ans
+
+        comparison = self._cmp(other)
+        if comparison == 0:
+            return self.copy_sign(other)
+
+        if comparison == -1:
+            ans = self.next_plus(context)
+        else: # comparison == 1
+            ans = self.next_minus(context)
+
+        # decide which flags to raise using value of ans
+        if ans._isinfinity():
+            context._raise_error(Overflow,
+                                 'Infinite result from next_toward',
+                                 ans._sign)
+            context._raise_error(Inexact)
+            context._raise_error(Rounded)
+        elif ans.adjusted() < context.Emin:
+            context._raise_error(Underflow)
+            context._raise_error(Subnormal)
+            context._raise_error(Inexact)
+            context._raise_error(Rounded)
+            # if precision == 1 then we don't raise Clamped for a
+            # result 0E-Etiny.
+            if not ans:
+                context._raise_error(Clamped)
+
+        return ans
+
+    def number_class(self, context=None):
+        """Returns an indication of the class of self.
+
+        The class is one of the following strings:
+          sNaN
+          NaN
+          -Infinity
+          -Normal
+          -Subnormal
+          -Zero
+          +Zero
+          +Subnormal
+          +Normal
+          +Infinity
+        """
+        if self.is_snan():
+            return "sNaN"
+        if self.is_qnan():
+            return "NaN"
+        inf = self._isinfinity()
+        if inf == 1:
+            return "+Infinity"
+        if inf == -1:
+            return "-Infinity"
+        if self.is_zero():
+            if self._sign:
+                return "-Zero"
+            else:
+                return "+Zero"
+        if context is None:
+            context = getcontext()
+        if self.is_subnormal(context=context):
+            if self._sign:
+                return "-Subnormal"
+            else:
+                return "+Subnormal"
+        # just a normal, regular, boring number, :)
+        if self._sign:
+            return "-Normal"
+        else:
+            return "+Normal"
+
+    def radix(self):
+        """Just returns 10, as this is Decimal, :)"""
+        return Decimal(10)
+
+    def rotate(self, other, context=None):
+        """Returns a rotated copy of self, value-of-other times."""
+        if context is None:
+            context = getcontext()
+
+        other = _convert_other(other, raiseit=True)
+
+        ans = self._check_nans(other, context)
+        if ans:
+            return ans
+
+        if other._exp != 0:
+            return context._raise_error(InvalidOperation)
+        if not (-context.prec <= int(other) <= context.prec):
+            return context._raise_error(InvalidOperation)
+
+        if self._isinfinity():
+            return Decimal(self)
+
+        # get values, pad if necessary
+        torot = int(other)
+        rotdig = self._int
+        topad = context.prec - len(rotdig)
+        if topad > 0:
+            rotdig = '0'*topad + rotdig
+        elif topad < 0:
+            rotdig = rotdig[-topad:]
+
+        # let's rotate!
+        rotated = rotdig[torot:] + rotdig[:torot]
+        return _dec_from_triple(self._sign,
+                                rotated.lstrip('0') or '0', self._exp)
+
+    def scaleb(self, other, context=None):
+        """Returns self operand after adding the second value to its exp."""
+        if context is None:
+            context = getcontext()
+
+        other = _convert_other(other, raiseit=True)
+
+        ans = self._check_nans(other, context)
+        if ans:
+            return ans
+
+        if other._exp != 0:
+            return context._raise_error(InvalidOperation)
+        liminf = -2 * (context.Emax + context.prec)
+        limsup =  2 * (context.Emax + context.prec)
+        if not (liminf <= int(other) <= limsup):
+            return context._raise_error(InvalidOperation)
+
+        if self._isinfinity():
+            return Decimal(self)
+
+        d = _dec_from_triple(self._sign, self._int, self._exp + int(other))
+        d = d._fix(context)
+        return d
+
+    def shift(self, other, context=None):
+        """Returns a shifted copy of self, value-of-other times."""
+        if context is None:
+            context = getcontext()
+
+        other = _convert_other(other, raiseit=True)
+
+        ans = self._check_nans(other, context)
+        if ans:
+            return ans
+
+        if other._exp != 0:
+            return context._raise_error(InvalidOperation)
+        if not (-context.prec <= int(other) <= context.prec):
+            return context._raise_error(InvalidOperation)
+
+        if self._isinfinity():
+            return Decimal(self)
+
+        # get values, pad if necessary
+        torot = int(other)
+        rotdig = self._int
+        topad = context.prec - len(rotdig)
+        if topad > 0:
+            rotdig = '0'*topad + rotdig
+        elif topad < 0:
+            rotdig = rotdig[-topad:]
+
+        # let's shift!
+        if torot < 0:
+            shifted = rotdig[:torot]
+        else:
+            shifted = rotdig + '0'*torot
+            shifted = shifted[-context.prec:]
+
+        return _dec_from_triple(self._sign,
+                                    shifted.lstrip('0') or '0', self._exp)
+
+    # Support for pickling, copy, and deepcopy
+    def __reduce__(self):
+        return (self.__class__, (str(self),))
+
+    def __copy__(self):
+        if type(self) is Decimal:
+            return self     # I'm immutable; therefore I am my own clone
+        return self.__class__(str(self))
+
+    def __deepcopy__(self, memo):
+        if type(self) is Decimal:
+            return self     # My components are also immutable
+        return self.__class__(str(self))
+
+    # PEP 3101 support.  the _localeconv keyword argument should be
+    # considered private: it's provided for ease of testing only.
+    def __format__(self, specifier, context=None, _localeconv=None):
+        """Format a Decimal instance according to the given specifier.
+
+        The specifier should be a standard format specifier, with the
+        form described in PEP 3101.  Formatting types 'e', 'E', 'f',
+        'F', 'g', 'G', 'n' and '%' are supported.  If the formatting
+        type is omitted it defaults to 'g' or 'G', depending on the
+        value of context.capitals.
+        """
+
+        # Note: PEP 3101 says that if the type is not present then
+        # there should be at least one digit after the decimal point.
+        # We take the liberty of ignoring this requirement for
+        # Decimal---it's presumably there to make sure that
+        # format(float, '') behaves similarly to str(float).
+        if context is None:
+            context = getcontext()
+
+        spec = _parse_format_specifier(specifier, _localeconv=_localeconv)
+
+        # special values don't care about the type or precision
+        if self._is_special:
+            sign = _format_sign(self._sign, spec)
+            body = str(self.copy_abs())
+            return _format_align(sign, body, spec)
+
+        # a type of None defaults to 'g' or 'G', depending on context
+        if spec['type'] is None:
+            spec['type'] = ['g', 'G'][context.capitals]
+
+        # if type is '%', adjust exponent of self accordingly
+        if spec['type'] == '%':
+            self = _dec_from_triple(self._sign, self._int, self._exp+2)
+
+        # round if necessary, taking rounding mode from the context
+        rounding = context.rounding
+        precision = spec['precision']
+        if precision is not None:
+            if spec['type'] in 'eE':
+                self = self._round(precision+1, rounding)
+            elif spec['type'] in 'fF%':
+                self = self._rescale(-precision, rounding)
+            elif spec['type'] in 'gG' and len(self._int) > precision:
+                self = self._round(precision, rounding)
+        # special case: zeros with a positive exponent can't be
+        # represented in fixed point; rescale them to 0e0.
+        if not self and self._exp > 0 and spec['type'] in 'fF%':
+            self = self._rescale(0, rounding)
+
+        # figure out placement of the decimal point
+        leftdigits = self._exp + len(self._int)
+        if spec['type'] in 'eE':
+            if not self and precision is not None:
+                dotplace = 1 - precision
+            else:
+                dotplace = 1
+        elif spec['type'] in 'fF%':
+            dotplace = leftdigits
+        elif spec['type'] in 'gG':
+            if self._exp <= 0 and leftdigits > -6:
+                dotplace = leftdigits
+            else:
+                dotplace = 1
+
+        # find digits before and after decimal point, and get exponent
+        if dotplace < 0:
+            intpart = '0'
+            fracpart = '0'*(-dotplace) + self._int
+        elif dotplace > len(self._int):
+            intpart = self._int + '0'*(dotplace-len(self._int))
+            fracpart = ''
+        else:
+            intpart = self._int[:dotplace] or '0'
+            fracpart = self._int[dotplace:]
+        exp = leftdigits-dotplace
+
+        # done with the decimal-specific stuff;  hand over the rest
+        # of the formatting to the _format_number function
+        return _format_number(self._sign, intpart, fracpart, exp, spec)
+
+    # support for Jython __tojava__:
+    def __tojava__(self, java_class):
+        if java_class not in (BigDecimal, Object):
+            return Py.NoConversion
+        return BigDecimal(str(self))
+
+def _dec_from_triple(sign, coefficient, exponent, special=False):
+    """Create a decimal instance directly, without any validation,
+    normalization (e.g. removal of leading zeros) or argument
+    conversion.
+
+    This function is for *internal use only*.
+    """
+
+    self = object.__new__(Decimal)
+    self._sign = sign
+    self._int = coefficient
+    self._exp = exponent
+    self._is_special = special
+
+    return self
+
+# Register Decimal as a kind of Number (an abstract base class).
+# However, do not register it as Real (because Decimals are not
+# interoperable with floats).
+_numbers.Number.register(Decimal)
+
+
+##### Context class #######################################################
+
+
+# get rounding method function:
+rounding_functions = [name for name in Decimal.__dict__.keys()
+                                    if name.startswith('_round_')]
+for name in rounding_functions:
+    # name is like _round_half_even, goes to the global ROUND_HALF_EVEN value.
+    globalname = name[1:].upper()
+    val = globals()[globalname]
+    Decimal._pick_rounding_function[val] = name
+
+del name, val, globalname, rounding_functions
+
+class _ContextManager(object):
+    """Context manager class to support localcontext().
+
+      Sets a copy of the supplied context in __enter__() and restores
+      the previous decimal context in __exit__()
+    """
+    def __init__(self, new_context):
+        self.new_context = new_context.copy()
+    def __enter__(self):
+        self.saved_context = getcontext()
+        setcontext(self.new_context)
+        return self.new_context
+    def __exit__(self, t, v, tb):
+        setcontext(self.saved_context)
+
+class Context(object):
+    """Contains the context for a Decimal instance.
+
+    Contains:
+    prec - precision (for use in rounding, division, square roots..)
+    rounding - rounding type (how you round)
+    traps - If traps[exception] = 1, then the exception is
+                    raised when it is caused.  Otherwise, a value is
+                    substituted in.
+    flags  - When an exception is caused, flags[exception] is set.
+             (Whether or not the trap_enabler is set)
+             Should be reset by user of Decimal instance.
+    Emin -   Minimum exponent
+    Emax -   Maximum exponent
+    capitals -      If 1, 1*10^1 is printed as 1E+1.
+                    If 0, printed as 1e1
+    _clamp - If 1, change exponents if too high (Default 0)
+    """
+
+    def __init__(self, prec=None, rounding=None,
+                 traps=None, flags=None,
+                 Emin=None, Emax=None,
+                 capitals=None, _clamp=0,
+                 _ignored_flags=None):
+        # Set defaults; for everything except flags and _ignored_flags,
+        # inherit from DefaultContext.
+        try:
+            dc = DefaultContext
+        except NameError:
+            pass
+
+        self.prec = prec if prec is not None else dc.prec
+        self.rounding = rounding if rounding is not None else dc.rounding
+        self.Emin = Emin if Emin is not None else dc.Emin
+        self.Emax = Emax if Emax is not None else dc.Emax
+        self.capitals = capitals if capitals is not None else dc.capitals
+        self._clamp = _clamp if _clamp is not None else dc._clamp
+
+        if _ignored_flags is None:
+            self._ignored_flags = []
+        else:
+            self._ignored_flags = _ignored_flags
+
+        if traps is None:
+            self.traps = dc.traps.copy()
+        elif not isinstance(traps, dict):
+            self.traps = dict((s, int(s in traps)) for s in _signals)
+        else:
+            self.traps = traps
+
+        if flags is None:
+            self.flags = dict.fromkeys(_signals, 0)
+        elif not isinstance(flags, dict):
+            self.flags = dict((s, int(s in flags)) for s in _signals)
+        else:
+            self.flags = flags
+
+    def __repr__(self):
+        """Show the current context."""
+        s = []
+        s.append('Context(prec=%(prec)d, rounding=%(rounding)s, '
+                 'Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d'
+                 % vars(self))
+        names = [f.__name__ for f, v in self.flags.items() if v]
+        s.append('flags=[' + ', '.join(names) + ']')
+        names = [t.__name__ for t, v in self.traps.items() if v]
+        s.append('traps=[' + ', '.join(names) + ']')
+        return ', '.join(s) + ')'
+
+    def clear_flags(self):
+        """Reset all flags to zero"""
+        for flag in self.flags:
+            self.flags[flag] = 0
+
+    def _shallow_copy(self):
+        """Returns a shallow copy from self."""
+        nc = Context(self.prec, self.rounding, self.traps,
+                     self.flags, self.Emin, self.Emax,
+                     self.capitals, self._clamp, self._ignored_flags)
+        return nc
+
+    def copy(self):
+        """Returns a deep copy from self."""
+        nc = Context(self.prec, self.rounding, self.traps.copy(),
+                     self.flags.copy(), self.Emin, self.Emax,
+                     self.capitals, self._clamp, self._ignored_flags)
+        return nc
+    __copy__ = copy
+
+    def _raise_error(self, condition, explanation = None, *args):
+        """Handles an error
+
+        If the flag is in _ignored_flags, returns the default response.
+        Otherwise, it sets the flag, then, if the corresponding
+        trap_enabler is set, it reraises the exception.  Otherwise, it returns
+        the default value after setting the flag.
+        """
+        error = _condition_map.get(condition, condition)
+        if error in self._ignored_flags:
+            # Don't touch the flag
+            return error().handle(self, *args)
+
+        self.flags[error] = 1
+        if not self.traps[error]:
+            # The errors define how to handle themselves.
+            return condition().handle(self, *args)
+
+        # Errors should only be risked on copies of the context
+        # self._ignored_flags = []
+        raise error(explanation)
+
+    def _ignore_all_flags(self):
+        """Ignore all flags, if they are raised"""
+        return self._ignore_flags(*_signals)
+
+    def _ignore_flags(self, *flags):
+        """Ignore the flags, if they are raised"""
+        # Do not mutate-- This way, copies of a context leave the original
+        # alone.
+        self._ignored_flags = (self._ignored_flags + list(flags))
+        return list(flags)
+
+    def _regard_flags(self, *flags):
+        """Stop ignoring the flags, if they are raised"""
+        if flags and isinstance(flags[0], (tuple,list)):
+            flags = flags[0]
+        for flag in flags:
+            self._ignored_flags.remove(flag)
+
+    # We inherit object.__hash__, so we must deny this explicitly
+    __hash__ = None
+
+    def Etiny(self):
+        """Returns Etiny (= Emin - prec + 1)"""
+        return int(self.Emin - self.prec + 1)
+
+    def Etop(self):
+        """Returns maximum exponent (= Emax - prec + 1)"""
+        return int(self.Emax - self.prec + 1)
+
+    def _set_rounding(self, type):
+        """Sets the rounding type.
+
+        Sets the rounding type, and returns the current (previous)
+        rounding type.  Often used like:
+
+        context = context.copy()
+        # so you don't change the calling context
+        # if an error occurs in the middle.
+        rounding = context._set_rounding(ROUND_UP)
+        val = self.__sub__(other, context=context)
+        context._set_rounding(rounding)
+
+        This will make it round up for that operation.
+        """
+        rounding = self.rounding
+        self.rounding= type
+        return rounding
+
+    def create_decimal(self, num='0'):
+        """Creates a new Decimal instance but using self as context.
+
+        This method implements the to-number operation of the
+        IBM Decimal specification."""
+
+        if isinstance(num, basestring) and num != num.strip():
+            return self._raise_error(ConversionSyntax,
+                                     "no trailing or leading whitespace is "
+                                     "permitted.")
+
+        d = Decimal(num, context=self)
+        if d._isnan() and len(d._int) > self.prec - self._clamp:
+            return self._raise_error(ConversionSyntax,
+                                     "diagnostic info too long in NaN")
+        return d._fix(self)
+
+    def create_decimal_from_float(self, f):
+        """Creates a new Decimal instance from a float but rounding using self
+        as the context.
+
+        >>> context = Context(prec=5, rounding=ROUND_DOWN)
+        >>> context.create_decimal_from_float(3.1415926535897932)
+        Decimal('3.1415')
+        >>> context = Context(prec=5, traps=[Inexact])
+        >>> context.create_decimal_from_float(3.1415926535897932)
+        Traceback (most recent call last):
+            ...
+        Inexact: None
+
+        """
+        d = Decimal.from_float(f)       # An exact conversion
+        return d._fix(self)             # Apply the context rounding
+
+    # Methods
+    def abs(self, a):
+        """Returns the absolute value of the operand.
+
+        If the operand is negative, the result is the same as using the minus
+        operation on the operand.  Otherwise, the result is the same as using
+        the plus operation on the operand.
+
+        >>> ExtendedContext.abs(Decimal('2.1'))
+        Decimal('2.1')
+        >>> ExtendedContext.abs(Decimal('-100'))
+        Decimal('100')
+        >>> ExtendedContext.abs(Decimal('101.5'))
+        Decimal('101.5')
+        >>> ExtendedContext.abs(Decimal('-101.5'))
+        Decimal('101.5')
+        >>> ExtendedContext.abs(-1)
+        Decimal('1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.__abs__(context=self)
+
+    def add(self, a, b):
+        """Return the sum of the two operands.
+
+        >>> ExtendedContext.add(Decimal('12'), Decimal('7.00'))
+        Decimal('19.00')
+        >>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4'))
+        Decimal('1.02E+4')
+        >>> ExtendedContext.add(1, Decimal(2))
+        Decimal('3')
+        >>> ExtendedContext.add(Decimal(8), 5)
+        Decimal('13')
+        >>> ExtendedContext.add(5, 5)
+        Decimal('10')
+        """
+        a = _convert_other(a, raiseit=True)
+        r = a.__add__(b, context=self)
+        if r is NotImplemented:
+            raise TypeError("Unable to convert %s to Decimal" % b)
+        else:
+            return r
+
+    def _apply(self, a):
+        return str(a._fix(self))
+
+    def canonical(self, a):
+        """Returns the same Decimal object.
+
+        As we do not have different encodings for the same number, the
+        received object already is in its canonical form.
+
+        >>> ExtendedContext.canonical(Decimal('2.50'))
+        Decimal('2.50')
+        """
+        return a.canonical(context=self)
+
+    def compare(self, a, b):
+        """Compares values numerically.
+
+        If the signs of the operands differ, a value representing each operand
+        ('-1' if the operand is less than zero, '0' if the operand is zero or
+        negative zero, or '1' if the operand is greater than zero) is used in
+        place of that operand for the comparison instead of the actual
+        operand.
+
+        The comparison is then effected by subtracting the second operand from
+        the first and then returning a value according to the result of the
+        subtraction: '-1' if the result is less than zero, '0' if the result is
+        zero or negative zero, or '1' if the result is greater than zero.
+
+        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('3'))
+        Decimal('-1')
+        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1'))
+        Decimal('0')
+        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10'))
+        Decimal('0')
+        >>> ExtendedContext.compare(Decimal('3'), Decimal('2.1'))
+        Decimal('1')
+        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('-3'))
+        Decimal('1')
+        >>> ExtendedContext.compare(Decimal('-3'), Decimal('2.1'))
+        Decimal('-1')
+        >>> ExtendedContext.compare(1, 2)
+        Decimal('-1')
+        >>> ExtendedContext.compare(Decimal(1), 2)
+        Decimal('-1')
+        >>> ExtendedContext.compare(1, Decimal(2))
+        Decimal('-1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.compare(b, context=self)
+
+    def compare_signal(self, a, b):
+        """Compares the values of the two operands numerically.
+
+        It's pretty much like compare(), but all NaNs signal, with signaling
+        NaNs taking precedence over quiet NaNs.
+
+        >>> c = ExtendedContext
+        >>> c.compare_signal(Decimal('2.1'), Decimal('3'))
+        Decimal('-1')
+        >>> c.compare_signal(Decimal('2.1'), Decimal('2.1'))
+        Decimal('0')
+        >>> c.flags[InvalidOperation] = 0
+        >>> print c.flags[InvalidOperation]
+        0
+        >>> c.compare_signal(Decimal('NaN'), Decimal('2.1'))
+        Decimal('NaN')
+        >>> print c.flags[InvalidOperation]
+        1
+        >>> c.flags[InvalidOperation] = 0
+        >>> print c.flags[InvalidOperation]
+        0
+        >>> c.compare_signal(Decimal('sNaN'), Decimal('2.1'))
+        Decimal('NaN')
+        >>> print c.flags[InvalidOperation]
+        1
+        >>> c.compare_signal(-1, 2)
+        Decimal('-1')
+        >>> c.compare_signal(Decimal(-1), 2)
+        Decimal('-1')
+        >>> c.compare_signal(-1, Decimal(2))
+        Decimal('-1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.compare_signal(b, context=self)
+
+    def compare_total(self, a, b):
+        """Compares two operands using their abstract representation.
+
+        This is not like the standard compare, which use their numerical
+        value. Note that a total ordering is defined for all possible abstract
+        representations.
+
+        >>> ExtendedContext.compare_total(Decimal('12.73'), Decimal('127.9'))
+        Decimal('-1')
+        >>> ExtendedContext.compare_total(Decimal('-127'),  Decimal('12'))
+        Decimal('-1')
+        >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.3'))
+        Decimal('-1')
+        >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.30'))
+        Decimal('0')
+        >>> ExtendedContext.compare_total(Decimal('12.3'),  Decimal('12.300'))
+        Decimal('1')
+        >>> ExtendedContext.compare_total(Decimal('12.3'),  Decimal('NaN'))
+        Decimal('-1')
+        >>> ExtendedContext.compare_total(1, 2)
+        Decimal('-1')
+        >>> ExtendedContext.compare_total(Decimal(1), 2)
+        Decimal('-1')
+        >>> ExtendedContext.compare_total(1, Decimal(2))
+        Decimal('-1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.compare_total(b)
+
+    def compare_total_mag(self, a, b):
+        """Compares two operands using their abstract representation ignoring sign.
+
+        Like compare_total, but with operand's sign ignored and assumed to be 0.
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.compare_total_mag(b)
+
+    def copy_abs(self, a):
+        """Returns a copy of the operand with the sign set to 0.
+
+        >>> ExtendedContext.copy_abs(Decimal('2.1'))
+        Decimal('2.1')
+        >>> ExtendedContext.copy_abs(Decimal('-100'))
+        Decimal('100')
+        >>> ExtendedContext.copy_abs(-1)
+        Decimal('1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.copy_abs()
+
+    def copy_decimal(self, a):
+        """Returns a copy of the decimal object.
+
+        >>> ExtendedContext.copy_decimal(Decimal('2.1'))
+        Decimal('2.1')
+        >>> ExtendedContext.copy_decimal(Decimal('-1.00'))
+        Decimal('-1.00')
+        >>> ExtendedContext.copy_decimal(1)
+        Decimal('1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return Decimal(a)
+
+    def copy_negate(self, a):
+        """Returns a copy of the operand with the sign inverted.
+
+        >>> ExtendedContext.copy_negate(Decimal('101.5'))
+        Decimal('-101.5')
+        >>> ExtendedContext.copy_negate(Decimal('-101.5'))
+        Decimal('101.5')
+        >>> ExtendedContext.copy_negate(1)
+        Decimal('-1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.copy_negate()
+
+    def copy_sign(self, a, b):
+        """Copies the second operand's sign to the first one.
+
+        In detail, it returns a copy of the first operand with the sign
+        equal to the sign of the second operand.
+
+        >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('7.33'))
+        Decimal('1.50')
+        >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('7.33'))
+        Decimal('1.50')
+        >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('-7.33'))
+        Decimal('-1.50')
+        >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('-7.33'))
+        Decimal('-1.50')
+        >>> ExtendedContext.copy_sign(1, -2)
+        Decimal('-1')
+        >>> ExtendedContext.copy_sign(Decimal(1), -2)
+        Decimal('-1')
+        >>> ExtendedContext.copy_sign(1, Decimal(-2))
+        Decimal('-1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.copy_sign(b)
+
+    def divide(self, a, b):
+        """Decimal division in a specified context.
+
+        >>> ExtendedContext.divide(Decimal('1'), Decimal('3'))
+        Decimal('0.333333333')
+        >>> ExtendedContext.divide(Decimal('2'), Decimal('3'))
+        Decimal('0.666666667')
+        >>> ExtendedContext.divide(Decimal('5'), Decimal('2'))
+        Decimal('2.5')
+        >>> ExtendedContext.divide(Decimal('1'), Decimal('10'))
+        Decimal('0.1')
+        >>> ExtendedContext.divide(Decimal('12'), Decimal('12'))
+        Decimal('1')
+        >>> ExtendedContext.divide(Decimal('8.00'), Decimal('2'))
+        Decimal('4.00')
+        >>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0'))
+        Decimal('1.20')
+        >>> ExtendedContext.divide(Decimal('1000'), Decimal('100'))
+        Decimal('10')
+        >>> ExtendedContext.divide(Decimal('1000'), Decimal('1'))
+        Decimal('1000')
+        >>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2'))
+        Decimal('1.20E+6')
+        >>> ExtendedContext.divide(5, 5)
+        Decimal('1')
+        >>> ExtendedContext.divide(Decimal(5), 5)
+        Decimal('1')
+        >>> ExtendedContext.divide(5, Decimal(5))
+        Decimal('1')
+        """
+        a = _convert_other(a, raiseit=True)
+        r = a.__div__(b, context=self)
+        if r is NotImplemented:
+            raise TypeError("Unable to convert %s to Decimal" % b)
+        else:
+            return r
+
+    def divide_int(self, a, b):
+        """Divides two numbers and returns the integer part of the result.
+
+        >>> ExtendedContext.divide_int(Decimal('2'), Decimal('3'))
+        Decimal('0')
+        >>> ExtendedContext.divide_int(Decimal('10'), Decimal('3'))
+        Decimal('3')
+        >>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3'))
+        Decimal('3')
+        >>> ExtendedContext.divide_int(10, 3)
+        Decimal('3')
+        >>> ExtendedContext.divide_int(Decimal(10), 3)
+        Decimal('3')
+        >>> ExtendedContext.divide_int(10, Decimal(3))
+        Decimal('3')
+        """
+        a = _convert_other(a, raiseit=True)
+        r = a.__floordiv__(b, context=self)
+        if r is NotImplemented:
+            raise TypeError("Unable to convert %s to Decimal" % b)
+        else:
+            return r
+
+    def divmod(self, a, b):
+        """Return (a // b, a % b).
+
+        >>> ExtendedContext.divmod(Decimal(8), Decimal(3))
+        (Decimal('2'), Decimal('2'))
+        >>> ExtendedContext.divmod(Decimal(8), Decimal(4))
+        (Decimal('2'), Decimal('0'))
+        >>> ExtendedContext.divmod(8, 4)
+        (Decimal('2'), Decimal('0'))
+        >>> ExtendedContext.divmod(Decimal(8), 4)
+        (Decimal('2'), Decimal('0'))
+        >>> ExtendedContext.divmod(8, Decimal(4))
+        (Decimal('2'), Decimal('0'))
+        """
+        a = _convert_other(a, raiseit=True)
+        r = a.__divmod__(b, context=self)
+        if r is NotImplemented:
+            raise TypeError("Unable to convert %s to Decimal" % b)
+        else:
+            return r
+
+    def exp(self, a):
+        """Returns e ** a.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> c.exp(Decimal('-Infinity'))
+        Decimal('0')
+        >>> c.exp(Decimal('-1'))
+        Decimal('0.367879441')
+        >>> c.exp(Decimal('0'))
+        Decimal('1')
+        >>> c.exp(Decimal('1'))
+        Decimal('2.71828183')
+        >>> c.exp(Decimal('0.693147181'))
+        Decimal('2.00000000')
+        >>> c.exp(Decimal('+Infinity'))
+        Decimal('Infinity')
+        >>> c.exp(10)
+        Decimal('22026.4658')
+        """
+        a =_convert_other(a, raiseit=True)
+        return a.exp(context=self)
+
+    def fma(self, a, b, c):
+        """Returns a multiplied by b, plus c.
+
+        The first two operands are multiplied together, using multiply,
+        the third operand is then added to the result of that
+        multiplication, using add, all with only one final rounding.
+
+        >>> ExtendedContext.fma(Decimal('3'), Decimal('5'), Decimal('7'))
+        Decimal('22')
+        >>> ExtendedContext.fma(Decimal('3'), Decimal('-5'), Decimal('7'))
+        Decimal('-8')
+        >>> ExtendedContext.fma(Decimal('888565290'), Decimal('1557.96930'), Decimal('-86087.7578'))
+        Decimal('1.38435736E+12')
+        >>> ExtendedContext.fma(1, 3, 4)
+        Decimal('7')
+        >>> ExtendedContext.fma(1, Decimal(3), 4)
+        Decimal('7')
+        >>> ExtendedContext.fma(1, 3, Decimal(4))
+        Decimal('7')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.fma(b, c, context=self)
+
+    def is_canonical(self, a):
+        """Return True if the operand is canonical; otherwise return False.
+
+        Currently, the encoding of a Decimal instance is always
+        canonical, so this method returns True for any Decimal.
+
+        >>> ExtendedContext.is_canonical(Decimal('2.50'))
+        True
+        """
+        return a.is_canonical()
+
+    def is_finite(self, a):
+        """Return True if the operand is finite; otherwise return False.
+
+        A Decimal instance is considered finite if it is neither
+        infinite nor a NaN.
+
+        >>> ExtendedContext.is_finite(Decimal('2.50'))
+        True
+        >>> ExtendedContext.is_finite(Decimal('-0.3'))
+        True
+        >>> ExtendedContext.is_finite(Decimal('0'))
+        True
+        >>> ExtendedContext.is_finite(Decimal('Inf'))
+        False
+        >>> ExtendedContext.is_finite(Decimal('NaN'))
+        False
+        >>> ExtendedContext.is_finite(1)
+        True
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_finite()
+
+    def is_infinite(self, a):
+        """Return True if the operand is infinite; otherwise return False.
+
+        >>> ExtendedContext.is_infinite(Decimal('2.50'))
+        False
+        >>> ExtendedContext.is_infinite(Decimal('-Inf'))
+        True
+        >>> ExtendedContext.is_infinite(Decimal('NaN'))
+        False
+        >>> ExtendedContext.is_infinite(1)
+        False
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_infinite()
+
+    def is_nan(self, a):
+        """Return True if the operand is a qNaN or sNaN;
+        otherwise return False.
+
+        >>> ExtendedContext.is_nan(Decimal('2.50'))
+        False
+        >>> ExtendedContext.is_nan(Decimal('NaN'))
+        True
+        >>> ExtendedContext.is_nan(Decimal('-sNaN'))
+        True
+        >>> ExtendedContext.is_nan(1)
+        False
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_nan()
+
+    def is_normal(self, a):
+        """Return True if the operand is a normal number;
+        otherwise return False.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> c.is_normal(Decimal('2.50'))
+        True
+        >>> c.is_normal(Decimal('0.1E-999'))
+        False
+        >>> c.is_normal(Decimal('0.00'))
+        False
+        >>> c.is_normal(Decimal('-Inf'))
+        False
+        >>> c.is_normal(Decimal('NaN'))
+        False
+        >>> c.is_normal(1)
+        True
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_normal(context=self)
+
+    def is_qnan(self, a):
+        """Return True if the operand is a quiet NaN; otherwise return False.
+
+        >>> ExtendedContext.is_qnan(Decimal('2.50'))
+        False
+        >>> ExtendedContext.is_qnan(Decimal('NaN'))
+        True
+        >>> ExtendedContext.is_qnan(Decimal('sNaN'))
+        False
+        >>> ExtendedContext.is_qnan(1)
+        False
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_qnan()
+
+    def is_signed(self, a):
+        """Return True if the operand is negative; otherwise return False.
+
+        >>> ExtendedContext.is_signed(Decimal('2.50'))
+        False
+        >>> ExtendedContext.is_signed(Decimal('-12'))
+        True
+        >>> ExtendedContext.is_signed(Decimal('-0'))
+        True
+        >>> ExtendedContext.is_signed(8)
+        False
+        >>> ExtendedContext.is_signed(-8)
+        True
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_signed()
+
+    def is_snan(self, a):
+        """Return True if the operand is a signaling NaN;
+        otherwise return False.
+
+        >>> ExtendedContext.is_snan(Decimal('2.50'))
+        False
+        >>> ExtendedContext.is_snan(Decimal('NaN'))
+        False
+        >>> ExtendedContext.is_snan(Decimal('sNaN'))
+        True
+        >>> ExtendedContext.is_snan(1)
+        False
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_snan()
+
+    def is_subnormal(self, a):
+        """Return True if the operand is subnormal; otherwise return False.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> c.is_subnormal(Decimal('2.50'))
+        False
+        >>> c.is_subnormal(Decimal('0.1E-999'))
+        True
+        >>> c.is_subnormal(Decimal('0.00'))
+        False
+        >>> c.is_subnormal(Decimal('-Inf'))
+        False
+        >>> c.is_subnormal(Decimal('NaN'))
+        False
+        >>> c.is_subnormal(1)
+        False
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_subnormal(context=self)
+
+    def is_zero(self, a):
+        """Return True if the operand is a zero; otherwise return False.
+
+        >>> ExtendedContext.is_zero(Decimal('0'))
+        True
+        >>> ExtendedContext.is_zero(Decimal('2.50'))
+        False
+        >>> ExtendedContext.is_zero(Decimal('-0E+2'))
+        True
+        >>> ExtendedContext.is_zero(1)
+        False
+        >>> ExtendedContext.is_zero(0)
+        True
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.is_zero()
+
+    def ln(self, a):
+        """Returns the natural (base e) logarithm of the operand.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> c.ln(Decimal('0'))
+        Decimal('-Infinity')
+        >>> c.ln(Decimal('1.000'))
+        Decimal('0')
+        >>> c.ln(Decimal('2.71828183'))
+        Decimal('1.00000000')
+        >>> c.ln(Decimal('10'))
+        Decimal('2.30258509')
+        >>> c.ln(Decimal('+Infinity'))
+        Decimal('Infinity')
+        >>> c.ln(1)
+        Decimal('0')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.ln(context=self)
+
+    def log10(self, a):
+        """Returns the base 10 logarithm of the operand.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> c.log10(Decimal('0'))
+        Decimal('-Infinity')
+        >>> c.log10(Decimal('0.001'))
+        Decimal('-3')
+        >>> c.log10(Decimal('1.000'))
+        Decimal('0')
+        >>> c.log10(Decimal('2'))
+        Decimal('0.301029996')
+        >>> c.log10(Decimal('10'))
+        Decimal('1')
+        >>> c.log10(Decimal('70'))
+        Decimal('1.84509804')
+        >>> c.log10(Decimal('+Infinity'))
+        Decimal('Infinity')
+        >>> c.log10(0)
+        Decimal('-Infinity')
+        >>> c.log10(1)
+        Decimal('0')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.log10(context=self)
+
+    def logb(self, a):
+        """ Returns the exponent of the magnitude of the operand's MSD.
+
+        The result is the integer which is the exponent of the magnitude
+        of the most significant digit of the operand (as though the
+        operand were truncated to a single digit while maintaining the
+        value of that digit and without limiting the resulting exponent).
+
+        >>> ExtendedContext.logb(Decimal('250'))
+        Decimal('2')
+        >>> ExtendedContext.logb(Decimal('2.50'))
+        Decimal('0')
+        >>> ExtendedContext.logb(Decimal('0.03'))
+        Decimal('-2')
+        >>> ExtendedContext.logb(Decimal('0'))
+        Decimal('-Infinity')
+        >>> ExtendedContext.logb(1)
+        Decimal('0')
+        >>> ExtendedContext.logb(10)
+        Decimal('1')
+        >>> ExtendedContext.logb(100)
+        Decimal('2')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.logb(context=self)
+
+    def logical_and(self, a, b):
+        """Applies the logical operation 'and' between each operand's digits.
+
+        The operands must be both logical numbers.
+
+        >>> ExtendedContext.logical_and(Decimal('0'), Decimal('0'))
+        Decimal('0')
+        >>> ExtendedContext.logical_and(Decimal('0'), Decimal('1'))
+        Decimal('0')
+        >>> ExtendedContext.logical_and(Decimal('1'), Decimal('0'))
+        Decimal('0')
+        >>> ExtendedContext.logical_and(Decimal('1'), Decimal('1'))
+        Decimal('1')
+        >>> ExtendedContext.logical_and(Decimal('1100'), Decimal('1010'))
+        Decimal('1000')
+        >>> ExtendedContext.logical_and(Decimal('1111'), Decimal('10'))
+        Decimal('10')
+        >>> ExtendedContext.logical_and(110, 1101)
+        Decimal('100')
+        >>> ExtendedContext.logical_and(Decimal(110), 1101)
+        Decimal('100')
+        >>> ExtendedContext.logical_and(110, Decimal(1101))
+        Decimal('100')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.logical_and(b, context=self)
+
+    def logical_invert(self, a):
+        """Invert all the digits in the operand.
+
+        The operand must be a logical number.
+
+        >>> ExtendedContext.logical_invert(Decimal('0'))
+        Decimal('111111111')
+        >>> ExtendedContext.logical_invert(Decimal('1'))
+        Decimal('111111110')
+        >>> ExtendedContext.logical_invert(Decimal('111111111'))
+        Decimal('0')
+        >>> ExtendedContext.logical_invert(Decimal('101010101'))
+        Decimal('10101010')
+        >>> ExtendedContext.logical_invert(1101)
+        Decimal('111110010')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.logical_invert(context=self)
+
+    def logical_or(self, a, b):
+        """Applies the logical operation 'or' between each operand's digits.
+
+        The operands must be both logical numbers.
+
+        >>> ExtendedContext.logical_or(Decimal('0'), Decimal('0'))
+        Decimal('0')
+        >>> ExtendedContext.logical_or(Decimal('0'), Decimal('1'))
+        Decimal('1')
+        >>> ExtendedContext.logical_or(Decimal('1'), Decimal('0'))
+        Decimal('1')
+        >>> ExtendedContext.logical_or(Decimal('1'), Decimal('1'))
+        Decimal('1')
+        >>> ExtendedContext.logical_or(Decimal('1100'), Decimal('1010'))
+        Decimal('1110')
+        >>> ExtendedContext.logical_or(Decimal('1110'), Decimal('10'))
+        Decimal('1110')
+        >>> ExtendedContext.logical_or(110, 1101)
+        Decimal('1111')
+        >>> ExtendedContext.logical_or(Decimal(110), 1101)
+        Decimal('1111')
+        >>> ExtendedContext.logical_or(110, Decimal(1101))
+        Decimal('1111')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.logical_or(b, context=self)
+
+    def logical_xor(self, a, b):
+        """Applies the logical operation 'xor' between each operand's digits.
+
+        The operands must be both logical numbers.
+
+        >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('0'))
+        Decimal('0')
+        >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('1'))
+        Decimal('1')
+        >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('0'))
+        Decimal('1')
+        >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('1'))
+        Decimal('0')
+        >>> ExtendedContext.logical_xor(Decimal('1100'), Decimal('1010'))
+        Decimal('110')
+        >>> ExtendedContext.logical_xor(Decimal('1111'), Decimal('10'))
+        Decimal('1101')
+        >>> ExtendedContext.logical_xor(110, 1101)
+        Decimal('1011')
+        >>> ExtendedContext.logical_xor(Decimal(110), 1101)
+        Decimal('1011')
+        >>> ExtendedContext.logical_xor(110, Decimal(1101))
+        Decimal('1011')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.logical_xor(b, context=self)
+
+    def max(self, a, b):
+        """max compares two values numerically and returns the maximum.
+
+        If either operand is a NaN then the general rules apply.
+        Otherwise, the operands are compared as though by the compare
+        operation.  If they are numerically equal then the left-hand operand
+        is chosen as the result.  Otherwise the maximum (closer to positive
+        infinity) of the two operands is chosen as the result.
+
+        >>> ExtendedContext.max(Decimal('3'), Decimal('2'))
+        Decimal('3')
+        >>> ExtendedContext.max(Decimal('-10'), Decimal('3'))
+        Decimal('3')
+        >>> ExtendedContext.max(Decimal('1.0'), Decimal('1'))
+        Decimal('1')
+        >>> ExtendedContext.max(Decimal('7'), Decimal('NaN'))
+        Decimal('7')
+        >>> ExtendedContext.max(1, 2)
+        Decimal('2')
+        >>> ExtendedContext.max(Decimal(1), 2)
+        Decimal('2')
+        >>> ExtendedContext.max(1, Decimal(2))
+        Decimal('2')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.max(b, context=self)
+
+    def max_mag(self, a, b):
+        """Compares the values numerically with their sign ignored.
+
+        >>> ExtendedContext.max_mag(Decimal('7'), Decimal('NaN'))
+        Decimal('7')
+        >>> ExtendedContext.max_mag(Decimal('7'), Decimal('-10'))
+        Decimal('-10')
+        >>> ExtendedContext.max_mag(1, -2)
+        Decimal('-2')
+        >>> ExtendedContext.max_mag(Decimal(1), -2)
+        Decimal('-2')
+        >>> ExtendedContext.max_mag(1, Decimal(-2))
+        Decimal('-2')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.max_mag(b, context=self)
+
+    def min(self, a, b):
+        """min compares two values numerically and returns the minimum.
+
+        If either operand is a NaN then the general rules apply.
+        Otherwise, the operands are compared as though by the compare
+        operation.  If they are numerically equal then the left-hand operand
+        is chosen as the result.  Otherwise the minimum (closer to negative
+        infinity) of the two operands is chosen as the result.
+
+        >>> ExtendedContext.min(Decimal('3'), Decimal('2'))
+        Decimal('2')
+        >>> ExtendedContext.min(Decimal('-10'), Decimal('3'))
+        Decimal('-10')
+        >>> ExtendedContext.min(Decimal('1.0'), Decimal('1'))
+        Decimal('1.0')
+        >>> ExtendedContext.min(Decimal('7'), Decimal('NaN'))
+        Decimal('7')
+        >>> ExtendedContext.min(1, 2)
+        Decimal('1')
+        >>> ExtendedContext.min(Decimal(1), 2)
+        Decimal('1')
+        >>> ExtendedContext.min(1, Decimal(29))
+        Decimal('1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.min(b, context=self)
+
+    def min_mag(self, a, b):
+        """Compares the values numerically with their sign ignored.
+
+        >>> ExtendedContext.min_mag(Decimal('3'), Decimal('-2'))
+        Decimal('-2')
+        >>> ExtendedContext.min_mag(Decimal('-3'), Decimal('NaN'))
+        Decimal('-3')
+        >>> ExtendedContext.min_mag(1, -2)
+        Decimal('1')
+        >>> ExtendedContext.min_mag(Decimal(1), -2)
+        Decimal('1')
+        >>> ExtendedContext.min_mag(1, Decimal(-2))
+        Decimal('1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.min_mag(b, context=self)
+
+    def minus(self, a):
+        """Minus corresponds to unary prefix minus in Python.
+
+        The operation is evaluated using the same rules as subtract; the
+        operation minus(a) is calculated as subtract('0', a) where the '0'
+        has the same exponent as the operand.
+
+        >>> ExtendedContext.minus(Decimal('1.3'))
+        Decimal('-1.3')
+        >>> ExtendedContext.minus(Decimal('-1.3'))
+        Decimal('1.3')
+        >>> ExtendedContext.minus(1)
+        Decimal('-1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.__neg__(context=self)
+
+    def multiply(self, a, b):
+        """multiply multiplies two operands.
+
+        If either operand is a special value then the general rules apply.
+        Otherwise, the operands are multiplied together
+        ('long multiplication'), resulting in a number which may be as long as
+        the sum of the lengths of the two operands.
+
+        >>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
+        Decimal('3.60')
+        >>> ExtendedContext.multiply(Decimal('7'), Decimal('3'))
+        Decimal('21')
+        >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8'))
+        Decimal('0.72')
+        >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0'))
+        Decimal('-0.0')
+        >>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321'))
+        Decimal('4.28135971E+11')
+        >>> ExtendedContext.multiply(7, 7)
+        Decimal('49')
+        >>> ExtendedContext.multiply(Decimal(7), 7)
+        Decimal('49')
+        >>> ExtendedContext.multiply(7, Decimal(7))
+        Decimal('49')
+        """
+        a = _convert_other(a, raiseit=True)
+        r = a.__mul__(b, context=self)
+        if r is NotImplemented:
+            raise TypeError("Unable to convert %s to Decimal" % b)
+        else:
+            return r
+
+    def next_minus(self, a):
+        """Returns the largest representable number smaller than a.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> ExtendedContext.next_minus(Decimal('1'))
+        Decimal('0.999999999')
+        >>> c.next_minus(Decimal('1E-1007'))
+        Decimal('0E-1007')
+        >>> ExtendedContext.next_minus(Decimal('-1.00000003'))
+        Decimal('-1.00000004')
+        >>> c.next_minus(Decimal('Infinity'))
+        Decimal('9.99999999E+999')
+        >>> c.next_minus(1)
+        Decimal('0.999999999')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.next_minus(context=self)
+
+    def next_plus(self, a):
+        """Returns the smallest representable number larger than a.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> ExtendedContext.next_plus(Decimal('1'))
+        Decimal('1.00000001')
+        >>> c.next_plus(Decimal('-1E-1007'))
+        Decimal('-0E-1007')
+        >>> ExtendedContext.next_plus(Decimal('-1.00000003'))
+        Decimal('-1.00000002')
+        >>> c.next_plus(Decimal('-Infinity'))
+        Decimal('-9.99999999E+999')
+        >>> c.next_plus(1)
+        Decimal('1.00000001')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.next_plus(context=self)
+
+    def next_toward(self, a, b):
+        """Returns the number closest to a, in direction towards b.
+
+        The result is the closest representable number from the first
+        operand (but not the first operand) that is in the direction
+        towards the second operand, unless the operands have the same
+        value.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> c.next_toward(Decimal('1'), Decimal('2'))
+        Decimal('1.00000001')
+        >>> c.next_toward(Decimal('-1E-1007'), Decimal('1'))
+        Decimal('-0E-1007')
+        >>> c.next_toward(Decimal('-1.00000003'), Decimal('0'))
+        Decimal('-1.00000002')
+        >>> c.next_toward(Decimal('1'), Decimal('0'))
+        Decimal('0.999999999')
+        >>> c.next_toward(Decimal('1E-1007'), Decimal('-100'))
+        Decimal('0E-1007')
+        >>> c.next_toward(Decimal('-1.00000003'), Decimal('-10'))
+        Decimal('-1.00000004')
+        >>> c.next_toward(Decimal('0.00'), Decimal('-0.0000'))
+        Decimal('-0.00')
+        >>> c.next_toward(0, 1)
+        Decimal('1E-1007')
+        >>> c.next_toward(Decimal(0), 1)
+        Decimal('1E-1007')
+        >>> c.next_toward(0, Decimal(1))
+        Decimal('1E-1007')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.next_toward(b, context=self)
+
+    def normalize(self, a):
+        """normalize reduces an operand to its simplest form.
+
+        Essentially a plus operation with all trailing zeros removed from the
+        result.
+
+        >>> ExtendedContext.normalize(Decimal('2.1'))
+        Decimal('2.1')
+        >>> ExtendedContext.normalize(Decimal('-2.0'))
+        Decimal('-2')
+        >>> ExtendedContext.normalize(Decimal('1.200'))
+        Decimal('1.2')
+        >>> ExtendedContext.normalize(Decimal('-120'))
+        Decimal('-1.2E+2')
+        >>> ExtendedContext.normalize(Decimal('120.00'))
+        Decimal('1.2E+2')
+        >>> ExtendedContext.normalize(Decimal('0.00'))
+        Decimal('0')
+        >>> ExtendedContext.normalize(6)
+        Decimal('6')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.normalize(context=self)
+
+    def number_class(self, a):
+        """Returns an indication of the class of the operand.
+
+        The class is one of the following strings:
+          -sNaN
+          -NaN
+          -Infinity
+          -Normal
+          -Subnormal
+          -Zero
+          +Zero
+          +Subnormal
+          +Normal
+          +Infinity
+
+        >>> c = Context(ExtendedContext)
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> c.number_class(Decimal('Infinity'))
+        '+Infinity'
+        >>> c.number_class(Decimal('1E-10'))
+        '+Normal'
+        >>> c.number_class(Decimal('2.50'))
+        '+Normal'
+        >>> c.number_class(Decimal('0.1E-999'))
+        '+Subnormal'
+        >>> c.number_class(Decimal('0'))
+        '+Zero'
+        >>> c.number_class(Decimal('-0'))
+        '-Zero'
+        >>> c.number_class(Decimal('-0.1E-999'))
+        '-Subnormal'
+        >>> c.number_class(Decimal('-1E-10'))
+        '-Normal'
+        >>> c.number_class(Decimal('-2.50'))
+        '-Normal'
+        >>> c.number_class(Decimal('-Infinity'))
+        '-Infinity'
+        >>> c.number_class(Decimal('NaN'))
+        'NaN'
+        >>> c.number_class(Decimal('-NaN'))
+        'NaN'
+        >>> c.number_class(Decimal('sNaN'))
+        'sNaN'
+        >>> c.number_class(123)
+        '+Normal'
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.number_class(context=self)
+
+    def plus(self, a):
+        """Plus corresponds to unary prefix plus in Python.
+
+        The operation is evaluated using the same rules as add; the
+        operation plus(a) is calculated as add('0', a) where the '0'
+        has the same exponent as the operand.
+
+        >>> ExtendedContext.plus(Decimal('1.3'))
+        Decimal('1.3')
+        >>> ExtendedContext.plus(Decimal('-1.3'))
+        Decimal('-1.3')
+        >>> ExtendedContext.plus(-1)
+        Decimal('-1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.__pos__(context=self)
+
+    def power(self, a, b, modulo=None):
+        """Raises a to the power of b, to modulo if given.
+
+        With two arguments, compute a**b.  If a is negative then b
+        must be integral.  The result will be inexact unless b is
+        integral and the result is finite and can be expressed exactly
+        in 'precision' digits.
+
+        With three arguments, compute (a**b) % modulo.  For the
+        three argument form, the following restrictions on the
+        arguments hold:
+
+         - all three arguments must be integral
+         - b must be nonnegative
+         - at least one of a or b must be nonzero
+         - modulo must be nonzero and have at most 'precision' digits
+
+        The result of pow(a, b, modulo) is identical to the result
+        that would be obtained by computing (a**b) % modulo with
+        unbounded precision, but is computed more efficiently.  It is
+        always exact.
+
+        >>> c = ExtendedContext.copy()
+        >>> c.Emin = -999
+        >>> c.Emax = 999
+        >>> c.power(Decimal('2'), Decimal('3'))
+        Decimal('8')
+        >>> c.power(Decimal('-2'), Decimal('3'))
+        Decimal('-8')
+        >>> c.power(Decimal('2'), Decimal('-3'))
+        Decimal('0.125')
+        >>> c.power(Decimal('1.7'), Decimal('8'))
+        Decimal('69.7575744')
+        >>> c.power(Decimal('10'), Decimal('0.301029996'))
+        Decimal('2.00000000')
+        >>> c.power(Decimal('Infinity'), Decimal('-1'))
+        Decimal('0')
+        >>> c.power(Decimal('Infinity'), Decimal('0'))
+        Decimal('1')
+        >>> c.power(Decimal('Infinity'), Decimal('1'))
+        Decimal('Infinity')
+        >>> c.power(Decimal('-Infinity'), Decimal('-1'))
+        Decimal('-0')
+        >>> c.power(Decimal('-Infinity'), Decimal('0'))
+        Decimal('1')
+        >>> c.power(Decimal('-Infinity'), Decimal('1'))
+        Decimal('-Infinity')
+        >>> c.power(Decimal('-Infinity'), Decimal('2'))
+        Decimal('Infinity')
+        >>> c.power(Decimal('0'), Decimal('0'))
+        Decimal('NaN')
+
+        >>> c.power(Decimal('3'), Decimal('7'), Decimal('16'))
+        Decimal('11')
+        >>> c.power(Decimal('-3'), Decimal('7'), Decimal('16'))
+        Decimal('-11')
+        >>> c.power(Decimal('-3'), Decimal('8'), Decimal('16'))
+        Decimal('1')
+        >>> c.power(Decimal('3'), Decimal('7'), Decimal('-16'))
+        Decimal('11')
+        >>> c.power(Decimal('23E12345'), Decimal('67E189'), Decimal('123456789'))
+        Decimal('11729830')
+        >>> c.power(Decimal('-0'), Decimal('17'), Decimal('1729'))
+        Decimal('-0')
+        >>> c.power(Decimal('-23'), Decimal('0'), Decimal('65537'))
+        Decimal('1')
+        >>> ExtendedContext.power(7, 7)
+        Decimal('823543')
+        >>> ExtendedContext.power(Decimal(7), 7)
+        Decimal('823543')
+        >>> ExtendedContext.power(7, Decimal(7), 2)
+        Decimal('1')
+        """
+        a = _convert_other(a, raiseit=True)
+        r = a.__pow__(b, modulo, context=self)
+        if r is NotImplemented:
+            raise TypeError("Unable to convert %s to Decimal" % b)
+        else:
+            return r
+
+    def quantize(self, a, b):
+        """Returns a value equal to 'a' (rounded), having the exponent of 'b'.
+
+        The coefficient of the result is derived from that of the left-hand
+        operand.  It may be rounded using the current rounding setting (if the
+        exponent is being increased), multiplied by a positive power of ten (if
+        the exponent is being decreased), or is unchanged (if the exponent is
+        already equal to that of the right-hand operand).
+
+        Unlike other operations, if the length of the coefficient after the
+        quantize operation would be greater than precision then an Invalid
+        operation condition is raised.  This guarantees that, unless there is
+        an error condition, the exponent of the result of a quantize is always
+        equal to that of the right-hand operand.
+
+        Also unlike other operations, quantize will never raise Underflow, even
+        if the result is subnormal and inexact.
+
+        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001'))
+        Decimal('2.170')
+        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01'))
+        Decimal('2.17')
+        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1'))
+        Decimal('2.2')
+        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0'))
+        Decimal('2')
+        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1'))
+        Decimal('0E+1')
+        >>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity'))
+        Decimal('-Infinity')
+        >>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity'))
+        Decimal('NaN')
+        >>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1'))
+        Decimal('-0')
+        >>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5'))
+        Decimal('-0E+5')
+        >>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2'))
+        Decimal('NaN')
+        >>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2'))
+        Decimal('NaN')
+        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1'))
+        Decimal('217.0')
+        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0'))
+        Decimal('217')
+        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1'))
+        Decimal('2.2E+2')
+        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2'))
+        Decimal('2E+2')
+        >>> ExtendedContext.quantize(1, 2)
+        Decimal('1')
+        >>> ExtendedContext.quantize(Decimal(1), 2)
+        Decimal('1')
+        >>> ExtendedContext.quantize(1, Decimal(2))
+        Decimal('1')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.quantize(b, context=self)
+
+    def radix(self):
+        """Just returns 10, as this is Decimal, :)
+
+        >>> ExtendedContext.radix()
+        Decimal('10')
+        """
+        return Decimal(10)
+
+    def remainder(self, a, b):
+        """Returns the remainder from integer division.
+
+        The result is the residue of the dividend after the operation of
+        calculating integer division as described for divide-integer, rounded
+        to precision digits if necessary.  The sign of the result, if
+        non-zero, is the same as that of the original dividend.
+
+        This operation will fail under the same conditions as integer division
+        (that is, if integer division on the same two operands would fail, the
+        remainder cannot be calculated).
+
+        >>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3'))
+        Decimal('2.1')
+        >>> ExtendedContext.remainder(Decimal('10'), Decimal('3'))
+        Decimal('1')
+        >>> ExtendedContext.remainder(Decimal('-10'), Decimal('3'))
+        Decimal('-1')
+        >>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1'))
+        Decimal('0.2')
+        >>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3'))
+        Decimal('0.1')
+        >>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3'))
+        Decimal('1.0')
+        >>> ExtendedContext.remainder(22, 6)
+        Decimal('4')
+        >>> ExtendedContext.remainder(Decimal(22), 6)
+        Decimal('4')
+        >>> ExtendedContext.remainder(22, Decimal(6))
+        Decimal('4')
+        """
+        a = _convert_other(a, raiseit=True)
+        r = a.__mod__(b, context=self)
+        if r is NotImplemented:
+            raise TypeError("Unable to convert %s to Decimal" % b)
+        else:
+            return r
+
+    def remainder_near(self, a, b):
+        """Returns to be "a - b * n", where n is the integer nearest the exact
+        value of "x / b" (if two integers are equally near then the even one
+        is chosen).  If the result is equal to 0 then its sign will be the
+        sign of a.
+
+        This operation will fail under the same conditions as integer division
+        (that is, if integer division on the same two operands would fail, the
+        remainder cannot be calculated).
+
+        >>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3'))
+        Decimal('-0.9')
+        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6'))
+        Decimal('-2')
+        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3'))
+        Decimal('1')
+        >>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3'))
+        Decimal('-1')
+        >>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1'))
+        Decimal('0.2')
+        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3'))
+        Decimal('0.1')
+        >>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3'))
+        Decimal('-0.3')
+        >>> ExtendedContext.remainder_near(3, 11)
+        Decimal('3')
+        >>> ExtendedContext.remainder_near(Decimal(3), 11)
+        Decimal('3')
+        >>> ExtendedContext.remainder_near(3, Decimal(11))
+        Decimal('3')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.remainder_near(b, context=self)
+
+    def rotate(self, a, b):
+        """Returns a rotated copy of a, b times.
+
+        The coefficient of the result is a rotated copy of the digits in
+        the coefficient of the first operand.  The number of places of
+        rotation is taken from the absolute value of the second operand,
+        with the rotation being to the left if the second operand is
+        positive or to the right otherwise.
+
+        >>> ExtendedContext.rotate(Decimal('34'), Decimal('8'))
+        Decimal('400000003')
+        >>> ExtendedContext.rotate(Decimal('12'), Decimal('9'))
+        Decimal('12')
+        >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('-2'))
+        Decimal('891234567')
+        >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('0'))
+        Decimal('123456789')
+        >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('+2'))
+        Decimal('345678912')
+        >>> ExtendedContext.rotate(1333333, 1)
+        Decimal('13333330')
+        >>> ExtendedContext.rotate(Decimal(1333333), 1)
+        Decimal('13333330')
+        >>> ExtendedContext.rotate(1333333, Decimal(1))
+        Decimal('13333330')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.rotate(b, context=self)
+
+    def same_quantum(self, a, b):
+        """Returns True if the two operands have the same exponent.
+
+        The result is never affected by either the sign or the coefficient of
+        either operand.
+
+        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.001'))
+        False
+        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.01'))
+        True
+        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('1'))
+        False
+        >>> ExtendedContext.same_quantum(Decimal('Inf'), Decimal('-Inf'))
+        True
+        >>> ExtendedContext.same_quantum(10000, -1)
+        True
+        >>> ExtendedContext.same_quantum(Decimal(10000), -1)
+        True
+        >>> ExtendedContext.same_quantum(10000, Decimal(-1))
+        True
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.same_quantum(b)
+
+    def scaleb (self, a, b):
+        """Returns the first operand after adding the second value its exp.
+
+        >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('-2'))
+        Decimal('0.0750')
+        >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('0'))
+        Decimal('7.50')
+        >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('3'))
+        Decimal('7.50E+3')
+        >>> ExtendedContext.scaleb(1, 4)
+        Decimal('1E+4')
+        >>> ExtendedContext.scaleb(Decimal(1), 4)
+        Decimal('1E+4')
+        >>> ExtendedContext.scaleb(1, Decimal(4))
+        Decimal('1E+4')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.scaleb(b, context=self)
+
+    def shift(self, a, b):
+        """Returns a shifted copy of a, b times.
+
+        The coefficient of the result is a shifted copy of the digits
+        in the coefficient of the first operand.  The number of places
+        to shift is taken from the absolute value of the second operand,
+        with the shift being to the left if the second operand is
+        positive or to the right otherwise.  Digits shifted into the
+        coefficient are zeros.
+
+        >>> ExtendedContext.shift(Decimal('34'), Decimal('8'))
+        Decimal('400000000')
+        >>> ExtendedContext.shift(Decimal('12'), Decimal('9'))
+        Decimal('0')
+        >>> ExtendedContext.shift(Decimal('123456789'), Decimal('-2'))
+        Decimal('1234567')
+        >>> ExtendedContext.shift(Decimal('123456789'), Decimal('0'))
+        Decimal('123456789')
+        >>> ExtendedContext.shift(Decimal('123456789'), Decimal('+2'))
+        Decimal('345678900')
+        >>> ExtendedContext.shift(88888888, 2)
+        Decimal('888888800')
+        >>> ExtendedContext.shift(Decimal(88888888), 2)
+        Decimal('888888800')
+        >>> ExtendedContext.shift(88888888, Decimal(2))
+        Decimal('888888800')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.shift(b, context=self)
+
+    def sqrt(self, a):
+        """Square root of a non-negative number to context precision.
+
+        If the result must be inexact, it is rounded using the round-half-even
+        algorithm.
+
+        >>> ExtendedContext.sqrt(Decimal('0'))
+        Decimal('0')
+        >>> ExtendedContext.sqrt(Decimal('-0'))
+        Decimal('-0')
+        >>> ExtendedContext.sqrt(Decimal('0.39'))
+        Decimal('0.624499800')
+        >>> ExtendedContext.sqrt(Decimal('100'))
+        Decimal('10')
+        >>> ExtendedContext.sqrt(Decimal('1'))
+        Decimal('1')
+        >>> ExtendedContext.sqrt(Decimal('1.0'))
+        Decimal('1.0')
+        >>> ExtendedContext.sqrt(Decimal('1.00'))
+        Decimal('1.0')
+        >>> ExtendedContext.sqrt(Decimal('7'))
+        Decimal('2.64575131')
+        >>> ExtendedContext.sqrt(Decimal('10'))
+        Decimal('3.16227766')
+        >>> ExtendedContext.sqrt(2)
+        Decimal('1.41421356')
+        >>> ExtendedContext.prec
+        9
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.sqrt(context=self)
+
+    def subtract(self, a, b):
+        """Return the difference between the two operands.
+
+        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07'))
+        Decimal('0.23')
+        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30'))
+        Decimal('0.00')
+        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07'))
+        Decimal('-0.77')
+        >>> ExtendedContext.subtract(8, 5)
+        Decimal('3')
+        >>> ExtendedContext.subtract(Decimal(8), 5)
+        Decimal('3')
+        >>> ExtendedContext.subtract(8, Decimal(5))
+        Decimal('3')
+        """
+        a = _convert_other(a, raiseit=True)
+        r = a.__sub__(b, context=self)
+        if r is NotImplemented:
+            raise TypeError("Unable to convert %s to Decimal" % b)
+        else:
+            return r
+
+    def to_eng_string(self, a):
+        """Converts a number to a string, using scientific notation.
+
+        The operation is not affected by the context.
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.to_eng_string(context=self)
+
+    def to_sci_string(self, a):
+        """Converts a number to a string, using scientific notation.
+
+        The operation is not affected by the context.
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.__str__(context=self)
+
+    def to_integral_exact(self, a):
+        """Rounds to an integer.
+
+        When the operand has a negative exponent, the result is the same
+        as using the quantize() operation using the given operand as the
+        left-hand-operand, 1E+0 as the right-hand-operand, and the precision
+        of the operand as the precision setting; Inexact and Rounded flags
+        are allowed in this operation.  The rounding mode is taken from the
+        context.
+
+        >>> ExtendedContext.to_integral_exact(Decimal('2.1'))
+        Decimal('2')
+        >>> ExtendedContext.to_integral_exact(Decimal('100'))
+        Decimal('100')
+        >>> ExtendedContext.to_integral_exact(Decimal('100.0'))
+        Decimal('100')
+        >>> ExtendedContext.to_integral_exact(Decimal('101.5'))
+        Decimal('102')
+        >>> ExtendedContext.to_integral_exact(Decimal('-101.5'))
+        Decimal('-102')
+        >>> ExtendedContext.to_integral_exact(Decimal('10E+5'))
+        Decimal('1.0E+6')
+        >>> ExtendedContext.to_integral_exact(Decimal('7.89E+77'))
+        Decimal('7.89E+77')
+        >>> ExtendedContext.to_integral_exact(Decimal('-Inf'))
+        Decimal('-Infinity')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.to_integral_exact(context=self)
+
+    def to_integral_value(self, a):
+        """Rounds to an integer.
+
+        When the operand has a negative exponent, the result is the same
+        as using the quantize() operation using the given operand as the
+        left-hand-operand, 1E+0 as the right-hand-operand, and the precision
+        of the operand as the precision setting, except that no flags will
+        be set.  The rounding mode is taken from the context.
+
+        >>> ExtendedContext.to_integral_value(Decimal('2.1'))
+        Decimal('2')
+        >>> ExtendedContext.to_integral_value(Decimal('100'))
+        Decimal('100')
+        >>> ExtendedContext.to_integral_value(Decimal('100.0'))
+        Decimal('100')
+        >>> ExtendedContext.to_integral_value(Decimal('101.5'))
+        Decimal('102')
+        >>> ExtendedContext.to_integral_value(Decimal('-101.5'))
+        Decimal('-102')
+        >>> ExtendedContext.to_integral_value(Decimal('10E+5'))
+        Decimal('1.0E+6')
+        >>> ExtendedContext.to_integral_value(Decimal('7.89E+77'))
+        Decimal('7.89E+77')
+        >>> ExtendedContext.to_integral_value(Decimal('-Inf'))
+        Decimal('-Infinity')
+        """
+        a = _convert_other(a, raiseit=True)
+        return a.to_integral_value(context=self)
+
+    # the method name changed, but we provide also the old one, for compatibility
+    to_integral = to_integral_value
+
+class _WorkRep(object):
+    __slots__ = ('sign','int','exp')
+    # sign: 0 or 1
+    # int:  int or long
+    # exp:  None, int, or string
+
+    def __init__(self, value=None):
+        if value is None:
+            self.sign = None
+            self.int = 0
+            self.exp = None
+        elif isinstance(value, Decimal):
+            self.sign = value._sign
+            self.int = int(value._int)
+            self.exp = value._exp
+        else:
+            # assert isinstance(value, tuple)
+            self.sign = value[0]
+            self.int = value[1]
+            self.exp = value[2]
+
+    def __repr__(self):
+        return "(%r, %r, %r)" % (self.sign, self.int, self.exp)
+
+    __str__ = __repr__
+
+
+
+def _normalize(op1, op2, prec = 0):
+    """Normalizes op1, op2 to have the same exp and length of coefficient.
+
+    Done during addition.
+    """
+    if op1.exp < op2.exp:
+        tmp = op2
+        other = op1
+    else:
+        tmp = op1
+        other = op2
+
+    # Let exp = min(tmp.exp - 1, tmp.adjusted() - precision - 1).
+    # Then adding 10**exp to tmp has the same effect (after rounding)
+    # as adding any positive quantity smaller than 10**exp; similarly
+    # for subtraction.  So if other is smaller than 10**exp we replace
+    # it with 10**exp.  This avoids tmp.exp - other.exp getting too large.
+    tmp_len = len(str(tmp.int))
+    other_len = len(str(other.int))
+    exp = tmp.exp + min(-1, tmp_len - prec - 2)
+    if other_len + other.exp - 1 < exp:
+        other.int = 1
+        other.exp = exp
+
+    tmp.int *= 10 ** (tmp.exp - other.exp)
+    tmp.exp = other.exp
+    return op1, op2
+
+##### Integer arithmetic functions used by ln, log10, exp and __pow__ #####
+
+# This function from Tim Peters was taken from here:
+# http://mail.python.org/pipermail/python-list/1999-July/007758.html
+# The correction being in the function definition is for speed, and
+# the whole function is not resolved with math.log because of avoiding
+# the use of floats.
+def _nbits(n, correction = {
+        '0': 4, '1': 3, '2': 2, '3': 2,
+        '4': 1, '5': 1, '6': 1, '7': 1,
+        '8': 0, '9': 0, 'a': 0, 'b': 0,
+        'c': 0, 'd': 0, 'e': 0, 'f': 0}):
+    """Number of bits in binary representation of the positive integer n,
+    or 0 if n == 0.
+    """
+    if n < 0:
+        raise ValueError("The argument to _nbits should be nonnegative.")
+    hex_n = "%x" % n
+    return 4*len(hex_n) - correction[hex_n[0]]
+
+def _sqrt_nearest(n, a):
+    """Closest integer to the square root of the positive integer n.  a is
+    an initial approximation to the square root.  Any positive integer
+    will do for a, but the closer a is to the square root of n the
+    faster convergence will be.
+
+    """
+    if n <= 0 or a <= 0:
+        raise ValueError("Both arguments to _sqrt_nearest should be positive.")
+
+    b=0
+    while a != b:
+        b, a = a, a--n//a>>1
+    return a
+
+def _rshift_nearest(x, shift):
+    """Given an integer x and a nonnegative integer shift, return closest
+    integer to x / 2**shift; use round-to-even in case of a tie.
+
+    """
+    b, q = 1L << shift, x >> shift
+    return q + (2*(x & (b-1)) + (q&1) > b)
+
+def _div_nearest(a, b):
+    """Closest integer to a/b, a and b positive integers; rounds to even
+    in the case of a tie.
+
+    """
+    q, r = divmod(a, b)
+    return q + (2*r + (q&1) > b)
+
+def _ilog(x, M, L = 8):
+    """Integer approximation to M*log(x/M), with absolute error boundable
+    in terms only of x/M.
+
+    Given positive integers x and M, return an integer approximation to
+    M * log(x/M).  For L = 8 and 0.1 <= x/M <= 10 the difference
+    between the approximation and the exact result is at most 22.  For
+    L = 8 and 1.0 <= x/M <= 10.0 the difference is at most 15.  In
+    both cases these are upper bounds on the error; it will usually be
+    much smaller."""
+
+    # The basic algorithm is the following: let log1p be the function
+    # log1p(x) = log(1+x).  Then log(x/M) = log1p((x-M)/M).  We use
+    # the reduction
+    #
+    #    log1p(y) = 2*log1p(y/(1+sqrt(1+y)))
+    #
+    # repeatedly until the argument to log1p is small (< 2**-L in
+    # absolute value).  For small y we can use the Taylor series
+    # expansion
+    #
+    #    log1p(y) ~ y - y**2/2 + y**3/3 - ... - (-y)**T/T
+    #
+    # truncating at T such that y**T is small enough.  The whole
+    # computation is carried out in a form of fixed-point arithmetic,
+    # with a real number z being represented by an integer
+    # approximation to z*M.  To avoid loss of precision, the y below
+    # is actually an integer approximation to 2**R*y*M, where R is the
+    # number of reductions performed so far.
+
+    y = x-M
+    # argument reduction; R = number of reductions performed
+    R = 0
+    while (R <= L and long(abs(y)) << L-R >= M or
+           R > L and abs(y) >> R-L >= M):
+        y = _div_nearest(long(M*y) << 1,
+                         M + _sqrt_nearest(M*(M+_rshift_nearest(y, R)), M))
+        R += 1
+
+    # Taylor series with T terms
+    T = -int(-10*len(str(M))//(3*L))
+    yshift = _rshift_nearest(y, R)
+    w = _div_nearest(M, T)
+    for k in xrange(T-1, 0, -1):
+        w = _div_nearest(M, k) - _div_nearest(yshift*w, M)
+
+    return _div_nearest(w*y, M)
+
+def _dlog10(c, e, p):
+    """Given integers c, e and p with c > 0, p >= 0, compute an integer
+    approximation to 10**p * log10(c*10**e), with an absolute error of
+    at most 1.  Assumes that c*10**e is not exactly 1."""
+
+    # increase precision by 2; compensate for this by dividing
+    # final result by 100
+    p += 2
+
+    # write c*10**e as d*10**f with either:
+    #   f >= 0 and 1 <= d <= 10, or
+    #   f <= 0 and 0.1 <= d <= 1.
+    # Thus for c*10**e close to 1, f = 0
+    l = len(str(c))
+    f = e+l - (e+l >= 1)
+
+    if p > 0:
+        M = 10**p
+        k = e+p-f
+        if k >= 0:
+            c *= 10**k
+        else:
+            c = _div_nearest(c, 10**-k)
+
+        log_d = _ilog(c, M) # error < 5 + 22 = 27
+        log_10 = _log10_digits(p) # error < 1
+        log_d = _div_nearest(log_d*M, log_10)
+        log_tenpower = f*M # exact
+    else:
+        log_d = 0  # error < 2.31
+        log_tenpower = _div_nearest(f, 10**-p) # error < 0.5
+
+    return _div_nearest(log_tenpower+log_d, 100)
+
+def _dlog(c, e, p):
+    """Given integers c, e and p with c > 0, compute an integer
+    approximation to 10**p * log(c*10**e), with an absolute error of
+    at most 1.  Assumes that c*10**e is not exactly 1."""
+
+    # Increase precision by 2. The precision increase is compensated
+    # for at the end with a division by 100.
+    p += 2
+
+    # rewrite c*10**e as d*10**f with either f >= 0 and 1 <= d <= 10,
+    # or f <= 0 and 0.1 <= d <= 1.  Then we can compute 10**p * log(c*10**e)
+    # as 10**p * log(d) + 10**p*f * log(10).
+    l = len(str(c))
+    f = e+l - (e+l >= 1)
+
+    # compute approximation to 10**p*log(d), with error < 27
+    if p > 0:
+        k = e+p-f
+        if k >= 0:
+            c *= 10**k
+        else:
+            c = _div_nearest(c, 10**-k)  # error of <= 0.5 in c
+
+        # _ilog magnifies existing error in c by a factor of at most 10
+        log_d = _ilog(c, 10**p) # error < 5 + 22 = 27
+    else:
+        # p <= 0: just approximate the whole thing by 0; error < 2.31
+        log_d = 0
+
+    # compute approximation to f*10**p*log(10), with error < 11.
+    if f:
+        extra = len(str(abs(f)))-1
+        if p + extra >= 0:
+            # error in f * _log10_digits(p+extra) < |f| * 1 = |f|
+            # after division, error < |f|/10**extra + 0.5 < 10 + 0.5 < 11
+            f_log_ten = _div_nearest(f*_log10_digits(p+extra), 10**extra)
+        else:
+            f_log_ten = 0
+    else:
+        f_log_ten = 0
+
+    # error in sum < 11+27 = 38; error after division < 0.38 + 0.5 < 1
+    return _div_nearest(f_log_ten + log_d, 100)
+
+class _Log10Memoize(object):
+    """Class to compute, store, and allow retrieval of, digits of the
+    constant log(10) = 2.302585....  This constant is needed by
+    Decimal.ln, Decimal.log10, Decimal.exp and Decimal.__pow__."""
+    def __init__(self):
+        self.digits = "23025850929940456840179914546843642076011014886"
+
+    def getdigits(self, p):
+        """Given an integer p >= 0, return floor(10**p)*log(10).
+
+        For example, self.getdigits(3) returns 2302.
+        """
+        # digits are stored as a string, for quick conversion to
+        # integer in the case that we've already computed enough
+        # digits; the stored digits should always be correct
+        # (truncated, not rounded to nearest).
+        if p < 0:
+            raise ValueError("p should be nonnegative")
+
+        if p >= len(self.digits):
+            # compute p+3, p+6, p+9, ... digits; continue until at
+            # least one of the extra digits is nonzero
+            extra = 3
+            while True:
+                # compute p+extra digits, correct to within 1ulp
+                M = 10**(p+extra+2)
+                digits = str(_div_nearest(_ilog(10*M, M), 100))
+                if digits[-extra:] != '0'*extra:
+                    break
+                extra += 3
+            # keep all reliable digits so far; remove trailing zeros
+            # and next nonzero digit
+            self.digits = digits.rstrip('0')[:-1]
+        return int(self.digits[:p+1])
+
+_log10_digits = _Log10Memoize().getdigits
+
+def _iexp(x, M, L=8):
+    """Given integers x and M, M > 0, such that x/M is small in absolute
+    value, compute an integer approximation to M*exp(x/M).  For 0 <=
+    x/M <= 2.4, the absolute error in the result is bounded by 60 (and
+    is usually much smaller)."""
+
+    # Algorithm: to compute exp(z) for a real number z, first divide z
+    # by a suitable power R of 2 so that |z/2**R| < 2**-L.  Then
+    # compute expm1(z/2**R) = exp(z/2**R) - 1 using the usual Taylor
+    # series
+    #
+    #     expm1(x) = x + x**2/2! + x**3/3! + ...
+    #
+    # Now use the identity
+    #
+    #     expm1(2x) = expm1(x)*(expm1(x)+2)
+    #
+    # R times to compute the sequence expm1(z/2**R),
+    # expm1(z/2**(R-1)), ... , exp(z/2), exp(z).
+
+    # Find R such that x/2**R/M <= 2**-L
+    R = _nbits((long(x)<<L)//M)
+
+    # Taylor series.  (2**L)**T > M
+    T = -int(-10*len(str(M))//(3*L))
+    y = _div_nearest(x, T)
+    Mshift = long(M)<<R
+    for i in xrange(T-1, 0, -1):
+        y = _div_nearest(x*(Mshift + y), Mshift * i)
+
+    # Expansion
+    for k in xrange(R-1, -1, -1):
+        Mshift = long(M)<<(k+2)
+        y = _div_nearest(y*(y+Mshift), Mshift)
+
+    return M+y
+
+def _dexp(c, e, p):
+    """Compute an approximation to exp(c*10**e), with p decimal places of
+    precision.
+
+    Returns integers d, f such that:
+
+      10**(p-1) <= d <= 10**p, and
+      (d-1)*10**f < exp(c*10**e) < (d+1)*10**f
+
+    In other words, d*10**f is an approximation to exp(c*10**e) with p
+    digits of precision, and with an error in d of at most 1.  This is
+    almost, but not quite, the same as the error being < 1ulp: when d
+    = 10**(p-1) the error could be up to 10 ulp."""
+
+    # we'll call iexp with M = 10**(p+2), giving p+3 digits of precision
+    p += 2
+
+    # compute log(10) with extra precision = adjusted exponent of c*10**e
+    extra = max(0, e + len(str(c)) - 1)
+    q = p + extra
+
+    # compute quotient c*10**e/(log(10)) = c*10**(e+q)/(log(10)*10**q),
+    # rounding down
+    shift = e+q
+    if shift >= 0:
+        cshift = c*10**shift
+    else:
+        cshift = c//10**-shift
+    quot, rem = divmod(cshift, _log10_digits(q))
+
+    # reduce remainder back to original precision
+    rem = _div_nearest(rem, 10**extra)
+
+    # error in result of _iexp < 120;  error after division < 0.62
+    return _div_nearest(_iexp(rem, 10**p), 1000), quot - p + 3
+
+def _dpower(xc, xe, yc, ye, p):
+    """Given integers xc, xe, yc and ye representing Decimals x = xc*10**xe and
+    y = yc*10**ye, compute x**y.  Returns a pair of integers (c, e) such that:
+
+      10**(p-1) <= c <= 10**p, and
+      (c-1)*10**e < x**y < (c+1)*10**e
+
+    in other words, c*10**e is an approximation to x**y with p digits
+    of precision, and with an error in c of at most 1.  (This is
+    almost, but not quite, the same as the error being < 1ulp: when c
+    == 10**(p-1) we can only guarantee error < 10ulp.)
+
+    We assume that: x is positive and not equal to 1, and y is nonzero.
+    """
+
+    # Find b such that 10**(b-1) <= |y| <= 10**b
+    b = len(str(abs(yc))) + ye
+
+    # log(x) = lxc*10**(-p-b-1), to p+b+1 places after the decimal point
+    lxc = _dlog(xc, xe, p+b+1)
+
+    # compute product y*log(x) = yc*lxc*10**(-p-b-1+ye) = pc*10**(-p-1)
+    shift = ye-b
+    if shift >= 0:
+        pc = lxc*yc*10**shift
+    else:
+        pc = _div_nearest(lxc*yc, 10**-shift)
+
+    if pc == 0:
+        # we prefer a result that isn't exactly 1; this makes it
+        # easier to compute a correctly rounded result in __pow__
+        if ((len(str(xc)) + xe >= 1) == (yc > 0)): # if x**y > 1:
+            coeff, exp = 10**(p-1)+1, 1-p
+        else:
+            coeff, exp = 10**p-1, -p
+    else:
+        coeff, exp = _dexp(pc, -(p+1), p+1)
+        coeff = _div_nearest(coeff, 10)
+        exp += 1
+
+    return coeff, exp
+
+def _log10_lb(c, correction = {
+        '1': 100, '2': 70, '3': 53, '4': 40, '5': 31,
+        '6': 23, '7': 16, '8': 10, '9': 5}):
+    """Compute a lower bound for 100*log10(c) for a positive integer c."""
+    if c <= 0:
+        raise ValueError("The argument to _log10_lb should be nonnegative.")
+    str_c = str(c)
+    return 100*len(str_c) - correction[str_c[0]]
+
+##### Helper Functions ####################################################
+
+def _convert_other(other, raiseit=False, allow_float=False):
+    """Convert other to Decimal.
+
+    Verifies that it's ok to use in an implicit construction.
+    If allow_float is true, allow conversion from float;  this
+    is used in the comparison methods (__eq__ and friends).
+
+    """
+    if isinstance(other, Decimal):
+        return other
+    if isinstance(other, (int, long)):
+        return Decimal(other)
+    if allow_float and isinstance(other, float):
+        return Decimal.from_float(other)
+
+    if raiseit:
+        raise TypeError("Unable to convert %s to Decimal" % other)
+    return NotImplemented
+
+##### Setup Specific Contexts ############################################
+
+# The default context prototype used by Context()
+# Is mutable, so that new contexts can have different default values
+
+DefaultContext = Context(
+        prec=28, rounding=ROUND_HALF_EVEN,
+        traps=[DivisionByZero, Overflow, InvalidOperation],
+        flags=[],
+        Emax=999999999,
+        Emin=-999999999,
+        capitals=1
+)
+
+# Pre-made alternate contexts offered by the specification
+# Don't change these; the user should be able to select these
+# contexts and be able to reproduce results from other implementations
+# of the spec.
+
+BasicContext = Context(
+        prec=9, rounding=ROUND_HALF_UP,
+        traps=[DivisionByZero, Overflow, InvalidOperation, Clamped, Underflow],
+        flags=[],
+)
+
+ExtendedContext = Context(
+        prec=9, rounding=ROUND_HALF_EVEN,
+        traps=[],
+        flags=[],
+)
+
+
+##### crud for parsing strings #############################################
+#
+# Regular expression used for parsing numeric strings.  Additional
+# comments:
+#
+# 1. Uncomment the two '\s*' lines to allow leading and/or trailing
+# whitespace.  But note that the specification disallows whitespace in
+# a numeric string.
+#
+# 2. For finite numbers (not infinities and NaNs) the body of the
+# number between the optional sign and the optional exponent must have
+# at least one decimal digit, possibly after the decimal point.  The
+# lookahead expression '(?=\d|\.\d)' checks this.
+
+import re
+_parser = re.compile(r"""        # A numeric string consists of:
+#    \s*
+    (?P<sign>[-+])?              # an optional sign, followed by either...
+    (
+        (?=\d|\.\d)              # ...a number (with at least one digit)
+        (?P<int>\d*)             # having a (possibly empty) integer part
+        (\.(?P<frac>\d*))?       # followed by an optional fractional part
+        (E(?P<exp>[-+]?\d+))?    # followed by an optional exponent, or...
+    |
+        Inf(inity)?              # ...an infinity, or...
+    |
+        (?P<signal>s)?           # ...an (optionally signaling)
+        NaN                      # NaN
+        (?P<diag>\d*)            # with (possibly empty) diagnostic info.
+    )
+#    \s*
+    \Z
+""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match
+
+_all_zeros = re.compile('0*$').match
+_exact_half = re.compile('50*$').match
+
+##### PEP3101 support functions ##############################################
+# The functions in this section have little to do with the Decimal
+# class, and could potentially be reused or adapted for other pure
+# Python numeric classes that want to implement __format__
+#
+# A format specifier for Decimal looks like:
+#
+#   [[fill]align][sign][0][minimumwidth][,][.precision][type]
+
+_parse_format_specifier_regex = re.compile(r"""\A
+(?:
+   (?P<fill>.)?
+   (?P<align>[<>=^])
+)?
+(?P<sign>[-+ ])?
+(?P<zeropad>0)?
+(?P<minimumwidth>(?!0)\d+)?
+(?P<thousands_sep>,)?
+(?:\.(?P<precision>0|(?!0)\d+))?
+(?P<type>[eEfFgGn%])?
+\Z
+""", re.VERBOSE)
+
+del re
+
+# The locale module is only needed for the 'n' format specifier.  The
+# rest of the PEP 3101 code functions quite happily without it, so we
+# don't care too much if locale isn't present.
+try:
+    import locale as _locale
+except ImportError:
+    pass
+
+def _parse_format_specifier(format_spec, _localeconv=None):
+    """Parse and validate a format specifier.
+
+    Turns a standard numeric format specifier into a dict, with the
+    following entries:
+
+      fill: fill character to pad field to minimum width
+      align: alignment type, either '<', '>', '=' or '^'
+      sign: either '+', '-' or ' '
+      minimumwidth: nonnegative integer giving minimum width
+      zeropad: boolean, indicating whether to pad with zeros
+      thousands_sep: string to use as thousands separator, or ''
+      grouping: grouping for thousands separators, in format
+        used by localeconv
+      decimal_point: string to use for decimal point
+      precision: nonnegative integer giving precision, or None
+      type: one of the characters 'eEfFgG%', or None
+      unicode: boolean (always True for Python 3.x)
+
+    """
+    m = _parse_format_specifier_regex.match(format_spec)
+    if m is None:
+        raise ValueError("Invalid format specifier: " + format_spec)
+
+    # get the dictionary
+    format_dict = m.groupdict()
+
+    # zeropad; defaults for fill and alignment.  If zero padding
+    # is requested, the fill and align fields should be absent.
+    fill = format_dict['fill']
+    align = format_dict['align']
+    format_dict['zeropad'] = (format_dict['zeropad'] is not None)
+    if format_dict['zeropad']:
+        if fill is not None:
+            raise ValueError("Fill character conflicts with '0'"
+                             " in format specifier: " + format_spec)
+        if align is not None:
+            raise ValueError("Alignment conflicts with '0' in "
+                             "format specifier: " + format_spec)
+    format_dict['fill'] = fill or ' '
+    # PEP 3101 originally specified that the default alignment should
+    # be left;  it was later agreed that right-aligned makes more sense
+    # for numeric types.  See http://bugs.python.org/issue6857.
+    format_dict['align'] = align or '>'
+
+    # default sign handling: '-' for negative, '' for positive
+    if format_dict['sign'] is None:
+        format_dict['sign'] = '-'
+
+    # minimumwidth defaults to 0; precision remains None if not given
+    format_dict['minimumwidth'] = int(format_dict['minimumwidth'] or '0')
+    if format_dict['precision'] is not None:
+        format_dict['precision'] = int(format_dict['precision'])
+
+    # if format type is 'g' or 'G' then a precision of 0 makes little
+    # sense; convert it to 1.  Same if format type is unspecified.
+    if format_dict['precision'] == 0:
+        if format_dict['type'] is None or format_dict['type'] in 'gG':
+            format_dict['precision'] = 1
+
+    # determine thousands separator, grouping, and decimal separator, and
+    # add appropriate entries to format_dict
+    if format_dict['type'] == 'n':
+        # apart from separators, 'n' behaves just like 'g'
+        format_dict['type'] = 'g'
+        if _localeconv is None:
+            _localeconv = _locale.localeconv()
+        if format_dict['thousands_sep'] is not None:
+            raise ValueError("Explicit thousands separator conflicts with "
+                             "'n' type in format specifier: " + format_spec)
+        format_dict['thousands_sep'] = _localeconv['thousands_sep']
+        format_dict['grouping'] = _localeconv['grouping']
+        format_dict['decimal_point'] = _localeconv['decimal_point']
+    else:
+        if format_dict['thousands_sep'] is None:
+            format_dict['thousands_sep'] = ''
+        format_dict['grouping'] = [3, 0]
+        format_dict['decimal_point'] = '.'
+
+    # record whether return type should be str or unicode
+    format_dict['unicode'] = isinstance(format_spec, unicode)
+
+    return format_dict
+
+def _format_align(sign, body, spec):
+    """Given an unpadded, non-aligned numeric string 'body' and sign
+    string 'sign', add padding and aligment conforming to the given
+    format specifier dictionary 'spec' (as produced by
+    parse_format_specifier).
+
+    Also converts result to unicode if necessary.
+
+    """
+    # how much extra space do we have to play with?
+    minimumwidth = spec['minimumwidth']
+    fill = spec['fill']
+    padding = fill*(minimumwidth - len(sign) - len(body))
+
+    align = spec['align']
+    if align == '<':
+        result = sign + body + padding
+    elif align == '>':
+        result = padding + sign + body
+    elif align == '=':
+        result = sign + padding + body
+    elif align == '^':
+        half = len(padding)//2
+        result = padding[:half] + sign + body + padding[half:]
+    else:
+        raise ValueError('Unrecognised alignment field')
+
+    # make sure that result is unicode if necessary
+    if spec['unicode']:
+        result = unicode(result)
+
+    return result
+
+def _group_lengths(grouping):
+    """Convert a localeconv-style grouping into a (possibly infinite)
+    iterable of integers representing group lengths.
+
+    """
+    # The result from localeconv()['grouping'], and the input to this
+    # function, should be a list of integers in one of the
+    # following three forms:
+    #
+    #   (1) an empty list, or
+    #   (2) nonempty list of positive integers + [0]
+    #   (3) list of positive integers + [locale.CHAR_MAX], or
+
+    from itertools import chain, repeat
+    if not grouping:
+        return []
+    elif grouping[-1] == 0 and len(grouping) >= 2:
+        return chain(grouping[:-1], repeat(grouping[-2]))
+    elif grouping[-1] == _locale.CHAR_MAX:
+        return grouping[:-1]
+    else:
+        raise ValueError('unrecognised format for grouping')
+
+def _insert_thousands_sep(digits, spec, min_width=1):
+    """Insert thousands separators into a digit string.
+
+    spec is a dictionary whose keys should include 'thousands_sep' and
+    'grouping'; typically it's the result of parsing the format
+    specifier using _parse_format_specifier.
+
+    The min_width keyword argument gives the minimum length of the
+    result, which will be padded on the left with zeros if necessary.
+
+    If necessary, the zero padding adds an extra '0' on the left to
+    avoid a leading thousands separator.  For example, inserting
+    commas every three digits in '123456', with min_width=8, gives
+    '0,123,456', even though that has length 9.
+
+    """
+
+    sep = spec['thousands_sep']
+    grouping = spec['grouping']
+
+    groups = []
+    for l in _group_lengths(grouping):
+        if l <= 0:
+            raise ValueError("group length should be positive")
+        # max(..., 1) forces at least 1 digit to the left of a separator
+        l = min(max(len(digits), min_width, 1), l)
+        groups.append('0'*(l - len(digits)) + digits[-l:])
+        digits = digits[:-l]
+        min_width -= l
+        if not digits and min_width <= 0:
+            break
+        min_width -= len(sep)
+    else:
+        l = max(len(digits), min_width, 1)
+        groups.append('0'*(l - len(digits)) + digits[-l:])
+    return sep.join(reversed(groups))
+
+def _format_sign(is_negative, spec):
+    """Determine sign character."""
+
+    if is_negative:
+        return '-'
+    elif spec['sign'] in ' +':
+        return spec['sign']
+    else:
+        return ''
+
+def _format_number(is_negative, intpart, fracpart, exp, spec):
+    """Format a number, given the following data:
+
+    is_negative: true if the number is negative, else false
+    intpart: string of digits that must appear before the decimal point
+    fracpart: string of digits that must come after the point
+    exp: exponent, as an integer
+    spec: dictionary resulting from parsing the format specifier
+
+    This function uses the information in spec to:
+      insert separators (decimal separator and thousands separators)
+      format the sign
+      format the exponent
+      add trailing '%' for the '%' type
+      zero-pad if necessary
+      fill and align if necessary
+    """
+
+    sign = _format_sign(is_negative, spec)
+
+    if fracpart:
+        fracpart = spec['decimal_point'] + fracpart
+
+    if exp != 0 or spec['type'] in 'eE':
+        echar = {'E': 'E', 'e': 'e', 'G': 'E', 'g': 'e'}[spec['type']]
+        fracpart += "{0}{1:+}".format(echar, exp)
+    if spec['type'] == '%':
+        fracpart += '%'
+
+    if spec['zeropad']:
+        min_width = spec['minimumwidth'] - len(fracpart) - len(sign)
+    else:
+        min_width = 0
+    intpart = _insert_thousands_sep(intpart, spec, min_width)
+
+    return _format_align(sign, intpart+fracpart, spec)
+
+
+##### Useful Constants (internal use only) ################################
+
+# Reusable defaults
+_Infinity = Decimal('Inf')
+_NegativeInfinity = Decimal('-Inf')
+_NaN = Decimal('NaN')
+_Zero = Decimal(0)
+_One = Decimal(1)
+_NegativeOne = Decimal(-1)
+
+# _SignedInfinity[sign] is infinity w/ that sign
+_SignedInfinity = (_Infinity, _NegativeInfinity)
+
+
+
+if __name__ == '__main__':
+    import doctest, sys
+    doctest.testmod(sys.modules[__name__])
diff --git a/src/main/resources/PythonLibs/difflib.py b/src/main/resources/PythonLibs/difflib.py
new file mode 100644
index 0000000000000000000000000000000000000000..3bbcb76b7ecb3315698542acc2d8016a49f24616
--- /dev/null
+++ b/src/main/resources/PythonLibs/difflib.py
@@ -0,0 +1,2059 @@
+#! /usr/bin/env python
+
+"""
+Module difflib -- helpers for computing deltas between objects.
+
+Function get_close_matches(word, possibilities, n=3, cutoff=0.6):
+    Use SequenceMatcher to return list of the best "good enough" matches.
+
+Function context_diff(a, b):
+    For two lists of strings, return a delta in context diff format.
+
+Function ndiff(a, b):
+    Return a delta: the difference between `a` and `b` (lists of strings).
+
+Function restore(delta, which):
+    Return one of the two sequences that generated an ndiff delta.
+
+Function unified_diff(a, b):
+    For two lists of strings, return a delta in unified diff format.
+
+Class SequenceMatcher:
+    A flexible class for comparing pairs of sequences of any type.
+
+Class Differ:
+    For producing human-readable deltas from sequences of lines of text.
+
+Class HtmlDiff:
+    For producing HTML side by side comparison with change highlights.
+"""
+
+__all__ = ['get_close_matches', 'ndiff', 'restore', 'SequenceMatcher',
+           'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff',
+           'unified_diff', 'HtmlDiff', 'Match']
+
+import heapq
+from collections import namedtuple as _namedtuple
+from functools import reduce
+
+Match = _namedtuple('Match', 'a b size')
+
+def _calculate_ratio(matches, length):
+    if length:
+        return 2.0 * matches / length
+    return 1.0
+
+class SequenceMatcher:
+
+    """
+    SequenceMatcher is a flexible class for comparing pairs of sequences of
+    any type, so long as the sequence elements are hashable.  The basic
+    algorithm predates, and is a little fancier than, an algorithm
+    published in the late 1980's by Ratcliff and Obershelp under the
+    hyperbolic name "gestalt pattern matching".  The basic idea is to find
+    the longest contiguous matching subsequence that contains no "junk"
+    elements (R-O doesn't address junk).  The same idea is then applied
+    recursively to the pieces of the sequences to the left and to the right
+    of the matching subsequence.  This does not yield minimal edit
+    sequences, but does tend to yield matches that "look right" to people.
+
+    SequenceMatcher tries to compute a "human-friendly diff" between two
+    sequences.  Unlike e.g. UNIX(tm) diff, the fundamental notion is the
+    longest *contiguous* & junk-free matching subsequence.  That's what
+    catches peoples' eyes.  The Windows(tm) windiff has another interesting
+    notion, pairing up elements that appear uniquely in each sequence.
+    That, and the method here, appear to yield more intuitive difference
+    reports than does diff.  This method appears to be the least vulnerable
+    to synching up on blocks of "junk lines", though (like blank lines in
+    ordinary text files, or maybe "<P>" lines in HTML files).  That may be
+    because this is the only method of the 3 that has a *concept* of
+    "junk" <wink>.
+
+    Example, comparing two strings, and considering blanks to be "junk":
+
+    >>> s = SequenceMatcher(lambda x: x == " ",
+    ...                     "private Thread currentThread;",
+    ...                     "private volatile Thread currentThread;")
+    >>>
+
+    .ratio() returns a float in [0, 1], measuring the "similarity" of the
+    sequences.  As a rule of thumb, a .ratio() value over 0.6 means the
+    sequences are close matches:
+
+    >>> print round(s.ratio(), 3)
+    0.866
+    >>>
+
+    If you're only interested in where the sequences match,
+    .get_matching_blocks() is handy:
+
+    >>> for block in s.get_matching_blocks():
+    ...     print "a[%d] and b[%d] match for %d elements" % block
+    a[0] and b[0] match for 8 elements
+    a[8] and b[17] match for 21 elements
+    a[29] and b[38] match for 0 elements
+
+    Note that the last tuple returned by .get_matching_blocks() is always a
+    dummy, (len(a), len(b), 0), and this is the only case in which the last
+    tuple element (number of elements matched) is 0.
+
+    If you want to know how to change the first sequence into the second,
+    use .get_opcodes():
+
+    >>> for opcode in s.get_opcodes():
+    ...     print "%6s a[%d:%d] b[%d:%d]" % opcode
+     equal a[0:8] b[0:8]
+    insert a[8:8] b[8:17]
+     equal a[8:29] b[17:38]
+
+    See the Differ class for a fancy human-friendly file differencer, which
+    uses SequenceMatcher both to compare sequences of lines, and to compare
+    sequences of characters within similar (near-matching) lines.
+
+    See also function get_close_matches() in this module, which shows how
+    simple code building on SequenceMatcher can be used to do useful work.
+
+    Timing:  Basic R-O is cubic time worst case and quadratic time expected
+    case.  SequenceMatcher is quadratic time for the worst case and has
+    expected-case behavior dependent in a complicated way on how many
+    elements the sequences have in common; best case time is linear.
+
+    Methods:
+
+    __init__(isjunk=None, a='', b='')
+        Construct a SequenceMatcher.
+
+    set_seqs(a, b)
+        Set the two sequences to be compared.
+
+    set_seq1(a)
+        Set the first sequence to be compared.
+
+    set_seq2(b)
+        Set the second sequence to be compared.
+
+    find_longest_match(alo, ahi, blo, bhi)
+        Find longest matching block in a[alo:ahi] and b[blo:bhi].
+
+    get_matching_blocks()
+        Return list of triples describing matching subsequences.
+
+    get_opcodes()
+        Return list of 5-tuples describing how to turn a into b.
+
+    ratio()
+        Return a measure of the sequences' similarity (float in [0,1]).
+
+    quick_ratio()
+        Return an upper bound on .ratio() relatively quickly.
+
+    real_quick_ratio()
+        Return an upper bound on ratio() very quickly.
+    """
+
+    def __init__(self, isjunk=None, a='', b='', autojunk=True):
+        """Construct a SequenceMatcher.
+
+        Optional arg isjunk is None (the default), or a one-argument
+        function that takes a sequence element and returns true iff the
+        element is junk.  None is equivalent to passing "lambda x: 0", i.e.
+        no elements are considered to be junk.  For example, pass
+            lambda x: x in " \\t"
+        if you're comparing lines as sequences of characters, and don't
+        want to synch up on blanks or hard tabs.
+
+        Optional arg a is the first of two sequences to be compared.  By
+        default, an empty string.  The elements of a must be hashable.  See
+        also .set_seqs() and .set_seq1().
+
+        Optional arg b is the second of two sequences to be compared.  By
+        default, an empty string.  The elements of b must be hashable. See
+        also .set_seqs() and .set_seq2().
+
+        Optional arg autojunk should be set to False to disable the
+        "automatic junk heuristic" that treats popular elements as junk
+        (see module documentation for more information).
+        """
+
+        # Members:
+        # a
+        #      first sequence
+        # b
+        #      second sequence; differences are computed as "what do
+        #      we need to do to 'a' to change it into 'b'?"
+        # b2j
+        #      for x in b, b2j[x] is a list of the indices (into b)
+        #      at which x appears; junk elements do not appear
+        # fullbcount
+        #      for x in b, fullbcount[x] == the number of times x
+        #      appears in b; only materialized if really needed (used
+        #      only for computing quick_ratio())
+        # matching_blocks
+        #      a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k];
+        #      ascending & non-overlapping in i and in j; terminated by
+        #      a dummy (len(a), len(b), 0) sentinel
+        # opcodes
+        #      a list of (tag, i1, i2, j1, j2) tuples, where tag is
+        #      one of
+        #          'replace'   a[i1:i2] should be replaced by b[j1:j2]
+        #          'delete'    a[i1:i2] should be deleted
+        #          'insert'    b[j1:j2] should be inserted
+        #          'equal'     a[i1:i2] == b[j1:j2]
+        # isjunk
+        #      a user-supplied function taking a sequence element and
+        #      returning true iff the element is "junk" -- this has
+        #      subtle but helpful effects on the algorithm, which I'll
+        #      get around to writing up someday <0.9 wink>.
+        #      DON'T USE!  Only __chain_b uses this.  Use isbjunk.
+        # isbjunk
+        #      for x in b, isbjunk(x) == isjunk(x) but much faster;
+        #      it's really the __contains__ method of a hidden dict.
+        #      DOES NOT WORK for x in a!
+        # isbpopular
+        #      for x in b, isbpopular(x) is true iff b is reasonably long
+        #      (at least 200 elements) and x accounts for more than 1 + 1% of
+        #      its elements (when autojunk is enabled).
+        #      DOES NOT WORK for x in a!
+
+        self.isjunk = isjunk
+        self.a = self.b = None
+        self.autojunk = autojunk
+        self.set_seqs(a, b)
+
+    def set_seqs(self, a, b):
+        """Set the two sequences to be compared.
+
+        >>> s = SequenceMatcher()
+        >>> s.set_seqs("abcd", "bcde")
+        >>> s.ratio()
+        0.75
+        """
+
+        self.set_seq1(a)
+        self.set_seq2(b)
+
+    def set_seq1(self, a):
+        """Set the first sequence to be compared.
+
+        The second sequence to be compared is not changed.
+
+        >>> s = SequenceMatcher(None, "abcd", "bcde")
+        >>> s.ratio()
+        0.75
+        >>> s.set_seq1("bcde")
+        >>> s.ratio()
+        1.0
+        >>>
+
+        SequenceMatcher computes and caches detailed information about the
+        second sequence, so if you want to compare one sequence S against
+        many sequences, use .set_seq2(S) once and call .set_seq1(x)
+        repeatedly for each of the other sequences.
+
+        See also set_seqs() and set_seq2().
+        """
+
+        if a is self.a:
+            return
+        self.a = a
+        self.matching_blocks = self.opcodes = None
+
+    def set_seq2(self, b):
+        """Set the second sequence to be compared.
+
+        The first sequence to be compared is not changed.
+
+        >>> s = SequenceMatcher(None, "abcd", "bcde")
+        >>> s.ratio()
+        0.75
+        >>> s.set_seq2("abcd")
+        >>> s.ratio()
+        1.0
+        >>>
+
+        SequenceMatcher computes and caches detailed information about the
+        second sequence, so if you want to compare one sequence S against
+        many sequences, use .set_seq2(S) once and call .set_seq1(x)
+        repeatedly for each of the other sequences.
+
+        See also set_seqs() and set_seq1().
+        """
+
+        if b is self.b:
+            return
+        self.b = b
+        self.matching_blocks = self.opcodes = None
+        self.fullbcount = None
+        self.__chain_b()
+
+    # For each element x in b, set b2j[x] to a list of the indices in
+    # b where x appears; the indices are in increasing order; note that
+    # the number of times x appears in b is len(b2j[x]) ...
+    # when self.isjunk is defined, junk elements don't show up in this
+    # map at all, which stops the central find_longest_match method
+    # from starting any matching block at a junk element ...
+    # also creates the fast isbjunk function ...
+    # b2j also does not contain entries for "popular" elements, meaning
+    # elements that account for more than 1 + 1% of the total elements, and
+    # when the sequence is reasonably large (>= 200 elements); this can
+    # be viewed as an adaptive notion of semi-junk, and yields an enormous
+    # speedup when, e.g., comparing program files with hundreds of
+    # instances of "return NULL;" ...
+    # note that this is only called when b changes; so for cross-product
+    # kinds of matches, it's best to call set_seq2 once, then set_seq1
+    # repeatedly
+
+    def __chain_b(self):
+        # Because isjunk is a user-defined (not C) function, and we test
+        # for junk a LOT, it's important to minimize the number of calls.
+        # Before the tricks described here, __chain_b was by far the most
+        # time-consuming routine in the whole module!  If anyone sees
+        # Jim Roskind, thank him again for profile.py -- I never would
+        # have guessed that.
+        # The first trick is to build b2j ignoring the possibility
+        # of junk.  I.e., we don't call isjunk at all yet.  Throwing
+        # out the junk later is much cheaper than building b2j "right"
+        # from the start.
+        b = self.b
+        self.b2j = b2j = {}
+
+        for i, elt in enumerate(b):
+            indices = b2j.setdefault(elt, [])
+            indices.append(i)
+
+        # Purge junk elements
+        junk = set()
+        isjunk = self.isjunk
+        if isjunk:
+            for elt in list(b2j.keys()):  # using list() since b2j is modified
+                if isjunk(elt):
+                    junk.add(elt)
+                    del b2j[elt]
+
+        # Purge popular elements that are not junk
+        popular = set()
+        n = len(b)
+        if self.autojunk and n >= 200:
+            ntest = n // 100 + 1
+            for elt, idxs in list(b2j.items()):
+                if len(idxs) > ntest:
+                    popular.add(elt)
+                    del b2j[elt]
+
+        # Now for x in b, isjunk(x) == x in junk, but the latter is much faster.
+        # Sicne the number of *unique* junk elements is probably small, the
+        # memory burden of keeping this set alive is likely trivial compared to
+        # the size of b2j.
+        self.isbjunk = junk.__contains__
+        self.isbpopular = popular.__contains__
+
+    def find_longest_match(self, alo, ahi, blo, bhi):
+        """Find longest matching block in a[alo:ahi] and b[blo:bhi].
+
+        If isjunk is not defined:
+
+        Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
+            alo <= i <= i+k <= ahi
+            blo <= j <= j+k <= bhi
+        and for all (i',j',k') meeting those conditions,
+            k >= k'
+            i <= i'
+            and if i == i', j <= j'
+
+        In other words, of all maximal matching blocks, return one that
+        starts earliest in a, and of all those maximal matching blocks that
+        start earliest in a, return the one that starts earliest in b.
+
+        >>> s = SequenceMatcher(None, " abcd", "abcd abcd")
+        >>> s.find_longest_match(0, 5, 0, 9)
+        Match(a=0, b=4, size=5)
+
+        If isjunk is defined, first the longest matching block is
+        determined as above, but with the additional restriction that no
+        junk element appears in the block.  Then that block is extended as
+        far as possible by matching (only) junk elements on both sides.  So
+        the resulting block never matches on junk except as identical junk
+        happens to be adjacent to an "interesting" match.
+
+        Here's the same example as before, but considering blanks to be
+        junk.  That prevents " abcd" from matching the " abcd" at the tail
+        end of the second sequence directly.  Instead only the "abcd" can
+        match, and matches the leftmost "abcd" in the second sequence:
+
+        >>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd")
+        >>> s.find_longest_match(0, 5, 0, 9)
+        Match(a=1, b=0, size=4)
+
+        If no blocks match, return (alo, blo, 0).
+
+        >>> s = SequenceMatcher(None, "ab", "c")
+        >>> s.find_longest_match(0, 2, 0, 1)
+        Match(a=0, b=0, size=0)
+        """
+
+        # CAUTION:  stripping common prefix or suffix would be incorrect.
+        # E.g.,
+        #    ab
+        #    acab
+        # Longest matching block is "ab", but if common prefix is
+        # stripped, it's "a" (tied with "b").  UNIX(tm) diff does so
+        # strip, so ends up claiming that ab is changed to acab by
+        # inserting "ca" in the middle.  That's minimal but unintuitive:
+        # "it's obvious" that someone inserted "ac" at the front.
+        # Windiff ends up at the same place as diff, but by pairing up
+        # the unique 'b's and then matching the first two 'a's.
+
+        a, b, b2j, isbjunk = self.a, self.b, self.b2j, self.isbjunk
+        besti, bestj, bestsize = alo, blo, 0
+        # find longest junk-free match
+        # during an iteration of the loop, j2len[j] = length of longest
+        # junk-free match ending with a[i-1] and b[j]
+        j2len = {}
+        nothing = []
+        for i in xrange(alo, ahi):
+            # look at all instances of a[i] in b; note that because
+            # b2j has no junk keys, the loop is skipped if a[i] is junk
+            j2lenget = j2len.get
+            newj2len = {}
+            for j in b2j.get(a[i], nothing):
+                # a[i] matches b[j]
+                if j < blo:
+                    continue
+                if j >= bhi:
+                    break
+                k = newj2len[j] = j2lenget(j-1, 0) + 1
+                if k > bestsize:
+                    besti, bestj, bestsize = i-k+1, j-k+1, k
+            j2len = newj2len
+
+        # Extend the best by non-junk elements on each end.  In particular,
+        # "popular" non-junk elements aren't in b2j, which greatly speeds
+        # the inner loop above, but also means "the best" match so far
+        # doesn't contain any junk *or* popular non-junk elements.
+        while besti > alo and bestj > blo and \
+              not isbjunk(b[bestj-1]) and \
+              a[besti-1] == b[bestj-1]:
+            besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+        while besti+bestsize < ahi and bestj+bestsize < bhi and \
+              not isbjunk(b[bestj+bestsize]) and \
+              a[besti+bestsize] == b[bestj+bestsize]:
+            bestsize += 1
+
+        # Now that we have a wholly interesting match (albeit possibly
+        # empty!), we may as well suck up the matching junk on each
+        # side of it too.  Can't think of a good reason not to, and it
+        # saves post-processing the (possibly considerable) expense of
+        # figuring out what to do with it.  In the case of an empty
+        # interesting match, this is clearly the right thing to do,
+        # because no other kind of match is possible in the regions.
+        while besti > alo and bestj > blo and \
+              isbjunk(b[bestj-1]) and \
+              a[besti-1] == b[bestj-1]:
+            besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+        while besti+bestsize < ahi and bestj+bestsize < bhi and \
+              isbjunk(b[bestj+bestsize]) and \
+              a[besti+bestsize] == b[bestj+bestsize]:
+            bestsize = bestsize + 1
+
+        return Match(besti, bestj, bestsize)
+
+    def get_matching_blocks(self):
+        """Return list of triples describing matching subsequences.
+
+        Each triple is of the form (i, j, n), and means that
+        a[i:i+n] == b[j:j+n].  The triples are monotonically increasing in
+        i and in j.  New in Python 2.5, it's also guaranteed that if
+        (i, j, n) and (i', j', n') are adjacent triples in the list, and
+        the second is not the last triple in the list, then i+n != i' or
+        j+n != j'.  IOW, adjacent triples never describe adjacent equal
+        blocks.
+
+        The last triple is a dummy, (len(a), len(b), 0), and is the only
+        triple with n==0.
+
+        >>> s = SequenceMatcher(None, "abxcd", "abcd")
+        >>> s.get_matching_blocks()
+        [Match(a=0, b=0, size=2), Match(a=3, b=2, size=2), Match(a=5, b=4, size=0)]
+        """
+
+        if self.matching_blocks is not None:
+            return self.matching_blocks
+        la, lb = len(self.a), len(self.b)
+
+        # This is most naturally expressed as a recursive algorithm, but
+        # at least one user bumped into extreme use cases that exceeded
+        # the recursion limit on their box.  So, now we maintain a list
+        # ('queue`) of blocks we still need to look at, and append partial
+        # results to `matching_blocks` in a loop; the matches are sorted
+        # at the end.
+        queue = [(0, la, 0, lb)]
+        matching_blocks = []
+        while queue:
+            alo, ahi, blo, bhi = queue.pop()
+            i, j, k = x = self.find_longest_match(alo, ahi, blo, bhi)
+            # a[alo:i] vs b[blo:j] unknown
+            # a[i:i+k] same as b[j:j+k]
+            # a[i+k:ahi] vs b[j+k:bhi] unknown
+            if k:   # if k is 0, there was no matching block
+                matching_blocks.append(x)
+                if alo < i and blo < j:
+                    queue.append((alo, i, blo, j))
+                if i+k < ahi and j+k < bhi:
+                    queue.append((i+k, ahi, j+k, bhi))
+        matching_blocks.sort()
+
+        # It's possible that we have adjacent equal blocks in the
+        # matching_blocks list now.  Starting with 2.5, this code was added
+        # to collapse them.
+        i1 = j1 = k1 = 0
+        non_adjacent = []
+        for i2, j2, k2 in matching_blocks:
+            # Is this block adjacent to i1, j1, k1?
+            if i1 + k1 == i2 and j1 + k1 == j2:
+                # Yes, so collapse them -- this just increases the length of
+                # the first block by the length of the second, and the first
+                # block so lengthened remains the block to compare against.
+                k1 += k2
+            else:
+                # Not adjacent.  Remember the first block (k1==0 means it's
+                # the dummy we started with), and make the second block the
+                # new block to compare against.
+                if k1:
+                    non_adjacent.append((i1, j1, k1))
+                i1, j1, k1 = i2, j2, k2
+        if k1:
+            non_adjacent.append((i1, j1, k1))
+
+        non_adjacent.append( (la, lb, 0) )
+        self.matching_blocks = non_adjacent
+        return map(Match._make, self.matching_blocks)
+
+    def get_opcodes(self):
+        """Return list of 5-tuples describing how to turn a into b.
+
+        Each tuple is of the form (tag, i1, i2, j1, j2).  The first tuple
+        has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
+        tuple preceding it, and likewise for j1 == the previous j2.
+
+        The tags are strings, with these meanings:
+
+        'replace':  a[i1:i2] should be replaced by b[j1:j2]
+        'delete':   a[i1:i2] should be deleted.
+                    Note that j1==j2 in this case.
+        'insert':   b[j1:j2] should be inserted at a[i1:i1].
+                    Note that i1==i2 in this case.
+        'equal':    a[i1:i2] == b[j1:j2]
+
+        >>> a = "qabxcd"
+        >>> b = "abycdf"
+        >>> s = SequenceMatcher(None, a, b)
+        >>> for tag, i1, i2, j1, j2 in s.get_opcodes():
+        ...    print ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" %
+        ...           (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2]))
+         delete a[0:1] (q) b[0:0] ()
+          equal a[1:3] (ab) b[0:2] (ab)
+        replace a[3:4] (x) b[2:3] (y)
+          equal a[4:6] (cd) b[3:5] (cd)
+         insert a[6:6] () b[5:6] (f)
+        """
+
+        if self.opcodes is not None:
+            return self.opcodes
+        i = j = 0
+        self.opcodes = answer = []
+        for ai, bj, size in self.get_matching_blocks():
+            # invariant:  we've pumped out correct diffs to change
+            # a[:i] into b[:j], and the next matching block is
+            # a[ai:ai+size] == b[bj:bj+size].  So we need to pump
+            # out a diff to change a[i:ai] into b[j:bj], pump out
+            # the matching block, and move (i,j) beyond the match
+            tag = ''
+            if i < ai and j < bj:
+                tag = 'replace'
+            elif i < ai:
+                tag = 'delete'
+            elif j < bj:
+                tag = 'insert'
+            if tag:
+                answer.append( (tag, i, ai, j, bj) )
+            i, j = ai+size, bj+size
+            # the list of matching blocks is terminated by a
+            # sentinel with size 0
+            if size:
+                answer.append( ('equal', ai, i, bj, j) )
+        return answer
+
+    def get_grouped_opcodes(self, n=3):
+        """ Isolate change clusters by eliminating ranges with no changes.
+
+        Return a generator of groups with upto n lines of context.
+        Each group is in the same format as returned by get_opcodes().
+
+        >>> from pprint import pprint
+        >>> a = map(str, range(1,40))
+        >>> b = a[:]
+        >>> b[8:8] = ['i']     # Make an insertion
+        >>> b[20] += 'x'       # Make a replacement
+        >>> b[23:28] = []      # Make a deletion
+        >>> b[30] += 'y'       # Make another replacement
+        >>> pprint(list(SequenceMatcher(None,a,b).get_grouped_opcodes()))
+        [[('equal', 5, 8, 5, 8), ('insert', 8, 8, 8, 9), ('equal', 8, 11, 9, 12)],
+         [('equal', 16, 19, 17, 20),
+          ('replace', 19, 20, 20, 21),
+          ('equal', 20, 22, 21, 23),
+          ('delete', 22, 27, 23, 23),
+          ('equal', 27, 30, 23, 26)],
+         [('equal', 31, 34, 27, 30),
+          ('replace', 34, 35, 30, 31),
+          ('equal', 35, 38, 31, 34)]]
+        """
+
+        codes = self.get_opcodes()
+        if not codes:
+            codes = [("equal", 0, 1, 0, 1)]
+        # Fixup leading and trailing groups if they show no changes.
+        if codes[0][0] == 'equal':
+            tag, i1, i2, j1, j2 = codes[0]
+            codes[0] = tag, max(i1, i2-n), i2, max(j1, j2-n), j2
+        if codes[-1][0] == 'equal':
+            tag, i1, i2, j1, j2 = codes[-1]
+            codes[-1] = tag, i1, min(i2, i1+n), j1, min(j2, j1+n)
+
+        nn = n + n
+        group = []
+        for tag, i1, i2, j1, j2 in codes:
+            # End the current group and start a new one whenever
+            # there is a large range with no changes.
+            if tag == 'equal' and i2-i1 > nn:
+                group.append((tag, i1, min(i2, i1+n), j1, min(j2, j1+n)))
+                yield group
+                group = []
+                i1, j1 = max(i1, i2-n), max(j1, j2-n)
+            group.append((tag, i1, i2, j1 ,j2))
+        if group and not (len(group)==1 and group[0][0] == 'equal'):
+            yield group
+
+    def ratio(self):
+        """Return a measure of the sequences' similarity (float in [0,1]).
+
+        Where T is the total number of elements in both sequences, and
+        M is the number of matches, this is 2.0*M / T.
+        Note that this is 1 if the sequences are identical, and 0 if
+        they have nothing in common.
+
+        .ratio() is expensive to compute if you haven't already computed
+        .get_matching_blocks() or .get_opcodes(), in which case you may
+        want to try .quick_ratio() or .real_quick_ratio() first to get an
+        upper bound.
+
+        >>> s = SequenceMatcher(None, "abcd", "bcde")
+        >>> s.ratio()
+        0.75
+        >>> s.quick_ratio()
+        0.75
+        >>> s.real_quick_ratio()
+        1.0
+        """
+
+        matches = reduce(lambda sum, triple: sum + triple[-1],
+                         self.get_matching_blocks(), 0)
+        return _calculate_ratio(matches, len(self.a) + len(self.b))
+
+    def quick_ratio(self):
+        """Return an upper bound on ratio() relatively quickly.
+
+        This isn't defined beyond that it is an upper bound on .ratio(), and
+        is faster to compute.
+        """
+
+        # viewing a and b as multisets, set matches to the cardinality
+        # of their intersection; this counts the number of matches
+        # without regard to order, so is clearly an upper bound
+        if self.fullbcount is None:
+            self.fullbcount = fullbcount = {}
+            for elt in self.b:
+                fullbcount[elt] = fullbcount.get(elt, 0) + 1
+        fullbcount = self.fullbcount
+        # avail[x] is the number of times x appears in 'b' less the
+        # number of times we've seen it in 'a' so far ... kinda
+        avail = {}
+        availhas, matches = avail.__contains__, 0
+        for elt in self.a:
+            if availhas(elt):
+                numb = avail[elt]
+            else:
+                numb = fullbcount.get(elt, 0)
+            avail[elt] = numb - 1
+            if numb > 0:
+                matches = matches + 1
+        return _calculate_ratio(matches, len(self.a) + len(self.b))
+
+    def real_quick_ratio(self):
+        """Return an upper bound on ratio() very quickly.
+
+        This isn't defined beyond that it is an upper bound on .ratio(), and
+        is faster to compute than either .ratio() or .quick_ratio().
+        """
+
+        la, lb = len(self.a), len(self.b)
+        # can't have more matches than the number of elements in the
+        # shorter sequence
+        return _calculate_ratio(min(la, lb), la + lb)
+
+def get_close_matches(word, possibilities, n=3, cutoff=0.6):
+    """Use SequenceMatcher to return list of the best "good enough" matches.
+
+    word is a sequence for which close matches are desired (typically a
+    string).
+
+    possibilities is a list of sequences against which to match word
+    (typically a list of strings).
+
+    Optional arg n (default 3) is the maximum number of close matches to
+    return.  n must be > 0.
+
+    Optional arg cutoff (default 0.6) is a float in [0, 1].  Possibilities
+    that don't score at least that similar to word are ignored.
+
+    The best (no more than n) matches among the possibilities are returned
+    in a list, sorted by similarity score, most similar first.
+
+    >>> get_close_matches("appel", ["ape", "apple", "peach", "puppy"])
+    ['apple', 'ape']
+    >>> import keyword as _keyword
+    >>> get_close_matches("wheel", _keyword.kwlist)
+    ['while']
+    >>> get_close_matches("apple", _keyword.kwlist)
+    []
+    >>> get_close_matches("accept", _keyword.kwlist)
+    ['except']
+    """
+
+    if not n >  0:
+        raise ValueError("n must be > 0: %r" % (n,))
+    if not 0.0 <= cutoff <= 1.0:
+        raise ValueError("cutoff must be in [0.0, 1.0]: %r" % (cutoff,))
+    result = []
+    s = SequenceMatcher()
+    s.set_seq2(word)
+    for x in possibilities:
+        s.set_seq1(x)
+        if s.real_quick_ratio() >= cutoff and \
+           s.quick_ratio() >= cutoff and \
+           s.ratio() >= cutoff:
+            result.append((s.ratio(), x))
+
+    # Move the best scorers to head of list
+    result = heapq.nlargest(n, result)
+    # Strip scores for the best n matches
+    return [x for score, x in result]
+
+def _count_leading(line, ch):
+    """
+    Return number of `ch` characters at the start of `line`.
+
+    Example:
+
+    >>> _count_leading('   abc', ' ')
+    3
+    """
+
+    i, n = 0, len(line)
+    while i < n and line[i] == ch:
+        i += 1
+    return i
+
+class Differ:
+    r"""
+    Differ is a class for comparing sequences of lines of text, and
+    producing human-readable differences or deltas.  Differ uses
+    SequenceMatcher both to compare sequences of lines, and to compare
+    sequences of characters within similar (near-matching) lines.
+
+    Each line of a Differ delta begins with a two-letter code:
+
+        '- '    line unique to sequence 1
+        '+ '    line unique to sequence 2
+        '  '    line common to both sequences
+        '? '    line not present in either input sequence
+
+    Lines beginning with '? ' attempt to guide the eye to intraline
+    differences, and were not present in either input sequence.  These lines
+    can be confusing if the sequences contain tab characters.
+
+    Note that Differ makes no claim to produce a *minimal* diff.  To the
+    contrary, minimal diffs are often counter-intuitive, because they synch
+    up anywhere possible, sometimes accidental matches 100 pages apart.
+    Restricting synch points to contiguous matches preserves some notion of
+    locality, at the occasional cost of producing a longer diff.
+
+    Example: Comparing two texts.
+
+    First we set up the texts, sequences of individual single-line strings
+    ending with newlines (such sequences can also be obtained from the
+    `readlines()` method of file-like objects):
+
+    >>> text1 = '''  1. Beautiful is better than ugly.
+    ...   2. Explicit is better than implicit.
+    ...   3. Simple is better than complex.
+    ...   4. Complex is better than complicated.
+    ... '''.splitlines(1)
+    >>> len(text1)
+    4
+    >>> text1[0][-1]
+    '\n'
+    >>> text2 = '''  1. Beautiful is better than ugly.
+    ...   3.   Simple is better than complex.
+    ...   4. Complicated is better than complex.
+    ...   5. Flat is better than nested.
+    ... '''.splitlines(1)
+
+    Next we instantiate a Differ object:
+
+    >>> d = Differ()
+
+    Note that when instantiating a Differ object we may pass functions to
+    filter out line and character 'junk'.  See Differ.__init__ for details.
+
+    Finally, we compare the two:
+
+    >>> result = list(d.compare(text1, text2))
+
+    'result' is a list of strings, so let's pretty-print it:
+
+    >>> from pprint import pprint as _pprint
+    >>> _pprint(result)
+    ['    1. Beautiful is better than ugly.\n',
+     '-   2. Explicit is better than implicit.\n',
+     '-   3. Simple is better than complex.\n',
+     '+   3.   Simple is better than complex.\n',
+     '?     ++\n',
+     '-   4. Complex is better than complicated.\n',
+     '?            ^                     ---- ^\n',
+     '+   4. Complicated is better than complex.\n',
+     '?           ++++ ^                      ^\n',
+     '+   5. Flat is better than nested.\n']
+
+    As a single multi-line string it looks like this:
+
+    >>> print ''.join(result),
+        1. Beautiful is better than ugly.
+    -   2. Explicit is better than implicit.
+    -   3. Simple is better than complex.
+    +   3.   Simple is better than complex.
+    ?     ++
+    -   4. Complex is better than complicated.
+    ?            ^                     ---- ^
+    +   4. Complicated is better than complex.
+    ?           ++++ ^                      ^
+    +   5. Flat is better than nested.
+
+    Methods:
+
+    __init__(linejunk=None, charjunk=None)
+        Construct a text differencer, with optional filters.
+
+    compare(a, b)
+        Compare two sequences of lines; generate the resulting delta.
+    """
+
+    def __init__(self, linejunk=None, charjunk=None):
+        """
+        Construct a text differencer, with optional filters.
+
+        The two optional keyword parameters are for filter functions:
+
+        - `linejunk`: A function that should accept a single string argument,
+          and return true iff the string is junk. The module-level function
+          `IS_LINE_JUNK` may be used to filter out lines without visible
+          characters, except for at most one splat ('#').  It is recommended
+          to leave linejunk None; as of Python 2.3, the underlying
+          SequenceMatcher class has grown an adaptive notion of "noise" lines
+          that's better than any static definition the author has ever been
+          able to craft.
+
+        - `charjunk`: A function that should accept a string of length 1. The
+          module-level function `IS_CHARACTER_JUNK` may be used to filter out
+          whitespace characters (a blank or tab; **note**: bad idea to include
+          newline in this!).  Use of IS_CHARACTER_JUNK is recommended.
+        """
+
+        self.linejunk = linejunk
+        self.charjunk = charjunk
+
+    def compare(self, a, b):
+        r"""
+        Compare two sequences of lines; generate the resulting delta.
+
+        Each sequence must contain individual single-line strings ending with
+        newlines. Such sequences can be obtained from the `readlines()` method
+        of file-like objects.  The delta generated also consists of newline-
+        terminated strings, ready to be printed as-is via the writeline()
+        method of a file-like object.
+
+        Example:
+
+        >>> print ''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(1),
+        ...                                'ore\ntree\nemu\n'.splitlines(1))),
+        - one
+        ?  ^
+        + ore
+        ?  ^
+        - two
+        - three
+        ?  -
+        + tree
+        + emu
+        """
+
+        cruncher = SequenceMatcher(self.linejunk, a, b)
+        for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
+            if tag == 'replace':
+                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
+            elif tag == 'delete':
+                g = self._dump('-', a, alo, ahi)
+            elif tag == 'insert':
+                g = self._dump('+', b, blo, bhi)
+            elif tag == 'equal':
+                g = self._dump(' ', a, alo, ahi)
+            else:
+                raise ValueError, 'unknown tag %r' % (tag,)
+
+            for line in g:
+                yield line
+
+    def _dump(self, tag, x, lo, hi):
+        """Generate comparison results for a same-tagged range."""
+        for i in xrange(lo, hi):
+            yield '%s %s' % (tag, x[i])
+
+    def _plain_replace(self, a, alo, ahi, b, blo, bhi):
+        assert alo < ahi and blo < bhi
+        # dump the shorter block first -- reduces the burden on short-term
+        # memory if the blocks are of very different sizes
+        if bhi - blo < ahi - alo:
+            first  = self._dump('+', b, blo, bhi)
+            second = self._dump('-', a, alo, ahi)
+        else:
+            first  = self._dump('-', a, alo, ahi)
+            second = self._dump('+', b, blo, bhi)
+
+        for g in first, second:
+            for line in g:
+                yield line
+
+    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
+        r"""
+        When replacing one block of lines with another, search the blocks
+        for *similar* lines; the best-matching pair (if any) is used as a
+        synch point, and intraline difference marking is done on the
+        similar pair. Lots of work, but often worth it.
+
+        Example:
+
+        >>> d = Differ()
+        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
+        ...                            ['abcdefGhijkl\n'], 0, 1)
+        >>> print ''.join(results),
+        - abcDefghiJkl
+        ?    ^  ^  ^
+        + abcdefGhijkl
+        ?    ^  ^  ^
+        """
+
+        # don't synch up unless the lines have a similarity score of at
+        # least cutoff; best_ratio tracks the best score seen so far
+        best_ratio, cutoff = 0.74, 0.75
+        cruncher = SequenceMatcher(self.charjunk)
+        eqi, eqj = None, None   # 1st indices of equal lines (if any)
+
+        # search for the pair that matches best without being identical
+        # (identical lines must be junk lines, & we don't want to synch up
+        # on junk -- unless we have to)
+        for j in xrange(blo, bhi):
+            bj = b[j]
+            cruncher.set_seq2(bj)
+            for i in xrange(alo, ahi):
+                ai = a[i]
+                if ai == bj:
+                    if eqi is None:
+                        eqi, eqj = i, j
+                    continue
+                cruncher.set_seq1(ai)
+                # computing similarity is expensive, so use the quick
+                # upper bounds first -- have seen this speed up messy
+                # compares by a factor of 3.
+                # note that ratio() is only expensive to compute the first
+                # time it's called on a sequence pair; the expensive part
+                # of the computation is cached by cruncher
+                if cruncher.real_quick_ratio() > best_ratio and \
+                      cruncher.quick_ratio() > best_ratio and \
+                      cruncher.ratio() > best_ratio:
+                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
+        if best_ratio < cutoff:
+            # no non-identical "pretty close" pair
+            if eqi is None:
+                # no identical pair either -- treat it as a straight replace
+                for line in self._plain_replace(a, alo, ahi, b, blo, bhi):
+                    yield line
+                return
+            # no close pair, but an identical pair -- synch up on that
+            best_i, best_j, best_ratio = eqi, eqj, 1.0
+        else:
+            # there's a close pair, so forget the identical pair (if any)
+            eqi = None
+
+        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
+        # identical
+
+        # pump out diffs from before the synch point
+        for line in self._fancy_helper(a, alo, best_i, b, blo, best_j):
+            yield line
+
+        # do intraline marking on the synch pair
+        aelt, belt = a[best_i], b[best_j]
+        if eqi is None:
+            # pump out a '-', '?', '+', '?' quad for the synched lines
+            atags = btags = ""
+            cruncher.set_seqs(aelt, belt)
+            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
+                la, lb = ai2 - ai1, bj2 - bj1
+                if tag == 'replace':
+                    atags += '^' * la
+                    btags += '^' * lb
+                elif tag == 'delete':
+                    atags += '-' * la
+                elif tag == 'insert':
+                    btags += '+' * lb
+                elif tag == 'equal':
+                    atags += ' ' * la
+                    btags += ' ' * lb
+                else:
+                    raise ValueError, 'unknown tag %r' % (tag,)
+            for line in self._qformat(aelt, belt, atags, btags):
+                yield line
+        else:
+            # the synch pair is identical
+            yield '  ' + aelt
+
+        # pump out diffs from after the synch point
+        for line in self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi):
+            yield line
+
+    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
+        g = []
+        if alo < ahi:
+            if blo < bhi:
+                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
+            else:
+                g = self._dump('-', a, alo, ahi)
+        elif blo < bhi:
+            g = self._dump('+', b, blo, bhi)
+
+        for line in g:
+            yield line
+
+    def _qformat(self, aline, bline, atags, btags):
+        r"""
+        Format "?" output and deal with leading tabs.
+
+        Example:
+
+        >>> d = Differ()
+        >>> results = d._qformat('\tabcDefghiJkl\n', '\tabcdefGhijkl\n',
+        ...                      '  ^ ^  ^      ', '  ^ ^  ^      ')
+        >>> for line in results: print repr(line)
+        ...
+        '- \tabcDefghiJkl\n'
+        '? \t ^ ^  ^\n'
+        '+ \tabcdefGhijkl\n'
+        '? \t ^ ^  ^\n'
+        """
+
+        # Can hurt, but will probably help most of the time.
+        common = min(_count_leading(aline, "\t"),
+                     _count_leading(bline, "\t"))
+        common = min(common, _count_leading(atags[:common], " "))
+        common = min(common, _count_leading(btags[:common], " "))
+        atags = atags[common:].rstrip()
+        btags = btags[common:].rstrip()
+
+        yield "- " + aline
+        if atags:
+            yield "? %s%s\n" % ("\t" * common, atags)
+
+        yield "+ " + bline
+        if btags:
+            yield "? %s%s\n" % ("\t" * common, btags)
+
+# With respect to junk, an earlier version of ndiff simply refused to
+# *start* a match with a junk element.  The result was cases like this:
+#     before: private Thread currentThread;
+#     after:  private volatile Thread currentThread;
+# If you consider whitespace to be junk, the longest contiguous match
+# not starting with junk is "e Thread currentThread".  So ndiff reported
+# that "e volatil" was inserted between the 't' and the 'e' in "private".
+# While an accurate view, to people that's absurd.  The current version
+# looks for matching blocks that are entirely junk-free, then extends the
+# longest one of those as far as possible but only with matching junk.
+# So now "currentThread" is matched, then extended to suck up the
+# preceding blank; then "private" is matched, and extended to suck up the
+# following blank; then "Thread" is matched; and finally ndiff reports
+# that "volatile " was inserted before "Thread".  The only quibble
+# remaining is that perhaps it was really the case that " volatile"
+# was inserted after "private".  I can live with that <wink>.
+
+import re
+
+def IS_LINE_JUNK(line, pat=re.compile(r"\s*#?\s*$").match):
+    r"""
+    Return 1 for ignorable line: iff `line` is blank or contains a single '#'.
+
+    Examples:
+
+    >>> IS_LINE_JUNK('\n')
+    True
+    >>> IS_LINE_JUNK('  #   \n')
+    True
+    >>> IS_LINE_JUNK('hello\n')
+    False
+    """
+
+    return pat(line) is not None
+
+def IS_CHARACTER_JUNK(ch, ws=" \t"):
+    r"""
+    Return 1 for ignorable character: iff `ch` is a space or tab.
+
+    Examples:
+
+    >>> IS_CHARACTER_JUNK(' ')
+    True
+    >>> IS_CHARACTER_JUNK('\t')
+    True
+    >>> IS_CHARACTER_JUNK('\n')
+    False
+    >>> IS_CHARACTER_JUNK('x')
+    False
+    """
+
+    return ch in ws
+
+
+########################################################################
+###  Unified Diff
+########################################################################
+
+def _format_range_unified(start, stop):
+    'Convert range to the "ed" format'
+    # Per the diff spec at http://www.unix.org/single_unix_specification/
+    beginning = start + 1     # lines start numbering with one
+    length = stop - start
+    if length == 1:
+        return '{}'.format(beginning)
+    if not length:
+        beginning -= 1        # empty ranges begin at line just before the range
+    return '{},{}'.format(beginning, length)
+
+def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
+                 tofiledate='', n=3, lineterm='\n'):
+    r"""
+    Compare two sequences of lines; generate the delta as a unified diff.
+
+    Unified diffs are a compact way of showing line changes and a few
+    lines of context.  The number of context lines is set by 'n' which
+    defaults to three.
+
+    By default, the diff control lines (those with ---, +++, or @@) are
+    created with a trailing newline.  This is helpful so that inputs
+    created from file.readlines() result in diffs that are suitable for
+    file.writelines() since both the inputs and outputs have trailing
+    newlines.
+
+    For inputs that do not have trailing newlines, set the lineterm
+    argument to "" so that the output will be uniformly newline free.
+
+    The unidiff format normally has a header for filenames and modification
+    times.  Any or all of these may be specified using strings for
+    'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
+    The modification times are normally expressed in the ISO 8601 format.
+
+    Example:
+
+    >>> for line in unified_diff('one two three four'.split(),
+    ...             'zero one tree four'.split(), 'Original', 'Current',
+    ...             '2005-01-26 23:30:50', '2010-04-02 10:20:52',
+    ...             lineterm=''):
+    ...     print line                  # doctest: +NORMALIZE_WHITESPACE
+    --- Original        2005-01-26 23:30:50
+    +++ Current         2010-04-02 10:20:52
+    @@ -1,4 +1,4 @@
+    +zero
+     one
+    -two
+    -three
+    +tree
+     four
+    """
+
+    started = False
+    for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
+        if not started:
+            started = True
+            fromdate = '\t{}'.format(fromfiledate) if fromfiledate else ''
+            todate = '\t{}'.format(tofiledate) if tofiledate else ''
+            yield '--- {}{}{}'.format(fromfile, fromdate, lineterm)
+            yield '+++ {}{}{}'.format(tofile, todate, lineterm)
+
+        first, last = group[0], group[-1]
+        file1_range = _format_range_unified(first[1], last[2])
+        file2_range = _format_range_unified(first[3], last[4])
+        yield '@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm)
+
+        for tag, i1, i2, j1, j2 in group:
+            if tag == 'equal':
+                for line in a[i1:i2]:
+                    yield ' ' + line
+                continue
+            if tag in ('replace', 'delete'):
+                for line in a[i1:i2]:
+                    yield '-' + line
+            if tag in ('replace', 'insert'):
+                for line in b[j1:j2]:
+                    yield '+' + line
+
+
+########################################################################
+###  Context Diff
+########################################################################
+
+def _format_range_context(start, stop):
+    'Convert range to the "ed" format'
+    # Per the diff spec at http://www.unix.org/single_unix_specification/
+    beginning = start + 1     # lines start numbering with one
+    length = stop - start
+    if not length:
+        beginning -= 1        # empty ranges begin at line just before the range
+    if length <= 1:
+        return '{}'.format(beginning)
+    return '{},{}'.format(beginning, beginning + length - 1)
+
+# See http://www.unix.org/single_unix_specification/
+def context_diff(a, b, fromfile='', tofile='',
+                 fromfiledate='', tofiledate='', n=3, lineterm='\n'):
+    r"""
+    Compare two sequences of lines; generate the delta as a context diff.
+
+    Context diffs are a compact way of showing line changes and a few
+    lines of context.  The number of context lines is set by 'n' which
+    defaults to three.
+
+    By default, the diff control lines (those with *** or ---) are
+    created with a trailing newline.  This is helpful so that inputs
+    created from file.readlines() result in diffs that are suitable for
+    file.writelines() since both the inputs and outputs have trailing
+    newlines.
+
+    For inputs that do not have trailing newlines, set the lineterm
+    argument to "" so that the output will be uniformly newline free.
+
+    The context diff format normally has a header for filenames and
+    modification times.  Any or all of these may be specified using
+    strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
+    The modification times are normally expressed in the ISO 8601 format.
+    If not specified, the strings default to blanks.
+
+    Example:
+
+    >>> print ''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(1),
+    ...       'zero\none\ntree\nfour\n'.splitlines(1), 'Original', 'Current')),
+    *** Original
+    --- Current
+    ***************
+    *** 1,4 ****
+      one
+    ! two
+    ! three
+      four
+    --- 1,4 ----
+    + zero
+      one
+    ! tree
+      four
+    """
+
+    prefix = dict(insert='+ ', delete='- ', replace='! ', equal='  ')
+    started = False
+    for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
+        if not started:
+            started = True
+            fromdate = '\t{}'.format(fromfiledate) if fromfiledate else ''
+            todate = '\t{}'.format(tofiledate) if tofiledate else ''
+            yield '*** {}{}{}'.format(fromfile, fromdate, lineterm)
+            yield '--- {}{}{}'.format(tofile, todate, lineterm)
+
+        first, last = group[0], group[-1]
+        yield '***************' + lineterm
+
+        file1_range = _format_range_context(first[1], last[2])
+        yield '*** {} ****{}'.format(file1_range, lineterm)
+
+        if any(tag in ('replace', 'delete') for tag, _, _, _, _ in group):
+            for tag, i1, i2, _, _ in group:
+                if tag != 'insert':
+                    for line in a[i1:i2]:
+                        yield prefix[tag] + line
+
+        file2_range = _format_range_context(first[3], last[4])
+        yield '--- {} ----{}'.format(file2_range, lineterm)
+
+        if any(tag in ('replace', 'insert') for tag, _, _, _, _ in group):
+            for tag, _, _, j1, j2 in group:
+                if tag != 'delete':
+                    for line in b[j1:j2]:
+                        yield prefix[tag] + line
+
+def ndiff(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK):
+    r"""
+    Compare `a` and `b` (lists of strings); return a `Differ`-style delta.
+
+    Optional keyword parameters `linejunk` and `charjunk` are for filter
+    functions (or None):
+
+    - linejunk: A function that should accept a single string argument, and
+      return true iff the string is junk.  The default is None, and is
+      recommended; as of Python 2.3, an adaptive notion of "noise" lines is
+      used that does a good job on its own.
+
+    - charjunk: A function that should accept a string of length 1. The
+      default is module-level function IS_CHARACTER_JUNK, which filters out
+      whitespace characters (a blank or tab; note: bad idea to include newline
+      in this!).
+
+    Tools/scripts/ndiff.py is a command-line front-end to this function.
+
+    Example:
+
+    >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(1),
+    ...              'ore\ntree\nemu\n'.splitlines(1))
+    >>> print ''.join(diff),
+    - one
+    ?  ^
+    + ore
+    ?  ^
+    - two
+    - three
+    ?  -
+    + tree
+    + emu
+    """
+    return Differ(linejunk, charjunk).compare(a, b)
+
+def _mdiff(fromlines, tolines, context=None, linejunk=None,
+           charjunk=IS_CHARACTER_JUNK):
+    r"""Returns generator yielding marked up from/to side by side differences.
+
+    Arguments:
+    fromlines -- list of text lines to compared to tolines
+    tolines -- list of text lines to be compared to fromlines
+    context -- number of context lines to display on each side of difference,
+               if None, all from/to text lines will be generated.
+    linejunk -- passed on to ndiff (see ndiff documentation)
+    charjunk -- passed on to ndiff (see ndiff documentation)
+
+    This function returns an interator which returns a tuple:
+    (from line tuple, to line tuple, boolean flag)
+
+    from/to line tuple -- (line num, line text)
+        line num -- integer or None (to indicate a context separation)
+        line text -- original line text with following markers inserted:
+            '\0+' -- marks start of added text
+            '\0-' -- marks start of deleted text
+            '\0^' -- marks start of changed text
+            '\1' -- marks end of added/deleted/changed text
+
+    boolean flag -- None indicates context separation, True indicates
+        either "from" or "to" line contains a change, otherwise False.
+
+    This function/iterator was originally developed to generate side by side
+    file difference for making HTML pages (see HtmlDiff class for example
+    usage).
+
+    Note, this function utilizes the ndiff function to generate the side by
+    side difference markup.  Optional ndiff arguments may be passed to this
+    function and they in turn will be passed to ndiff.
+    """
+    import re
+
+    # regular expression for finding intraline change indices
+    change_re = re.compile('(\++|\-+|\^+)')
+
+    # create the difference iterator to generate the differences
+    diff_lines_iterator = ndiff(fromlines,tolines,linejunk,charjunk)
+
+    def _make_line(lines, format_key, side, num_lines=[0,0]):
+        """Returns line of text with user's change markup and line formatting.
+
+        lines -- list of lines from the ndiff generator to produce a line of
+                 text from.  When producing the line of text to return, the
+                 lines used are removed from this list.
+        format_key -- '+' return first line in list with "add" markup around
+                          the entire line.
+                      '-' return first line in list with "delete" markup around
+                          the entire line.
+                      '?' return first line in list with add/delete/change
+                          intraline markup (indices obtained from second line)
+                      None return first line in list with no markup
+        side -- indice into the num_lines list (0=from,1=to)
+        num_lines -- from/to current line number.  This is NOT intended to be a
+                     passed parameter.  It is present as a keyword argument to
+                     maintain memory of the current line numbers between calls
+                     of this function.
+
+        Note, this function is purposefully not defined at the module scope so
+        that data it needs from its parent function (within whose context it
+        is defined) does not need to be of module scope.
+        """
+        num_lines[side] += 1
+        # Handle case where no user markup is to be added, just return line of
+        # text with user's line format to allow for usage of the line number.
+        if format_key is None:
+            return (num_lines[side],lines.pop(0)[2:])
+        # Handle case of intraline changes
+        if format_key == '?':
+            text, markers = lines.pop(0), lines.pop(0)
+            # find intraline changes (store change type and indices in tuples)
+            sub_info = []
+            def record_sub_info(match_object,sub_info=sub_info):
+                sub_info.append([match_object.group(1)[0],match_object.span()])
+                return match_object.group(1)
+            change_re.sub(record_sub_info,markers)
+            # process each tuple inserting our special marks that won't be
+            # noticed by an xml/html escaper.
+            for key,(begin,end) in sub_info[::-1]:
+                text = text[0:begin]+'\0'+key+text[begin:end]+'\1'+text[end:]
+            text = text[2:]
+        # Handle case of add/delete entire line
+        else:
+            text = lines.pop(0)[2:]
+            # if line of text is just a newline, insert a space so there is
+            # something for the user to highlight and see.
+            if not text:
+                text = ' '
+            # insert marks that won't be noticed by an xml/html escaper.
+            text = '\0' + format_key + text + '\1'
+        # Return line of text, first allow user's line formatter to do its
+        # thing (such as adding the line number) then replace the special
+        # marks with what the user's change markup.
+        return (num_lines[side],text)
+
+    def _line_iterator():
+        """Yields from/to lines of text with a change indication.
+
+        This function is an iterator.  It itself pulls lines from a
+        differencing iterator, processes them and yields them.  When it can
+        it yields both a "from" and a "to" line, otherwise it will yield one
+        or the other.  In addition to yielding the lines of from/to text, a
+        boolean flag is yielded to indicate if the text line(s) have
+        differences in them.
+
+        Note, this function is purposefully not defined at the module scope so
+        that data it needs from its parent function (within whose context it
+        is defined) does not need to be of module scope.
+        """
+        lines = []
+        num_blanks_pending, num_blanks_to_yield = 0, 0
+        while True:
+            # Load up next 4 lines so we can look ahead, create strings which
+            # are a concatenation of the first character of each of the 4 lines
+            # so we can do some very readable comparisons.
+            while len(lines) < 4:
+                try:
+                    lines.append(diff_lines_iterator.next())
+                except StopIteration:
+                    lines.append('X')
+            s = ''.join([line[0] for line in lines])
+            if s.startswith('X'):
+                # When no more lines, pump out any remaining blank lines so the
+                # corresponding add/delete lines get a matching blank line so
+                # all line pairs get yielded at the next level.
+                num_blanks_to_yield = num_blanks_pending
+            elif s.startswith('-?+?'):
+                # simple intraline change
+                yield _make_line(lines,'?',0), _make_line(lines,'?',1), True
+                continue
+            elif s.startswith('--++'):
+                # in delete block, add block coming: we do NOT want to get
+                # caught up on blank lines yet, just process the delete line
+                num_blanks_pending -= 1
+                yield _make_line(lines,'-',0), None, True
+                continue
+            elif s.startswith(('--?+', '--+', '- ')):
+                # in delete block and see a intraline change or unchanged line
+                # coming: yield the delete line and then blanks
+                from_line,to_line = _make_line(lines,'-',0), None
+                num_blanks_to_yield,num_blanks_pending = num_blanks_pending-1,0
+            elif s.startswith('-+?'):
+                # intraline change
+                yield _make_line(lines,None,0), _make_line(lines,'?',1), True
+                continue
+            elif s.startswith('-?+'):
+                # intraline change
+                yield _make_line(lines,'?',0), _make_line(lines,None,1), True
+                continue
+            elif s.startswith('-'):
+                # delete FROM line
+                num_blanks_pending -= 1
+                yield _make_line(lines,'-',0), None, True
+                continue
+            elif s.startswith('+--'):
+                # in add block, delete block coming: we do NOT want to get
+                # caught up on blank lines yet, just process the add line
+                num_blanks_pending += 1
+                yield None, _make_line(lines,'+',1), True
+                continue
+            elif s.startswith(('+ ', '+-')):
+                # will be leaving an add block: yield blanks then add line
+                from_line, to_line = None, _make_line(lines,'+',1)
+                num_blanks_to_yield,num_blanks_pending = num_blanks_pending+1,0
+            elif s.startswith('+'):
+                # inside an add block, yield the add line
+                num_blanks_pending += 1
+                yield None, _make_line(lines,'+',1), True
+                continue
+            elif s.startswith(' '):
+                # unchanged text, yield it to both sides
+                yield _make_line(lines[:],None,0),_make_line(lines,None,1),False
+                continue
+            # Catch up on the blank lines so when we yield the next from/to
+            # pair, they are lined up.
+            while(num_blanks_to_yield < 0):
+                num_blanks_to_yield += 1
+                yield None,('','\n'),True
+            while(num_blanks_to_yield > 0):
+                num_blanks_to_yield -= 1
+                yield ('','\n'),None,True
+            if s.startswith('X'):
+                raise StopIteration
+            else:
+                yield from_line,to_line,True
+
+    def _line_pair_iterator():
+        """Yields from/to lines of text with a change indication.
+
+        This function is an iterator.  It itself pulls lines from the line
+        iterator.  Its difference from that iterator is that this function
+        always yields a pair of from/to text lines (with the change
+        indication).  If necessary it will collect single from/to lines
+        until it has a matching pair from/to pair to yield.
+
+        Note, this function is purposefully not defined at the module scope so
+        that data it needs from its parent function (within whose context it
+        is defined) does not need to be of module scope.
+        """
+        line_iterator = _line_iterator()
+        fromlines,tolines=[],[]
+        while True:
+            # Collecting lines of text until we have a from/to pair
+            while (len(fromlines)==0 or len(tolines)==0):
+                from_line, to_line, found_diff =line_iterator.next()
+                if from_line is not None:
+                    fromlines.append((from_line,found_diff))
+                if to_line is not None:
+                    tolines.append((to_line,found_diff))
+            # Once we have a pair, remove them from the collection and yield it
+            from_line, fromDiff = fromlines.pop(0)
+            to_line, to_diff = tolines.pop(0)
+            yield (from_line,to_line,fromDiff or to_diff)
+
+    # Handle case where user does not want context differencing, just yield
+    # them up without doing anything else with them.
+    line_pair_iterator = _line_pair_iterator()
+    if context is None:
+        while True:
+            yield line_pair_iterator.next()
+    # Handle case where user wants context differencing.  We must do some
+    # storage of lines until we know for sure that they are to be yielded.
+    else:
+        context += 1
+        lines_to_write = 0
+        while True:
+            # Store lines up until we find a difference, note use of a
+            # circular queue because we only need to keep around what
+            # we need for context.
+            index, contextLines = 0, [None]*(context)
+            found_diff = False
+            while(found_diff is False):
+                from_line, to_line, found_diff = line_pair_iterator.next()
+                i = index % context
+                contextLines[i] = (from_line, to_line, found_diff)
+                index += 1
+            # Yield lines that we have collected so far, but first yield
+            # the user's separator.
+            if index > context:
+                yield None, None, None
+                lines_to_write = context
+            else:
+                lines_to_write = index
+                index = 0
+            while(lines_to_write):
+                i = index % context
+                index += 1
+                yield contextLines[i]
+                lines_to_write -= 1
+            # Now yield the context lines after the change
+            lines_to_write = context-1
+            while(lines_to_write):
+                from_line, to_line, found_diff = line_pair_iterator.next()
+                # If another change within the context, extend the context
+                if found_diff:
+                    lines_to_write = context-1
+                else:
+                    lines_to_write -= 1
+                yield from_line, to_line, found_diff
+
+
+_file_template = """
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+
+<head>
+    <meta http-equiv="Content-Type"
+          content="text/html; charset=ISO-8859-1" />
+    <title></title>
+    <style type="text/css">%(styles)s
+    </style>
+</head>
+
+<body>
+    %(table)s%(legend)s
+</body>
+
+</html>"""
+
+_styles = """
+        table.diff {font-family:Courier; border:medium;}
+        .diff_header {background-color:#e0e0e0}
+        td.diff_header {text-align:right}
+        .diff_next {background-color:#c0c0c0}
+        .diff_add {background-color:#aaffaa}
+        .diff_chg {background-color:#ffff77}
+        .diff_sub {background-color:#ffaaaa}"""
+
+_table_template = """
+    <table class="diff" id="difflib_chg_%(prefix)s_top"
+           cellspacing="0" cellpadding="0" rules="groups" >
+        <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup>
+        <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup>
+        %(header_row)s
+        <tbody>
+%(data_rows)s        </tbody>
+    </table>"""
+
+_legend = """
+    <table class="diff" summary="Legends">
+        <tr> <th colspan="2"> Legends </th> </tr>
+        <tr> <td> <table border="" summary="Colors">
+                      <tr><th> Colors </th> </tr>
+                      <tr><td class="diff_add">&nbsp;Added&nbsp;</td></tr>
+                      <tr><td class="diff_chg">Changed</td> </tr>
+                      <tr><td class="diff_sub">Deleted</td> </tr>
+                  </table></td>
+             <td> <table border="" summary="Links">
+                      <tr><th colspan="2"> Links </th> </tr>
+                      <tr><td>(f)irst change</td> </tr>
+                      <tr><td>(n)ext change</td> </tr>
+                      <tr><td>(t)op</td> </tr>
+                  </table></td> </tr>
+    </table>"""
+
+class HtmlDiff(object):
+    """For producing HTML side by side comparison with change highlights.
+
+    This class can be used to create an HTML table (or a complete HTML file
+    containing the table) showing a side by side, line by line comparison
+    of text with inter-line and intra-line change highlights.  The table can
+    be generated in either full or contextual difference mode.
+
+    The following methods are provided for HTML generation:
+
+    make_table -- generates HTML for a single side by side table
+    make_file -- generates complete HTML file with a single side by side table
+
+    See tools/scripts/diff.py for an example usage of this class.
+    """
+
+    _file_template = _file_template
+    _styles = _styles
+    _table_template = _table_template
+    _legend = _legend
+    _default_prefix = 0
+
+    def __init__(self,tabsize=8,wrapcolumn=None,linejunk=None,
+                 charjunk=IS_CHARACTER_JUNK):
+        """HtmlDiff instance initializer
+
+        Arguments:
+        tabsize -- tab stop spacing, defaults to 8.
+        wrapcolumn -- column number where lines are broken and wrapped,
+            defaults to None where lines are not wrapped.
+        linejunk,charjunk -- keyword arguments passed into ndiff() (used to by
+            HtmlDiff() to generate the side by side HTML differences).  See
+            ndiff() documentation for argument default values and descriptions.
+        """
+        self._tabsize = tabsize
+        self._wrapcolumn = wrapcolumn
+        self._linejunk = linejunk
+        self._charjunk = charjunk
+
+    def make_file(self,fromlines,tolines,fromdesc='',todesc='',context=False,
+                  numlines=5):
+        """Returns HTML file of side by side comparison with change highlights
+
+        Arguments:
+        fromlines -- list of "from" lines
+        tolines -- list of "to" lines
+        fromdesc -- "from" file column header string
+        todesc -- "to" file column header string
+        context -- set to True for contextual differences (defaults to False
+            which shows full differences).
+        numlines -- number of context lines.  When context is set True,
+            controls number of lines displayed before and after the change.
+            When context is False, controls the number of lines to place
+            the "next" link anchors before the next change (so click of
+            "next" link jumps to just before the change).
+        """
+
+        return self._file_template % dict(
+            styles = self._styles,
+            legend = self._legend,
+            table = self.make_table(fromlines,tolines,fromdesc,todesc,
+                                    context=context,numlines=numlines))
+
+    def _tab_newline_replace(self,fromlines,tolines):
+        """Returns from/to line lists with tabs expanded and newlines removed.
+
+        Instead of tab characters being replaced by the number of spaces
+        needed to fill in to the next tab stop, this function will fill
+        the space with tab characters.  This is done so that the difference
+        algorithms can identify changes in a file when tabs are replaced by
+        spaces and vice versa.  At the end of the HTML generation, the tab
+        characters will be replaced with a nonbreakable space.
+        """
+        def expand_tabs(line):
+            # hide real spaces
+            line = line.replace(' ','\0')
+            # expand tabs into spaces
+            line = line.expandtabs(self._tabsize)
+            # replace spaces from expanded tabs back into tab characters
+            # (we'll replace them with markup after we do differencing)
+            line = line.replace(' ','\t')
+            return line.replace('\0',' ').rstrip('\n')
+        fromlines = [expand_tabs(line) for line in fromlines]
+        tolines = [expand_tabs(line) for line in tolines]
+        return fromlines,tolines
+
+    def _split_line(self,data_list,line_num,text):
+        """Builds list of text lines by splitting text lines at wrap point
+
+        This function will determine if the input text line needs to be
+        wrapped (split) into separate lines.  If so, the first wrap point
+        will be determined and the first line appended to the output
+        text line list.  This function is used recursively to handle
+        the second part of the split line to further split it.
+        """
+        # if blank line or context separator, just add it to the output list
+        if not line_num:
+            data_list.append((line_num,text))
+            return
+
+        # if line text doesn't need wrapping, just add it to the output list
+        size = len(text)
+        max = self._wrapcolumn
+        if (size <= max) or ((size -(text.count('\0')*3)) <= max):
+            data_list.append((line_num,text))
+            return
+
+        # scan text looking for the wrap point, keeping track if the wrap
+        # point is inside markers
+        i = 0
+        n = 0
+        mark = ''
+        while n < max and i < size:
+            if text[i] == '\0':
+                i += 1
+                mark = text[i]
+                i += 1
+            elif text[i] == '\1':
+                i += 1
+                mark = ''
+            else:
+                i += 1
+                n += 1
+
+        # wrap point is inside text, break it up into separate lines
+        line1 = text[:i]
+        line2 = text[i:]
+
+        # if wrap point is inside markers, place end marker at end of first
+        # line and start marker at beginning of second line because each
+        # line will have its own table tag markup around it.
+        if mark:
+            line1 = line1 + '\1'
+            line2 = '\0' + mark + line2
+
+        # tack on first line onto the output list
+        data_list.append((line_num,line1))
+
+        # use this routine again to wrap the remaining text
+        self._split_line(data_list,'>',line2)
+
+    def _line_wrapper(self,diffs):
+        """Returns iterator that splits (wraps) mdiff text lines"""
+
+        # pull from/to data and flags from mdiff iterator
+        for fromdata,todata,flag in diffs:
+            # check for context separators and pass them through
+            if flag is None:
+                yield fromdata,todata,flag
+                continue
+            (fromline,fromtext),(toline,totext) = fromdata,todata
+            # for each from/to line split it at the wrap column to form
+            # list of text lines.
+            fromlist,tolist = [],[]
+            self._split_line(fromlist,fromline,fromtext)
+            self._split_line(tolist,toline,totext)
+            # yield from/to line in pairs inserting blank lines as
+            # necessary when one side has more wrapped lines
+            while fromlist or tolist:
+                if fromlist:
+                    fromdata = fromlist.pop(0)
+                else:
+                    fromdata = ('',' ')
+                if tolist:
+                    todata = tolist.pop(0)
+                else:
+                    todata = ('',' ')
+                yield fromdata,todata,flag
+
+    def _collect_lines(self,diffs):
+        """Collects mdiff output into separate lists
+
+        Before storing the mdiff from/to data into a list, it is converted
+        into a single line of text with HTML markup.
+        """
+
+        fromlist,tolist,flaglist = [],[],[]
+        # pull from/to data and flags from mdiff style iterator
+        for fromdata,todata,flag in diffs:
+            try:
+                # store HTML markup of the lines into the lists
+                fromlist.append(self._format_line(0,flag,*fromdata))
+                tolist.append(self._format_line(1,flag,*todata))
+            except TypeError:
+                # exceptions occur for lines where context separators go
+                fromlist.append(None)
+                tolist.append(None)
+            flaglist.append(flag)
+        return fromlist,tolist,flaglist
+
+    def _format_line(self,side,flag,linenum,text):
+        """Returns HTML markup of "from" / "to" text lines
+
+        side -- 0 or 1 indicating "from" or "to" text
+        flag -- indicates if difference on line
+        linenum -- line number (used for line number column)
+        text -- line text to be marked up
+        """
+        try:
+            linenum = '%d' % linenum
+            id = ' id="%s%s"' % (self._prefix[side],linenum)
+        except TypeError:
+            # handle blank lines where linenum is '>' or ''
+            id = ''
+        # replace those things that would get confused with HTML symbols
+        text=text.replace("&","&amp;").replace(">","&gt;").replace("<","&lt;")
+
+        # make space non-breakable so they don't get compressed or line wrapped
+        text = text.replace(' ','&nbsp;').rstrip()
+
+        return '<td class="diff_header"%s>%s</td><td nowrap="nowrap">%s</td>' \
+               % (id,linenum,text)
+
+    def _make_prefix(self):
+        """Create unique anchor prefixes"""
+
+        # Generate a unique anchor prefix so multiple tables
+        # can exist on the same HTML page without conflicts.
+        fromprefix = "from%d_" % HtmlDiff._default_prefix
+        toprefix = "to%d_" % HtmlDiff._default_prefix
+        HtmlDiff._default_prefix += 1
+        # store prefixes so line format method has access
+        self._prefix = [fromprefix,toprefix]
+
+    def _convert_flags(self,fromlist,tolist,flaglist,context,numlines):
+        """Makes list of "next" links"""
+
+        # all anchor names will be generated using the unique "to" prefix
+        toprefix = self._prefix[1]
+
+        # process change flags, generating middle column of next anchors/links
+        next_id = ['']*len(flaglist)
+        next_href = ['']*len(flaglist)
+        num_chg, in_change = 0, False
+        last = 0
+        for i,flag in enumerate(flaglist):
+            if flag:
+                if not in_change:
+                    in_change = True
+                    last = i
+                    # at the beginning of a change, drop an anchor a few lines
+                    # (the context lines) before the change for the previous
+                    # link
+                    i = max([0,i-numlines])
+                    next_id[i] = ' id="difflib_chg_%s_%d"' % (toprefix,num_chg)
+                    # at the beginning of a change, drop a link to the next
+                    # change
+                    num_chg += 1
+                    next_href[last] = '<a href="#difflib_chg_%s_%d">n</a>' % (
+                         toprefix,num_chg)
+            else:
+                in_change = False
+        # check for cases where there is no content to avoid exceptions
+        if not flaglist:
+            flaglist = [False]
+            next_id = ['']
+            next_href = ['']
+            last = 0
+            if context:
+                fromlist = ['<td></td><td>&nbsp;No Differences Found&nbsp;</td>']
+                tolist = fromlist
+            else:
+                fromlist = tolist = ['<td></td><td>&nbsp;Empty File&nbsp;</td>']
+        # if not a change on first line, drop a link
+        if not flaglist[0]:
+            next_href[0] = '<a href="#difflib_chg_%s_0">f</a>' % toprefix
+        # redo the last link to link to the top
+        next_href[last] = '<a href="#difflib_chg_%s_top">t</a>' % (toprefix)
+
+        return fromlist,tolist,flaglist,next_href,next_id
+
+    def make_table(self,fromlines,tolines,fromdesc='',todesc='',context=False,
+                   numlines=5):
+        """Returns HTML table of side by side comparison with change highlights
+
+        Arguments:
+        fromlines -- list of "from" lines
+        tolines -- list of "to" lines
+        fromdesc -- "from" file column header string
+        todesc -- "to" file column header string
+        context -- set to True for contextual differences (defaults to False
+            which shows full differences).
+        numlines -- number of context lines.  When context is set True,
+            controls number of lines displayed before and after the change.
+            When context is False, controls the number of lines to place
+            the "next" link anchors before the next change (so click of
+            "next" link jumps to just before the change).
+        """
+
+        # make unique anchor prefixes so that multiple tables may exist
+        # on the same page without conflict.
+        self._make_prefix()
+
+        # change tabs to spaces before it gets more difficult after we insert
+        # markkup
+        fromlines,tolines = self._tab_newline_replace(fromlines,tolines)
+
+        # create diffs iterator which generates side by side from/to data
+        if context:
+            context_lines = numlines
+        else:
+            context_lines = None
+        diffs = _mdiff(fromlines,tolines,context_lines,linejunk=self._linejunk,
+                      charjunk=self._charjunk)
+
+        # set up iterator to wrap lines that exceed desired width
+        if self._wrapcolumn:
+            diffs = self._line_wrapper(diffs)
+
+        # collect up from/to lines and flags into lists (also format the lines)
+        fromlist,tolist,flaglist = self._collect_lines(diffs)
+
+        # process change flags, generating middle column of next anchors/links
+        fromlist,tolist,flaglist,next_href,next_id = self._convert_flags(
+            fromlist,tolist,flaglist,context,numlines)
+
+        s = []
+        fmt = '            <tr><td class="diff_next"%s>%s</td>%s' + \
+              '<td class="diff_next">%s</td>%s</tr>\n'
+        for i in range(len(flaglist)):
+            if flaglist[i] is None:
+                # mdiff yields None on separator lines skip the bogus ones
+                # generated for the first line
+                if i > 0:
+                    s.append('        </tbody>        \n        <tbody>\n')
+            else:
+                s.append( fmt % (next_id[i],next_href[i],fromlist[i],
+                                           next_href[i],tolist[i]))
+        if fromdesc or todesc:
+            header_row = '<thead><tr>%s%s%s%s</tr></thead>' % (
+                '<th class="diff_next"><br /></th>',
+                '<th colspan="2" class="diff_header">%s</th>' % fromdesc,
+                '<th class="diff_next"><br /></th>',
+                '<th colspan="2" class="diff_header">%s</th>' % todesc)
+        else:
+            header_row = ''
+
+        table = self._table_template % dict(
+            data_rows=''.join(s),
+            header_row=header_row,
+            prefix=self._prefix[1])
+
+        return table.replace('\0+','<span class="diff_add">'). \
+                     replace('\0-','<span class="diff_sub">'). \
+                     replace('\0^','<span class="diff_chg">'). \
+                     replace('\1','</span>'). \
+                     replace('\t','&nbsp;')
+
+del re
+
+def restore(delta, which):
+    r"""
+    Generate one of the two sequences that generated a delta.
+
+    Given a `delta` produced by `Differ.compare()` or `ndiff()`, extract
+    lines originating from file 1 or 2 (parameter `which`), stripping off line
+    prefixes.
+
+    Examples:
+
+    >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(1),
+    ...              'ore\ntree\nemu\n'.splitlines(1))
+    >>> diff = list(diff)
+    >>> print ''.join(restore(diff, 1)),
+    one
+    two
+    three
+    >>> print ''.join(restore(diff, 2)),
+    ore
+    tree
+    emu
+    """
+    try:
+        tag = {1: "- ", 2: "+ "}[int(which)]
+    except KeyError:
+        raise ValueError, ('unknown delta choice (must be 1 or 2): %r'
+                           % which)
+    prefixes = ("  ", tag)
+    for line in delta:
+        if line[:2] in prefixes:
+            yield line[2:]
+
+def _test():
+    import doctest, difflib
+    return doctest.testmod(difflib)
+
+if __name__ == "__main__":
+    _test()
diff --git a/src/main/resources/PythonLibs/dircache.py b/src/main/resources/PythonLibs/dircache.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e4f0b508ac74e47495622472b2382370fa3d9d9
--- /dev/null
+++ b/src/main/resources/PythonLibs/dircache.py
@@ -0,0 +1,41 @@
+"""Read and cache directory listings.
+
+The listdir() routine returns a sorted list of the files in a directory,
+using a cache to avoid reading the directory more often than necessary.
+The annotate() routine appends slashes to directories."""
+from warnings import warnpy3k
+warnpy3k("the dircache module has been removed in Python 3.0", stacklevel=2)
+del warnpy3k
+
+import os
+
+__all__ = ["listdir", "opendir", "annotate", "reset"]
+
+cache = {}
+
+def reset():
+    """Reset the cache completely."""
+    global cache
+    cache = {}
+
+def listdir(path):
+    """List directory contents, using cache."""
+    try:
+        cached_mtime, list = cache[path]
+        del cache[path]
+    except KeyError:
+        cached_mtime, list = -1, []
+    mtime = os.stat(path).st_mtime
+    if mtime != cached_mtime:
+        list = os.listdir(path)
+        list.sort()
+    cache[path] = mtime, list
+    return list
+
+opendir = listdir # XXX backward compatibility
+
+def annotate(head, list):
+    """Add '/' suffixes to directories."""
+    for i in range(len(list)):
+        if os.path.isdir(os.path.join(head, list[i])):
+            list[i] = list[i] + '/'
diff --git a/src/main/resources/PythonLibs/dis.py b/src/main/resources/PythonLibs/dis.py
new file mode 100644
index 0000000000000000000000000000000000000000..5aa09c95b6d8df8354e38be0d5163e9796302cb3
--- /dev/null
+++ b/src/main/resources/PythonLibs/dis.py
@@ -0,0 +1,224 @@
+"""Disassembler of Python byte code into mnemonics."""
+
+import sys
+import types
+
+from opcode import *
+from opcode import __all__ as _opcodes_all
+
+__all__ = ["dis", "disassemble", "distb", "disco",
+           "findlinestarts", "findlabels"] + _opcodes_all
+del _opcodes_all
+
+_have_code = (types.MethodType, types.FunctionType, types.CodeType,
+              types.ClassType, type)
+
+def dis(x=None):
+    """Disassemble classes, methods, functions, or code.
+
+    With no argument, disassemble the last traceback.
+
+    """
+    if x is None:
+        distb()
+        return
+    if isinstance(x, types.InstanceType):
+        x = x.__class__
+    if hasattr(x, 'im_func'):
+        x = x.im_func
+    if hasattr(x, 'func_code'):
+        x = x.func_code
+    if hasattr(x, '__dict__'):
+        items = x.__dict__.items()
+        items.sort()
+        for name, x1 in items:
+            if isinstance(x1, _have_code):
+                print "Disassembly of %s:" % name
+                try:
+                    dis(x1)
+                except TypeError, msg:
+                    print "Sorry:", msg
+                print
+    elif hasattr(x, 'co_code'):
+        disassemble(x)
+    elif isinstance(x, str):
+        disassemble_string(x)
+    else:
+        raise TypeError, \
+              "don't know how to disassemble %s objects" % \
+              type(x).__name__
+
+def distb(tb=None):
+    """Disassemble a traceback (default: last traceback)."""
+    if tb is None:
+        try:
+            tb = sys.last_traceback
+        except AttributeError:
+            raise RuntimeError, "no last traceback to disassemble"
+        while tb.tb_next: tb = tb.tb_next
+    disassemble(tb.tb_frame.f_code, tb.tb_lasti)
+
+def disassemble(co, lasti=-1):
+    """Disassemble a code object."""
+    code = co.co_code
+    labels = findlabels(code)
+    linestarts = dict(findlinestarts(co))
+    n = len(code)
+    i = 0
+    extended_arg = 0
+    free = None
+    while i < n:
+        c = code[i]
+        op = ord(c)
+        if i in linestarts:
+            if i > 0:
+                print
+            print "%3d" % linestarts[i],
+        else:
+            print '   ',
+
+        if i == lasti: print '-->',
+        else: print '   ',
+        if i in labels: print '>>',
+        else: print '  ',
+        print repr(i).rjust(4),
+        print opname[op].ljust(20),
+        i = i+1
+        if op >= HAVE_ARGUMENT:
+            oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
+            extended_arg = 0
+            i = i+2
+            if op == EXTENDED_ARG:
+                extended_arg = oparg*65536L
+            print repr(oparg).rjust(5),
+            if op in hasconst:
+                print '(' + repr(co.co_consts[oparg]) + ')',
+            elif op in hasname:
+                print '(' + co.co_names[oparg] + ')',
+            elif op in hasjrel:
+                print '(to ' + repr(i + oparg) + ')',
+            elif op in haslocal:
+                print '(' + co.co_varnames[oparg] + ')',
+            elif op in hascompare:
+                print '(' + cmp_op[oparg] + ')',
+            elif op in hasfree:
+                if free is None:
+                    free = co.co_cellvars + co.co_freevars
+                print '(' + free[oparg] + ')',
+        print
+
+def disassemble_string(code, lasti=-1, varnames=None, names=None,
+                       constants=None):
+    labels = findlabels(code)
+    n = len(code)
+    i = 0
+    while i < n:
+        c = code[i]
+        op = ord(c)
+        if i == lasti: print '-->',
+        else: print '   ',
+        if i in labels: print '>>',
+        else: print '  ',
+        print repr(i).rjust(4),
+        print opname[op].ljust(15),
+        i = i+1
+        if op >= HAVE_ARGUMENT:
+            oparg = ord(code[i]) + ord(code[i+1])*256
+            i = i+2
+            print repr(oparg).rjust(5),
+            if op in hasconst:
+                if constants:
+                    print '(' + repr(constants[oparg]) + ')',
+                else:
+                    print '(%d)'%oparg,
+            elif op in hasname:
+                if names is not None:
+                    print '(' + names[oparg] + ')',
+                else:
+                    print '(%d)'%oparg,
+            elif op in hasjrel:
+                print '(to ' + repr(i + oparg) + ')',
+            elif op in haslocal:
+                if varnames:
+                    print '(' + varnames[oparg] + ')',
+                else:
+                    print '(%d)' % oparg,
+            elif op in hascompare:
+                print '(' + cmp_op[oparg] + ')',
+        print
+
+disco = disassemble                     # XXX For backwards compatibility
+
+def findlabels(code):
+    """Detect all offsets in a byte code which are jump targets.
+
+    Return the list of offsets.
+
+    """
+    labels = []
+    n = len(code)
+    i = 0
+    while i < n:
+        c = code[i]
+        op = ord(c)
+        i = i+1
+        if op >= HAVE_ARGUMENT:
+            oparg = ord(code[i]) + ord(code[i+1])*256
+            i = i+2
+            label = -1
+            if op in hasjrel:
+                label = i+oparg
+            elif op in hasjabs:
+                label = oparg
+            if label >= 0:
+                if label not in labels:
+                    labels.append(label)
+    return labels
+
+def findlinestarts(code):
+    """Find the offsets in a byte code which are start of lines in the source.
+
+    Generate pairs (offset, lineno) as described in Python/compile.c.
+
+    """
+    byte_increments = [ord(c) for c in code.co_lnotab[0::2]]
+    line_increments = [ord(c) for c in code.co_lnotab[1::2]]
+
+    lastlineno = None
+    lineno = code.co_firstlineno
+    addr = 0
+    for byte_incr, line_incr in zip(byte_increments, line_increments):
+        if byte_incr:
+            if lineno != lastlineno:
+                yield (addr, lineno)
+                lastlineno = lineno
+            addr += byte_incr
+        lineno += line_incr
+    if lineno != lastlineno:
+        yield (addr, lineno)
+
+def _test():
+    """Simple test program to disassemble a file."""
+    if sys.argv[1:]:
+        if sys.argv[2:]:
+            sys.stderr.write("usage: python dis.py [-|file]\n")
+            sys.exit(2)
+        fn = sys.argv[1]
+        if not fn or fn == "-":
+            fn = None
+    else:
+        fn = None
+    if fn is None:
+        f = sys.stdin
+    else:
+        f = open(fn)
+    source = f.read()
+    if fn is not None:
+        f.close()
+    else:
+        fn = "<stdin>"
+    code = compile(source, fn, "exec")
+    dis(code)
+
+if __name__ == "__main__":
+    _test()
diff --git a/src/main/resources/PythonLibs/distutils/README b/src/main/resources/PythonLibs/distutils/README
new file mode 100644
index 0000000000000000000000000000000000000000..408a203b85d5ffd0d5447e27207e2b99dc49078f
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/README
@@ -0,0 +1,13 @@
+This directory contains the Distutils package.
+
+There's a full documentation available at:
+
+    http://docs.python.org/distutils/
+
+The Distutils-SIG web page is also a good starting point:
+
+    http://www.python.org/sigs/distutils-sig/
+
+WARNING : Distutils must remain compatible with 2.3
+
+$Id$
diff --git a/src/main/resources/PythonLibs/distutils/__init__.py b/src/main/resources/PythonLibs/distutils/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..036062cc337aa081758f85f9c8378b8d758fa2fb
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/__init__.py
@@ -0,0 +1,19 @@
+"""distutils
+
+The main package for the Python Module Distribution Utilities.  Normally
+used from a setup script as
+
+   from distutils.core import setup
+
+   setup (...)
+"""
+
+__revision__ = "$Id$"
+
+# Distutils version
+#
+# Updated automatically by the Python release process.
+#
+#--start constants--
+__version__ = "2.7.3"
+#--end constants--
diff --git a/src/main/resources/PythonLibs/distutils/archive_util.py b/src/main/resources/PythonLibs/distutils/archive_util.py
new file mode 100644
index 0000000000000000000000000000000000000000..834b722ed3f140784e308231f667794c9c2a4b43
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/archive_util.py
@@ -0,0 +1,243 @@
+"""distutils.archive_util
+
+Utility functions for creating archive files (tarballs, zip files,
+that sort of thing)."""
+
+__revision__ = "$Id$"
+
+import os
+from warnings import warn
+import sys
+
+from distutils.errors import DistutilsExecError
+from distutils.spawn import spawn
+from distutils.dir_util import mkpath
+from distutils import log
+
+try:
+    from pwd import getpwnam
+except ImportError:
+    getpwnam = None
+
+try:
+    from grp import getgrnam
+except ImportError:
+    getgrnam = None
+
+def _get_gid(name):
+    """Returns a gid, given a group name."""
+    if getgrnam is None or name is None:
+        return None
+    try:
+        result = getgrnam(name)
+    except KeyError:
+        result = None
+    if result is not None:
+        return result[2]
+    return None
+
+def _get_uid(name):
+    """Returns an uid, given a user name."""
+    if getpwnam is None or name is None:
+        return None
+    try:
+        result = getpwnam(name)
+    except KeyError:
+        result = None
+    if result is not None:
+        return result[2]
+    return None
+
+def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
+                 owner=None, group=None):
+    """Create a (possibly compressed) tar file from all the files under
+    'base_dir'.
+
+    'compress' must be "gzip" (the default), "compress", "bzip2", or None.
+    (compress will be deprecated in Python 3.2)
+
+    'owner' and 'group' can be used to define an owner and a group for the
+    archive that is being built. If not provided, the current owner and group
+    will be used.
+
+    The output tar file will be named 'base_dir' +  ".tar", possibly plus
+    the appropriate compression extension (".gz", ".bz2" or ".Z").
+
+    Returns the output filename.
+    """
+    tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''}
+    compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'compress': '.Z'}
+
+    # flags for compression program, each element of list will be an argument
+    if compress is not None and compress not in compress_ext.keys():
+        raise ValueError, \
+              ("bad value for 'compress': must be None, 'gzip', 'bzip2' "
+               "or 'compress'")
+
+    archive_name = base_name + '.tar'
+    if compress != 'compress':
+        archive_name += compress_ext.get(compress, '')
+
+    mkpath(os.path.dirname(archive_name), dry_run=dry_run)
+
+    # creating the tarball
+    import tarfile  # late import so Python build itself doesn't break
+
+    log.info('Creating tar archive')
+
+    uid = _get_uid(owner)
+    gid = _get_gid(group)
+
+    def _set_uid_gid(tarinfo):
+        if gid is not None:
+            tarinfo.gid = gid
+            tarinfo.gname = group
+        if uid is not None:
+            tarinfo.uid = uid
+            tarinfo.uname = owner
+        return tarinfo
+
+    if not dry_run:
+        tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
+        try:
+            tar.add(base_dir, filter=_set_uid_gid)
+        finally:
+            tar.close()
+
+    # compression using `compress`
+    if compress == 'compress':
+        warn("'compress' will be deprecated.", PendingDeprecationWarning)
+        # the option varies depending on the platform
+        compressed_name = archive_name + compress_ext[compress]
+        if sys.platform == 'win32':
+            cmd = [compress, archive_name, compressed_name]
+        else:
+            cmd = [compress, '-f', archive_name]
+        spawn(cmd, dry_run=dry_run)
+        return compressed_name
+
+    return archive_name
+
+def make_zipfile(base_name, base_dir, verbose=0, dry_run=0):
+    """Create a zip file from all the files under 'base_dir'.
+
+    The output zip file will be named 'base_name' + ".zip".  Uses either the
+    "zipfile" Python module (if available) or the InfoZIP "zip" utility
+    (if installed and found on the default search path).  If neither tool is
+    available, raises DistutilsExecError.  Returns the name of the output zip
+    file.
+    """
+    try:
+        import zipfile
+    except ImportError:
+        zipfile = None
+
+    zip_filename = base_name + ".zip"
+    mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
+
+    # If zipfile module is not available, try spawning an external
+    # 'zip' command.
+    if zipfile is None:
+        if verbose:
+            zipoptions = "-r"
+        else:
+            zipoptions = "-rq"
+
+        try:
+            spawn(["zip", zipoptions, zip_filename, base_dir],
+                  dry_run=dry_run)
+        except DistutilsExecError:
+            # XXX really should distinguish between "couldn't find
+            # external 'zip' command" and "zip failed".
+            raise DistutilsExecError, \
+                  ("unable to create zip file '%s': "
+                   "could neither import the 'zipfile' module nor "
+                   "find a standalone zip utility") % zip_filename
+
+    else:
+        log.info("creating '%s' and adding '%s' to it",
+                 zip_filename, base_dir)
+
+        if not dry_run:
+            zip = zipfile.ZipFile(zip_filename, "w",
+                                  compression=zipfile.ZIP_DEFLATED)
+
+            for dirpath, dirnames, filenames in os.walk(base_dir):
+                for name in filenames:
+                    path = os.path.normpath(os.path.join(dirpath, name))
+                    if os.path.isfile(path):
+                        zip.write(path, path)
+                        log.info("adding '%s'" % path)
+            zip.close()
+
+    return zip_filename
+
+ARCHIVE_FORMATS = {
+    'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
+    'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
+    'ztar':  (make_tarball, [('compress', 'compress')], "compressed tar file"),
+    'tar':   (make_tarball, [('compress', None)], "uncompressed tar file"),
+    'zip':   (make_zipfile, [],"ZIP file")
+    }
+
+def check_archive_formats(formats):
+    """Returns the first format from the 'format' list that is unknown.
+
+    If all formats are known, returns None
+    """
+    for format in formats:
+        if format not in ARCHIVE_FORMATS:
+            return format
+    return None
+
+def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
+                 dry_run=0, owner=None, group=None):
+    """Create an archive file (eg. zip or tar).
+
+    'base_name' is the name of the file to create, minus any format-specific
+    extension; 'format' is the archive format: one of "zip", "tar", "ztar",
+    or "gztar".
+
+    'root_dir' is a directory that will be the root directory of the
+    archive; ie. we typically chdir into 'root_dir' before creating the
+    archive.  'base_dir' is the directory where we start archiving from;
+    ie. 'base_dir' will be the common prefix of all files and
+    directories in the archive.  'root_dir' and 'base_dir' both default
+    to the current directory.  Returns the name of the archive file.
+
+    'owner' and 'group' are used when creating a tar archive. By default,
+    uses the current owner and group.
+    """
+    save_cwd = os.getcwd()
+    if root_dir is not None:
+        log.debug("changing into '%s'", root_dir)
+        base_name = os.path.abspath(base_name)
+        if not dry_run:
+            os.chdir(root_dir)
+
+    if base_dir is None:
+        base_dir = os.curdir
+
+    kwargs = {'dry_run': dry_run}
+
+    try:
+        format_info = ARCHIVE_FORMATS[format]
+    except KeyError:
+        raise ValueError, "unknown archive format '%s'" % format
+
+    func = format_info[0]
+    for arg, val in format_info[1]:
+        kwargs[arg] = val
+
+    if format != 'zip':
+        kwargs['owner'] = owner
+        kwargs['group'] = group
+
+    try:
+        filename = func(base_name, base_dir, **kwargs)
+    finally:
+        if root_dir is not None:
+            log.debug("changing back to '%s'", save_cwd)
+            os.chdir(save_cwd)
+
+    return filename
diff --git a/src/main/resources/PythonLibs/distutils/bcppcompiler.py b/src/main/resources/PythonLibs/distutils/bcppcompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..f26e7ae4673bd4bb477a4a0e117d8e30c4f62126
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/bcppcompiler.py
@@ -0,0 +1,394 @@
+"""distutils.bcppcompiler
+
+Contains BorlandCCompiler, an implementation of the abstract CCompiler class
+for the Borland C++ compiler.
+"""
+
+# This implementation by Lyle Johnson, based on the original msvccompiler.py
+# module and using the directions originally published by Gordon Williams.
+
+# XXX looks like there's a LOT of overlap between these two classes:
+# someone should sit down and factor out the common code as
+# WindowsCCompiler!  --GPW
+
+__revision__ = "$Id$"
+
+import os
+
+from distutils.errors import (DistutilsExecError, CompileError, LibError,
+                              LinkError, UnknownFileError)
+from distutils.ccompiler import CCompiler, gen_preprocess_options
+from distutils.file_util import write_file
+from distutils.dep_util import newer
+from distutils import log
+
+class BCPPCompiler(CCompiler) :
+    """Concrete class that implements an interface to the Borland C/C++
+    compiler, as defined by the CCompiler abstract class.
+    """
+
+    compiler_type = 'bcpp'
+
+    # Just set this so CCompiler's constructor doesn't barf.  We currently
+    # don't use the 'set_executables()' bureaucracy provided by CCompiler,
+    # as it really isn't necessary for this sort of single-compiler class.
+    # Would be nice to have a consistent interface with UnixCCompiler,
+    # though, so it's worth thinking about.
+    executables = {}
+
+    # Private class data (need to distinguish C from C++ source for compiler)
+    _c_extensions = ['.c']
+    _cpp_extensions = ['.cc', '.cpp', '.cxx']
+
+    # Needed for the filename generation methods provided by the
+    # base class, CCompiler.
+    src_extensions = _c_extensions + _cpp_extensions
+    obj_extension = '.obj'
+    static_lib_extension = '.lib'
+    shared_lib_extension = '.dll'
+    static_lib_format = shared_lib_format = '%s%s'
+    exe_extension = '.exe'
+
+
+    def __init__ (self,
+                  verbose=0,
+                  dry_run=0,
+                  force=0):
+
+        CCompiler.__init__ (self, verbose, dry_run, force)
+
+        # These executables are assumed to all be in the path.
+        # Borland doesn't seem to use any special registry settings to
+        # indicate their installation locations.
+
+        self.cc = "bcc32.exe"
+        self.linker = "ilink32.exe"
+        self.lib = "tlib.exe"
+
+        self.preprocess_options = None
+        self.compile_options = ['/tWM', '/O2', '/q', '/g0']
+        self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0']
+
+        self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
+        self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
+        self.ldflags_static = []
+        self.ldflags_exe = ['/Gn', '/q', '/x']
+        self.ldflags_exe_debug = ['/Gn', '/q', '/x','/r']
+
+
+    # -- Worker methods ------------------------------------------------
+
+    def compile(self, sources,
+                output_dir=None, macros=None, include_dirs=None, debug=0,
+                extra_preargs=None, extra_postargs=None, depends=None):
+
+        macros, objects, extra_postargs, pp_opts, build = \
+                self._setup_compile(output_dir, macros, include_dirs, sources,
+                                    depends, extra_postargs)
+        compile_opts = extra_preargs or []
+        compile_opts.append ('-c')
+        if debug:
+            compile_opts.extend (self.compile_options_debug)
+        else:
+            compile_opts.extend (self.compile_options)
+
+        for obj in objects:
+            try:
+                src, ext = build[obj]
+            except KeyError:
+                continue
+            # XXX why do the normpath here?
+            src = os.path.normpath(src)
+            obj = os.path.normpath(obj)
+            # XXX _setup_compile() did a mkpath() too but before the normpath.
+            # Is it possible to skip the normpath?
+            self.mkpath(os.path.dirname(obj))
+
+            if ext == '.res':
+                # This is already a binary file -- skip it.
+                continue # the 'for' loop
+            if ext == '.rc':
+                # This needs to be compiled to a .res file -- do it now.
+                try:
+                    self.spawn (["brcc32", "-fo", obj, src])
+                except DistutilsExecError, msg:
+                    raise CompileError, msg
+                continue # the 'for' loop
+
+            # The next two are both for the real compiler.
+            if ext in self._c_extensions:
+                input_opt = ""
+            elif ext in self._cpp_extensions:
+                input_opt = "-P"
+            else:
+                # Unknown file type -- no extra options.  The compiler
+                # will probably fail, but let it just in case this is a
+                # file the compiler recognizes even if we don't.
+                input_opt = ""
+
+            output_opt = "-o" + obj
+
+            # Compiler command line syntax is: "bcc32 [options] file(s)".
+            # Note that the source file names must appear at the end of
+            # the command line.
+            try:
+                self.spawn ([self.cc] + compile_opts + pp_opts +
+                            [input_opt, output_opt] +
+                            extra_postargs + [src])
+            except DistutilsExecError, msg:
+                raise CompileError, msg
+
+        return objects
+
+    # compile ()
+
+
+    def create_static_lib (self,
+                           objects,
+                           output_libname,
+                           output_dir=None,
+                           debug=0,
+                           target_lang=None):
+
+        (objects, output_dir) = self._fix_object_args (objects, output_dir)
+        output_filename = \
+            self.library_filename (output_libname, output_dir=output_dir)
+
+        if self._need_link (objects, output_filename):
+            lib_args = [output_filename, '/u'] + objects
+            if debug:
+                pass                    # XXX what goes here?
+            try:
+                self.spawn ([self.lib] + lib_args)
+            except DistutilsExecError, msg:
+                raise LibError, msg
+        else:
+            log.debug("skipping %s (up-to-date)", output_filename)
+
+    # create_static_lib ()
+
+
+    def link (self,
+              target_desc,
+              objects,
+              output_filename,
+              output_dir=None,
+              libraries=None,
+              library_dirs=None,
+              runtime_library_dirs=None,
+              export_symbols=None,
+              debug=0,
+              extra_preargs=None,
+              extra_postargs=None,
+              build_temp=None,
+              target_lang=None):
+
+        # XXX this ignores 'build_temp'!  should follow the lead of
+        # msvccompiler.py
+
+        (objects, output_dir) = self._fix_object_args (objects, output_dir)
+        (libraries, library_dirs, runtime_library_dirs) = \
+            self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
+
+        if runtime_library_dirs:
+            log.warn("I don't know what to do with 'runtime_library_dirs': %s",
+                     str(runtime_library_dirs))
+
+        if output_dir is not None:
+            output_filename = os.path.join (output_dir, output_filename)
+
+        if self._need_link (objects, output_filename):
+
+            # Figure out linker args based on type of target.
+            if target_desc == CCompiler.EXECUTABLE:
+                startup_obj = 'c0w32'
+                if debug:
+                    ld_args = self.ldflags_exe_debug[:]
+                else:
+                    ld_args = self.ldflags_exe[:]
+            else:
+                startup_obj = 'c0d32'
+                if debug:
+                    ld_args = self.ldflags_shared_debug[:]
+                else:
+                    ld_args = self.ldflags_shared[:]
+
+
+            # Create a temporary exports file for use by the linker
+            if export_symbols is None:
+                def_file = ''
+            else:
+                head, tail = os.path.split (output_filename)
+                modname, ext = os.path.splitext (tail)
+                temp_dir = os.path.dirname(objects[0]) # preserve tree structure
+                def_file = os.path.join (temp_dir, '%s.def' % modname)
+                contents = ['EXPORTS']
+                for sym in (export_symbols or []):
+                    contents.append('  %s=_%s' % (sym, sym))
+                self.execute(write_file, (def_file, contents),
+                             "writing %s" % def_file)
+
+            # Borland C++ has problems with '/' in paths
+            objects2 = map(os.path.normpath, objects)
+            # split objects in .obj and .res files
+            # Borland C++ needs them at different positions in the command line
+            objects = [startup_obj]
+            resources = []
+            for file in objects2:
+                (base, ext) = os.path.splitext(os.path.normcase(file))
+                if ext == '.res':
+                    resources.append(file)
+                else:
+                    objects.append(file)
+
+
+            for l in library_dirs:
+                ld_args.append("/L%s" % os.path.normpath(l))
+            ld_args.append("/L.") # we sometimes use relative paths
+
+            # list of object files
+            ld_args.extend(objects)
+
+            # XXX the command-line syntax for Borland C++ is a bit wonky;
+            # certain filenames are jammed together in one big string, but
+            # comma-delimited.  This doesn't mesh too well with the
+            # Unix-centric attitude (with a DOS/Windows quoting hack) of
+            # 'spawn()', so constructing the argument list is a bit
+            # awkward.  Note that doing the obvious thing and jamming all
+            # the filenames and commas into one argument would be wrong,
+            # because 'spawn()' would quote any filenames with spaces in
+            # them.  Arghghh!.  Apparently it works fine as coded...
+
+            # name of dll/exe file
+            ld_args.extend([',',output_filename])
+            # no map file and start libraries
+            ld_args.append(',,')
+
+            for lib in libraries:
+                # see if we find it and if there is a bcpp specific lib
+                # (xxx_bcpp.lib)
+                libfile = self.find_library_file(library_dirs, lib, debug)
+                if libfile is None:
+                    ld_args.append(lib)
+                    # probably a BCPP internal library -- don't warn
+                else:
+                    # full name which prefers bcpp_xxx.lib over xxx.lib
+                    ld_args.append(libfile)
+
+            # some default libraries
+            ld_args.append ('import32')
+            ld_args.append ('cw32mt')
+
+            # def file for export symbols
+            ld_args.extend([',',def_file])
+            # add resource files
+            ld_args.append(',')
+            ld_args.extend(resources)
+
+
+            if extra_preargs:
+                ld_args[:0] = extra_preargs
+            if extra_postargs:
+                ld_args.extend(extra_postargs)
+
+            self.mkpath (os.path.dirname (output_filename))
+            try:
+                self.spawn ([self.linker] + ld_args)
+            except DistutilsExecError, msg:
+                raise LinkError, msg
+
+        else:
+            log.debug("skipping %s (up-to-date)", output_filename)
+
+    # link ()
+
+    # -- Miscellaneous methods -----------------------------------------
+
+
+    def find_library_file (self, dirs, lib, debug=0):
+        # List of effective library names to try, in order of preference:
+        # xxx_bcpp.lib is better than xxx.lib
+        # and xxx_d.lib is better than xxx.lib if debug is set
+        #
+        # The "_bcpp" suffix is to handle a Python installation for people
+        # with multiple compilers (primarily Distutils hackers, I suspect
+        # ;-).  The idea is they'd have one static library for each
+        # compiler they care about, since (almost?) every Windows compiler
+        # seems to have a different format for static libraries.
+        if debug:
+            dlib = (lib + "_d")
+            try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib)
+        else:
+            try_names = (lib + "_bcpp", lib)
+
+        for dir in dirs:
+            for name in try_names:
+                libfile = os.path.join(dir, self.library_filename(name))
+                if os.path.exists(libfile):
+                    return libfile
+        else:
+            # Oops, didn't find it in *any* of 'dirs'
+            return None
+
+    # overwrite the one from CCompiler to support rc and res-files
+    def object_filenames (self,
+                          source_filenames,
+                          strip_dir=0,
+                          output_dir=''):
+        if output_dir is None: output_dir = ''
+        obj_names = []
+        for src_name in source_filenames:
+            # use normcase to make sure '.rc' is really '.rc' and not '.RC'
+            (base, ext) = os.path.splitext (os.path.normcase(src_name))
+            if ext not in (self.src_extensions + ['.rc','.res']):
+                raise UnknownFileError, \
+                      "unknown file type '%s' (from '%s')" % \
+                      (ext, src_name)
+            if strip_dir:
+                base = os.path.basename (base)
+            if ext == '.res':
+                # these can go unchanged
+                obj_names.append (os.path.join (output_dir, base + ext))
+            elif ext == '.rc':
+                # these need to be compiled to .res-files
+                obj_names.append (os.path.join (output_dir, base + '.res'))
+            else:
+                obj_names.append (os.path.join (output_dir,
+                                            base + self.obj_extension))
+        return obj_names
+
+    # object_filenames ()
+
+    def preprocess (self,
+                    source,
+                    output_file=None,
+                    macros=None,
+                    include_dirs=None,
+                    extra_preargs=None,
+                    extra_postargs=None):
+
+        (_, macros, include_dirs) = \
+            self._fix_compile_args(None, macros, include_dirs)
+        pp_opts = gen_preprocess_options(macros, include_dirs)
+        pp_args = ['cpp32.exe'] + pp_opts
+        if output_file is not None:
+            pp_args.append('-o' + output_file)
+        if extra_preargs:
+            pp_args[:0] = extra_preargs
+        if extra_postargs:
+            pp_args.extend(extra_postargs)
+        pp_args.append(source)
+
+        # We need to preprocess: either we're being forced to, or the
+        # source file is newer than the target (or the target doesn't
+        # exist).
+        if self.force or output_file is None or newer(source, output_file):
+            if output_file:
+                self.mkpath(os.path.dirname(output_file))
+            try:
+                self.spawn(pp_args)
+            except DistutilsExecError, msg:
+                print msg
+                raise CompileError, msg
+
+    # preprocess()
diff --git a/src/main/resources/PythonLibs/distutils/ccompiler.py b/src/main/resources/PythonLibs/distutils/ccompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..fac13c7e8a5689f0bf965e0ffd73c7edeb67c2ac
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/ccompiler.py
@@ -0,0 +1,1148 @@
+"""distutils.ccompiler
+
+Contains CCompiler, an abstract base class that defines the interface
+for the Distutils compiler abstraction model."""
+
+__revision__ = "$Id: ccompiler.py 86238 2010-11-06 04:06:18Z eric.araujo $"
+
+import sys
+import os
+import re
+
+from distutils.errors import (CompileError, LinkError, UnknownFileError,
+                              DistutilsPlatformError, DistutilsModuleError)
+from distutils.spawn import spawn
+from distutils.file_util import move_file
+from distutils.dir_util import mkpath
+from distutils.dep_util import newer_group
+from distutils.util import split_quoted, execute
+from distutils import log
+
+_sysconfig = __import__('sysconfig')
+
+def customize_compiler(compiler):
+    """Do any platform-specific customization of a CCompiler instance.
+
+    Mainly needed on Unix, so we can plug in the information that
+    varies across Unices and is stored in Python's Makefile.
+    """
+    if compiler.compiler_type == "unix":
+        (cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
+            _sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
+                                       'CCSHARED', 'LDSHARED', 'SO', 'AR',
+                                       'ARFLAGS')
+
+        if 'CC' in os.environ:
+            cc = os.environ['CC']
+        if 'CXX' in os.environ:
+            cxx = os.environ['CXX']
+        if 'LDSHARED' in os.environ:
+            ldshared = os.environ['LDSHARED']
+        if 'CPP' in os.environ:
+            cpp = os.environ['CPP']
+        else:
+            cpp = cc + " -E"           # not always
+        if 'LDFLAGS' in os.environ:
+            ldshared = ldshared + ' ' + os.environ['LDFLAGS']
+        if 'CFLAGS' in os.environ:
+            cflags = opt + ' ' + os.environ['CFLAGS']
+            ldshared = ldshared + ' ' + os.environ['CFLAGS']
+        if 'CPPFLAGS' in os.environ:
+            cpp = cpp + ' ' + os.environ['CPPFLAGS']
+            cflags = cflags + ' ' + os.environ['CPPFLAGS']
+            ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
+        if 'AR' in os.environ:
+            ar = os.environ['AR']
+        if 'ARFLAGS' in os.environ:
+            archiver = ar + ' ' + os.environ['ARFLAGS']
+        else:
+            archiver = ar + ' ' + ar_flags
+
+        cc_cmd = cc + ' ' + cflags
+        compiler.set_executables(
+            preprocessor=cpp,
+            compiler=cc_cmd,
+            compiler_so=cc_cmd + ' ' + ccshared,
+            compiler_cxx=cxx,
+            linker_so=ldshared,
+            linker_exe=cc,
+            archiver=archiver)
+
+        compiler.shared_lib_extension = so_ext
+
+class CCompiler:
+    """Abstract base class to define the interface that must be implemented
+    by real compiler classes.  Also has some utility methods used by
+    several compiler classes.
+
+    The basic idea behind a compiler abstraction class is that each
+    instance can be used for all the compile/link steps in building a
+    single project.  Thus, attributes common to all of those compile and
+    link steps -- include directories, macros to define, libraries to link
+    against, etc. -- are attributes of the compiler instance.  To allow for
+    variability in how individual files are treated, most of those
+    attributes may be varied on a per-compilation or per-link basis.
+    """
+
+    # 'compiler_type' is a class attribute that identifies this class.  It
+    # keeps code that wants to know what kind of compiler it's dealing with
+    # from having to import all possible compiler classes just to do an
+    # 'isinstance'.  In concrete CCompiler subclasses, 'compiler_type'
+    # should really, really be one of the keys of the 'compiler_class'
+    # dictionary (see below -- used by the 'new_compiler()' factory
+    # function) -- authors of new compiler interface classes are
+    # responsible for updating 'compiler_class'!
+    compiler_type = None
+
+    # XXX things not handled by this compiler abstraction model:
+    #   * client can't provide additional options for a compiler,
+    #     e.g. warning, optimization, debugging flags.  Perhaps this
+    #     should be the domain of concrete compiler abstraction classes
+    #     (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base
+    #     class should have methods for the common ones.
+    #   * can't completely override the include or library searchg
+    #     path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2".
+    #     I'm not sure how widely supported this is even by Unix
+    #     compilers, much less on other platforms.  And I'm even less
+    #     sure how useful it is; maybe for cross-compiling, but
+    #     support for that is a ways off.  (And anyways, cross
+    #     compilers probably have a dedicated binary with the
+    #     right paths compiled in.  I hope.)
+    #   * can't do really freaky things with the library list/library
+    #     dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against
+    #     different versions of libfoo.a in different locations.  I
+    #     think this is useless without the ability to null out the
+    #     library search path anyways.
+
+
+    # Subclasses that rely on the standard filename generation methods
+    # implemented below should override these; see the comment near
+    # those methods ('object_filenames()' et. al.) for details:
+    src_extensions = None               # list of strings
+    obj_extension = None                # string
+    static_lib_extension = None
+    shared_lib_extension = None         # string
+    static_lib_format = None            # format string
+    shared_lib_format = None            # prob. same as static_lib_format
+    exe_extension = None                # string
+
+    # Default language settings. language_map is used to detect a source
+    # file or Extension target language, checking source filenames.
+    # language_order is used to detect the language precedence, when deciding
+    # what language to use when mixing source types. For example, if some
+    # extension has two files with ".c" extension, and one with ".cpp", it
+    # is still linked as c++.
+    language_map = {".c"   : "c",
+                    ".cc"  : "c++",
+                    ".cpp" : "c++",
+                    ".cxx" : "c++",
+                    ".m"   : "objc",
+                   }
+    language_order = ["c++", "objc", "c"]
+
+    def __init__ (self, verbose=0, dry_run=0, force=0):
+        self.dry_run = dry_run
+        self.force = force
+        self.verbose = verbose
+
+        # 'output_dir': a common output directory for object, library,
+        # shared object, and shared library files
+        self.output_dir = None
+
+        # 'macros': a list of macro definitions (or undefinitions).  A
+        # macro definition is a 2-tuple (name, value), where the value is
+        # either a string or None (no explicit value).  A macro
+        # undefinition is a 1-tuple (name,).
+        self.macros = []
+
+        # 'include_dirs': a list of directories to search for include files
+        self.include_dirs = []
+
+        # 'libraries': a list of libraries to include in any link
+        # (library names, not filenames: eg. "foo" not "libfoo.a")
+        self.libraries = []
+
+        # 'library_dirs': a list of directories to search for libraries
+        self.library_dirs = []
+
+        # 'runtime_library_dirs': a list of directories to search for
+        # shared libraries/objects at runtime
+        self.runtime_library_dirs = []
+
+        # 'objects': a list of object files (or similar, such as explicitly
+        # named library files) to include on any link
+        self.objects = []
+
+        for key in self.executables.keys():
+            self.set_executable(key, self.executables[key])
+
+    def set_executables(self, **args):
+        """Define the executables (and options for them) that will be run
+        to perform the various stages of compilation.  The exact set of
+        executables that may be specified here depends on the compiler
+        class (via the 'executables' class attribute), but most will have:
+          compiler      the C/C++ compiler
+          linker_so     linker used to create shared objects and libraries
+          linker_exe    linker used to create binary executables
+          archiver      static library creator
+
+        On platforms with a command-line (Unix, DOS/Windows), each of these
+        is a string that will be split into executable name and (optional)
+        list of arguments.  (Splitting the string is done similarly to how
+        Unix shells operate: words are delimited by spaces, but quotes and
+        backslashes can override this.  See
+        'distutils.util.split_quoted()'.)
+        """
+
+        # Note that some CCompiler implementation classes will define class
+        # attributes 'cpp', 'cc', etc. with hard-coded executable names;
+        # this is appropriate when a compiler class is for exactly one
+        # compiler/OS combination (eg. MSVCCompiler).  Other compiler
+        # classes (UnixCCompiler, in particular) are driven by information
+        # discovered at run-time, since there are many different ways to do
+        # basically the same things with Unix C compilers.
+
+        for key in args.keys():
+            if key not in self.executables:
+                raise ValueError, \
+                      "unknown executable '%s' for class %s" % \
+                      (key, self.__class__.__name__)
+            self.set_executable(key, args[key])
+
+    def set_executable(self, key, value):
+        if isinstance(value, str):
+            setattr(self, key, split_quoted(value))
+        else:
+            setattr(self, key, value)
+
+    def _find_macro(self, name):
+        i = 0
+        for defn in self.macros:
+            if defn[0] == name:
+                return i
+            i = i + 1
+        return None
+
+    def _check_macro_definitions(self, definitions):
+        """Ensures that every element of 'definitions' is a valid macro
+        definition, ie. either (name,value) 2-tuple or a (name,) tuple.  Do
+        nothing if all definitions are OK, raise TypeError otherwise.
+        """
+        for defn in definitions:
+            if not (isinstance(defn, tuple) and
+                    (len (defn) == 1 or
+                     (len (defn) == 2 and
+                      (isinstance(defn[1], str) or defn[1] is None))) and
+                    isinstance(defn[0], str)):
+                raise TypeError, \
+                      ("invalid macro definition '%s': " % defn) + \
+                      "must be tuple (string,), (string, string), or " + \
+                      "(string, None)"
+
+
+    # -- Bookkeeping methods -------------------------------------------
+
+    def define_macro(self, name, value=None):
+        """Define a preprocessor macro for all compilations driven by this
+        compiler object.  The optional parameter 'value' should be a
+        string; if it is not supplied, then the macro will be defined
+        without an explicit value and the exact outcome depends on the
+        compiler used (XXX true? does ANSI say anything about this?)
+        """
+        # Delete from the list of macro definitions/undefinitions if
+        # already there (so that this one will take precedence).
+        i = self._find_macro (name)
+        if i is not None:
+            del self.macros[i]
+
+        defn = (name, value)
+        self.macros.append (defn)
+
+    def undefine_macro(self, name):
+        """Undefine a preprocessor macro for all compilations driven by
+        this compiler object.  If the same macro is defined by
+        'define_macro()' and undefined by 'undefine_macro()' the last call
+        takes precedence (including multiple redefinitions or
+        undefinitions).  If the macro is redefined/undefined on a
+        per-compilation basis (ie. in the call to 'compile()'), then that
+        takes precedence.
+        """
+        # Delete from the list of macro definitions/undefinitions if
+        # already there (so that this one will take precedence).
+        i = self._find_macro (name)
+        if i is not None:
+            del self.macros[i]
+
+        undefn = (name,)
+        self.macros.append (undefn)
+
+    def add_include_dir(self, dir):
+        """Add 'dir' to the list of directories that will be searched for
+        header files.  The compiler is instructed to search directories in
+        the order in which they are supplied by successive calls to
+        'add_include_dir()'.
+        """
+        self.include_dirs.append (dir)
+
+    def set_include_dirs(self, dirs):
+        """Set the list of directories that will be searched to 'dirs' (a
+        list of strings).  Overrides any preceding calls to
+        'add_include_dir()'; subsequence calls to 'add_include_dir()' add
+        to the list passed to 'set_include_dirs()'.  This does not affect
+        any list of standard include directories that the compiler may
+        search by default.
+        """
+        self.include_dirs = dirs[:]
+
+    def add_library(self, libname):
+        """Add 'libname' to the list of libraries that will be included in
+        all links driven by this compiler object.  Note that 'libname'
+        should *not* be the name of a file containing a library, but the
+        name of the library itself: the actual filename will be inferred by
+        the linker, the compiler, or the compiler class (depending on the
+        platform).
+
+        The linker will be instructed to link against libraries in the
+        order they were supplied to 'add_library()' and/or
+        'set_libraries()'.  It is perfectly valid to duplicate library
+        names; the linker will be instructed to link against libraries as
+        many times as they are mentioned.
+        """
+        self.libraries.append (libname)
+
+    def set_libraries(self, libnames):
+        """Set the list of libraries to be included in all links driven by
+        this compiler object to 'libnames' (a list of strings).  This does
+        not affect any standard system libraries that the linker may
+        include by default.
+        """
+        self.libraries = libnames[:]
+
+
+    def add_library_dir(self, dir):
+        """Add 'dir' to the list of directories that will be searched for
+        libraries specified to 'add_library()' and 'set_libraries()'.  The
+        linker will be instructed to search for libraries in the order they
+        are supplied to 'add_library_dir()' and/or 'set_library_dirs()'.
+        """
+        self.library_dirs.append(dir)
+
+    def set_library_dirs(self, dirs):
+        """Set the list of library search directories to 'dirs' (a list of
+        strings).  This does not affect any standard library search path
+        that the linker may search by default.
+        """
+        self.library_dirs = dirs[:]
+
+    def add_runtime_library_dir(self, dir):
+        """Add 'dir' to the list of directories that will be searched for
+        shared libraries at runtime.
+        """
+        self.runtime_library_dirs.append(dir)
+
+    def set_runtime_library_dirs(self, dirs):
+        """Set the list of directories to search for shared libraries at
+        runtime to 'dirs' (a list of strings).  This does not affect any
+        standard search path that the runtime linker may search by
+        default.
+        """
+        self.runtime_library_dirs = dirs[:]
+
+    def add_link_object(self, object):
+        """Add 'object' to the list of object files (or analogues, such as
+        explicitly named library files or the output of "resource
+        compilers") to be included in every link driven by this compiler
+        object.
+        """
+        self.objects.append(object)
+
+    def set_link_objects(self, objects):
+        """Set the list of object files (or analogues) to be included in
+        every link to 'objects'.  This does not affect any standard object
+        files that the linker may include by default (such as system
+        libraries).
+        """
+        self.objects = objects[:]
+
+
+    # -- Private utility methods --------------------------------------
+    # (here for the convenience of subclasses)
+
+    # Helper method to prep compiler in subclass compile() methods
+
+    def _setup_compile(self, outdir, macros, incdirs, sources, depends,
+                       extra):
+        """Process arguments and decide which source files to compile."""
+        if outdir is None:
+            outdir = self.output_dir
+        elif not isinstance(outdir, str):
+            raise TypeError, "'output_dir' must be a string or None"
+
+        if macros is None:
+            macros = self.macros
+        elif isinstance(macros, list):
+            macros = macros + (self.macros or [])
+        else:
+            raise TypeError, "'macros' (if supplied) must be a list of tuples"
+
+        if incdirs is None:
+            incdirs = self.include_dirs
+        elif isinstance(incdirs, (list, tuple)):
+            incdirs = list(incdirs) + (self.include_dirs or [])
+        else:
+            raise TypeError, \
+                  "'include_dirs' (if supplied) must be a list of strings"
+
+        if extra is None:
+            extra = []
+
+        # Get the list of expected output (object) files
+        objects = self.object_filenames(sources,
+                                        strip_dir=0,
+                                        output_dir=outdir)
+        assert len(objects) == len(sources)
+
+        pp_opts = gen_preprocess_options(macros, incdirs)
+
+        build = {}
+        for i in range(len(sources)):
+            src = sources[i]
+            obj = objects[i]
+            ext = os.path.splitext(src)[1]
+            self.mkpath(os.path.dirname(obj))
+            build[obj] = (src, ext)
+
+        return macros, objects, extra, pp_opts, build
+
+    def _get_cc_args(self, pp_opts, debug, before):
+        # works for unixccompiler, emxccompiler, cygwinccompiler
+        cc_args = pp_opts + ['-c']
+        if debug:
+            cc_args[:0] = ['-g']
+        if before:
+            cc_args[:0] = before
+        return cc_args
+
+    def _fix_compile_args(self, output_dir, macros, include_dirs):
+        """Typecheck and fix-up some of the arguments to the 'compile()'
+        method, and return fixed-up values.  Specifically: if 'output_dir'
+        is None, replaces it with 'self.output_dir'; ensures that 'macros'
+        is a list, and augments it with 'self.macros'; ensures that
+        'include_dirs' is a list, and augments it with 'self.include_dirs'.
+        Guarantees that the returned values are of the correct type,
+        i.e. for 'output_dir' either string or None, and for 'macros' and
+        'include_dirs' either list or None.
+        """
+        if output_dir is None:
+            output_dir = self.output_dir
+        elif not isinstance(output_dir, str):
+            raise TypeError, "'output_dir' must be a string or None"
+
+        if macros is None:
+            macros = self.macros
+        elif isinstance(macros, list):
+            macros = macros + (self.macros or [])
+        else:
+            raise TypeError, "'macros' (if supplied) must be a list of tuples"
+
+        if include_dirs is None:
+            include_dirs = self.include_dirs
+        elif isinstance(include_dirs, (list, tuple)):
+            include_dirs = list (include_dirs) + (self.include_dirs or [])
+        else:
+            raise TypeError, \
+                  "'include_dirs' (if supplied) must be a list of strings"
+
+        return output_dir, macros, include_dirs
+
+    def _fix_object_args(self, objects, output_dir):
+        """Typecheck and fix up some arguments supplied to various methods.
+        Specifically: ensure that 'objects' is a list; if output_dir is
+        None, replace with self.output_dir.  Return fixed versions of
+        'objects' and 'output_dir'.
+        """
+        if not isinstance(objects, (list, tuple)):
+            raise TypeError, \
+                  "'objects' must be a list or tuple of strings"
+        objects = list (objects)
+
+        if output_dir is None:
+            output_dir = self.output_dir
+        elif not isinstance(output_dir, str):
+            raise TypeError, "'output_dir' must be a string or None"
+
+        return (objects, output_dir)
+
+    def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
+        """Typecheck and fix up some of the arguments supplied to the
+        'link_*' methods.  Specifically: ensure that all arguments are
+        lists, and augment them with their permanent versions
+        (eg. 'self.libraries' augments 'libraries').  Return a tuple with
+        fixed versions of all arguments.
+        """
+        if libraries is None:
+            libraries = self.libraries
+        elif isinstance(libraries, (list, tuple)):
+            libraries = list (libraries) + (self.libraries or [])
+        else:
+            raise TypeError, \
+                  "'libraries' (if supplied) must be a list of strings"
+
+        if library_dirs is None:
+            library_dirs = self.library_dirs
+        elif isinstance(library_dirs, (list, tuple)):
+            library_dirs = list (library_dirs) + (self.library_dirs or [])
+        else:
+            raise TypeError, \
+                  "'library_dirs' (if supplied) must be a list of strings"
+
+        if runtime_library_dirs is None:
+            runtime_library_dirs = self.runtime_library_dirs
+        elif isinstance(runtime_library_dirs, (list, tuple)):
+            runtime_library_dirs = (list (runtime_library_dirs) +
+                                    (self.runtime_library_dirs or []))
+        else:
+            raise TypeError, \
+                  "'runtime_library_dirs' (if supplied) " + \
+                  "must be a list of strings"
+
+        return (libraries, library_dirs, runtime_library_dirs)
+
+    def _need_link(self, objects, output_file):
+        """Return true if we need to relink the files listed in 'objects'
+        to recreate 'output_file'.
+        """
+        if self.force:
+            return 1
+        else:
+            if self.dry_run:
+                newer = newer_group (objects, output_file, missing='newer')
+            else:
+                newer = newer_group (objects, output_file)
+            return newer
+
+    def detect_language(self, sources):
+        """Detect the language of a given file, or list of files. Uses
+        language_map, and language_order to do the job.
+        """
+        if not isinstance(sources, list):
+            sources = [sources]
+        lang = None
+        index = len(self.language_order)
+        for source in sources:
+            base, ext = os.path.splitext(source)
+            extlang = self.language_map.get(ext)
+            try:
+                extindex = self.language_order.index(extlang)
+                if extindex < index:
+                    lang = extlang
+                    index = extindex
+            except ValueError:
+                pass
+        return lang
+
+    # -- Worker methods ------------------------------------------------
+    # (must be implemented by subclasses)
+
+    def preprocess(self, source, output_file=None, macros=None,
+                   include_dirs=None, extra_preargs=None, extra_postargs=None):
+        """Preprocess a single C/C++ source file, named in 'source'.
+        Output will be written to file named 'output_file', or stdout if
+        'output_file' not supplied.  'macros' is a list of macro
+        definitions as for 'compile()', which will augment the macros set
+        with 'define_macro()' and 'undefine_macro()'.  'include_dirs' is a
+        list of directory names that will be added to the default list.
+
+        Raises PreprocessError on failure.
+        """
+        pass
+
+    def compile(self, sources, output_dir=None, macros=None,
+                include_dirs=None, debug=0, extra_preargs=None,
+                extra_postargs=None, depends=None):
+        """Compile one or more source files.
+
+        'sources' must be a list of filenames, most likely C/C++
+        files, but in reality anything that can be handled by a
+        particular compiler and compiler class (eg. MSVCCompiler can
+        handle resource files in 'sources').  Return a list of object
+        filenames, one per source filename in 'sources'.  Depending on
+        the implementation, not all source files will necessarily be
+        compiled, but all corresponding object filenames will be
+        returned.
+
+        If 'output_dir' is given, object files will be put under it, while
+        retaining their original path component.  That is, "foo/bar.c"
+        normally compiles to "foo/bar.o" (for a Unix implementation); if
+        'output_dir' is "build", then it would compile to
+        "build/foo/bar.o".
+
+        'macros', if given, must be a list of macro definitions.  A macro
+        definition is either a (name, value) 2-tuple or a (name,) 1-tuple.
+        The former defines a macro; if the value is None, the macro is
+        defined without an explicit value.  The 1-tuple case undefines a
+        macro.  Later definitions/redefinitions/ undefinitions take
+        precedence.
+
+        'include_dirs', if given, must be a list of strings, the
+        directories to add to the default include file search path for this
+        compilation only.
+
+        'debug' is a boolean; if true, the compiler will be instructed to
+        output debug symbols in (or alongside) the object file(s).
+
+        'extra_preargs' and 'extra_postargs' are implementation- dependent.
+        On platforms that have the notion of a command-line (e.g. Unix,
+        DOS/Windows), they are most likely lists of strings: extra
+        command-line arguments to prepand/append to the compiler command
+        line.  On other platforms, consult the implementation class
+        documentation.  In any event, they are intended as an escape hatch
+        for those occasions when the abstract compiler framework doesn't
+        cut the mustard.
+
+        'depends', if given, is a list of filenames that all targets
+        depend on.  If a source file is older than any file in
+        depends, then the source file will be recompiled.  This
+        supports dependency tracking, but only at a coarse
+        granularity.
+
+        Raises CompileError on failure.
+        """
+        # A concrete compiler class can either override this method
+        # entirely or implement _compile().
+
+        macros, objects, extra_postargs, pp_opts, build = \
+                self._setup_compile(output_dir, macros, include_dirs, sources,
+                                    depends, extra_postargs)
+        cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
+
+        for obj in objects:
+            try:
+                src, ext = build[obj]
+            except KeyError:
+                continue
+            self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
+
+        # Return *all* object filenames, not just the ones we just built.
+        return objects
+
+    def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+        """Compile 'src' to product 'obj'."""
+
+        # A concrete compiler class that does not override compile()
+        # should implement _compile().
+        pass
+
+    def create_static_lib(self, objects, output_libname, output_dir=None,
+                          debug=0, target_lang=None):
+        """Link a bunch of stuff together to create a static library file.
+        The "bunch of stuff" consists of the list of object files supplied
+        as 'objects', the extra object files supplied to
+        'add_link_object()' and/or 'set_link_objects()', the libraries
+        supplied to 'add_library()' and/or 'set_libraries()', and the
+        libraries supplied as 'libraries' (if any).
+
+        'output_libname' should be a library name, not a filename; the
+        filename will be inferred from the library name.  'output_dir' is
+        the directory where the library file will be put.
+
+        'debug' is a boolean; if true, debugging information will be
+        included in the library (note that on most platforms, it is the
+        compile step where this matters: the 'debug' flag is included here
+        just for consistency).
+
+        'target_lang' is the target language for which the given objects
+        are being compiled. This allows specific linkage time treatment of
+        certain languages.
+
+        Raises LibError on failure.
+        """
+        pass
+
+    # values for target_desc parameter in link()
+    SHARED_OBJECT = "shared_object"
+    SHARED_LIBRARY = "shared_library"
+    EXECUTABLE = "executable"
+
+    def link(self, target_desc, objects, output_filename, output_dir=None,
+             libraries=None, library_dirs=None, runtime_library_dirs=None,
+             export_symbols=None, debug=0, extra_preargs=None,
+             extra_postargs=None, build_temp=None, target_lang=None):
+        """Link a bunch of stuff together to create an executable or
+        shared library file.
+
+        The "bunch of stuff" consists of the list of object files supplied
+        as 'objects'.  'output_filename' should be a filename.  If
+        'output_dir' is supplied, 'output_filename' is relative to it
+        (i.e. 'output_filename' can provide directory components if
+        needed).
+
+        'libraries' is a list of libraries to link against.  These are
+        library names, not filenames, since they're translated into
+        filenames in a platform-specific way (eg. "foo" becomes "libfoo.a"
+        on Unix and "foo.lib" on DOS/Windows).  However, they can include a
+        directory component, which means the linker will look in that
+        specific directory rather than searching all the normal locations.
+
+        'library_dirs', if supplied, should be a list of directories to
+        search for libraries that were specified as bare library names
+        (ie. no directory component).  These are on top of the system
+        default and those supplied to 'add_library_dir()' and/or
+        'set_library_dirs()'.  'runtime_library_dirs' is a list of
+        directories that will be embedded into the shared library and used
+        to search for other shared libraries that *it* depends on at
+        run-time.  (This may only be relevant on Unix.)
+
+        'export_symbols' is a list of symbols that the shared library will
+        export.  (This appears to be relevant only on Windows.)
+
+        'debug' is as for 'compile()' and 'create_static_lib()', with the
+        slight distinction that it actually matters on most platforms (as
+        opposed to 'create_static_lib()', which includes a 'debug' flag
+        mostly for form's sake).
+
+        'extra_preargs' and 'extra_postargs' are as for 'compile()' (except
+        of course that they supply command-line arguments for the
+        particular linker being used).
+
+        'target_lang' is the target language for which the given objects
+        are being compiled. This allows specific linkage time treatment of
+        certain languages.
+
+        Raises LinkError on failure.
+        """
+        raise NotImplementedError
+
+
+    # Old 'link_*()' methods, rewritten to use the new 'link()' method.
+
+    def link_shared_lib(self, objects, output_libname, output_dir=None,
+                        libraries=None, library_dirs=None,
+                        runtime_library_dirs=None, export_symbols=None,
+                        debug=0, extra_preargs=None, extra_postargs=None,
+                        build_temp=None, target_lang=None):
+        self.link(CCompiler.SHARED_LIBRARY, objects,
+                  self.library_filename(output_libname, lib_type='shared'),
+                  output_dir,
+                  libraries, library_dirs, runtime_library_dirs,
+                  export_symbols, debug,
+                  extra_preargs, extra_postargs, build_temp, target_lang)
+
+
+    def link_shared_object(self, objects, output_filename, output_dir=None,
+                           libraries=None, library_dirs=None,
+                           runtime_library_dirs=None, export_symbols=None,
+                           debug=0, extra_preargs=None, extra_postargs=None,
+                           build_temp=None, target_lang=None):
+        self.link(CCompiler.SHARED_OBJECT, objects,
+                  output_filename, output_dir,
+                  libraries, library_dirs, runtime_library_dirs,
+                  export_symbols, debug,
+                  extra_preargs, extra_postargs, build_temp, target_lang)
+
+    def link_executable(self, objects, output_progname, output_dir=None,
+                        libraries=None, library_dirs=None,
+                        runtime_library_dirs=None, debug=0, extra_preargs=None,
+                        extra_postargs=None, target_lang=None):
+        self.link(CCompiler.EXECUTABLE, objects,
+                  self.executable_filename(output_progname), output_dir,
+                  libraries, library_dirs, runtime_library_dirs, None,
+                  debug, extra_preargs, extra_postargs, None, target_lang)
+
+
+    # -- Miscellaneous methods -----------------------------------------
+    # These are all used by the 'gen_lib_options() function; there is
+    # no appropriate default implementation so subclasses should
+    # implement all of these.
+
+    def library_dir_option(self, dir):
+        """Return the compiler option to add 'dir' to the list of
+        directories searched for libraries.
+        """
+        raise NotImplementedError
+
+    def runtime_library_dir_option(self, dir):
+        """Return the compiler option to add 'dir' to the list of
+        directories searched for runtime libraries.
+        """
+        raise NotImplementedError
+
+    def library_option(self, lib):
+        """Return the compiler option to add 'dir' to the list of libraries
+        linked into the shared library or executable.
+        """
+        raise NotImplementedError
+
+    def has_function(self, funcname, includes=None, include_dirs=None,
+                     libraries=None, library_dirs=None):
+        """Return a boolean indicating whether funcname is supported on
+        the current platform.  The optional arguments can be used to
+        augment the compilation environment.
+        """
+
+        # this can't be included at module scope because it tries to
+        # import math which might not be available at that point - maybe
+        # the necessary logic should just be inlined?
+        import tempfile
+        if includes is None:
+            includes = []
+        if include_dirs is None:
+            include_dirs = []
+        if libraries is None:
+            libraries = []
+        if library_dirs is None:
+            library_dirs = []
+        fd, fname = tempfile.mkstemp(".c", funcname, text=True)
+        f = os.fdopen(fd, "w")
+        try:
+            for incl in includes:
+                f.write("""#include "%s"\n""" % incl)
+            f.write("""\
+main (int argc, char **argv) {
+    %s();
+}
+""" % funcname)
+        finally:
+            f.close()
+        try:
+            objects = self.compile([fname], include_dirs=include_dirs)
+        except CompileError:
+            return False
+
+        try:
+            self.link_executable(objects, "a.out",
+                                 libraries=libraries,
+                                 library_dirs=library_dirs)
+        except (LinkError, TypeError):
+            return False
+        return True
+
+    def find_library_file (self, dirs, lib, debug=0):
+        """Search the specified list of directories for a static or shared
+        library file 'lib' and return the full path to that file.  If
+        'debug' true, look for a debugging version (if that makes sense on
+        the current platform).  Return None if 'lib' wasn't found in any of
+        the specified directories.
+        """
+        raise NotImplementedError
+
+    # -- Filename generation methods -----------------------------------
+
+    # The default implementation of the filename generating methods are
+    # prejudiced towards the Unix/DOS/Windows view of the world:
+    #   * object files are named by replacing the source file extension
+    #     (eg. .c/.cpp -> .o/.obj)
+    #   * library files (shared or static) are named by plugging the
+    #     library name and extension into a format string, eg.
+    #     "lib%s.%s" % (lib_name, ".a") for Unix static libraries
+    #   * executables are named by appending an extension (possibly
+    #     empty) to the program name: eg. progname + ".exe" for
+    #     Windows
+    #
+    # To reduce redundant code, these methods expect to find
+    # several attributes in the current object (presumably defined
+    # as class attributes):
+    #   * src_extensions -
+    #     list of C/C++ source file extensions, eg. ['.c', '.cpp']
+    #   * obj_extension -
+    #     object file extension, eg. '.o' or '.obj'
+    #   * static_lib_extension -
+    #     extension for static library files, eg. '.a' or '.lib'
+    #   * shared_lib_extension -
+    #     extension for shared library/object files, eg. '.so', '.dll'
+    #   * static_lib_format -
+    #     format string for generating static library filenames,
+    #     eg. 'lib%s.%s' or '%s.%s'
+    #   * shared_lib_format
+    #     format string for generating shared library filenames
+    #     (probably same as static_lib_format, since the extension
+    #     is one of the intended parameters to the format string)
+    #   * exe_extension -
+    #     extension for executable files, eg. '' or '.exe'
+
+    def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
+        if output_dir is None:
+            output_dir = ''
+        obj_names = []
+        for src_name in source_filenames:
+            base, ext = os.path.splitext(src_name)
+            base = os.path.splitdrive(base)[1] # Chop off the drive
+            base = base[os.path.isabs(base):]  # If abs, chop off leading /
+            if ext not in self.src_extensions:
+                raise UnknownFileError, \
+                      "unknown file type '%s' (from '%s')" % (ext, src_name)
+            if strip_dir:
+                base = os.path.basename(base)
+            obj_names.append(os.path.join(output_dir,
+                                          base + self.obj_extension))
+        return obj_names
+
+    def shared_object_filename(self, basename, strip_dir=0, output_dir=''):
+        assert output_dir is not None
+        if strip_dir:
+            basename = os.path.basename (basename)
+        return os.path.join(output_dir, basename + self.shared_lib_extension)
+
+    def executable_filename(self, basename, strip_dir=0, output_dir=''):
+        assert output_dir is not None
+        if strip_dir:
+            basename = os.path.basename (basename)
+        return os.path.join(output_dir, basename + (self.exe_extension or ''))
+
+    def library_filename(self, libname, lib_type='static',     # or 'shared'
+                         strip_dir=0, output_dir=''):
+        assert output_dir is not None
+        if lib_type not in ("static", "shared", "dylib"):
+            raise ValueError, "'lib_type' must be \"static\", \"shared\" or \"dylib\""
+        fmt = getattr(self, lib_type + "_lib_format")
+        ext = getattr(self, lib_type + "_lib_extension")
+
+        dir, base = os.path.split (libname)
+        filename = fmt % (base, ext)
+        if strip_dir:
+            dir = ''
+
+        return os.path.join(output_dir, dir, filename)
+
+
+    # -- Utility methods -----------------------------------------------
+
+    def announce(self, msg, level=1):
+        log.debug(msg)
+
+    def debug_print(self, msg):
+        from distutils.debug import DEBUG
+        if DEBUG:
+            print msg
+
+    def warn(self, msg):
+        sys.stderr.write("warning: %s\n" % msg)
+
+    def execute(self, func, args, msg=None, level=1):
+        execute(func, args, msg, self.dry_run)
+
+    def spawn(self, cmd):
+        spawn(cmd, dry_run=self.dry_run)
+
+    def move_file(self, src, dst):
+        return move_file(src, dst, dry_run=self.dry_run)
+
+    def mkpath(self, name, mode=0777):
+        mkpath(name, mode, dry_run=self.dry_run)
+
+
+# class CCompiler
+
+
+# Map a sys.platform/os.name ('posix', 'nt') to the default compiler
+# type for that platform. Keys are interpreted as re match
+# patterns. Order is important; platform mappings are preferred over
+# OS names.
+_default_compilers = (
+
+    # Platform string mappings
+
+    # on a cygwin built python we can use gcc like an ordinary UNIXish
+    # compiler
+    ('cygwin.*', 'unix'),
+    ('os2emx', 'emx'),
+    ('java.*', 'jython'),
+
+    # OS name mappings
+    ('posix', 'unix'),
+    ('nt', 'msvc'),
+
+    )
+
+def get_default_compiler(osname=None, platform=None):
+    """ Determine the default compiler to use for the given platform.
+
+        osname should be one of the standard Python OS names (i.e. the
+        ones returned by os.name) and platform the common value
+        returned by sys.platform for the platform in question.
+
+        The default values are os.name and sys.platform in case the
+        parameters are not given.
+
+    """
+    if osname is None:
+        osname = os.name
+    if platform is None:
+        platform = sys.platform
+    for pattern, compiler in _default_compilers:
+        if re.match(pattern, platform) is not None or \
+           re.match(pattern, osname) is not None:
+            return compiler
+    # Default to Unix compiler
+    return 'unix'
+
+# Map compiler types to (module_name, class_name) pairs -- ie. where to
+# find the code that implements an interface to this compiler.  (The module
+# is assumed to be in the 'distutils' package.)
+compiler_class = { 'unix':    ('unixccompiler', 'UnixCCompiler',
+                               "standard UNIX-style compiler"),
+                   'msvc':    ('msvccompiler', 'MSVCCompiler',
+                               "Microsoft Visual C++"),
+                   'cygwin':  ('cygwinccompiler', 'CygwinCCompiler',
+                               "Cygwin port of GNU C Compiler for Win32"),
+                   'mingw32': ('cygwinccompiler', 'Mingw32CCompiler',
+                               "Mingw32 port of GNU C Compiler for Win32"),
+                   'bcpp':    ('bcppcompiler', 'BCPPCompiler',
+                               "Borland C++ Compiler"),
+                   'emx':     ('emxccompiler', 'EMXCCompiler',
+                               "EMX port of GNU C Compiler for OS/2"),
+                   'jython':  ('jythoncompiler', 'JythonCompiler',
+                               "Compiling is not supported on Jython"),
+                 }
+
+def show_compilers():
+    """Print list of available compilers (used by the "--help-compiler"
+    options to "build", "build_ext", "build_clib").
+    """
+    # XXX this "knows" that the compiler option it's describing is
+    # "--compiler", which just happens to be the case for the three
+    # commands that use it.
+    from distutils.fancy_getopt import FancyGetopt
+    compilers = []
+    for compiler in compiler_class.keys():
+        compilers.append(("compiler="+compiler, None,
+                          compiler_class[compiler][2]))
+    compilers.sort()
+    pretty_printer = FancyGetopt(compilers)
+    pretty_printer.print_help("List of available compilers:")
+
+
+def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
+    """Generate an instance of some CCompiler subclass for the supplied
+    platform/compiler combination.  'plat' defaults to 'os.name'
+    (eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler
+    for that platform.  Currently only 'posix' and 'nt' are supported, and
+    the default compilers are "traditional Unix interface" (UnixCCompiler
+    class) and Visual C++ (MSVCCompiler class).  Note that it's perfectly
+    possible to ask for a Unix compiler object under Windows, and a
+    Microsoft compiler object under Unix -- if you supply a value for
+    'compiler', 'plat' is ignored.
+    """
+    if plat is None:
+        plat = os.name
+
+    try:
+        if compiler is None:
+            compiler = get_default_compiler(plat)
+
+        (module_name, class_name, long_description) = compiler_class[compiler]
+    except KeyError:
+        msg = "don't know how to compile C/C++ code on platform '%s'" % plat
+        if compiler is not None:
+            msg = msg + " with '%s' compiler" % compiler
+        raise DistutilsPlatformError, msg
+
+    try:
+        module_name = "distutils." + module_name
+        __import__ (module_name)
+        module = sys.modules[module_name]
+        klass = vars(module)[class_name]
+    except ImportError:
+        raise DistutilsModuleError, \
+              "can't compile C/C++ code: unable to load module '%s'" % \
+              module_name
+    except KeyError:
+        raise DistutilsModuleError, \
+              ("can't compile C/C++ code: unable to find class '%s' " +
+               "in module '%s'") % (class_name, module_name)
+
+    # XXX The None is necessary to preserve backwards compatibility
+    # with classes that expect verbose to be the first positional
+    # argument.
+    return klass(None, dry_run, force)
+
+
+def gen_preprocess_options(macros, include_dirs):
+    """Generate C pre-processor options (-D, -U, -I) as used by at least
+    two types of compilers: the typical Unix compiler and Visual C++.
+    'macros' is the usual thing, a list of 1- or 2-tuples, where (name,)
+    means undefine (-U) macro 'name', and (name,value) means define (-D)
+    macro 'name' to 'value'.  'include_dirs' is just a list of directory
+    names to be added to the header file search path (-I).  Returns a list
+    of command-line options suitable for either Unix compilers or Visual
+    C++.
+    """
+    # XXX it would be nice (mainly aesthetic, and so we don't generate
+    # stupid-looking command lines) to go over 'macros' and eliminate
+    # redundant definitions/undefinitions (ie. ensure that only the
+    # latest mention of a particular macro winds up on the command
+    # line).  I don't think it's essential, though, since most (all?)
+    # Unix C compilers only pay attention to the latest -D or -U
+    # mention of a macro on their command line.  Similar situation for
+    # 'include_dirs'.  I'm punting on both for now.  Anyways, weeding out
+    # redundancies like this should probably be the province of
+    # CCompiler, since the data structures used are inherited from it
+    # and therefore common to all CCompiler classes.
+
+    pp_opts = []
+    for macro in macros:
+
+        if not (isinstance(macro, tuple) and
+                1 <= len (macro) <= 2):
+            raise TypeError, \
+                  ("bad macro definition '%s': " +
+                   "each element of 'macros' list must be a 1- or 2-tuple") % \
+                  macro
+
+        if len (macro) == 1:        # undefine this macro
+            pp_opts.append ("-U%s" % macro[0])
+        elif len (macro) == 2:
+            if macro[1] is None:    # define with no explicit value
+                pp_opts.append ("-D%s" % macro[0])
+            else:
+                # XXX *don't* need to be clever about quoting the
+                # macro value here, because we're going to avoid the
+                # shell at all costs when we spawn the command!
+                pp_opts.append ("-D%s=%s" % macro)
+
+    for dir in include_dirs:
+        pp_opts.append ("-I%s" % dir)
+
+    return pp_opts
+
+
+def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
+    """Generate linker options for searching library directories and
+    linking with specific libraries.
+
+    'libraries' and 'library_dirs' are, respectively, lists of library names
+    (not filenames!) and search directories.  Returns a list of command-line
+    options suitable for use with some compiler (depending on the two format
+    strings passed in).
+    """
+    lib_opts = []
+
+    for dir in library_dirs:
+        lib_opts.append(compiler.library_dir_option(dir))
+
+    for dir in runtime_library_dirs:
+        opt = compiler.runtime_library_dir_option(dir)
+        if isinstance(opt, list):
+            lib_opts.extend(opt)
+        else:
+            lib_opts.append(opt)
+
+    # XXX it's important that we *not* remove redundant library mentions!
+    # sometimes you really do have to say "-lfoo -lbar -lfoo" in order to
+    # resolve all symbols.  I just hope we never have to say "-lfoo obj.o
+    # -lbar" to get things to work -- that's certainly a possibility, but a
+    # pretty nasty way to arrange your C code.
+
+    for lib in libraries:
+        lib_dir, lib_name = os.path.split(lib)
+        if lib_dir != '':
+            lib_file = compiler.find_library_file([lib_dir], lib_name)
+            if lib_file is not None:
+                lib_opts.append(lib_file)
+            else:
+                compiler.warn("no library file corresponding to "
+                              "'%s' found (skipping)" % lib)
+        else:
+            lib_opts.append(compiler.library_option(lib))
+
+    return lib_opts
diff --git a/src/main/resources/PythonLibs/distutils/cmd.py b/src/main/resources/PythonLibs/distutils/cmd.py
new file mode 100644
index 0000000000000000000000000000000000000000..9ad5657e40a59c081f70052f3fe43814f45cdd98
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/cmd.py
@@ -0,0 +1,457 @@
+"""distutils.cmd
+
+Provides the Command class, the base class for the command classes
+in the distutils.command package.
+"""
+
+__revision__ = "$Id$"
+
+import sys, os, re
+from distutils.errors import DistutilsOptionError
+from distutils import util, dir_util, file_util, archive_util, dep_util
+from distutils import log
+
+class Command:
+    """Abstract base class for defining command classes, the "worker bees"
+    of the Distutils.  A useful analogy for command classes is to think of
+    them as subroutines with local variables called "options".  The options
+    are "declared" in 'initialize_options()' and "defined" (given their
+    final values, aka "finalized") in 'finalize_options()', both of which
+    must be defined by every command class.  The distinction between the
+    two is necessary because option values might come from the outside
+    world (command line, config file, ...), and any options dependent on
+    other options must be computed *after* these outside influences have
+    been processed -- hence 'finalize_options()'.  The "body" of the
+    subroutine, where it does all its work based on the values of its
+    options, is the 'run()' method, which must also be implemented by every
+    command class.
+    """
+
+    # 'sub_commands' formalizes the notion of a "family" of commands,
+    # eg. "install" as the parent with sub-commands "install_lib",
+    # "install_headers", etc.  The parent of a family of commands
+    # defines 'sub_commands' as a class attribute; it's a list of
+    #    (command_name : string, predicate : unbound_method | string | None)
+    # tuples, where 'predicate' is a method of the parent command that
+    # determines whether the corresponding command is applicable in the
+    # current situation.  (Eg. we "install_headers" is only applicable if
+    # we have any C header files to install.)  If 'predicate' is None,
+    # that command is always applicable.
+    #
+    # 'sub_commands' is usually defined at the *end* of a class, because
+    # predicates can be unbound methods, so they must already have been
+    # defined.  The canonical example is the "install" command.
+    sub_commands = []
+
+
+    # -- Creation/initialization methods -------------------------------
+
+    def __init__(self, dist):
+        """Create and initialize a new Command object.  Most importantly,
+        invokes the 'initialize_options()' method, which is the real
+        initializer and depends on the actual command being
+        instantiated.
+        """
+        # late import because of mutual dependence between these classes
+        from distutils.dist import Distribution
+
+        if not isinstance(dist, Distribution):
+            raise TypeError, "dist must be a Distribution instance"
+        if self.__class__ is Command:
+            raise RuntimeError, "Command is an abstract class"
+
+        self.distribution = dist
+        self.initialize_options()
+
+        # Per-command versions of the global flags, so that the user can
+        # customize Distutils' behaviour command-by-command and let some
+        # commands fall back on the Distribution's behaviour.  None means
+        # "not defined, check self.distribution's copy", while 0 or 1 mean
+        # false and true (duh).  Note that this means figuring out the real
+        # value of each flag is a touch complicated -- hence "self._dry_run"
+        # will be handled by __getattr__, below.
+        # XXX This needs to be fixed.
+        self._dry_run = None
+
+        # verbose is largely ignored, but needs to be set for
+        # backwards compatibility (I think)?
+        self.verbose = dist.verbose
+
+        # Some commands define a 'self.force' option to ignore file
+        # timestamps, but methods defined *here* assume that
+        # 'self.force' exists for all commands.  So define it here
+        # just to be safe.
+        self.force = None
+
+        # The 'help' flag is just used for command-line parsing, so
+        # none of that complicated bureaucracy is needed.
+        self.help = 0
+
+        # 'finalized' records whether or not 'finalize_options()' has been
+        # called.  'finalize_options()' itself should not pay attention to
+        # this flag: it is the business of 'ensure_finalized()', which
+        # always calls 'finalize_options()', to respect/update it.
+        self.finalized = 0
+
+    # XXX A more explicit way to customize dry_run would be better.
+    def __getattr__(self, attr):
+        if attr == 'dry_run':
+            myval = getattr(self, "_" + attr)
+            if myval is None:
+                return getattr(self.distribution, attr)
+            else:
+                return myval
+        else:
+            raise AttributeError, attr
+
+    def ensure_finalized(self):
+        if not self.finalized:
+            self.finalize_options()
+        self.finalized = 1
+
+    # Subclasses must define:
+    #   initialize_options()
+    #     provide default values for all options; may be customized by
+    #     setup script, by options from config file(s), or by command-line
+    #     options
+    #   finalize_options()
+    #     decide on the final values for all options; this is called
+    #     after all possible intervention from the outside world
+    #     (command-line, option file, etc.) has been processed
+    #   run()
+    #     run the command: do whatever it is we're here to do,
+    #     controlled by the command's various option values
+
+    def initialize_options(self):
+        """Set default values for all the options that this command
+        supports.  Note that these defaults may be overridden by other
+        commands, by the setup script, by config files, or by the
+        command-line.  Thus, this is not the place to code dependencies
+        between options; generally, 'initialize_options()' implementations
+        are just a bunch of "self.foo = None" assignments.
+
+        This method must be implemented by all command classes.
+        """
+        raise RuntimeError, \
+              "abstract method -- subclass %s must override" % self.__class__
+
+    def finalize_options(self):
+        """Set final values for all the options that this command supports.
+        This is always called as late as possible, ie.  after any option
+        assignments from the command-line or from other commands have been
+        done.  Thus, this is the place to code option dependencies: if
+        'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
+        long as 'foo' still has the same value it was assigned in
+        'initialize_options()'.
+
+        This method must be implemented by all command classes.
+        """
+        raise RuntimeError, \
+              "abstract method -- subclass %s must override" % self.__class__
+
+
+    def dump_options(self, header=None, indent=""):
+        from distutils.fancy_getopt import longopt_xlate
+        if header is None:
+            header = "command options for '%s':" % self.get_command_name()
+        self.announce(indent + header, level=log.INFO)
+        indent = indent + "  "
+        for (option, _, _) in self.user_options:
+            option = option.translate(longopt_xlate)
+            if option[-1] == "=":
+                option = option[:-1]
+            value = getattr(self, option)
+            self.announce(indent + "%s = %s" % (option, value),
+                          level=log.INFO)
+
+    def run(self):
+        """A command's raison d'etre: carry out the action it exists to
+        perform, controlled by the options initialized in
+        'initialize_options()', customized by other commands, the setup
+        script, the command-line, and config files, and finalized in
+        'finalize_options()'.  All terminal output and filesystem
+        interaction should be done by 'run()'.
+
+        This method must be implemented by all command classes.
+        """
+        raise RuntimeError, \
+              "abstract method -- subclass %s must override" % self.__class__
+
+    def announce(self, msg, level=1):
+        """If the current verbosity level is of greater than or equal to
+        'level' print 'msg' to stdout.
+        """
+        log.log(level, msg)
+
+    def debug_print(self, msg):
+        """Print 'msg' to stdout if the global DEBUG (taken from the
+        DISTUTILS_DEBUG environment variable) flag is true.
+        """
+        from distutils.debug import DEBUG
+        if DEBUG:
+            print msg
+            sys.stdout.flush()
+
+
+    # -- Option validation methods -------------------------------------
+    # (these are very handy in writing the 'finalize_options()' method)
+    #
+    # NB. the general philosophy here is to ensure that a particular option
+    # value meets certain type and value constraints.  If not, we try to
+    # force it into conformance (eg. if we expect a list but have a string,
+    # split the string on comma and/or whitespace).  If we can't force the
+    # option into conformance, raise DistutilsOptionError.  Thus, command
+    # classes need do nothing more than (eg.)
+    #   self.ensure_string_list('foo')
+    # and they can be guaranteed that thereafter, self.foo will be
+    # a list of strings.
+
+    def _ensure_stringlike(self, option, what, default=None):
+        val = getattr(self, option)
+        if val is None:
+            setattr(self, option, default)
+            return default
+        elif not isinstance(val, str):
+            raise DistutilsOptionError, \
+                  "'%s' must be a %s (got `%s`)" % (option, what, val)
+        return val
+
+    def ensure_string(self, option, default=None):
+        """Ensure that 'option' is a string; if not defined, set it to
+        'default'.
+        """
+        self._ensure_stringlike(option, "string", default)
+
+    def ensure_string_list(self, option):
+        """Ensure that 'option' is a list of strings.  If 'option' is
+        currently a string, we split it either on /,\s*/ or /\s+/, so
+        "foo bar baz", "foo,bar,baz", and "foo,   bar baz" all become
+        ["foo", "bar", "baz"].
+        """
+        val = getattr(self, option)
+        if val is None:
+            return
+        elif isinstance(val, str):
+            setattr(self, option, re.split(r',\s*|\s+', val))
+        else:
+            if isinstance(val, list):
+                # checks if all elements are str
+                ok = 1
+                for element in val:
+                    if not isinstance(element, str):
+                        ok = 0
+                        break
+            else:
+                ok = 0
+
+            if not ok:
+                raise DistutilsOptionError, \
+                    "'%s' must be a list of strings (got %r)" % \
+                        (option, val)
+
+
+    def _ensure_tested_string(self, option, tester,
+                              what, error_fmt, default=None):
+        val = self._ensure_stringlike(option, what, default)
+        if val is not None and not tester(val):
+            raise DistutilsOptionError, \
+                  ("error in '%s' option: " + error_fmt) % (option, val)
+
+    def ensure_filename(self, option):
+        """Ensure that 'option' is the name of an existing file."""
+        self._ensure_tested_string(option, os.path.isfile,
+                                   "filename",
+                                   "'%s' does not exist or is not a file")
+
+    def ensure_dirname(self, option):
+        self._ensure_tested_string(option, os.path.isdir,
+                                   "directory name",
+                                   "'%s' does not exist or is not a directory")
+
+
+    # -- Convenience methods for commands ------------------------------
+
+    def get_command_name(self):
+        if hasattr(self, 'command_name'):
+            return self.command_name
+        else:
+            return self.__class__.__name__
+
+    def set_undefined_options(self, src_cmd, *option_pairs):
+        """Set the values of any "undefined" options from corresponding
+        option values in some other command object.  "Undefined" here means
+        "is None", which is the convention used to indicate that an option
+        has not been changed between 'initialize_options()' and
+        'finalize_options()'.  Usually called from 'finalize_options()' for
+        options that depend on some other command rather than another
+        option of the same command.  'src_cmd' is the other command from
+        which option values will be taken (a command object will be created
+        for it if necessary); the remaining arguments are
+        '(src_option,dst_option)' tuples which mean "take the value of
+        'src_option' in the 'src_cmd' command object, and copy it to
+        'dst_option' in the current command object".
+        """
+
+        # Option_pairs: list of (src_option, dst_option) tuples
+
+        src_cmd_obj = self.distribution.get_command_obj(src_cmd)
+        src_cmd_obj.ensure_finalized()
+        for (src_option, dst_option) in option_pairs:
+            if getattr(self, dst_option) is None:
+                setattr(self, dst_option,
+                        getattr(src_cmd_obj, src_option))
+
+
+    def get_finalized_command(self, command, create=1):
+        """Wrapper around Distribution's 'get_command_obj()' method: find
+        (create if necessary and 'create' is true) the command object for
+        'command', call its 'ensure_finalized()' method, and return the
+        finalized command object.
+        """
+        cmd_obj = self.distribution.get_command_obj(command, create)
+        cmd_obj.ensure_finalized()
+        return cmd_obj
+
+    # XXX rename to 'get_reinitialized_command()'? (should do the
+    # same in dist.py, if so)
+    def reinitialize_command(self, command, reinit_subcommands=0):
+        return self.distribution.reinitialize_command(
+            command, reinit_subcommands)
+
+    def run_command(self, command):
+        """Run some other command: uses the 'run_command()' method of
+        Distribution, which creates and finalizes the command object if
+        necessary and then invokes its 'run()' method.
+        """
+        self.distribution.run_command(command)
+
+    def get_sub_commands(self):
+        """Determine the sub-commands that are relevant in the current
+        distribution (ie., that need to be run).  This is based on the
+        'sub_commands' class attribute: each tuple in that list may include
+        a method that we call to determine if the subcommand needs to be
+        run for the current distribution.  Return a list of command names.
+        """
+        commands = []
+        for (cmd_name, method) in self.sub_commands:
+            if method is None or method(self):
+                commands.append(cmd_name)
+        return commands
+
+
+    # -- External world manipulation -----------------------------------
+
+    def warn(self, msg):
+        log.warn("warning: %s: %s\n" %
+                (self.get_command_name(), msg))
+
+    def execute(self, func, args, msg=None, level=1):
+        util.execute(func, args, msg, dry_run=self.dry_run)
+
+    def mkpath(self, name, mode=0777):
+        dir_util.mkpath(name, mode, dry_run=self.dry_run)
+
+    def copy_file(self, infile, outfile,
+                   preserve_mode=1, preserve_times=1, link=None, level=1):
+        """Copy a file respecting verbose, dry-run and force flags.  (The
+        former two default to whatever is in the Distribution object, and
+        the latter defaults to false for commands that don't define it.)"""
+
+        return file_util.copy_file(
+            infile, outfile,
+            preserve_mode, preserve_times,
+            not self.force,
+            link,
+            dry_run=self.dry_run)
+
+    def copy_tree(self, infile, outfile,
+                   preserve_mode=1, preserve_times=1, preserve_symlinks=0,
+                   level=1):
+        """Copy an entire directory tree respecting verbose, dry-run,
+        and force flags.
+        """
+        return dir_util.copy_tree(
+            infile, outfile,
+            preserve_mode,preserve_times,preserve_symlinks,
+            not self.force,
+            dry_run=self.dry_run)
+
+    def move_file (self, src, dst, level=1):
+        """Move a file respecting dry-run flag."""
+        return file_util.move_file(src, dst, dry_run = self.dry_run)
+
+    def spawn (self, cmd, search_path=1, level=1):
+        """Spawn an external command respecting dry-run flag."""
+        from distutils.spawn import spawn
+        spawn(cmd, search_path, dry_run= self.dry_run)
+
+    def make_archive(self, base_name, format, root_dir=None, base_dir=None,
+                     owner=None, group=None):
+        return archive_util.make_archive(base_name, format, root_dir,
+                                         base_dir, dry_run=self.dry_run,
+                                         owner=owner, group=group)
+
+    def make_file(self, infiles, outfile, func, args,
+                  exec_msg=None, skip_msg=None, level=1):
+        """Special case of 'execute()' for operations that process one or
+        more input files and generate one output file.  Works just like
+        'execute()', except the operation is skipped and a different
+        message printed if 'outfile' already exists and is newer than all
+        files listed in 'infiles'.  If the command defined 'self.force',
+        and it is true, then the command is unconditionally run -- does no
+        timestamp checks.
+        """
+        if skip_msg is None:
+            skip_msg = "skipping %s (inputs unchanged)" % outfile
+
+        # Allow 'infiles' to be a single string
+        if isinstance(infiles, str):
+            infiles = (infiles,)
+        elif not isinstance(infiles, (list, tuple)):
+            raise TypeError, \
+                  "'infiles' must be a string, or a list or tuple of strings"
+
+        if exec_msg is None:
+            exec_msg = "generating %s from %s" % \
+                       (outfile, ', '.join(infiles))
+
+        # If 'outfile' must be regenerated (either because it doesn't
+        # exist, is out-of-date, or the 'force' flag is true) then
+        # perform the action that presumably regenerates it
+        if self.force or dep_util.newer_group(infiles, outfile):
+            self.execute(func, args, exec_msg, level)
+
+        # Otherwise, print the "skip" message
+        else:
+            log.debug(skip_msg)
+
+# XXX 'install_misc' class not currently used -- it was the base class for
+# both 'install_scripts' and 'install_data', but they outgrew it.  It might
+# still be useful for 'install_headers', though, so I'm keeping it around
+# for the time being.
+
+class install_misc(Command):
+    """Common base class for installing some files in a subdirectory.
+    Currently used by install_data and install_scripts.
+    """
+
+    user_options = [('install-dir=', 'd', "directory to install the files to")]
+
+    def initialize_options (self):
+        self.install_dir = None
+        self.outfiles = []
+
+    def _install_dir_from(self, dirname):
+        self.set_undefined_options('install', (dirname, 'install_dir'))
+
+    def _copy_files(self, filelist):
+        self.outfiles = []
+        if not filelist:
+            return
+        self.mkpath(self.install_dir)
+        for f in filelist:
+            self.copy_file(f, self.install_dir)
+            self.outfiles.append(os.path.join(self.install_dir, f))
+
+    def get_outputs(self):
+        return self.outfiles
diff --git a/src/main/resources/PythonLibs/distutils/command/__init__.py b/src/main/resources/PythonLibs/distutils/command/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..20b159f74ecfc6a49498240066a77de4b0f3f5ce
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/__init__.py
@@ -0,0 +1,33 @@
+"""distutils.command
+
+Package containing implementation of all the standard Distutils
+commands."""
+
+__revision__ = "$Id$"
+
+__all__ = ['build',
+           'build_py',
+           'build_ext',
+           'build_clib',
+           'build_scripts',
+           'clean',
+           'install',
+           'install_lib',
+           'install_headers',
+           'install_scripts',
+           'install_data',
+           'sdist',
+           'register',
+           'bdist',
+           'bdist_dumb',
+           'bdist_rpm',
+           'bdist_wininst',
+           'upload',
+           'check',
+           # These two are reserved for future use:
+           #'bdist_sdux',
+           #'bdist_pkgtool',
+           # Note:
+           # bdist_packager is not included because it only provides
+           # an abstract base class
+          ]
diff --git a/src/main/resources/PythonLibs/distutils/command/bdist.py b/src/main/resources/PythonLibs/distutils/command/bdist.py
new file mode 100644
index 0000000000000000000000000000000000000000..b23331032888691f4c722289974458948e5703f4
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/bdist.py
@@ -0,0 +1,153 @@
+"""distutils.command.bdist
+
+Implements the Distutils 'bdist' command (create a built [binary]
+distribution)."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: bdist.py 62197 2008-04-07 01:53:39Z mark.hammond $"
+
+import os
+from types import *
+from distutils.core import Command
+from distutils.errors import *
+from distutils.util import get_platform
+
+
+def show_formats ():
+    """Print list of available formats (arguments to "--format" option).
+    """
+    from distutils.fancy_getopt import FancyGetopt
+    formats=[]
+    for format in bdist.format_commands:
+        formats.append(("formats=" + format, None,
+                        bdist.format_command[format][1]))
+    pretty_printer = FancyGetopt(formats)
+    pretty_printer.print_help("List of available distribution formats:")
+
+
+class bdist (Command):
+
+    description = "create a built (binary) distribution"
+
+    user_options = [('bdist-base=', 'b',
+                     "temporary directory for creating built distributions"),
+                    ('plat-name=', 'p',
+                     "platform name to embed in generated filenames "
+                     "(default: %s)" % get_platform()),
+                    ('formats=', None,
+                     "formats for distribution (comma-separated list)"),
+                    ('dist-dir=', 'd',
+                     "directory to put final built distributions in "
+                     "[default: dist]"),
+                    ('skip-build', None,
+                     "skip rebuilding everything (for testing/debugging)"),
+                   ]
+
+    boolean_options = ['skip-build']
+
+    help_options = [
+        ('help-formats', None,
+         "lists available distribution formats", show_formats),
+        ]
+
+    # The following commands do not take a format option from bdist
+    no_format_option = ('bdist_rpm',
+                        #'bdist_sdux', 'bdist_pkgtool'
+                        )
+
+    # This won't do in reality: will need to distinguish RPM-ish Linux,
+    # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS.
+    default_format = { 'posix': 'gztar',
+                       'java': 'gztar',
+                       'nt': 'zip',
+                       'os2': 'zip', }
+
+    # Establish the preferred order (for the --help-formats option).
+    format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar',
+                       'wininst', 'zip',
+                       #'pkgtool', 'sdux'
+                       ]
+
+    # And the real information.
+    format_command = { 'rpm':   ('bdist_rpm',  "RPM distribution"),
+                       'zip':   ('bdist_dumb', "ZIP file"),
+                       'gztar': ('bdist_dumb', "gzip'ed tar file"),
+                       'bztar': ('bdist_dumb', "bzip2'ed tar file"),
+                       'ztar':  ('bdist_dumb', "compressed tar file"),
+                       'tar':   ('bdist_dumb', "tar file"),
+                       'wininst': ('bdist_wininst',
+                                   "Windows executable installer"),
+                       'zip':   ('bdist_dumb', "ZIP file"),
+                       #'pkgtool': ('bdist_pkgtool',
+                       #            "Solaris pkgtool distribution"),
+                       #'sdux':  ('bdist_sdux', "HP-UX swinstall depot"),
+                      }
+
+
+    def initialize_options (self):
+        self.bdist_base = None
+        self.plat_name = None
+        self.formats = None
+        self.dist_dir = None
+        self.skip_build = 0
+
+    # initialize_options()
+
+
+    def finalize_options (self):
+        # have to finalize 'plat_name' before 'bdist_base'
+        if self.plat_name is None:
+            if self.skip_build:
+                self.plat_name = get_platform()
+            else:
+                self.plat_name = self.get_finalized_command('build').plat_name
+
+        # 'bdist_base' -- parent of per-built-distribution-format
+        # temporary directories (eg. we'll probably have
+        # "build/bdist.<plat>/dumb", "build/bdist.<plat>/rpm", etc.)
+        if self.bdist_base is None:
+            build_base = self.get_finalized_command('build').build_base
+            self.bdist_base = os.path.join(build_base,
+                                           'bdist.' + self.plat_name)
+
+        self.ensure_string_list('formats')
+        if self.formats is None:
+            try:
+                self.formats = [self.default_format[os.name]]
+            except KeyError:
+                raise DistutilsPlatformError, \
+                      "don't know how to create built distributions " + \
+                      "on platform %s" % os.name
+
+        if self.dist_dir is None:
+            self.dist_dir = "dist"
+
+    # finalize_options()
+
+    def run (self):
+
+        # Figure out which sub-commands we need to run.
+        commands = []
+        for format in self.formats:
+            try:
+                commands.append(self.format_command[format][0])
+            except KeyError:
+                raise DistutilsOptionError, "invalid format '%s'" % format
+
+        # Reinitialize and run each command.
+        for i in range(len(self.formats)):
+            cmd_name = commands[i]
+            sub_cmd = self.reinitialize_command(cmd_name)
+            if cmd_name not in self.no_format_option:
+                sub_cmd.format = self.formats[i]
+
+            # If we're going to need to run this command again, tell it to
+            # keep its temporary files around so subsequent runs go faster.
+            if cmd_name in commands[i+1:]:
+                sub_cmd.keep_temp = 1
+            self.run_command(cmd_name)
+
+    # run()
+
+# class bdist
diff --git a/src/main/resources/PythonLibs/distutils/command/bdist_dumb.py b/src/main/resources/PythonLibs/distutils/command/bdist_dumb.py
new file mode 100644
index 0000000000000000000000000000000000000000..7a2540465d6940123701e024c53b0c4bbaf544d1
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/bdist_dumb.py
@@ -0,0 +1,133 @@
+"""distutils.command.bdist_dumb
+
+Implements the Distutils 'bdist_dumb' command (create a "dumb" built
+distribution -- i.e., just an archive to be unpacked under $prefix or
+$exec_prefix)."""
+
+__revision__ = "$Id: bdist_dumb.py 77761 2010-01-26 22:46:15Z tarek.ziade $"
+
+import os
+
+from sysconfig import get_python_version
+
+from distutils.util import get_platform
+from distutils.core import Command
+from distutils.dir_util import remove_tree, ensure_relative
+from distutils.errors import DistutilsPlatformError
+from distutils import log
+
+class bdist_dumb (Command):
+
+    description = 'create a "dumb" built distribution'
+
+    user_options = [('bdist-dir=', 'd',
+                     "temporary directory for creating the distribution"),
+                    ('plat-name=', 'p',
+                     "platform name to embed in generated filenames "
+                     "(default: %s)" % get_platform()),
+                    ('format=', 'f',
+                     "archive format to create (tar, ztar, gztar, zip)"),
+                    ('keep-temp', 'k',
+                     "keep the pseudo-installation tree around after " +
+                     "creating the distribution archive"),
+                    ('dist-dir=', 'd',
+                     "directory to put final built distributions in"),
+                    ('skip-build', None,
+                     "skip rebuilding everything (for testing/debugging)"),
+                    ('relative', None,
+                     "build the archive using relative paths"
+                     "(default: false)"),
+                    ('owner=', 'u',
+                     "Owner name used when creating a tar file"
+                     " [default: current user]"),
+                    ('group=', 'g',
+                     "Group name used when creating a tar file"
+                     " [default: current group]"),
+                   ]
+
+    boolean_options = ['keep-temp', 'skip-build', 'relative']
+
+    default_format = { 'posix': 'gztar',
+                       'java': 'gztar',
+                       'nt': 'zip',
+                       'os2': 'zip' }
+
+
+    def initialize_options (self):
+        self.bdist_dir = None
+        self.plat_name = None
+        self.format = None
+        self.keep_temp = 0
+        self.dist_dir = None
+        self.skip_build = 0
+        self.relative = 0
+        self.owner = None
+        self.group = None
+
+    def finalize_options(self):
+        if self.bdist_dir is None:
+            bdist_base = self.get_finalized_command('bdist').bdist_base
+            self.bdist_dir = os.path.join(bdist_base, 'dumb')
+
+        if self.format is None:
+            try:
+                self.format = self.default_format[os.name]
+            except KeyError:
+                raise DistutilsPlatformError, \
+                      ("don't know how to create dumb built distributions " +
+                       "on platform %s") % os.name
+
+        self.set_undefined_options('bdist',
+                                   ('dist_dir', 'dist_dir'),
+                                   ('plat_name', 'plat_name'))
+
+    def run(self):
+        if not self.skip_build:
+            self.run_command('build')
+
+        install = self.reinitialize_command('install', reinit_subcommands=1)
+        install.root = self.bdist_dir
+        install.skip_build = self.skip_build
+        install.warn_dir = 0
+
+        log.info("installing to %s" % self.bdist_dir)
+        self.run_command('install')
+
+        # And make an archive relative to the root of the
+        # pseudo-installation tree.
+        archive_basename = "%s.%s" % (self.distribution.get_fullname(),
+                                      self.plat_name)
+
+        # OS/2 objects to any ":" characters in a filename (such as when
+        # a timestamp is used in a version) so change them to hyphens.
+        if os.name == "os2":
+            archive_basename = archive_basename.replace(":", "-")
+
+        pseudoinstall_root = os.path.join(self.dist_dir, archive_basename)
+        if not self.relative:
+            archive_root = self.bdist_dir
+        else:
+            if (self.distribution.has_ext_modules() and
+                (install.install_base != install.install_platbase)):
+                raise DistutilsPlatformError, \
+                      ("can't make a dumb built distribution where "
+                       "base and platbase are different (%s, %s)"
+                       % (repr(install.install_base),
+                          repr(install.install_platbase)))
+            else:
+                archive_root = os.path.join(self.bdist_dir,
+                                   ensure_relative(install.install_base))
+
+        # Make the archive
+        filename = self.make_archive(pseudoinstall_root,
+                                     self.format, root_dir=archive_root,
+                                     owner=self.owner, group=self.group)
+        if self.distribution.has_ext_modules():
+            pyversion = get_python_version()
+        else:
+            pyversion = 'any'
+        self.distribution.dist_files.append(('bdist_dumb', pyversion,
+                                             filename))
+
+        if not self.keep_temp:
+            remove_tree(self.bdist_dir, dry_run=self.dry_run)
diff --git a/src/main/resources/PythonLibs/distutils/command/bdist_msi.py b/src/main/resources/PythonLibs/distutils/command/bdist_msi.py
new file mode 100644
index 0000000000000000000000000000000000000000..703f873b164e895988ef100de8561ed7dd7e6f41
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/bdist_msi.py
@@ -0,0 +1,742 @@
+# -*- coding: iso-8859-1 -*-
+# Copyright (C) 2005, 2006 Martin von Löwis
+# Licensed to PSF under a Contributor Agreement.
+# The bdist_wininst command proper
+# based on bdist_wininst
+"""
+Implements the bdist_msi command.
+"""
+import sys, os
+from sysconfig import get_python_version
+
+from distutils.core import Command
+from distutils.dir_util import remove_tree
+from distutils.version import StrictVersion
+from distutils.errors import DistutilsOptionError
+from distutils import log
+from distutils.util import get_platform
+
+import msilib
+from msilib import schema, sequence, text
+from msilib import Directory, Feature, Dialog, add_data
+
+class PyDialog(Dialog):
+    """Dialog class with a fixed layout: controls at the top, then a ruler,
+    then a list of buttons: back, next, cancel. Optionally a bitmap at the
+    left."""
+    def __init__(self, *args, **kw):
+        """Dialog(database, name, x, y, w, h, attributes, title, first,
+        default, cancel, bitmap=true)"""
+        Dialog.__init__(self, *args)
+        ruler = self.h - 36
+        #if kw.get("bitmap", True):
+        #    self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin")
+        self.line("BottomLine", 0, ruler, self.w, 0)
+
+    def title(self, title):
+        "Set the title text of the dialog at the top."
+        # name, x, y, w, h, flags=Visible|Enabled|Transparent|NoPrefix,
+        # text, in VerdanaBold10
+        self.text("Title", 15, 10, 320, 60, 0x30003,
+                  r"{\VerdanaBold10}%s" % title)
+
+    def back(self, title, next, name = "Back", active = 1):
+        """Add a back button with a given title, the tab-next button,
+        its name in the Control table, possibly initially disabled.
+
+        Return the button, so that events can be associated"""
+        if active:
+            flags = 3 # Visible|Enabled
+        else:
+            flags = 1 # Visible
+        return self.pushbutton(name, 180, self.h-27 , 56, 17, flags, title, next)
+
+    def cancel(self, title, next, name = "Cancel", active = 1):
+        """Add a cancel button with a given title, the tab-next button,
+        its name in the Control table, possibly initially disabled.
+
+        Return the button, so that events can be associated"""
+        if active:
+            flags = 3 # Visible|Enabled
+        else:
+            flags = 1 # Visible
+        return self.pushbutton(name, 304, self.h-27, 56, 17, flags, title, next)
+
+    def next(self, title, next, name = "Next", active = 1):
+        """Add a Next button with a given title, the tab-next button,
+        its name in the Control table, possibly initially disabled.
+
+        Return the button, so that events can be associated"""
+        if active:
+            flags = 3 # Visible|Enabled
+        else:
+            flags = 1 # Visible
+        return self.pushbutton(name, 236, self.h-27, 56, 17, flags, title, next)
+
+    def xbutton(self, name, title, next, xpos):
+        """Add a button with a given title, the tab-next button,
+        its name in the Control table, giving its x position; the
+        y-position is aligned with the other buttons.
+
+        Return the button, so that events can be associated"""
+        return self.pushbutton(name, int(self.w*xpos - 28), self.h-27, 56, 17, 3, title, next)
+
+class bdist_msi (Command):
+
+    description = "create a Microsoft Installer (.msi) binary distribution"
+
+    user_options = [('bdist-dir=', None,
+                     "temporary directory for creating the distribution"),
+                    ('plat-name=', 'p',
+                     "platform name to embed in generated filenames "
+                     "(default: %s)" % get_platform()),
+                    ('keep-temp', 'k',
+                     "keep the pseudo-installation tree around after " +
+                     "creating the distribution archive"),
+                    ('target-version=', None,
+                     "require a specific python version" +
+                     " on the target system"),
+                    ('no-target-compile', 'c',
+                     "do not compile .py to .pyc on the target system"),
+                    ('no-target-optimize', 'o',
+                     "do not compile .py to .pyo (optimized)"
+                     "on the target system"),
+                    ('dist-dir=', 'd',
+                     "directory to put final built distributions in"),
+                    ('skip-build', None,
+                     "skip rebuilding everything (for testing/debugging)"),
+                    ('install-script=', None,
+                     "basename of installation script to be run after"
+                     "installation or before deinstallation"),
+                    ('pre-install-script=', None,
+                     "Fully qualified filename of a script to be run before "
+                     "any files are installed.  This script need not be in the "
+                     "distribution"),
+                   ]
+
+    boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
+                       'skip-build']
+
+    all_versions = ['2.0', '2.1', '2.2', '2.3', '2.4',
+                    '2.5', '2.6', '2.7', '2.8', '2.9',
+                    '3.0', '3.1', '3.2', '3.3', '3.4',
+                    '3.5', '3.6', '3.7', '3.8', '3.9']
+    other_version = 'X'
+
+    def initialize_options (self):
+        self.bdist_dir = None
+        self.plat_name = None
+        self.keep_temp = 0
+        self.no_target_compile = 0
+        self.no_target_optimize = 0
+        self.target_version = None
+        self.dist_dir = None
+        self.skip_build = None
+        self.install_script = None
+        self.pre_install_script = None
+        self.versions = None
+
+    def finalize_options (self):
+        self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
+
+        if self.bdist_dir is None:
+            bdist_base = self.get_finalized_command('bdist').bdist_base
+            self.bdist_dir = os.path.join(bdist_base, 'msi')
+
+        short_version = get_python_version()
+        if (not self.target_version) and self.distribution.has_ext_modules():
+            self.target_version = short_version
+
+        if self.target_version:
+            self.versions = [self.target_version]
+            if not self.skip_build and self.distribution.has_ext_modules()\
+               and self.target_version != short_version:
+                raise DistutilsOptionError, \
+                      "target version can only be %s, or the '--skip-build'" \
+                      " option must be specified" % (short_version,)
+        else:
+            self.versions = list(self.all_versions)
+
+        self.set_undefined_options('bdist',
+                                   ('dist_dir', 'dist_dir'),
+                                   ('plat_name', 'plat_name'),
+                                   )
+
+        if self.pre_install_script:
+            raise DistutilsOptionError, "the pre-install-script feature is not yet implemented"
+
+        if self.install_script:
+            for script in self.distribution.scripts:
+                if self.install_script == os.path.basename(script):
+                    break
+            else:
+                raise DistutilsOptionError, \
+                      "install_script '%s' not found in scripts" % \
+                      self.install_script
+        self.install_script_key = None
+    # finalize_options()
+
+
+    def run (self):
+        if not self.skip_build:
+            self.run_command('build')
+
+        install = self.reinitialize_command('install', reinit_subcommands=1)
+        install.prefix = self.bdist_dir
+        install.skip_build = self.skip_build
+        install.warn_dir = 0
+
+        install_lib = self.reinitialize_command('install_lib')
+        # we do not want to include pyc or pyo files
+        install_lib.compile = 0
+        install_lib.optimize = 0
+
+        if self.distribution.has_ext_modules():
+            # If we are building an installer for a Python version other
+            # than the one we are currently running, then we need to ensure
+            # our build_lib reflects the other Python version rather than ours.
+            # Note that for target_version!=sys.version, we must have skipped the
+            # build step, so there is no issue with enforcing the build of this
+            # version.
+            target_version = self.target_version
+            if not target_version:
+                assert self.skip_build, "Should have already checked this"
+                target_version = sys.version[0:3]
+            plat_specifier = ".%s-%s" % (self.plat_name, target_version)
+            build = self.get_finalized_command('build')
+            build.build_lib = os.path.join(build.build_base,
+                                           'lib' + plat_specifier)
+
+        log.info("installing to %s", self.bdist_dir)
+        install.ensure_finalized()
+
+        # avoid warning of 'install_lib' about installing
+        # into a directory not in sys.path
+        sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
+
+        install.run()
+
+        del sys.path[0]
+
+        self.mkpath(self.dist_dir)
+        fullname = self.distribution.get_fullname()
+        installer_name = self.get_installer_filename(fullname)
+        installer_name = os.path.abspath(installer_name)
+        if os.path.exists(installer_name): os.unlink(installer_name)
+
+        metadata = self.distribution.metadata
+        author = metadata.author
+        if not author:
+            author = metadata.maintainer
+        if not author:
+            author = "UNKNOWN"
+        version = metadata.get_version()
+        # ProductVersion must be strictly numeric
+        # XXX need to deal with prerelease versions
+        sversion = "%d.%d.%d" % StrictVersion(version).version
+        # Prefix ProductName with Python x.y, so that
+        # it sorts together with the other Python packages
+        # in Add-Remove-Programs (APR)
+        fullname = self.distribution.get_fullname()
+        if self.target_version:
+            product_name = "Python %s %s" % (self.target_version, fullname)
+        else:
+            product_name = "Python %s" % (fullname)
+        self.db = msilib.init_database(installer_name, schema,
+                product_name, msilib.gen_uuid(),
+                sversion, author)
+        msilib.add_tables(self.db, sequence)
+        props = [('DistVersion', version)]
+        email = metadata.author_email or metadata.maintainer_email
+        if email:
+            props.append(("ARPCONTACT", email))
+        if metadata.url:
+            props.append(("ARPURLINFOABOUT", metadata.url))
+        if props:
+            add_data(self.db, 'Property', props)
+
+        self.add_find_python()
+        self.add_files()
+        self.add_scripts()
+        self.add_ui()
+        self.db.Commit()
+
+        if hasattr(self.distribution, 'dist_files'):
+            tup = 'bdist_msi', self.target_version or 'any', fullname
+            self.distribution.dist_files.append(tup)
+
+        if not self.keep_temp:
+            remove_tree(self.bdist_dir, dry_run=self.dry_run)
+
+    def add_files(self):
+        db = self.db
+        cab = msilib.CAB("distfiles")
+        rootdir = os.path.abspath(self.bdist_dir)
+
+        root = Directory(db, cab, None, rootdir, "TARGETDIR", "SourceDir")
+        f = Feature(db, "Python", "Python", "Everything",
+                    0, 1, directory="TARGETDIR")
+
+        items = [(f, root, '')]
+        for version in self.versions + [self.other_version]:
+            target = "TARGETDIR" + version
+            name = default = "Python" + version
+            desc = "Everything"
+            if version is self.other_version:
+                title = "Python from another location"
+                level = 2
+            else:
+                title = "Python %s from registry" % version
+                level = 1
+            f = Feature(db, name, title, desc, 1, level, directory=target)
+            dir = Directory(db, cab, root, rootdir, target, default)
+            items.append((f, dir, version))
+        db.Commit()
+
+        seen = {}
+        for feature, dir, version in items:
+            todo = [dir]
+            while todo:
+                dir = todo.pop()
+                for file in os.listdir(dir.absolute):
+                    afile = os.path.join(dir.absolute, file)
+                    if os.path.isdir(afile):
+                        short = "%s|%s" % (dir.make_short(file), file)
+                        default = file + version
+                        newdir = Directory(db, cab, dir, file, default, short)
+                        todo.append(newdir)
+                    else:
+                        if not dir.component:
+                            dir.start_component(dir.logical, feature, 0)
+                        if afile not in seen:
+                            key = seen[afile] = dir.add_file(file)
+                            if file==self.install_script:
+                                if self.install_script_key:
+                                    raise DistutilsOptionError(
+                                          "Multiple files with name %s" % file)
+                                self.install_script_key = '[#%s]' % key
+                        else:
+                            key = seen[afile]
+                            add_data(self.db, "DuplicateFile",
+                                [(key + version, dir.component, key, None, dir.logical)])
+            db.Commit()
+        cab.commit(db)
+
+    def add_find_python(self):
+        """Adds code to the installer to compute the location of Python.
+
+        Properties PYTHON.MACHINE.X.Y and PYTHON.USER.X.Y will be set from the
+        registry for each version of Python.
+
+        Properties TARGETDIRX.Y will be set from PYTHON.USER.X.Y if defined,
+        else from PYTHON.MACHINE.X.Y.
+
+        Properties PYTHONX.Y will be set to TARGETDIRX.Y\\python.exe"""
+
+        start = 402
+        for ver in self.versions:
+            install_path = r"SOFTWARE\Python\PythonCore\%s\InstallPath" % ver
+            machine_reg = "python.machine." + ver
+            user_reg = "python.user." + ver
+            machine_prop = "PYTHON.MACHINE." + ver
+            user_prop = "PYTHON.USER." + ver
+            machine_action = "PythonFromMachine" + ver
+            user_action = "PythonFromUser" + ver
+            exe_action = "PythonExe" + ver
+            target_dir_prop = "TARGETDIR" + ver
+            exe_prop = "PYTHON" + ver
+            if msilib.Win64:
+                # type: msidbLocatorTypeRawValue + msidbLocatorType64bit
+                Type = 2+16
+            else:
+                Type = 2
+            add_data(self.db, "RegLocator",
+                    [(machine_reg, 2, install_path, None, Type),
+                     (user_reg, 1, install_path, None, Type)])
+            add_data(self.db, "AppSearch",
+                    [(machine_prop, machine_reg),
+                     (user_prop, user_reg)])
+            add_data(self.db, "CustomAction",
+                    [(machine_action, 51+256, target_dir_prop, "[" + machine_prop + "]"),
+                     (user_action, 51+256, target_dir_prop, "[" + user_prop + "]"),
+                     (exe_action, 51+256, exe_prop, "[" + target_dir_prop + "]\\python.exe"),
+                    ])
+            add_data(self.db, "InstallExecuteSequence",
+                    [(machine_action, machine_prop, start),
+                     (user_action, user_prop, start + 1),
+                     (exe_action, None, start + 2),
+                    ])
+            add_data(self.db, "InstallUISequence",
+                    [(machine_action, machine_prop, start),
+                     (user_action, user_prop, start + 1),
+                     (exe_action, None, start + 2),
+                    ])
+            add_data(self.db, "Condition",
+                    [("Python" + ver, 0, "NOT TARGETDIR" + ver)])
+            start += 4
+            assert start < 500
+
+    def add_scripts(self):
+        if self.install_script:
+            start = 6800
+            for ver in self.versions + [self.other_version]:
+                install_action = "install_script." + ver
+                exe_prop = "PYTHON" + ver
+                add_data(self.db, "CustomAction",
+                        [(install_action, 50, exe_prop, self.install_script_key)])
+                add_data(self.db, "InstallExecuteSequence",
+                        [(install_action, "&Python%s=3" % ver, start)])
+                start += 1
+        # XXX pre-install scripts are currently refused in finalize_options()
+        #     but if this feature is completed, it will also need to add
+        #     entries for each version as the above code does
+        if self.pre_install_script:
+            scriptfn = os.path.join(self.bdist_dir, "preinstall.bat")
+            f = open(scriptfn, "w")
+            # The batch file will be executed with [PYTHON], so that %1
+            # is the path to the Python interpreter; %0 will be the path
+            # of the batch file.
+            # rem ="""
+            # %1 %0
+            # exit
+            # """
+            # <actual script>
+            f.write('rem ="""\n%1 %0\nexit\n"""\n')
+            f.write(open(self.pre_install_script).read())
+            f.close()
+            add_data(self.db, "Binary",
+                [("PreInstall", msilib.Binary(scriptfn))
+                ])
+            add_data(self.db, "CustomAction",
+                [("PreInstall", 2, "PreInstall", None)
+                ])
+            add_data(self.db, "InstallExecuteSequence",
+                    [("PreInstall", "NOT Installed", 450)])
+
+
+    def add_ui(self):
+        db = self.db
+        x = y = 50
+        w = 370
+        h = 300
+        title = "[ProductName] Setup"
+
+        # see "Dialog Style Bits"
+        modal = 3      # visible | modal
+        modeless = 1   # visible
+
+        # UI customization properties
+        add_data(db, "Property",
+                 # See "DefaultUIFont Property"
+                 [("DefaultUIFont", "DlgFont8"),
+                  # See "ErrorDialog Style Bit"
+                  ("ErrorDialog", "ErrorDlg"),
+                  ("Progress1", "Install"),   # modified in maintenance type dlg
+                  ("Progress2", "installs"),
+                  ("MaintenanceForm_Action", "Repair"),
+                  # possible values: ALL, JUSTME
+                  ("WhichUsers", "ALL")
+                 ])
+
+        # Fonts, see "TextStyle Table"
+        add_data(db, "TextStyle",
+                 [("DlgFont8", "Tahoma", 9, None, 0),
+                  ("DlgFontBold8", "Tahoma", 8, None, 1), #bold
+                  ("VerdanaBold10", "Verdana", 10, None, 1),
+                  ("VerdanaRed9", "Verdana", 9, 255, 0),
+                 ])
+
+        # UI Sequences, see "InstallUISequence Table", "Using a Sequence Table"
+        # Numbers indicate sequence; see sequence.py for how these action integrate
+        add_data(db, "InstallUISequence",
+                 [("PrepareDlg", "Not Privileged or Windows9x or Installed", 140),
+                  ("WhichUsersDlg", "Privileged and not Windows9x and not Installed", 141),
+                  # In the user interface, assume all-users installation if privileged.
+                  ("SelectFeaturesDlg", "Not Installed", 1230),
+                  # XXX no support for resume installations yet
+                  #("ResumeDlg", "Installed AND (RESUME OR Preselected)", 1240),
+                  ("MaintenanceTypeDlg", "Installed AND NOT RESUME AND NOT Preselected", 1250),
+                  ("ProgressDlg", None, 1280)])
+
+        add_data(db, 'ActionText', text.ActionText)
+        add_data(db, 'UIText', text.UIText)
+        #####################################################################
+        # Standard dialogs: FatalError, UserExit, ExitDialog
+        fatal=PyDialog(db, "FatalError", x, y, w, h, modal, title,
+                     "Finish", "Finish", "Finish")
+        fatal.title("[ProductName] Installer ended prematurely")
+        fatal.back("< Back", "Finish", active = 0)
+        fatal.cancel("Cancel", "Back", active = 0)
+        fatal.text("Description1", 15, 70, 320, 80, 0x30003,
+                   "[ProductName] setup ended prematurely because of an error.  Your system has not been modified.  To install this program at a later time, please run the installation again.")
+        fatal.text("Description2", 15, 155, 320, 20, 0x30003,
+                   "Click the Finish button to exit the Installer.")
+        c=fatal.next("Finish", "Cancel", name="Finish")
+        c.event("EndDialog", "Exit")
+
+        user_exit=PyDialog(db, "UserExit", x, y, w, h, modal, title,
+                     "Finish", "Finish", "Finish")
+        user_exit.title("[ProductName] Installer was interrupted")
+        user_exit.back("< Back", "Finish", active = 0)
+        user_exit.cancel("Cancel", "Back", active = 0)
+        user_exit.text("Description1", 15, 70, 320, 80, 0x30003,
+                   "[ProductName] setup was interrupted.  Your system has not been modified.  "
+                   "To install this program at a later time, please run the installation again.")
+        user_exit.text("Description2", 15, 155, 320, 20, 0x30003,
+                   "Click the Finish button to exit the Installer.")
+        c = user_exit.next("Finish", "Cancel", name="Finish")
+        c.event("EndDialog", "Exit")
+
+        exit_dialog = PyDialog(db, "ExitDialog", x, y, w, h, modal, title,
+                             "Finish", "Finish", "Finish")
+        exit_dialog.title("Completing the [ProductName] Installer")
+        exit_dialog.back("< Back", "Finish", active = 0)
+        exit_dialog.cancel("Cancel", "Back", active = 0)
+        exit_dialog.text("Description", 15, 235, 320, 20, 0x30003,
+                   "Click the Finish button to exit the Installer.")
+        c = exit_dialog.next("Finish", "Cancel", name="Finish")
+        c.event("EndDialog", "Return")
+
+        #####################################################################
+        # Required dialog: FilesInUse, ErrorDlg
+        inuse = PyDialog(db, "FilesInUse",
+                         x, y, w, h,
+                         19,                # KeepModeless|Modal|Visible
+                         title,
+                         "Retry", "Retry", "Retry", bitmap=False)
+        inuse.text("Title", 15, 6, 200, 15, 0x30003,
+                   r"{\DlgFontBold8}Files in Use")
+        inuse.text("Description", 20, 23, 280, 20, 0x30003,
+               "Some files that need to be updated are currently in use.")
+        inuse.text("Text", 20, 55, 330, 50, 3,
+                   "The following applications are using files that need to be updated by this setup. Close these applications and then click Retry to continue the installation or Cancel to exit it.")
+        inuse.control("List", "ListBox", 20, 107, 330, 130, 7, "FileInUseProcess",
+                      None, None, None)
+        c=inuse.back("Exit", "Ignore", name="Exit")
+        c.event("EndDialog", "Exit")
+        c=inuse.next("Ignore", "Retry", name="Ignore")
+        c.event("EndDialog", "Ignore")
+        c=inuse.cancel("Retry", "Exit", name="Retry")
+        c.event("EndDialog","Retry")
+
+        # See "Error Dialog". See "ICE20" for the required names of the controls.
+        error = Dialog(db, "ErrorDlg",
+                       50, 10, 330, 101,
+                       65543,       # Error|Minimize|Modal|Visible
+                       title,
+                       "ErrorText", None, None)
+        error.text("ErrorText", 50,9,280,48,3, "")
+        #error.control("ErrorIcon", "Icon", 15, 9, 24, 24, 5242881, None, "py.ico", None, None)
+        error.pushbutton("N",120,72,81,21,3,"No",None).event("EndDialog","ErrorNo")
+        error.pushbutton("Y",240,72,81,21,3,"Yes",None).event("EndDialog","ErrorYes")
+        error.pushbutton("A",0,72,81,21,3,"Abort",None).event("EndDialog","ErrorAbort")
+        error.pushbutton("C",42,72,81,21,3,"Cancel",None).event("EndDialog","ErrorCancel")
+        error.pushbutton("I",81,72,81,21,3,"Ignore",None).event("EndDialog","ErrorIgnore")
+        error.pushbutton("O",159,72,81,21,3,"Ok",None).event("EndDialog","ErrorOk")
+        error.pushbutton("R",198,72,81,21,3,"Retry",None).event("EndDialog","ErrorRetry")
+
+        #####################################################################
+        # Global "Query Cancel" dialog
+        cancel = Dialog(db, "CancelDlg", 50, 10, 260, 85, 3, title,
+                        "No", "No", "No")
+        cancel.text("Text", 48, 15, 194, 30, 3,
+                    "Are you sure you want to cancel [ProductName] installation?")
+        #cancel.control("Icon", "Icon", 15, 15, 24, 24, 5242881, None,
+        #               "py.ico", None, None)
+        c=cancel.pushbutton("Yes", 72, 57, 56, 17, 3, "Yes", "No")
+        c.event("EndDialog", "Exit")
+
+        c=cancel.pushbutton("No", 132, 57, 56, 17, 3, "No", "Yes")
+        c.event("EndDialog", "Return")
+
+        #####################################################################
+        # Global "Wait for costing" dialog
+        costing = Dialog(db, "WaitForCostingDlg", 50, 10, 260, 85, modal, title,
+                         "Return", "Return", "Return")
+        costing.text("Text", 48, 15, 194, 30, 3,
+                     "Please wait while the installer finishes determining your disk space requirements.")
+        c = costing.pushbutton("Return", 102, 57, 56, 17, 3, "Return", None)
+        c.event("EndDialog", "Exit")
+
+        #####################################################################
+        # Preparation dialog: no user input except cancellation
+        prep = PyDialog(db, "PrepareDlg", x, y, w, h, modeless, title,
+                        "Cancel", "Cancel", "Cancel")
+        prep.text("Description", 15, 70, 320, 40, 0x30003,
+                  "Please wait while the Installer prepares to guide you through the installation.")
+        prep.title("Welcome to the [ProductName] Installer")
+        c=prep.text("ActionText", 15, 110, 320, 20, 0x30003, "Pondering...")
+        c.mapping("ActionText", "Text")
+        c=prep.text("ActionData", 15, 135, 320, 30, 0x30003, None)
+        c.mapping("ActionData", "Text")
+        prep.back("Back", None, active=0)
+        prep.next("Next", None, active=0)
+        c=prep.cancel("Cancel", None)
+        c.event("SpawnDialog", "CancelDlg")
+
+        #####################################################################
+        # Feature (Python directory) selection
+        seldlg = PyDialog(db, "SelectFeaturesDlg", x, y, w, h, modal, title,
+                        "Next", "Next", "Cancel")
+        seldlg.title("Select Python Installations")
+
+        seldlg.text("Hint", 15, 30, 300, 20, 3,
+                    "Select the Python locations where %s should be installed."
+                    % self.distribution.get_fullname())
+
+        seldlg.back("< Back", None, active=0)
+        c = seldlg.next("Next >", "Cancel")
+        order = 1
+        c.event("[TARGETDIR]", "[SourceDir]", ordering=order)
+        for version in self.versions + [self.other_version]:
+            order += 1
+            c.event("[TARGETDIR]", "[TARGETDIR%s]" % version,
+                    "FEATURE_SELECTED AND &Python%s=3" % version,
+                    ordering=order)
+        c.event("SpawnWaitDialog", "WaitForCostingDlg", ordering=order + 1)
+        c.event("EndDialog", "Return", ordering=order + 2)
+        c = seldlg.cancel("Cancel", "Features")
+        c.event("SpawnDialog", "CancelDlg")
+
+        c = seldlg.control("Features", "SelectionTree", 15, 60, 300, 120, 3,
+                           "FEATURE", None, "PathEdit", None)
+        c.event("[FEATURE_SELECTED]", "1")
+        ver = self.other_version
+        install_other_cond = "FEATURE_SELECTED AND &Python%s=3" % ver
+        dont_install_other_cond = "FEATURE_SELECTED AND &Python%s<>3" % ver
+
+        c = seldlg.text("Other", 15, 200, 300, 15, 3,
+                        "Provide an alternate Python location")
+        c.condition("Enable", install_other_cond)
+        c.condition("Show", install_other_cond)
+        c.condition("Disable", dont_install_other_cond)
+        c.condition("Hide", dont_install_other_cond)
+
+        c = seldlg.control("PathEdit", "PathEdit", 15, 215, 300, 16, 1,
+                           "TARGETDIR" + ver, None, "Next", None)
+        c.condition("Enable", install_other_cond)
+        c.condition("Show", install_other_cond)
+        c.condition("Disable", dont_install_other_cond)
+        c.condition("Hide", dont_install_other_cond)
+
+        #####################################################################
+        # Disk cost
+        cost = PyDialog(db, "DiskCostDlg", x, y, w, h, modal, title,
+                        "OK", "OK", "OK", bitmap=False)
+        cost.text("Title", 15, 6, 200, 15, 0x30003,
+                  "{\DlgFontBold8}Disk Space Requirements")
+        cost.text("Description", 20, 20, 280, 20, 0x30003,
+                  "The disk space required for the installation of the selected features.")
+        cost.text("Text", 20, 53, 330, 60, 3,
+                  "The highlighted volumes (if any) do not have enough disk space "
+              "available for the currently selected features.  You can either "
+              "remove some files from the highlighted volumes, or choose to "
+              "install less features onto local drive(s), or select different "
+              "destination drive(s).")
+        cost.control("VolumeList", "VolumeCostList", 20, 100, 330, 150, 393223,
+                     None, "{120}{70}{70}{70}{70}", None, None)
+        cost.xbutton("OK", "Ok", None, 0.5).event("EndDialog", "Return")
+
+        #####################################################################
+        # WhichUsers Dialog. Only available on NT, and for privileged users.
+        # This must be run before FindRelatedProducts, because that will
+        # take into account whether the previous installation was per-user
+        # or per-machine. We currently don't support going back to this
+        # dialog after "Next" was selected; to support this, we would need to
+        # find how to reset the ALLUSERS property, and how to re-run
+        # FindRelatedProducts.
+        # On Windows9x, the ALLUSERS property is ignored on the command line
+        # and in the Property table, but installer fails according to the documentation
+        # if a dialog attempts to set ALLUSERS.
+        whichusers = PyDialog(db, "WhichUsersDlg", x, y, w, h, modal, title,
+                            "AdminInstall", "Next", "Cancel")
+        whichusers.title("Select whether to install [ProductName] for all users of this computer.")
+        # A radio group with two options: allusers, justme
+        g = whichusers.radiogroup("AdminInstall", 15, 60, 260, 50, 3,
+                                  "WhichUsers", "", "Next")
+        g.add("ALL", 0, 5, 150, 20, "Install for all users")
+        g.add("JUSTME", 0, 25, 150, 20, "Install just for me")
+
+        whichusers.back("Back", None, active=0)
+
+        c = whichusers.next("Next >", "Cancel")
+        c.event("[ALLUSERS]", "1", 'WhichUsers="ALL"', 1)
+        c.event("EndDialog", "Return", ordering = 2)
+
+        c = whichusers.cancel("Cancel", "AdminInstall")
+        c.event("SpawnDialog", "CancelDlg")
+
+        #####################################################################
+        # Installation Progress dialog (modeless)
+        progress = PyDialog(db, "ProgressDlg", x, y, w, h, modeless, title,
+                            "Cancel", "Cancel", "Cancel", bitmap=False)
+        progress.text("Title", 20, 15, 200, 15, 0x30003,
+                      "{\DlgFontBold8}[Progress1] [ProductName]")
+        progress.text("Text", 35, 65, 300, 30, 3,
+                      "Please wait while the Installer [Progress2] [ProductName]. "
+                      "This may take several minutes.")
+        progress.text("StatusLabel", 35, 100, 35, 20, 3, "Status:")
+
+        c=progress.text("ActionText", 70, 100, w-70, 20, 3, "Pondering...")
+        c.mapping("ActionText", "Text")
+
+        #c=progress.text("ActionData", 35, 140, 300, 20, 3, None)
+        #c.mapping("ActionData", "Text")
+
+        c=progress.control("ProgressBar", "ProgressBar", 35, 120, 300, 10, 65537,
+                           None, "Progress done", None, None)
+        c.mapping("SetProgress", "Progress")
+
+        progress.back("< Back", "Next", active=False)
+        progress.next("Next >", "Cancel", active=False)
+        progress.cancel("Cancel", "Back").event("SpawnDialog", "CancelDlg")
+
+        ###################################################################
+        # Maintenance type: repair/uninstall
+        maint = PyDialog(db, "MaintenanceTypeDlg", x, y, w, h, modal, title,
+                         "Next", "Next", "Cancel")
+        maint.title("Welcome to the [ProductName] Setup Wizard")
+        maint.text("BodyText", 15, 63, 330, 42, 3,
+                   "Select whether you want to repair or remove [ProductName].")
+        g=maint.radiogroup("RepairRadioGroup", 15, 108, 330, 60, 3,
+                            "MaintenanceForm_Action", "", "Next")
+        #g.add("Change", 0, 0, 200, 17, "&Change [ProductName]")
+        g.add("Repair", 0, 18, 200, 17, "&Repair [ProductName]")
+        g.add("Remove", 0, 36, 200, 17, "Re&move [ProductName]")
+
+        maint.back("< Back", None, active=False)
+        c=maint.next("Finish", "Cancel")
+        # Change installation: Change progress dialog to "Change", then ask
+        # for feature selection
+        #c.event("[Progress1]", "Change", 'MaintenanceForm_Action="Change"', 1)
+        #c.event("[Progress2]", "changes", 'MaintenanceForm_Action="Change"', 2)
+
+        # Reinstall: Change progress dialog to "Repair", then invoke reinstall
+        # Also set list of reinstalled features to "ALL"
+        c.event("[REINSTALL]", "ALL", 'MaintenanceForm_Action="Repair"', 5)
+        c.event("[Progress1]", "Repairing", 'MaintenanceForm_Action="Repair"', 6)
+        c.event("[Progress2]", "repairs", 'MaintenanceForm_Action="Repair"', 7)
+        c.event("Reinstall", "ALL", 'MaintenanceForm_Action="Repair"', 8)
+
+        # Uninstall: Change progress to "Remove", then invoke uninstall
+        # Also set list of removed features to "ALL"
+        c.event("[REMOVE]", "ALL", 'MaintenanceForm_Action="Remove"', 11)
+        c.event("[Progress1]", "Removing", 'MaintenanceForm_Action="Remove"', 12)
+        c.event("[Progress2]", "removes", 'MaintenanceForm_Action="Remove"', 13)
+        c.event("Remove", "ALL", 'MaintenanceForm_Action="Remove"', 14)
+
+        # Close dialog when maintenance action scheduled
+        c.event("EndDialog", "Return", 'MaintenanceForm_Action<>"Change"', 20)
+        #c.event("NewDialog", "SelectFeaturesDlg", 'MaintenanceForm_Action="Change"', 21)
+
+        maint.cancel("Cancel", "RepairRadioGroup").event("SpawnDialog", "CancelDlg")
+
+    def get_installer_filename(self, fullname):
+        # Factored out to allow overriding in subclasses
+        if self.target_version:
+            base_name = "%s.%s-py%s.msi" % (fullname, self.plat_name,
+                                            self.target_version)
+        else:
+            base_name = "%s.%s.msi" % (fullname, self.plat_name)
+        installer_name = os.path.join(self.dist_dir, base_name)
+        return installer_name
diff --git a/src/main/resources/PythonLibs/distutils/command/bdist_rpm.py b/src/main/resources/PythonLibs/distutils/command/bdist_rpm.py
new file mode 100644
index 0000000000000000000000000000000000000000..595824367e336769b109e1546baf481a92e55186
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/bdist_rpm.py
@@ -0,0 +1,587 @@
+"""distutils.command.bdist_rpm
+
+Implements the Distutils 'bdist_rpm' command (create RPM source and binary
+distributions)."""
+
+__revision__ = "$Id$"
+
+import sys
+import os
+import string
+
+from distutils.core import Command
+from distutils.debug import DEBUG
+from distutils.file_util import write_file
+from distutils.errors import (DistutilsOptionError, DistutilsPlatformError,
+                              DistutilsFileError, DistutilsExecError)
+from distutils import log
+
+class bdist_rpm (Command):
+
+    description = "create an RPM distribution"
+
+    user_options = [
+        ('bdist-base=', None,
+         "base directory for creating built distributions"),
+        ('rpm-base=', None,
+         "base directory for creating RPMs (defaults to \"rpm\" under "
+         "--bdist-base; must be specified for RPM 2)"),
+        ('dist-dir=', 'd',
+         "directory to put final RPM files in "
+         "(and .spec files if --spec-only)"),
+        ('python=', None,
+         "path to Python interpreter to hard-code in the .spec file "
+         "(default: \"python\")"),
+        ('fix-python', None,
+         "hard-code the exact path to the current Python interpreter in "
+         "the .spec file"),
+        ('spec-only', None,
+         "only regenerate spec file"),
+        ('source-only', None,
+         "only generate source RPM"),
+        ('binary-only', None,
+         "only generate binary RPM"),
+        ('use-bzip2', None,
+         "use bzip2 instead of gzip to create source distribution"),
+
+        # More meta-data: too RPM-specific to put in the setup script,
+        # but needs to go in the .spec file -- so we make these options
+        # to "bdist_rpm".  The idea is that packagers would put this
+        # info in setup.cfg, although they are of course free to
+        # supply it on the command line.
+        ('distribution-name=', None,
+         "name of the (Linux) distribution to which this "
+         "RPM applies (*not* the name of the module distribution!)"),
+        ('group=', None,
+         "package classification [default: \"Development/Libraries\"]"),
+        ('release=', None,
+         "RPM release number"),
+        ('serial=', None,
+         "RPM serial number"),
+        ('vendor=', None,
+         "RPM \"vendor\" (eg. \"Joe Blow <joe@example.com>\") "
+         "[default: maintainer or author from setup script]"),
+        ('packager=', None,
+         "RPM packager (eg. \"Jane Doe <jane@example.net>\")"
+         "[default: vendor]"),
+        ('doc-files=', None,
+         "list of documentation files (space or comma-separated)"),
+        ('changelog=', None,
+         "RPM changelog"),
+        ('icon=', None,
+         "name of icon file"),
+        ('provides=', None,
+         "capabilities provided by this package"),
+        ('requires=', None,
+         "capabilities required by this package"),
+        ('conflicts=', None,
+         "capabilities which conflict with this package"),
+        ('build-requires=', None,
+         "capabilities required to build this package"),
+        ('obsoletes=', None,
+         "capabilities made obsolete by this package"),
+        ('no-autoreq', None,
+         "do not automatically calculate dependencies"),
+
+        # Actions to take when building RPM
+        ('keep-temp', 'k',
+         "don't clean up RPM build directory"),
+        ('no-keep-temp', None,
+         "clean up RPM build directory [default]"),
+        ('use-rpm-opt-flags', None,
+         "compile with RPM_OPT_FLAGS when building from source RPM"),
+        ('no-rpm-opt-flags', None,
+         "do not pass any RPM CFLAGS to compiler"),
+        ('rpm3-mode', None,
+         "RPM 3 compatibility mode (default)"),
+        ('rpm2-mode', None,
+         "RPM 2 compatibility mode"),
+
+        # Add the hooks necessary for specifying custom scripts
+        ('prep-script=', None,
+         "Specify a script for the PREP phase of RPM building"),
+        ('build-script=', None,
+         "Specify a script for the BUILD phase of RPM building"),
+
+        ('pre-install=', None,
+         "Specify a script for the pre-INSTALL phase of RPM building"),
+        ('install-script=', None,
+         "Specify a script for the INSTALL phase of RPM building"),
+        ('post-install=', None,
+         "Specify a script for the post-INSTALL phase of RPM building"),
+
+        ('pre-uninstall=', None,
+         "Specify a script for the pre-UNINSTALL phase of RPM building"),
+        ('post-uninstall=', None,
+         "Specify a script for the post-UNINSTALL phase of RPM building"),
+
+        ('clean-script=', None,
+         "Specify a script for the CLEAN phase of RPM building"),
+
+        ('verify-script=', None,
+         "Specify a script for the VERIFY phase of the RPM build"),
+
+        # Allow a packager to explicitly force an architecture
+        ('force-arch=', None,
+         "Force an architecture onto the RPM build process"),
+
+        ('quiet', 'q',
+         "Run the INSTALL phase of RPM building in quiet mode"),
+        ]
+
+    boolean_options = ['keep-temp', 'use-rpm-opt-flags', 'rpm3-mode',
+                       'no-autoreq', 'quiet']
+
+    negative_opt = {'no-keep-temp': 'keep-temp',
+                    'no-rpm-opt-flags': 'use-rpm-opt-flags',
+                    'rpm2-mode': 'rpm3-mode'}
+
+
+    def initialize_options (self):
+        self.bdist_base = None
+        self.rpm_base = None
+        self.dist_dir = None
+        self.python = None
+        self.fix_python = None
+        self.spec_only = None
+        self.binary_only = None
+        self.source_only = None
+        self.use_bzip2 = None
+
+        self.distribution_name = None
+        self.group = None
+        self.release = None
+        self.serial = None
+        self.vendor = None
+        self.packager = None
+        self.doc_files = None
+        self.changelog = None
+        self.icon = None
+
+        self.prep_script = None
+        self.build_script = None
+        self.install_script = None
+        self.clean_script = None
+        self.verify_script = None
+        self.pre_install = None
+        self.post_install = None
+        self.pre_uninstall = None
+        self.post_uninstall = None
+        self.prep = None
+        self.provides = None
+        self.requires = None
+        self.conflicts = None
+        self.build_requires = None
+        self.obsoletes = None
+
+        self.keep_temp = 0
+        self.use_rpm_opt_flags = 1
+        self.rpm3_mode = 1
+        self.no_autoreq = 0
+
+        self.force_arch = None
+        self.quiet = 0
+
+    # initialize_options()
+
+
+    def finalize_options (self):
+        self.set_undefined_options('bdist', ('bdist_base', 'bdist_base'))
+        if self.rpm_base is None:
+            if not self.rpm3_mode:
+                raise DistutilsOptionError, \
+                      "you must specify --rpm-base in RPM 2 mode"
+            self.rpm_base = os.path.join(self.bdist_base, "rpm")
+
+        if self.python is None:
+            if self.fix_python:
+                self.python = sys.executable
+            else:
+                self.python = "python"
+        elif self.fix_python:
+            raise DistutilsOptionError, \
+                  "--python and --fix-python are mutually exclusive options"
+
+        if os.name != 'posix':
+            raise DistutilsPlatformError, \
+                  ("don't know how to create RPM "
+                   "distributions on platform %s" % os.name)
+        if self.binary_only and self.source_only:
+            raise DistutilsOptionError, \
+                  "cannot supply both '--source-only' and '--binary-only'"
+
+        # don't pass CFLAGS to pure python distributions
+        if not self.distribution.has_ext_modules():
+            self.use_rpm_opt_flags = 0
+
+        self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
+        self.finalize_package_data()
+
+    # finalize_options()
+
+    def finalize_package_data (self):
+        self.ensure_string('group', "Development/Libraries")
+        self.ensure_string('vendor',
+                           "%s <%s>" % (self.distribution.get_contact(),
+                                        self.distribution.get_contact_email()))
+        self.ensure_string('packager')
+        self.ensure_string_list('doc_files')
+        if isinstance(self.doc_files, list):
+            for readme in ('README', 'README.txt'):
+                if os.path.exists(readme) and readme not in self.doc_files:
+                    self.doc_files.append(readme)
+
+        self.ensure_string('release', "1")
+        self.ensure_string('serial')   # should it be an int?
+
+        self.ensure_string('distribution_name')
+
+        self.ensure_string('changelog')
+          # Format changelog correctly
+        self.changelog = self._format_changelog(self.changelog)
+
+        self.ensure_filename('icon')
+
+        self.ensure_filename('prep_script')
+        self.ensure_filename('build_script')
+        self.ensure_filename('install_script')
+        self.ensure_filename('clean_script')
+        self.ensure_filename('verify_script')
+        self.ensure_filename('pre_install')
+        self.ensure_filename('post_install')
+        self.ensure_filename('pre_uninstall')
+        self.ensure_filename('post_uninstall')
+
+        # XXX don't forget we punted on summaries and descriptions -- they
+        # should be handled here eventually!
+
+        # Now *this* is some meta-data that belongs in the setup script...
+        self.ensure_string_list('provides')
+        self.ensure_string_list('requires')
+        self.ensure_string_list('conflicts')
+        self.ensure_string_list('build_requires')
+        self.ensure_string_list('obsoletes')
+
+        self.ensure_string('force_arch')
+    # finalize_package_data ()
+
+
+    def run (self):
+
+        if DEBUG:
+            print "before _get_package_data():"
+            print "vendor =", self.vendor
+            print "packager =", self.packager
+            print "doc_files =", self.doc_files
+            print "changelog =", self.changelog
+
+        # make directories
+        if self.spec_only:
+            spec_dir = self.dist_dir
+            self.mkpath(spec_dir)
+        else:
+            rpm_dir = {}
+            for d in ('SOURCES', 'SPECS', 'BUILD', 'RPMS', 'SRPMS'):
+                rpm_dir[d] = os.path.join(self.rpm_base, d)
+                self.mkpath(rpm_dir[d])
+            spec_dir = rpm_dir['SPECS']
+
+        # Spec file goes into 'dist_dir' if '--spec-only specified',
+        # build/rpm.<plat> otherwise.
+        spec_path = os.path.join(spec_dir,
+                                 "%s.spec" % self.distribution.get_name())
+        self.execute(write_file,
+                     (spec_path,
+                      self._make_spec_file()),
+                     "writing '%s'" % spec_path)
+
+        if self.spec_only: # stop if requested
+            return
+
+        # Make a source distribution and copy to SOURCES directory with
+        # optional icon.
+        saved_dist_files = self.distribution.dist_files[:]
+        sdist = self.reinitialize_command('sdist')
+        if self.use_bzip2:
+            sdist.formats = ['bztar']
+        else:
+            sdist.formats = ['gztar']
+        self.run_command('sdist')
+        self.distribution.dist_files = saved_dist_files
+
+        source = sdist.get_archive_files()[0]
+        source_dir = rpm_dir['SOURCES']
+        self.copy_file(source, source_dir)
+
+        if self.icon:
+            if os.path.exists(self.icon):
+                self.copy_file(self.icon, source_dir)
+            else:
+                raise DistutilsFileError, \
+                      "icon file '%s' does not exist" % self.icon
+
+
+        # build package
+        log.info("building RPMs")
+        rpm_cmd = ['rpm']
+        if os.path.exists('/usr/bin/rpmbuild') or \
+           os.path.exists('/bin/rpmbuild'):
+            rpm_cmd = ['rpmbuild']
+
+        if self.source_only: # what kind of RPMs?
+            rpm_cmd.append('-bs')
+        elif self.binary_only:
+            rpm_cmd.append('-bb')
+        else:
+            rpm_cmd.append('-ba')
+        if self.rpm3_mode:
+            rpm_cmd.extend(['--define',
+                             '_topdir %s' % os.path.abspath(self.rpm_base)])
+        if not self.keep_temp:
+            rpm_cmd.append('--clean')
+
+        if self.quiet:
+            rpm_cmd.append('--quiet')
+
+        rpm_cmd.append(spec_path)
+        # Determine the binary rpm names that should be built out of this spec
+        # file
+        # Note that some of these may not be really built (if the file
+        # list is empty)
+        nvr_string = "%{name}-%{version}-%{release}"
+        src_rpm = nvr_string + ".src.rpm"
+        non_src_rpm = "%{arch}/" + nvr_string + ".%{arch}.rpm"
+        q_cmd = r"rpm -q --qf '%s %s\n' --specfile '%s'" % (
+            src_rpm, non_src_rpm, spec_path)
+
+        out = os.popen(q_cmd)
+        try:
+            binary_rpms = []
+            source_rpm = None
+            while 1:
+                line = out.readline()
+                if not line:
+                    break
+                l = string.split(string.strip(line))
+                assert(len(l) == 2)
+                binary_rpms.append(l[1])
+                # The source rpm is named after the first entry in the spec file
+                if source_rpm is None:
+                    source_rpm = l[0]
+
+            status = out.close()
+            if status:
+                raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd))
+
+        finally:
+            out.close()
+
+        self.spawn(rpm_cmd)
+
+        if not self.dry_run:
+            if self.distribution.has_ext_modules():
+                pyversion = get_python_version()
+            else:
+                pyversion = 'any'
+
+            if not self.binary_only:
+                srpm = os.path.join(rpm_dir['SRPMS'], source_rpm)
+                assert(os.path.exists(srpm))
+                self.move_file(srpm, self.dist_dir)
+                filename = os.path.join(self.dist_dir, source_rpm)
+                self.distribution.dist_files.append(
+                    ('bdist_rpm', pyversion, filename))
+
+            if not self.source_only:
+                for rpm in binary_rpms:
+                    rpm = os.path.join(rpm_dir['RPMS'], rpm)
+                    if os.path.exists(rpm):
+                        self.move_file(rpm, self.dist_dir)
+                        filename = os.path.join(self.dist_dir,
+                                                os.path.basename(rpm))
+                        self.distribution.dist_files.append(
+                            ('bdist_rpm', pyversion, filename))
+    # run()
+
+    def _dist_path(self, path):
+        return os.path.join(self.dist_dir, os.path.basename(path))
+
+    def _make_spec_file(self):
+        """Generate the text of an RPM spec file and return it as a
+        list of strings (one per line).
+        """
+        # definitions and headers
+        spec_file = [
+            '%define name ' + self.distribution.get_name(),
+            '%define version ' + self.distribution.get_version().replace('-','_'),
+            '%define unmangled_version ' + self.distribution.get_version(),
+            '%define release ' + self.release.replace('-','_'),
+            '',
+            'Summary: ' + self.distribution.get_description(),
+            ]
+
+        # put locale summaries into spec file
+        # XXX not supported for now (hard to put a dictionary
+        # in a config file -- arg!)
+        #for locale in self.summaries.keys():
+        #    spec_file.append('Summary(%s): %s' % (locale,
+        #                                          self.summaries[locale]))
+
+        spec_file.extend([
+            'Name: %{name}',
+            'Version: %{version}',
+            'Release: %{release}',])
+
+        # XXX yuck! this filename is available from the "sdist" command,
+        # but only after it has run: and we create the spec file before
+        # running "sdist", in case of --spec-only.
+        if self.use_bzip2:
+            spec_file.append('Source0: %{name}-%{unmangled_version}.tar.bz2')
+        else:
+            spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz')
+
+        spec_file.extend([
+            'License: ' + self.distribution.get_license(),
+            'Group: ' + self.group,
+            'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot',
+            'Prefix: %{_prefix}', ])
+
+        if not self.force_arch:
+            # noarch if no extension modules
+            if not self.distribution.has_ext_modules():
+                spec_file.append('BuildArch: noarch')
+        else:
+            spec_file.append( 'BuildArch: %s' % self.force_arch )
+
+        for field in ('Vendor',
+                      'Packager',
+                      'Provides',
+                      'Requires',
+                      'Conflicts',
+                      'Obsoletes',
+                      ):
+            val = getattr(self, string.lower(field))
+            if isinstance(val, list):
+                spec_file.append('%s: %s' % (field, string.join(val)))
+            elif val is not None:
+                spec_file.append('%s: %s' % (field, val))
+
+
+        if self.distribution.get_url() != 'UNKNOWN':
+            spec_file.append('Url: ' + self.distribution.get_url())
+
+        if self.distribution_name:
+            spec_file.append('Distribution: ' + self.distribution_name)
+
+        if self.build_requires:
+            spec_file.append('BuildRequires: ' +
+                             string.join(self.build_requires))
+
+        if self.icon:
+            spec_file.append('Icon: ' + os.path.basename(self.icon))
+
+        if self.no_autoreq:
+            spec_file.append('AutoReq: 0')
+
+        spec_file.extend([
+            '',
+            '%description',
+            self.distribution.get_long_description()
+            ])
+
+        # put locale descriptions into spec file
+        # XXX again, suppressed because config file syntax doesn't
+        # easily support this ;-(
+        #for locale in self.descriptions.keys():
+        #    spec_file.extend([
+        #        '',
+        #        '%description -l ' + locale,
+        #        self.descriptions[locale],
+        #        ])
+
+        # rpm scripts
+        # figure out default build script
+        def_setup_call = "%s %s" % (self.python,os.path.basename(sys.argv[0]))
+        def_build = "%s build" % def_setup_call
+        if self.use_rpm_opt_flags:
+            def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build
+
+        # insert contents of files
+
+        # XXX this is kind of misleading: user-supplied options are files
+        # that we open and interpolate into the spec file, but the defaults
+        # are just text that we drop in as-is.  Hmmm.
+
+        install_cmd = ('%s install -O1 --root=$RPM_BUILD_ROOT '
+                       '--record=INSTALLED_FILES') % def_setup_call
+
+        script_options = [
+            ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"),
+            ('build', 'build_script', def_build),
+            ('install', 'install_script', install_cmd),
+            ('clean', 'clean_script', "rm -rf $RPM_BUILD_ROOT"),
+            ('verifyscript', 'verify_script', None),
+            ('pre', 'pre_install', None),
+            ('post', 'post_install', None),
+            ('preun', 'pre_uninstall', None),
+            ('postun', 'post_uninstall', None),
+        ]
+
+        for (rpm_opt, attr, default) in script_options:
+            # Insert contents of file referred to, if no file is referred to
+            # use 'default' as contents of script
+            val = getattr(self, attr)
+            if val or default:
+                spec_file.extend([
+                    '',
+                    '%' + rpm_opt,])
+                if val:
+                    spec_file.extend(string.split(open(val, 'r').read(), '\n'))
+                else:
+                    spec_file.append(default)
+
+
+        # files section
+        spec_file.extend([
+            '',
+            '%files -f INSTALLED_FILES',
+            '%defattr(-,root,root)',
+            ])
+
+        if self.doc_files:
+            spec_file.append('%doc ' + string.join(self.doc_files))
+
+        if self.changelog:
+            spec_file.extend([
+                '',
+                '%changelog',])
+            spec_file.extend(self.changelog)
+
+        return spec_file
+
+    # _make_spec_file ()
+
+    def _format_changelog(self, changelog):
+        """Format the changelog correctly and convert it to a list of strings
+        """
+        if not changelog:
+            return changelog
+        new_changelog = []
+        for line in string.split(string.strip(changelog), '\n'):
+            line = string.strip(line)
+            if line[0] == '*':
+                new_changelog.extend(['', line])
+            elif line[0] == '-':
+                new_changelog.append(line)
+            else:
+                new_changelog.append('  ' + line)
+
+        # strip trailing newline inserted by first changelog entry
+        if not new_changelog[0]:
+            del new_changelog[0]
+
+        return new_changelog
+
+    # _format_changelog()
+
+# class bdist_rpm
diff --git a/src/main/resources/PythonLibs/distutils/command/bdist_wininst.py b/src/main/resources/PythonLibs/distutils/command/bdist_wininst.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa9383af98b641fd5041aacbd1c2d142b434deb7
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/bdist_wininst.py
@@ -0,0 +1,368 @@
+"""distutils.command.bdist_wininst
+
+Implements the Distutils 'bdist_wininst' command: create a windows installer
+exe-program."""
+
+__revision__ = "$Id$"
+
+import sys
+import os
+import string
+
+from sysconfig import get_python_version
+
+from distutils.core import Command
+from distutils.dir_util import remove_tree
+from distutils.errors import DistutilsOptionError, DistutilsPlatformError
+from distutils import log
+from distutils.util import get_platform
+
+class bdist_wininst (Command):
+
+    description = "create an executable installer for MS Windows"
+
+    user_options = [('bdist-dir=', None,
+                     "temporary directory for creating the distribution"),
+                    ('plat-name=', 'p',
+                     "platform name to embed in generated filenames "
+                     "(default: %s)" % get_platform()),
+                    ('keep-temp', 'k',
+                     "keep the pseudo-installation tree around after " +
+                     "creating the distribution archive"),
+                    ('target-version=', None,
+                     "require a specific python version" +
+                     " on the target system"),
+                    ('no-target-compile', 'c',
+                     "do not compile .py to .pyc on the target system"),
+                    ('no-target-optimize', 'o',
+                     "do not compile .py to .pyo (optimized)"
+                     "on the target system"),
+                    ('dist-dir=', 'd',
+                     "directory to put final built distributions in"),
+                    ('bitmap=', 'b',
+                     "bitmap to use for the installer instead of python-powered logo"),
+                    ('title=', 't',
+                     "title to display on the installer background instead of default"),
+                    ('skip-build', None,
+                     "skip rebuilding everything (for testing/debugging)"),
+                    ('install-script=', None,
+                     "basename of installation script to be run after"
+                     "installation or before deinstallation"),
+                    ('pre-install-script=', None,
+                     "Fully qualified filename of a script to be run before "
+                     "any files are installed.  This script need not be in the "
+                     "distribution"),
+                    ('user-access-control=', None,
+                     "specify Vista's UAC handling - 'none'/default=no "
+                     "handling, 'auto'=use UAC if target Python installed for "
+                     "all users, 'force'=always use UAC"),
+                   ]
+
+    boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
+                       'skip-build']
+
+    def initialize_options (self):
+        self.bdist_dir = None
+        self.plat_name = None
+        self.keep_temp = 0
+        self.no_target_compile = 0
+        self.no_target_optimize = 0
+        self.target_version = None
+        self.dist_dir = None
+        self.bitmap = None
+        self.title = None
+        self.skip_build = None
+        self.install_script = None
+        self.pre_install_script = None
+        self.user_access_control = None
+
+    # initialize_options()
+
+
+    def finalize_options (self):
+        self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
+
+        if self.bdist_dir is None:
+            if self.skip_build and self.plat_name:
+                # If build is skipped and plat_name is overridden, bdist will
+                # not see the correct 'plat_name' - so set that up manually.
+                bdist = self.distribution.get_command_obj('bdist')
+                bdist.plat_name = self.plat_name
+                # next the command will be initialized using that name
+            bdist_base = self.get_finalized_command('bdist').bdist_base
+            self.bdist_dir = os.path.join(bdist_base, 'wininst')
+
+        if not self.target_version:
+            self.target_version = ""
+
+        if not self.skip_build and self.distribution.has_ext_modules():
+            short_version = get_python_version()
+            if self.target_version and self.target_version != short_version:
+                raise DistutilsOptionError, \
+                      "target version can only be %s, or the '--skip-build'" \
+                      " option must be specified" % (short_version,)
+            self.target_version = short_version
+
+        self.set_undefined_options('bdist',
+                                   ('dist_dir', 'dist_dir'),
+                                   ('plat_name', 'plat_name'),
+                                  )
+
+        if self.install_script:
+            for script in self.distribution.scripts:
+                if self.install_script == os.path.basename(script):
+                    break
+            else:
+                raise DistutilsOptionError, \
+                      "install_script '%s' not found in scripts" % \
+                      self.install_script
+    # finalize_options()
+
+
+    def run (self):
+        if (sys.platform != "win32" and
+            (self.distribution.has_ext_modules() or
+             self.distribution.has_c_libraries())):
+            raise DistutilsPlatformError \
+                  ("distribution contains extensions and/or C libraries; "
+                   "must be compiled on a Windows 32 platform")
+
+        if not self.skip_build:
+            self.run_command('build')
+
+        install = self.reinitialize_command('install', reinit_subcommands=1)
+        install.root = self.bdist_dir
+        install.skip_build = self.skip_build
+        install.warn_dir = 0
+        install.plat_name = self.plat_name
+
+        install_lib = self.reinitialize_command('install_lib')
+        # we do not want to include pyc or pyo files
+        install_lib.compile = 0
+        install_lib.optimize = 0
+
+        if self.distribution.has_ext_modules():
+            # If we are building an installer for a Python version other
+            # than the one we are currently running, then we need to ensure
+            # our build_lib reflects the other Python version rather than ours.
+            # Note that for target_version!=sys.version, we must have skipped the
+            # build step, so there is no issue with enforcing the build of this
+            # version.
+            target_version = self.target_version
+            if not target_version:
+                assert self.skip_build, "Should have already checked this"
+                target_version = sys.version[0:3]
+            plat_specifier = ".%s-%s" % (self.plat_name, target_version)
+            build = self.get_finalized_command('build')
+            build.build_lib = os.path.join(build.build_base,
+                                           'lib' + plat_specifier)
+
+        # Use a custom scheme for the zip-file, because we have to decide
+        # at installation time which scheme to use.
+        for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
+            value = string.upper(key)
+            if key == 'headers':
+                value = value + '/Include/$dist_name'
+            setattr(install,
+                    'install_' + key,
+                    value)
+
+        log.info("installing to %s", self.bdist_dir)
+        install.ensure_finalized()
+
+        # avoid warning of 'install_lib' about installing
+        # into a directory not in sys.path
+        sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
+
+        install.run()
+
+        del sys.path[0]
+
+        # And make an archive relative to the root of the
+        # pseudo-installation tree.
+        from tempfile import mktemp
+        archive_basename = mktemp()
+        fullname = self.distribution.get_fullname()
+        arcname = self.make_archive(archive_basename, "zip",
+                                    root_dir=self.bdist_dir)
+        # create an exe containing the zip-file
+        self.create_exe(arcname, fullname, self.bitmap)
+        if self.distribution.has_ext_modules():
+            pyversion = get_python_version()
+        else:
+            pyversion = 'any'
+        self.distribution.dist_files.append(('bdist_wininst', pyversion,
+                                             self.get_installer_filename(fullname)))
+        # remove the zip-file again
+        log.debug("removing temporary file '%s'", arcname)
+        os.remove(arcname)
+
+        if not self.keep_temp:
+            remove_tree(self.bdist_dir, dry_run=self.dry_run)
+
+    # run()
+
+    def get_inidata (self):
+        # Return data describing the installation.
+
+        lines = []
+        metadata = self.distribution.metadata
+
+        # Write the [metadata] section.
+        lines.append("[metadata]")
+
+        # 'info' will be displayed in the installer's dialog box,
+        # describing the items to be installed.
+        info = (metadata.long_description or '') + '\n'
+
+        # Escape newline characters
+        def escape(s):
+            return string.replace(s, "\n", "\\n")
+
+        for name in ["author", "author_email", "description", "maintainer",
+                     "maintainer_email", "name", "url", "version"]:
+            data = getattr(metadata, name, "")
+            if data:
+                info = info + ("\n    %s: %s" % \
+                               (string.capitalize(name), escape(data)))
+                lines.append("%s=%s" % (name, escape(data)))
+
+        # The [setup] section contains entries controlling
+        # the installer runtime.
+        lines.append("\n[Setup]")
+        if self.install_script:
+            lines.append("install_script=%s" % self.install_script)
+        lines.append("info=%s" % escape(info))
+        lines.append("target_compile=%d" % (not self.no_target_compile))
+        lines.append("target_optimize=%d" % (not self.no_target_optimize))
+        if self.target_version:
+            lines.append("target_version=%s" % self.target_version)
+        if self.user_access_control:
+            lines.append("user_access_control=%s" % self.user_access_control)
+
+        title = self.title or self.distribution.get_fullname()
+        lines.append("title=%s" % escape(title))
+        import time
+        import distutils
+        build_info = "Built %s with distutils-%s" % \
+                     (time.ctime(time.time()), distutils.__version__)
+        lines.append("build_info=%s" % build_info)
+        return string.join(lines, "\n")
+
+    # get_inidata()
+
+    def create_exe (self, arcname, fullname, bitmap=None):
+        import struct
+
+        self.mkpath(self.dist_dir)
+
+        cfgdata = self.get_inidata()
+
+        installer_name = self.get_installer_filename(fullname)
+        self.announce("creating %s" % installer_name)
+
+        if bitmap:
+            bitmapdata = open(bitmap, "rb").read()
+            bitmaplen = len(bitmapdata)
+        else:
+            bitmaplen = 0
+
+        file = open(installer_name, "wb")
+        file.write(self.get_exe_bytes())
+        if bitmap:
+            file.write(bitmapdata)
+
+        # Convert cfgdata from unicode to ascii, mbcs encoded
+        try:
+            unicode
+        except NameError:
+            pass
+        else:
+            if isinstance(cfgdata, unicode):
+                cfgdata = cfgdata.encode("mbcs")
+
+        # Append the pre-install script
+        cfgdata = cfgdata + "\0"
+        if self.pre_install_script:
+            script_data = open(self.pre_install_script, "r").read()
+            cfgdata = cfgdata + script_data + "\n\0"
+        else:
+            # empty pre-install script
+            cfgdata = cfgdata + "\0"
+        file.write(cfgdata)
+
+        # The 'magic number' 0x1234567B is used to make sure that the
+        # binary layout of 'cfgdata' is what the wininst.exe binary
+        # expects.  If the layout changes, increment that number, make
+        # the corresponding changes to the wininst.exe sources, and
+        # recompile them.
+        header = struct.pack("<iii",
+                             0x1234567B,       # tag
+                             len(cfgdata),     # length
+                             bitmaplen,        # number of bytes in bitmap
+                             )
+        file.write(header)
+        file.write(open(arcname, "rb").read())
+
+    # create_exe()
+
+    def get_installer_filename(self, fullname):
+        # Factored out to allow overriding in subclasses
+        if self.target_version:
+            # if we create an installer for a specific python version,
+            # it's better to include this in the name
+            installer_name = os.path.join(self.dist_dir,
+                                          "%s.%s-py%s.exe" %
+                                           (fullname, self.plat_name, self.target_version))
+        else:
+            installer_name = os.path.join(self.dist_dir,
+                                          "%s.%s.exe" % (fullname, self.plat_name))
+        return installer_name
+    # get_installer_filename()
+
+    def get_exe_bytes (self):
+        from distutils.msvccompiler import get_build_version
+        # If a target-version other than the current version has been
+        # specified, then using the MSVC version from *this* build is no good.
+        # Without actually finding and executing the target version and parsing
+        # its sys.version, we just hard-code our knowledge of old versions.
+        # NOTE: Possible alternative is to allow "--target-version" to
+        # specify a Python executable rather than a simple version string.
+        # We can then execute this program to obtain any info we need, such
+        # as the real sys.version string for the build.
+        cur_version = get_python_version()
+        if self.target_version and self.target_version != cur_version:
+            # If the target version is *later* than us, then we assume they
+            # use what we use
+            # string compares seem wrong, but are what sysconfig.py itself uses
+            if self.target_version > cur_version:
+                bv = get_build_version()
+            else:
+                if self.target_version < "2.4":
+                    bv = 6.0
+                else:
+                    bv = 7.1
+        else:
+            # for current version - use authoritative check.
+            bv = get_build_version()
+
+        # wininst-x.y.exe is in the same directory as this file
+        directory = os.path.dirname(__file__)
+        # we must use a wininst-x.y.exe built with the same C compiler
+        # used for python.  XXX What about mingw, borland, and so on?
+
+        # if plat_name starts with "win" but is not "win32"
+        # we want to strip "win" and leave the rest (e.g. -amd64)
+        # for all other cases, we don't want any suffix
+        if self.plat_name != 'win32' and self.plat_name[:3] == 'win':
+            sfix = self.plat_name[3:]
+        else:
+            sfix = ''
+
+        filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix))
+        f = open(filename, "rb")
+        try:
+            return f.read()
+        finally:
+            f.close()
+# class bdist_wininst
diff --git a/src/main/resources/PythonLibs/distutils/command/build.py b/src/main/resources/PythonLibs/distutils/command/build.py
new file mode 100644
index 0000000000000000000000000000000000000000..f84bf359dc60938e79e1be7beca84051929aa2c7
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/build.py
@@ -0,0 +1,147 @@
+"""distutils.command.build
+
+Implements the Distutils 'build' command."""
+
+__revision__ = "$Id$"
+
+import sys, os
+
+from distutils.util import get_platform
+from distutils.core import Command
+from distutils.errors import DistutilsOptionError
+
+def show_compilers():
+    from distutils.ccompiler import show_compilers
+    show_compilers()
+
+class build(Command):
+
+    description = "build everything needed to install"
+
+    user_options = [
+        ('build-base=', 'b',
+         "base directory for build library"),
+        ('build-purelib=', None,
+         "build directory for platform-neutral distributions"),
+        ('build-platlib=', None,
+         "build directory for platform-specific distributions"),
+        ('build-lib=', None,
+         "build directory for all distribution (defaults to either " +
+         "build-purelib or build-platlib"),
+        ('build-scripts=', None,
+         "build directory for scripts"),
+        ('build-temp=', 't',
+         "temporary build directory"),
+        ('plat-name=', 'p',
+         "platform name to build for, if supported "
+         "(default: %s)" % get_platform()),
+        ('compiler=', 'c',
+         "specify the compiler type"),
+        ('debug', 'g',
+         "compile extensions and libraries with debugging information"),
+        ('force', 'f',
+         "forcibly build everything (ignore file timestamps)"),
+        ('executable=', 'e',
+         "specify final destination interpreter path (build.py)"),
+        ]
+
+    boolean_options = ['debug', 'force']
+
+    help_options = [
+        ('help-compiler', None,
+         "list available compilers", show_compilers),
+        ]
+
+    def initialize_options(self):
+        self.build_base = 'build'
+        # these are decided only after 'build_base' has its final value
+        # (unless overridden by the user or client)
+        self.build_purelib = None
+        self.build_platlib = None
+        self.build_lib = None
+        self.build_temp = None
+        self.build_scripts = None
+        self.compiler = None
+        self.plat_name = None
+        self.debug = None
+        self.force = 0
+        self.executable = None
+
+    def finalize_options(self):
+        if self.plat_name is None:
+            self.plat_name = get_platform()
+        else:
+            # plat-name only supported for windows (other platforms are
+            # supported via ./configure flags, if at all).  Avoid misleading
+            # other platforms.
+            if os.name != 'nt':
+                raise DistutilsOptionError(
+                            "--plat-name only supported on Windows (try "
+                            "using './configure --help' on your platform)")
+
+        plat_specifier = ".%s-%s" % (self.plat_name, sys.version[0:3])
+
+        # Make it so Python 2.x and Python 2.x with --with-pydebug don't
+        # share the same build directories. Doing so confuses the build
+        # process for C modules
+        if hasattr(sys, 'gettotalrefcount'):
+            plat_specifier += '-pydebug'
+
+        # 'build_purelib' and 'build_platlib' just default to 'lib' and
+        # 'lib.<plat>' under the base build directory.  We only use one of
+        # them for a given distribution, though --
+        if self.build_purelib is None:
+            self.build_purelib = os.path.join(self.build_base, 'lib')
+        if self.build_platlib is None:
+            self.build_platlib = os.path.join(self.build_base,
+                                              'lib' + plat_specifier)
+
+        # 'build_lib' is the actual directory that we will use for this
+        # particular module distribution -- if user didn't supply it, pick
+        # one of 'build_purelib' or 'build_platlib'.
+        if self.build_lib is None:
+            if self.distribution.ext_modules:
+                self.build_lib = self.build_platlib
+            else:
+                self.build_lib = self.build_purelib
+
+        # 'build_temp' -- temporary directory for compiler turds,
+        # "build/temp.<plat>"
+        if self.build_temp is None:
+            self.build_temp = os.path.join(self.build_base,
+                                           'temp' + plat_specifier)
+        if self.build_scripts is None:
+            self.build_scripts = os.path.join(self.build_base,
+                                              'scripts-' + sys.version[0:3])
+
+        if self.executable is None:
+            self.executable = os.path.normpath(sys.executable)
+
+    def run(self):
+        # Run all relevant sub-commands.  This will be some subset of:
+        #  - build_py      - pure Python modules
+        #  - build_clib    - standalone C libraries
+        #  - build_ext     - Python extensions
+        #  - build_scripts - (Python) scripts
+        for cmd_name in self.get_sub_commands():
+            self.run_command(cmd_name)
+
+    # -- Predicates for the sub-command list ---------------------------
+
+    def has_pure_modules (self):
+        return self.distribution.has_pure_modules()
+
+    def has_c_libraries (self):
+        return self.distribution.has_c_libraries()
+
+    def has_ext_modules (self):
+        return self.distribution.has_ext_modules()
+
+    def has_scripts (self):
+        return self.distribution.has_scripts()
+
+    sub_commands = [('build_py',      has_pure_modules),
+                    ('build_clib',    has_c_libraries),
+                    ('build_ext',     has_ext_modules),
+                    ('build_scripts', has_scripts),
+                   ]
diff --git a/src/main/resources/PythonLibs/distutils/command/build_clib.py b/src/main/resources/PythonLibs/distutils/command/build_clib.py
new file mode 100644
index 0000000000000000000000000000000000000000..205587e7fc96826da43641d748ed4a068928732c
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/build_clib.py
@@ -0,0 +1,209 @@
+"""distutils.command.build_clib
+
+Implements the Distutils 'build_clib' command, to build a C/C++ library
+that is included in the module distribution and needed by an extension
+module."""
+
+__revision__ = "$Id$"
+
+
+# XXX this module has *lots* of code ripped-off quite transparently from
+# build_ext.py -- not surprisingly really, as the work required to build
+# a static library from a collection of C source files is not really all
+# that different from what's required to build a shared object file from
+# a collection of C source files.  Nevertheless, I haven't done the
+# necessary refactoring to account for the overlap in code between the
+# two modules, mainly because a number of subtle details changed in the
+# cut 'n paste.  Sigh.
+
+import os
+from distutils.core import Command
+from distutils.errors import DistutilsSetupError
+from distutils.sysconfig import customize_compiler
+from distutils import log
+
+def show_compilers():
+    from distutils.ccompiler import show_compilers
+    show_compilers()
+
+
+class build_clib(Command):
+
+    description = "build C/C++ libraries used by Python extensions"
+
+    user_options = [
+        ('build-clib=', 'b',
+         "directory to build C/C++ libraries to"),
+        ('build-temp=', 't',
+         "directory to put temporary build by-products"),
+        ('debug', 'g',
+         "compile with debugging information"),
+        ('force', 'f',
+         "forcibly build everything (ignore file timestamps)"),
+        ('compiler=', 'c',
+         "specify the compiler type"),
+        ]
+
+    boolean_options = ['debug', 'force']
+
+    help_options = [
+        ('help-compiler', None,
+         "list available compilers", show_compilers),
+        ]
+
+    def initialize_options(self):
+        self.build_clib = None
+        self.build_temp = None
+
+        # List of libraries to build
+        self.libraries = None
+
+        # Compilation options for all libraries
+        self.include_dirs = None
+        self.define = None
+        self.undef = None
+        self.debug = None
+        self.force = 0
+        self.compiler = None
+
+
+    def finalize_options(self):
+        # This might be confusing: both build-clib and build-temp default
+        # to build-temp as defined by the "build" command.  This is because
+        # I think that C libraries are really just temporary build
+        # by-products, at least from the point of view of building Python
+        # extensions -- but I want to keep my options open.
+        self.set_undefined_options('build',
+                                   ('build_temp', 'build_clib'),
+                                   ('build_temp', 'build_temp'),
+                                   ('compiler', 'compiler'),
+                                   ('debug', 'debug'),
+                                   ('force', 'force'))
+
+        self.libraries = self.distribution.libraries
+        if self.libraries:
+            self.check_library_list(self.libraries)
+
+        if self.include_dirs is None:
+            self.include_dirs = self.distribution.include_dirs or []
+        if isinstance(self.include_dirs, str):
+            self.include_dirs = self.include_dirs.split(os.pathsep)
+
+        # XXX same as for build_ext -- what about 'self.define' and
+        # 'self.undef' ?
+
+    def run(self):
+        if not self.libraries:
+            return
+
+        # Yech -- this is cut 'n pasted from build_ext.py!
+        from distutils.ccompiler import new_compiler
+        self.compiler = new_compiler(compiler=self.compiler,
+                                     dry_run=self.dry_run,
+                                     force=self.force)
+        customize_compiler(self.compiler)
+
+        if self.include_dirs is not None:
+            self.compiler.set_include_dirs(self.include_dirs)
+        if self.define is not None:
+            # 'define' option is a list of (name,value) tuples
+            for (name,value) in self.define:
+                self.compiler.define_macro(name, value)
+        if self.undef is not None:
+            for macro in self.undef:
+                self.compiler.undefine_macro(macro)
+
+        self.build_libraries(self.libraries)
+
+
+    def check_library_list(self, libraries):
+        """Ensure that the list of libraries is valid.
+
+        `library` is presumably provided as a command option 'libraries'.
+        This method checks that it is a list of 2-tuples, where the tuples
+        are (library_name, build_info_dict).
+
+        Raise DistutilsSetupError if the structure is invalid anywhere;
+        just returns otherwise.
+        """
+        if not isinstance(libraries, list):
+            raise DistutilsSetupError, \
+                  "'libraries' option must be a list of tuples"
+
+        for lib in libraries:
+            if not isinstance(lib, tuple) and len(lib) != 2:
+                raise DistutilsSetupError, \
+                      "each element of 'libraries' must a 2-tuple"
+
+            name, build_info = lib
+
+            if not isinstance(name, str):
+                raise DistutilsSetupError, \
+                      "first element of each tuple in 'libraries' " + \
+                      "must be a string (the library name)"
+            if '/' in name or (os.sep != '/' and os.sep in name):
+                raise DistutilsSetupError, \
+                      ("bad library name '%s': " +
+                       "may not contain directory separators") % \
+                      lib[0]
+
+            if not isinstance(build_info, dict):
+                raise DistutilsSetupError, \
+                      "second element of each tuple in 'libraries' " + \
+                      "must be a dictionary (build info)"
+
+    def get_library_names(self):
+        # Assume the library list is valid -- 'check_library_list()' is
+        # called from 'finalize_options()', so it should be!
+        if not self.libraries:
+            return None
+
+        lib_names = []
+        for (lib_name, build_info) in self.libraries:
+            lib_names.append(lib_name)
+        return lib_names
+
+
+    def get_source_files(self):
+        self.check_library_list(self.libraries)
+        filenames = []
+        for (lib_name, build_info) in self.libraries:
+            sources = build_info.get('sources')
+            if sources is None or not isinstance(sources, (list, tuple)):
+                raise DistutilsSetupError, \
+                      ("in 'libraries' option (library '%s'), "
+                       "'sources' must be present and must be "
+                       "a list of source filenames") % lib_name
+
+            filenames.extend(sources)
+        return filenames
+
+    def build_libraries(self, libraries):
+        for (lib_name, build_info) in libraries:
+            sources = build_info.get('sources')
+            if sources is None or not isinstance(sources, (list, tuple)):
+                raise DistutilsSetupError, \
+                      ("in 'libraries' option (library '%s'), " +
+                       "'sources' must be present and must be " +
+                       "a list of source filenames") % lib_name
+            sources = list(sources)
+
+            log.info("building '%s' library", lib_name)
+
+            # First, compile the source code to object files in the library
+            # directory.  (This should probably change to putting object
+            # files in a temporary build directory.)
+            macros = build_info.get('macros')
+            include_dirs = build_info.get('include_dirs')
+            objects = self.compiler.compile(sources,
+                                            output_dir=self.build_temp,
+                                            macros=macros,
+                                            include_dirs=include_dirs,
+                                            debug=self.debug)
+
+            # Now "link" the object files together into a static library.
+            # (On Unix at least, this isn't really linking -- it just
+            # builds an archive.  Whatever.)
+            self.compiler.create_static_lib(objects, lib_name,
+                                            output_dir=self.build_clib,
+                                            debug=self.debug)
diff --git a/src/main/resources/PythonLibs/distutils/command/build_ext.py b/src/main/resources/PythonLibs/distutils/command/build_ext.py
new file mode 100644
index 0000000000000000000000000000000000000000..923197bac43674e86fdfb3970c8a730c8893c63a
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/build_ext.py
@@ -0,0 +1,768 @@
+"""distutils.command.build_ext
+
+Implements the Distutils 'build_ext' command, for building extension
+modules (currently limited to C extensions, should accommodate C++
+extensions ASAP)."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id$"
+
+import sys, os, string, re
+from types import *
+from site import USER_BASE, USER_SITE
+from distutils.core import Command
+from distutils.errors import *
+from distutils.sysconfig import customize_compiler, get_python_version
+from distutils.dep_util import newer_group
+from distutils.extension import Extension
+from distutils.util import get_platform
+from distutils import log
+
+if os.name == 'nt':
+    from distutils.msvccompiler import get_build_version
+    MSVC_VERSION = int(get_build_version())
+
+# An extension name is just a dot-separated list of Python NAMEs (ie.
+# the same as a fully-qualified module name).
+extension_name_re = re.compile \
+    (r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$')
+
+
+def show_compilers ():
+    from distutils.ccompiler import show_compilers
+    show_compilers()
+
+
+class build_ext (Command):
+
+    description = "build C/C++ extensions (compile/link to build directory)"
+
+    # XXX thoughts on how to deal with complex command-line options like
+    # these, i.e. how to make it so fancy_getopt can suck them off the
+    # command line and make it look like setup.py defined the appropriate
+    # lists of tuples of what-have-you.
+    #   - each command needs a callback to process its command-line options
+    #   - Command.__init__() needs access to its share of the whole
+    #     command line (must ultimately come from
+    #     Distribution.parse_command_line())
+    #   - it then calls the current command class' option-parsing
+    #     callback to deal with weird options like -D, which have to
+    #     parse the option text and churn out some custom data
+    #     structure
+    #   - that data structure (in this case, a list of 2-tuples)
+    #     will then be present in the command object by the time
+    #     we get to finalize_options() (i.e. the constructor
+    #     takes care of both command-line and client options
+    #     in between initialize_options() and finalize_options())
+
+    sep_by = " (separated by '%s')" % os.pathsep
+    user_options = [
+        ('build-lib=', 'b',
+         "directory for compiled extension modules"),
+        ('build-temp=', 't',
+         "directory for temporary files (build by-products)"),
+        ('plat-name=', 'p',
+         "platform name to cross-compile for, if supported "
+         "(default: %s)" % get_platform()),
+        ('inplace', 'i',
+         "ignore build-lib and put compiled extensions into the source " +
+         "directory alongside your pure Python modules"),
+        ('include-dirs=', 'I',
+         "list of directories to search for header files" + sep_by),
+        ('define=', 'D',
+         "C preprocessor macros to define"),
+        ('undef=', 'U',
+         "C preprocessor macros to undefine"),
+        ('libraries=', 'l',
+         "external C libraries to link with"),
+        ('library-dirs=', 'L',
+         "directories to search for external C libraries" + sep_by),
+        ('rpath=', 'R',
+         "directories to search for shared C libraries at runtime"),
+        ('link-objects=', 'O',
+         "extra explicit link objects to include in the link"),
+        ('debug', 'g',
+         "compile/link with debugging information"),
+        ('force', 'f',
+         "forcibly build everything (ignore file timestamps)"),
+        ('compiler=', 'c',
+         "specify the compiler type"),
+        ('swig-cpp', None,
+         "make SWIG create C++ files (default is C)"),
+        ('swig-opts=', None,
+         "list of SWIG command line options"),
+        ('swig=', None,
+         "path to the SWIG executable"),
+        ('user', None,
+         "add user include, library and rpath"),
+        ]
+
+    boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user']
+
+    help_options = [
+        ('help-compiler', None,
+         "list available compilers", show_compilers),
+        ]
+
+    def initialize_options (self):
+        self.extensions = None
+        self.build_lib = None
+        self.plat_name = None
+        self.build_temp = None
+        self.inplace = 0
+        self.package = None
+
+        self.include_dirs = None
+        self.define = None
+        self.undef = None
+        self.libraries = None
+        self.library_dirs = None
+        self.rpath = None
+        self.link_objects = None
+        self.debug = None
+        self.force = None
+        self.compiler = None
+        self.swig = None
+        self.swig_cpp = None
+        self.swig_opts = None
+        self.user = None
+
+    def finalize_options(self):
+        from distutils import sysconfig
+
+        self.set_undefined_options('build',
+                                   ('build_lib', 'build_lib'),
+                                   ('build_temp', 'build_temp'),
+                                   ('compiler', 'compiler'),
+                                   ('debug', 'debug'),
+                                   ('force', 'force'),
+                                   ('plat_name', 'plat_name'),
+                                   )
+
+        if self.package is None:
+            self.package = self.distribution.ext_package
+
+        self.extensions = self.distribution.ext_modules
+
+        # Make sure Python's include directories (for Python.h, pyconfig.h,
+        # etc.) are in the include search path.
+        py_include = sysconfig.get_python_inc()
+        plat_py_include = sysconfig.get_python_inc(plat_specific=1)
+        if self.include_dirs is None:
+            self.include_dirs = self.distribution.include_dirs or []
+        if isinstance(self.include_dirs, str):
+            self.include_dirs = self.include_dirs.split(os.pathsep)
+
+        # Put the Python "system" include dir at the end, so that
+        # any local include dirs take precedence.
+        self.include_dirs.append(py_include)
+        if plat_py_include != py_include:
+            self.include_dirs.append(plat_py_include)
+
+        self.ensure_string_list('libraries')
+
+        # Life is easier if we're not forever checking for None, so
+        # simplify these options to empty lists if unset
+        if self.libraries is None:
+            self.libraries = []
+        if self.library_dirs is None:
+            self.library_dirs = []
+        elif type(self.library_dirs) is StringType:
+            self.library_dirs = string.split(self.library_dirs, os.pathsep)
+
+        if self.rpath is None:
+            self.rpath = []
+        elif type(self.rpath) is StringType:
+            self.rpath = string.split(self.rpath, os.pathsep)
+
+        # for extensions under windows use different directories
+        # for Release and Debug builds.
+        # also Python's library directory must be appended to library_dirs
+        if os.name == 'nt':
+            # the 'libs' directory is for binary installs - we assume that
+            # must be the *native* platform.  But we don't really support
+            # cross-compiling via a binary install anyway, so we let it go.
+            self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
+            if self.debug:
+                self.build_temp = os.path.join(self.build_temp, "Debug")
+            else:
+                self.build_temp = os.path.join(self.build_temp, "Release")
+
+            # Append the source distribution include and library directories,
+            # this allows distutils on windows to work in the source tree
+            self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
+            if MSVC_VERSION == 9:
+                # Use the .lib files for the correct architecture
+                if self.plat_name == 'win32':
+                    suffix = ''
+                else:
+                    # win-amd64 or win-ia64
+                    suffix = self.plat_name[4:]
+                new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
+                if suffix:
+                    new_lib = os.path.join(new_lib, suffix)
+                self.library_dirs.append(new_lib)
+
+            elif MSVC_VERSION == 8:
+                self.library_dirs.append(os.path.join(sys.exec_prefix,
+                                         'PC', 'VS8.0'))
+            elif MSVC_VERSION == 7:
+                self.library_dirs.append(os.path.join(sys.exec_prefix,
+                                         'PC', 'VS7.1'))
+            else:
+                self.library_dirs.append(os.path.join(sys.exec_prefix,
+                                         'PC', 'VC6'))
+
+        # OS/2 (EMX) doesn't support Debug vs Release builds, but has the
+        # import libraries in its "Config" subdirectory
+        if os.name == 'os2':
+            self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config'))
+
+        # for extensions under Cygwin and AtheOS Python's library directory must be
+        # appended to library_dirs
+        if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos':
+            if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
+                # building third party extensions
+                self.library_dirs.append(os.path.join(sys.prefix, "lib",
+                                                      "python" + get_python_version(),
+                                                      "config"))
+            else:
+                # building python standard extensions
+                self.library_dirs.append('.')
+
+        # for extensions under Linux or Solaris with a shared Python library,
+        # Python's library directory must be appended to library_dirs
+        sysconfig.get_config_var('Py_ENABLE_SHARED')
+        if ((sys.platform.startswith('linux') or sys.platform.startswith('gnu')
+             or sys.platform.startswith('sunos'))
+            and sysconfig.get_config_var('Py_ENABLE_SHARED')):
+            if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
+                # building third party extensions
+                self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
+            else:
+                # building python standard extensions
+                self.library_dirs.append('.')
+
+        # The argument parsing will result in self.define being a string, but
+        # it has to be a list of 2-tuples.  All the preprocessor symbols
+        # specified by the 'define' option will be set to '1'.  Multiple
+        # symbols can be separated with commas.
+
+        if self.define:
+            defines = self.define.split(',')
+            self.define = map(lambda symbol: (symbol, '1'), defines)
+
+        # The option for macros to undefine is also a string from the
+        # option parsing, but has to be a list.  Multiple symbols can also
+        # be separated with commas here.
+        if self.undef:
+            self.undef = self.undef.split(',')
+
+        if self.swig_opts is None:
+            self.swig_opts = []
+        else:
+            self.swig_opts = self.swig_opts.split(' ')
+
+        # Finally add the user include and library directories if requested
+        if self.user:
+            user_include = os.path.join(USER_BASE, "include")
+            user_lib = os.path.join(USER_BASE, "lib")
+            if os.path.isdir(user_include):
+                self.include_dirs.append(user_include)
+            if os.path.isdir(user_lib):
+                self.library_dirs.append(user_lib)
+                self.rpath.append(user_lib)
+
+    def run(self):
+        from distutils.ccompiler import new_compiler
+
+        # 'self.extensions', as supplied by setup.py, is a list of
+        # Extension instances.  See the documentation for Extension (in
+        # distutils.extension) for details.
+        #
+        # For backwards compatibility with Distutils 0.8.2 and earlier, we
+        # also allow the 'extensions' list to be a list of tuples:
+        #    (ext_name, build_info)
+        # where build_info is a dictionary containing everything that
+        # Extension instances do except the name, with a few things being
+        # differently named.  We convert these 2-tuples to Extension
+        # instances as needed.
+
+        if not self.extensions:
+            return
+
+        # If we were asked to build any C/C++ libraries, make sure that the
+        # directory where we put them is in the library search path for
+        # linking extensions.
+        if self.distribution.has_c_libraries():
+            build_clib = self.get_finalized_command('build_clib')
+            self.libraries.extend(build_clib.get_library_names() or [])
+            self.library_dirs.append(build_clib.build_clib)
+
+        # Setup the CCompiler object that we'll use to do all the
+        # compiling and linking
+        self.compiler = new_compiler(compiler=self.compiler,
+                                     verbose=self.verbose,
+                                     dry_run=self.dry_run,
+                                     force=self.force)
+        customize_compiler(self.compiler)
+        # If we are cross-compiling, init the compiler now (if we are not
+        # cross-compiling, init would not hurt, but people may rely on
+        # late initialization of compiler even if they shouldn't...)
+        if os.name == 'nt' and self.plat_name != get_platform():
+            self.compiler.initialize(self.plat_name)
+
+        # And make sure that any compile/link-related options (which might
+        # come from the command-line or from the setup script) are set in
+        # that CCompiler object -- that way, they automatically apply to
+        # all compiling and linking done here.
+        if self.include_dirs is not None:
+            self.compiler.set_include_dirs(self.include_dirs)
+        if self.define is not None:
+            # 'define' option is a list of (name,value) tuples
+            for (name, value) in self.define:
+                self.compiler.define_macro(name, value)
+        if self.undef is not None:
+            for macro in self.undef:
+                self.compiler.undefine_macro(macro)
+        if self.libraries is not None:
+            self.compiler.set_libraries(self.libraries)
+        if self.library_dirs is not None:
+            self.compiler.set_library_dirs(self.library_dirs)
+        if self.rpath is not None:
+            self.compiler.set_runtime_library_dirs(self.rpath)
+        if self.link_objects is not None:
+            self.compiler.set_link_objects(self.link_objects)
+
+        # Now actually compile and link everything.
+        self.build_extensions()
+
+    def check_extensions_list(self, extensions):
+        """Ensure that the list of extensions (presumably provided as a
+        command option 'extensions') is valid, i.e. it is a list of
+        Extension objects.  We also support the old-style list of 2-tuples,
+        where the tuples are (ext_name, build_info), which are converted to
+        Extension instances here.
+
+        Raise DistutilsSetupError if the structure is invalid anywhere;
+        just returns otherwise.
+        """
+        if not isinstance(extensions, list):
+            raise DistutilsSetupError, \
+                  "'ext_modules' option must be a list of Extension instances"
+
+        for i, ext in enumerate(extensions):
+            if isinstance(ext, Extension):
+                continue                # OK! (assume type-checking done
+                                        # by Extension constructor)
+
+            if not isinstance(ext, tuple) or len(ext) != 2:
+                raise DistutilsSetupError, \
+                      ("each element of 'ext_modules' option must be an "
+                       "Extension instance or 2-tuple")
+
+            ext_name, build_info = ext
+
+            log.warn(("old-style (ext_name, build_info) tuple found in "
+                      "ext_modules for extension '%s'"
+                      "-- please convert to Extension instance" % ext_name))
+
+            if not (isinstance(ext_name, str) and
+                    extension_name_re.match(ext_name)):
+                raise DistutilsSetupError, \
+                      ("first element of each tuple in 'ext_modules' "
+                       "must be the extension name (a string)")
+
+            if not isinstance(build_info, dict):
+                raise DistutilsSetupError, \
+                      ("second element of each tuple in 'ext_modules' "
+                       "must be a dictionary (build info)")
+
+            # OK, the (ext_name, build_info) dict is type-safe: convert it
+            # to an Extension instance.
+            ext = Extension(ext_name, build_info['sources'])
+
+            # Easy stuff: one-to-one mapping from dict elements to
+            # instance attributes.
+            for key in ('include_dirs', 'library_dirs', 'libraries',
+                        'extra_objects', 'extra_compile_args',
+                        'extra_link_args'):
+                val = build_info.get(key)
+                if val is not None:
+                    setattr(ext, key, val)
+
+            # Medium-easy stuff: same syntax/semantics, different names.
+            ext.runtime_library_dirs = build_info.get('rpath')
+            if 'def_file' in build_info:
+                log.warn("'def_file' element of build info dict "
+                         "no longer supported")
+
+            # Non-trivial stuff: 'macros' split into 'define_macros'
+            # and 'undef_macros'.
+            macros = build_info.get('macros')
+            if macros:
+                ext.define_macros = []
+                ext.undef_macros = []
+                for macro in macros:
+                    if not (isinstance(macro, tuple) and len(macro) in (1, 2)):
+                        raise DistutilsSetupError, \
+                              ("'macros' element of build info dict "
+                               "must be 1- or 2-tuple")
+                    if len(macro) == 1:
+                        ext.undef_macros.append(macro[0])
+                    elif len(macro) == 2:
+                        ext.define_macros.append(macro)
+
+            extensions[i] = ext
+
+    def get_source_files(self):
+        self.check_extensions_list(self.extensions)
+        filenames = []
+
+        # Wouldn't it be neat if we knew the names of header files too...
+        for ext in self.extensions:
+            filenames.extend(ext.sources)
+
+        return filenames
+
+    def get_outputs(self):
+        # Sanity check the 'extensions' list -- can't assume this is being
+        # done in the same run as a 'build_extensions()' call (in fact, we
+        # can probably assume that it *isn't*!).
+        self.check_extensions_list(self.extensions)
+
+        # And build the list of output (built) filenames.  Note that this
+        # ignores the 'inplace' flag, and assumes everything goes in the
+        # "build" tree.
+        outputs = []
+        for ext in self.extensions:
+            outputs.append(self.get_ext_fullpath(ext.name))
+        return outputs
+
+    def build_extensions(self):
+        # First, sanity-check the 'extensions' list
+        self.check_extensions_list(self.extensions)
+
+        for ext in self.extensions:
+            self.build_extension(ext)
+
+    def build_extension(self, ext):
+        sources = ext.sources
+        if sources is None or type(sources) not in (ListType, TupleType):
+            raise DistutilsSetupError, \
+                  ("in 'ext_modules' option (extension '%s'), " +
+                   "'sources' must be present and must be " +
+                   "a list of source filenames") % ext.name
+        sources = list(sources)
+
+        ext_path = self.get_ext_fullpath(ext.name)
+        depends = sources + ext.depends
+        if not (self.force or newer_group(depends, ext_path, 'newer')):
+            log.debug("skipping '%s' extension (up-to-date)", ext.name)
+            return
+        else:
+            log.info("building '%s' extension", ext.name)
+
+        # First, scan the sources for SWIG definition files (.i), run
+        # SWIG on 'em to create .c files, and modify the sources list
+        # accordingly.
+        sources = self.swig_sources(sources, ext)
+
+        # Next, compile the source code to object files.
+
+        # XXX not honouring 'define_macros' or 'undef_macros' -- the
+        # CCompiler API needs to change to accommodate this, and I
+        # want to do one thing at a time!
+
+        # Two possible sources for extra compiler arguments:
+        #   - 'extra_compile_args' in Extension object
+        #   - CFLAGS environment variable (not particularly
+        #     elegant, but people seem to expect it and I
+        #     guess it's useful)
+        # The environment variable should take precedence, and
+        # any sensible compiler will give precedence to later
+        # command line args.  Hence we combine them in order:
+        extra_args = ext.extra_compile_args or []
+
+        macros = ext.define_macros[:]
+        for undef in ext.undef_macros:
+            macros.append((undef,))
+
+        objects = self.compiler.compile(sources,
+                                         output_dir=self.build_temp,
+                                         macros=macros,
+                                         include_dirs=ext.include_dirs,
+                                         debug=self.debug,
+                                         extra_postargs=extra_args,
+                                         depends=ext.depends)
+
+        # XXX -- this is a Vile HACK!
+        #
+        # The setup.py script for Python on Unix needs to be able to
+        # get this list so it can perform all the clean up needed to
+        # avoid keeping object files around when cleaning out a failed
+        # build of an extension module.  Since Distutils does not
+        # track dependencies, we have to get rid of intermediates to
+        # ensure all the intermediates will be properly re-built.
+        #
+        self._built_objects = objects[:]
+
+        # Now link the object files together into a "shared object" --
+        # of course, first we have to figure out all the other things
+        # that go into the mix.
+        if ext.extra_objects:
+            objects.extend(ext.extra_objects)
+        extra_args = ext.extra_link_args or []
+
+        # Detect target language, if not provided
+        language = ext.language or self.compiler.detect_language(sources)
+
+        self.compiler.link_shared_object(
+            objects, ext_path,
+            libraries=self.get_libraries(ext),
+            library_dirs=ext.library_dirs,
+            runtime_library_dirs=ext.runtime_library_dirs,
+            extra_postargs=extra_args,
+            export_symbols=self.get_export_symbols(ext),
+            debug=self.debug,
+            build_temp=self.build_temp,
+            target_lang=language)
+
+
+    def swig_sources (self, sources, extension):
+
+        """Walk the list of source files in 'sources', looking for SWIG
+        interface (.i) files.  Run SWIG on all that are found, and
+        return a modified 'sources' list with SWIG source files replaced
+        by the generated C (or C++) files.
+        """
+
+        new_sources = []
+        swig_sources = []
+        swig_targets = {}
+
+        # XXX this drops generated C/C++ files into the source tree, which
+        # is fine for developers who want to distribute the generated
+        # source -- but there should be an option to put SWIG output in
+        # the temp dir.
+
+        if self.swig_cpp:
+            log.warn("--swig-cpp is deprecated - use --swig-opts=-c++")
+
+        if self.swig_cpp or ('-c++' in self.swig_opts) or \
+           ('-c++' in extension.swig_opts):
+            target_ext = '.cpp'
+        else:
+            target_ext = '.c'
+
+        for source in sources:
+            (base, ext) = os.path.splitext(source)
+            if ext == ".i":             # SWIG interface file
+                new_sources.append(base + '_wrap' + target_ext)
+                swig_sources.append(source)
+                swig_targets[source] = new_sources[-1]
+            else:
+                new_sources.append(source)
+
+        if not swig_sources:
+            return new_sources
+
+        swig = self.swig or self.find_swig()
+        swig_cmd = [swig, "-python"]
+        swig_cmd.extend(self.swig_opts)
+        if self.swig_cpp:
+            swig_cmd.append("-c++")
+
+        # Do not override commandline arguments
+        if not self.swig_opts:
+            for o in extension.swig_opts:
+                swig_cmd.append(o)
+
+        for source in swig_sources:
+            target = swig_targets[source]
+            log.info("swigging %s to %s", source, target)
+            self.spawn(swig_cmd + ["-o", target, source])
+
+        return new_sources
+
+    # swig_sources ()
+
+    def find_swig (self):
+        """Return the name of the SWIG executable.  On Unix, this is
+        just "swig" -- it should be in the PATH.  Tries a bit harder on
+        Windows.
+        """
+
+        if os.name == "posix":
+            return "swig"
+        elif os.name == "nt":
+
+            # Look for SWIG in its standard installation directory on
+            # Windows (or so I presume!).  If we find it there, great;
+            # if not, act like Unix and assume it's in the PATH.
+            for vers in ("1.3", "1.2", "1.1"):
+                fn = os.path.join("c:\\swig%s" % vers, "swig.exe")
+                if os.path.isfile(fn):
+                    return fn
+            else:
+                return "swig.exe"
+
+        elif os.name == "os2":
+            # assume swig available in the PATH.
+            return "swig.exe"
+
+        else:
+            raise DistutilsPlatformError, \
+                  ("I don't know how to find (much less run) SWIG "
+                   "on platform '%s'") % os.name
+
+    # find_swig ()
+
+    # -- Name generators -----------------------------------------------
+    # (extension names, filenames, whatever)
+    def get_ext_fullpath(self, ext_name):
+        """Returns the path of the filename for a given extension.
+
+        The file is located in `build_lib` or directly in the package
+        (inplace option).
+        """
+        # makes sure the extension name is only using dots
+        all_dots = string.maketrans('/'+os.sep, '..')
+        ext_name = ext_name.translate(all_dots)
+
+        fullname = self.get_ext_fullname(ext_name)
+        modpath = fullname.split('.')
+        filename = self.get_ext_filename(ext_name)
+        filename = os.path.split(filename)[-1]
+
+        if not self.inplace:
+            # no further work needed
+            # returning :
+            #   build_dir/package/path/filename
+            filename = os.path.join(*modpath[:-1]+[filename])
+            return os.path.join(self.build_lib, filename)
+
+        # the inplace option requires to find the package directory
+        # using the build_py command for that
+        package = '.'.join(modpath[0:-1])
+        build_py = self.get_finalized_command('build_py')
+        package_dir = os.path.abspath(build_py.get_package_dir(package))
+
+        # returning
+        #   package_dir/filename
+        return os.path.join(package_dir, filename)
+
+    def get_ext_fullname(self, ext_name):
+        """Returns the fullname of a given extension name.
+
+        Adds the `package.` prefix"""
+        if self.package is None:
+            return ext_name
+        else:
+            return self.package + '.' + ext_name
+
+    def get_ext_filename(self, ext_name):
+        r"""Convert the name of an extension (eg. "foo.bar") into the name
+        of the file from which it will be loaded (eg. "foo/bar.so", or
+        "foo\bar.pyd").
+        """
+        from distutils.sysconfig import get_config_var
+        ext_path = string.split(ext_name, '.')
+        # OS/2 has an 8 character module (extension) limit :-(
+        if os.name == "os2":
+            ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8]
+        # extensions in debug_mode are named 'module_d.pyd' under windows
+        so_ext = get_config_var('SO')
+        if os.name == 'nt' and self.debug:
+            return os.path.join(*ext_path) + '_d' + so_ext
+        return os.path.join(*ext_path) + so_ext
+
+    def get_export_symbols (self, ext):
+        """Return the list of symbols that a shared extension has to
+        export.  This either uses 'ext.export_symbols' or, if it's not
+        provided, "init" + module_name.  Only relevant on Windows, where
+        the .pyd file (DLL) must export the module "init" function.
+        """
+        initfunc_name = "init" + ext.name.split('.')[-1]
+        if initfunc_name not in ext.export_symbols:
+            ext.export_symbols.append(initfunc_name)
+        return ext.export_symbols
+
+    def get_libraries (self, ext):
+        """Return the list of libraries to link against when building a
+        shared extension.  On most platforms, this is just 'ext.libraries';
+        on Windows and OS/2, we add the Python library (eg. python20.dll).
+        """
+        # The python library is always needed on Windows.  For MSVC, this
+        # is redundant, since the library is mentioned in a pragma in
+        # pyconfig.h that MSVC groks.  The other Windows compilers all seem
+        # to need it mentioned explicitly, though, so that's what we do.
+        # Append '_d' to the python import library on debug builds.
+        if sys.platform == "win32":
+            from distutils.msvccompiler import MSVCCompiler
+            if not isinstance(self.compiler, MSVCCompiler):
+                template = "python%d%d"
+                if self.debug:
+                    template = template + '_d'
+                pythonlib = (template %
+                       (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+                # don't extend ext.libraries, it may be shared with other
+                # extensions, it is a reference to the original list
+                return ext.libraries + [pythonlib]
+            else:
+                return ext.libraries
+        elif sys.platform == "os2emx":
+            # EMX/GCC requires the python library explicitly, and I
+            # believe VACPP does as well (though not confirmed) - AIM Apr01
+            template = "python%d%d"
+            # debug versions of the main DLL aren't supported, at least
+            # not at this time - AIM Apr01
+            #if self.debug:
+            #    template = template + '_d'
+            pythonlib = (template %
+                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            # don't extend ext.libraries, it may be shared with other
+            # extensions, it is a reference to the original list
+            return ext.libraries + [pythonlib]
+        elif sys.platform[:6] == "cygwin":
+            template = "python%d.%d"
+            pythonlib = (template %
+                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            # don't extend ext.libraries, it may be shared with other
+            # extensions, it is a reference to the original list
+            return ext.libraries + [pythonlib]
+        elif sys.platform[:6] == "atheos":
+            from distutils import sysconfig
+
+            template = "python%d.%d"
+            pythonlib = (template %
+                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            # Get SHLIBS from Makefile
+            extra = []
+            for lib in sysconfig.get_config_var('SHLIBS').split():
+                if lib.startswith('-l'):
+                    extra.append(lib[2:])
+                else:
+                    extra.append(lib)
+            # don't extend ext.libraries, it may be shared with other
+            # extensions, it is a reference to the original list
+            return ext.libraries + [pythonlib, "m"] + extra
+
+        elif sys.platform == 'darwin':
+            # Don't use the default code below
+            return ext.libraries
+        elif sys.platform[:3] == 'aix':
+            # Don't use the default code below
+            return ext.libraries
+        else:
+            from distutils import sysconfig
+            if sysconfig.get_config_var('Py_ENABLE_SHARED'):
+                template = "python%d.%d"
+                pythonlib = (template %
+                             (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+                return ext.libraries + [pythonlib]
+            else:
+                return ext.libraries
+
+# class build_ext
diff --git a/src/main/resources/PythonLibs/distutils/command/build_py.py b/src/main/resources/PythonLibs/distutils/command/build_py.py
new file mode 100644
index 0000000000000000000000000000000000000000..04c455f0eb9a2efda0d6d199010f96bff26f3fe5
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/build_py.py
@@ -0,0 +1,393 @@
+"""distutils.command.build_py
+
+Implements the Distutils 'build_py' command."""
+
+__revision__ = "$Id$"
+
+import os
+import sys
+from glob import glob
+
+from distutils.core import Command
+from distutils.errors import DistutilsOptionError, DistutilsFileError
+from distutils.util import convert_path
+from distutils import log
+
+class build_py(Command):
+
+    description = "\"build\" pure Python modules (copy to build directory)"
+
+    user_options = [
+        ('build-lib=', 'd', "directory to \"build\" (copy) to"),
+        ('compile', 'c', "compile .py to .pyc"),
+        ('no-compile', None, "don't compile .py files [default]"),
+        ('optimize=', 'O',
+         "also compile with optimization: -O1 for \"python -O\", "
+         "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
+        ('force', 'f', "forcibly build everything (ignore file timestamps)"),
+        ]
+
+    boolean_options = ['compile', 'force']
+    negative_opt = {'no-compile' : 'compile'}
+
+    def initialize_options(self):
+        self.build_lib = None
+        self.py_modules = None
+        self.package = None
+        self.package_data = None
+        self.package_dir = None
+        self.compile = 0
+        self.optimize = 0
+        self.force = None
+
+    def finalize_options(self):
+        self.set_undefined_options('build',
+                                   ('build_lib', 'build_lib'),
+                                   ('force', 'force'))
+
+        # Get the distribution options that are aliases for build_py
+        # options -- list of packages and list of modules.
+        self.packages = self.distribution.packages
+        self.py_modules = self.distribution.py_modules
+        self.package_data = self.distribution.package_data
+        self.package_dir = {}
+        if self.distribution.package_dir:
+            for name, path in self.distribution.package_dir.items():
+                self.package_dir[name] = convert_path(path)
+        self.data_files = self.get_data_files()
+
+        # Ick, copied straight from install_lib.py (fancy_getopt needs a
+        # type system!  Hell, *everything* needs a type system!!!)
+        if not isinstance(self.optimize, int):
+            try:
+                self.optimize = int(self.optimize)
+                assert 0 <= self.optimize <= 2
+            except (ValueError, AssertionError):
+                raise DistutilsOptionError("optimize must be 0, 1, or 2")
+
+    def run(self):
+        # XXX copy_file by default preserves atime and mtime.  IMHO this is
+        # the right thing to do, but perhaps it should be an option -- in
+        # particular, a site administrator might want installed files to
+        # reflect the time of installation rather than the last
+        # modification time before the installed release.
+
+        # XXX copy_file by default preserves mode, which appears to be the
+        # wrong thing to do: if a file is read-only in the working
+        # directory, we want it to be installed read/write so that the next
+        # installation of the same module distribution can overwrite it
+        # without problems.  (This might be a Unix-specific issue.)  Thus
+        # we turn off 'preserve_mode' when copying to the build directory,
+        # since the build directory is supposed to be exactly what the
+        # installation will look like (ie. we preserve mode when
+        # installing).
+
+        # Two options control which modules will be installed: 'packages'
+        # and 'py_modules'.  The former lets us work with whole packages, not
+        # specifying individual modules at all; the latter is for
+        # specifying modules one-at-a-time.
+
+        if self.py_modules:
+            self.build_modules()
+        if self.packages:
+            self.build_packages()
+            self.build_package_data()
+
+        self.byte_compile(self.get_outputs(include_bytecode=0))
+
+    def get_data_files(self):
+        """Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
+        data = []
+        if not self.packages:
+            return data
+        for package in self.packages:
+            # Locate package source directory
+            src_dir = self.get_package_dir(package)
+
+            # Compute package build directory
+            build_dir = os.path.join(*([self.build_lib] + package.split('.')))
+
+            # Length of path to strip from found files
+            plen = 0
+            if src_dir:
+                plen = len(src_dir)+1
+
+            # Strip directory from globbed filenames
+            filenames = [
+                file[plen:] for file in self.find_data_files(package, src_dir)
+                ]
+            data.append((package, src_dir, build_dir, filenames))
+        return data
+
+    def find_data_files(self, package, src_dir):
+        """Return filenames for package's data files in 'src_dir'"""
+        globs = (self.package_data.get('', [])
+                 + self.package_data.get(package, []))
+        files = []
+        for pattern in globs:
+            # Each pattern has to be converted to a platform-specific path
+            filelist = glob(os.path.join(src_dir, convert_path(pattern)))
+            # Files that match more than one pattern are only added once
+            files.extend([fn for fn in filelist if fn not in files])
+        return files
+
+    def build_package_data(self):
+        """Copy data files into build directory"""
+        for package, src_dir, build_dir, filenames in self.data_files:
+            for filename in filenames:
+                target = os.path.join(build_dir, filename)
+                self.mkpath(os.path.dirname(target))
+                self.copy_file(os.path.join(src_dir, filename), target,
+                               preserve_mode=False)
+
+    def get_package_dir(self, package):
+        """Return the directory, relative to the top of the source
+           distribution, where package 'package' should be found
+           (at least according to the 'package_dir' option, if any)."""
+
+        path = package.split('.')
+
+        if not self.package_dir:
+            if path:
+                return os.path.join(*path)
+            else:
+                return ''
+        else:
+            tail = []
+            while path:
+                try:
+                    pdir = self.package_dir['.'.join(path)]
+                except KeyError:
+                    tail.insert(0, path[-1])
+                    del path[-1]
+                else:
+                    tail.insert(0, pdir)
+                    return os.path.join(*tail)
+            else:
+                # Oops, got all the way through 'path' without finding a
+                # match in package_dir.  If package_dir defines a directory
+                # for the root (nameless) package, then fallback on it;
+                # otherwise, we might as well have not consulted
+                # package_dir at all, as we just use the directory implied
+                # by 'tail' (which should be the same as the original value
+                # of 'path' at this point).
+                pdir = self.package_dir.get('')
+                if pdir is not None:
+                    tail.insert(0, pdir)
+
+                if tail:
+                    return os.path.join(*tail)
+                else:
+                    return ''
+
+    def check_package(self, package, package_dir):
+        # Empty dir name means current directory, which we can probably
+        # assume exists.  Also, os.path.exists and isdir don't know about
+        # my "empty string means current dir" convention, so we have to
+        # circumvent them.
+        if package_dir != "":
+            if not os.path.exists(package_dir):
+                raise DistutilsFileError(
+                      "package directory '%s' does not exist" % package_dir)
+            if not os.path.isdir(package_dir):
+                raise DistutilsFileError(
+                       "supposed package directory '%s' exists, "
+                       "but is not a directory" % package_dir)
+
+        # Require __init__.py for all but the "root package"
+        if package:
+            init_py = os.path.join(package_dir, "__init__.py")
+            if os.path.isfile(init_py):
+                return init_py
+            else:
+                log.warn(("package init file '%s' not found " +
+                          "(or not a regular file)"), init_py)
+
+        # Either not in a package at all (__init__.py not expected), or
+        # __init__.py doesn't exist -- so don't return the filename.
+        return None
+
+    def check_module(self, module, module_file):
+        if not os.path.isfile(module_file):
+            log.warn("file %s (for module %s) not found", module_file, module)
+            return False
+        else:
+            return True
+
+    def find_package_modules(self, package, package_dir):
+        self.check_package(package, package_dir)
+        module_files = glob(os.path.join(package_dir, "*.py"))
+        modules = []
+        setup_script = os.path.abspath(self.distribution.script_name)
+
+        for f in module_files:
+            abs_f = os.path.abspath(f)
+            if abs_f != setup_script:
+                module = os.path.splitext(os.path.basename(f))[0]
+                modules.append((package, module, f))
+            else:
+                self.debug_print("excluding %s" % setup_script)
+        return modules
+
+    def find_modules(self):
+        """Finds individually-specified Python modules, ie. those listed by
+        module name in 'self.py_modules'.  Returns a list of tuples (package,
+        module_base, filename): 'package' is a tuple of the path through
+        package-space to the module; 'module_base' is the bare (no
+        packages, no dots) module name, and 'filename' is the path to the
+        ".py" file (relative to the distribution root) that implements the
+        module.
+        """
+        # Map package names to tuples of useful info about the package:
+        #    (package_dir, checked)
+        # package_dir - the directory where we'll find source files for
+        #   this package
+        # checked - true if we have checked that the package directory
+        #   is valid (exists, contains __init__.py, ... ?)
+        packages = {}
+
+        # List of (package, module, filename) tuples to return
+        modules = []
+
+        # We treat modules-in-packages almost the same as toplevel modules,
+        # just the "package" for a toplevel is empty (either an empty
+        # string or empty list, depending on context).  Differences:
+        #   - don't check for __init__.py in directory for empty package
+        for module in self.py_modules:
+            path = module.split('.')
+            package = '.'.join(path[0:-1])
+            module_base = path[-1]
+
+            try:
+                (package_dir, checked) = packages[package]
+            except KeyError:
+                package_dir = self.get_package_dir(package)
+                checked = 0
+
+            if not checked:
+                init_py = self.check_package(package, package_dir)
+                packages[package] = (package_dir, 1)
+                if init_py:
+                    modules.append((package, "__init__", init_py))
+
+            # XXX perhaps we should also check for just .pyc files
+            # (so greedy closed-source bastards can distribute Python
+            # modules too)
+            module_file = os.path.join(package_dir, module_base + ".py")
+            if not self.check_module(module, module_file):
+                continue
+
+            modules.append((package, module_base, module_file))
+
+        return modules
+
+    def find_all_modules(self):
+        """Compute the list of all modules that will be built, whether
+        they are specified one-module-at-a-time ('self.py_modules') or
+        by whole packages ('self.packages').  Return a list of tuples
+        (package, module, module_file), just like 'find_modules()' and
+        'find_package_modules()' do."""
+        modules = []
+        if self.py_modules:
+            modules.extend(self.find_modules())
+        if self.packages:
+            for package in self.packages:
+                package_dir = self.get_package_dir(package)
+                m = self.find_package_modules(package, package_dir)
+                modules.extend(m)
+        return modules
+
+    def get_source_files(self):
+        return [module[-1] for module in self.find_all_modules()]
+
+    def get_module_outfile(self, build_dir, package, module):
+        outfile_path = [build_dir] + list(package) + [module + ".py"]
+        return os.path.join(*outfile_path)
+
+    def get_outputs(self, include_bytecode=1):
+        modules = self.find_all_modules()
+        outputs = []
+        for (package, module, module_file) in modules:
+            package = package.split('.')
+            filename = self.get_module_outfile(self.build_lib, package, module)
+            outputs.append(filename)
+            if include_bytecode:
+                if self.compile:
+                    outputs.append(filename + "c")
+                if self.optimize > 0:
+                    outputs.append(filename + "o")
+
+        outputs += [
+            os.path.join(build_dir, filename)
+            for package, src_dir, build_dir, filenames in self.data_files
+            for filename in filenames
+            ]
+
+        return outputs
+
+    def build_module(self, module, module_file, package):
+        if isinstance(package, str):
+            package = package.split('.')
+        elif not isinstance(package, (list, tuple)):
+            raise TypeError(
+                  "'package' must be a string (dot-separated), list, or tuple")
+
+        # Now put the module source file into the "build" area -- this is
+        # easy, we just copy it somewhere under self.build_lib (the build
+        # directory for Python source).
+        outfile = self.get_module_outfile(self.build_lib, package, module)
+        dir = os.path.dirname(outfile)
+        self.mkpath(dir)
+        return self.copy_file(module_file, outfile, preserve_mode=0)
+
+    def build_modules(self):
+        modules = self.find_modules()
+        for (package, module, module_file) in modules:
+
+            # Now "build" the module -- ie. copy the source file to
+            # self.build_lib (the build directory for Python source).
+            # (Actually, it gets copied to the directory for this package
+            # under self.build_lib.)
+            self.build_module(module, module_file, package)
+
+    def build_packages(self):
+        for package in self.packages:
+
+            # Get list of (package, module, module_file) tuples based on
+            # scanning the package directory.  'package' is only included
+            # in the tuple so that 'find_modules()' and
+            # 'find_package_tuples()' have a consistent interface; it's
+            # ignored here (apart from a sanity check).  Also, 'module' is
+            # the *unqualified* module name (ie. no dots, no package -- we
+            # already know its package!), and 'module_file' is the path to
+            # the .py file, relative to the current directory
+            # (ie. including 'package_dir').
+            package_dir = self.get_package_dir(package)
+            modules = self.find_package_modules(package, package_dir)
+
+            # Now loop over the modules we found, "building" each one (just
+            # copy it to self.build_lib).
+            for (package_, module, module_file) in modules:
+                assert package == package_
+                self.build_module(module, module_file, package)
+
+    def byte_compile(self, files):
+        if sys.dont_write_bytecode:
+            self.warn('byte-compiling is disabled, skipping.')
+            return
+
+        from distutils.util import byte_compile
+        prefix = self.build_lib
+        if prefix[-1] != os.sep:
+            prefix = prefix + os.sep
+
+        # XXX this code is essentially the same as the 'byte_compile()
+        # method of the "install_lib" command, except for the determination
+        # of the 'prefix' string.  Hmmm.
+
+        if self.compile:
+            byte_compile(files, optimize=0,
+                         force=self.force, prefix=prefix, dry_run=self.dry_run)
+        if self.optimize > 0:
+            byte_compile(files, optimize=self.optimize,
+                         force=self.force, prefix=prefix, dry_run=self.dry_run)
diff --git a/src/main/resources/PythonLibs/distutils/command/build_scripts.py b/src/main/resources/PythonLibs/distutils/command/build_scripts.py
new file mode 100644
index 0000000000000000000000000000000000000000..35755a1a7de469076776074d1e49a9dd6ed4affc
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/build_scripts.py
@@ -0,0 +1,158 @@
+"""distutils.command.build_scripts
+
+Implements the Distutils 'build_scripts' command."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: build_scripts.py 59668 2008-01-02 18:59:36Z guido.van.rossum $"
+
+import sys, os, re
+from stat import ST_MODE
+from distutils import sysconfig
+from distutils.core import Command
+from distutils.dep_util import newer
+from distutils.util import convert_path
+from distutils import log
+
+# check if Python is called on the first line with this expression
+first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
+
+class build_scripts (Command):
+
+    description = "\"build\" scripts (copy and fixup #! line)"
+
+    user_options = [
+        ('build-dir=', 'd', "directory to \"build\" (copy) to"),
+        ('force', 'f', "forcibly build everything (ignore file timestamps"),
+        ('executable=', 'e', "specify final destination interpreter path"),
+        ]
+
+    boolean_options = ['force']
+
+
+    def initialize_options (self):
+        self.build_dir = None
+        self.scripts = None
+        self.force = None
+        self.executable = None
+        self.outfiles = None
+
+    def finalize_options (self):
+        self.set_undefined_options('build',
+                                   ('build_scripts', 'build_dir'),
+                                   ('force', 'force'),
+                                   ('executable', 'executable'))
+        self.scripts = self.distribution.scripts
+
+    def get_source_files(self):
+        return self.scripts
+
+    def run (self):
+        if not self.scripts:
+            return
+        self.copy_scripts()
+
+
+    def copy_scripts (self):
+        """Copy each script listed in 'self.scripts'; if it's marked as a
+        Python script in the Unix way (first line matches 'first_line_re',
+        ie. starts with "\#!" and contains "python"), then adjust the first
+        line to refer to the current Python interpreter as we copy.
+        """
+        self.mkpath(self.build_dir)
+        outfiles = []
+        for script in self.scripts:
+            adjust = 0
+            script = convert_path(script)
+            outfile = os.path.join(self.build_dir, os.path.basename(script))
+            outfiles.append(outfile)
+
+            if not self.force and not newer(script, outfile):
+                log.debug("not copying %s (up-to-date)", script)
+                continue
+
+            # Always open the file, but ignore failures in dry-run mode --
+            # that way, we'll get accurate feedback if we can read the
+            # script.
+            try:
+                f = open(script, "r")
+            except IOError:
+                if not self.dry_run:
+                    raise
+                f = None
+            else:
+                first_line = f.readline()
+                if not first_line:
+                    self.warn("%s is an empty file (skipping)" % script)
+                    continue
+
+                match = first_line_re.match(first_line)
+                if match:
+                    adjust = 1
+                    post_interp = match.group(1) or ''
+
+            if adjust:
+                log.info("copying and adjusting %s -> %s", script,
+                         self.build_dir)
+                if not sysconfig.python_build:
+                    executable = self.executable
+                else:
+                    executable = os.path.join(
+                        sysconfig.get_config_var("BINDIR"),
+                        "python" + sysconfig.get_config_var("EXE"))
+                executable = fix_jython_executable(executable, post_interp)
+                if not self.dry_run:
+                    outf = open(outfile, "w")
+                    outf.write("#!%s%s\n" %
+                               (executable,
+                                post_interp))
+                    outf.writelines(f.readlines())
+                    outf.close()
+                if f:
+                    f.close()
+            else:
+                if f:
+                    f.close()
+                self.copy_file(script, outfile)
+
+        if hasattr(os, 'chmod'):
+            for file in outfiles:
+                if self.dry_run:
+                    log.info("changing mode of %s", file)
+                else:
+                    oldmode = os.stat(file)[ST_MODE] & 07777
+                    newmode = (oldmode | 0555) & 07777
+                    if newmode != oldmode:
+                        log.info("changing mode of %s from %o to %o",
+                                 file, oldmode, newmode)
+                        os.chmod(file, newmode)
+
+    # copy_scripts ()
+
+# class build_scripts
+
+
+def is_sh(executable):
+    """Determine if the specified executable is a .sh (contains a #! line)"""
+    try:
+        fp = open(executable)
+        magic = fp.read(2)
+        fp.close()
+    except IOError, OSError:
+        return executable
+    return magic == '#!'
+
+
+def fix_jython_executable(executable, options):
+    if sys.platform.startswith('java') and is_sh(executable):
+        # Workaround Jython's sys.executable being a .sh (an invalid
+        # shebang line interpreter)
+        if options:
+            # Can't apply the workaround, leave it broken
+            log.warn("WARNING: Unable to adapt shebang line for Jython,"
+                             " the following script is NOT executable\n"
+                     "         see http://bugs.jython.org/issue1112 for"
+                             " more information.")
+        else:
+            return '/usr/bin/env %s' % executable
+    return executable
diff --git a/src/main/resources/PythonLibs/distutils/command/check.py b/src/main/resources/PythonLibs/distutils/command/check.py
new file mode 100644
index 0000000000000000000000000000000000000000..152bf0de98bf705261dc5b7a3ab9f5ed4ad82652
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/check.py
@@ -0,0 +1,149 @@
+"""distutils.command.check
+
+Implements the Distutils 'check' command.
+"""
+__revision__ = "$Id$"
+
+from distutils.core import Command
+from distutils.dist import PKG_INFO_ENCODING
+from distutils.errors import DistutilsSetupError
+
+try:
+    # docutils is installed
+    from docutils.utils import Reporter
+    from docutils.parsers.rst import Parser
+    from docutils import frontend
+    from docutils import nodes
+    from StringIO import StringIO
+
+    class SilentReporter(Reporter):
+
+        def __init__(self, source, report_level, halt_level, stream=None,
+                     debug=0, encoding='ascii', error_handler='replace'):
+            self.messages = []
+            Reporter.__init__(self, source, report_level, halt_level, stream,
+                              debug, encoding, error_handler)
+
+        def system_message(self, level, message, *children, **kwargs):
+            self.messages.append((level, message, children, kwargs))
+            return nodes.system_message(message, level=level,
+                                        type=self.levels[level],
+                                        *children, **kwargs)
+
+    HAS_DOCUTILS = True
+except ImportError:
+    # docutils is not installed
+    HAS_DOCUTILS = False
+
+class check(Command):
+    """This command checks the meta-data of the package.
+    """
+    description = ("perform some checks on the package")
+    user_options = [('metadata', 'm', 'Verify meta-data'),
+                    ('restructuredtext', 'r',
+                     ('Checks if long string meta-data syntax '
+                      'are reStructuredText-compliant')),
+                    ('strict', 's',
+                     'Will exit with an error if a check fails')]
+
+    boolean_options = ['metadata', 'restructuredtext', 'strict']
+
+    def initialize_options(self):
+        """Sets default values for options."""
+        self.restructuredtext = 0
+        self.metadata = 1
+        self.strict = 0
+        self._warnings = 0
+
+    def finalize_options(self):
+        pass
+
+    def warn(self, msg):
+        """Counts the number of warnings that occurs."""
+        self._warnings += 1
+        return Command.warn(self, msg)
+
+    def run(self):
+        """Runs the command."""
+        # perform the various tests
+        if self.metadata:
+            self.check_metadata()
+        if self.restructuredtext:
+            if HAS_DOCUTILS:
+                self.check_restructuredtext()
+            elif self.strict:
+                raise DistutilsSetupError('The docutils package is needed.')
+
+        # let's raise an error in strict mode, if we have at least
+        # one warning
+        if self.strict and self._warnings > 0:
+            raise DistutilsSetupError('Please correct your package.')
+
+    def check_metadata(self):
+        """Ensures that all required elements of meta-data are supplied.
+
+        name, version, URL, (author and author_email) or
+        (maintainer and maintainer_email)).
+
+        Warns if any are missing.
+        """
+        metadata = self.distribution.metadata
+
+        missing = []
+        for attr in ('name', 'version', 'url'):
+            if not (hasattr(metadata, attr) and getattr(metadata, attr)):
+                missing.append(attr)
+
+        if missing:
+            self.warn("missing required meta-data: %s"  % ', '.join(missing))
+        if metadata.author:
+            if not metadata.author_email:
+                self.warn("missing meta-data: if 'author' supplied, " +
+                          "'author_email' must be supplied too")
+        elif metadata.maintainer:
+            if not metadata.maintainer_email:
+                self.warn("missing meta-data: if 'maintainer' supplied, " +
+                          "'maintainer_email' must be supplied too")
+        else:
+            self.warn("missing meta-data: either (author and author_email) " +
+                      "or (maintainer and maintainer_email) " +
+                      "must be supplied")
+
+    def check_restructuredtext(self):
+        """Checks if the long string fields are reST-compliant."""
+        data = self.distribution.get_long_description()
+        if not isinstance(data, unicode):
+            data = data.decode(PKG_INFO_ENCODING)
+        for warning in self._check_rst_data(data):
+            line = warning[-1].get('line')
+            if line is None:
+                warning = warning[1]
+            else:
+                warning = '%s (line %s)' % (warning[1], line)
+            self.warn(warning)
+
+    def _check_rst_data(self, data):
+        """Returns warnings when the provided data doesn't compile."""
+        source_path = StringIO()
+        parser = Parser()
+        settings = frontend.OptionParser().get_default_values()
+        settings.tab_width = 4
+        settings.pep_references = None
+        settings.rfc_references = None
+        reporter = SilentReporter(source_path,
+                          settings.report_level,
+                          settings.halt_level,
+                          stream=settings.warning_stream,
+                          debug=settings.debug,
+                          encoding=settings.error_encoding,
+                          error_handler=settings.error_encoding_error_handler)
+
+        document = nodes.document(settings, reporter, source=source_path)
+        document.note_source(source_path, -1)
+        try:
+            parser.parse(data, document)
+        except AttributeError:
+            reporter.messages.append((-1, 'Could not finish the parsing.',
+                                      '', {}))
+
+        return reporter.messages
diff --git a/src/main/resources/PythonLibs/distutils/command/clean.py b/src/main/resources/PythonLibs/distutils/command/clean.py
new file mode 100644
index 0000000000000000000000000000000000000000..90ef35f1ca74018c2f2936b714b24ea38f904054
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/clean.py
@@ -0,0 +1,80 @@
+"""distutils.command.clean
+
+Implements the Distutils 'clean' command."""
+
+# contributed by Bastian Kleineidam <calvin@cs.uni-sb.de>, added 2000-03-18
+
+__revision__ = "$Id$"
+
+import os
+from distutils.core import Command
+from distutils.dir_util import remove_tree
+from distutils import log
+
+class clean(Command):
+
+    description = "clean up temporary files from 'build' command"
+    user_options = [
+        ('build-base=', 'b',
+         "base build directory (default: 'build.build-base')"),
+        ('build-lib=', None,
+         "build directory for all modules (default: 'build.build-lib')"),
+        ('build-temp=', 't',
+         "temporary build directory (default: 'build.build-temp')"),
+        ('build-scripts=', None,
+         "build directory for scripts (default: 'build.build-scripts')"),
+        ('bdist-base=', None,
+         "temporary directory for built distributions"),
+        ('all', 'a',
+         "remove all build output, not just temporary by-products")
+    ]
+
+    boolean_options = ['all']
+
+    def initialize_options(self):
+        self.build_base = None
+        self.build_lib = None
+        self.build_temp = None
+        self.build_scripts = None
+        self.bdist_base = None
+        self.all = None
+
+    def finalize_options(self):
+        self.set_undefined_options('build',
+                                   ('build_base', 'build_base'),
+                                   ('build_lib', 'build_lib'),
+                                   ('build_scripts', 'build_scripts'),
+                                   ('build_temp', 'build_temp'))
+        self.set_undefined_options('bdist',
+                                   ('bdist_base', 'bdist_base'))
+
+    def run(self):
+        # remove the build/temp.<plat> directory (unless it's already
+        # gone)
+        if os.path.exists(self.build_temp):
+            remove_tree(self.build_temp, dry_run=self.dry_run)
+        else:
+            log.debug("'%s' does not exist -- can't clean it",
+                      self.build_temp)
+
+        if self.all:
+            # remove build directories
+            for directory in (self.build_lib,
+                              self.bdist_base,
+                              self.build_scripts):
+                if os.path.exists(directory):
+                    remove_tree(directory, dry_run=self.dry_run)
+                else:
+                    log.warn("'%s' does not exist -- can't clean it",
+                             directory)
+
+        # just for the heck of it, try to remove the base build directory:
+        # we might have emptied it right now, but if not we don't care
+        if not self.dry_run:
+            try:
+                os.rmdir(self.build_base)
+                log.info("removing '%s'", self.build_base)
+            except OSError:
+                pass
+
+# class clean
diff --git a/src/main/resources/PythonLibs/distutils/command/command_template b/src/main/resources/PythonLibs/distutils/command/command_template
new file mode 100644
index 0000000000000000000000000000000000000000..50bbab7b6ec0d44120f3e978164ceceedb267e14
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/command_template
@@ -0,0 +1,45 @@
+"""distutils.command.x
+
+Implements the Distutils 'x' command.
+"""
+
+# created 2000/mm/dd, John Doe
+
+__revision__ = "$Id$"
+
+from distutils.core import Command
+
+
+class x (Command):
+
+    # Brief (40-50 characters) description of the command
+    description = ""
+
+    # List of option tuples: long name, short name (None if no short
+    # name), and help string.
+    user_options = [('', '',
+                     ""),
+                   ]
+
+
+    def initialize_options (self):
+        self. = None
+        self. = None
+        self. = None
+
+    # initialize_options()
+
+
+    def finalize_options (self):
+        if self.x is None:
+            self.x = 
+
+    # finalize_options()
+
+
+    def run (self):
+
+
+    # run()
+
+# class x
diff --git a/src/main/resources/PythonLibs/distutils/command/config.py b/src/main/resources/PythonLibs/distutils/command/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..b084913563a3e234521a746be24b4fb2b4837c4a
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/config.py
@@ -0,0 +1,357 @@
+"""distutils.command.config
+
+Implements the Distutils 'config' command, a (mostly) empty command class
+that exists mainly to be sub-classed by specific module distributions and
+applications.  The idea is that while every "config" command is different,
+at least they're all named the same, and users always see "config" in the
+list of standard commands.  Also, this is a good place to put common
+configure-like tasks: "try to compile this C code", or "figure out where
+this header file lives".
+"""
+
+__revision__ = "$Id$"
+
+import os
+import re
+
+from distutils.core import Command
+from distutils.errors import DistutilsExecError
+from distutils.sysconfig import customize_compiler
+from distutils import log
+
+LANG_EXT = {'c': '.c', 'c++': '.cxx'}
+
+class config(Command):
+
+    description = "prepare to build"
+
+    user_options = [
+        ('compiler=', None,
+         "specify the compiler type"),
+        ('cc=', None,
+         "specify the compiler executable"),
+        ('include-dirs=', 'I',
+         "list of directories to search for header files"),
+        ('define=', 'D',
+         "C preprocessor macros to define"),
+        ('undef=', 'U',
+         "C preprocessor macros to undefine"),
+        ('libraries=', 'l',
+         "external C libraries to link with"),
+        ('library-dirs=', 'L',
+         "directories to search for external C libraries"),
+
+        ('noisy', None,
+         "show every action (compile, link, run, ...) taken"),
+        ('dump-source', None,
+         "dump generated source files before attempting to compile them"),
+        ]
+
+
+    # The three standard command methods: since the "config" command
+    # does nothing by default, these are empty.
+
+    def initialize_options(self):
+        self.compiler = None
+        self.cc = None
+        self.include_dirs = None
+        self.libraries = None
+        self.library_dirs = None
+
+        # maximal output for now
+        self.noisy = 1
+        self.dump_source = 1
+
+        # list of temporary files generated along-the-way that we have
+        # to clean at some point
+        self.temp_files = []
+
+    def finalize_options(self):
+        if self.include_dirs is None:
+            self.include_dirs = self.distribution.include_dirs or []
+        elif isinstance(self.include_dirs, str):
+            self.include_dirs = self.include_dirs.split(os.pathsep)
+
+        if self.libraries is None:
+            self.libraries = []
+        elif isinstance(self.libraries, str):
+            self.libraries = [self.libraries]
+
+        if self.library_dirs is None:
+            self.library_dirs = []
+        elif isinstance(self.library_dirs, str):
+            self.library_dirs = self.library_dirs.split(os.pathsep)
+
+    def run(self):
+        pass
+
+
+    # Utility methods for actual "config" commands.  The interfaces are
+    # loosely based on Autoconf macros of similar names.  Sub-classes
+    # may use these freely.
+
+    def _check_compiler(self):
+        """Check that 'self.compiler' really is a CCompiler object;
+        if not, make it one.
+        """
+        # We do this late, and only on-demand, because this is an expensive
+        # import.
+        from distutils.ccompiler import CCompiler, new_compiler
+        if not isinstance(self.compiler, CCompiler):
+            self.compiler = new_compiler(compiler=self.compiler,
+                                         dry_run=self.dry_run, force=1)
+            customize_compiler(self.compiler)
+            if self.include_dirs:
+                self.compiler.set_include_dirs(self.include_dirs)
+            if self.libraries:
+                self.compiler.set_libraries(self.libraries)
+            if self.library_dirs:
+                self.compiler.set_library_dirs(self.library_dirs)
+
+
+    def _gen_temp_sourcefile(self, body, headers, lang):
+        filename = "_configtest" + LANG_EXT[lang]
+        file = open(filename, "w")
+        if headers:
+            for header in headers:
+                file.write("#include <%s>\n" % header)
+            file.write("\n")
+        file.write(body)
+        if body[-1] != "\n":
+            file.write("\n")
+        file.close()
+        return filename
+
+    def _preprocess(self, body, headers, include_dirs, lang):
+        src = self._gen_temp_sourcefile(body, headers, lang)
+        out = "_configtest.i"
+        self.temp_files.extend([src, out])
+        self.compiler.preprocess(src, out, include_dirs=include_dirs)
+        return (src, out)
+
+    def _compile(self, body, headers, include_dirs, lang):
+        src = self._gen_temp_sourcefile(body, headers, lang)
+        if self.dump_source:
+            dump_file(src, "compiling '%s':" % src)
+        (obj,) = self.compiler.object_filenames([src])
+        self.temp_files.extend([src, obj])
+        self.compiler.compile([src], include_dirs=include_dirs)
+        return (src, obj)
+
+    def _link(self, body, headers, include_dirs, libraries, library_dirs,
+              lang):
+        (src, obj) = self._compile(body, headers, include_dirs, lang)
+        prog = os.path.splitext(os.path.basename(src))[0]
+        self.compiler.link_executable([obj], prog,
+                                      libraries=libraries,
+                                      library_dirs=library_dirs,
+                                      target_lang=lang)
+
+        if self.compiler.exe_extension is not None:
+            prog = prog + self.compiler.exe_extension
+        self.temp_files.append(prog)
+
+        return (src, obj, prog)
+
+    def _clean(self, *filenames):
+        if not filenames:
+            filenames = self.temp_files
+            self.temp_files = []
+        log.info("removing: %s", ' '.join(filenames))
+        for filename in filenames:
+            try:
+                os.remove(filename)
+            except OSError:
+                pass
+
+
+    # XXX these ignore the dry-run flag: what to do, what to do? even if
+    # you want a dry-run build, you still need some sort of configuration
+    # info.  My inclination is to make it up to the real config command to
+    # consult 'dry_run', and assume a default (minimal) configuration if
+    # true.  The problem with trying to do it here is that you'd have to
+    # return either true or false from all the 'try' methods, neither of
+    # which is correct.
+
+    # XXX need access to the header search path and maybe default macros.
+
+    def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
+        """Construct a source file from 'body' (a string containing lines
+        of C/C++ code) and 'headers' (a list of header files to include)
+        and run it through the preprocessor.  Return true if the
+        preprocessor succeeded, false if there were any errors.
+        ('body' probably isn't of much use, but what the heck.)
+        """
+        from distutils.ccompiler import CompileError
+        self._check_compiler()
+        ok = 1
+        try:
+            self._preprocess(body, headers, include_dirs, lang)
+        except CompileError:
+            ok = 0
+
+        self._clean()
+        return ok
+
+    def search_cpp(self, pattern, body=None, headers=None, include_dirs=None,
+                   lang="c"):
+        """Construct a source file (just like 'try_cpp()'), run it through
+        the preprocessor, and return true if any line of the output matches
+        'pattern'.  'pattern' should either be a compiled regex object or a
+        string containing a regex.  If both 'body' and 'headers' are None,
+        preprocesses an empty file -- which can be useful to determine the
+        symbols the preprocessor and compiler set by default.
+        """
+        self._check_compiler()
+        src, out = self._preprocess(body, headers, include_dirs, lang)
+
+        if isinstance(pattern, str):
+            pattern = re.compile(pattern)
+
+        file = open(out)
+        match = 0
+        while 1:
+            line = file.readline()
+            if line == '':
+                break
+            if pattern.search(line):
+                match = 1
+                break
+
+        file.close()
+        self._clean()
+        return match
+
+    def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
+        """Try to compile a source file built from 'body' and 'headers'.
+        Return true on success, false otherwise.
+        """
+        from distutils.ccompiler import CompileError
+        self._check_compiler()
+        try:
+            self._compile(body, headers, include_dirs, lang)
+            ok = 1
+        except CompileError:
+            ok = 0
+
+        log.info(ok and "success!" or "failure.")
+        self._clean()
+        return ok
+
+    def try_link(self, body, headers=None, include_dirs=None, libraries=None,
+                 library_dirs=None, lang="c"):
+        """Try to compile and link a source file, built from 'body' and
+        'headers', to executable form.  Return true on success, false
+        otherwise.
+        """
+        from distutils.ccompiler import CompileError, LinkError
+        self._check_compiler()
+        try:
+            self._link(body, headers, include_dirs,
+                       libraries, library_dirs, lang)
+            ok = 1
+        except (CompileError, LinkError):
+            ok = 0
+
+        log.info(ok and "success!" or "failure.")
+        self._clean()
+        return ok
+
+    def try_run(self, body, headers=None, include_dirs=None, libraries=None,
+                library_dirs=None, lang="c"):
+        """Try to compile, link to an executable, and run a program
+        built from 'body' and 'headers'.  Return true on success, false
+        otherwise.
+        """
+        from distutils.ccompiler import CompileError, LinkError
+        self._check_compiler()
+        try:
+            src, obj, exe = self._link(body, headers, include_dirs,
+                                       libraries, library_dirs, lang)
+            self.spawn([exe])
+            ok = 1
+        except (CompileError, LinkError, DistutilsExecError):
+            ok = 0
+
+        log.info(ok and "success!" or "failure.")
+        self._clean()
+        return ok
+
+
+    # -- High-level methods --------------------------------------------
+    # (these are the ones that are actually likely to be useful
+    # when implementing a real-world config command!)
+
+    def check_func(self, func, headers=None, include_dirs=None,
+                   libraries=None, library_dirs=None, decl=0, call=0):
+
+        """Determine if function 'func' is available by constructing a
+        source file that refers to 'func', and compiles and links it.
+        If everything succeeds, returns true; otherwise returns false.
+
+        The constructed source file starts out by including the header
+        files listed in 'headers'.  If 'decl' is true, it then declares
+        'func' (as "int func()"); you probably shouldn't supply 'headers'
+        and set 'decl' true in the same call, or you might get errors about
+        a conflicting declarations for 'func'.  Finally, the constructed
+        'main()' function either references 'func' or (if 'call' is true)
+        calls it.  'libraries' and 'library_dirs' are used when
+        linking.
+        """
+
+        self._check_compiler()
+        body = []
+        if decl:
+            body.append("int %s ();" % func)
+        body.append("int main () {")
+        if call:
+            body.append("  %s();" % func)
+        else:
+            body.append("  %s;" % func)
+        body.append("}")
+        body = "\n".join(body) + "\n"
+
+        return self.try_link(body, headers, include_dirs,
+                             libraries, library_dirs)
+
+    # check_func ()
+
+    def check_lib(self, library, library_dirs=None, headers=None,
+                  include_dirs=None, other_libraries=[]):
+        """Determine if 'library' is available to be linked against,
+        without actually checking that any particular symbols are provided
+        by it.  'headers' will be used in constructing the source file to
+        be compiled, but the only effect of this is to check if all the
+        header files listed are available.  Any libraries listed in
+        'other_libraries' will be included in the link, in case 'library'
+        has symbols that depend on other libraries.
+        """
+        self._check_compiler()
+        return self.try_link("int main (void) { }",
+                             headers, include_dirs,
+                             [library]+other_libraries, library_dirs)
+
+    def check_header(self, header, include_dirs=None, library_dirs=None,
+                     lang="c"):
+        """Determine if the system header file named by 'header_file'
+        exists and can be found by the preprocessor; return true if so,
+        false otherwise.
+        """
+        return self.try_cpp(body="/* No body */", headers=[header],
+                            include_dirs=include_dirs)
+
+
+def dump_file(filename, head=None):
+    """Dumps a file content into log.info.
+
+    If head is not None, will be dumped before the file content.
+    """
+    if head is None:
+        log.info('%s' % filename)
+    else:
+        log.info(head)
+    file = open(filename)
+    try:
+        log.info(file.read())
+    finally:
+        file.close()
diff --git a/src/main/resources/PythonLibs/distutils/command/install.py b/src/main/resources/PythonLibs/distutils/command/install.py
new file mode 100644
index 0000000000000000000000000000000000000000..baffa1d019bb615eef87b7ef4c73a68481ad7345
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/install.py
@@ -0,0 +1,614 @@
+"""distutils.command.install
+
+Implements the Distutils 'install' command."""
+
+from distutils import log
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: install.py 43363 2006-03-27 21:55:21Z phillip.eby $"
+
+import sys, os, string
+from types import *
+from distutils.core import Command
+from distutils.debug import DEBUG
+from distutils.sysconfig import get_config_vars
+from distutils.errors import DistutilsPlatformError
+from distutils.file_util import write_file
+from distutils.util import convert_path, subst_vars, change_root
+from distutils.errors import DistutilsOptionError
+from glob import glob
+
+if sys.version < "2.2":
+    WINDOWS_SCHEME = {
+        'purelib': '$base',
+        'platlib': '$base',
+        'headers': '$base/Include/$dist_name',
+        'scripts': '$base/Scripts',
+        'data'   : '$base',
+    }
+else:
+    WINDOWS_SCHEME = {
+        'purelib': '$base/Lib/site-packages',
+        'platlib': '$base/Lib/site-packages',
+        'headers': '$base/Include/$dist_name',
+        'scripts': '$base/Scripts',
+        'data'   : '$base',
+    }
+
+INSTALL_SCHEMES = {
+    'unix_prefix': {
+        'purelib': '$base/lib/python$py_version_short/site-packages',
+        'platlib': '$platbase/lib/python$py_version_short/site-packages',
+        'headers': '$base/include/python$py_version_short/$dist_name',
+        'scripts': '$base/bin',
+        'data'   : '$base',
+        },
+    'unix_home': {
+        'purelib': '$base/lib/python',
+        'platlib': '$base/lib/python',
+        'headers': '$base/include/python/$dist_name',
+        'scripts': '$base/bin',
+        'data'   : '$base',
+        },
+    'nt': WINDOWS_SCHEME,
+    'mac': {
+        'purelib': '$base/Lib/site-packages',
+        'platlib': '$base/Lib/site-packages',
+        'headers': '$base/Include/$dist_name',
+        'scripts': '$base/Scripts',
+        'data'   : '$base',
+        },
+    'os2': {
+        'purelib': '$base/Lib/site-packages',
+        'platlib': '$base/Lib/site-packages',
+        'headers': '$base/Include/$dist_name',
+        'scripts': '$base/Scripts',
+        'data'   : '$base',
+        },
+    'java': {
+        'purelib': '$base/Lib/site-packages',
+        'platlib': '$base/Lib/site-packages',
+        'headers': '$base/Include/$dist_name',
+        'scripts': '$base/bin',
+        'data'   : '$base',
+        }
+    }
+
+# The keys to an installation scheme; if any new types of files are to be
+# installed, be sure to add an entry to every installation scheme above,
+# and to SCHEME_KEYS here.
+SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')
+
+
+class install (Command):
+
+    description = "install everything from build directory"
+
+    user_options = [
+        # Select installation scheme and set base director(y|ies)
+        ('prefix=', None,
+         "installation prefix"),
+        ('exec-prefix=', None,
+         "(Unix only) prefix for platform-specific files"),
+        ('home=', None,
+         "(Unix only) home directory to install under"),
+
+        # Or, just set the base director(y|ies)
+        ('install-base=', None,
+         "base installation directory (instead of --prefix or --home)"),
+        ('install-platbase=', None,
+         "base installation directory for platform-specific files " +
+         "(instead of --exec-prefix or --home)"),
+        ('root=', None,
+         "install everything relative to this alternate root directory"),
+
+        # Or, explicitly set the installation scheme
+        ('install-purelib=', None,
+         "installation directory for pure Python module distributions"),
+        ('install-platlib=', None,
+         "installation directory for non-pure module distributions"),
+        ('install-lib=', None,
+         "installation directory for all module distributions " +
+         "(overrides --install-purelib and --install-platlib)"),
+
+        ('install-headers=', None,
+         "installation directory for C/C++ headers"),
+        ('install-scripts=', None,
+         "installation directory for Python scripts"),
+        ('install-data=', None,
+         "installation directory for data files"),
+
+        # Byte-compilation options -- see install_lib.py for details, as
+        # these are duplicated from there (but only install_lib does
+        # anything with them).
+        ('compile', 'c', "compile .py to .pyc [default]"),
+        ('no-compile', None, "don't compile .py files"),
+        ('optimize=', 'O',
+         "also compile with optimization: -O1 for \"python -O\", "
+         "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
+
+        # Miscellaneous control options
+        ('force', 'f',
+         "force installation (overwrite any existing files)"),
+        ('skip-build', None,
+         "skip rebuilding everything (for testing/debugging)"),
+
+        # Where to install documentation (eventually!)
+        #('doc-format=', None, "format of documentation to generate"),
+        #('install-man=', None, "directory for Unix man pages"),
+        #('install-html=', None, "directory for HTML documentation"),
+        #('install-info=', None, "directory for GNU info files"),
+
+        ('record=', None,
+         "filename in which to record list of installed files"),
+        ]
+
+    boolean_options = ['compile', 'force', 'skip-build']
+    negative_opt = {'no-compile' : 'compile'}
+
+
+    def initialize_options (self):
+
+        # High-level options: these select both an installation base
+        # and scheme.
+        self.prefix = None
+        self.exec_prefix = None
+        self.home = None
+
+        # These select only the installation base; it's up to the user to
+        # specify the installation scheme (currently, that means supplying
+        # the --install-{platlib,purelib,scripts,data} options).
+        self.install_base = None
+        self.install_platbase = None
+        self.root = None
+
+        # These options are the actual installation directories; if not
+        # supplied by the user, they are filled in using the installation
+        # scheme implied by prefix/exec-prefix/home and the contents of
+        # that installation scheme.
+        self.install_purelib = None     # for pure module distributions
+        self.install_platlib = None     # non-pure (dists w/ extensions)
+        self.install_headers = None     # for C/C++ headers
+        self.install_lib = None         # set to either purelib or platlib
+        self.install_scripts = None
+        self.install_data = None
+
+        self.compile = None
+        self.optimize = None
+
+        # These two are for putting non-packagized distributions into their
+        # own directory and creating a .pth file if it makes sense.
+        # 'extra_path' comes from the setup file; 'install_path_file' can
+        # be turned off if it makes no sense to install a .pth file.  (But
+        # better to install it uselessly than to guess wrong and not
+        # install it when it's necessary and would be used!)  Currently,
+        # 'install_path_file' is always true unless some outsider meddles
+        # with it.
+        self.extra_path = None
+        self.install_path_file = 1
+
+        # 'force' forces installation, even if target files are not
+        # out-of-date.  'skip_build' skips running the "build" command,
+        # handy if you know it's not necessary.  'warn_dir' (which is *not*
+        # a user option, it's just there so the bdist_* commands can turn
+        # it off) determines whether we warn about installing to a
+        # directory not in sys.path.
+        self.force = 0
+        self.skip_build = 0
+        self.warn_dir = 1
+
+        # These are only here as a conduit from the 'build' command to the
+        # 'install_*' commands that do the real work.  ('build_base' isn't
+        # actually used anywhere, but it might be useful in future.)  They
+        # are not user options, because if the user told the install
+        # command where the build directory is, that wouldn't affect the
+        # build command.
+        self.build_base = None
+        self.build_lib = None
+
+        # Not defined yet because we don't know anything about
+        # documentation yet.
+        #self.install_man = None
+        #self.install_html = None
+        #self.install_info = None
+
+        self.record = None
+
+
+    # -- Option finalizing methods -------------------------------------
+    # (This is rather more involved than for most commands,
+    # because this is where the policy for installing third-
+    # party Python modules on various platforms given a wide
+    # array of user input is decided.  Yes, it's quite complex!)
+
+    def finalize_options (self):
+
+        # This method (and its pliant slaves, like 'finalize_unix()',
+        # 'finalize_other()', and 'select_scheme()') is where the default
+        # installation directories for modules, extension modules, and
+        # anything else we care to install from a Python module
+        # distribution.  Thus, this code makes a pretty important policy
+        # statement about how third-party stuff is added to a Python
+        # installation!  Note that the actual work of installation is done
+        # by the relatively simple 'install_*' commands; they just take
+        # their orders from the installation directory options determined
+        # here.
+
+        # Check for errors/inconsistencies in the options; first, stuff
+        # that's wrong on any platform.
+
+        if ((self.prefix or self.exec_prefix or self.home) and
+            (self.install_base or self.install_platbase)):
+            raise DistutilsOptionError, \
+                  ("must supply either prefix/exec-prefix/home or " +
+                   "install-base/install-platbase -- not both")
+
+        if self.home and (self.prefix or self.exec_prefix):
+            raise DistutilsOptionError, \
+                  "must supply either home or prefix/exec-prefix -- not both"
+
+        # Next, stuff that's wrong (or dubious) only on certain platforms.
+        if os.name != "posix":
+            if self.exec_prefix:
+                self.warn("exec-prefix option ignored on this platform")
+                self.exec_prefix = None
+
+        # Now the interesting logic -- so interesting that we farm it out
+        # to other methods.  The goal of these methods is to set the final
+        # values for the install_{lib,scripts,data,...}  options, using as
+        # input a heady brew of prefix, exec_prefix, home, install_base,
+        # install_platbase, user-supplied versions of
+        # install_{purelib,platlib,lib,scripts,data,...}, and the
+        # INSTALL_SCHEME dictionary above.  Phew!
+
+        self.dump_dirs("pre-finalize_{unix,other}")
+
+        if os.name == 'posix':
+            self.finalize_unix()
+        else:
+            self.finalize_other()
+
+        self.dump_dirs("post-finalize_{unix,other}()")
+
+        # Expand configuration variables, tilde, etc. in self.install_base
+        # and self.install_platbase -- that way, we can use $base or
+        # $platbase in the other installation directories and not worry
+        # about needing recursive variable expansion (shudder).
+
+        py_version = (string.split(sys.version))[0]
+        (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix')
+        self.config_vars = {'dist_name': self.distribution.get_name(),
+                            'dist_version': self.distribution.get_version(),
+                            'dist_fullname': self.distribution.get_fullname(),
+                            'py_version': py_version,
+                            'py_version_short': py_version[0:3],
+                            'sys_prefix': prefix,
+                            'prefix': prefix,
+                            'sys_exec_prefix': exec_prefix,
+                            'exec_prefix': exec_prefix,
+                           }
+        self.expand_basedirs()
+
+        self.dump_dirs("post-expand_basedirs()")
+
+        # Now define config vars for the base directories so we can expand
+        # everything else.
+        self.config_vars['base'] = self.install_base
+        self.config_vars['platbase'] = self.install_platbase
+
+        if DEBUG:
+            from pprint import pprint
+            print "config vars:"
+            pprint(self.config_vars)
+
+        # Expand "~" and configuration variables in the installation
+        # directories.
+        self.expand_dirs()
+
+        self.dump_dirs("post-expand_dirs()")
+
+        # Pick the actual directory to install all modules to: either
+        # install_purelib or install_platlib, depending on whether this
+        # module distribution is pure or not.  Of course, if the user
+        # already specified install_lib, use their selection.
+        if self.install_lib is None:
+            if self.distribution.ext_modules: # has extensions: non-pure
+                self.install_lib = self.install_platlib
+            else:
+                self.install_lib = self.install_purelib
+
+
+        # Convert directories from Unix /-separated syntax to the local
+        # convention.
+        self.convert_paths('lib', 'purelib', 'platlib',
+                           'scripts', 'data', 'headers')
+
+        # Well, we're not actually fully completely finalized yet: we still
+        # have to deal with 'extra_path', which is the hack for allowing
+        # non-packagized module distributions (hello, Numerical Python!) to
+        # get their own directories.
+        self.handle_extra_path()
+        self.install_libbase = self.install_lib # needed for .pth file
+        self.install_lib = os.path.join(self.install_lib, self.extra_dirs)
+
+        # If a new root directory was supplied, make all the installation
+        # dirs relative to it.
+        if self.root is not None:
+            self.change_roots('libbase', 'lib', 'purelib', 'platlib',
+                              'scripts', 'data', 'headers')
+
+        self.dump_dirs("after prepending root")
+
+        # Find out the build directories, ie. where to install from.
+        self.set_undefined_options('build',
+                                   ('build_base', 'build_base'),
+                                   ('build_lib', 'build_lib'))
+
+        # Punt on doc directories for now -- after all, we're punting on
+        # documentation completely!
+
+    # finalize_options ()
+
+
+    def dump_dirs (self, msg):
+        if DEBUG:
+            from distutils.fancy_getopt import longopt_xlate
+            print msg + ":"
+            for opt in self.user_options:
+                opt_name = opt[0]
+                if opt_name[-1] == "=":
+                    opt_name = opt_name[0:-1]
+                if self.negative_opt.has_key(opt_name):
+                    opt_name = string.translate(self.negative_opt[opt_name],
+                                                longopt_xlate)
+                    val = not getattr(self, opt_name)
+                else:
+                    opt_name = string.translate(opt_name, longopt_xlate)
+                    val = getattr(self, opt_name)
+                print "  %s: %s" % (opt_name, val)
+
+
+    def finalize_unix (self):
+
+        if self.install_base is not None or self.install_platbase is not None:
+            if ((self.install_lib is None and
+                 self.install_purelib is None and
+                 self.install_platlib is None) or
+                self.install_headers is None or
+                self.install_scripts is None or
+                self.install_data is None):
+                raise DistutilsOptionError, \
+                      ("install-base or install-platbase supplied, but "
+                      "installation scheme is incomplete")
+            return
+
+        if self.home is not None:
+            self.install_base = self.install_platbase = self.home
+            self.select_scheme("unix_home")
+        else:
+            if self.prefix is None:
+                if self.exec_prefix is not None:
+                    raise DistutilsOptionError, \
+                          "must not supply exec-prefix without prefix"
+
+                self.prefix = os.path.normpath(sys.prefix)
+                self.exec_prefix = os.path.normpath(sys.exec_prefix)
+
+            else:
+                if self.exec_prefix is None:
+                    self.exec_prefix = self.prefix
+
+            self.install_base = self.prefix
+            self.install_platbase = self.exec_prefix
+            self.select_scheme("unix_prefix")
+
+    # finalize_unix ()
+
+
+    def finalize_other (self):          # Windows and Mac OS for now
+
+        if self.home is not None:
+            self.install_base = self.install_platbase = self.home
+            self.select_scheme("unix_home")
+        else:
+            if self.prefix is None:
+                self.prefix = os.path.normpath(sys.prefix)
+
+            self.install_base = self.install_platbase = self.prefix
+            try:
+                self.select_scheme(os.name)
+            except KeyError:
+                raise DistutilsPlatformError, \
+                      "I don't know how to install stuff on '%s'" % os.name
+
+    # finalize_other ()
+
+
+    def select_scheme (self, name):
+        # it's the caller's problem if they supply a bad name!
+        scheme = INSTALL_SCHEMES[name]
+        for key in SCHEME_KEYS:
+            attrname = 'install_' + key
+            if getattr(self, attrname) is None:
+                setattr(self, attrname, scheme[key])
+
+
+    def _expand_attrs (self, attrs):
+        for attr in attrs:
+            val = getattr(self, attr)
+            if val is not None:
+                if os.name == 'posix':
+                    val = os.path.expanduser(val)
+                val = subst_vars(val, self.config_vars)
+                setattr(self, attr, val)
+
+
+    def expand_basedirs (self):
+        self._expand_attrs(['install_base',
+                            'install_platbase',
+                            'root'])
+
+    def expand_dirs (self):
+        self._expand_attrs(['install_purelib',
+                            'install_platlib',
+                            'install_lib',
+                            'install_headers',
+                            'install_scripts',
+                            'install_data',])
+
+
+    def convert_paths (self, *names):
+        for name in names:
+            attr = "install_" + name
+            setattr(self, attr, convert_path(getattr(self, attr)))
+
+
+    def handle_extra_path (self):
+
+        if self.extra_path is None:
+            self.extra_path = self.distribution.extra_path
+
+        if self.extra_path is not None:
+            if type(self.extra_path) is StringType:
+                self.extra_path = string.split(self.extra_path, ',')
+
+            if len(self.extra_path) == 1:
+                path_file = extra_dirs = self.extra_path[0]
+            elif len(self.extra_path) == 2:
+                (path_file, extra_dirs) = self.extra_path
+            else:
+                raise DistutilsOptionError, \
+                      ("'extra_path' option must be a list, tuple, or "
+                      "comma-separated string with 1 or 2 elements")
+
+            # convert to local form in case Unix notation used (as it
+            # should be in setup scripts)
+            extra_dirs = convert_path(extra_dirs)
+
+        else:
+            path_file = None
+            extra_dirs = ''
+
+        # XXX should we warn if path_file and not extra_dirs? (in which
+        # case the path file would be harmless but pointless)
+        self.path_file = path_file
+        self.extra_dirs = extra_dirs
+
+    # handle_extra_path ()
+
+
+    def change_roots (self, *names):
+        for name in names:
+            attr = "install_" + name
+            setattr(self, attr, change_root(self.root, getattr(self, attr)))
+
+
+    # -- Command execution methods -------------------------------------
+
+    def run (self):
+
+        # Obviously have to build before we can install
+        if not self.skip_build:
+            self.run_command('build')
+
+        # Run all sub-commands (at least those that need to be run)
+        for cmd_name in self.get_sub_commands():
+            self.run_command(cmd_name)
+
+        if self.path_file:
+            self.create_path_file()
+
+        # write list of installed files, if requested.
+        if self.record:
+            outputs = self.get_outputs()
+            if self.root:               # strip any package prefix
+                root_len = len(self.root)
+                for counter in xrange(len(outputs)):
+                    outputs[counter] = outputs[counter][root_len:]
+            self.execute(write_file,
+                         (self.record, outputs),
+                         "writing list of installed files to '%s'" %
+                         self.record)
+
+        sys_path = map(os.path.normpath, sys.path)
+        sys_path = map(os.path.normcase, sys_path)
+        install_lib = os.path.normcase(os.path.normpath(self.install_lib))
+        if (self.warn_dir and
+            not (self.path_file and self.install_path_file) and
+            install_lib not in sys_path):
+            log.debug(("modules installed to '%s', which is not in "
+                       "Python's module search path (sys.path) -- "
+                       "you'll have to change the search path yourself"),
+                       self.install_lib)
+
+    # run ()
+
+    def create_path_file (self):
+        filename = os.path.join(self.install_libbase,
+                                self.path_file + ".pth")
+        if self.install_path_file:
+            self.execute(write_file,
+                         (filename, [self.extra_dirs]),
+                         "creating %s" % filename)
+        else:
+            self.warn("path file '%s' not created" % filename)
+
+
+    # -- Reporting methods ---------------------------------------------
+
+    def get_outputs (self):
+        # Assemble the outputs of all the sub-commands.
+        outputs = []
+        for cmd_name in self.get_sub_commands():
+            cmd = self.get_finalized_command(cmd_name)
+            # Add the contents of cmd.get_outputs(), ensuring
+            # that outputs doesn't contain duplicate entries
+            for filename in cmd.get_outputs():
+                if filename not in outputs:
+                    outputs.append(filename)
+
+        if self.path_file and self.install_path_file:
+            outputs.append(os.path.join(self.install_libbase,
+                                        self.path_file + ".pth"))
+
+        return outputs
+
+    def get_inputs (self):
+        # XXX gee, this looks familiar ;-(
+        inputs = []
+        for cmd_name in self.get_sub_commands():
+            cmd = self.get_finalized_command(cmd_name)
+            inputs.extend(cmd.get_inputs())
+
+        return inputs
+
+
+    # -- Predicates for sub-command list -------------------------------
+
+    def has_lib (self):
+        """Return true if the current distribution has any Python
+        modules to install."""
+        return (self.distribution.has_pure_modules() or
+                self.distribution.has_ext_modules())
+
+    def has_headers (self):
+        return self.distribution.has_headers()
+
+    def has_scripts (self):
+        return self.distribution.has_scripts()
+
+    def has_data (self):
+        return self.distribution.has_data_files()
+
+
+    # 'sub_commands': a list of commands this command might have to run to
+    # get its work done.  See cmd.py for more info.
+    sub_commands = [('install_lib',     has_lib),
+                    ('install_headers', has_headers),
+                    ('install_scripts', has_scripts),
+                    ('install_data',    has_data),
+                    ('install_egg_info', lambda self:True),
+                   ]
+
+# class install
diff --git a/src/main/resources/PythonLibs/distutils/command/install_data.py b/src/main/resources/PythonLibs/distutils/command/install_data.py
new file mode 100644
index 0000000000000000000000000000000000000000..ab40797b9866537d9aba9029ed52ecc6cf66bee0
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/install_data.py
@@ -0,0 +1,81 @@
+"""distutils.command.install_data
+
+Implements the Distutils 'install_data' command, for installing
+platform-independent data files."""
+
+# contributed by Bastian Kleineidam
+
+__revision__ = "$Id$"
+
+import os
+from distutils.core import Command
+from distutils.util import change_root, convert_path
+
+class install_data(Command):
+
+    description = "install data files"
+
+    user_options = [
+        ('install-dir=', 'd',
+         "base directory for installing data files "
+         "(default: installation base dir)"),
+        ('root=', None,
+         "install everything relative to this alternate root directory"),
+        ('force', 'f', "force installation (overwrite existing files)"),
+        ]
+
+    boolean_options = ['force']
+
+    def initialize_options(self):
+        self.install_dir = None
+        self.outfiles = []
+        self.root = None
+        self.force = 0
+        self.data_files = self.distribution.data_files
+        self.warn_dir = 1
+
+    def finalize_options(self):
+        self.set_undefined_options('install',
+                                   ('install_data', 'install_dir'),
+                                   ('root', 'root'),
+                                   ('force', 'force'),
+                                  )
+
+    def run(self):
+        self.mkpath(self.install_dir)
+        for f in self.data_files:
+            if isinstance(f, str):
+                # it's a simple file, so copy it
+                f = convert_path(f)
+                if self.warn_dir:
+                    self.warn("setup script did not provide a directory for "
+                              "'%s' -- installing right in '%s'" %
+                              (f, self.install_dir))
+                (out, _) = self.copy_file(f, self.install_dir)
+                self.outfiles.append(out)
+            else:
+                # it's a tuple with path to install to and a list of files
+                dir = convert_path(f[0])
+                if not os.path.isabs(dir):
+                    dir = os.path.join(self.install_dir, dir)
+                elif self.root:
+                    dir = change_root(self.root, dir)
+                self.mkpath(dir)
+
+                if f[1] == []:
+                    # If there are no files listed, the user must be
+                    # trying to create an empty directory, so add the
+                    # directory to the list of output files.
+                    self.outfiles.append(dir)
+                else:
+                    # Copy files, adding them to the list of output files.
+                    for data in f[1]:
+                        data = convert_path(data)
+                        (out, _) = self.copy_file(data, dir)
+                        self.outfiles.append(out)
+
+    def get_inputs(self):
+        return self.data_files or []
+
+    def get_outputs(self):
+        return self.outfiles
diff --git a/src/main/resources/PythonLibs/distutils/command/install_egg_info.py b/src/main/resources/PythonLibs/distutils/command/install_egg_info.py
new file mode 100644
index 0000000000000000000000000000000000000000..c8880310dfcf645fb5728dfb5ad90de79d24c17a
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/install_egg_info.py
@@ -0,0 +1,78 @@
+"""distutils.command.install_egg_info
+
+Implements the Distutils 'install_egg_info' command, for installing
+a package's PKG-INFO metadata."""
+
+
+from distutils.cmd import Command
+from distutils import log, dir_util
+import os, sys, re
+
+class install_egg_info(Command):
+    """Install an .egg-info file for the package"""
+
+    description = "Install package's PKG-INFO metadata as an .egg-info file"
+    user_options = [
+        ('install-dir=', 'd', "directory to install to"),
+    ]
+
+    def initialize_options(self):
+        self.install_dir = None
+
+    def finalize_options(self):
+        self.set_undefined_options('install_lib',('install_dir','install_dir'))
+        basename = "%s-%s-py%s.egg-info" % (
+            to_filename(safe_name(self.distribution.get_name())),
+            to_filename(safe_version(self.distribution.get_version())),
+            sys.version[:3]
+        )
+        self.target = os.path.join(self.install_dir, basename)
+        self.outputs = [self.target]
+
+    def run(self):
+        target = self.target
+        if os.path.isdir(target) and not os.path.islink(target):
+            dir_util.remove_tree(target, dry_run=self.dry_run)
+        elif os.path.exists(target):
+            self.execute(os.unlink,(self.target,),"Removing "+target)
+        elif not os.path.isdir(self.install_dir):
+            self.execute(os.makedirs, (self.install_dir,),
+                         "Creating "+self.install_dir)
+        log.info("Writing %s", target)
+        if not self.dry_run:
+            f = open(target, 'w')
+            self.distribution.metadata.write_pkg_file(f)
+            f.close()
+
+    def get_outputs(self):
+        return self.outputs
+
+
+# The following routines are taken from setuptools' pkg_resources module and
+# can be replaced by importing them from pkg_resources once it is included
+# in the stdlib.
+
+def safe_name(name):
+    """Convert an arbitrary string to a standard distribution name
+
+    Any runs of non-alphanumeric/. characters are replaced with a single '-'.
+    """
+    return re.sub('[^A-Za-z0-9.]+', '-', name)
+
+
+def safe_version(version):
+    """Convert an arbitrary string to a standard version string
+
+    Spaces become dots, and all other non-alphanumeric characters become
+    dashes, with runs of multiple dashes condensed to a single dash.
+    """
+    version = version.replace(' ','.')
+    return re.sub('[^A-Za-z0-9.]+', '-', version)
+
+
+def to_filename(name):
+    """Convert a project or version name to its filename-escaped form
+
+    Any '-' characters are currently replaced with '_'.
+    """
+    return name.replace('-','_')
diff --git a/src/main/resources/PythonLibs/distutils/command/install_headers.py b/src/main/resources/PythonLibs/distutils/command/install_headers.py
new file mode 100644
index 0000000000000000000000000000000000000000..d892416a8ccd9c6374eaaef3cc373698a972a22e
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/install_headers.py
@@ -0,0 +1,51 @@
+"""distutils.command.install_headers
+
+Implements the Distutils 'install_headers' command, to install C/C++ header
+files to the Python include directory."""
+
+__revision__ = "$Id$"
+
+from distutils.core import Command
+
+
+# XXX force is never used
+class install_headers(Command):
+
+    description = "install C/C++ header files"
+
+    user_options = [('install-dir=', 'd',
+                     "directory to install header files to"),
+                    ('force', 'f',
+                     "force installation (overwrite existing files)"),
+                   ]
+
+    boolean_options = ['force']
+
+    def initialize_options(self):
+        self.install_dir = None
+        self.force = 0
+        self.outfiles = []
+
+    def finalize_options(self):
+        self.set_undefined_options('install',
+                                   ('install_headers', 'install_dir'),
+                                   ('force', 'force'))
+
+
+    def run(self):
+        headers = self.distribution.headers
+        if not headers:
+            return
+
+        self.mkpath(self.install_dir)
+        for header in headers:
+            (out, _) = self.copy_file(header, self.install_dir)
+            self.outfiles.append(out)
+
+    def get_inputs(self):
+        return self.distribution.headers or []
+
+    def get_outputs(self):
+        return self.outfiles
+
+# class install_headers
diff --git a/src/main/resources/PythonLibs/distutils/command/install_lib.py b/src/main/resources/PythonLibs/distutils/command/install_lib.py
new file mode 100644
index 0000000000000000000000000000000000000000..043e8b6e27151e959d123938720a6d4978ca5701
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/install_lib.py
@@ -0,0 +1,219 @@
+"""distutils.command.install_lib
+
+Implements the Distutils 'install_lib' command
+(install all Python modules)."""
+
+__revision__ = "$Id$"
+
+import os
+import sys
+
+from distutils.core import Command
+from distutils.errors import DistutilsOptionError
+
+
+# Extension for Python source files.
+if hasattr(os, 'extsep'):
+    PYTHON_SOURCE_EXTENSION = os.extsep + "py"
+else:
+    PYTHON_SOURCE_EXTENSION = ".py"
+
+class install_lib(Command):
+
+    description = "install all Python modules (extensions and pure Python)"
+
+    # The byte-compilation options are a tad confusing.  Here are the
+    # possible scenarios:
+    #   1) no compilation at all (--no-compile --no-optimize)
+    #   2) compile .pyc only (--compile --no-optimize; default)
+    #   3) compile .pyc and "level 1" .pyo (--compile --optimize)
+    #   4) compile "level 1" .pyo only (--no-compile --optimize)
+    #   5) compile .pyc and "level 2" .pyo (--compile --optimize-more)
+    #   6) compile "level 2" .pyo only (--no-compile --optimize-more)
+    #
+    # The UI for this is two option, 'compile' and 'optimize'.
+    # 'compile' is strictly boolean, and only decides whether to
+    # generate .pyc files.  'optimize' is three-way (0, 1, or 2), and
+    # decides both whether to generate .pyo files and what level of
+    # optimization to use.
+
+    user_options = [
+        ('install-dir=', 'd', "directory to install to"),
+        ('build-dir=','b', "build directory (where to install from)"),
+        ('force', 'f', "force installation (overwrite existing files)"),
+        ('compile', 'c', "compile .py to .pyc [default]"),
+        ('no-compile', None, "don't compile .py files"),
+        ('optimize=', 'O',
+         "also compile with optimization: -O1 for \"python -O\", "
+         "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
+        ('skip-build', None, "skip the build steps"),
+        ]
+
+    boolean_options = ['force', 'compile', 'skip-build']
+    negative_opt = {'no-compile' : 'compile'}
+
+    def initialize_options(self):
+        # let the 'install' command dictate our installation directory
+        self.install_dir = None
+        self.build_dir = None
+        self.force = 0
+        self.compile = None
+        self.optimize = None
+        self.skip_build = None
+
+    def finalize_options(self):
+        # Get all the information we need to install pure Python modules
+        # from the umbrella 'install' command -- build (source) directory,
+        # install (target) directory, and whether to compile .py files.
+        self.set_undefined_options('install',
+                                   ('build_lib', 'build_dir'),
+                                   ('install_lib', 'install_dir'),
+                                   ('force', 'force'),
+                                   ('compile', 'compile'),
+                                   ('optimize', 'optimize'),
+                                   ('skip_build', 'skip_build'),
+                                  )
+
+        if self.compile is None:
+            self.compile = 1
+        if self.optimize is None:
+            self.optimize = 0
+
+        if not isinstance(self.optimize, int):
+            try:
+                self.optimize = int(self.optimize)
+                if self.optimize not in (0, 1, 2):
+                    raise AssertionError
+            except (ValueError, AssertionError):
+                raise DistutilsOptionError, "optimize must be 0, 1, or 2"
+
+    def run(self):
+        # Make sure we have built everything we need first
+        self.build()
+
+        # Install everything: simply dump the entire contents of the build
+        # directory to the installation directory (that's the beauty of
+        # having a build directory!)
+        outfiles = self.install()
+
+        # (Optionally) compile .py to .pyc
+        if outfiles is not None and self.distribution.has_pure_modules():
+            self.byte_compile(outfiles)
+
+    # -- Top-level worker functions ------------------------------------
+    # (called from 'run()')
+
+    def build(self):
+        if not self.skip_build:
+            if self.distribution.has_pure_modules():
+                self.run_command('build_py')
+            if self.distribution.has_ext_modules():
+                self.run_command('build_ext')
+
+    def install(self):
+        if os.path.isdir(self.build_dir):
+            outfiles = self.copy_tree(self.build_dir, self.install_dir)
+        else:
+            self.warn("'%s' does not exist -- no Python modules to install" %
+                      self.build_dir)
+            return
+        return outfiles
+
+    def byte_compile(self, files):
+        if sys.dont_write_bytecode:
+            self.warn('byte-compiling is disabled, skipping.')
+            return
+
+        from distutils.util import byte_compile
+
+        # Get the "--root" directory supplied to the "install" command,
+        # and use it as a prefix to strip off the purported filename
+        # encoded in bytecode files.  This is far from complete, but it
+        # should at least generate usable bytecode in RPM distributions.
+        install_root = self.get_finalized_command('install').root
+
+        if self.compile:
+            byte_compile(files, optimize=0,
+                         force=self.force, prefix=install_root,
+                         dry_run=self.dry_run)
+        if self.optimize > 0:
+            byte_compile(files, optimize=self.optimize,
+                         force=self.force, prefix=install_root,
+                         verbose=self.verbose, dry_run=self.dry_run)
+
+
+    # -- Utility methods -----------------------------------------------
+
+    def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir):
+        if not has_any:
+            return []
+
+        build_cmd = self.get_finalized_command(build_cmd)
+        build_files = build_cmd.get_outputs()
+        build_dir = getattr(build_cmd, cmd_option)
+
+        prefix_len = len(build_dir) + len(os.sep)
+        outputs = []
+        for file in build_files:
+            outputs.append(os.path.join(output_dir, file[prefix_len:]))
+
+        return outputs
+
+    def _bytecode_filenames(self, py_filenames):
+        bytecode_files = []
+        for py_file in py_filenames:
+            # Since build_py handles package data installation, the
+            # list of outputs can contain more than just .py files.
+            # Make sure we only report bytecode for the .py files.
+            ext = os.path.splitext(os.path.normcase(py_file))[1]
+            if ext != PYTHON_SOURCE_EXTENSION:
+                continue
+            if self.compile:
+                bytecode_files.append(py_file + "c")
+            if self.optimize > 0:
+                bytecode_files.append(py_file + "o")
+
+        return bytecode_files
+
+
+    # -- External interface --------------------------------------------
+    # (called by outsiders)
+
+    def get_outputs(self):
+        """Return the list of files that would be installed if this command
+        were actually run.  Not affected by the "dry-run" flag or whether
+        modules have actually been built yet.
+        """
+        pure_outputs = \
+            self._mutate_outputs(self.distribution.has_pure_modules(),
+                                 'build_py', 'build_lib',
+                                 self.install_dir)
+        if self.compile:
+            bytecode_outputs = self._bytecode_filenames(pure_outputs)
+        else:
+            bytecode_outputs = []
+
+        ext_outputs = \
+            self._mutate_outputs(self.distribution.has_ext_modules(),
+                                 'build_ext', 'build_lib',
+                                 self.install_dir)
+
+        return pure_outputs + bytecode_outputs + ext_outputs
+
+    def get_inputs(self):
+        """Get the list of files that are input to this command, ie. the
+        files that get installed as they are named in the build tree.
+        The files in this list correspond one-to-one to the output
+        filenames returned by 'get_outputs()'.
+        """
+        inputs = []
+
+        if self.distribution.has_pure_modules():
+            build_py = self.get_finalized_command('build_py')
+            inputs.extend(build_py.get_outputs())
+
+        if self.distribution.has_ext_modules():
+            build_ext = self.get_finalized_command('build_ext')
+            inputs.extend(build_ext.get_outputs())
+
+        return inputs
diff --git a/src/main/resources/PythonLibs/distutils/command/install_scripts.py b/src/main/resources/PythonLibs/distutils/command/install_scripts.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0f4a2ea456e81a68ce51b2c2133e204e219ad6d
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/install_scripts.py
@@ -0,0 +1,64 @@
+"""distutils.command.install_scripts
+
+Implements the Distutils 'install_scripts' command, for installing
+Python scripts."""
+
+# contributed by Bastian Kleineidam
+
+__revision__ = "$Id: install_scripts.py 68943 2009-01-25 22:09:10Z tarek.ziade $"
+
+import os
+from distutils.core import Command
+from distutils import log
+from stat import ST_MODE
+
+class install_scripts (Command):
+
+    description = "install scripts (Python or otherwise)"
+
+    user_options = [
+        ('install-dir=', 'd', "directory to install scripts to"),
+        ('build-dir=','b', "build directory (where to install from)"),
+        ('force', 'f', "force installation (overwrite existing files)"),
+        ('skip-build', None, "skip the build steps"),
+    ]
+
+    boolean_options = ['force', 'skip-build']
+
+
+    def initialize_options (self):
+        self.install_dir = None
+        self.force = 0
+        self.build_dir = None
+        self.skip_build = None
+
+    def finalize_options (self):
+        self.set_undefined_options('build', ('build_scripts', 'build_dir'))
+        self.set_undefined_options('install',
+                                   ('install_scripts', 'install_dir'),
+                                   ('force', 'force'),
+                                   ('skip_build', 'skip_build'),
+                                  )
+
+    def run (self):
+        if not self.skip_build:
+            self.run_command('build_scripts')
+        self.outfiles = self.copy_tree(self.build_dir, self.install_dir)
+        if hasattr(os, 'chmod'):
+            # Set the executable bits (owner, group, and world) on
+            # all the scripts we just installed.
+            for file in self.get_outputs():
+                if self.dry_run:
+                    log.info("changing mode of %s", file)
+                else:
+                    mode = ((os.stat(file)[ST_MODE]) | 0555) & 07777
+                    log.info("changing mode of %s to %o", file, mode)
+                    os.chmod(file, mode)
+
+    def get_inputs (self):
+        return self.distribution.scripts or []
+
+    def get_outputs(self):
+        return self.outfiles or []
+
+# class install_scripts
diff --git a/src/main/resources/PythonLibs/distutils/command/register.py b/src/main/resources/PythonLibs/distutils/command/register.py
new file mode 100644
index 0000000000000000000000000000000000000000..edb42b955d6ab59276db6dc7da5188f61c84782d
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/register.py
@@ -0,0 +1,315 @@
+"""distutils.command.register
+
+Implements the Distutils 'register' command (register with the repository).
+"""
+
+# created 2002/10/21, Richard Jones
+
+__revision__ = "$Id$"
+
+import urllib2
+import getpass
+import urlparse
+from warnings import warn
+
+from distutils.core import PyPIRCCommand
+from distutils import log
+
+class register(PyPIRCCommand):
+
+    description = ("register the distribution with the Python package index")
+    user_options = PyPIRCCommand.user_options + [
+        ('list-classifiers', None,
+         'list the valid Trove classifiers'),
+        ('strict', None ,
+         'Will stop the registering if the meta-data are not fully compliant')
+        ]
+    boolean_options = PyPIRCCommand.boolean_options + [
+        'verify', 'list-classifiers', 'strict']
+
+    sub_commands = [('check', lambda self: True)]
+
+    def initialize_options(self):
+        PyPIRCCommand.initialize_options(self)
+        self.list_classifiers = 0
+        self.strict = 0
+
+    def finalize_options(self):
+        PyPIRCCommand.finalize_options(self)
+        # setting options for the `check` subcommand
+        check_options = {'strict': ('register', self.strict),
+                         'restructuredtext': ('register', 1)}
+        self.distribution.command_options['check'] = check_options
+
+    def run(self):
+        self.finalize_options()
+        self._set_config()
+
+        # Run sub commands
+        for cmd_name in self.get_sub_commands():
+            self.run_command(cmd_name)
+
+        if self.dry_run:
+            self.verify_metadata()
+        elif self.list_classifiers:
+            self.classifiers()
+        else:
+            self.send_metadata()
+
+    def check_metadata(self):
+        """Deprecated API."""
+        warn("distutils.command.register.check_metadata is deprecated, \
+              use the check command instead", PendingDeprecationWarning)
+        check = self.distribution.get_command_obj('check')
+        check.ensure_finalized()
+        check.strict = self.strict
+        check.restructuredtext = 1
+        check.run()
+
+    def _set_config(self):
+        ''' Reads the configuration file and set attributes.
+        '''
+        config = self._read_pypirc()
+        if config != {}:
+            self.username = config['username']
+            self.password = config['password']
+            self.repository = config['repository']
+            self.realm = config['realm']
+            self.has_config = True
+        else:
+            if self.repository not in ('pypi', self.DEFAULT_REPOSITORY):
+                raise ValueError('%s not found in .pypirc' % self.repository)
+            if self.repository == 'pypi':
+                self.repository = self.DEFAULT_REPOSITORY
+            self.has_config = False
+
+    def classifiers(self):
+        ''' Fetch the list of classifiers from the server.
+        '''
+        response = urllib2.urlopen(self.repository+'?:action=list_classifiers')
+        log.info(response.read())
+
+    def verify_metadata(self):
+        ''' Send the metadata to the package index server to be checked.
+        '''
+        # send the info to the server and report the result
+        (code, result) = self.post_to_server(self.build_post_data('verify'))
+        log.info('Server response (%s): %s' % (code, result))
+
+
+    def send_metadata(self):
+        ''' Send the metadata to the package index server.
+
+            Well, do the following:
+            1. figure who the user is, and then
+            2. send the data as a Basic auth'ed POST.
+
+            First we try to read the username/password from $HOME/.pypirc,
+            which is a ConfigParser-formatted file with a section
+            [distutils] containing username and password entries (both
+            in clear text). Eg:
+
+                [distutils]
+                index-servers =
+                    pypi
+
+                [pypi]
+                username: fred
+                password: sekrit
+
+            Otherwise, to figure who the user is, we offer the user three
+            choices:
+
+             1. use existing login,
+             2. register as a new user, or
+             3. set the password to a random string and email the user.
+
+        '''
+        # see if we can short-cut and get the username/password from the
+        # config
+        if self.has_config:
+            choice = '1'
+            username = self.username
+            password = self.password
+        else:
+            choice = 'x'
+            username = password = ''
+
+        # get the user's login info
+        choices = '1 2 3 4'.split()
+        while choice not in choices:
+            self.announce('''\
+We need to know who you are, so please choose either:
+ 1. use your existing login,
+ 2. register as a new user,
+ 3. have the server generate a new password for you (and email it to you), or
+ 4. quit
+Your selection [default 1]: ''', log.INFO)
+
+            choice = raw_input()
+            if not choice:
+                choice = '1'
+            elif choice not in choices:
+                print 'Please choose one of the four options!'
+
+        if choice == '1':
+            # get the username and password
+            while not username:
+                username = raw_input('Username: ')
+            while not password:
+                password = getpass.getpass('Password: ')
+
+            # set up the authentication
+            auth = urllib2.HTTPPasswordMgr()
+            host = urlparse.urlparse(self.repository)[1]
+            auth.add_password(self.realm, host, username, password)
+            # send the info to the server and report the result
+            code, result = self.post_to_server(self.build_post_data('submit'),
+                auth)
+            self.announce('Server response (%s): %s' % (code, result),
+                          log.INFO)
+
+            # possibly save the login
+            if code == 200:
+                if self.has_config:
+                    # sharing the password in the distribution instance
+                    # so the upload command can reuse it
+                    self.distribution.password = password
+                else:
+                    self.announce(('I can store your PyPI login so future '
+                                   'submissions will be faster.'), log.INFO)
+                    self.announce('(the login will be stored in %s)' % \
+                                  self._get_rc_file(), log.INFO)
+                    choice = 'X'
+                    while choice.lower() not in 'yn':
+                        choice = raw_input('Save your login (y/N)?')
+                        if not choice:
+                            choice = 'n'
+                    if choice.lower() == 'y':
+                        self._store_pypirc(username, password)
+
+        elif choice == '2':
+            data = {':action': 'user'}
+            data['name'] = data['password'] = data['email'] = ''
+            data['confirm'] = None
+            while not data['name']:
+                data['name'] = raw_input('Username: ')
+            while data['password'] != data['confirm']:
+                while not data['password']:
+                    data['password'] = getpass.getpass('Password: ')
+                while not data['confirm']:
+                    data['confirm'] = getpass.getpass(' Confirm: ')
+                if data['password'] != data['confirm']:
+                    data['password'] = ''
+                    data['confirm'] = None
+                    print "Password and confirm don't match!"
+            while not data['email']:
+                data['email'] = raw_input('   EMail: ')
+            code, result = self.post_to_server(data)
+            if code != 200:
+                log.info('Server response (%s): %s' % (code, result))
+            else:
+                log.info('You will receive an email shortly.')
+                log.info(('Follow the instructions in it to '
+                          'complete registration.'))
+        elif choice == '3':
+            data = {':action': 'password_reset'}
+            data['email'] = ''
+            while not data['email']:
+                data['email'] = raw_input('Your email address: ')
+            code, result = self.post_to_server(data)
+            log.info('Server response (%s): %s' % (code, result))
+
+    def build_post_data(self, action):
+        # figure the data to send - the metadata plus some additional
+        # information used by the package server
+        meta = self.distribution.metadata
+        data = {
+            ':action': action,
+            'metadata_version' : '1.0',
+            'name': meta.get_name(),
+            'version': meta.get_version(),
+            'summary': meta.get_description(),
+            'home_page': meta.get_url(),
+            'author': meta.get_contact(),
+            'author_email': meta.get_contact_email(),
+            'license': meta.get_licence(),
+            'description': meta.get_long_description(),
+            'keywords': meta.get_keywords(),
+            'platform': meta.get_platforms(),
+            'classifiers': meta.get_classifiers(),
+            'download_url': meta.get_download_url(),
+            # PEP 314
+            'provides': meta.get_provides(),
+            'requires': meta.get_requires(),
+            'obsoletes': meta.get_obsoletes(),
+        }
+        if data['provides'] or data['requires'] or data['obsoletes']:
+            data['metadata_version'] = '1.1'
+        return data
+
+    def post_to_server(self, data, auth=None):
+        ''' Post a query to the server, and return a string response.
+        '''
+        if 'name' in data:
+            self.announce('Registering %s to %s' % (data['name'],
+                                                   self.repository),
+                                                   log.INFO)
+        # Build up the MIME payload for the urllib2 POST data
+        boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
+        sep_boundary = '\n--' + boundary
+        end_boundary = sep_boundary + '--'
+        chunks = []
+        for key, value in data.items():
+            # handle multiple entries for the same name
+            if type(value) not in (type([]), type( () )):
+                value = [value]
+            for value in value:
+                chunks.append(sep_boundary)
+                chunks.append('\nContent-Disposition: form-data; name="%s"'%key)
+                chunks.append("\n\n")
+                chunks.append(value)
+                if value and value[-1] == '\r':
+                    chunks.append('\n')  # write an extra newline (lurve Macs)
+        chunks.append(end_boundary)
+        chunks.append("\n")
+
+        # chunks may be bytes (str) or unicode objects that we need to encode
+        body = []
+        for chunk in chunks:
+            if isinstance(chunk, unicode):
+                body.append(chunk.encode('utf-8'))
+            else:
+                body.append(chunk)
+
+        body = ''.join(body)
+
+        # build the Request
+        headers = {
+            'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8'%boundary,
+            'Content-length': str(len(body))
+        }
+        req = urllib2.Request(self.repository, body, headers)
+
+        # handle HTTP and include the Basic Auth handler
+        opener = urllib2.build_opener(
+            urllib2.HTTPBasicAuthHandler(password_mgr=auth)
+        )
+        data = ''
+        try:
+            result = opener.open(req)
+        except urllib2.HTTPError, e:
+            if self.show_response:
+                data = e.fp.read()
+            result = e.code, e.msg
+        except urllib2.URLError, e:
+            result = 500, str(e)
+        else:
+            if self.show_response:
+                data = result.read()
+            result = 200, 'OK'
+        if self.show_response:
+            dashes = '-' * 75
+            self.announce('%s%s%s' % (dashes, data, dashes))
+
+        return result
diff --git a/src/main/resources/PythonLibs/distutils/command/sdist.py b/src/main/resources/PythonLibs/distutils/command/sdist.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca3e0b5cc6feab48bd5a039301f81bb94e5ff66b
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/sdist.py
@@ -0,0 +1,469 @@
+"""distutils.command.sdist
+
+Implements the Distutils 'sdist' command (create a source distribution)."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: sdist.py 61268 2008-03-06 07:14:26Z martin.v.loewis $"
+
+import sys, os, string
+from types import *
+from glob import glob
+from distutils.core import Command
+from distutils import dir_util, dep_util, file_util, archive_util
+from distutils.text_file import TextFile
+from distutils.errors import *
+from distutils.filelist import FileList
+from distutils import log
+
+
+def show_formats ():
+    """Print all possible values for the 'formats' option (used by
+    the "--help-formats" command-line option).
+    """
+    from distutils.fancy_getopt import FancyGetopt
+    from distutils.archive_util import ARCHIVE_FORMATS
+    formats=[]
+    for format in ARCHIVE_FORMATS.keys():
+        formats.append(("formats=" + format, None,
+                        ARCHIVE_FORMATS[format][2]))
+    formats.sort()
+    pretty_printer = FancyGetopt(formats)
+    pretty_printer.print_help(
+        "List of available source distribution formats:")
+
+class sdist (Command):
+
+    description = "create a source distribution (tarball, zip file, etc.)"
+
+    user_options = [
+        ('template=', 't',
+         "name of manifest template file [default: MANIFEST.in]"),
+        ('manifest=', 'm',
+         "name of manifest file [default: MANIFEST]"),
+        ('use-defaults', None,
+         "include the default file set in the manifest "
+         "[default; disable with --no-defaults]"),
+        ('no-defaults', None,
+         "don't include the default file set"),
+        ('prune', None,
+         "specifically exclude files/directories that should not be "
+         "distributed (build tree, RCS/CVS dirs, etc.) "
+         "[default; disable with --no-prune]"),
+        ('no-prune', None,
+         "don't automatically exclude anything"),
+        ('manifest-only', 'o',
+         "just regenerate the manifest and then stop "
+         "(implies --force-manifest)"),
+        ('force-manifest', 'f',
+         "forcibly regenerate the manifest and carry on as usual"),
+        ('formats=', None,
+         "formats for source distribution (comma-separated list)"),
+        ('keep-temp', 'k',
+         "keep the distribution tree around after creating " +
+         "archive file(s)"),
+        ('dist-dir=', 'd',
+         "directory to put the source distribution archive(s) in "
+         "[default: dist]"),
+        ]
+
+    boolean_options = ['use-defaults', 'prune',
+                       'manifest-only', 'force-manifest',
+                       'keep-temp']
+
+    help_options = [
+        ('help-formats', None,
+         "list available distribution formats", show_formats),
+        ]
+
+    negative_opt = {'no-defaults': 'use-defaults',
+                    'no-prune': 'prune' }
+
+    default_format = { 'posix': 'gztar',
+                       'java': 'gztar',
+                       'nt': 'zip' }
+
+    def initialize_options (self):
+        # 'template' and 'manifest' are, respectively, the names of
+        # the manifest template and manifest file.
+        self.template = None
+        self.manifest = None
+
+        # 'use_defaults': if true, we will include the default file set
+        # in the manifest
+        self.use_defaults = 1
+        self.prune = 1
+
+        self.manifest_only = 0
+        self.force_manifest = 0
+
+        self.formats = None
+        self.keep_temp = 0
+        self.dist_dir = None
+
+        self.archive_files = None
+
+
+    def finalize_options (self):
+        if self.manifest is None:
+            self.manifest = "MANIFEST"
+        if self.template is None:
+            self.template = "MANIFEST.in"
+
+        self.ensure_string_list('formats')
+        if self.formats is None:
+            try:
+                self.formats = [self.default_format[os.name]]
+            except KeyError:
+                raise DistutilsPlatformError, \
+                      "don't know how to create source distributions " + \
+                      "on platform %s" % os.name
+
+        bad_format = archive_util.check_archive_formats(self.formats)
+        if bad_format:
+            raise DistutilsOptionError, \
+                  "unknown archive format '%s'" % bad_format
+
+        if self.dist_dir is None:
+            self.dist_dir = "dist"
+
+
+    def run (self):
+
+        # 'filelist' contains the list of files that will make up the
+        # manifest
+        self.filelist = FileList()
+
+        # Ensure that all required meta-data is given; warn if not (but
+        # don't die, it's not *that* serious!)
+        self.check_metadata()
+
+        # Do whatever it takes to get the list of files to process
+        # (process the manifest template, read an existing manifest,
+        # whatever).  File list is accumulated in 'self.filelist'.
+        self.get_file_list()
+
+        # If user just wanted us to regenerate the manifest, stop now.
+        if self.manifest_only:
+            return
+
+        # Otherwise, go ahead and create the source distribution tarball,
+        # or zipfile, or whatever.
+        self.make_distribution()
+
+
+    def check_metadata (self):
+        """Ensure that all required elements of meta-data (name, version,
+        URL, (author and author_email) or (maintainer and
+        maintainer_email)) are supplied by the Distribution object; warn if
+        any are missing.
+        """
+        metadata = self.distribution.metadata
+
+        missing = []
+        for attr in ('name', 'version', 'url'):
+            if not (hasattr(metadata, attr) and getattr(metadata, attr)):
+                missing.append(attr)
+
+        if missing:
+            self.warn("missing required meta-data: " +
+                      string.join(missing, ", "))
+
+        if metadata.author:
+            if not metadata.author_email:
+                self.warn("missing meta-data: if 'author' supplied, " +
+                          "'author_email' must be supplied too")
+        elif metadata.maintainer:
+            if not metadata.maintainer_email:
+                self.warn("missing meta-data: if 'maintainer' supplied, " +
+                          "'maintainer_email' must be supplied too")
+        else:
+            self.warn("missing meta-data: either (author and author_email) " +
+                      "or (maintainer and maintainer_email) " +
+                      "must be supplied")
+
+    # check_metadata ()
+
+
+    def get_file_list (self):
+        """Figure out the list of files to include in the source
+        distribution, and put it in 'self.filelist'.  This might involve
+        reading the manifest template (and writing the manifest), or just
+        reading the manifest, or just using the default file set -- it all
+        depends on the user's options and the state of the filesystem.
+        """
+
+        # If we have a manifest template, see if it's newer than the
+        # manifest; if so, we'll regenerate the manifest.
+        template_exists = os.path.isfile(self.template)
+        if template_exists:
+            template_newer = dep_util.newer(self.template, self.manifest)
+
+        # The contents of the manifest file almost certainly depend on the
+        # setup script as well as the manifest template -- so if the setup
+        # script is newer than the manifest, we'll regenerate the manifest
+        # from the template.  (Well, not quite: if we already have a
+        # manifest, but there's no template -- which will happen if the
+        # developer elects to generate a manifest some other way -- then we
+        # can't regenerate the manifest, so we don't.)
+        self.debug_print("checking if %s newer than %s" %
+                         (self.distribution.script_name, self.manifest))
+        setup_newer = dep_util.newer(self.distribution.script_name,
+                                     self.manifest)
+
+        # cases:
+        #   1) no manifest, template exists: generate manifest
+        #      (covered by 2a: no manifest == template newer)
+        #   2) manifest & template exist:
+        #      2a) template or setup script newer than manifest:
+        #          regenerate manifest
+        #      2b) manifest newer than both:
+        #          do nothing (unless --force or --manifest-only)
+        #   3) manifest exists, no template:
+        #      do nothing (unless --force or --manifest-only)
+        #   4) no manifest, no template: generate w/ warning ("defaults only")
+
+        manifest_outofdate = (template_exists and
+                              (template_newer or setup_newer))
+        force_regen = self.force_manifest or self.manifest_only
+        manifest_exists = os.path.isfile(self.manifest)
+        neither_exists = (not template_exists and not manifest_exists)
+
+        # Regenerate the manifest if necessary (or if explicitly told to)
+        if manifest_outofdate or neither_exists or force_regen:
+            if not template_exists:
+                self.warn(("manifest template '%s' does not exist " +
+                           "(using default file list)") %
+                          self.template)
+            self.filelist.findall()
+
+            if self.use_defaults:
+                self.add_defaults()
+            if template_exists:
+                self.read_template()
+            if self.prune:
+                self.prune_file_list()
+
+            self.filelist.sort()
+            self.filelist.remove_duplicates()
+            self.write_manifest()
+
+        # Don't regenerate the manifest, just read it in.
+        else:
+            self.read_manifest()
+
+    # get_file_list ()
+
+
+    def add_defaults (self):
+        """Add all the default files to self.filelist:
+          - README or README.txt
+          - setup.py
+          - test/test*.py
+          - all pure Python modules mentioned in setup script
+          - all C sources listed as part of extensions or C libraries
+            in the setup script (doesn't catch C headers!)
+        Warns if (README or README.txt) or setup.py are missing; everything
+        else is optional.
+        """
+
+        standards = [('README', 'README.txt'), self.distribution.script_name]
+        for fn in standards:
+            if type(fn) is TupleType:
+                alts = fn
+                got_it = 0
+                for fn in alts:
+                    if os.path.exists(fn):
+                        got_it = 1
+                        self.filelist.append(fn)
+                        break
+
+                if not got_it:
+                    self.warn("standard file not found: should have one of " +
+                              string.join(alts, ', '))
+            else:
+                if os.path.exists(fn):
+                    self.filelist.append(fn)
+                else:
+                    self.warn("standard file '%s' not found" % fn)
+
+        optional = ['test/test*.py', 'setup.cfg']
+        for pattern in optional:
+            files = filter(os.path.isfile, glob(pattern))
+            if files:
+                self.filelist.extend(files)
+
+        if self.distribution.has_pure_modules():
+            build_py = self.get_finalized_command('build_py')
+            self.filelist.extend(build_py.get_source_files())
+
+        if self.distribution.has_ext_modules():
+            build_ext = self.get_finalized_command('build_ext')
+            self.filelist.extend(build_ext.get_source_files())
+
+        if self.distribution.has_c_libraries():
+            build_clib = self.get_finalized_command('build_clib')
+            self.filelist.extend(build_clib.get_source_files())
+
+        if self.distribution.has_scripts():
+            build_scripts = self.get_finalized_command('build_scripts')
+            self.filelist.extend(build_scripts.get_source_files())
+
+    # add_defaults ()
+
+
+    def read_template (self):
+        """Read and parse manifest template file named by self.template.
+
+        (usually "MANIFEST.in") The parsing and processing is done by
+        'self.filelist', which updates itself accordingly.
+        """
+        log.info("reading manifest template '%s'", self.template)
+        template = TextFile(self.template,
+                            strip_comments=1,
+                            skip_blanks=1,
+                            join_lines=1,
+                            lstrip_ws=1,
+                            rstrip_ws=1,
+                            collapse_join=1)
+
+        while 1:
+            line = template.readline()
+            if line is None:            # end of file
+                break
+
+            try:
+                self.filelist.process_template_line(line)
+            except DistutilsTemplateError, msg:
+                self.warn("%s, line %d: %s" % (template.filename,
+                                               template.current_line,
+                                               msg))
+
+    # read_template ()
+
+
+    def prune_file_list (self):
+        """Prune off branches that might slip into the file list as created
+        by 'read_template()', but really don't belong there:
+          * the build tree (typically "build")
+          * the release tree itself (only an issue if we ran "sdist"
+            previously with --keep-temp, or it aborted)
+          * any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories
+        """
+        build = self.get_finalized_command('build')
+        base_dir = self.distribution.get_fullname()
+
+        self.filelist.exclude_pattern(None, prefix=build.build_base)
+        self.filelist.exclude_pattern(None, prefix=base_dir)
+        self.filelist.exclude_pattern(r'(^|/)(RCS|CVS|\.svn|\.hg|\.git|\.bzr|_darcs)/.*', is_regex=1)
+
+
+    def write_manifest (self):
+        """Write the file list in 'self.filelist' (presumably as filled in
+        by 'add_defaults()' and 'read_template()') to the manifest file
+        named by 'self.manifest'.
+        """
+        self.execute(file_util.write_file,
+                     (self.manifest, self.filelist.files),
+                     "writing manifest file '%s'" % self.manifest)
+
+    # write_manifest ()
+
+
+    def read_manifest (self):
+        """Read the manifest file (named by 'self.manifest') and use it to
+        fill in 'self.filelist', the list of files to include in the source
+        distribution.
+        """
+        log.info("reading manifest file '%s'", self.manifest)
+        manifest = open(self.manifest)
+        try:
+            while 1:
+                line = manifest.readline()
+                if line == '':              # end of file
+                    break
+                if line[-1] == '\n':
+                    line = line[0:-1]
+                self.filelist.append(line)
+        finally:
+            manifest.close()
+
+    # read_manifest ()
+
+
+    def make_release_tree (self, base_dir, files):
+        """Create the directory tree that will become the source
+        distribution archive.  All directories implied by the filenames in
+        'files' are created under 'base_dir', and then we hard link or copy
+        (if hard linking is unavailable) those files into place.
+        Essentially, this duplicates the developer's source tree, but in a
+        directory named after the distribution, containing only the files
+        to be distributed.
+        """
+        # Create all the directories under 'base_dir' necessary to
+        # put 'files' there; the 'mkpath()' is just so we don't die
+        # if the manifest happens to be empty.
+        self.mkpath(base_dir)
+        dir_util.create_tree(base_dir, files, dry_run=self.dry_run)
+
+        # And walk over the list of files, either making a hard link (if
+        # os.link exists) to each one that doesn't already exist in its
+        # corresponding location under 'base_dir', or copying each file
+        # that's out-of-date in 'base_dir'.  (Usually, all files will be
+        # out-of-date, because by default we blow away 'base_dir' when
+        # we're done making the distribution archives.)
+
+        if hasattr(os, 'link'):        # can make hard links on this system
+            link = 'hard'
+            msg = "making hard links in %s..." % base_dir
+        else:                           # nope, have to copy
+            link = None
+            msg = "copying files to %s..." % base_dir
+
+        if not files:
+            log.warn("no files to distribute -- empty manifest?")
+        else:
+            log.info(msg)
+        for file in files:
+            if not os.path.isfile(file):
+                log.warn("'%s' not a regular file -- skipping" % file)
+            else:
+                dest = os.path.join(base_dir, file)
+                self.copy_file(file, dest, link=link)
+
+        self.distribution.metadata.write_pkg_info(base_dir)
+
+    # make_release_tree ()
+
+    def make_distribution (self):
+        """Create the source distribution(s).  First, we create the release
+        tree with 'make_release_tree()'; then, we create all required
+        archive files (according to 'self.formats') from the release tree.
+        Finally, we clean up by blowing away the release tree (unless
+        'self.keep_temp' is true).  The list of archive files created is
+        stored so it can be retrieved later by 'get_archive_files()'.
+        """
+        # Don't warn about missing meta-data here -- should be (and is!)
+        # done elsewhere.
+        base_dir = self.distribution.get_fullname()
+        base_name = os.path.join(self.dist_dir, base_dir)
+
+        self.make_release_tree(base_dir, self.filelist.files)
+        archive_files = []              # remember names of files we create
+        for fmt in self.formats:
+            file = self.make_archive(base_name, fmt, base_dir=base_dir)
+            archive_files.append(file)
+            self.distribution.dist_files.append(('sdist', '', file))
+
+        self.archive_files = archive_files
+
+        if not self.keep_temp:
+            dir_util.remove_tree(base_dir, dry_run=self.dry_run)
+
+    def get_archive_files (self):
+        """Return the list of archive files created when the command
+        was run, or None if the command hasn't run yet.
+        """
+        return self.archive_files
+
+# class sdist
diff --git a/src/main/resources/PythonLibs/distutils/command/upload.py b/src/main/resources/PythonLibs/distutils/command/upload.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0133353a63a6c4aed923cf16db3a2fa2b96afac
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/command/upload.py
@@ -0,0 +1,194 @@
+"""distutils.command.upload
+
+Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
+import os
+import socket
+import platform
+from urllib2 import urlopen, Request, HTTPError
+from base64 import standard_b64encode
+import urlparse
+import cStringIO as StringIO
+from hashlib import md5
+
+from distutils.errors import DistutilsOptionError
+from distutils.core import PyPIRCCommand
+from distutils.spawn import spawn
+from distutils import log
+
+class upload(PyPIRCCommand):
+
+    description = "upload binary package to PyPI"
+
+    user_options = PyPIRCCommand.user_options + [
+        ('sign', 's',
+         'sign files to upload using gpg'),
+        ('identity=', 'i', 'GPG identity used to sign files'),
+        ]
+
+    boolean_options = PyPIRCCommand.boolean_options + ['sign']
+
+    def initialize_options(self):
+        PyPIRCCommand.initialize_options(self)
+        self.username = ''
+        self.password = ''
+        self.show_response = 0
+        self.sign = False
+        self.identity = None
+
+    def finalize_options(self):
+        PyPIRCCommand.finalize_options(self)
+        if self.identity and not self.sign:
+            raise DistutilsOptionError(
+                "Must use --sign for --identity to have meaning"
+            )
+        config = self._read_pypirc()
+        if config != {}:
+            self.username = config['username']
+            self.password = config['password']
+            self.repository = config['repository']
+            self.realm = config['realm']
+
+        # getting the password from the distribution
+        # if previously set by the register command
+        if not self.password and self.distribution.password:
+            self.password = self.distribution.password
+
+    def run(self):
+        if not self.distribution.dist_files:
+            raise DistutilsOptionError("No dist file created in earlier command")
+        for command, pyversion, filename in self.distribution.dist_files:
+            self.upload_file(command, pyversion, filename)
+
+    def upload_file(self, command, pyversion, filename):
+        # Makes sure the repository URL is compliant
+        schema, netloc, url, params, query, fragments = \
+            urlparse.urlparse(self.repository)
+        if params or query or fragments:
+            raise AssertionError("Incompatible url %s" % self.repository)
+
+        if schema not in ('http', 'https'):
+            raise AssertionError("unsupported schema " + schema)
+
+        # Sign if requested
+        if self.sign:
+            gpg_args = ["gpg", "--detach-sign", "-a", filename]
+            if self.identity:
+                gpg_args[2:2] = ["--local-user", self.identity]
+            spawn(gpg_args,
+                  dry_run=self.dry_run)
+
+        # Fill in the data - send all the meta-data in case we need to
+        # register a new release
+        f = open(filename,'rb')
+        try:
+            content = f.read()
+        finally:
+            f.close()
+        meta = self.distribution.metadata
+        data = {
+            # action
+            ':action': 'file_upload',
+            'protcol_version': '1',
+
+            # identify release
+            'name': meta.get_name(),
+            'version': meta.get_version(),
+
+            # file content
+            'content': (os.path.basename(filename),content),
+            'filetype': command,
+            'pyversion': pyversion,
+            'md5_digest': md5(content).hexdigest(),
+
+            # additional meta-data
+            'metadata_version' : '1.0',
+            'summary': meta.get_description(),
+            'home_page': meta.get_url(),
+            'author': meta.get_contact(),
+            'author_email': meta.get_contact_email(),
+            'license': meta.get_licence(),
+            'description': meta.get_long_description(),
+            'keywords': meta.get_keywords(),
+            'platform': meta.get_platforms(),
+            'classifiers': meta.get_classifiers(),
+            'download_url': meta.get_download_url(),
+            # PEP 314
+            'provides': meta.get_provides(),
+            'requires': meta.get_requires(),
+            'obsoletes': meta.get_obsoletes(),
+            }
+        comment = ''
+        if command == 'bdist_rpm':
+            dist, version, id = platform.dist()
+            if dist:
+                comment = 'built for %s %s' % (dist, version)
+        elif command == 'bdist_dumb':
+            comment = 'built for %s' % platform.platform(terse=1)
+        data['comment'] = comment
+
+        if self.sign:
+            data['gpg_signature'] = (os.path.basename(filename) + ".asc",
+                                     open(filename+".asc").read())
+
+        # set up the authentication
+        auth = "Basic " + standard_b64encode(self.username + ":" +
+                                             self.password)
+
+        # Build up the MIME payload for the POST data
+        boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
+        sep_boundary = '\n--' + boundary
+        end_boundary = sep_boundary + '--'
+        body = StringIO.StringIO()
+        for key, value in data.items():
+            # handle multiple entries for the same name
+            if not isinstance(value, list):
+                value = [value]
+            for value in value:
+                if isinstance(value, tuple):
+                    fn = ';filename="%s"' % value[0]
+                    value = value[1]
+                else:
+                    fn = ""
+
+                body.write(sep_boundary)
+                body.write('\nContent-Disposition: form-data; name="%s"'%key)
+                body.write(fn)
+                body.write("\n\n")
+                body.write(value)
+                if value and value[-1] == '\r':
+                    body.write('\n')  # write an extra newline (lurve Macs)
+        body.write(end_boundary)
+        body.write("\n")
+        body = body.getvalue()
+
+        self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
+
+        # build the Request
+        headers = {'Content-type':
+                        'multipart/form-data; boundary=%s' % boundary,
+                   'Content-length': str(len(body)),
+                   'Authorization': auth}
+
+        request = Request(self.repository, data=body,
+                          headers=headers)
+        # send the data
+        try:
+            result = urlopen(request)
+            status = result.getcode()
+            reason = result.msg
+            if self.show_response:
+                msg = '\n'.join(('-' * 75, r.read(), '-' * 75))
+                self.announce(msg, log.INFO)
+        except socket.error, e:
+            self.announce(str(e), log.ERROR)
+            return
+        except HTTPError, e:
+            status = e.code
+            reason = e.msg
+
+        if status == 200:
+            self.announce('Server response (%s): %s' % (status, reason),
+                          log.INFO)
+        else:
+            self.announce('Upload failed (%s): %s' % (status, reason),
+                          log.ERROR)
diff --git a/src/main/resources/PythonLibs/distutils/command/wininst-6.0.exe b/src/main/resources/PythonLibs/distutils/command/wininst-6.0.exe
new file mode 100644
index 0000000000000000000000000000000000000000..f57c855a613e2de2b00fff1df431b8d08d171077
Binary files /dev/null and b/src/main/resources/PythonLibs/distutils/command/wininst-6.0.exe differ
diff --git a/src/main/resources/PythonLibs/distutils/command/wininst-7.1.exe b/src/main/resources/PythonLibs/distutils/command/wininst-7.1.exe
new file mode 100644
index 0000000000000000000000000000000000000000..1433bc1ad3775ec9277e13ca8bdca3a5dbc23643
Binary files /dev/null and b/src/main/resources/PythonLibs/distutils/command/wininst-7.1.exe differ
diff --git a/src/main/resources/PythonLibs/distutils/command/wininst-8.0.exe b/src/main/resources/PythonLibs/distutils/command/wininst-8.0.exe
new file mode 100644
index 0000000000000000000000000000000000000000..7403bfabf5cc10c13ef2b6a2ea276b4f6d26ff37
Binary files /dev/null and b/src/main/resources/PythonLibs/distutils/command/wininst-8.0.exe differ
diff --git a/src/main/resources/PythonLibs/distutils/command/wininst-9.0-amd64.exe b/src/main/resources/PythonLibs/distutils/command/wininst-9.0-amd64.exe
new file mode 100644
index 0000000000000000000000000000000000000000..11d8011c717c3a1c54afbe00e002fab6d37766c6
Binary files /dev/null and b/src/main/resources/PythonLibs/distutils/command/wininst-9.0-amd64.exe differ
diff --git a/src/main/resources/PythonLibs/distutils/command/wininst-9.0.exe b/src/main/resources/PythonLibs/distutils/command/wininst-9.0.exe
new file mode 100644
index 0000000000000000000000000000000000000000..dadb31d8938b9b147830382495eee2453c171648
Binary files /dev/null and b/src/main/resources/PythonLibs/distutils/command/wininst-9.0.exe differ
diff --git a/src/main/resources/PythonLibs/distutils/config.py b/src/main/resources/PythonLibs/distutils/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d327143bea711c3e6e765d3a6dab8f80da89da7
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/config.py
@@ -0,0 +1,116 @@
+"""distutils.pypirc
+
+Provides the PyPIRCCommand class, the base class for the command classes
+that uses .pypirc in the distutils.command package.
+"""
+import os
+from ConfigParser import ConfigParser
+
+from distutils.cmd import Command
+
+DEFAULT_PYPIRC = """\
+[distutils]
+index-servers =
+    pypi
+
+[pypi]
+username:%s
+password:%s
+"""
+
+class PyPIRCCommand(Command):
+    """Base command that knows how to handle the .pypirc file
+    """
+    DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
+    DEFAULT_REALM = 'pypi'
+    repository = None
+    realm = None
+
+    user_options = [
+        ('repository=', 'r',
+         "url of repository [default: %s]" % \
+            DEFAULT_REPOSITORY),
+        ('show-response', None,
+         'display full response text from server')]
+
+    boolean_options = ['show-response']
+
+    def _get_rc_file(self):
+        """Returns rc file path."""
+        return os.path.join(os.path.expanduser('~'), '.pypirc')
+
+    def _store_pypirc(self, username, password):
+        """Creates a default .pypirc file."""
+        rc = self._get_rc_file()
+        f = os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0600), 'w')
+        try:
+            f.write(DEFAULT_PYPIRC % (username, password))
+        finally:
+            f.close()
+
+    def _read_pypirc(self):
+        """Reads the .pypirc file."""
+        rc = self._get_rc_file()
+        if os.path.exists(rc):
+            self.announce('Using PyPI login from %s' % rc)
+            repository = self.repository or self.DEFAULT_REPOSITORY
+            config = ConfigParser()
+            config.read(rc)
+            sections = config.sections()
+            if 'distutils' in sections:
+                # let's get the list of servers
+                index_servers = config.get('distutils', 'index-servers')
+                _servers = [server.strip() for server in
+                            index_servers.split('\n')
+                            if server.strip() != '']
+                if _servers == []:
+                    # nothing set, let's try to get the default pypi
+                    if 'pypi' in sections:
+                        _servers = ['pypi']
+                    else:
+                        # the file is not properly defined, returning
+                        # an empty dict
+                        return {}
+                for server in _servers:
+                    current = {'server': server}
+                    current['username'] = config.get(server, 'username')
+
+                    # optional params
+                    for key, default in (('repository',
+                                          self.DEFAULT_REPOSITORY),
+                                         ('realm', self.DEFAULT_REALM),
+                                         ('password', None)):
+                        if config.has_option(server, key):
+                            current[key] = config.get(server, key)
+                        else:
+                            current[key] = default
+                    if (current['server'] == repository or
+                        current['repository'] == repository):
+                        return current
+            elif 'server-login' in sections:
+                # old format
+                server = 'server-login'
+                if config.has_option(server, 'repository'):
+                    repository = config.get(server, 'repository')
+                else:
+                    repository = self.DEFAULT_REPOSITORY
+                return {'username': config.get(server, 'username'),
+                        'password': config.get(server, 'password'),
+                        'repository': repository,
+                        'server': server,
+                        'realm': self.DEFAULT_REALM}
+
+        return {}
+
+    def initialize_options(self):
+        """Initialize options."""
+        self.repository = None
+        self.realm = None
+        self.show_response = 0
+
+    def finalize_options(self):
+        """Finalizes options."""
+        if self.repository is None:
+            self.repository = self.DEFAULT_REPOSITORY
+        if self.realm is None:
+            self.realm = self.DEFAULT_REALM
diff --git a/src/main/resources/PythonLibs/distutils/core.py b/src/main/resources/PythonLibs/distutils/core.py
new file mode 100644
index 0000000000000000000000000000000000000000..b89557d7679ce9e7f8ce8df8957e5d7175332695
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/core.py
@@ -0,0 +1,242 @@
+"""distutils.core
+
+The only module that needs to be imported to use the Distutils; provides
+the 'setup' function (which is to be called from the setup script).  Also
+indirectly provides the Distribution and Command classes, although they are
+really defined in distutils.dist and distutils.cmd.
+"""
+
+__revision__ = "$Id$"
+
+import sys
+import os
+
+from distutils.debug import DEBUG
+from distutils.errors import (DistutilsSetupError, DistutilsArgError,
+                              DistutilsError, CCompilerError)
+from distutils.util import grok_environment_error
+
+# Mainly import these so setup scripts can "from distutils.core import" them.
+from distutils.dist import Distribution
+from distutils.cmd import Command
+from distutils.config import PyPIRCCommand
+from distutils.extension import Extension
+
+# This is a barebones help message generated displayed when the user
+# runs the setup script with no arguments at all.  More useful help
+# is generated with various --help options: global help, list commands,
+# and per-command help.
+USAGE = """\
+usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
+   or: %(script)s --help [cmd1 cmd2 ...]
+   or: %(script)s --help-commands
+   or: %(script)s cmd --help
+"""
+
+def gen_usage(script_name):
+    script = os.path.basename(script_name)
+    return USAGE % {'script': script}
+
+
+# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'.
+_setup_stop_after = None
+_setup_distribution = None
+
+# Legal keyword arguments for the setup() function
+setup_keywords = ('distclass', 'script_name', 'script_args', 'options',
+                  'name', 'version', 'author', 'author_email',
+                  'maintainer', 'maintainer_email', 'url', 'license',
+                  'description', 'long_description', 'keywords',
+                  'platforms', 'classifiers', 'download_url',
+                  'requires', 'provides', 'obsoletes',
+                  )
+
+# Legal keyword arguments for the Extension constructor
+extension_keywords = ('name', 'sources', 'include_dirs',
+                      'define_macros', 'undef_macros',
+                      'library_dirs', 'libraries', 'runtime_library_dirs',
+                      'extra_objects', 'extra_compile_args', 'extra_link_args',
+                      'swig_opts', 'export_symbols', 'depends', 'language')
+
+def setup(**attrs):
+    """The gateway to the Distutils: do everything your setup script needs
+    to do, in a highly flexible and user-driven way.  Briefly: create a
+    Distribution instance; find and parse config files; parse the command
+    line; run each Distutils command found there, customized by the options
+    supplied to 'setup()' (as keyword arguments), in config files, and on
+    the command line.
+
+    The Distribution instance might be an instance of a class supplied via
+    the 'distclass' keyword argument to 'setup'; if no such class is
+    supplied, then the Distribution class (in dist.py) is instantiated.
+    All other arguments to 'setup' (except for 'cmdclass') are used to set
+    attributes of the Distribution instance.
+
+    The 'cmdclass' argument, if supplied, is a dictionary mapping command
+    names to command classes.  Each command encountered on the command line
+    will be turned into a command class, which is in turn instantiated; any
+    class found in 'cmdclass' is used in place of the default, which is
+    (for command 'foo_bar') class 'foo_bar' in module
+    'distutils.command.foo_bar'.  The command class must provide a
+    'user_options' attribute which is a list of option specifiers for
+    'distutils.fancy_getopt'.  Any command-line options between the current
+    and the next command are used to set attributes of the current command
+    object.
+
+    When the entire command-line has been successfully parsed, calls the
+    'run()' method on each command object in turn.  This method will be
+    driven entirely by the Distribution object (which each command object
+    has a reference to, thanks to its constructor), and the
+    command-specific options that became attributes of each command
+    object.
+    """
+
+    global _setup_stop_after, _setup_distribution
+
+    # Determine the distribution class -- either caller-supplied or
+    # our Distribution (see below).
+    klass = attrs.get('distclass')
+    if klass:
+        del attrs['distclass']
+    else:
+        klass = Distribution
+
+    if 'script_name' not in attrs:
+        attrs['script_name'] = os.path.basename(sys.argv[0])
+    if 'script_args' not in attrs:
+        attrs['script_args'] = sys.argv[1:]
+
+    # Create the Distribution instance, using the remaining arguments
+    # (ie. everything except distclass) to initialize it
+    try:
+        _setup_distribution = dist = klass(attrs)
+    except DistutilsSetupError, msg:
+        if 'name' in attrs:
+            raise SystemExit, "error in %s setup command: %s" % \
+                  (attrs['name'], msg)
+        else:
+            raise SystemExit, "error in setup command: %s" % msg
+
+    if _setup_stop_after == "init":
+        return dist
+
+    # Find and parse the config file(s): they will override options from
+    # the setup script, but be overridden by the command line.
+    dist.parse_config_files()
+
+    if DEBUG:
+        print "options (after parsing config files):"
+        dist.dump_option_dicts()
+
+    if _setup_stop_after == "config":
+        return dist
+
+    # Parse the command line and override config files; any
+    # command-line errors are the end user's fault, so turn them into
+    # SystemExit to suppress tracebacks.
+    try:
+        ok = dist.parse_command_line()
+    except DistutilsArgError, msg:
+        raise SystemExit, gen_usage(dist.script_name) + "\nerror: %s" % msg
+
+    if DEBUG:
+        print "options (after parsing command line):"
+        dist.dump_option_dicts()
+
+    if _setup_stop_after == "commandline":
+        return dist
+
+    # And finally, run all the commands found on the command line.
+    if ok:
+        try:
+            dist.run_commands()
+        except KeyboardInterrupt:
+            raise SystemExit, "interrupted"
+        except (IOError, os.error), exc:
+            error = grok_environment_error(exc)
+
+            if DEBUG:
+                sys.stderr.write(error + "\n")
+                raise
+            else:
+                raise SystemExit, error
+
+        except (DistutilsError,
+                CCompilerError), msg:
+            if DEBUG:
+                raise
+            else:
+                raise SystemExit, "error: " + str(msg)
+
+    return dist
+
+
+def run_setup(script_name, script_args=None, stop_after="run"):
+    """Run a setup script in a somewhat controlled environment, and
+    return the Distribution instance that drives things.  This is useful
+    if you need to find out the distribution meta-data (passed as
+    keyword args from 'script' to 'setup()', or the contents of the
+    config files or command-line.
+
+    'script_name' is a file that will be run with 'execfile()';
+    'sys.argv[0]' will be replaced with 'script' for the duration of the
+    call.  'script_args' is a list of strings; if supplied,
+    'sys.argv[1:]' will be replaced by 'script_args' for the duration of
+    the call.
+
+    'stop_after' tells 'setup()' when to stop processing; possible
+    values:
+      init
+        stop after the Distribution instance has been created and
+        populated with the keyword arguments to 'setup()'
+      config
+        stop after config files have been parsed (and their data
+        stored in the Distribution instance)
+      commandline
+        stop after the command-line ('sys.argv[1:]' or 'script_args')
+        have been parsed (and the data stored in the Distribution)
+      run [default]
+        stop after all commands have been run (the same as if 'setup()'
+        had been called in the usual way
+
+    Returns the Distribution instance, which provides all information
+    used to drive the Distutils.
+    """
+    if stop_after not in ('init', 'config', 'commandline', 'run'):
+        raise ValueError, "invalid value for 'stop_after': %r" % (stop_after,)
+
+    global _setup_stop_after, _setup_distribution
+    _setup_stop_after = stop_after
+
+    save_argv = sys.argv
+    g = {'__file__': script_name}
+    l = {}
+    try:
+        try:
+            sys.argv[0] = script_name
+            if script_args is not None:
+                sys.argv[1:] = script_args
+            f = open(script_name)
+            try:
+                exec f.read() in g, l
+            finally:
+                f.close()
+        finally:
+            sys.argv = save_argv
+            _setup_stop_after = None
+    except SystemExit:
+        # Hmm, should we do something if exiting with a non-zero code
+        # (ie. error)?
+        pass
+    except:
+        raise
+
+    if _setup_distribution is None:
+        raise RuntimeError, \
+              ("'distutils.core.setup()' was never called -- "
+               "perhaps '%s' is not a Distutils setup script?") % \
+              script_name
+
+    # I wonder if the setup script's namespace -- g and l -- would be of
+    # any interest to callers?
+    return _setup_distribution
diff --git a/src/main/resources/PythonLibs/distutils/cygwinccompiler.py b/src/main/resources/PythonLibs/distutils/cygwinccompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1ee815c6cc782354a1ee1735a88d31679e1e4db
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/cygwinccompiler.py
@@ -0,0 +1,449 @@
+"""distutils.cygwinccompiler
+
+Provides the CygwinCCompiler class, a subclass of UnixCCompiler that
+handles the Cygwin port of the GNU C compiler to Windows.  It also contains
+the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
+cygwin in no-cygwin mode).
+"""
+
+# problems:
+#
+# * if you use a msvc compiled python version (1.5.2)
+#   1. you have to insert a __GNUC__ section in its config.h
+#   2. you have to generate a import library for its dll
+#      - create a def-file for python??.dll
+#      - create a import library using
+#             dlltool --dllname python15.dll --def python15.def \
+#                       --output-lib libpython15.a
+#
+#   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
+#
+# * We put export_symbols in a def-file, and don't use
+#   --export-all-symbols because it doesn't worked reliable in some
+#   tested configurations. And because other windows compilers also
+#   need their symbols specified this no serious problem.
+#
+# tested configurations:
+#
+# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works
+#   (after patching python's config.h and for C++ some other include files)
+#   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
+# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works
+#   (ld doesn't support -shared, so we use dllwrap)
+# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now
+#   - its dllwrap doesn't work, there is a bug in binutils 2.10.90
+#     see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html
+#   - using gcc -mdll instead dllwrap doesn't work without -static because
+#     it tries to link against dlls instead their import libraries. (If
+#     it finds the dll first.)
+#     By specifying -static we force ld to link against the import libraries,
+#     this is windows standard and there are normally not the necessary symbols
+#     in the dlls.
+#   *** only the version of June 2000 shows these problems
+# * cygwin gcc 3.2/ld 2.13.90 works
+#   (ld supports -shared)
+# * mingw gcc 3.2/ld 2.13 works
+#   (ld supports -shared)
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id$"
+
+import os,sys,copy
+from distutils.ccompiler import gen_preprocess_options, gen_lib_options
+from distutils.unixccompiler import UnixCCompiler
+from distutils.file_util import write_file
+from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
+from distutils import log
+
+def get_msvcr():
+    """Include the appropriate MSVC runtime library if Python was built
+    with MSVC 7.0 or later.
+    """
+    msc_pos = sys.version.find('MSC v.')
+    if msc_pos != -1:
+        msc_ver = sys.version[msc_pos+6:msc_pos+10]
+        if msc_ver == '1300':
+            # MSVC 7.0
+            return ['msvcr70']
+        elif msc_ver == '1310':
+            # MSVC 7.1
+            return ['msvcr71']
+        elif msc_ver == '1400':
+            # VS2005 / MSVC 8.0
+            return ['msvcr80']
+        elif msc_ver == '1500':
+            # VS2008 / MSVC 9.0
+            return ['msvcr90']
+        else:
+            raise ValueError("Unknown MS Compiler version %s " % msc_ver)
+
+
+class CygwinCCompiler (UnixCCompiler):
+
+    compiler_type = 'cygwin'
+    obj_extension = ".o"
+    static_lib_extension = ".a"
+    shared_lib_extension = ".dll"
+    static_lib_format = "lib%s%s"
+    shared_lib_format = "%s%s"
+    exe_extension = ".exe"
+
+    def __init__ (self, verbose=0, dry_run=0, force=0):
+
+        UnixCCompiler.__init__ (self, verbose, dry_run, force)
+
+        (status, details) = check_config_h()
+        self.debug_print("Python's GCC status: %s (details: %s)" %
+                         (status, details))
+        if status is not CONFIG_H_OK:
+            self.warn(
+                "Python's pyconfig.h doesn't seem to support your compiler. "
+                "Reason: %s. "
+                "Compiling may fail because of undefined preprocessor macros."
+                % details)
+
+        self.gcc_version, self.ld_version, self.dllwrap_version = \
+            get_versions()
+        self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
+                         (self.gcc_version,
+                          self.ld_version,
+                          self.dllwrap_version) )
+
+        # ld_version >= "2.10.90" and < "2.13" should also be able to use
+        # gcc -mdll instead of dllwrap
+        # Older dllwraps had own version numbers, newer ones use the
+        # same as the rest of binutils ( also ld )
+        # dllwrap 2.10.90 is buggy
+        if self.ld_version >= "2.10.90":
+            self.linker_dll = "gcc"
+        else:
+            self.linker_dll = "dllwrap"
+
+        # ld_version >= "2.13" support -shared so use it instead of
+        # -mdll -static
+        if self.ld_version >= "2.13":
+            shared_option = "-shared"
+        else:
+            shared_option = "-mdll -static"
+
+        # Hard-code GCC because that's what this is all about.
+        # XXX optimization, warnings etc. should be customizable.
+        self.set_executables(compiler='gcc -mcygwin -O -Wall',
+                             compiler_so='gcc -mcygwin -mdll -O -Wall',
+                             compiler_cxx='g++ -mcygwin -O -Wall',
+                             linker_exe='gcc -mcygwin',
+                             linker_so=('%s -mcygwin %s' %
+                                        (self.linker_dll, shared_option)))
+
+        # cygwin and mingw32 need different sets of libraries
+        if self.gcc_version == "2.91.57":
+            # cygwin shouldn't need msvcrt, but without the dlls will crash
+            # (gcc version 2.91.57) -- perhaps something about initialization
+            self.dll_libraries=["msvcrt"]
+            self.warn(
+                "Consider upgrading to a newer version of gcc")
+        else:
+            # Include the appropriate MSVC runtime library if Python was built
+            # with MSVC 7.0 or later.
+            self.dll_libraries = get_msvcr()
+
+    # __init__ ()
+
+
+    def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+        if ext == '.rc' or ext == '.res':
+            # gcc needs '.res' and '.rc' compiled to object files !!!
+            try:
+                self.spawn(["windres", "-i", src, "-o", obj])
+            except DistutilsExecError, msg:
+                raise CompileError, msg
+        else: # for other files use the C-compiler
+            try:
+                self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
+                           extra_postargs)
+            except DistutilsExecError, msg:
+                raise CompileError, msg
+
+    def link (self,
+              target_desc,
+              objects,
+              output_filename,
+              output_dir=None,
+              libraries=None,
+              library_dirs=None,
+              runtime_library_dirs=None,
+              export_symbols=None,
+              debug=0,
+              extra_preargs=None,
+              extra_postargs=None,
+              build_temp=None,
+              target_lang=None):
+
+        # use separate copies, so we can modify the lists
+        extra_preargs = copy.copy(extra_preargs or [])
+        libraries = copy.copy(libraries or [])
+        objects = copy.copy(objects or [])
+
+        # Additional libraries
+        libraries.extend(self.dll_libraries)
+
+        # handle export symbols by creating a def-file
+        # with executables this only works with gcc/ld as linker
+        if ((export_symbols is not None) and
+            (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
+            # (The linker doesn't do anything if output is up-to-date.
+            # So it would probably better to check if we really need this,
+            # but for this we had to insert some unchanged parts of
+            # UnixCCompiler, and this is not what we want.)
+
+            # we want to put some files in the same directory as the
+            # object files are, build_temp doesn't help much
+            # where are the object files
+            temp_dir = os.path.dirname(objects[0])
+            # name of dll to give the helper files the same base name
+            (dll_name, dll_extension) = os.path.splitext(
+                os.path.basename(output_filename))
+
+            # generate the filenames for these files
+            def_file = os.path.join(temp_dir, dll_name + ".def")
+            lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
+
+            # Generate .def file
+            contents = [
+                "LIBRARY %s" % os.path.basename(output_filename),
+                "EXPORTS"]
+            for sym in export_symbols:
+                contents.append(sym)
+            self.execute(write_file, (def_file, contents),
+                         "writing %s" % def_file)
+
+            # next add options for def-file and to creating import libraries
+
+            # dllwrap uses different options than gcc/ld
+            if self.linker_dll == "dllwrap":
+                extra_preargs.extend(["--output-lib", lib_file])
+                # for dllwrap we have to use a special option
+                extra_preargs.extend(["--def", def_file])
+            # we use gcc/ld here and can be sure ld is >= 2.9.10
+            else:
+                # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
+                #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
+                # for gcc/ld the def-file is specified as any object files
+                objects.append(def_file)
+
+        #end: if ((export_symbols is not None) and
+        #        (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
+
+        # who wants symbols and a many times larger output file
+        # should explicitly switch the debug mode on
+        # otherwise we let dllwrap/ld strip the output file
+        # (On my machine: 10KB < stripped_file < ??100KB
+        #   unstripped_file = stripped_file + XXX KB
+        #  ( XXX=254 for a typical python extension))
+        if not debug:
+            extra_preargs.append("-s")
+
+        UnixCCompiler.link(self,
+                           target_desc,
+                           objects,
+                           output_filename,
+                           output_dir,
+                           libraries,
+                           library_dirs,
+                           runtime_library_dirs,
+                           None, # export_symbols, we do this in our def-file
+                           debug,
+                           extra_preargs,
+                           extra_postargs,
+                           build_temp,
+                           target_lang)
+
+    # link ()
+
+    # -- Miscellaneous methods -----------------------------------------
+
+    # overwrite the one from CCompiler to support rc and res-files
+    def object_filenames (self,
+                          source_filenames,
+                          strip_dir=0,
+                          output_dir=''):
+        if output_dir is None: output_dir = ''
+        obj_names = []
+        for src_name in source_filenames:
+            # use normcase to make sure '.rc' is really '.rc' and not '.RC'
+            (base, ext) = os.path.splitext (os.path.normcase(src_name))
+            if ext not in (self.src_extensions + ['.rc','.res']):
+                raise UnknownFileError, \
+                      "unknown file type '%s' (from '%s')" % \
+                      (ext, src_name)
+            if strip_dir:
+                base = os.path.basename (base)
+            if ext == '.res' or ext == '.rc':
+                # these need to be compiled to object files
+                obj_names.append (os.path.join (output_dir,
+                                            base + ext + self.obj_extension))
+            else:
+                obj_names.append (os.path.join (output_dir,
+                                            base + self.obj_extension))
+        return obj_names
+
+    # object_filenames ()
+
+# class CygwinCCompiler
+
+
+# the same as cygwin plus some additional parameters
+class Mingw32CCompiler (CygwinCCompiler):
+
+    compiler_type = 'mingw32'
+
+    def __init__ (self,
+                  verbose=0,
+                  dry_run=0,
+                  force=0):
+
+        CygwinCCompiler.__init__ (self, verbose, dry_run, force)
+
+        # ld_version >= "2.13" support -shared so use it instead of
+        # -mdll -static
+        if self.ld_version >= "2.13":
+            shared_option = "-shared"
+        else:
+            shared_option = "-mdll -static"
+
+        # A real mingw32 doesn't need to specify a different entry point,
+        # but cygwin 2.91.57 in no-cygwin-mode needs it.
+        if self.gcc_version <= "2.91.57":
+            entry_point = '--entry _DllMain@12'
+        else:
+            entry_point = ''
+
+        self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
+                             compiler_so='gcc -mno-cygwin -mdll -O -Wall',
+                             compiler_cxx='g++ -mno-cygwin -O -Wall',
+                             linker_exe='gcc -mno-cygwin',
+                             linker_so='%s -mno-cygwin %s %s'
+                                        % (self.linker_dll, shared_option,
+                                           entry_point))
+        # Maybe we should also append -mthreads, but then the finished
+        # dlls need another dll (mingwm10.dll see Mingw32 docs)
+        # (-mthreads: Support thread-safe exception handling on `Mingw32')
+
+        # no additional libraries needed
+        self.dll_libraries=[]
+
+        # Include the appropriate MSVC runtime library if Python was built
+        # with MSVC 7.0 or later.
+        self.dll_libraries = get_msvcr()
+
+    # __init__ ()
+
+# class Mingw32CCompiler
+
+# Because these compilers aren't configured in Python's pyconfig.h file by
+# default, we should at least warn the user if he is using a unmodified
+# version.
+
+CONFIG_H_OK = "ok"
+CONFIG_H_NOTOK = "not ok"
+CONFIG_H_UNCERTAIN = "uncertain"
+
+def check_config_h():
+
+    """Check if the current Python installation (specifically, pyconfig.h)
+    appears amenable to building extensions with GCC.  Returns a tuple
+    (status, details), where 'status' is one of the following constants:
+      CONFIG_H_OK
+        all is well, go ahead and compile
+      CONFIG_H_NOTOK
+        doesn't look good
+      CONFIG_H_UNCERTAIN
+        not sure -- unable to read pyconfig.h
+    'details' is a human-readable string explaining the situation.
+
+    Note there are two ways to conclude "OK": either 'sys.version' contains
+    the string "GCC" (implying that this Python was built with GCC), or the
+    installed "pyconfig.h" contains the string "__GNUC__".
+    """
+
+    # XXX since this function also checks sys.version, it's not strictly a
+    # "pyconfig.h" check -- should probably be renamed...
+
+    from distutils import sysconfig
+    import string
+    # if sys.version contains GCC then python was compiled with
+    # GCC, and the pyconfig.h file should be OK
+    if string.find(sys.version,"GCC") >= 0:
+        return (CONFIG_H_OK, "sys.version mentions 'GCC'")
+
+    fn = sysconfig.get_config_h_filename()
+    try:
+        # It would probably better to read single lines to search.
+        # But we do this only once, and it is fast enough
+        f = open(fn)
+        try:
+            s = f.read()
+        finally:
+            f.close()
+
+    except IOError, exc:
+        # if we can't read this file, we cannot say it is wrong
+        # the compiler will complain later about this file as missing
+        return (CONFIG_H_UNCERTAIN,
+                "couldn't read '%s': %s" % (fn, exc.strerror))
+
+    else:
+        # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
+        if string.find(s,"__GNUC__") >= 0:
+            return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
+        else:
+            return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
+
+
+
+def get_versions():
+    """ Try to find out the versions of gcc, ld and dllwrap.
+        If not possible it returns None for it.
+    """
+    from distutils.version import LooseVersion
+    from distutils.spawn import find_executable
+    import re
+
+    gcc_exe = find_executable('gcc')
+    if gcc_exe:
+        out = os.popen(gcc_exe + ' -dumpversion','r')
+        out_string = out.read()
+        out.close()
+        result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
+        if result:
+            gcc_version = LooseVersion(result.group(1))
+        else:
+            gcc_version = None
+    else:
+        gcc_version = None
+    ld_exe = find_executable('ld')
+    if ld_exe:
+        out = os.popen(ld_exe + ' -v','r')
+        out_string = out.read()
+        out.close()
+        result = re.search('(\d+\.\d+(\.\d+)*)',out_string)
+        if result:
+            ld_version = LooseVersion(result.group(1))
+        else:
+            ld_version = None
+    else:
+        ld_version = None
+    dllwrap_exe = find_executable('dllwrap')
+    if dllwrap_exe:
+        out = os.popen(dllwrap_exe + ' --version','r')
+        out_string = out.read()
+        out.close()
+        result = re.search(' (\d+\.\d+(\.\d+)*)',out_string)
+        if result:
+            dllwrap_version = LooseVersion(result.group(1))
+        else:
+            dllwrap_version = None
+    else:
+        dllwrap_version = None
+    return (gcc_version, ld_version, dllwrap_version)
diff --git a/src/main/resources/PythonLibs/distutils/debug.py b/src/main/resources/PythonLibs/distutils/debug.py
new file mode 100644
index 0000000000000000000000000000000000000000..2886744402e1b5c219f5bbfcc5aab32418632e86
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/debug.py
@@ -0,0 +1,7 @@
+import os
+
+__revision__ = "$Id$"
+
+# If DISTUTILS_DEBUG is anything other than the empty string, we run in
+# debug mode.
+DEBUG = os.environ.get('DISTUTILS_DEBUG')
diff --git a/src/main/resources/PythonLibs/distutils/dep_util.py b/src/main/resources/PythonLibs/distutils/dep_util.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b759056ea8b2a0042355d715d984c496dae54a6
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/dep_util.py
@@ -0,0 +1,89 @@
+"""distutils.dep_util
+
+Utility functions for simple, timestamp-based dependency of files
+and groups of files; also, function based entirely on such
+timestamp dependency analysis."""
+
+__revision__ = "$Id$"
+
+import os
+from stat import ST_MTIME
+from distutils.errors import DistutilsFileError
+
+def newer(source, target):
+    """Tells if the target is newer than the source.
+
+    Return true if 'source' exists and is more recently modified than
+    'target', or if 'source' exists and 'target' doesn't.
+
+    Return false if both exist and 'target' is the same age or younger
+    than 'source'. Raise DistutilsFileError if 'source' does not exist.
+
+    Note that this test is not very accurate: files created in the same second
+    will have the same "age".
+    """
+    if not os.path.exists(source):
+        raise DistutilsFileError("file '%s' does not exist" %
+                                 os.path.abspath(source))
+    if not os.path.exists(target):
+        return True
+
+    return os.stat(source)[ST_MTIME] > os.stat(target)[ST_MTIME]
+
+def newer_pairwise(sources, targets):
+    """Walk two filename lists in parallel, testing if each source is newer
+    than its corresponding target.  Return a pair of lists (sources,
+    targets) where source is newer than target, according to the semantics
+    of 'newer()'.
+    """
+    if len(sources) != len(targets):
+        raise ValueError, "'sources' and 'targets' must be same length"
+
+    # build a pair of lists (sources, targets) where  source is newer
+    n_sources = []
+    n_targets = []
+    for source, target in zip(sources, targets):
+        if newer(source, target):
+            n_sources.append(source)
+            n_targets.append(target)
+
+    return n_sources, n_targets
+
+def newer_group(sources, target, missing='error'):
+    """Return true if 'target' is out-of-date with respect to any file
+    listed in 'sources'.
+
+    In other words, if 'target' exists and is newer
+    than every file in 'sources', return false; otherwise return true.
+    'missing' controls what we do when a source file is missing; the
+    default ("error") is to blow up with an OSError from inside 'stat()';
+    if it is "ignore", we silently drop any missing source files; if it is
+    "newer", any missing source files make us assume that 'target' is
+    out-of-date (this is handy in "dry-run" mode: it'll make you pretend to
+    carry out commands that wouldn't work because inputs are missing, but
+    that doesn't matter because you're not actually going to run the
+    commands).
+    """
+    # If the target doesn't even exist, then it's definitely out-of-date.
+    if not os.path.exists(target):
+        return True
+
+    # Otherwise we have to find out the hard way: if *any* source file
+    # is more recent than 'target', then 'target' is out-of-date and
+    # we can immediately return true.  If we fall through to the end
+    # of the loop, then 'target' is up-to-date and we return false.
+    target_mtime = os.stat(target)[ST_MTIME]
+
+    for source in sources:
+        if not os.path.exists(source):
+            if missing == 'error':      # blow up when we stat() the file
+                pass
+            elif missing == 'ignore':   # missing source dropped from
+                continue                #  target's dependency list
+            elif missing == 'newer':    # missing source means target is
+                return True             #  out-of-date
+
+        if os.stat(source)[ST_MTIME] > target_mtime:
+            return True
+
+    return False
diff --git a/src/main/resources/PythonLibs/distutils/dir_util.py b/src/main/resources/PythonLibs/distutils/dir_util.py
new file mode 100644
index 0000000000000000000000000000000000000000..5026e246685eacf3575db56b944924b2d0e84042
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/dir_util.py
@@ -0,0 +1,216 @@
+"""distutils.dir_util
+
+Utility functions for manipulating directories and directory trees."""
+
+__revision__ = "$Id$"
+
+import os
+import errno
+from distutils.errors import DistutilsFileError, DistutilsInternalError
+from distutils import log
+
+# cache for by mkpath() -- in addition to cheapening redundant calls,
+# eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
+_path_created = {}
+
+# I don't use os.makedirs because a) it's new to Python 1.5.2, and
+# b) it blows up if the directory already exists (I want to silently
+# succeed in that case).
+def mkpath(name, mode=0777, verbose=1, dry_run=0):
+    """Create a directory and any missing ancestor directories.
+
+    If the directory already exists (or if 'name' is the empty string, which
+    means the current directory, which of course exists), then do nothing.
+    Raise DistutilsFileError if unable to create some directory along the way
+    (eg. some sub-path exists, but is a file rather than a directory).
+    If 'verbose' is true, print a one-line summary of each mkdir to stdout.
+    Return the list of directories actually created.
+    """
+
+    global _path_created
+
+    # Detect a common bug -- name is None
+    if not isinstance(name, basestring):
+        raise DistutilsInternalError, \
+              "mkpath: 'name' must be a string (got %r)" % (name,)
+
+    # XXX what's the better way to handle verbosity? print as we create
+    # each directory in the path (the current behaviour), or only announce
+    # the creation of the whole path? (quite easy to do the latter since
+    # we're not using a recursive algorithm)
+
+    name = os.path.normpath(name)
+    created_dirs = []
+    if os.path.isdir(name) or name == '':
+        return created_dirs
+    if _path_created.get(os.path.abspath(name)):
+        return created_dirs
+
+    (head, tail) = os.path.split(name)
+    tails = [tail]                      # stack of lone dirs to create
+
+    while head and tail and not os.path.isdir(head):
+        (head, tail) = os.path.split(head)
+        tails.insert(0, tail)          # push next higher dir onto stack
+
+    # now 'head' contains the deepest directory that already exists
+    # (that is, the child of 'head' in 'name' is the highest directory
+    # that does *not* exist)
+    for d in tails:
+        #print "head = %s, d = %s: " % (head, d),
+        head = os.path.join(head, d)
+        abs_head = os.path.abspath(head)
+
+        if _path_created.get(abs_head):
+            continue
+
+        if verbose >= 1:
+            log.info("creating %s", head)
+
+        if not dry_run:
+            try:
+                os.mkdir(head, mode)
+            except OSError, exc:
+                if not (exc.errno == errno.EEXIST and os.path.isdir(head)):
+                    raise DistutilsFileError(
+                          "could not create '%s': %s" % (head, exc.args[-1]))
+            created_dirs.append(head)
+
+        _path_created[abs_head] = 1
+    return created_dirs
+
+def create_tree(base_dir, files, mode=0777, verbose=1, dry_run=0):
+    """Create all the empty directories under 'base_dir' needed to put 'files'
+    there.
+
+    'base_dir' is just the a name of a directory which doesn't necessarily
+    exist yet; 'files' is a list of filenames to be interpreted relative to
+    'base_dir'.  'base_dir' + the directory portion of every file in 'files'
+    will be created if it doesn't already exist.  'mode', 'verbose' and
+    'dry_run' flags are as for 'mkpath()'.
+    """
+    # First get the list of directories to create
+    need_dir = {}
+    for file in files:
+        need_dir[os.path.join(base_dir, os.path.dirname(file))] = 1
+    need_dirs = need_dir.keys()
+    need_dirs.sort()
+
+    # Now create them
+    for dir in need_dirs:
+        mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
+
+def copy_tree(src, dst, preserve_mode=1, preserve_times=1,
+              preserve_symlinks=0, update=0, verbose=1, dry_run=0):
+    """Copy an entire directory tree 'src' to a new location 'dst'.
+
+    Both 'src' and 'dst' must be directory names.  If 'src' is not a
+    directory, raise DistutilsFileError.  If 'dst' does not exist, it is
+    created with 'mkpath()'.  The end result of the copy is that every
+    file in 'src' is copied to 'dst', and directories under 'src' are
+    recursively copied to 'dst'.  Return the list of files that were
+    copied or might have been copied, using their output name.  The
+    return value is unaffected by 'update' or 'dry_run': it is simply
+    the list of all files under 'src', with the names changed to be
+    under 'dst'.
+
+    'preserve_mode' and 'preserve_times' are the same as for
+    'copy_file'; note that they only apply to regular files, not to
+    directories.  If 'preserve_symlinks' is true, symlinks will be
+    copied as symlinks (on platforms that support them!); otherwise
+    (the default), the destination of the symlink will be copied.
+    'update' and 'verbose' are the same as for 'copy_file'.
+    """
+    from distutils.file_util import copy_file
+
+    if not dry_run and not os.path.isdir(src):
+        raise DistutilsFileError, \
+              "cannot copy tree '%s': not a directory" % src
+    try:
+        names = os.listdir(src)
+    except os.error, (errno, errstr):
+        if dry_run:
+            names = []
+        else:
+            raise DistutilsFileError, \
+                  "error listing files in '%s': %s" % (src, errstr)
+
+    if not dry_run:
+        mkpath(dst, verbose=verbose)
+
+    outputs = []
+
+    for n in names:
+        src_name = os.path.join(src, n)
+        dst_name = os.path.join(dst, n)
+
+        if n.startswith('.nfs'):
+            # skip NFS rename files
+            continue
+
+        if preserve_symlinks and os.path.islink(src_name):
+            link_dest = os.readlink(src_name)
+            if verbose >= 1:
+                log.info("linking %s -> %s", dst_name, link_dest)
+            if not dry_run:
+                os.symlink(link_dest, dst_name)
+            outputs.append(dst_name)
+
+        elif os.path.isdir(src_name):
+            outputs.extend(
+                copy_tree(src_name, dst_name, preserve_mode,
+                          preserve_times, preserve_symlinks, update,
+                          verbose=verbose, dry_run=dry_run))
+        else:
+            copy_file(src_name, dst_name, preserve_mode,
+                      preserve_times, update, verbose=verbose,
+                      dry_run=dry_run)
+            outputs.append(dst_name)
+
+    return outputs
+
+def _build_cmdtuple(path, cmdtuples):
+    """Helper for remove_tree()."""
+    for f in os.listdir(path):
+        real_f = os.path.join(path,f)
+        if os.path.isdir(real_f) and not os.path.islink(real_f):
+            _build_cmdtuple(real_f, cmdtuples)
+        else:
+            cmdtuples.append((os.remove, real_f))
+    cmdtuples.append((os.rmdir, path))
+
+def remove_tree(directory, verbose=1, dry_run=0):
+    """Recursively remove an entire directory tree.
+
+    Any errors are ignored (apart from being reported to stdout if 'verbose'
+    is true).
+    """
+    from distutils.util import grok_environment_error
+    global _path_created
+
+    if verbose >= 1:
+        log.info("removing '%s' (and everything under it)", directory)
+    if dry_run:
+        return
+    cmdtuples = []
+    _build_cmdtuple(directory, cmdtuples)
+    for cmd in cmdtuples:
+        try:
+            cmd[0](cmd[1])
+            # remove dir from cache if it's already there
+            abspath = os.path.abspath(cmd[1])
+            if abspath in _path_created:
+                del _path_created[abspath]
+        except (IOError, OSError), exc:
+            log.warn(grok_environment_error(
+                    exc, "error removing %s: " % directory))
+
+def ensure_relative(path):
+    """Take the full path 'path', and make it a relative path.
+
+    This is useful to make 'path' the second argument to os.path.join().
+    """
+    drive, path = os.path.splitdrive(path)
+    if path[0:1] == os.sep:
+        path = drive + path[1:]
+    return path
diff --git a/src/main/resources/PythonLibs/distutils/dist.py b/src/main/resources/PythonLibs/distutils/dist.py
new file mode 100644
index 0000000000000000000000000000000000000000..e025313dbd94e762fc0a9eb93f48dd5dce7cff4f
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/dist.py
@@ -0,0 +1,1249 @@
+"""distutils.dist
+
+Provides the Distribution class, which represents the module distribution
+being built/installed/distributed.
+"""
+
+__revision__ = "$Id$"
+
+import sys, os, re
+from email import message_from_file
+
+try:
+    import warnings
+except ImportError:
+    warnings = None
+
+from distutils.errors import (DistutilsOptionError, DistutilsArgError,
+                              DistutilsModuleError, DistutilsClassError)
+from distutils.fancy_getopt import FancyGetopt, translate_longopt
+from distutils.util import check_environ, strtobool, rfc822_escape
+from distutils import log
+from distutils.debug import DEBUG
+
+# Encoding used for the PKG-INFO files
+PKG_INFO_ENCODING = 'utf-8'
+
+# Regex to define acceptable Distutils command names.  This is not *quite*
+# the same as a Python NAME -- I don't allow leading underscores.  The fact
+# that they're very similar is no coincidence; the default naming scheme is
+# to look for a Python module named after the command.
+command_re = re.compile (r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
+
+
+class Distribution:
+    """The core of the Distutils.  Most of the work hiding behind 'setup'
+    is really done within a Distribution instance, which farms the work out
+    to the Distutils commands specified on the command line.
+
+    Setup scripts will almost never instantiate Distribution directly,
+    unless the 'setup()' function is totally inadequate to their needs.
+    However, it is conceivable that a setup script might wish to subclass
+    Distribution for some specialized purpose, and then pass the subclass
+    to 'setup()' as the 'distclass' keyword argument.  If so, it is
+    necessary to respect the expectations that 'setup' has of Distribution.
+    See the code for 'setup()', in core.py, for details.
+    """
+
+
+    # 'global_options' describes the command-line options that may be
+    # supplied to the setup script prior to any actual commands.
+    # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
+    # these global options.  This list should be kept to a bare minimum,
+    # since every global option is also valid as a command option -- and we
+    # don't want to pollute the commands with too many options that they
+    # have minimal control over.
+    # The fourth entry for verbose means that it can be repeated.
+    global_options = [('verbose', 'v', "run verbosely (default)", 1),
+                      ('quiet', 'q', "run quietly (turns verbosity off)"),
+                      ('dry-run', 'n', "don't actually do anything"),
+                      ('help', 'h', "show detailed help message"),
+                      ('no-user-cfg', None,
+                       'ignore pydistutils.cfg in your home directory'),
+    ]
+
+    # 'common_usage' is a short (2-3 line) string describing the common
+    # usage of the setup script.
+    common_usage = """\
+Common commands: (see '--help-commands' for more)
+
+  setup.py build      will build the package underneath 'build/'
+  setup.py install    will install the package
+"""
+
+    # options that are not propagated to the commands
+    display_options = [
+        ('help-commands', None,
+         "list all available commands"),
+        ('name', None,
+         "print package name"),
+        ('version', 'V',
+         "print package version"),
+        ('fullname', None,
+         "print <package name>-<version>"),
+        ('author', None,
+         "print the author's name"),
+        ('author-email', None,
+         "print the author's email address"),
+        ('maintainer', None,
+         "print the maintainer's name"),
+        ('maintainer-email', None,
+         "print the maintainer's email address"),
+        ('contact', None,
+         "print the maintainer's name if known, else the author's"),
+        ('contact-email', None,
+         "print the maintainer's email address if known, else the author's"),
+        ('url', None,
+         "print the URL for this package"),
+        ('license', None,
+         "print the license of the package"),
+        ('licence', None,
+         "alias for --license"),
+        ('description', None,
+         "print the package description"),
+        ('long-description', None,
+         "print the long package description"),
+        ('platforms', None,
+         "print the list of platforms"),
+        ('classifiers', None,
+         "print the list of classifiers"),
+        ('keywords', None,
+         "print the list of keywords"),
+        ('provides', None,
+         "print the list of packages/modules provided"),
+        ('requires', None,
+         "print the list of packages/modules required"),
+        ('obsoletes', None,
+         "print the list of packages/modules made obsolete")
+        ]
+    display_option_names = map(lambda x: translate_longopt(x[0]),
+                               display_options)
+
+    # negative options are options that exclude other options
+    negative_opt = {'quiet': 'verbose'}
+
+
+    # -- Creation/initialization methods -------------------------------
+
+    def __init__ (self, attrs=None):
+        """Construct a new Distribution instance: initialize all the
+        attributes of a Distribution, and then use 'attrs' (a dictionary
+        mapping attribute names to values) to assign some of those
+        attributes their "real" values.  (Any attributes not mentioned in
+        'attrs' will be assigned to some null value: 0, None, an empty list
+        or dictionary, etc.)  Most importantly, initialize the
+        'command_obj' attribute to the empty dictionary; this will be
+        filled in with real command objects by 'parse_command_line()'.
+        """
+
+        # Default values for our command-line options
+        self.verbose = 1
+        self.dry_run = 0
+        self.help = 0
+        for attr in self.display_option_names:
+            setattr(self, attr, 0)
+
+        # Store the distribution meta-data (name, version, author, and so
+        # forth) in a separate object -- we're getting to have enough
+        # information here (and enough command-line options) that it's
+        # worth it.  Also delegate 'get_XXX()' methods to the 'metadata'
+        # object in a sneaky and underhanded (but efficient!) way.
+        self.metadata = DistributionMetadata()
+        for basename in self.metadata._METHOD_BASENAMES:
+            method_name = "get_" + basename
+            setattr(self, method_name, getattr(self.metadata, method_name))
+
+        # 'cmdclass' maps command names to class objects, so we
+        # can 1) quickly figure out which class to instantiate when
+        # we need to create a new command object, and 2) have a way
+        # for the setup script to override command classes
+        self.cmdclass = {}
+
+        # 'command_packages' is a list of packages in which commands
+        # are searched for.  The factory for command 'foo' is expected
+        # to be named 'foo' in the module 'foo' in one of the packages
+        # named here.  This list is searched from the left; an error
+        # is raised if no named package provides the command being
+        # searched for.  (Always access using get_command_packages().)
+        self.command_packages = None
+
+        # 'script_name' and 'script_args' are usually set to sys.argv[0]
+        # and sys.argv[1:], but they can be overridden when the caller is
+        # not necessarily a setup script run from the command-line.
+        self.script_name = None
+        self.script_args = None
+
+        # 'command_options' is where we store command options between
+        # parsing them (from config files, the command-line, etc.) and when
+        # they are actually needed -- ie. when the command in question is
+        # instantiated.  It is a dictionary of dictionaries of 2-tuples:
+        #   command_options = { command_name : { option : (source, value) } }
+        self.command_options = {}
+
+        # 'dist_files' is the list of (command, pyversion, file) that
+        # have been created by any dist commands run so far. This is
+        # filled regardless of whether the run is dry or not. pyversion
+        # gives sysconfig.get_python_version() if the dist file is
+        # specific to a Python version, 'any' if it is good for all
+        # Python versions on the target platform, and '' for a source
+        # file. pyversion should not be used to specify minimum or
+        # maximum required Python versions; use the metainfo for that
+        # instead.
+        self.dist_files = []
+
+        # These options are really the business of various commands, rather
+        # than of the Distribution itself.  We provide aliases for them in
+        # Distribution as a convenience to the developer.
+        self.packages = None
+        self.package_data = {}
+        self.package_dir = None
+        self.py_modules = None
+        self.libraries = None
+        self.headers = None
+        self.ext_modules = None
+        self.ext_package = None
+        self.include_dirs = None
+        self.extra_path = None
+        self.scripts = None
+        self.data_files = None
+        self.password = ''
+
+        # And now initialize bookkeeping stuff that can't be supplied by
+        # the caller at all.  'command_obj' maps command names to
+        # Command instances -- that's how we enforce that every command
+        # class is a singleton.
+        self.command_obj = {}
+
+        # 'have_run' maps command names to boolean values; it keeps track
+        # of whether we have actually run a particular command, to make it
+        # cheap to "run" a command whenever we think we might need to -- if
+        # it's already been done, no need for expensive filesystem
+        # operations, we just check the 'have_run' dictionary and carry on.
+        # It's only safe to query 'have_run' for a command class that has
+        # been instantiated -- a false value will be inserted when the
+        # command object is created, and replaced with a true value when
+        # the command is successfully run.  Thus it's probably best to use
+        # '.get()' rather than a straight lookup.
+        self.have_run = {}
+
+        # Now we'll use the attrs dictionary (ultimately, keyword args from
+        # the setup script) to possibly override any or all of these
+        # distribution options.
+
+        if attrs:
+            # Pull out the set of command options and work on them
+            # specifically.  Note that this order guarantees that aliased
+            # command options will override any supplied redundantly
+            # through the general options dictionary.
+            options = attrs.get('options')
+            if options is not None:
+                del attrs['options']
+                for (command, cmd_options) in options.items():
+                    opt_dict = self.get_option_dict(command)
+                    for (opt, val) in cmd_options.items():
+                        opt_dict[opt] = ("setup script", val)
+
+            if 'licence' in attrs:
+                attrs['license'] = attrs['licence']
+                del attrs['licence']
+                msg = "'licence' distribution option is deprecated; use 'license'"
+                if warnings is not None:
+                    warnings.warn(msg)
+                else:
+                    sys.stderr.write(msg + "\n")
+
+            # Now work on the rest of the attributes.  Any attribute that's
+            # not already defined is invalid!
+            for (key, val) in attrs.items():
+                if hasattr(self.metadata, "set_" + key):
+                    getattr(self.metadata, "set_" + key)(val)
+                elif hasattr(self.metadata, key):
+                    setattr(self.metadata, key, val)
+                elif hasattr(self, key):
+                    setattr(self, key, val)
+                else:
+                    msg = "Unknown distribution option: %s" % repr(key)
+                    if warnings is not None:
+                        warnings.warn(msg)
+                    else:
+                        sys.stderr.write(msg + "\n")
+
+        # no-user-cfg is handled before other command line args
+        # because other args override the config files, and this
+        # one is needed before we can load the config files.
+        # If attrs['script_args'] wasn't passed, assume false.
+        #
+        # This also make sure we just look at the global options
+        self.want_user_cfg = True
+
+        if self.script_args is not None:
+            for arg in self.script_args:
+                if not arg.startswith('-'):
+                    break
+                if arg == '--no-user-cfg':
+                    self.want_user_cfg = False
+                    break
+
+        self.finalize_options()
+
+    def get_option_dict(self, command):
+        """Get the option dictionary for a given command.  If that
+        command's option dictionary hasn't been created yet, then create it
+        and return the new dictionary; otherwise, return the existing
+        option dictionary.
+        """
+        dict = self.command_options.get(command)
+        if dict is None:
+            dict = self.command_options[command] = {}
+        return dict
+
+    def dump_option_dicts(self, header=None, commands=None, indent=""):
+        from pprint import pformat
+
+        if commands is None:             # dump all command option dicts
+            commands = self.command_options.keys()
+            commands.sort()
+
+        if header is not None:
+            self.announce(indent + header)
+            indent = indent + "  "
+
+        if not commands:
+            self.announce(indent + "no commands known yet")
+            return
+
+        for cmd_name in commands:
+            opt_dict = self.command_options.get(cmd_name)
+            if opt_dict is None:
+                self.announce(indent +
+                              "no option dict for '%s' command" % cmd_name)
+            else:
+                self.announce(indent +
+                              "option dict for '%s' command:" % cmd_name)
+                out = pformat(opt_dict)
+                for line in out.split('\n'):
+                    self.announce(indent + "  " + line)
+
+    # -- Config file finding/parsing methods ---------------------------
+
+    def find_config_files(self):
+        """Find as many configuration files as should be processed for this
+        platform, and return a list of filenames in the order in which they
+        should be parsed.  The filenames returned are guaranteed to exist
+        (modulo nasty race conditions).
+
+        There are three possible config files: distutils.cfg in the
+        Distutils installation directory (ie. where the top-level
+        Distutils __inst__.py file lives), a file in the user's home
+        directory named .pydistutils.cfg on Unix and pydistutils.cfg
+        on Windows/Mac; and setup.cfg in the current directory.
+
+        The file in the user's home directory can be disabled with the
+        --no-user-cfg option.
+        """
+        files = []
+        check_environ()
+
+        # Where to look for the system-wide Distutils config file
+        sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
+
+        # Look for the system config file
+        sys_file = os.path.join(sys_dir, "distutils.cfg")
+        if os.path.isfile(sys_file):
+            files.append(sys_file)
+
+        # What to call the per-user config file
+        if os.name == 'posix':
+            user_filename = ".pydistutils.cfg"
+        else:
+            user_filename = "pydistutils.cfg"
+
+        # And look for the user config file
+        if self.want_user_cfg:
+            user_file = os.path.join(os.path.expanduser('~'), user_filename)
+            if os.path.isfile(user_file):
+                files.append(user_file)
+
+        # All platforms support local setup.cfg
+        local_file = "setup.cfg"
+        if os.path.isfile(local_file):
+            files.append(local_file)
+
+        if DEBUG:
+            self.announce("using config files: %s" % ', '.join(files))
+
+        return files
+
+    def parse_config_files(self, filenames=None):
+        from ConfigParser import ConfigParser
+
+        if filenames is None:
+            filenames = self.find_config_files()
+
+        if DEBUG:
+            self.announce("Distribution.parse_config_files():")
+
+        parser = ConfigParser()
+        for filename in filenames:
+            if DEBUG:
+                self.announce("  reading %s" % filename)
+            parser.read(filename)
+            for section in parser.sections():
+                options = parser.options(section)
+                opt_dict = self.get_option_dict(section)
+
+                for opt in options:
+                    if opt != '__name__':
+                        val = parser.get(section,opt)
+                        opt = opt.replace('-', '_')
+                        opt_dict[opt] = (filename, val)
+
+            # Make the ConfigParser forget everything (so we retain
+            # the original filenames that options come from)
+            parser.__init__()
+
+        # If there was a "global" section in the config file, use it
+        # to set Distribution options.
+
+        if 'global' in self.command_options:
+            for (opt, (src, val)) in self.command_options['global'].items():
+                alias = self.negative_opt.get(opt)
+                try:
+                    if alias:
+                        setattr(self, alias, not strtobool(val))
+                    elif opt in ('verbose', 'dry_run'): # ugh!
+                        setattr(self, opt, strtobool(val))
+                    else:
+                        setattr(self, opt, val)
+                except ValueError, msg:
+                    raise DistutilsOptionError, msg
+
+    # -- Command-line parsing methods ----------------------------------
+
+    def parse_command_line(self):
+        """Parse the setup script's command line, taken from the
+        'script_args' instance attribute (which defaults to 'sys.argv[1:]'
+        -- see 'setup()' in core.py).  This list is first processed for
+        "global options" -- options that set attributes of the Distribution
+        instance.  Then, it is alternately scanned for Distutils commands
+        and options for that command.  Each new command terminates the
+        options for the previous command.  The allowed options for a
+        command are determined by the 'user_options' attribute of the
+        command class -- thus, we have to be able to load command classes
+        in order to parse the command line.  Any error in that 'options'
+        attribute raises DistutilsGetoptError; any error on the
+        command-line raises DistutilsArgError.  If no Distutils commands
+        were found on the command line, raises DistutilsArgError.  Return
+        true if command-line was successfully parsed and we should carry
+        on with executing commands; false if no errors but we shouldn't
+        execute commands (currently, this only happens if user asks for
+        help).
+        """
+        #
+        # We now have enough information to show the Macintosh dialog
+        # that allows the user to interactively specify the "command line".
+        #
+        toplevel_options = self._get_toplevel_options()
+
+        # We have to parse the command line a bit at a time -- global
+        # options, then the first command, then its options, and so on --
+        # because each command will be handled by a different class, and
+        # the options that are valid for a particular class aren't known
+        # until we have loaded the command class, which doesn't happen
+        # until we know what the command is.
+
+        self.commands = []
+        parser = FancyGetopt(toplevel_options + self.display_options)
+        parser.set_negative_aliases(self.negative_opt)
+        parser.set_aliases({'licence': 'license'})
+        args = parser.getopt(args=self.script_args, object=self)
+        option_order = parser.get_option_order()
+        log.set_verbosity(self.verbose)
+
+        # for display options we return immediately
+        if self.handle_display_options(option_order):
+            return
+        while args:
+            args = self._parse_command_opts(parser, args)
+            if args is None:            # user asked for help (and got it)
+                return
+
+        # Handle the cases of --help as a "global" option, ie.
+        # "setup.py --help" and "setup.py --help command ...".  For the
+        # former, we show global options (--verbose, --dry-run, etc.)
+        # and display-only options (--name, --version, etc.); for the
+        # latter, we omit the display-only options and show help for
+        # each command listed on the command line.
+        if self.help:
+            self._show_help(parser,
+                            display_options=len(self.commands) == 0,
+                            commands=self.commands)
+            return
+
+        # Oops, no commands found -- an end-user error
+        if not self.commands:
+            raise DistutilsArgError, "no commands supplied"
+
+        # All is well: return true
+        return 1
+
+    def _get_toplevel_options(self):
+        """Return the non-display options recognized at the top level.
+
+        This includes options that are recognized *only* at the top
+        level as well as options recognized for commands.
+        """
+        return self.global_options + [
+            ("command-packages=", None,
+             "list of packages that provide distutils commands"),
+            ]
+
+    def _parse_command_opts(self, parser, args):
+        """Parse the command-line options for a single command.
+        'parser' must be a FancyGetopt instance; 'args' must be the list
+        of arguments, starting with the current command (whose options
+        we are about to parse).  Returns a new version of 'args' with
+        the next command at the front of the list; will be the empty
+        list if there are no more commands on the command line.  Returns
+        None if the user asked for help on this command.
+        """
+        # late import because of mutual dependence between these modules
+        from distutils.cmd import Command
+
+        # Pull the current command from the head of the command line
+        command = args[0]
+        if not command_re.match(command):
+            raise SystemExit, "invalid command name '%s'" % command
+        self.commands.append(command)
+
+        # Dig up the command class that implements this command, so we
+        # 1) know that it's a valid command, and 2) know which options
+        # it takes.
+        try:
+            cmd_class = self.get_command_class(command)
+        except DistutilsModuleError, msg:
+            raise DistutilsArgError, msg
+
+        # Require that the command class be derived from Command -- want
+        # to be sure that the basic "command" interface is implemented.
+        if not issubclass(cmd_class, Command):
+            raise DistutilsClassError, \
+                  "command class %s must subclass Command" % cmd_class
+
+        # Also make sure that the command object provides a list of its
+        # known options.
+        if not (hasattr(cmd_class, 'user_options') and
+                isinstance(cmd_class.user_options, list)):
+            raise DistutilsClassError, \
+                  ("command class %s must provide " +
+                   "'user_options' attribute (a list of tuples)") % \
+                  cmd_class
+
+        # If the command class has a list of negative alias options,
+        # merge it in with the global negative aliases.
+        negative_opt = self.negative_opt
+        if hasattr(cmd_class, 'negative_opt'):
+            negative_opt = negative_opt.copy()
+            negative_opt.update(cmd_class.negative_opt)
+
+        # Check for help_options in command class.  They have a different
+        # format (tuple of four) so we need to preprocess them here.
+        if (hasattr(cmd_class, 'help_options') and
+            isinstance(cmd_class.help_options, list)):
+            help_options = fix_help_options(cmd_class.help_options)
+        else:
+            help_options = []
+
+
+        # All commands support the global options too, just by adding
+        # in 'global_options'.
+        parser.set_option_table(self.global_options +
+                                cmd_class.user_options +
+                                help_options)
+        parser.set_negative_aliases(negative_opt)
+        (args, opts) = parser.getopt(args[1:])
+        if hasattr(opts, 'help') and opts.help:
+            self._show_help(parser, display_options=0, commands=[cmd_class])
+            return
+
+        if (hasattr(cmd_class, 'help_options') and
+            isinstance(cmd_class.help_options, list)):
+            help_option_found=0
+            for (help_option, short, desc, func) in cmd_class.help_options:
+                if hasattr(opts, parser.get_attr_name(help_option)):
+                    help_option_found=1
+                    if hasattr(func, '__call__'):
+                        func()
+                    else:
+                        raise DistutilsClassError(
+                            "invalid help function %r for help option '%s': "
+                            "must be a callable object (function, etc.)"
+                            % (func, help_option))
+
+            if help_option_found:
+                return
+
+        # Put the options from the command-line into their official
+        # holding pen, the 'command_options' dictionary.
+        opt_dict = self.get_option_dict(command)
+        for (name, value) in vars(opts).items():
+            opt_dict[name] = ("command line", value)
+
+        return args
+
+    def finalize_options(self):
+        """Set final values for all the options on the Distribution
+        instance, analogous to the .finalize_options() method of Command
+        objects.
+        """
+        for attr in ('keywords', 'platforms'):
+            value = getattr(self.metadata, attr)
+            if value is None:
+                continue
+            if isinstance(value, str):
+                value = [elm.strip() for elm in value.split(',')]
+                setattr(self.metadata, attr, value)
+
+    def _show_help(self, parser, global_options=1, display_options=1,
+                   commands=[]):
+        """Show help for the setup script command-line in the form of
+        several lists of command-line options.  'parser' should be a
+        FancyGetopt instance; do not expect it to be returned in the
+        same state, as its option table will be reset to make it
+        generate the correct help text.
+
+        If 'global_options' is true, lists the global options:
+        --verbose, --dry-run, etc.  If 'display_options' is true, lists
+        the "display-only" options: --name, --version, etc.  Finally,
+        lists per-command help for every command name or command class
+        in 'commands'.
+        """
+        # late import because of mutual dependence between these modules
+        from distutils.core import gen_usage
+        from distutils.cmd import Command
+
+        if global_options:
+            if display_options:
+                options = self._get_toplevel_options()
+            else:
+                options = self.global_options
+            parser.set_option_table(options)
+            parser.print_help(self.common_usage + "\nGlobal options:")
+            print('')
+
+        if display_options:
+            parser.set_option_table(self.display_options)
+            parser.print_help(
+                "Information display options (just display " +
+                "information, ignore any commands)")
+            print('')
+
+        for command in self.commands:
+            if isinstance(command, type) and issubclass(command, Command):
+                klass = command
+            else:
+                klass = self.get_command_class(command)
+            if (hasattr(klass, 'help_options') and
+                isinstance(klass.help_options, list)):
+                parser.set_option_table(klass.user_options +
+                                        fix_help_options(klass.help_options))
+            else:
+                parser.set_option_table(klass.user_options)
+            parser.print_help("Options for '%s' command:" % klass.__name__)
+            print('')
+
+        print(gen_usage(self.script_name))
+
+    def handle_display_options(self, option_order):
+        """If there were any non-global "display-only" options
+        (--help-commands or the metadata display options) on the command
+        line, display the requested info and return true; else return
+        false.
+        """
+        from distutils.core import gen_usage
+
+        # User just wants a list of commands -- we'll print it out and stop
+        # processing now (ie. if they ran "setup --help-commands foo bar",
+        # we ignore "foo bar").
+        if self.help_commands:
+            self.print_commands()
+            print('')
+            print(gen_usage(self.script_name))
+            return 1
+
+        # If user supplied any of the "display metadata" options, then
+        # display that metadata in the order in which the user supplied the
+        # metadata options.
+        any_display_options = 0
+        is_display_option = {}
+        for option in self.display_options:
+            is_display_option[option[0]] = 1
+
+        for (opt, val) in option_order:
+            if val and is_display_option.get(opt):
+                opt = translate_longopt(opt)
+                value = getattr(self.metadata, "get_"+opt)()
+                if opt in ['keywords', 'platforms']:
+                    print(','.join(value))
+                elif opt in ('classifiers', 'provides', 'requires',
+                             'obsoletes'):
+                    print('\n'.join(value))
+                else:
+                    print(value)
+                any_display_options = 1
+
+        return any_display_options
+
+    def print_command_list(self, commands, header, max_length):
+        """Print a subset of the list of all commands -- used by
+        'print_commands()'.
+        """
+        print(header + ":")
+
+        for cmd in commands:
+            klass = self.cmdclass.get(cmd)
+            if not klass:
+                klass = self.get_command_class(cmd)
+            try:
+                description = klass.description
+            except AttributeError:
+                description = "(no description available)"
+
+            print("  %-*s  %s" % (max_length, cmd, description))
+
+    def print_commands(self):
+        """Print out a help message listing all available commands with a
+        description of each.  The list is divided into "standard commands"
+        (listed in distutils.command.__all__) and "extra commands"
+        (mentioned in self.cmdclass, but not a standard command).  The
+        descriptions come from the command class attribute
+        'description'.
+        """
+        import distutils.command
+        std_commands = distutils.command.__all__
+        is_std = {}
+        for cmd in std_commands:
+            is_std[cmd] = 1
+
+        extra_commands = []
+        for cmd in self.cmdclass.keys():
+            if not is_std.get(cmd):
+                extra_commands.append(cmd)
+
+        max_length = 0
+        for cmd in (std_commands + extra_commands):
+            if len(cmd) > max_length:
+                max_length = len(cmd)
+
+        self.print_command_list(std_commands,
+                                "Standard commands",
+                                max_length)
+        if extra_commands:
+            print
+            self.print_command_list(extra_commands,
+                                    "Extra commands",
+                                    max_length)
+
+    def get_command_list(self):
+        """Get a list of (command, description) tuples.
+        The list is divided into "standard commands" (listed in
+        distutils.command.__all__) and "extra commands" (mentioned in
+        self.cmdclass, but not a standard command).  The descriptions come
+        from the command class attribute 'description'.
+        """
+        # Currently this is only used on Mac OS, for the Mac-only GUI
+        # Distutils interface (by Jack Jansen)
+
+        import distutils.command
+        std_commands = distutils.command.__all__
+        is_std = {}
+        for cmd in std_commands:
+            is_std[cmd] = 1
+
+        extra_commands = []
+        for cmd in self.cmdclass.keys():
+            if not is_std.get(cmd):
+                extra_commands.append(cmd)
+
+        rv = []
+        for cmd in (std_commands + extra_commands):
+            klass = self.cmdclass.get(cmd)
+            if not klass:
+                klass = self.get_command_class(cmd)
+            try:
+                description = klass.description
+            except AttributeError:
+                description = "(no description available)"
+            rv.append((cmd, description))
+        return rv
+
+    # -- Command class/object methods ----------------------------------
+
+    def get_command_packages(self):
+        """Return a list of packages from which commands are loaded."""
+        pkgs = self.command_packages
+        if not isinstance(pkgs, list):
+            if pkgs is None:
+                pkgs = ''
+            pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
+            if "distutils.command" not in pkgs:
+                pkgs.insert(0, "distutils.command")
+            self.command_packages = pkgs
+        return pkgs
+
+    def get_command_class(self, command):
+        """Return the class that implements the Distutils command named by
+        'command'.  First we check the 'cmdclass' dictionary; if the
+        command is mentioned there, we fetch the class object from the
+        dictionary and return it.  Otherwise we load the command module
+        ("distutils.command." + command) and fetch the command class from
+        the module.  The loaded class is also stored in 'cmdclass'
+        to speed future calls to 'get_command_class()'.
+
+        Raises DistutilsModuleError if the expected module could not be
+        found, or if that module does not define the expected class.
+        """
+        klass = self.cmdclass.get(command)
+        if klass:
+            return klass
+
+        for pkgname in self.get_command_packages():
+            module_name = "%s.%s" % (pkgname, command)
+            klass_name = command
+
+            try:
+                __import__ (module_name)
+                module = sys.modules[module_name]
+            except ImportError:
+                continue
+
+            try:
+                klass = getattr(module, klass_name)
+            except AttributeError:
+                raise DistutilsModuleError, \
+                      "invalid command '%s' (no class '%s' in module '%s')" \
+                      % (command, klass_name, module_name)
+
+            self.cmdclass[command] = klass
+            return klass
+
+        raise DistutilsModuleError("invalid command '%s'" % command)
+
+
+    def get_command_obj(self, command, create=1):
+        """Return the command object for 'command'.  Normally this object
+        is cached on a previous call to 'get_command_obj()'; if no command
+        object for 'command' is in the cache, then we either create and
+        return it (if 'create' is true) or return None.
+        """
+        cmd_obj = self.command_obj.get(command)
+        if not cmd_obj and create:
+            if DEBUG:
+                self.announce("Distribution.get_command_obj(): " \
+                              "creating '%s' command object" % command)
+
+            klass = self.get_command_class(command)
+            cmd_obj = self.command_obj[command] = klass(self)
+            self.have_run[command] = 0
+
+            # Set any options that were supplied in config files
+            # or on the command line.  (NB. support for error
+            # reporting is lame here: any errors aren't reported
+            # until 'finalize_options()' is called, which means
+            # we won't report the source of the error.)
+            options = self.command_options.get(command)
+            if options:
+                self._set_command_options(cmd_obj, options)
+
+        return cmd_obj
+
+    def _set_command_options(self, command_obj, option_dict=None):
+        """Set the options for 'command_obj' from 'option_dict'.  Basically
+        this means copying elements of a dictionary ('option_dict') to
+        attributes of an instance ('command').
+
+        'command_obj' must be a Command instance.  If 'option_dict' is not
+        supplied, uses the standard option dictionary for this command
+        (from 'self.command_options').
+        """
+        command_name = command_obj.get_command_name()
+        if option_dict is None:
+            option_dict = self.get_option_dict(command_name)
+
+        if DEBUG:
+            self.announce("  setting options for '%s' command:" % command_name)
+        for (option, (source, value)) in option_dict.items():
+            if DEBUG:
+                self.announce("    %s = %s (from %s)" % (option, value,
+                                                         source))
+            try:
+                bool_opts = map(translate_longopt, command_obj.boolean_options)
+            except AttributeError:
+                bool_opts = []
+            try:
+                neg_opt = command_obj.negative_opt
+            except AttributeError:
+                neg_opt = {}
+
+            try:
+                is_string = isinstance(value, str)
+                if option in neg_opt and is_string:
+                    setattr(command_obj, neg_opt[option], not strtobool(value))
+                elif option in bool_opts and is_string:
+                    setattr(command_obj, option, strtobool(value))
+                elif hasattr(command_obj, option):
+                    setattr(command_obj, option, value)
+                else:
+                    raise DistutilsOptionError, \
+                          ("error in %s: command '%s' has no such option '%s'"
+                           % (source, command_name, option))
+            except ValueError, msg:
+                raise DistutilsOptionError, msg
+
+    def reinitialize_command(self, command, reinit_subcommands=0):
+        """Reinitializes a command to the state it was in when first
+        returned by 'get_command_obj()': ie., initialized but not yet
+        finalized.  This provides the opportunity to sneak option
+        values in programmatically, overriding or supplementing
+        user-supplied values from the config files and command line.
+        You'll have to re-finalize the command object (by calling
+        'finalize_options()' or 'ensure_finalized()') before using it for
+        real.
+
+        'command' should be a command name (string) or command object.  If
+        'reinit_subcommands' is true, also reinitializes the command's
+        sub-commands, as declared by the 'sub_commands' class attribute (if
+        it has one).  See the "install" command for an example.  Only
+        reinitializes the sub-commands that actually matter, ie. those
+        whose test predicates return true.
+
+        Returns the reinitialized command object.
+        """
+        from distutils.cmd import Command
+        if not isinstance(command, Command):
+            command_name = command
+            command = self.get_command_obj(command_name)
+        else:
+            command_name = command.get_command_name()
+
+        if not command.finalized:
+            return command
+        command.initialize_options()
+        command.finalized = 0
+        self.have_run[command_name] = 0
+        self._set_command_options(command)
+
+        if reinit_subcommands:
+            for sub in command.get_sub_commands():
+                self.reinitialize_command(sub, reinit_subcommands)
+
+        return command
+
+    # -- Methods that operate on the Distribution ----------------------
+
+    def announce(self, msg, level=log.INFO):
+        log.log(level, msg)
+
+    def run_commands(self):
+        """Run each command that was seen on the setup script command line.
+        Uses the list of commands found and cache of command objects
+        created by 'get_command_obj()'.
+        """
+        for cmd in self.commands:
+            self.run_command(cmd)
+
+    # -- Methods that operate on its Commands --------------------------
+
+    def run_command(self, command):
+        """Do whatever it takes to run a command (including nothing at all,
+        if the command has already been run).  Specifically: if we have
+        already created and run the command named by 'command', return
+        silently without doing anything.  If the command named by 'command'
+        doesn't even have a command object yet, create one.  Then invoke
+        'run()' on that command object (or an existing one).
+        """
+        # Already been here, done that? then return silently.
+        if self.have_run.get(command):
+            return
+
+        log.info("running %s", command)
+        cmd_obj = self.get_command_obj(command)
+        cmd_obj.ensure_finalized()
+        cmd_obj.run()
+        self.have_run[command] = 1
+
+
+    # -- Distribution query methods ------------------------------------
+
+    def has_pure_modules(self):
+        return len(self.packages or self.py_modules or []) > 0
+
+    def has_ext_modules(self):
+        return self.ext_modules and len(self.ext_modules) > 0
+
+    def has_c_libraries(self):
+        return self.libraries and len(self.libraries) > 0
+
+    def has_modules(self):
+        return self.has_pure_modules() or self.has_ext_modules()
+
+    def has_headers(self):
+        return self.headers and len(self.headers) > 0
+
+    def has_scripts(self):
+        return self.scripts and len(self.scripts) > 0
+
+    def has_data_files(self):
+        return self.data_files and len(self.data_files) > 0
+
+    def is_pure(self):
+        return (self.has_pure_modules() and
+                not self.has_ext_modules() and
+                not self.has_c_libraries())
+
+    # -- Metadata query methods ----------------------------------------
+
+    # If you're looking for 'get_name()', 'get_version()', and so forth,
+    # they are defined in a sneaky way: the constructor binds self.get_XXX
+    # to self.metadata.get_XXX.  The actual code is in the
+    # DistributionMetadata class, below.
+
+class DistributionMetadata:
+    """Dummy class to hold the distribution meta-data: name, version,
+    author, and so forth.
+    """
+
+    _METHOD_BASENAMES = ("name", "version", "author", "author_email",
+                         "maintainer", "maintainer_email", "url",
+                         "license", "description", "long_description",
+                         "keywords", "platforms", "fullname", "contact",
+                         "contact_email", "license", "classifiers",
+                         "download_url",
+                         # PEP 314
+                         "provides", "requires", "obsoletes",
+                         )
+
+    def __init__(self, path=None):
+        if path is not None:
+            self.read_pkg_file(open(path))
+        else:
+            self.name = None
+            self.version = None
+            self.author = None
+            self.author_email = None
+            self.maintainer = None
+            self.maintainer_email = None
+            self.url = None
+            self.license = None
+            self.description = None
+            self.long_description = None
+            self.keywords = None
+            self.platforms = None
+            self.classifiers = None
+            self.download_url = None
+            # PEP 314
+            self.provides = None
+            self.requires = None
+            self.obsoletes = None
+
+    def read_pkg_file(self, file):
+        """Reads the metadata values from a file object."""
+        msg = message_from_file(file)
+
+        def _read_field(name):
+            value = msg[name]
+            if value == 'UNKNOWN':
+                return None
+            return value
+
+        def _read_list(name):
+            values = msg.get_all(name, None)
+            if values == []:
+                return None
+            return values
+
+        metadata_version = msg['metadata-version']
+        self.name = _read_field('name')
+        self.version = _read_field('version')
+        self.description = _read_field('summary')
+        # we are filling author only.
+        self.author = _read_field('author')
+        self.maintainer = None
+        self.author_email = _read_field('author-email')
+        self.maintainer_email = None
+        self.url = _read_field('home-page')
+        self.license = _read_field('license')
+
+        if 'download-url' in msg:
+            self.download_url = _read_field('download-url')
+        else:
+            self.download_url = None
+
+        self.long_description = _read_field('description')
+        self.description = _read_field('summary')
+
+        if 'keywords' in msg:
+            self.keywords = _read_field('keywords').split(',')
+
+        self.platforms = _read_list('platform')
+        self.classifiers = _read_list('classifier')
+
+        # PEP 314 - these fields only exist in 1.1
+        if metadata_version == '1.1':
+            self.requires = _read_list('requires')
+            self.provides = _read_list('provides')
+            self.obsoletes = _read_list('obsoletes')
+        else:
+            self.requires = None
+            self.provides = None
+            self.obsoletes = None
+
+    def write_pkg_info(self, base_dir):
+        """Write the PKG-INFO file into the release tree.
+        """
+        pkg_info = open(os.path.join(base_dir, 'PKG-INFO'), 'w')
+        try:
+            self.write_pkg_file(pkg_info)
+        finally:
+            pkg_info.close()
+
+    def write_pkg_file(self, file):
+        """Write the PKG-INFO format data to a file object.
+        """
+        version = '1.0'
+        if (self.provides or self.requires or self.obsoletes or
+            self.classifiers or self.download_url):
+            version = '1.1'
+
+        self._write_field(file, 'Metadata-Version', version)
+        self._write_field(file, 'Name', self.get_name())
+        self._write_field(file, 'Version', self.get_version())
+        self._write_field(file, 'Summary', self.get_description())
+        self._write_field(file, 'Home-page', self.get_url())
+        self._write_field(file, 'Author', self.get_contact())
+        self._write_field(file, 'Author-email', self.get_contact_email())
+        self._write_field(file, 'License', self.get_license())
+        if self.download_url:
+            self._write_field(file, 'Download-URL', self.download_url)
+
+        long_desc = rfc822_escape(self.get_long_description())
+        self._write_field(file, 'Description', long_desc)
+
+        keywords = ','.join(self.get_keywords())
+        if keywords:
+            self._write_field(file, 'Keywords', keywords)
+
+        self._write_list(file, 'Platform', self.get_platforms())
+        self._write_list(file, 'Classifier', self.get_classifiers())
+
+        # PEP 314
+        self._write_list(file, 'Requires', self.get_requires())
+        self._write_list(file, 'Provides', self.get_provides())
+        self._write_list(file, 'Obsoletes', self.get_obsoletes())
+
+    def _write_field(self, file, name, value):
+        file.write('%s: %s\n' % (name, self._encode_field(value)))
+
+    def _write_list (self, file, name, values):
+        for value in values:
+            self._write_field(file, name, value)
+
+    def _encode_field(self, value):
+        if value is None:
+            return None
+        if isinstance(value, unicode):
+            return value.encode(PKG_INFO_ENCODING)
+        return str(value)
+
+    # -- Metadata query methods ----------------------------------------
+
+    def get_name(self):
+        return self.name or "UNKNOWN"
+
+    def get_version(self):
+        return self.version or "0.0.0"
+
+    def get_fullname(self):
+        return "%s-%s" % (self.get_name(), self.get_version())
+
+    def get_author(self):
+        return self._encode_field(self.author) or "UNKNOWN"
+
+    def get_author_email(self):
+        return self.author_email or "UNKNOWN"
+
+    def get_maintainer(self):
+        return self._encode_field(self.maintainer) or "UNKNOWN"
+
+    def get_maintainer_email(self):
+        return self.maintainer_email or "UNKNOWN"
+
+    def get_contact(self):
+        return (self._encode_field(self.maintainer) or
+                self._encode_field(self.author) or "UNKNOWN")
+
+    def get_contact_email(self):
+        return self.maintainer_email or self.author_email or "UNKNOWN"
+
+    def get_url(self):
+        return self.url or "UNKNOWN"
+
+    def get_license(self):
+        return self.license or "UNKNOWN"
+    get_licence = get_license
+
+    def get_description(self):
+        return self._encode_field(self.description) or "UNKNOWN"
+
+    def get_long_description(self):
+        return self._encode_field(self.long_description) or "UNKNOWN"
+
+    def get_keywords(self):
+        return self.keywords or []
+
+    def get_platforms(self):
+        return self.platforms or ["UNKNOWN"]
+
+    def get_classifiers(self):
+        return self.classifiers or []
+
+    def get_download_url(self):
+        return self.download_url or "UNKNOWN"
+
+    # PEP 314
+    def get_requires(self):
+        return self.requires or []
+
+    def set_requires(self, value):
+        import distutils.versionpredicate
+        for v in value:
+            distutils.versionpredicate.VersionPredicate(v)
+        self.requires = value
+
+    def get_provides(self):
+        return self.provides or []
+
+    def set_provides(self, value):
+        value = [v.strip() for v in value]
+        for v in value:
+            import distutils.versionpredicate
+            distutils.versionpredicate.split_provision(v)
+        self.provides = value
+
+    def get_obsoletes(self):
+        return self.obsoletes or []
+
+    def set_obsoletes(self, value):
+        import distutils.versionpredicate
+        for v in value:
+            distutils.versionpredicate.VersionPredicate(v)
+        self.obsoletes = value
+
+def fix_help_options(options):
+    """Convert a 4-tuple 'help_options' list as found in various command
+    classes to the 3-tuple form required by FancyGetopt.
+    """
+    new_options = []
+    for help_tuple in options:
+        new_options.append(help_tuple[0:3])
+    return new_options
diff --git a/src/main/resources/PythonLibs/distutils/emxccompiler.py b/src/main/resources/PythonLibs/distutils/emxccompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0172058a38175d00bc2da288447c2336be6c15c
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/emxccompiler.py
@@ -0,0 +1,319 @@
+"""distutils.emxccompiler
+
+Provides the EMXCCompiler class, a subclass of UnixCCompiler that
+handles the EMX port of the GNU C compiler to OS/2.
+"""
+
+# issues:
+#
+# * OS/2 insists that DLLs can have names no longer than 8 characters
+#   We put export_symbols in a def-file, as though the DLL can have
+#   an arbitrary length name, but truncate the output filename.
+#
+# * only use OMF objects and use LINK386 as the linker (-Zomf)
+#
+# * always build for multithreading (-Zmt) as the accompanying OS/2 port
+#   of Python is only distributed with threads enabled.
+#
+# tested configurations:
+#
+# * EMX gcc 2.81/EMX 0.9d fix03
+
+__revision__ = "$Id$"
+
+import os,sys,copy
+from distutils.ccompiler import gen_preprocess_options, gen_lib_options
+from distutils.unixccompiler import UnixCCompiler
+from distutils.file_util import write_file
+from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
+from distutils import log
+
+class EMXCCompiler (UnixCCompiler):
+
+    compiler_type = 'emx'
+    obj_extension = ".obj"
+    static_lib_extension = ".lib"
+    shared_lib_extension = ".dll"
+    static_lib_format = "%s%s"
+    shared_lib_format = "%s%s"
+    res_extension = ".res"      # compiled resource file
+    exe_extension = ".exe"
+
+    def __init__ (self,
+                  verbose=0,
+                  dry_run=0,
+                  force=0):
+
+        UnixCCompiler.__init__ (self, verbose, dry_run, force)
+
+        (status, details) = check_config_h()
+        self.debug_print("Python's GCC status: %s (details: %s)" %
+                         (status, details))
+        if status is not CONFIG_H_OK:
+            self.warn(
+                "Python's pyconfig.h doesn't seem to support your compiler.  " +
+                ("Reason: %s." % details) +
+                "Compiling may fail because of undefined preprocessor macros.")
+
+        (self.gcc_version, self.ld_version) = \
+            get_versions()
+        self.debug_print(self.compiler_type + ": gcc %s, ld %s\n" %
+                         (self.gcc_version,
+                          self.ld_version) )
+
+        # Hard-code GCC because that's what this is all about.
+        # XXX optimization, warnings etc. should be customizable.
+        self.set_executables(compiler='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',
+                             compiler_so='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',
+                             linker_exe='gcc -Zomf -Zmt -Zcrtdll',
+                             linker_so='gcc -Zomf -Zmt -Zcrtdll -Zdll')
+
+        # want the gcc library statically linked (so that we don't have
+        # to distribute a version dependent on the compiler we have)
+        self.dll_libraries=["gcc"]
+
+    # __init__ ()
+
+    def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+        if ext == '.rc':
+            # gcc requires '.rc' compiled to binary ('.res') files !!!
+            try:
+                self.spawn(["rc", "-r", src])
+            except DistutilsExecError, msg:
+                raise CompileError, msg
+        else: # for other files use the C-compiler
+            try:
+                self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
+                           extra_postargs)
+            except DistutilsExecError, msg:
+                raise CompileError, msg
+
+    def link (self,
+              target_desc,
+              objects,
+              output_filename,
+              output_dir=None,
+              libraries=None,
+              library_dirs=None,
+              runtime_library_dirs=None,
+              export_symbols=None,
+              debug=0,
+              extra_preargs=None,
+              extra_postargs=None,
+              build_temp=None,
+              target_lang=None):
+
+        # use separate copies, so we can modify the lists
+        extra_preargs = copy.copy(extra_preargs or [])
+        libraries = copy.copy(libraries or [])
+        objects = copy.copy(objects or [])
+
+        # Additional libraries
+        libraries.extend(self.dll_libraries)
+
+        # handle export symbols by creating a def-file
+        # with executables this only works with gcc/ld as linker
+        if ((export_symbols is not None) and
+            (target_desc != self.EXECUTABLE)):
+            # (The linker doesn't do anything if output is up-to-date.
+            # So it would probably better to check if we really need this,
+            # but for this we had to insert some unchanged parts of
+            # UnixCCompiler, and this is not what we want.)
+
+            # we want to put some files in the same directory as the
+            # object files are, build_temp doesn't help much
+            # where are the object files
+            temp_dir = os.path.dirname(objects[0])
+            # name of dll to give the helper files the same base name
+            (dll_name, dll_extension) = os.path.splitext(
+                os.path.basename(output_filename))
+
+            # generate the filenames for these files
+            def_file = os.path.join(temp_dir, dll_name + ".def")
+
+            # Generate .def file
+            contents = [
+                "LIBRARY %s INITINSTANCE TERMINSTANCE" % \
+                os.path.splitext(os.path.basename(output_filename))[0],
+                "DATA MULTIPLE NONSHARED",
+                "EXPORTS"]
+            for sym in export_symbols:
+                contents.append('  "%s"' % sym)
+            self.execute(write_file, (def_file, contents),
+                         "writing %s" % def_file)
+
+            # next add options for def-file and to creating import libraries
+            # for gcc/ld the def-file is specified as any other object files
+            objects.append(def_file)
+
+        #end: if ((export_symbols is not None) and
+        #        (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
+
+        # who wants symbols and a many times larger output file
+        # should explicitly switch the debug mode on
+        # otherwise we let dllwrap/ld strip the output file
+        # (On my machine: 10KB < stripped_file < ??100KB
+        #   unstripped_file = stripped_file + XXX KB
+        #  ( XXX=254 for a typical python extension))
+        if not debug:
+            extra_preargs.append("-s")
+
+        UnixCCompiler.link(self,
+                           target_desc,
+                           objects,
+                           output_filename,
+                           output_dir,
+                           libraries,
+                           library_dirs,
+                           runtime_library_dirs,
+                           None, # export_symbols, we do this in our def-file
+                           debug,
+                           extra_preargs,
+                           extra_postargs,
+                           build_temp,
+                           target_lang)
+
+    # link ()
+
+    # -- Miscellaneous methods -----------------------------------------
+
+    # override the object_filenames method from CCompiler to
+    # support rc and res-files
+    def object_filenames (self,
+                          source_filenames,
+                          strip_dir=0,
+                          output_dir=''):
+        if output_dir is None: output_dir = ''
+        obj_names = []
+        for src_name in source_filenames:
+            # use normcase to make sure '.rc' is really '.rc' and not '.RC'
+            (base, ext) = os.path.splitext (os.path.normcase(src_name))
+            if ext not in (self.src_extensions + ['.rc']):
+                raise UnknownFileError, \
+                      "unknown file type '%s' (from '%s')" % \
+                      (ext, src_name)
+            if strip_dir:
+                base = os.path.basename (base)
+            if ext == '.rc':
+                # these need to be compiled to object files
+                obj_names.append (os.path.join (output_dir,
+                                            base + self.res_extension))
+            else:
+                obj_names.append (os.path.join (output_dir,
+                                            base + self.obj_extension))
+        return obj_names
+
+    # object_filenames ()
+
+    # override the find_library_file method from UnixCCompiler
+    # to deal with file naming/searching differences
+    def find_library_file(self, dirs, lib, debug=0):
+        shortlib = '%s.lib' % lib
+        longlib = 'lib%s.lib' % lib    # this form very rare
+
+        # get EMX's default library directory search path
+        try:
+            emx_dirs = os.environ['LIBRARY_PATH'].split(';')
+        except KeyError:
+            emx_dirs = []
+
+        for dir in dirs + emx_dirs:
+            shortlibp = os.path.join(dir, shortlib)
+            longlibp = os.path.join(dir, longlib)
+            if os.path.exists(shortlibp):
+                return shortlibp
+            elif os.path.exists(longlibp):
+                return longlibp
+
+        # Oops, didn't find it in *any* of 'dirs'
+        return None
+
+# class EMXCCompiler
+
+
+# Because these compilers aren't configured in Python's pyconfig.h file by
+# default, we should at least warn the user if he is using a unmodified
+# version.
+
+CONFIG_H_OK = "ok"
+CONFIG_H_NOTOK = "not ok"
+CONFIG_H_UNCERTAIN = "uncertain"
+
+def check_config_h():
+
+    """Check if the current Python installation (specifically, pyconfig.h)
+    appears amenable to building extensions with GCC.  Returns a tuple
+    (status, details), where 'status' is one of the following constants:
+      CONFIG_H_OK
+        all is well, go ahead and compile
+      CONFIG_H_NOTOK
+        doesn't look good
+      CONFIG_H_UNCERTAIN
+        not sure -- unable to read pyconfig.h
+    'details' is a human-readable string explaining the situation.
+
+    Note there are two ways to conclude "OK": either 'sys.version' contains
+    the string "GCC" (implying that this Python was built with GCC), or the
+    installed "pyconfig.h" contains the string "__GNUC__".
+    """
+
+    # XXX since this function also checks sys.version, it's not strictly a
+    # "pyconfig.h" check -- should probably be renamed...
+
+    from distutils import sysconfig
+    import string
+    # if sys.version contains GCC then python was compiled with
+    # GCC, and the pyconfig.h file should be OK
+    if string.find(sys.version,"GCC") >= 0:
+        return (CONFIG_H_OK, "sys.version mentions 'GCC'")
+
+    fn = sysconfig.get_config_h_filename()
+    try:
+        # It would probably better to read single lines to search.
+        # But we do this only once, and it is fast enough
+        f = open(fn)
+        try:
+            s = f.read()
+        finally:
+            f.close()
+
+    except IOError, exc:
+        # if we can't read this file, we cannot say it is wrong
+        # the compiler will complain later about this file as missing
+        return (CONFIG_H_UNCERTAIN,
+                "couldn't read '%s': %s" % (fn, exc.strerror))
+
+    else:
+        # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
+        if string.find(s,"__GNUC__") >= 0:
+            return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
+        else:
+            return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
+
+
+def get_versions():
+    """ Try to find out the versions of gcc and ld.
+        If not possible it returns None for it.
+    """
+    from distutils.version import StrictVersion
+    from distutils.spawn import find_executable
+    import re
+
+    gcc_exe = find_executable('gcc')
+    if gcc_exe:
+        out = os.popen(gcc_exe + ' -dumpversion','r')
+        try:
+            out_string = out.read()
+        finally:
+            out.close()
+        result = re.search('(\d+\.\d+\.\d+)',out_string)
+        if result:
+            gcc_version = StrictVersion(result.group(1))
+        else:
+            gcc_version = None
+    else:
+        gcc_version = None
+    # EMX ld has no way of reporting version number, and we use GCC
+    # anyway - so we can link OMF DLLs
+    ld_version = None
+    return (gcc_version, ld_version)
diff --git a/src/main/resources/PythonLibs/distutils/errors.py b/src/main/resources/PythonLibs/distutils/errors.py
new file mode 100644
index 0000000000000000000000000000000000000000..d9c47c761cb4428cacef0efbe010f78a9d1f930d
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/errors.py
@@ -0,0 +1,88 @@
+"""distutils.errors
+
+Provides exceptions used by the Distutils modules.  Note that Distutils
+modules may raise standard exceptions; in particular, SystemExit is
+usually raised for errors that are obviously the end-user's fault
+(eg. bad command-line arguments).
+
+This module is safe to use in "from ... import *" mode; it only exports
+symbols whose names start with "Distutils" and end with "Error"."""
+
+__revision__ = "$Id$"
+
+class DistutilsError(Exception):
+    """The root of all Distutils evil."""
+
+class DistutilsModuleError(DistutilsError):
+    """Unable to load an expected module, or to find an expected class
+    within some module (in particular, command modules and classes)."""
+
+class DistutilsClassError(DistutilsError):
+    """Some command class (or possibly distribution class, if anyone
+    feels a need to subclass Distribution) is found not to be holding
+    up its end of the bargain, ie. implementing some part of the
+    "command "interface."""
+
+class DistutilsGetoptError(DistutilsError):
+    """The option table provided to 'fancy_getopt()' is bogus."""
+
+class DistutilsArgError(DistutilsError):
+    """Raised by fancy_getopt in response to getopt.error -- ie. an
+    error in the command line usage."""
+
+class DistutilsFileError(DistutilsError):
+    """Any problems in the filesystem: expected file not found, etc.
+    Typically this is for problems that we detect before IOError or
+    OSError could be raised."""
+
+class DistutilsOptionError(DistutilsError):
+    """Syntactic/semantic errors in command options, such as use of
+    mutually conflicting options, or inconsistent options,
+    badly-spelled values, etc.  No distinction is made between option
+    values originating in the setup script, the command line, config
+    files, or what-have-you -- but if we *know* something originated in
+    the setup script, we'll raise DistutilsSetupError instead."""
+
+class DistutilsSetupError(DistutilsError):
+    """For errors that can be definitely blamed on the setup script,
+    such as invalid keyword arguments to 'setup()'."""
+
+class DistutilsPlatformError(DistutilsError):
+    """We don't know how to do something on the current platform (but
+    we do know how to do it on some platform) -- eg. trying to compile
+    C files on a platform not supported by a CCompiler subclass."""
+
+class DistutilsExecError(DistutilsError):
+    """Any problems executing an external program (such as the C
+    compiler, when compiling C files)."""
+
+class DistutilsInternalError(DistutilsError):
+    """Internal inconsistencies or impossibilities (obviously, this
+    should never be seen if the code is working!)."""
+
+class DistutilsTemplateError(DistutilsError):
+    """Syntax error in a file list template."""
+
+class DistutilsByteCompileError(DistutilsError):
+    """Byte compile error."""
+
+# Exception classes used by the CCompiler implementation classes
+class CCompilerError(Exception):
+    """Some compile/link operation failed."""
+
+class PreprocessError(CCompilerError):
+    """Failure to preprocess one or more C/C++ files."""
+
+class CompileError(CCompilerError):
+    """Failure to compile one or more C/C++ source files."""
+
+class LibError(CCompilerError):
+    """Failure to create a static library from one or more C/C++ object
+    files."""
+
+class LinkError(CCompilerError):
+    """Failure to link one or more C/C++ object files into an executable
+    or shared library file."""
+
+class UnknownFileError(CCompilerError):
+    """Attempt to process an unknown file type."""
diff --git a/src/main/resources/PythonLibs/distutils/extension.py b/src/main/resources/PythonLibs/distutils/extension.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a67ca8b3ea9b4690e69a6e47a01794b01106d39
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/extension.py
@@ -0,0 +1,255 @@
+"""distutils.extension
+
+Provides the Extension class, used to describe C/C++ extension
+modules in setup scripts."""
+
+__revision__ = "$Id$"
+
+import os, string, sys
+from types import *
+
+try:
+    import warnings
+except ImportError:
+    warnings = None
+
+# This class is really only used by the "build_ext" command, so it might
+# make sense to put it in distutils.command.build_ext.  However, that
+# module is already big enough, and I want to make this class a bit more
+# complex to simplify some common cases ("foo" module in "foo.c") and do
+# better error-checking ("foo.c" actually exists).
+#
+# Also, putting this in build_ext.py means every setup script would have to
+# import that large-ish module (indirectly, through distutils.core) in
+# order to do anything.
+
+class Extension:
+    """Just a collection of attributes that describes an extension
+    module and everything needed to build it (hopefully in a portable
+    way, but there are hooks that let you be as unportable as you need).
+
+    Instance attributes:
+      name : string
+        the full name of the extension, including any packages -- ie.
+        *not* a filename or pathname, but Python dotted name
+      sources : [string]
+        list of source filenames, relative to the distribution root
+        (where the setup script lives), in Unix form (slash-separated)
+        for portability.  Source files may be C, C++, SWIG (.i),
+        platform-specific resource files, or whatever else is recognized
+        by the "build_ext" command as source for a Python extension.
+      include_dirs : [string]
+        list of directories to search for C/C++ header files (in Unix
+        form for portability)
+      define_macros : [(name : string, value : string|None)]
+        list of macros to define; each macro is defined using a 2-tuple,
+        where 'value' is either the string to define it to or None to
+        define it without a particular value (equivalent of "#define
+        FOO" in source or -DFOO on Unix C compiler command line)
+      undef_macros : [string]
+        list of macros to undefine explicitly
+      library_dirs : [string]
+        list of directories to search for C/C++ libraries at link time
+      libraries : [string]
+        list of library names (not filenames or paths) to link against
+      runtime_library_dirs : [string]
+        list of directories to search for C/C++ libraries at run time
+        (for shared extensions, this is when the extension is loaded)
+      extra_objects : [string]
+        list of extra files to link with (eg. object files not implied
+        by 'sources', static library that must be explicitly specified,
+        binary resource files, etc.)
+      extra_compile_args : [string]
+        any extra platform- and compiler-specific information to use
+        when compiling the source files in 'sources'.  For platforms and
+        compilers where "command line" makes sense, this is typically a
+        list of command-line arguments, but for other platforms it could
+        be anything.
+      extra_link_args : [string]
+        any extra platform- and compiler-specific information to use
+        when linking object files together to create the extension (or
+        to create a new static Python interpreter).  Similar
+        interpretation as for 'extra_compile_args'.
+      export_symbols : [string]
+        list of symbols to be exported from a shared extension.  Not
+        used on all platforms, and not generally necessary for Python
+        extensions, which typically export exactly one symbol: "init" +
+        extension_name.
+      swig_opts : [string]
+        any extra options to pass to SWIG if a source file has the .i
+        extension.
+      depends : [string]
+        list of files that the extension depends on
+      language : string
+        extension language (i.e. "c", "c++", "objc"). Will be detected
+        from the source extensions if not provided.
+    """
+
+    # When adding arguments to this constructor, be sure to update
+    # setup_keywords in core.py.
+    def __init__ (self, name, sources,
+                  include_dirs=None,
+                  define_macros=None,
+                  undef_macros=None,
+                  library_dirs=None,
+                  libraries=None,
+                  runtime_library_dirs=None,
+                  extra_objects=None,
+                  extra_compile_args=None,
+                  extra_link_args=None,
+                  export_symbols=None,
+                  swig_opts = None,
+                  depends=None,
+                  language=None,
+                  **kw                      # To catch unknown keywords
+                 ):
+        assert type(name) is StringType, "'name' must be a string"
+        assert (type(sources) is ListType and
+                map(type, sources) == [StringType]*len(sources)), \
+                "'sources' must be a list of strings"
+
+        self.name = name
+        self.sources = sources
+        self.include_dirs = include_dirs or []
+        self.define_macros = define_macros or []
+        self.undef_macros = undef_macros or []
+        self.library_dirs = library_dirs or []
+        self.libraries = libraries or []
+        self.runtime_library_dirs = runtime_library_dirs or []
+        self.extra_objects = extra_objects or []
+        self.extra_compile_args = extra_compile_args or []
+        self.extra_link_args = extra_link_args or []
+        self.export_symbols = export_symbols or []
+        self.swig_opts = swig_opts or []
+        self.depends = depends or []
+        self.language = language
+
+        # If there are unknown keyword options, warn about them
+        if len(kw):
+            L = kw.keys() ; L.sort()
+            L = map(repr, L)
+            msg = "Unknown Extension options: " + string.join(L, ', ')
+            if warnings is not None:
+                warnings.warn(msg)
+            else:
+                sys.stderr.write(msg + '\n')
+# class Extension
+
+
+def read_setup_file (filename):
+    from distutils.sysconfig import \
+         parse_makefile, expand_makefile_vars, _variable_rx
+    from distutils.text_file import TextFile
+    from distutils.util import split_quoted
+
+    # First pass over the file to gather "VAR = VALUE" assignments.
+    vars = parse_makefile(filename)
+
+    # Second pass to gobble up the real content: lines of the form
+    #   <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...]
+    file = TextFile(filename,
+                    strip_comments=1, skip_blanks=1, join_lines=1,
+                    lstrip_ws=1, rstrip_ws=1)
+    try:
+        extensions = []
+
+        while 1:
+            line = file.readline()
+            if line is None:                # eof
+                break
+            if _variable_rx.match(line):    # VAR=VALUE, handled in first pass
+                continue
+
+                if line[0] == line[-1] == "*":
+                    file.warn("'%s' lines not handled yet" % line)
+                    continue
+
+            #print "original line: " + line
+            line = expand_makefile_vars(line, vars)
+            words = split_quoted(line)
+            #print "expanded line: " + line
+
+            # NB. this parses a slightly different syntax than the old
+            # makesetup script: here, there must be exactly one extension per
+            # line, and it must be the first word of the line.  I have no idea
+            # why the old syntax supported multiple extensions per line, as
+            # they all wind up being the same.
+
+            module = words[0]
+            ext = Extension(module, [])
+            append_next_word = None
+
+            for word in words[1:]:
+                if append_next_word is not None:
+                    append_next_word.append(word)
+                    append_next_word = None
+                    continue
+
+                suffix = os.path.splitext(word)[1]
+                switch = word[0:2] ; value = word[2:]
+
+                if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"):
+                    # hmm, should we do something about C vs. C++ sources?
+                    # or leave it up to the CCompiler implementation to
+                    # worry about?
+                    ext.sources.append(word)
+                elif switch == "-I":
+                    ext.include_dirs.append(value)
+                elif switch == "-D":
+                    equals = string.find(value, "=")
+                    if equals == -1:        # bare "-DFOO" -- no value
+                        ext.define_macros.append((value, None))
+                    else:                   # "-DFOO=blah"
+                        ext.define_macros.append((value[0:equals],
+                                                  value[equals+2:]))
+                elif switch == "-U":
+                    ext.undef_macros.append(value)
+                elif switch == "-C":        # only here 'cause makesetup has it!
+                    ext.extra_compile_args.append(word)
+                elif switch == "-l":
+                    ext.libraries.append(value)
+                elif switch == "-L":
+                    ext.library_dirs.append(value)
+                elif switch == "-R":
+                    ext.runtime_library_dirs.append(value)
+                elif word == "-rpath":
+                    append_next_word = ext.runtime_library_dirs
+                elif word == "-Xlinker":
+                    append_next_word = ext.extra_link_args
+                elif word == "-Xcompiler":
+                    append_next_word = ext.extra_compile_args
+                elif switch == "-u":
+                    ext.extra_link_args.append(word)
+                    if not value:
+                        append_next_word = ext.extra_link_args
+                elif word == "-Xcompiler":
+                    append_next_word = ext.extra_compile_args
+                elif switch == "-u":
+                    ext.extra_link_args.append(word)
+                    if not value:
+                        append_next_word = ext.extra_link_args
+                elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
+                    # NB. a really faithful emulation of makesetup would
+                    # append a .o file to extra_objects only if it
+                    # had a slash in it; otherwise, it would s/.o/.c/
+                    # and append it to sources.  Hmmmm.
+                    ext.extra_objects.append(word)
+                else:
+                    file.warn("unrecognized argument '%s'" % word)
+
+            extensions.append(ext)
+    finally:
+        file.close()
+
+        #print "module:", module
+        #print "source files:", source_files
+        #print "cpp args:", cpp_args
+        #print "lib args:", library_args
+
+        #extensions[module] = { 'sources': source_files,
+        #                       'cpp_args': cpp_args,
+        #                       'lib_args': library_args }
+
+    return extensions
+
+# read_setup_file ()
diff --git a/src/main/resources/PythonLibs/distutils/fancy_getopt.py b/src/main/resources/PythonLibs/distutils/fancy_getopt.py
new file mode 100644
index 0000000000000000000000000000000000000000..2dea948025936bf842acbfb26385b8f965a571e8
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/fancy_getopt.py
@@ -0,0 +1,484 @@
+"""distutils.fancy_getopt
+
+Wrapper around the standard getopt module that provides the following
+additional features:
+  * short and long options are tied together
+  * options have help strings, so fancy_getopt could potentially
+    create a complete usage summary
+  * options set attributes of a passed-in object
+"""
+
+__revision__ = "$Id$"
+
+import sys
+import string
+import re
+import getopt
+from distutils.errors import DistutilsGetoptError, DistutilsArgError
+
+# Much like command_re in distutils.core, this is close to but not quite
+# the same as a Python NAME -- except, in the spirit of most GNU
+# utilities, we use '-' in place of '_'.  (The spirit of LISP lives on!)
+# The similarities to NAME are again not a coincidence...
+longopt_pat = r'[a-zA-Z](?:[a-zA-Z0-9-]*)'
+longopt_re = re.compile(r'^%s$' % longopt_pat)
+
+# For recognizing "negative alias" options, eg. "quiet=!verbose"
+neg_alias_re = re.compile("^(%s)=!(%s)$" % (longopt_pat, longopt_pat))
+
+# This is used to translate long options to legitimate Python identifiers
+# (for use as attributes of some object).
+longopt_xlate = string.maketrans('-', '_')
+
+class FancyGetopt:
+    """Wrapper around the standard 'getopt()' module that provides some
+    handy extra functionality:
+      * short and long options are tied together
+      * options have help strings, and help text can be assembled
+        from them
+      * options set attributes of a passed-in object
+      * boolean options can have "negative aliases" -- eg. if
+        --quiet is the "negative alias" of --verbose, then "--quiet"
+        on the command line sets 'verbose' to false
+    """
+
+    def __init__ (self, option_table=None):
+
+        # The option table is (currently) a list of tuples.  The
+        # tuples may have 3 or four values:
+        #   (long_option, short_option, help_string [, repeatable])
+        # if an option takes an argument, its long_option should have '='
+        # appended; short_option should just be a single character, no ':'
+        # in any case.  If a long_option doesn't have a corresponding
+        # short_option, short_option should be None.  All option tuples
+        # must have long options.
+        self.option_table = option_table
+
+        # 'option_index' maps long option names to entries in the option
+        # table (ie. those 3-tuples).
+        self.option_index = {}
+        if self.option_table:
+            self._build_index()
+
+        # 'alias' records (duh) alias options; {'foo': 'bar'} means
+        # --foo is an alias for --bar
+        self.alias = {}
+
+        # 'negative_alias' keeps track of options that are the boolean
+        # opposite of some other option
+        self.negative_alias = {}
+
+        # These keep track of the information in the option table.  We
+        # don't actually populate these structures until we're ready to
+        # parse the command-line, since the 'option_table' passed in here
+        # isn't necessarily the final word.
+        self.short_opts = []
+        self.long_opts = []
+        self.short2long = {}
+        self.attr_name = {}
+        self.takes_arg = {}
+
+        # And 'option_order' is filled up in 'getopt()'; it records the
+        # original order of options (and their values) on the command-line,
+        # but expands short options, converts aliases, etc.
+        self.option_order = []
+
+    # __init__ ()
+
+
+    def _build_index (self):
+        self.option_index.clear()
+        for option in self.option_table:
+            self.option_index[option[0]] = option
+
+    def set_option_table (self, option_table):
+        self.option_table = option_table
+        self._build_index()
+
+    def add_option (self, long_option, short_option=None, help_string=None):
+        if long_option in self.option_index:
+            raise DistutilsGetoptError, \
+                  "option conflict: already an option '%s'" % long_option
+        else:
+            option = (long_option, short_option, help_string)
+            self.option_table.append(option)
+            self.option_index[long_option] = option
+
+
+    def has_option (self, long_option):
+        """Return true if the option table for this parser has an
+        option with long name 'long_option'."""
+        return long_option in self.option_index
+
+    def get_attr_name (self, long_option):
+        """Translate long option name 'long_option' to the form it
+        has as an attribute of some object: ie., translate hyphens
+        to underscores."""
+        return string.translate(long_option, longopt_xlate)
+
+
+    def _check_alias_dict (self, aliases, what):
+        assert isinstance(aliases, dict)
+        for (alias, opt) in aliases.items():
+            if alias not in self.option_index:
+                raise DistutilsGetoptError, \
+                      ("invalid %s '%s': "
+                       "option '%s' not defined") % (what, alias, alias)
+            if opt not in self.option_index:
+                raise DistutilsGetoptError, \
+                      ("invalid %s '%s': "
+                       "aliased option '%s' not defined") % (what, alias, opt)
+
+    def set_aliases (self, alias):
+        """Set the aliases for this option parser."""
+        self._check_alias_dict(alias, "alias")
+        self.alias = alias
+
+    def set_negative_aliases (self, negative_alias):
+        """Set the negative aliases for this option parser.
+        'negative_alias' should be a dictionary mapping option names to
+        option names, both the key and value must already be defined
+        in the option table."""
+        self._check_alias_dict(negative_alias, "negative alias")
+        self.negative_alias = negative_alias
+
+
+    def _grok_option_table (self):
+        """Populate the various data structures that keep tabs on the
+        option table.  Called by 'getopt()' before it can do anything
+        worthwhile.
+        """
+        self.long_opts = []
+        self.short_opts = []
+        self.short2long.clear()
+        self.repeat = {}
+
+        for option in self.option_table:
+            if len(option) == 3:
+                long, short, help = option
+                repeat = 0
+            elif len(option) == 4:
+                long, short, help, repeat = option
+            else:
+                # the option table is part of the code, so simply
+                # assert that it is correct
+                raise ValueError, "invalid option tuple: %r" % (option,)
+
+            # Type- and value-check the option names
+            if not isinstance(long, str) or len(long) < 2:
+                raise DistutilsGetoptError, \
+                      ("invalid long option '%s': "
+                       "must be a string of length >= 2") % long
+
+            if (not ((short is None) or
+                     (isinstance(short, str) and len(short) == 1))):
+                raise DistutilsGetoptError, \
+                      ("invalid short option '%s': "
+                       "must a single character or None") % short
+
+            self.repeat[long] = repeat
+            self.long_opts.append(long)
+
+            if long[-1] == '=':             # option takes an argument?
+                if short: short = short + ':'
+                long = long[0:-1]
+                self.takes_arg[long] = 1
+            else:
+
+                # Is option is a "negative alias" for some other option (eg.
+                # "quiet" == "!verbose")?
+                alias_to = self.negative_alias.get(long)
+                if alias_to is not None:
+                    if self.takes_arg[alias_to]:
+                        raise DistutilsGetoptError, \
+                              ("invalid negative alias '%s': "
+                               "aliased option '%s' takes a value") % \
+                               (long, alias_to)
+
+                    self.long_opts[-1] = long # XXX redundant?!
+                    self.takes_arg[long] = 0
+
+                else:
+                    self.takes_arg[long] = 0
+
+            # If this is an alias option, make sure its "takes arg" flag is
+            # the same as the option it's aliased to.
+            alias_to = self.alias.get(long)
+            if alias_to is not None:
+                if self.takes_arg[long] != self.takes_arg[alias_to]:
+                    raise DistutilsGetoptError, \
+                          ("invalid alias '%s': inconsistent with "
+                           "aliased option '%s' (one of them takes a value, "
+                           "the other doesn't") % (long, alias_to)
+
+
+            # Now enforce some bondage on the long option name, so we can
+            # later translate it to an attribute name on some object.  Have
+            # to do this a bit late to make sure we've removed any trailing
+            # '='.
+            if not longopt_re.match(long):
+                raise DistutilsGetoptError, \
+                      ("invalid long option name '%s' " +
+                       "(must be letters, numbers, hyphens only") % long
+
+            self.attr_name[long] = self.get_attr_name(long)
+            if short:
+                self.short_opts.append(short)
+                self.short2long[short[0]] = long
+
+        # for option_table
+
+    # _grok_option_table()
+
+
+    def getopt (self, args=None, object=None):
+        """Parse command-line options in args. Store as attributes on object.
+
+        If 'args' is None or not supplied, uses 'sys.argv[1:]'.  If
+        'object' is None or not supplied, creates a new OptionDummy
+        object, stores option values there, and returns a tuple (args,
+        object).  If 'object' is supplied, it is modified in place and
+        'getopt()' just returns 'args'; in both cases, the returned
+        'args' is a modified copy of the passed-in 'args' list, which
+        is left untouched.
+        """
+        if args is None:
+            args = sys.argv[1:]
+        if object is None:
+            object = OptionDummy()
+            created_object = 1
+        else:
+            created_object = 0
+
+        self._grok_option_table()
+
+        short_opts = string.join(self.short_opts)
+        try:
+            opts, args = getopt.getopt(args, short_opts, self.long_opts)
+        except getopt.error, msg:
+            raise DistutilsArgError, msg
+
+        for opt, val in opts:
+            if len(opt) == 2 and opt[0] == '-': # it's a short option
+                opt = self.short2long[opt[1]]
+            else:
+                assert len(opt) > 2 and opt[:2] == '--'
+                opt = opt[2:]
+
+            alias = self.alias.get(opt)
+            if alias:
+                opt = alias
+
+            if not self.takes_arg[opt]:     # boolean option?
+                assert val == '', "boolean option can't have value"
+                alias = self.negative_alias.get(opt)
+                if alias:
+                    opt = alias
+                    val = 0
+                else:
+                    val = 1
+
+            attr = self.attr_name[opt]
+            # The only repeating option at the moment is 'verbose'.
+            # It has a negative option -q quiet, which should set verbose = 0.
+            if val and self.repeat.get(attr) is not None:
+                val = getattr(object, attr, 0) + 1
+            setattr(object, attr, val)
+            self.option_order.append((opt, val))
+
+        # for opts
+        if created_object:
+            return args, object
+        else:
+            return args
+
+    # getopt()
+
+
+    def get_option_order (self):
+        """Returns the list of (option, value) tuples processed by the
+        previous run of 'getopt()'.  Raises RuntimeError if
+        'getopt()' hasn't been called yet.
+        """
+        if self.option_order is None:
+            raise RuntimeError, "'getopt()' hasn't been called yet"
+        else:
+            return self.option_order
+
+
+    def generate_help (self, header=None):
+        """Generate help text (a list of strings, one per suggested line of
+        output) from the option table for this FancyGetopt object.
+        """
+        # Blithely assume the option table is good: probably wouldn't call
+        # 'generate_help()' unless you've already called 'getopt()'.
+
+        # First pass: determine maximum length of long option names
+        max_opt = 0
+        for option in self.option_table:
+            long = option[0]
+            short = option[1]
+            l = len(long)
+            if long[-1] == '=':
+                l = l - 1
+            if short is not None:
+                l = l + 5                   # " (-x)" where short == 'x'
+            if l > max_opt:
+                max_opt = l
+
+        opt_width = max_opt + 2 + 2 + 2     # room for indent + dashes + gutter
+
+        # Typical help block looks like this:
+        #   --foo       controls foonabulation
+        # Help block for longest option looks like this:
+        #   --flimflam  set the flim-flam level
+        # and with wrapped text:
+        #   --flimflam  set the flim-flam level (must be between
+        #               0 and 100, except on Tuesdays)
+        # Options with short names will have the short name shown (but
+        # it doesn't contribute to max_opt):
+        #   --foo (-f)  controls foonabulation
+        # If adding the short option would make the left column too wide,
+        # we push the explanation off to the next line
+        #   --flimflam (-l)
+        #               set the flim-flam level
+        # Important parameters:
+        #   - 2 spaces before option block start lines
+        #   - 2 dashes for each long option name
+        #   - min. 2 spaces between option and explanation (gutter)
+        #   - 5 characters (incl. space) for short option name
+
+        # Now generate lines of help text.  (If 80 columns were good enough
+        # for Jesus, then 78 columns are good enough for me!)
+        line_width = 78
+        text_width = line_width - opt_width
+        big_indent = ' ' * opt_width
+        if header:
+            lines = [header]
+        else:
+            lines = ['Option summary:']
+
+        for option in self.option_table:
+            long, short, help = option[:3]
+            text = wrap_text(help, text_width)
+            if long[-1] == '=':
+                long = long[0:-1]
+
+            # Case 1: no short option at all (makes life easy)
+            if short is None:
+                if text:
+                    lines.append("  --%-*s  %s" % (max_opt, long, text[0]))
+                else:
+                    lines.append("  --%-*s  " % (max_opt, long))
+
+            # Case 2: we have a short option, so we have to include it
+            # just after the long option
+            else:
+                opt_names = "%s (-%s)" % (long, short)
+                if text:
+                    lines.append("  --%-*s  %s" %
+                                 (max_opt, opt_names, text[0]))
+                else:
+                    lines.append("  --%-*s" % opt_names)
+
+            for l in text[1:]:
+                lines.append(big_indent + l)
+
+        # for self.option_table
+
+        return lines
+
+    # generate_help ()
+
+    def print_help (self, header=None, file=None):
+        if file is None:
+            file = sys.stdout
+        for line in self.generate_help(header):
+            file.write(line + "\n")
+
+# class FancyGetopt
+
+
+def fancy_getopt (options, negative_opt, object, args):
+    parser = FancyGetopt(options)
+    parser.set_negative_aliases(negative_opt)
+    return parser.getopt(args, object)
+
+
+WS_TRANS = string.maketrans(string.whitespace, ' ' * len(string.whitespace))
+
+def wrap_text (text, width):
+    """wrap_text(text : string, width : int) -> [string]
+
+    Split 'text' into multiple lines of no more than 'width' characters
+    each, and return the list of strings that results.
+    """
+
+    if text is None:
+        return []
+    if len(text) <= width:
+        return [text]
+
+    text = string.expandtabs(text)
+    text = string.translate(text, WS_TRANS)
+    chunks = re.split(r'( +|-+)', text)
+    chunks = filter(None, chunks)      # ' - ' results in empty strings
+    lines = []
+
+    while chunks:
+
+        cur_line = []                   # list of chunks (to-be-joined)
+        cur_len = 0                     # length of current line
+
+        while chunks:
+            l = len(chunks[0])
+            if cur_len + l <= width:    # can squeeze (at least) this chunk in
+                cur_line.append(chunks[0])
+                del chunks[0]
+                cur_len = cur_len + l
+            else:                       # this line is full
+                # drop last chunk if all space
+                if cur_line and cur_line[-1][0] == ' ':
+                    del cur_line[-1]
+                break
+
+        if chunks:                      # any chunks left to process?
+
+            # if the current line is still empty, then we had a single
+            # chunk that's too big too fit on a line -- so we break
+            # down and break it up at the line width
+            if cur_len == 0:
+                cur_line.append(chunks[0][0:width])
+                chunks[0] = chunks[0][width:]
+
+            # all-whitespace chunks at the end of a line can be discarded
+            # (and we know from the re.split above that if a chunk has
+            # *any* whitespace, it is *all* whitespace)
+            if chunks[0][0] == ' ':
+                del chunks[0]
+
+        # and store this line in the list-of-all-lines -- as a single
+        # string, of course!
+        lines.append(string.join(cur_line, ''))
+
+    # while chunks
+
+    return lines
+
+
+def translate_longopt(opt):
+    """Convert a long option name to a valid Python identifier by
+    changing "-" to "_".
+    """
+    return string.translate(opt, longopt_xlate)
+
+
+class OptionDummy:
+    """Dummy class just used as a place to hold command-line option
+    values as instance attributes."""
+
+    def __init__ (self, options=[]):
+        """Create a new OptionDummy instance.  The attributes listed in
+        'options' will be initialized to None."""
+        for opt in options:
+            setattr(self, opt, None)
diff --git a/src/main/resources/PythonLibs/distutils/file_util.py b/src/main/resources/PythonLibs/distutils/file_util.py
new file mode 100644
index 0000000000000000000000000000000000000000..e62ec27fd4f04b3319ecf0d7814443114fe766cb
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/file_util.py
@@ -0,0 +1,231 @@
+"""distutils.file_util
+
+Utility functions for operating on single files.
+"""
+
+__revision__ = "$Id: file_util.py 86238 2010-11-06 04:06:18Z eric.araujo $"
+
+import os
+from distutils.errors import DistutilsFileError
+from distutils import log
+
+# for generating verbose output in 'copy_file()'
+_copy_action = {None: 'copying',
+                'hard': 'hard linking',
+                'sym': 'symbolically linking'}
+
+
+def _copy_file_contents(src, dst, buffer_size=16*1024):
+    """Copy the file 'src' to 'dst'.
+
+    Both must be filenames. Any error opening either file, reading from
+    'src', or writing to 'dst', raises DistutilsFileError.  Data is
+    read/written in chunks of 'buffer_size' bytes (default 16k).  No attempt
+    is made to handle anything apart from regular files.
+    """
+    # Stolen from shutil module in the standard library, but with
+    # custom error-handling added.
+    fsrc = None
+    fdst = None
+    try:
+        try:
+            fsrc = open(src, 'rb')
+        except os.error, (errno, errstr):
+            raise DistutilsFileError("could not open '%s': %s" % (src, errstr))
+
+        if os.path.exists(dst):
+            try:
+                os.unlink(dst)
+            except os.error, (errno, errstr):
+                raise DistutilsFileError(
+                      "could not delete '%s': %s" % (dst, errstr))
+
+        try:
+            fdst = open(dst, 'wb')
+        except os.error, (errno, errstr):
+            raise DistutilsFileError(
+                  "could not create '%s': %s" % (dst, errstr))
+
+        while 1:
+            try:
+                buf = fsrc.read(buffer_size)
+            except os.error, (errno, errstr):
+                raise DistutilsFileError(
+                      "could not read from '%s': %s" % (src, errstr))
+
+            if not buf:
+                break
+
+            try:
+                fdst.write(buf)
+            except os.error, (errno, errstr):
+                raise DistutilsFileError(
+                      "could not write to '%s': %s" % (dst, errstr))
+
+    finally:
+        if fdst:
+            fdst.close()
+        if fsrc:
+            fsrc.close()
+
+def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
+              link=None, verbose=1, dry_run=0):
+    """Copy a file 'src' to 'dst'.
+
+    If 'dst' is a directory, then 'src' is copied there with the same name;
+    otherwise, it must be a filename.  (If the file exists, it will be
+    ruthlessly clobbered.)  If 'preserve_mode' is true (the default),
+    the file's mode (type and permission bits, or whatever is analogous on
+    the current platform) is copied.  If 'preserve_times' is true (the
+    default), the last-modified and last-access times are copied as well.
+    If 'update' is true, 'src' will only be copied if 'dst' does not exist,
+    or if 'dst' does exist but is older than 'src'.
+
+    'link' allows you to make hard links (os.link) or symbolic links
+    (os.symlink) instead of copying: set it to "hard" or "sym"; if it is
+    None (the default), files are copied.  Don't set 'link' on systems that
+    don't support it: 'copy_file()' doesn't check if hard or symbolic
+    linking is available.
+
+    Under Mac OS, uses the native file copy function in macostools; on
+    other systems, uses '_copy_file_contents()' to copy file contents.
+
+    Return a tuple (dest_name, copied): 'dest_name' is the actual name of
+    the output file, and 'copied' is true if the file was copied (or would
+    have been copied, if 'dry_run' true).
+    """
+    # XXX if the destination file already exists, we clobber it if
+    # copying, but blow up if linking.  Hmmm.  And I don't know what
+    # macostools.copyfile() does.  Should definitely be consistent, and
+    # should probably blow up if destination exists and we would be
+    # changing it (ie. it's not already a hard/soft link to src OR
+    # (not update) and (src newer than dst).
+
+    from distutils.dep_util import newer
+    from stat import ST_ATIME, ST_MTIME, ST_MODE, S_IMODE
+
+    if not os.path.isfile(src):
+        raise DistutilsFileError(
+              "can't copy '%s': doesn't exist or not a regular file" % src)
+
+    if os.path.isdir(dst):
+        dir = dst
+        dst = os.path.join(dst, os.path.basename(src))
+    else:
+        dir = os.path.dirname(dst)
+
+    if update and not newer(src, dst):
+        if verbose >= 1:
+            log.debug("not copying %s (output up-to-date)", src)
+        return dst, 0
+
+    try:
+        action = _copy_action[link]
+    except KeyError:
+        raise ValueError("invalid value '%s' for 'link' argument" % link)
+
+    if verbose >= 1:
+        if os.path.basename(dst) == os.path.basename(src):
+            log.info("%s %s -> %s", action, src, dir)
+        else:
+            log.info("%s %s -> %s", action, src, dst)
+
+    if dry_run:
+        return (dst, 1)
+
+    # If linking (hard or symbolic), use the appropriate system call
+    # (Unix only, of course, but that's the caller's responsibility)
+    if link == 'hard':
+        if not (os.path.exists(dst) and os.path.samefile(src, dst)):
+            os.link(src, dst)
+    elif link == 'sym':
+        if not (os.path.exists(dst) and os.path.samefile(src, dst)):
+            os.symlink(src, dst)
+
+    # Otherwise (non-Mac, not linking), copy the file contents and
+    # (optionally) copy the times and mode.
+    else:
+        _copy_file_contents(src, dst)
+        if preserve_mode or preserve_times:
+            st = os.stat(src)
+
+            # According to David Ascher <da@ski.org>, utime() should be done
+            # before chmod() (at least under NT).
+            if preserve_times:
+                os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))
+            if preserve_mode and hasattr(os, 'chmod'):
+                os.chmod(dst, S_IMODE(st[ST_MODE]))
+
+    return (dst, 1)
+
+# XXX I suspect this is Unix-specific -- need porting help!
+def move_file (src, dst, verbose=1, dry_run=0):
+    """Move a file 'src' to 'dst'.
+
+    If 'dst' is a directory, the file will be moved into it with the same
+    name; otherwise, 'src' is just renamed to 'dst'.  Return the new
+    full name of the file.
+
+    Handles cross-device moves on Unix using 'copy_file()'.  What about
+    other systems???
+    """
+    from os.path import exists, isfile, isdir, basename, dirname
+    import errno
+
+    if verbose >= 1:
+        log.info("moving %s -> %s", src, dst)
+
+    if dry_run:
+        return dst
+
+    if not isfile(src):
+        raise DistutilsFileError("can't move '%s': not a regular file" % src)
+
+    if isdir(dst):
+        dst = os.path.join(dst, basename(src))
+    elif exists(dst):
+        raise DistutilsFileError(
+              "can't move '%s': destination '%s' already exists" %
+              (src, dst))
+
+    if not isdir(dirname(dst)):
+        raise DistutilsFileError(
+              "can't move '%s': destination '%s' not a valid path" % \
+              (src, dst))
+
+    copy_it = 0
+    try:
+        os.rename(src, dst)
+    except os.error, (num, msg):
+        if num == errno.EXDEV:
+            copy_it = 1
+        else:
+            raise DistutilsFileError(
+                  "couldn't move '%s' to '%s': %s" % (src, dst, msg))
+
+    if copy_it:
+        copy_file(src, dst, verbose=verbose)
+        try:
+            os.unlink(src)
+        except os.error, (num, msg):
+            try:
+                os.unlink(dst)
+            except os.error:
+                pass
+            raise DistutilsFileError(
+                  ("couldn't move '%s' to '%s' by copy/delete: " +
+                   "delete '%s' failed: %s") %
+                  (src, dst, src, msg))
+    return dst
+
+
+def write_file (filename, contents):
+    """Create a file with the specified name and write 'contents' (a
+    sequence of strings without line terminators) to it.
+    """
+    f = open(filename, "w")
+    try:
+        for line in contents:
+            f.write(line + "\n")
+    finally:
+        f.close()
diff --git a/src/main/resources/PythonLibs/distutils/filelist.py b/src/main/resources/PythonLibs/distutils/filelist.py
new file mode 100644
index 0000000000000000000000000000000000000000..2f1c457ea0bec53348c5e3c88b4fb407339c4b3e
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/filelist.py
@@ -0,0 +1,343 @@
+"""distutils.filelist
+
+Provides the FileList class, used for poking about the filesystem
+and building lists of files.
+"""
+
+__revision__ = "$Id$"
+
+import os, re
+import fnmatch
+from distutils.util import convert_path
+from distutils.errors import DistutilsTemplateError, DistutilsInternalError
+from distutils import log
+
+class FileList:
+    """A list of files built by on exploring the filesystem and filtered by
+    applying various patterns to what we find there.
+
+    Instance attributes:
+      dir
+        directory from which files will be taken -- only used if
+        'allfiles' not supplied to constructor
+      files
+        list of filenames currently being built/filtered/manipulated
+      allfiles
+        complete list of files under consideration (ie. without any
+        filtering applied)
+    """
+
+    def __init__(self, warn=None, debug_print=None):
+        # ignore argument to FileList, but keep them for backwards
+        # compatibility
+        self.allfiles = None
+        self.files = []
+
+    def set_allfiles(self, allfiles):
+        self.allfiles = allfiles
+
+    def findall(self, dir=os.curdir):
+        self.allfiles = findall(dir)
+
+    def debug_print(self, msg):
+        """Print 'msg' to stdout if the global DEBUG (taken from the
+        DISTUTILS_DEBUG environment variable) flag is true.
+        """
+        from distutils.debug import DEBUG
+        if DEBUG:
+            print msg
+
+    # -- List-like methods ---------------------------------------------
+
+    def append(self, item):
+        self.files.append(item)
+
+    def extend(self, items):
+        self.files.extend(items)
+
+    def sort(self):
+        # Not a strict lexical sort!
+        sortable_files = map(os.path.split, self.files)
+        sortable_files.sort()
+        self.files = []
+        for sort_tuple in sortable_files:
+            self.files.append(os.path.join(*sort_tuple))
+
+
+    # -- Other miscellaneous utility methods ---------------------------
+
+    def remove_duplicates(self):
+        # Assumes list has been sorted!
+        for i in range(len(self.files) - 1, 0, -1):
+            if self.files[i] == self.files[i - 1]:
+                del self.files[i]
+
+
+    # -- "File template" methods ---------------------------------------
+
+    def _parse_template_line(self, line):
+        words = line.split()
+        action = words[0]
+
+        patterns = dir = dir_pattern = None
+
+        if action in ('include', 'exclude',
+                      'global-include', 'global-exclude'):
+            if len(words) < 2:
+                raise DistutilsTemplateError, \
+                      "'%s' expects <pattern1> <pattern2> ..." % action
+
+            patterns = map(convert_path, words[1:])
+
+        elif action in ('recursive-include', 'recursive-exclude'):
+            if len(words) < 3:
+                raise DistutilsTemplateError, \
+                      "'%s' expects <dir> <pattern1> <pattern2> ..." % action
+
+            dir = convert_path(words[1])
+            patterns = map(convert_path, words[2:])
+
+        elif action in ('graft', 'prune'):
+            if len(words) != 2:
+                raise DistutilsTemplateError, \
+                     "'%s' expects a single <dir_pattern>" % action
+
+            dir_pattern = convert_path(words[1])
+
+        else:
+            raise DistutilsTemplateError, "unknown action '%s'" % action
+
+        return (action, patterns, dir, dir_pattern)
+
+    def process_template_line(self, line):
+        # Parse the line: split it up, make sure the right number of words
+        # is there, and return the relevant words.  'action' is always
+        # defined: it's the first word of the line.  Which of the other
+        # three are defined depends on the action; it'll be either
+        # patterns, (dir and patterns), or (dir_pattern).
+        action, patterns, dir, dir_pattern = self._parse_template_line(line)
+
+        # OK, now we know that the action is valid and we have the
+        # right number of words on the line for that action -- so we
+        # can proceed with minimal error-checking.
+        if action == 'include':
+            self.debug_print("include " + ' '.join(patterns))
+            for pattern in patterns:
+                if not self.include_pattern(pattern, anchor=1):
+                    log.warn("warning: no files found matching '%s'",
+                             pattern)
+
+        elif action == 'exclude':
+            self.debug_print("exclude " + ' '.join(patterns))
+            for pattern in patterns:
+                if not self.exclude_pattern(pattern, anchor=1):
+                    log.warn(("warning: no previously-included files "
+                              "found matching '%s'"), pattern)
+
+        elif action == 'global-include':
+            self.debug_print("global-include " + ' '.join(patterns))
+            for pattern in patterns:
+                if not self.include_pattern(pattern, anchor=0):
+                    log.warn(("warning: no files found matching '%s' " +
+                              "anywhere in distribution"), pattern)
+
+        elif action == 'global-exclude':
+            self.debug_print("global-exclude " + ' '.join(patterns))
+            for pattern in patterns:
+                if not self.exclude_pattern(pattern, anchor=0):
+                    log.warn(("warning: no previously-included files matching "
+                              "'%s' found anywhere in distribution"),
+                             pattern)
+
+        elif action == 'recursive-include':
+            self.debug_print("recursive-include %s %s" %
+                             (dir, ' '.join(patterns)))
+            for pattern in patterns:
+                if not self.include_pattern(pattern, prefix=dir):
+                    log.warn(("warning: no files found matching '%s' " +
+                                "under directory '%s'"),
+                             pattern, dir)
+
+        elif action == 'recursive-exclude':
+            self.debug_print("recursive-exclude %s %s" %
+                             (dir, ' '.join(patterns)))
+            for pattern in patterns:
+                if not self.exclude_pattern(pattern, prefix=dir):
+                    log.warn(("warning: no previously-included files matching "
+                              "'%s' found under directory '%s'"),
+                             pattern, dir)
+
+        elif action == 'graft':
+            self.debug_print("graft " + dir_pattern)
+            if not self.include_pattern(None, prefix=dir_pattern):
+                log.warn("warning: no directories found matching '%s'",
+                         dir_pattern)
+
+        elif action == 'prune':
+            self.debug_print("prune " + dir_pattern)
+            if not self.exclude_pattern(None, prefix=dir_pattern):
+                log.warn(("no previously-included directories found " +
+                          "matching '%s'"), dir_pattern)
+        else:
+            raise DistutilsInternalError, \
+                  "this cannot happen: invalid action '%s'" % action
+
+    # -- Filtering/selection methods -----------------------------------
+
+    def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0):
+        """Select strings (presumably filenames) from 'self.files' that
+        match 'pattern', a Unix-style wildcard (glob) pattern.
+
+        Patterns are not quite the same as implemented by the 'fnmatch'
+        module: '*' and '?'  match non-special characters, where "special"
+        is platform-dependent: slash on Unix; colon, slash, and backslash on
+        DOS/Windows; and colon on Mac OS.
+
+        If 'anchor' is true (the default), then the pattern match is more
+        stringent: "*.py" will match "foo.py" but not "foo/bar.py".  If
+        'anchor' is false, both of these will match.
+
+        If 'prefix' is supplied, then only filenames starting with 'prefix'
+        (itself a pattern) and ending with 'pattern', with anything in between
+        them, will match.  'anchor' is ignored in this case.
+
+        If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and
+        'pattern' is assumed to be either a string containing a regex or a
+        regex object -- no translation is done, the regex is just compiled
+        and used as-is.
+
+        Selected strings will be added to self.files.
+
+        Return 1 if files are found.
+        """
+        # XXX docstring lying about what the special chars are?
+        files_found = 0
+        pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
+        self.debug_print("include_pattern: applying regex r'%s'" %
+                         pattern_re.pattern)
+
+        # delayed loading of allfiles list
+        if self.allfiles is None:
+            self.findall()
+
+        for name in self.allfiles:
+            if pattern_re.search(name):
+                self.debug_print(" adding " + name)
+                self.files.append(name)
+                files_found = 1
+
+        return files_found
+
+
+    def exclude_pattern(self, pattern, anchor=1, prefix=None, is_regex=0):
+        """Remove strings (presumably filenames) from 'files' that match
+        'pattern'.
+
+        Other parameters are the same as for 'include_pattern()', above.
+        The list 'self.files' is modified in place. Return 1 if files are
+        found.
+        """
+        files_found = 0
+        pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
+        self.debug_print("exclude_pattern: applying regex r'%s'" %
+                         pattern_re.pattern)
+        for i in range(len(self.files)-1, -1, -1):
+            if pattern_re.search(self.files[i]):
+                self.debug_print(" removing " + self.files[i])
+                del self.files[i]
+                files_found = 1
+
+        return files_found
+
+
+# ----------------------------------------------------------------------
+# Utility functions
+
+def findall(dir = os.curdir):
+    """Find all files under 'dir' and return the list of full filenames
+    (relative to 'dir').
+    """
+    from stat import ST_MODE, S_ISREG, S_ISDIR, S_ISLNK
+
+    list = []
+    stack = [dir]
+    pop = stack.pop
+    push = stack.append
+
+    while stack:
+        dir = pop()
+        names = os.listdir(dir)
+
+        for name in names:
+            if dir != os.curdir:        # avoid the dreaded "./" syndrome
+                fullname = os.path.join(dir, name)
+            else:
+                fullname = name
+
+            # Avoid excess stat calls -- just one will do, thank you!
+            stat = os.stat(fullname)
+            mode = stat[ST_MODE]
+            if S_ISREG(mode):
+                list.append(fullname)
+            elif S_ISDIR(mode) and not S_ISLNK(mode):
+                push(fullname)
+
+    return list
+
+
+def glob_to_re(pattern):
+    """Translate a shell-like glob pattern to a regular expression.
+
+    Return a string containing the regex.  Differs from
+    'fnmatch.translate()' in that '*' does not match "special characters"
+    (which are platform-specific).
+    """
+    pattern_re = fnmatch.translate(pattern)
+
+    # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which
+    # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix,
+    # and by extension they shouldn't match such "special characters" under
+    # any OS.  So change all non-escaped dots in the RE to match any
+    # character except the special characters (currently: just os.sep).
+    sep = os.sep
+    if os.sep == '\\':
+        # we're using a regex to manipulate a regex, so we need
+        # to escape the backslash twice
+        sep = r'\\\\'
+    escaped = r'\1[^%s]' % sep
+    pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', escaped, pattern_re)
+    return pattern_re
+
+
+def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0):
+    """Translate a shell-like wildcard pattern to a compiled regular
+    expression.
+
+    Return the compiled regex.  If 'is_regex' true,
+    then 'pattern' is directly compiled to a regex (if it's a string)
+    or just returned as-is (assumes it's a regex object).
+    """
+    if is_regex:
+        if isinstance(pattern, str):
+            return re.compile(pattern)
+        else:
+            return pattern
+
+    if pattern:
+        pattern_re = glob_to_re(pattern)
+    else:
+        pattern_re = ''
+
+    if prefix is not None:
+        # ditch end of pattern character
+        empty_pattern = glob_to_re('')
+        prefix_re = glob_to_re(prefix)[:-len(empty_pattern)]
+        sep = os.sep
+        if os.sep == '\\':
+            sep = r'\\'
+        pattern_re = "^" + sep.join((prefix_re, ".*" + pattern_re))
+    else:                               # no prefix -- respect anchor flag
+        if anchor:
+            pattern_re = "^" + pattern_re
+
+    return re.compile(pattern_re)
diff --git a/src/main/resources/PythonLibs/distutils/jythoncompiler.py b/src/main/resources/PythonLibs/distutils/jythoncompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..91d106a4bdcb1596b365566c5d11e86a353225b2
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/jythoncompiler.py
@@ -0,0 +1,21 @@
+"""distutils.jythoncompiler
+
+Jython does not support extension libraries. This CCompiler simply
+raises CCompiler exceptions.
+"""
+
+from distutils.ccompiler import CCompiler
+from distutils.errors import CCompilerError
+
+class JythonCompiler(CCompiler):
+
+    """Refuses to compile C extensions on Jython"""
+
+    compiler_type = 'jython'
+    executables = {}
+
+    def refuse_compilation(self, *args, **kwargs):
+        """Refuse compilation"""
+        raise CCompilerError('Compiling extensions is not supported on Jython')
+
+    preprocess = compile = create_static_lib = link = refuse_compilation
diff --git a/src/main/resources/PythonLibs/distutils/log.py b/src/main/resources/PythonLibs/distutils/log.py
new file mode 100644
index 0000000000000000000000000000000000000000..758857081c80e13ec772aea668323961478a752b
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/log.py
@@ -0,0 +1,71 @@
+"""A simple log mechanism styled after PEP 282."""
+
+# The class here is styled after PEP 282 so that it could later be
+# replaced with a standard Python logging implementation.
+
+DEBUG = 1
+INFO = 2
+WARN = 3
+ERROR = 4
+FATAL = 5
+
+import sys
+
+class Log:
+
+    def __init__(self, threshold=WARN):
+        self.threshold = threshold
+
+    def _log(self, level, msg, args):
+        if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
+            raise ValueError('%s wrong log level' % str(level))
+
+        if level >= self.threshold:
+            if args:
+                msg = msg % args
+            if level in (WARN, ERROR, FATAL):
+                stream = sys.stderr
+            else:
+                stream = sys.stdout
+            stream.write('%s\n' % msg)
+            stream.flush()
+
+    def log(self, level, msg, *args):
+        self._log(level, msg, args)
+
+    def debug(self, msg, *args):
+        self._log(DEBUG, msg, args)
+
+    def info(self, msg, *args):
+        self._log(INFO, msg, args)
+
+    def warn(self, msg, *args):
+        self._log(WARN, msg, args)
+
+    def error(self, msg, *args):
+        self._log(ERROR, msg, args)
+
+    def fatal(self, msg, *args):
+        self._log(FATAL, msg, args)
+
+_global_log = Log()
+log = _global_log.log
+debug = _global_log.debug
+info = _global_log.info
+warn = _global_log.warn
+error = _global_log.error
+fatal = _global_log.fatal
+
+def set_threshold(level):
+    # return the old threshold for use from tests
+    old = _global_log.threshold
+    _global_log.threshold = level
+    return old
+
+def set_verbosity(v):
+    if v <= 0:
+        set_threshold(WARN)
+    elif v == 1:
+        set_threshold(INFO)
+    elif v >= 2:
+        set_threshold(DEBUG)
diff --git a/src/main/resources/PythonLibs/distutils/msvc9compiler.py b/src/main/resources/PythonLibs/distutils/msvc9compiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ec9b92a5dcbd0656c3bc4ecf32269d3a9e82202
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/msvc9compiler.py
@@ -0,0 +1,801 @@
+"""distutils.msvc9compiler
+
+Contains MSVCCompiler, an implementation of the abstract CCompiler class
+for the Microsoft Visual Studio 2008.
+
+The module is compatible with VS 2005 and VS 2008. You can find legacy support
+for older versions of VS in distutils.msvccompiler.
+"""
+
+# Written by Perry Stoll
+# hacked by Robin Becker and Thomas Heller to do a better job of
+#   finding DevStudio (through the registry)
+# ported to VS2005 and VS 2008 by Christian Heimes
+
+__revision__ = "$Id$"
+
+import os
+import subprocess
+import sys
+import re
+
+from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
+                              CompileError, LibError, LinkError)
+from distutils.ccompiler import CCompiler, gen_lib_options
+from distutils import log
+from distutils.util import get_platform
+
+import _winreg
+
+RegOpenKeyEx = _winreg.OpenKeyEx
+RegEnumKey = _winreg.EnumKey
+RegEnumValue = _winreg.EnumValue
+RegError = _winreg.error
+
+HKEYS = (_winreg.HKEY_USERS,
+         _winreg.HKEY_CURRENT_USER,
+         _winreg.HKEY_LOCAL_MACHINE,
+         _winreg.HKEY_CLASSES_ROOT)
+
+NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32)
+if NATIVE_WIN64:
+    # Visual C++ is a 32-bit application, so we need to look in
+    # the corresponding registry branch, if we're running a
+    # 64-bit Python on Win64
+    VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f"
+    VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f"
+    WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows"
+    NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework"
+else:
+    VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
+    VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f"
+    WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
+    NET_BASE = r"Software\Microsoft\.NETFramework"
+
+# A map keyed by get_platform() return values to values accepted by
+# 'vcvarsall.bat'.  Note a cross-compile may combine these (eg, 'x86_amd64' is
+# the param to cross-compile on x86 targetting amd64.)
+PLAT_TO_VCVARS = {
+    'win32' : 'x86',
+    'win-amd64' : 'amd64',
+    'win-ia64' : 'ia64',
+}
+
+class Reg:
+    """Helper class to read values from the registry
+    """
+
+    def get_value(cls, path, key):
+        for base in HKEYS:
+            d = cls.read_values(base, path)
+            if d and key in d:
+                return d[key]
+        raise KeyError(key)
+    get_value = classmethod(get_value)
+
+    def read_keys(cls, base, key):
+        """Return list of registry keys."""
+        try:
+            handle = RegOpenKeyEx(base, key)
+        except RegError:
+            return None
+        L = []
+        i = 0
+        while True:
+            try:
+                k = RegEnumKey(handle, i)
+            except RegError:
+                break
+            L.append(k)
+            i += 1
+        return L
+    read_keys = classmethod(read_keys)
+
+    def read_values(cls, base, key):
+        """Return dict of registry keys and values.
+
+        All names are converted to lowercase.
+        """
+        try:
+            handle = RegOpenKeyEx(base, key)
+        except RegError:
+            return None
+        d = {}
+        i = 0
+        while True:
+            try:
+                name, value, type = RegEnumValue(handle, i)
+            except RegError:
+                break
+            name = name.lower()
+            d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
+            i += 1
+        return d
+    read_values = classmethod(read_values)
+
+    def convert_mbcs(s):
+        dec = getattr(s, "decode", None)
+        if dec is not None:
+            try:
+                s = dec("mbcs")
+            except UnicodeError:
+                pass
+        return s
+    convert_mbcs = staticmethod(convert_mbcs)
+
+class MacroExpander:
+
+    def __init__(self, version):
+        self.macros = {}
+        self.vsbase = VS_BASE % version
+        self.load_macros(version)
+
+    def set_macro(self, macro, path, key):
+        self.macros["$(%s)" % macro] = Reg.get_value(path, key)
+
+    def load_macros(self, version):
+        self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir")
+        self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir")
+        self.set_macro("FrameworkDir", NET_BASE, "installroot")
+        try:
+            if version >= 8.0:
+                self.set_macro("FrameworkSDKDir", NET_BASE,
+                               "sdkinstallrootv2.0")
+            else:
+                raise KeyError("sdkinstallrootv2.0")
+        except KeyError:
+            raise DistutilsPlatformError(
+            """Python was built with Visual Studio 2008;
+extensions must be built with a compiler than can generate compatible binaries.
+Visual Studio 2008 was not found on this system. If you have Cygwin installed,
+you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
+
+        if version >= 9.0:
+            self.set_macro("FrameworkVersion", self.vsbase, "clr version")
+            self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder")
+        else:
+            p = r"Software\Microsoft\NET Framework Setup\Product"
+            for base in HKEYS:
+                try:
+                    h = RegOpenKeyEx(base, p)
+                except RegError:
+                    continue
+                key = RegEnumKey(h, 0)
+                d = Reg.get_value(base, r"%s\%s" % (p, key))
+                self.macros["$(FrameworkVersion)"] = d["version"]
+
+    def sub(self, s):
+        for k, v in self.macros.items():
+            s = s.replace(k, v)
+        return s
+
+def get_build_version():
+    """Return the version of MSVC that was used to build Python.
+
+    For Python 2.3 and up, the version number is included in
+    sys.version.  For earlier versions, assume the compiler is MSVC 6.
+    """
+    prefix = "MSC v."
+    i = sys.version.find(prefix)
+    if i == -1:
+        return 6
+    i = i + len(prefix)
+    s, rest = sys.version[i:].split(" ", 1)
+    majorVersion = int(s[:-2]) - 6
+    minorVersion = int(s[2:3]) / 10.0
+    # I don't think paths are affected by minor version in version 6
+    if majorVersion == 6:
+        minorVersion = 0
+    if majorVersion >= 6:
+        return majorVersion + minorVersion
+    # else we don't know what version of the compiler this is
+    return None
+
+def normalize_and_reduce_paths(paths):
+    """Return a list of normalized paths with duplicates removed.
+
+    The current order of paths is maintained.
+    """
+    # Paths are normalized so things like:  /a and /a/ aren't both preserved.
+    reduced_paths = []
+    for p in paths:
+        np = os.path.normpath(p)
+        # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
+        if np not in reduced_paths:
+            reduced_paths.append(np)
+    return reduced_paths
+
+def removeDuplicates(variable):
+    """Remove duplicate values of an environment variable.
+    """
+    oldList = variable.split(os.pathsep)
+    newList = []
+    for i in oldList:
+        if i not in newList:
+            newList.append(i)
+    newVariable = os.pathsep.join(newList)
+    return newVariable
+
+def find_vcvarsall(version):
+    """Find the vcvarsall.bat file
+
+    At first it tries to find the productdir of VS 2008 in the registry. If
+    that fails it falls back to the VS90COMNTOOLS env var.
+    """
+    vsbase = VS_BASE % version
+    try:
+        productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
+                                   "productdir")
+    except KeyError:
+        productdir = None
+
+    # trying Express edition
+    if productdir is None:
+        vsbase = VSEXPRESS_BASE % version
+        try:
+            productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
+                                       "productdir")
+        except KeyError:
+            productdir = None
+            log.debug("Unable to find productdir in registry")
+
+    if not productdir or not os.path.isdir(productdir):
+        toolskey = "VS%0.f0COMNTOOLS" % version
+        toolsdir = os.environ.get(toolskey, None)
+
+        if toolsdir and os.path.isdir(toolsdir):
+            productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
+            productdir = os.path.abspath(productdir)
+            if not os.path.isdir(productdir):
+                log.debug("%s is not a valid directory" % productdir)
+                return None
+        else:
+            log.debug("Env var %s is not set or invalid" % toolskey)
+    if not productdir:
+        log.debug("No productdir found")
+        return None
+    vcvarsall = os.path.join(productdir, "vcvarsall.bat")
+    if os.path.isfile(vcvarsall):
+        return vcvarsall
+    log.debug("Unable to find vcvarsall.bat")
+    return None
+
+def query_vcvarsall(version, arch="x86"):
+    """Launch vcvarsall.bat and read the settings from its environment
+    """
+    vcvarsall = find_vcvarsall(version)
+    interesting = set(("include", "lib", "libpath", "path"))
+    result = {}
+
+    if vcvarsall is None:
+        raise DistutilsPlatformError("Unable to find vcvarsall.bat")
+    log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
+    popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+    try:
+        stdout, stderr = popen.communicate()
+        if popen.wait() != 0:
+            raise DistutilsPlatformError(stderr.decode("mbcs"))
+
+        stdout = stdout.decode("mbcs")
+        for line in stdout.split("\n"):
+            line = Reg.convert_mbcs(line)
+            if '=' not in line:
+                continue
+            line = line.strip()
+            key, value = line.split('=', 1)
+            key = key.lower()
+            if key in interesting:
+                if value.endswith(os.pathsep):
+                    value = value[:-1]
+                result[key] = removeDuplicates(value)
+
+    finally:
+        popen.stdout.close()
+        popen.stderr.close()
+
+    if len(result) != len(interesting):
+        raise ValueError(str(list(result.keys())))
+
+    return result
+
+# More globals
+VERSION = get_build_version()
+if VERSION < 8.0:
+    raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
+# MACROS = MacroExpander(VERSION)
+
+class MSVCCompiler(CCompiler) :
+    """Concrete class that implements an interface to Microsoft Visual C++,
+       as defined by the CCompiler abstract class."""
+
+    compiler_type = 'msvc'
+
+    # Just set this so CCompiler's constructor doesn't barf.  We currently
+    # don't use the 'set_executables()' bureaucracy provided by CCompiler,
+    # as it really isn't necessary for this sort of single-compiler class.
+    # Would be nice to have a consistent interface with UnixCCompiler,
+    # though, so it's worth thinking about.
+    executables = {}
+
+    # Private class data (need to distinguish C from C++ source for compiler)
+    _c_extensions = ['.c']
+    _cpp_extensions = ['.cc', '.cpp', '.cxx']
+    _rc_extensions = ['.rc']
+    _mc_extensions = ['.mc']
+
+    # Needed for the filename generation methods provided by the
+    # base class, CCompiler.
+    src_extensions = (_c_extensions + _cpp_extensions +
+                      _rc_extensions + _mc_extensions)
+    res_extension = '.res'
+    obj_extension = '.obj'
+    static_lib_extension = '.lib'
+    shared_lib_extension = '.dll'
+    static_lib_format = shared_lib_format = '%s%s'
+    exe_extension = '.exe'
+
+    def __init__(self, verbose=0, dry_run=0, force=0):
+        CCompiler.__init__ (self, verbose, dry_run, force)
+        self.__version = VERSION
+        self.__root = r"Software\Microsoft\VisualStudio"
+        # self.__macros = MACROS
+        self.__paths = []
+        # target platform (.plat_name is consistent with 'bdist')
+        self.plat_name = None
+        self.__arch = None # deprecated name
+        self.initialized = False
+
+    def initialize(self, plat_name=None):
+        # multi-init means we would need to check platform same each time...
+        assert not self.initialized, "don't init multiple times"
+        if plat_name is None:
+            plat_name = get_platform()
+        # sanity check for platforms to prevent obscure errors later.
+        ok_plats = 'win32', 'win-amd64', 'win-ia64'
+        if plat_name not in ok_plats:
+            raise DistutilsPlatformError("--plat-name must be one of %s" %
+                                         (ok_plats,))
+
+        if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
+            # Assume that the SDK set up everything alright; don't try to be
+            # smarter
+            self.cc = "cl.exe"
+            self.linker = "link.exe"
+            self.lib = "lib.exe"
+            self.rc = "rc.exe"
+            self.mc = "mc.exe"
+        else:
+            # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
+            # to cross compile, you use 'x86_amd64'.
+            # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
+            # compile use 'x86' (ie, it runs the x86 compiler directly)
+            # No idea how itanium handles this, if at all.
+            if plat_name == get_platform() or plat_name == 'win32':
+                # native build or cross-compile to win32
+                plat_spec = PLAT_TO_VCVARS[plat_name]
+            else:
+                # cross compile from win32 -> some 64bit
+                plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \
+                            PLAT_TO_VCVARS[plat_name]
+
+            vc_env = query_vcvarsall(VERSION, plat_spec)
+
+            # take care to only use strings in the environment.
+            self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep)
+            os.environ['lib'] = vc_env['lib'].encode('mbcs')
+            os.environ['include'] = vc_env['include'].encode('mbcs')
+
+            if len(self.__paths) == 0:
+                raise DistutilsPlatformError("Python was built with %s, "
+                       "and extensions need to be built with the same "
+                       "version of the compiler, but it isn't installed."
+                       % self.__product)
+
+            self.cc = self.find_exe("cl.exe")
+            self.linker = self.find_exe("link.exe")
+            self.lib = self.find_exe("lib.exe")
+            self.rc = self.find_exe("rc.exe")   # resource compiler
+            self.mc = self.find_exe("mc.exe")   # message compiler
+            #self.set_path_env_var('lib')
+            #self.set_path_env_var('include')
+
+        # extend the MSVC path with the current path
+        try:
+            for p in os.environ['path'].split(';'):
+                self.__paths.append(p)
+        except KeyError:
+            pass
+        self.__paths = normalize_and_reduce_paths(self.__paths)
+        os.environ['path'] = ";".join(self.__paths)
+
+        self.preprocess_options = None
+        if self.__arch == "x86":
+            self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3',
+                                     '/DNDEBUG']
+            self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3',
+                                          '/Z7', '/D_DEBUG']
+        else:
+            # Win64
+            self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
+                                     '/DNDEBUG']
+            self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
+                                          '/Z7', '/D_DEBUG']
+
+        self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
+        if self.__version >= 7:
+            self.ldflags_shared_debug = [
+                '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None'
+                ]
+        self.ldflags_static = [ '/nologo']
+
+        self.initialized = True
+
+    # -- Worker methods ------------------------------------------------
+
+    def object_filenames(self,
+                         source_filenames,
+                         strip_dir=0,
+                         output_dir=''):
+        # Copied from ccompiler.py, extended to return .res as 'object'-file
+        # for .rc input file
+        if output_dir is None: output_dir = ''
+        obj_names = []
+        for src_name in source_filenames:
+            (base, ext) = os.path.splitext (src_name)
+            base = os.path.splitdrive(base)[1] # Chop off the drive
+            base = base[os.path.isabs(base):]  # If abs, chop off leading /
+            if ext not in self.src_extensions:
+                # Better to raise an exception instead of silently continuing
+                # and later complain about sources and targets having
+                # different lengths
+                raise CompileError ("Don't know how to compile %s" % src_name)
+            if strip_dir:
+                base = os.path.basename (base)
+            if ext in self._rc_extensions:
+                obj_names.append (os.path.join (output_dir,
+                                                base + self.res_extension))
+            elif ext in self._mc_extensions:
+                obj_names.append (os.path.join (output_dir,
+                                                base + self.res_extension))
+            else:
+                obj_names.append (os.path.join (output_dir,
+                                                base + self.obj_extension))
+        return obj_names
+
+
+    def compile(self, sources,
+                output_dir=None, macros=None, include_dirs=None, debug=0,
+                extra_preargs=None, extra_postargs=None, depends=None):
+
+        if not self.initialized:
+            self.initialize()
+        compile_info = self._setup_compile(output_dir, macros, include_dirs,
+                                           sources, depends, extra_postargs)
+        macros, objects, extra_postargs, pp_opts, build = compile_info
+
+        compile_opts = extra_preargs or []
+        compile_opts.append ('/c')
+        if debug:
+            compile_opts.extend(self.compile_options_debug)
+        else:
+            compile_opts.extend(self.compile_options)
+
+        for obj in objects:
+            try:
+                src, ext = build[obj]
+            except KeyError:
+                continue
+            if debug:
+                # pass the full pathname to MSVC in debug mode,
+                # this allows the debugger to find the source file
+                # without asking the user to browse for it
+                src = os.path.abspath(src)
+
+            if ext in self._c_extensions:
+                input_opt = "/Tc" + src
+            elif ext in self._cpp_extensions:
+                input_opt = "/Tp" + src
+            elif ext in self._rc_extensions:
+                # compile .RC to .RES file
+                input_opt = src
+                output_opt = "/fo" + obj
+                try:
+                    self.spawn([self.rc] + pp_opts +
+                               [output_opt] + [input_opt])
+                except DistutilsExecError, msg:
+                    raise CompileError(msg)
+                continue
+            elif ext in self._mc_extensions:
+                # Compile .MC to .RC file to .RES file.
+                #   * '-h dir' specifies the directory for the
+                #     generated include file
+                #   * '-r dir' specifies the target directory of the
+                #     generated RC file and the binary message resource
+                #     it includes
+                #
+                # For now (since there are no options to change this),
+                # we use the source-directory for the include file and
+                # the build directory for the RC file and message
+                # resources. This works at least for win32all.
+                h_dir = os.path.dirname(src)
+                rc_dir = os.path.dirname(obj)
+                try:
+                    # first compile .MC to .RC and .H file
+                    self.spawn([self.mc] +
+                               ['-h', h_dir, '-r', rc_dir] + [src])
+                    base, _ = os.path.splitext (os.path.basename (src))
+                    rc_file = os.path.join (rc_dir, base + '.rc')
+                    # then compile .RC to .RES file
+                    self.spawn([self.rc] +
+                               ["/fo" + obj] + [rc_file])
+
+                except DistutilsExecError, msg:
+                    raise CompileError(msg)
+                continue
+            else:
+                # how to handle this file?
+                raise CompileError("Don't know how to compile %s to %s"
+                                   % (src, obj))
+
+            output_opt = "/Fo" + obj
+            try:
+                self.spawn([self.cc] + compile_opts + pp_opts +
+                           [input_opt, output_opt] +
+                           extra_postargs)
+            except DistutilsExecError, msg:
+                raise CompileError(msg)
+
+        return objects
+
+
+    def create_static_lib(self,
+                          objects,
+                          output_libname,
+                          output_dir=None,
+                          debug=0,
+                          target_lang=None):
+
+        if not self.initialized:
+            self.initialize()
+        (objects, output_dir) = self._fix_object_args(objects, output_dir)
+        output_filename = self.library_filename(output_libname,
+                                                output_dir=output_dir)
+
+        if self._need_link(objects, output_filename):
+            lib_args = objects + ['/OUT:' + output_filename]
+            if debug:
+                pass # XXX what goes here?
+            try:
+                self.spawn([self.lib] + lib_args)
+            except DistutilsExecError, msg:
+                raise LibError(msg)
+        else:
+            log.debug("skipping %s (up-to-date)", output_filename)
+
+
+    def link(self,
+             target_desc,
+             objects,
+             output_filename,
+             output_dir=None,
+             libraries=None,
+             library_dirs=None,
+             runtime_library_dirs=None,
+             export_symbols=None,
+             debug=0,
+             extra_preargs=None,
+             extra_postargs=None,
+             build_temp=None,
+             target_lang=None):
+
+        if not self.initialized:
+            self.initialize()
+        (objects, output_dir) = self._fix_object_args(objects, output_dir)
+        fixed_args = self._fix_lib_args(libraries, library_dirs,
+                                        runtime_library_dirs)
+        (libraries, library_dirs, runtime_library_dirs) = fixed_args
+
+        if runtime_library_dirs:
+            self.warn ("I don't know what to do with 'runtime_library_dirs': "
+                       + str (runtime_library_dirs))
+
+        lib_opts = gen_lib_options(self,
+                                   library_dirs, runtime_library_dirs,
+                                   libraries)
+        if output_dir is not None:
+            output_filename = os.path.join(output_dir, output_filename)
+
+        if self._need_link(objects, output_filename):
+            if target_desc == CCompiler.EXECUTABLE:
+                if debug:
+                    ldflags = self.ldflags_shared_debug[1:]
+                else:
+                    ldflags = self.ldflags_shared[1:]
+            else:
+                if debug:
+                    ldflags = self.ldflags_shared_debug
+                else:
+                    ldflags = self.ldflags_shared
+
+            export_opts = []
+            for sym in (export_symbols or []):
+                export_opts.append("/EXPORT:" + sym)
+
+            ld_args = (ldflags + lib_opts + export_opts +
+                       objects + ['/OUT:' + output_filename])
+
+            # The MSVC linker generates .lib and .exp files, which cannot be
+            # suppressed by any linker switches. The .lib files may even be
+            # needed! Make sure they are generated in the temporary build
+            # directory. Since they have different names for debug and release
+            # builds, they can go into the same directory.
+            build_temp = os.path.dirname(objects[0])
+            if export_symbols is not None:
+                (dll_name, dll_ext) = os.path.splitext(
+                    os.path.basename(output_filename))
+                implib_file = os.path.join(
+                    build_temp,
+                    self.library_filename(dll_name))
+                ld_args.append ('/IMPLIB:' + implib_file)
+
+            self.manifest_setup_ldargs(output_filename, build_temp, ld_args)
+
+            if extra_preargs:
+                ld_args[:0] = extra_preargs
+            if extra_postargs:
+                ld_args.extend(extra_postargs)
+
+            self.mkpath(os.path.dirname(output_filename))
+            try:
+                self.spawn([self.linker] + ld_args)
+            except DistutilsExecError, msg:
+                raise LinkError(msg)
+
+            # embed the manifest
+            # XXX - this is somewhat fragile - if mt.exe fails, distutils
+            # will still consider the DLL up-to-date, but it will not have a
+            # manifest.  Maybe we should link to a temp file?  OTOH, that
+            # implies a build environment error that shouldn't go undetected.
+            mfinfo = self.manifest_get_embed_info(target_desc, ld_args)
+            if mfinfo is not None:
+                mffilename, mfid = mfinfo
+                out_arg = '-outputresource:%s;%s' % (output_filename, mfid)
+                try:
+                    self.spawn(['mt.exe', '-nologo', '-manifest',
+                                mffilename, out_arg])
+                except DistutilsExecError, msg:
+                    raise LinkError(msg)
+        else:
+            log.debug("skipping %s (up-to-date)", output_filename)
+
+    def manifest_setup_ldargs(self, output_filename, build_temp, ld_args):
+        # If we need a manifest at all, an embedded manifest is recommended.
+        # See MSDN article titled
+        # "How to: Embed a Manifest Inside a C/C++ Application"
+        # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
+        # Ask the linker to generate the manifest in the temp dir, so
+        # we can check it, and possibly embed it, later.
+        temp_manifest = os.path.join(
+                build_temp,
+                os.path.basename(output_filename) + ".manifest")
+        ld_args.append('/MANIFESTFILE:' + temp_manifest)
+
+    def manifest_get_embed_info(self, target_desc, ld_args):
+        # If a manifest should be embedded, return a tuple of
+        # (manifest_filename, resource_id).  Returns None if no manifest
+        # should be embedded.  See http://bugs.python.org/issue7833 for why
+        # we want to avoid any manifest for extension modules if we can)
+        for arg in ld_args:
+            if arg.startswith("/MANIFESTFILE:"):
+                temp_manifest = arg.split(":", 1)[1]
+                break
+        else:
+            # no /MANIFESTFILE so nothing to do.
+            return None
+        if target_desc == CCompiler.EXECUTABLE:
+            # by default, executables always get the manifest with the
+            # CRT referenced.
+            mfid = 1
+        else:
+            # Extension modules try and avoid any manifest if possible.
+            mfid = 2
+            temp_manifest = self._remove_visual_c_ref(temp_manifest)
+        if temp_manifest is None:
+            return None
+        return temp_manifest, mfid
+
+    def _remove_visual_c_ref(self, manifest_file):
+        try:
+            # Remove references to the Visual C runtime, so they will
+            # fall through to the Visual C dependency of Python.exe.
+            # This way, when installed for a restricted user (e.g.
+            # runtimes are not in WinSxS folder, but in Python's own
+            # folder), the runtimes do not need to be in every folder
+            # with .pyd's.
+            # Returns either the filename of the modified manifest or
+            # None if no manifest should be embedded.
+            manifest_f = open(manifest_file)
+            try:
+                manifest_buf = manifest_f.read()
+            finally:
+                manifest_f.close()
+            pattern = re.compile(
+                r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
+                r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
+                re.DOTALL)
+            manifest_buf = re.sub(pattern, "", manifest_buf)
+            pattern = "<dependentAssembly>\s*</dependentAssembly>"
+            manifest_buf = re.sub(pattern, "", manifest_buf)
+            # Now see if any other assemblies are referenced - if not, we
+            # don't want a manifest embedded.
+            pattern = re.compile(
+                r"""<assemblyIdentity.*?name=(?:"|')(.+?)(?:"|')"""
+                r""".*?(?:/>|</assemblyIdentity>)""", re.DOTALL)
+            if re.search(pattern, manifest_buf) is None:
+                return None
+
+            manifest_f = open(manifest_file, 'w')
+            try:
+                manifest_f.write(manifest_buf)
+                return manifest_file
+            finally:
+                manifest_f.close()
+        except IOError:
+            pass
+
+    # -- Miscellaneous methods -----------------------------------------
+    # These are all used by the 'gen_lib_options() function, in
+    # ccompiler.py.
+
+    def library_dir_option(self, dir):
+        return "/LIBPATH:" + dir
+
+    def runtime_library_dir_option(self, dir):
+        raise DistutilsPlatformError(
+              "don't know how to set runtime library search path for MSVC++")
+
+    def library_option(self, lib):
+        return self.library_filename(lib)
+
+
+    def find_library_file(self, dirs, lib, debug=0):
+        # Prefer a debugging library if found (and requested), but deal
+        # with it if we don't have one.
+        if debug:
+            try_names = [lib + "_d", lib]
+        else:
+            try_names = [lib]
+        for dir in dirs:
+            for name in try_names:
+                libfile = os.path.join(dir, self.library_filename (name))
+                if os.path.exists(libfile):
+                    return libfile
+        else:
+            # Oops, didn't find it in *any* of 'dirs'
+            return None
+
+    # Helper methods for using the MSVC registry settings
+
+    def find_exe(self, exe):
+        """Return path to an MSVC executable program.
+
+        Tries to find the program in several places: first, one of the
+        MSVC program search paths from the registry; next, the directories
+        in the PATH environment variable.  If any of those work, return an
+        absolute path that is known to exist.  If none of them work, just
+        return the original program name, 'exe'.
+        """
+        for p in self.__paths:
+            fn = os.path.join(os.path.abspath(p), exe)
+            if os.path.isfile(fn):
+                return fn
+
+        # didn't find it; try existing path
+        for p in os.environ['Path'].split(';'):
+            fn = os.path.join(os.path.abspath(p),exe)
+            if os.path.isfile(fn):
+                return fn
+
+        return exe
diff --git a/src/main/resources/PythonLibs/distutils/msvccompiler.py b/src/main/resources/PythonLibs/distutils/msvccompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..0e69fd368cac78f3967f16336731c7bd6dc87151
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/msvccompiler.py
@@ -0,0 +1,659 @@
+"""distutils.msvccompiler
+
+Contains MSVCCompiler, an implementation of the abstract CCompiler class
+for the Microsoft Visual Studio.
+"""
+
+# Written by Perry Stoll
+# hacked by Robin Becker and Thomas Heller to do a better job of
+#   finding DevStudio (through the registry)
+
+__revision__ = "$Id$"
+
+import sys
+import os
+import string
+
+from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
+                              CompileError, LibError, LinkError)
+from distutils.ccompiler import CCompiler, gen_lib_options
+from distutils import log
+
+_can_read_reg = 0
+try:
+    import _winreg
+
+    _can_read_reg = 1
+    hkey_mod = _winreg
+
+    RegOpenKeyEx = _winreg.OpenKeyEx
+    RegEnumKey = _winreg.EnumKey
+    RegEnumValue = _winreg.EnumValue
+    RegError = _winreg.error
+
+except ImportError:
+    try:
+        import win32api
+        import win32con
+        _can_read_reg = 1
+        hkey_mod = win32con
+
+        RegOpenKeyEx = win32api.RegOpenKeyEx
+        RegEnumKey = win32api.RegEnumKey
+        RegEnumValue = win32api.RegEnumValue
+        RegError = win32api.error
+
+    except ImportError:
+        log.info("Warning: Can't read registry to find the "
+                 "necessary compiler setting\n"
+                 "Make sure that Python modules _winreg, "
+                 "win32api or win32con are installed.")
+        pass
+
+if _can_read_reg:
+    HKEYS = (hkey_mod.HKEY_USERS,
+             hkey_mod.HKEY_CURRENT_USER,
+             hkey_mod.HKEY_LOCAL_MACHINE,
+             hkey_mod.HKEY_CLASSES_ROOT)
+
+def read_keys(base, key):
+    """Return list of registry keys."""
+
+    try:
+        handle = RegOpenKeyEx(base, key)
+    except RegError:
+        return None
+    L = []
+    i = 0
+    while 1:
+        try:
+            k = RegEnumKey(handle, i)
+        except RegError:
+            break
+        L.append(k)
+        i = i + 1
+    return L
+
+def read_values(base, key):
+    """Return dict of registry keys and values.
+
+    All names are converted to lowercase.
+    """
+    try:
+        handle = RegOpenKeyEx(base, key)
+    except RegError:
+        return None
+    d = {}
+    i = 0
+    while 1:
+        try:
+            name, value, type = RegEnumValue(handle, i)
+        except RegError:
+            break
+        name = name.lower()
+        d[convert_mbcs(name)] = convert_mbcs(value)
+        i = i + 1
+    return d
+
+def convert_mbcs(s):
+    enc = getattr(s, "encode", None)
+    if enc is not None:
+        try:
+            s = enc("mbcs")
+        except UnicodeError:
+            pass
+    return s
+
+class MacroExpander:
+
+    def __init__(self, version):
+        self.macros = {}
+        self.load_macros(version)
+
+    def set_macro(self, macro, path, key):
+        for base in HKEYS:
+            d = read_values(base, path)
+            if d:
+                self.macros["$(%s)" % macro] = d[key]
+                break
+
+    def load_macros(self, version):
+        vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
+        self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
+        self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
+        net = r"Software\Microsoft\.NETFramework"
+        self.set_macro("FrameworkDir", net, "installroot")
+        try:
+            if version > 7.0:
+                self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
+            else:
+                self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
+        except KeyError:
+            raise DistutilsPlatformError, \
+                  ("""Python was built with Visual Studio 2003;
+extensions must be built with a compiler than can generate compatible binaries.
+Visual Studio 2003 was not found on this system. If you have Cygwin installed,
+you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
+
+        p = r"Software\Microsoft\NET Framework Setup\Product"
+        for base in HKEYS:
+            try:
+                h = RegOpenKeyEx(base, p)
+            except RegError:
+                continue
+            key = RegEnumKey(h, 0)
+            d = read_values(base, r"%s\%s" % (p, key))
+            self.macros["$(FrameworkVersion)"] = d["version"]
+
+    def sub(self, s):
+        for k, v in self.macros.items():
+            s = string.replace(s, k, v)
+        return s
+
+def get_build_version():
+    """Return the version of MSVC that was used to build Python.
+
+    For Python 2.3 and up, the version number is included in
+    sys.version.  For earlier versions, assume the compiler is MSVC 6.
+    """
+
+    prefix = "MSC v."
+    i = string.find(sys.version, prefix)
+    if i == -1:
+        return 6
+    i = i + len(prefix)
+    s, rest = sys.version[i:].split(" ", 1)
+    majorVersion = int(s[:-2]) - 6
+    minorVersion = int(s[2:3]) / 10.0
+    # I don't think paths are affected by minor version in version 6
+    if majorVersion == 6:
+        minorVersion = 0
+    if majorVersion >= 6:
+        return majorVersion + minorVersion
+    # else we don't know what version of the compiler this is
+    return None
+
+def get_build_architecture():
+    """Return the processor architecture.
+
+    Possible results are "Intel", "Itanium", or "AMD64".
+    """
+
+    prefix = " bit ("
+    i = string.find(sys.version, prefix)
+    if i == -1:
+        return "Intel"
+    j = string.find(sys.version, ")", i)
+    return sys.version[i+len(prefix):j]
+
+def normalize_and_reduce_paths(paths):
+    """Return a list of normalized paths with duplicates removed.
+
+    The current order of paths is maintained.
+    """
+    # Paths are normalized so things like:  /a and /a/ aren't both preserved.
+    reduced_paths = []
+    for p in paths:
+        np = os.path.normpath(p)
+        # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
+        if np not in reduced_paths:
+            reduced_paths.append(np)
+    return reduced_paths
+
+
+class MSVCCompiler (CCompiler) :
+    """Concrete class that implements an interface to Microsoft Visual C++,
+       as defined by the CCompiler abstract class."""
+
+    compiler_type = 'msvc'
+
+    # Just set this so CCompiler's constructor doesn't barf.  We currently
+    # don't use the 'set_executables()' bureaucracy provided by CCompiler,
+    # as it really isn't necessary for this sort of single-compiler class.
+    # Would be nice to have a consistent interface with UnixCCompiler,
+    # though, so it's worth thinking about.
+    executables = {}
+
+    # Private class data (need to distinguish C from C++ source for compiler)
+    _c_extensions = ['.c']
+    _cpp_extensions = ['.cc', '.cpp', '.cxx']
+    _rc_extensions = ['.rc']
+    _mc_extensions = ['.mc']
+
+    # Needed for the filename generation methods provided by the
+    # base class, CCompiler.
+    src_extensions = (_c_extensions + _cpp_extensions +
+                      _rc_extensions + _mc_extensions)
+    res_extension = '.res'
+    obj_extension = '.obj'
+    static_lib_extension = '.lib'
+    shared_lib_extension = '.dll'
+    static_lib_format = shared_lib_format = '%s%s'
+    exe_extension = '.exe'
+
+    def __init__ (self, verbose=0, dry_run=0, force=0):
+        CCompiler.__init__ (self, verbose, dry_run, force)
+        self.__version = get_build_version()
+        self.__arch = get_build_architecture()
+        if self.__arch == "Intel":
+            # x86
+            if self.__version >= 7:
+                self.__root = r"Software\Microsoft\VisualStudio"
+                self.__macros = MacroExpander(self.__version)
+            else:
+                self.__root = r"Software\Microsoft\Devstudio"
+            self.__product = "Visual Studio version %s" % self.__version
+        else:
+            # Win64. Assume this was built with the platform SDK
+            self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
+
+        self.initialized = False
+
+    def initialize(self):
+        self.__paths = []
+        if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
+            # Assume that the SDK set up everything alright; don't try to be
+            # smarter
+            self.cc = "cl.exe"
+            self.linker = "link.exe"
+            self.lib = "lib.exe"
+            self.rc = "rc.exe"
+            self.mc = "mc.exe"
+        else:
+            self.__paths = self.get_msvc_paths("path")
+
+            if len (self.__paths) == 0:
+                raise DistutilsPlatformError, \
+                      ("Python was built with %s, "
+                       "and extensions need to be built with the same "
+                       "version of the compiler, but it isn't installed." % self.__product)
+
+            self.cc = self.find_exe("cl.exe")
+            self.linker = self.find_exe("link.exe")
+            self.lib = self.find_exe("lib.exe")
+            self.rc = self.find_exe("rc.exe")   # resource compiler
+            self.mc = self.find_exe("mc.exe")   # message compiler
+            self.set_path_env_var('lib')
+            self.set_path_env_var('include')
+
+        # extend the MSVC path with the current path
+        try:
+            for p in string.split(os.environ['path'], ';'):
+                self.__paths.append(p)
+        except KeyError:
+            pass
+        self.__paths = normalize_and_reduce_paths(self.__paths)
+        os.environ['path'] = string.join(self.__paths, ';')
+
+        self.preprocess_options = None
+        if self.__arch == "Intel":
+            self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
+                                     '/DNDEBUG']
+            self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
+                                          '/Z7', '/D_DEBUG']
+        else:
+            # Win64
+            self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
+                                     '/DNDEBUG']
+            self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
+                                          '/Z7', '/D_DEBUG']
+
+        self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
+        if self.__version >= 7:
+            self.ldflags_shared_debug = [
+                '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
+                ]
+        else:
+            self.ldflags_shared_debug = [
+                '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
+                ]
+        self.ldflags_static = [ '/nologo']
+
+        self.initialized = True
+
+    # -- Worker methods ------------------------------------------------
+
+    def object_filenames (self,
+                          source_filenames,
+                          strip_dir=0,
+                          output_dir=''):
+        # Copied from ccompiler.py, extended to return .res as 'object'-file
+        # for .rc input file
+        if output_dir is None: output_dir = ''
+        obj_names = []
+        for src_name in source_filenames:
+            (base, ext) = os.path.splitext (src_name)
+            base = os.path.splitdrive(base)[1] # Chop off the drive
+            base = base[os.path.isabs(base):]  # If abs, chop off leading /
+            if ext not in self.src_extensions:
+                # Better to raise an exception instead of silently continuing
+                # and later complain about sources and targets having
+                # different lengths
+                raise CompileError ("Don't know how to compile %s" % src_name)
+            if strip_dir:
+                base = os.path.basename (base)
+            if ext in self._rc_extensions:
+                obj_names.append (os.path.join (output_dir,
+                                                base + self.res_extension))
+            elif ext in self._mc_extensions:
+                obj_names.append (os.path.join (output_dir,
+                                                base + self.res_extension))
+            else:
+                obj_names.append (os.path.join (output_dir,
+                                                base + self.obj_extension))
+        return obj_names
+
+    # object_filenames ()
+
+
+    def compile(self, sources,
+                output_dir=None, macros=None, include_dirs=None, debug=0,
+                extra_preargs=None, extra_postargs=None, depends=None):
+
+        if not self.initialized: self.initialize()
+        macros, objects, extra_postargs, pp_opts, build = \
+                self._setup_compile(output_dir, macros, include_dirs, sources,
+                                    depends, extra_postargs)
+
+        compile_opts = extra_preargs or []
+        compile_opts.append ('/c')
+        if debug:
+            compile_opts.extend(self.compile_options_debug)
+        else:
+            compile_opts.extend(self.compile_options)
+
+        for obj in objects:
+            try:
+                src, ext = build[obj]
+            except KeyError:
+                continue
+            if debug:
+                # pass the full pathname to MSVC in debug mode,
+                # this allows the debugger to find the source file
+                # without asking the user to browse for it
+                src = os.path.abspath(src)
+
+            if ext in self._c_extensions:
+                input_opt = "/Tc" + src
+            elif ext in self._cpp_extensions:
+                input_opt = "/Tp" + src
+            elif ext in self._rc_extensions:
+                # compile .RC to .RES file
+                input_opt = src
+                output_opt = "/fo" + obj
+                try:
+                    self.spawn ([self.rc] + pp_opts +
+                                [output_opt] + [input_opt])
+                except DistutilsExecError, msg:
+                    raise CompileError, msg
+                continue
+            elif ext in self._mc_extensions:
+
+                # Compile .MC to .RC file to .RES file.
+                #   * '-h dir' specifies the directory for the
+                #     generated include file
+                #   * '-r dir' specifies the target directory of the
+                #     generated RC file and the binary message resource
+                #     it includes
+                #
+                # For now (since there are no options to change this),
+                # we use the source-directory for the include file and
+                # the build directory for the RC file and message
+                # resources. This works at least for win32all.
+
+                h_dir = os.path.dirname (src)
+                rc_dir = os.path.dirname (obj)
+                try:
+                    # first compile .MC to .RC and .H file
+                    self.spawn ([self.mc] +
+                                ['-h', h_dir, '-r', rc_dir] + [src])
+                    base, _ = os.path.splitext (os.path.basename (src))
+                    rc_file = os.path.join (rc_dir, base + '.rc')
+                    # then compile .RC to .RES file
+                    self.spawn ([self.rc] +
+                                ["/fo" + obj] + [rc_file])
+
+                except DistutilsExecError, msg:
+                    raise CompileError, msg
+                continue
+            else:
+                # how to handle this file?
+                raise CompileError (
+                    "Don't know how to compile %s to %s" % \
+                    (src, obj))
+
+            output_opt = "/Fo" + obj
+            try:
+                self.spawn ([self.cc] + compile_opts + pp_opts +
+                            [input_opt, output_opt] +
+                            extra_postargs)
+            except DistutilsExecError, msg:
+                raise CompileError, msg
+
+        return objects
+
+    # compile ()
+
+
+    def create_static_lib (self,
+                           objects,
+                           output_libname,
+                           output_dir=None,
+                           debug=0,
+                           target_lang=None):
+
+        if not self.initialized: self.initialize()
+        (objects, output_dir) = self._fix_object_args (objects, output_dir)
+        output_filename = \
+            self.library_filename (output_libname, output_dir=output_dir)
+
+        if self._need_link (objects, output_filename):
+            lib_args = objects + ['/OUT:' + output_filename]
+            if debug:
+                pass                    # XXX what goes here?
+            try:
+                self.spawn ([self.lib] + lib_args)
+            except DistutilsExecError, msg:
+                raise LibError, msg
+
+        else:
+            log.debug("skipping %s (up-to-date)", output_filename)
+
+    # create_static_lib ()
+
+    def link (self,
+              target_desc,
+              objects,
+              output_filename,
+              output_dir=None,
+              libraries=None,
+              library_dirs=None,
+              runtime_library_dirs=None,
+              export_symbols=None,
+              debug=0,
+              extra_preargs=None,
+              extra_postargs=None,
+              build_temp=None,
+              target_lang=None):
+
+        if not self.initialized: self.initialize()
+        (objects, output_dir) = self._fix_object_args (objects, output_dir)
+        (libraries, library_dirs, runtime_library_dirs) = \
+            self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
+
+        if runtime_library_dirs:
+            self.warn ("I don't know what to do with 'runtime_library_dirs': "
+                       + str (runtime_library_dirs))
+
+        lib_opts = gen_lib_options (self,
+                                    library_dirs, runtime_library_dirs,
+                                    libraries)
+        if output_dir is not None:
+            output_filename = os.path.join (output_dir, output_filename)
+
+        if self._need_link (objects, output_filename):
+
+            if target_desc == CCompiler.EXECUTABLE:
+                if debug:
+                    ldflags = self.ldflags_shared_debug[1:]
+                else:
+                    ldflags = self.ldflags_shared[1:]
+            else:
+                if debug:
+                    ldflags = self.ldflags_shared_debug
+                else:
+                    ldflags = self.ldflags_shared
+
+            export_opts = []
+            for sym in (export_symbols or []):
+                export_opts.append("/EXPORT:" + sym)
+
+            ld_args = (ldflags + lib_opts + export_opts +
+                       objects + ['/OUT:' + output_filename])
+
+            # The MSVC linker generates .lib and .exp files, which cannot be
+            # suppressed by any linker switches. The .lib files may even be
+            # needed! Make sure they are generated in the temporary build
+            # directory. Since they have different names for debug and release
+            # builds, they can go into the same directory.
+            if export_symbols is not None:
+                (dll_name, dll_ext) = os.path.splitext(
+                    os.path.basename(output_filename))
+                implib_file = os.path.join(
+                    os.path.dirname(objects[0]),
+                    self.library_filename(dll_name))
+                ld_args.append ('/IMPLIB:' + implib_file)
+
+            if extra_preargs:
+                ld_args[:0] = extra_preargs
+            if extra_postargs:
+                ld_args.extend(extra_postargs)
+
+            self.mkpath (os.path.dirname (output_filename))
+            try:
+                self.spawn ([self.linker] + ld_args)
+            except DistutilsExecError, msg:
+                raise LinkError, msg
+
+        else:
+            log.debug("skipping %s (up-to-date)", output_filename)
+
+    # link ()
+
+
+    # -- Miscellaneous methods -----------------------------------------
+    # These are all used by the 'gen_lib_options() function, in
+    # ccompiler.py.
+
+    def library_dir_option (self, dir):
+        return "/LIBPATH:" + dir
+
+    def runtime_library_dir_option (self, dir):
+        raise DistutilsPlatformError, \
+              "don't know how to set runtime library search path for MSVC++"
+
+    def library_option (self, lib):
+        return self.library_filename (lib)
+
+
+    def find_library_file (self, dirs, lib, debug=0):
+        # Prefer a debugging library if found (and requested), but deal
+        # with it if we don't have one.
+        if debug:
+            try_names = [lib + "_d", lib]
+        else:
+            try_names = [lib]
+        for dir in dirs:
+            for name in try_names:
+                libfile = os.path.join(dir, self.library_filename (name))
+                if os.path.exists(libfile):
+                    return libfile
+        else:
+            # Oops, didn't find it in *any* of 'dirs'
+            return None
+
+    # find_library_file ()
+
+    # Helper methods for using the MSVC registry settings
+
+    def find_exe(self, exe):
+        """Return path to an MSVC executable program.
+
+        Tries to find the program in several places: first, one of the
+        MSVC program search paths from the registry; next, the directories
+        in the PATH environment variable.  If any of those work, return an
+        absolute path that is known to exist.  If none of them work, just
+        return the original program name, 'exe'.
+        """
+
+        for p in self.__paths:
+            fn = os.path.join(os.path.abspath(p), exe)
+            if os.path.isfile(fn):
+                return fn
+
+        # didn't find it; try existing path
+        for p in string.split(os.environ['Path'],';'):
+            fn = os.path.join(os.path.abspath(p),exe)
+            if os.path.isfile(fn):
+                return fn
+
+        return exe
+
+    def get_msvc_paths(self, path, platform='x86'):
+        """Get a list of devstudio directories (include, lib or path).
+
+        Return a list of strings.  The list will be empty if unable to
+        access the registry or appropriate registry keys not found.
+        """
+
+        if not _can_read_reg:
+            return []
+
+        path = path + " dirs"
+        if self.__version >= 7:
+            key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
+                   % (self.__root, self.__version))
+        else:
+            key = (r"%s\6.0\Build System\Components\Platforms"
+                   r"\Win32 (%s)\Directories" % (self.__root, platform))
+
+        for base in HKEYS:
+            d = read_values(base, key)
+            if d:
+                if self.__version >= 7:
+                    return string.split(self.__macros.sub(d[path]), ";")
+                else:
+                    return string.split(d[path], ";")
+        # MSVC 6 seems to create the registry entries we need only when
+        # the GUI is run.
+        if self.__version == 6:
+            for base in HKEYS:
+                if read_values(base, r"%s\6.0" % self.__root) is not None:
+                    self.warn("It seems you have Visual Studio 6 installed, "
+                        "but the expected registry settings are not present.\n"
+                        "You must at least run the Visual Studio GUI once "
+                        "so that these entries are created.")
+                    break
+        return []
+
+    def set_path_env_var(self, name):
+        """Set environment variable 'name' to an MSVC path type value.
+
+        This is equivalent to a SET command prior to execution of spawned
+        commands.
+        """
+
+        if name == "lib":
+            p = self.get_msvc_paths("library")
+        else:
+            p = self.get_msvc_paths(name)
+        if p:
+            os.environ[name] = string.join(p, ';')
+
+
+if get_build_version() >= 8.0:
+    log.debug("Importing new compiler from distutils.msvc9compiler")
+    OldMSVCCompiler = MSVCCompiler
+    from distutils.msvc9compiler import MSVCCompiler
+    # get_build_architecture not really relevant now we support cross-compile
+    from distutils.msvc9compiler import MacroExpander
diff --git a/src/main/resources/PythonLibs/distutils/spawn.py b/src/main/resources/PythonLibs/distutils/spawn.py
new file mode 100644
index 0000000000000000000000000000000000000000..5bc6e5ec9f420e8d61bfe7a2dd8b0b8a70c1a7ee
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/spawn.py
@@ -0,0 +1,196 @@
+"""distutils.spawn
+
+Provides the 'spawn()' function, a front-end to various platform-
+specific functions for launching another program in a sub-process.
+Also provides the 'find_executable()' to search the path for a given
+executable name.
+"""
+
+__revision__ = "$Id: spawn.py 73147 2009-06-02 15:58:43Z tarek.ziade $"
+
+import sys
+import os
+
+from distutils.errors import DistutilsPlatformError, DistutilsExecError
+from distutils import log
+
+def spawn(cmd, search_path=1, verbose=0, dry_run=0):
+    """Run another program, specified as a command list 'cmd', in a new process.
+
+    'cmd' is just the argument list for the new process, ie.
+    cmd[0] is the program to run and cmd[1:] are the rest of its arguments.
+    There is no way to run a program with a name different from that of its
+    executable.
+
+    If 'search_path' is true (the default), the system's executable
+    search path will be used to find the program; otherwise, cmd[0]
+    must be the exact path to the executable.  If 'dry_run' is true,
+    the command will not actually be run.
+
+    Raise DistutilsExecError if running the program fails in any way; just
+    return on success.
+    """
+    if os.name == 'posix':
+        _spawn_posix(cmd, search_path, dry_run=dry_run)
+    elif os.name == 'nt':
+        _spawn_nt(cmd, search_path, dry_run=dry_run)
+    elif os.name == 'os2':
+        _spawn_os2(cmd, search_path, dry_run=dry_run)
+    elif os.name == 'java':
+        _spawn_java(cmd, search_path, dry_run=dry_run)
+    else:
+        raise DistutilsPlatformError, \
+              "don't know how to spawn programs on platform '%s'" % os.name
+
+def _nt_quote_args(args):
+    """Quote command-line arguments for DOS/Windows conventions.
+
+    Just wraps every argument which contains blanks in double quotes, and
+    returns a new argument list.
+    """
+    # XXX this doesn't seem very robust to me -- but if the Windows guys
+    # say it'll work, I guess I'll have to accept it.  (What if an arg
+    # contains quotes?  What other magic characters, other than spaces,
+    # have to be escaped?  Is there an escaping mechanism other than
+    # quoting?)
+    for i, arg in enumerate(args):
+        if ' ' in arg:
+            args[i] = '"%s"' % arg
+    return args
+
+def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0):
+    executable = cmd[0]
+    cmd = _nt_quote_args(cmd)
+    if search_path:
+        # either we find one or it stays the same
+        executable = find_executable(executable) or executable
+    log.info(' '.join([executable] + cmd[1:]))
+    if not dry_run:
+        # spawn for NT requires a full path to the .exe
+        try:
+            rc = os.spawnv(os.P_WAIT, executable, cmd)
+        except OSError, exc:
+            # this seems to happen when the command isn't found
+            raise DistutilsExecError, \
+                  "command '%s' failed: %s" % (cmd[0], exc[-1])
+        if rc != 0:
+            # and this reflects the command running but failing
+            raise DistutilsExecError, \
+                  "command '%s' failed with exit status %d" % (cmd[0], rc)
+
+def _spawn_os2(cmd, search_path=1, verbose=0, dry_run=0):
+    executable = cmd[0]
+    if search_path:
+        # either we find one or it stays the same
+        executable = find_executable(executable) or executable
+    log.info(' '.join([executable] + cmd[1:]))
+    if not dry_run:
+        # spawnv for OS/2 EMX requires a full path to the .exe
+        try:
+            rc = os.spawnv(os.P_WAIT, executable, cmd)
+        except OSError, exc:
+            # this seems to happen when the command isn't found
+            raise DistutilsExecError, \
+                  "command '%s' failed: %s" % (cmd[0], exc[-1])
+        if rc != 0:
+            # and this reflects the command running but failing
+            log.debug("command '%s' failed with exit status %d" % (cmd[0], rc))
+            raise DistutilsExecError, \
+                  "command '%s' failed with exit status %d" % (cmd[0], rc)
+
+
+def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0):
+    log.info(' '.join(cmd))
+    if dry_run:
+        return
+    exec_fn = search_path and os.execvp or os.execv
+    pid = os.fork()
+
+    if pid == 0:  # in the child
+        try:
+            exec_fn(cmd[0], cmd)
+        except OSError, e:
+            sys.stderr.write("unable to execute %s: %s\n" %
+                             (cmd[0], e.strerror))
+            os._exit(1)
+
+        sys.stderr.write("unable to execute %s for unknown reasons" % cmd[0])
+        os._exit(1)
+    else:   # in the parent
+        # Loop until the child either exits or is terminated by a signal
+        # (ie. keep waiting if it's merely stopped)
+        while 1:
+            try:
+                pid, status = os.waitpid(pid, 0)
+            except OSError, exc:
+                import errno
+                if exc.errno == errno.EINTR:
+                    continue
+                raise DistutilsExecError, \
+                      "command '%s' failed: %s" % (cmd[0], exc[-1])
+            if os.WIFSIGNALED(status):
+                raise DistutilsExecError, \
+                      "command '%s' terminated by signal %d" % \
+                      (cmd[0], os.WTERMSIG(status))
+
+            elif os.WIFEXITED(status):
+                exit_status = os.WEXITSTATUS(status)
+                if exit_status == 0:
+                    return   # hey, it succeeded!
+                else:
+                    raise DistutilsExecError, \
+                          "command '%s' failed with exit status %d" % \
+                          (cmd[0], exit_status)
+
+            elif os.WIFSTOPPED(status):
+                continue
+
+            else:
+                raise DistutilsExecError, \
+                      "unknown error executing '%s': termination status %d" % \
+                      (cmd[0], status)
+
+def _spawn_java(cmd,
+                search_path=1,
+                verbose=0,
+                dry_run=0):
+    executable = cmd[0]
+    cmd = ' '.join(_nt_quote_args(cmd))
+    log.info(cmd)
+    if not dry_run:
+        try:
+            rc = os.system(cmd) >> 8
+        except OSError, exc:
+            # this seems to happen when the command isn't found
+            raise DistutilsExecError, \
+                  "command '%s' failed: %s" % (executable, exc[-1])
+        if rc != 0:
+            # and this reflects the command running but failing
+            print "command '%s' failed with exit status %d" % (executable, rc)
+            raise DistutilsExecError, \
+                  "command '%s' failed with exit status %d" % (executable, rc)
+
+
+def find_executable(executable, path=None):
+    """Tries to find 'executable' in the directories listed in 'path'.
+
+    A string listing directories separated by 'os.pathsep'; defaults to
+    os.environ['PATH'].  Returns the complete filename or None if not found.
+    """
+    if path is None:
+        path = os.environ['PATH']
+    paths = path.split(os.pathsep)
+    base, ext = os.path.splitext(executable)
+
+    if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'):
+        executable = executable + '.exe'
+
+    if not os.path.isfile(executable):
+        for p in paths:
+            f = os.path.join(p, executable)
+            if os.path.isfile(f):
+                # the file exists, we have a shot at spawn working
+                return f
+        return None
+    else:
+        return executable
diff --git a/src/main/resources/PythonLibs/distutils/sysconfig.py b/src/main/resources/PythonLibs/distutils/sysconfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..c22b50802ff0636cffeebd29dbd7de447122f3a2
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/sysconfig.py
@@ -0,0 +1,622 @@
+"""Provide access to Python's configuration information.  The specific
+configuration variables available depend heavily on the platform and
+configuration.  The values may be retrieved using
+get_config_var(name), and the list of variables is available via
+get_config_vars().keys().  Additional convenience functions are also
+available.
+
+Written by:   Fred L. Drake, Jr.
+Email:        <fdrake@acm.org>
+"""
+
+__revision__ = "$Id: sysconfig.py 83688 2010-08-03 21:18:06Z mark.dickinson $"
+
+import os
+import re
+import string
+import sys
+
+from distutils.errors import DistutilsPlatformError
+
+# These are needed in a couple of spots, so just compute them once.
+PREFIX = os.path.normpath(sys.prefix)
+EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
+
+# Path to the base directory of the project. On Windows the binary may
+# live in project/PCBuild9.  If we're dealing with an x64 Windows build,
+# it'll live in project/PCbuild/amd64.
+project_base = os.path.dirname(os.path.realpath(sys.executable))
+if os.name == "nt" and "pcbuild" in project_base[-8:].lower():
+    project_base = os.path.abspath(os.path.join(project_base, os.path.pardir))
+# PC/VS7.1
+if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower():
+    project_base = os.path.abspath(os.path.join(project_base, os.path.pardir,
+                                                os.path.pardir))
+# PC/AMD64
+if os.name == "nt" and "\\pcbuild\\amd64" in project_base[-14:].lower():
+    project_base = os.path.abspath(os.path.join(project_base, os.path.pardir,
+                                                os.path.pardir))
+
+# python_build: (Boolean) if true, we're either building Python or
+# building an extension with an un-installed Python, so we use
+# different (hard-wired) directories.
+# Setup.local is available for Makefile builds including VPATH builds,
+# Setup.dist is available on Windows
+def _python_build():
+    for fn in ("Setup.dist", "Setup.local"):
+        if os.path.isfile(os.path.join(project_base, "Modules", fn)):
+            return True
+    return False
+python_build = _python_build()
+
+
+def get_python_version():
+    """Return a string containing the major and minor Python version,
+    leaving off the patchlevel.  Sample return values could be '1.5'
+    or '2.2'.
+    """
+    return sys.version[:3]
+
+
+def get_python_inc(plat_specific=0, prefix=None):
+    """Return the directory containing installed Python header files.
+
+    If 'plat_specific' is false (the default), this is the path to the
+    non-platform-specific header files, i.e. Python.h and so on;
+    otherwise, this is the path to platform-specific header files
+    (namely pyconfig.h).
+
+    If 'prefix' is supplied, use it instead of sys.prefix or
+    sys.exec_prefix -- i.e., ignore 'plat_specific'.
+    """
+    if prefix is None:
+        prefix = plat_specific and EXEC_PREFIX or PREFIX
+
+    if os.name == "posix":
+        if python_build:
+            buildir = os.path.dirname(os.path.realpath(sys.executable))
+            if plat_specific:
+                # python.h is located in the buildir
+                inc_dir = buildir
+            else:
+                # the source dir is relative to the buildir
+                srcdir = os.path.abspath(os.path.join(buildir,
+                                         get_config_var('srcdir')))
+                # Include is located in the srcdir
+                inc_dir = os.path.join(srcdir, "Include")
+            return inc_dir
+        return os.path.join(prefix, "include", "python" + get_python_version())
+    elif os.name == "nt":
+        return os.path.join(prefix, "include")
+    elif os.name == "mac":
+        if plat_specific:
+            return os.path.join(prefix, "Mac", "Include")
+        else:
+            return os.path.join(prefix, "Include")
+    elif os.name == "os2" or os.name == "java":
+        return os.path.join(prefix, "Include")
+    else:
+        raise DistutilsPlatformError(
+            "I don't know where Python installs its C header files "
+            "on platform '%s'" % os.name)
+
+
+def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
+    """Return the directory containing the Python library (standard or
+    site additions).
+
+    If 'plat_specific' is true, return the directory containing
+    platform-specific modules, i.e. any module from a non-pure-Python
+    module distribution; otherwise, return the platform-shared library
+    directory.  If 'standard_lib' is true, return the directory
+    containing standard Python library modules; otherwise, return the
+    directory for site-specific modules.
+
+    If 'prefix' is supplied, use it instead of sys.prefix or
+    sys.exec_prefix -- i.e., ignore 'plat_specific'.
+    """
+    if prefix is None:
+        prefix = plat_specific and EXEC_PREFIX or PREFIX
+
+    if os.name == "posix":
+        libpython = os.path.join(prefix,
+                                 "lib", "python" + get_python_version())
+        if standard_lib:
+            return libpython
+        else:
+            return os.path.join(libpython, "site-packages")
+
+    elif os.name == "nt":
+        if standard_lib:
+            return os.path.join(prefix, "Lib")
+        else:
+            if get_python_version() < "2.2":
+                return prefix
+            else:
+                return os.path.join(prefix, "Lib", "site-packages")
+
+    elif os.name == "mac":
+        if plat_specific:
+            if standard_lib:
+                return os.path.join(prefix, "Lib", "lib-dynload")
+            else:
+                return os.path.join(prefix, "Lib", "site-packages")
+        else:
+            if standard_lib:
+                return os.path.join(prefix, "Lib")
+            else:
+                return os.path.join(prefix, "Lib", "site-packages")
+
+    elif os.name == "os2" or os.name == "java":
+        if standard_lib:
+            return os.path.join(prefix, "Lib")
+        else:
+            return os.path.join(prefix, "Lib", "site-packages")
+
+    else:
+        raise DistutilsPlatformError(
+            "I don't know where Python installs its library "
+            "on platform '%s'" % os.name)
+
+
+def customize_compiler(compiler):
+    """Do any platform-specific customization of a CCompiler instance.
+
+    Mainly needed on Unix, so we can plug in the information that
+    varies across Unices and is stored in Python's Makefile.
+    """
+    if compiler.compiler_type == "unix":
+        (cc, cxx, opt, cflags, ccshared, ldshared, so_ext) = \
+            get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
+                            'CCSHARED', 'LDSHARED', 'SO')
+
+        if 'CC' in os.environ:
+            cc = os.environ['CC']
+        if 'CXX' in os.environ:
+            cxx = os.environ['CXX']
+        if 'LDSHARED' in os.environ:
+            ldshared = os.environ['LDSHARED']
+        if 'CPP' in os.environ:
+            cpp = os.environ['CPP']
+        else:
+            cpp = cc + " -E"           # not always
+        if 'LDFLAGS' in os.environ:
+            ldshared = ldshared + ' ' + os.environ['LDFLAGS']
+        if 'CFLAGS' in os.environ:
+            cflags = opt + ' ' + os.environ['CFLAGS']
+            ldshared = ldshared + ' ' + os.environ['CFLAGS']
+        if 'CPPFLAGS' in os.environ:
+            cpp = cpp + ' ' + os.environ['CPPFLAGS']
+            cflags = cflags + ' ' + os.environ['CPPFLAGS']
+            ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
+
+        cc_cmd = cc + ' ' + cflags
+        compiler.set_executables(
+            preprocessor=cpp,
+            compiler=cc_cmd,
+            compiler_so=cc_cmd + ' ' + ccshared,
+            compiler_cxx=cxx,
+            linker_so=ldshared,
+            linker_exe=cc)
+
+        compiler.shared_lib_extension = so_ext
+
+
+def get_config_h_filename():
+    """Return full pathname of installed pyconfig.h file."""
+    if python_build:
+        if os.name == "nt":
+            inc_dir = os.path.join(project_base, "PC")
+        else:
+            inc_dir = project_base
+    else:
+        inc_dir = get_python_inc(plat_specific=1)
+    if get_python_version() < '2.2':
+        config_h = 'config.h'
+    else:
+        # The name of the config.h file changed in 2.2
+        config_h = 'pyconfig.h'
+    return os.path.join(inc_dir, config_h)
+
+
+def get_makefile_filename():
+    """Return full pathname of installed Makefile from the Python build."""
+    if python_build:
+        return os.path.join(os.path.dirname(os.path.realpath(sys.executable)),
+                            "Makefile")
+    lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
+    return os.path.join(lib_dir, "config", "Makefile")
+
+
+def parse_config_h(fp, g=None):
+    """Parse a config.h-style file.
+
+    A dictionary containing name/value pairs is returned.  If an
+    optional dictionary is passed in as the second argument, it is
+    used instead of a new dictionary.
+    """
+    if g is None:
+        g = {}
+    define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
+    undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
+    #
+    while 1:
+        line = fp.readline()
+        if not line:
+            break
+        m = define_rx.match(line)
+        if m:
+            n, v = m.group(1, 2)
+            try: v = int(v)
+            except ValueError: pass
+            g[n] = v
+        else:
+            m = undef_rx.match(line)
+            if m:
+                g[m.group(1)] = 0
+    return g
+
+
+# Regexes needed for parsing Makefile (and similar syntaxes,
+# like old-style Setup files).
+_variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
+_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
+_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
+
+def parse_makefile(fn, g=None):
+    """Parse a Makefile-style file.
+
+    A dictionary containing name/value pairs is returned.  If an
+    optional dictionary is passed in as the second argument, it is
+    used instead of a new dictionary.
+    """
+    from distutils.text_file import TextFile
+    fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1)
+
+    if g is None:
+        g = {}
+    done = {}
+    notdone = {}
+
+    while 1:
+        line = fp.readline()
+        if line is None:  # eof
+            break
+        m = _variable_rx.match(line)
+        if m:
+            n, v = m.group(1, 2)
+            v = v.strip()
+            # `$$' is a literal `$' in make
+            tmpv = v.replace('$$', '')
+
+            if "$" in tmpv:
+                notdone[n] = v
+            else:
+                try:
+                    v = int(v)
+                except ValueError:
+                    # insert literal `$'
+                    done[n] = v.replace('$$', '$')
+                else:
+                    done[n] = v
+
+    # do variable interpolation here
+    while notdone:
+        for name in notdone.keys():
+            value = notdone[name]
+            m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
+            if m:
+                n = m.group(1)
+                found = True
+                if n in done:
+                    item = str(done[n])
+                elif n in notdone:
+                    # get it on a subsequent round
+                    found = False
+                elif n in os.environ:
+                    # do it like make: fall back to environment
+                    item = os.environ[n]
+                else:
+                    done[n] = item = ""
+                if found:
+                    after = value[m.end():]
+                    value = value[:m.start()] + item + after
+                    if "$" in after:
+                        notdone[name] = value
+                    else:
+                        try: value = int(value)
+                        except ValueError:
+                            done[name] = value.strip()
+                        else:
+                            done[name] = value
+                        del notdone[name]
+            else:
+                # bogus variable reference; just drop it since we can't deal
+                del notdone[name]
+
+    fp.close()
+
+    # save the results in the global dictionary
+    g.update(done)
+    return g
+
+
+def expand_makefile_vars(s, vars):
+    """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
+    'string' according to 'vars' (a dictionary mapping variable names to
+    values).  Variables not present in 'vars' are silently expanded to the
+    empty string.  The variable values in 'vars' should not contain further
+    variable expansions; if 'vars' is the output of 'parse_makefile()',
+    you're fine.  Returns a variable-expanded version of 's'.
+    """
+
+    # This algorithm does multiple expansion, so if vars['foo'] contains
+    # "${bar}", it will expand ${foo} to ${bar}, and then expand
+    # ${bar}... and so forth.  This is fine as long as 'vars' comes from
+    # 'parse_makefile()', which takes care of such expansions eagerly,
+    # according to make's variable expansion semantics.
+
+    while 1:
+        m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
+        if m:
+            (beg, end) = m.span()
+            s = s[0:beg] + vars.get(m.group(1)) + s[end:]
+        else:
+            break
+    return s
+
+
+_config_vars = None
+
+def _init_posix():
+    """Initialize the module as appropriate for POSIX systems."""
+    g = {}
+    # load the installed Makefile:
+    try:
+        filename = get_makefile_filename()
+        parse_makefile(filename, g)
+    except IOError, msg:
+        my_msg = "invalid Python installation: unable to open %s" % filename
+        if hasattr(msg, "strerror"):
+            my_msg = my_msg + " (%s)" % msg.strerror
+
+        raise DistutilsPlatformError(my_msg)
+
+    # load the installed pyconfig.h:
+    try:
+        filename = get_config_h_filename()
+        parse_config_h(file(filename), g)
+    except IOError, msg:
+        my_msg = "invalid Python installation: unable to open %s" % filename
+        if hasattr(msg, "strerror"):
+            my_msg = my_msg + " (%s)" % msg.strerror
+
+        raise DistutilsPlatformError(my_msg)
+
+    # On MacOSX we need to check the setting of the environment variable
+    # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so
+    # it needs to be compatible.
+    # If it isn't set we set it to the configure-time value
+    if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in g:
+        cfg_target = g['MACOSX_DEPLOYMENT_TARGET']
+        cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '')
+        if cur_target == '':
+            cur_target = cfg_target
+            os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target)
+        elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')):
+            my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure'
+                % (cur_target, cfg_target))
+            raise DistutilsPlatformError(my_msg)
+
+    # On AIX, there are wrong paths to the linker scripts in the Makefile
+    # -- these paths are relative to the Python source, but when installed
+    # the scripts are in another directory.
+    if python_build:
+        g['LDSHARED'] = g['BLDSHARED']
+
+    elif get_python_version() < '2.1':
+        # The following two branches are for 1.5.2 compatibility.
+        if sys.platform == 'aix4':          # what about AIX 3.x ?
+            # Linker script is in the config directory, not in Modules as the
+            # Makefile says.
+            python_lib = get_python_lib(standard_lib=1)
+            ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix')
+            python_exp = os.path.join(python_lib, 'config', 'python.exp')
+
+            g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp)
+
+        elif sys.platform == 'beos':
+            # Linker script is in the config directory.  In the Makefile it is
+            # relative to the srcdir, which after installation no longer makes
+            # sense.
+            python_lib = get_python_lib(standard_lib=1)
+            linkerscript_path = string.split(g['LDSHARED'])[0]
+            linkerscript_name = os.path.basename(linkerscript_path)
+            linkerscript = os.path.join(python_lib, 'config',
+                                        linkerscript_name)
+
+            # XXX this isn't the right place to do this: adding the Python
+            # library to the link, if needed, should be in the "build_ext"
+            # command.  (It's also needed for non-MS compilers on Windows, and
+            # it's taken care of for them by the 'build_ext.get_libraries()'
+            # method.)
+            g['LDSHARED'] = ("%s -L%s/lib -lpython%s" %
+                             (linkerscript, PREFIX, get_python_version()))
+
+    global _config_vars
+    _config_vars = g
+
+
+def _init_nt():
+    """Initialize the module as appropriate for NT"""
+    g = {}
+    # set basic install directories
+    g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
+    g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
+
+    # XXX hmmm.. a normal install puts include files here
+    g['INCLUDEPY'] = get_python_inc(plat_specific=0)
+
+    g['SO'] = '.pyd'
+    g['EXE'] = ".exe"
+    g['VERSION'] = get_python_version().replace(".", "")
+    g['BINDIR'] = os.path.dirname(os.path.realpath(sys.executable))
+
+    global _config_vars
+    _config_vars = g
+
+
+def _init_mac():
+    """Initialize the module as appropriate for Macintosh systems"""
+    g = {}
+    # set basic install directories
+    g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
+    g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
+
+    # XXX hmmm.. a normal install puts include files here
+    g['INCLUDEPY'] = get_python_inc(plat_specific=0)
+
+    import MacOS
+    if not hasattr(MacOS, 'runtimemodel'):
+        g['SO'] = '.ppc.slb'
+    else:
+        g['SO'] = '.%s.slb' % MacOS.runtimemodel
+
+    # XXX are these used anywhere?
+    g['install_lib'] = os.path.join(EXEC_PREFIX, "Lib")
+    g['install_platlib'] = os.path.join(EXEC_PREFIX, "Mac", "Lib")
+
+    # These are used by the extension module build
+    g['srcdir'] = ':'
+    global _config_vars
+    _config_vars = g
+
+
+def _init_os2():
+    """Initialize the module as appropriate for OS/2"""
+    g = {}
+    # set basic install directories
+    g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
+    g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
+
+    # XXX hmmm.. a normal install puts include files here
+    g['INCLUDEPY'] = get_python_inc(plat_specific=0)
+
+    g['SO'] = '.pyd'
+    g['EXE'] = ".exe"
+
+    global _config_vars
+    _config_vars = g
+
+
+def _init_jython():
+    """Initialize the module as appropriate for Jython"""
+    # Stub out some values that build_ext expects; they don't matter
+    # anyway
+    _init_os2()
+
+
+def get_config_vars(*args):
+    """With no arguments, return a dictionary of all configuration
+    variables relevant for the current platform.  Generally this includes
+    everything needed to build extensions and install both pure modules and
+    extensions.  On Unix, this means every variable defined in Python's
+    installed Makefile; on Windows and Mac OS it's a much smaller set.
+
+    With arguments, return a list of values that result from looking up
+    each argument in the configuration variable dictionary.
+    """
+    global _config_vars
+    if _config_vars is None:
+        if sys.platform.startswith('java'):
+            # Jython might pose as a different os.name, but we always
+            # want _init_jython regardless
+            func = _init_jython
+        else:
+            func = globals().get("_init_" + os.name)
+        if func:
+            func()
+        else:
+            _config_vars = {}
+
+        # Normalized versions of prefix and exec_prefix are handy to have;
+        # in fact, these are the standard versions used most places in the
+        # Distutils.
+        _config_vars['prefix'] = PREFIX
+        _config_vars['exec_prefix'] = EXEC_PREFIX
+
+        if sys.platform == 'darwin':
+            kernel_version = os.uname()[2] # Kernel version (8.4.3)
+            major_version = int(kernel_version.split('.')[0])
+
+            if major_version < 8:
+                # On Mac OS X before 10.4, check if -arch and -isysroot
+                # are in CFLAGS or LDFLAGS and remove them if they are.
+                # This is needed when building extensions on a 10.3 system
+                # using a universal build of python.
+                for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
+                        # a number of derived variables. These need to be
+                        # patched up as well.
+                        'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
+                    flags = _config_vars[key]
+                    flags = re.sub('-arch\s+\w+\s', ' ', flags)
+                    flags = re.sub('-isysroot [^ \t]*', ' ', flags)
+                    _config_vars[key] = flags
+
+            else:
+
+                # Allow the user to override the architecture flags using
+                # an environment variable.
+                # NOTE: This name was introduced by Apple in OSX 10.5 and
+                # is used by several scripting languages distributed with
+                # that OS release.
+
+                if 'ARCHFLAGS' in os.environ:
+                    arch = os.environ['ARCHFLAGS']
+                    for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
+                        # a number of derived variables. These need to be
+                        # patched up as well.
+                        'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
+
+                        flags = _config_vars[key]
+                        flags = re.sub('-arch\s+\w+\s', ' ', flags)
+                        flags = flags + ' ' + arch
+                        _config_vars[key] = flags
+
+                # If we're on OSX 10.5 or later and the user tries to
+                # compiles an extension using an SDK that is not present
+                # on the current machine it is better to not use an SDK
+                # than to fail.
+                #
+                # The major usecase for this is users using a Python.org
+                # binary installer  on OSX 10.6: that installer uses
+                # the 10.4u SDK, but that SDK is not installed by default
+                # when you install Xcode.
+                #
+                m = re.search('-isysroot\s+(\S+)', _config_vars['CFLAGS'])
+                if m is not None:
+                    sdk = m.group(1)
+                    if not os.path.exists(sdk):
+                        for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
+                             # a number of derived variables. These need to be
+                             # patched up as well.
+                            'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
+
+                            flags = _config_vars[key]
+                            flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
+                            _config_vars[key] = flags
+
+    if args:
+        vals = []
+        for name in args:
+            vals.append(_config_vars.get(name))
+        return vals
+    else:
+        return _config_vars
+
+def get_config_var(name):
+    """Return the value of a single variable using the dictionary
+    returned by 'get_config_vars()'.  Equivalent to
+    get_config_vars().get(name)
+    """
+    return get_config_vars().get(name)
diff --git a/src/main/resources/PythonLibs/distutils/text_file.py b/src/main/resources/PythonLibs/distutils/text_file.py
new file mode 100644
index 0000000000000000000000000000000000000000..09a798b1902d773ea98765f3dd58dba3ca64b878
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/text_file.py
@@ -0,0 +1,304 @@
+"""text_file
+
+provides the TextFile class, which gives an interface to text files
+that (optionally) takes care of stripping comments, ignoring blank
+lines, and joining lines with backslashes."""
+
+__revision__ = "$Id$"
+
+import sys
+
+
+class TextFile:
+
+    """Provides a file-like object that takes care of all the things you
+       commonly want to do when processing a text file that has some
+       line-by-line syntax: strip comments (as long as "#" is your
+       comment character), skip blank lines, join adjacent lines by
+       escaping the newline (ie. backslash at end of line), strip
+       leading and/or trailing whitespace.  All of these are optional
+       and independently controllable.
+
+       Provides a 'warn()' method so you can generate warning messages that
+       report physical line number, even if the logical line in question
+       spans multiple physical lines.  Also provides 'unreadline()' for
+       implementing line-at-a-time lookahead.
+
+       Constructor is called as:
+
+           TextFile (filename=None, file=None, **options)
+
+       It bombs (RuntimeError) if both 'filename' and 'file' are None;
+       'filename' should be a string, and 'file' a file object (or
+       something that provides 'readline()' and 'close()' methods).  It is
+       recommended that you supply at least 'filename', so that TextFile
+       can include it in warning messages.  If 'file' is not supplied,
+       TextFile creates its own using the 'open()' builtin.
+
+       The options are all boolean, and affect the value returned by
+       'readline()':
+         strip_comments [default: true]
+           strip from "#" to end-of-line, as well as any whitespace
+           leading up to the "#" -- unless it is escaped by a backslash
+         lstrip_ws [default: false]
+           strip leading whitespace from each line before returning it
+         rstrip_ws [default: true]
+           strip trailing whitespace (including line terminator!) from
+           each line before returning it
+         skip_blanks [default: true}
+           skip lines that are empty *after* stripping comments and
+           whitespace.  (If both lstrip_ws and rstrip_ws are false,
+           then some lines may consist of solely whitespace: these will
+           *not* be skipped, even if 'skip_blanks' is true.)
+         join_lines [default: false]
+           if a backslash is the last non-newline character on a line
+           after stripping comments and whitespace, join the following line
+           to it to form one "logical line"; if N consecutive lines end
+           with a backslash, then N+1 physical lines will be joined to
+           form one logical line.
+         collapse_join [default: false]
+           strip leading whitespace from lines that are joined to their
+           predecessor; only matters if (join_lines and not lstrip_ws)
+
+       Note that since 'rstrip_ws' can strip the trailing newline, the
+       semantics of 'readline()' must differ from those of the builtin file
+       object's 'readline()' method!  In particular, 'readline()' returns
+       None for end-of-file: an empty string might just be a blank line (or
+       an all-whitespace line), if 'rstrip_ws' is true but 'skip_blanks' is
+       not."""
+
+    default_options = { 'strip_comments': 1,
+                        'skip_blanks':    1,
+                        'lstrip_ws':      0,
+                        'rstrip_ws':      1,
+                        'join_lines':     0,
+                        'collapse_join':  0,
+                      }
+
+    def __init__ (self, filename=None, file=None, **options):
+        """Construct a new TextFile object.  At least one of 'filename'
+           (a string) and 'file' (a file-like object) must be supplied.
+           They keyword argument options are described above and affect
+           the values returned by 'readline()'."""
+
+        if filename is None and file is None:
+            raise RuntimeError, \
+                  "you must supply either or both of 'filename' and 'file'"
+
+        # set values for all options -- either from client option hash
+        # or fallback to default_options
+        for opt in self.default_options.keys():
+            if opt in options:
+                setattr (self, opt, options[opt])
+
+            else:
+                setattr (self, opt, self.default_options[opt])
+
+        # sanity check client option hash
+        for opt in options.keys():
+            if opt not in self.default_options:
+                raise KeyError, "invalid TextFile option '%s'" % opt
+
+        if file is None:
+            self.open (filename)
+        else:
+            self.filename = filename
+            self.file = file
+            self.current_line = 0       # assuming that file is at BOF!
+
+        # 'linebuf' is a stack of lines that will be emptied before we
+        # actually read from the file; it's only populated by an
+        # 'unreadline()' operation
+        self.linebuf = []
+
+
+    def open (self, filename):
+        """Open a new file named 'filename'.  This overrides both the
+           'filename' and 'file' arguments to the constructor."""
+
+        self.filename = filename
+        self.file = open (self.filename, 'r')
+        self.current_line = 0
+
+
+    def close (self):
+        """Close the current file and forget everything we know about it
+           (filename, current line number)."""
+
+        self.file.close ()
+        self.file = None
+        self.filename = None
+        self.current_line = None
+
+
+    def gen_error (self, msg, line=None):
+        outmsg = []
+        if line is None:
+            line = self.current_line
+        outmsg.append(self.filename + ", ")
+        if isinstance(line, (list, tuple)):
+            outmsg.append("lines %d-%d: " % tuple (line))
+        else:
+            outmsg.append("line %d: " % line)
+        outmsg.append(str(msg))
+        return ''.join(outmsg)
+
+
+    def error (self, msg, line=None):
+        raise ValueError, "error: " + self.gen_error(msg, line)
+
+    def warn (self, msg, line=None):
+        """Print (to stderr) a warning message tied to the current logical
+           line in the current file.  If the current logical line in the
+           file spans multiple physical lines, the warning refers to the
+           whole range, eg. "lines 3-5".  If 'line' supplied, it overrides
+           the current line number; it may be a list or tuple to indicate a
+           range of physical lines, or an integer for a single physical
+           line."""
+        sys.stderr.write("warning: " + self.gen_error(msg, line) + "\n")
+
+
+    def readline (self):
+        """Read and return a single logical line from the current file (or
+           from an internal buffer if lines have previously been "unread"
+           with 'unreadline()').  If the 'join_lines' option is true, this
+           may involve reading multiple physical lines concatenated into a
+           single string.  Updates the current line number, so calling
+           'warn()' after 'readline()' emits a warning about the physical
+           line(s) just read.  Returns None on end-of-file, since the empty
+           string can occur if 'rstrip_ws' is true but 'strip_blanks' is
+           not."""
+
+        # If any "unread" lines waiting in 'linebuf', return the top
+        # one.  (We don't actually buffer read-ahead data -- lines only
+        # get put in 'linebuf' if the client explicitly does an
+        # 'unreadline()'.
+        if self.linebuf:
+            line = self.linebuf[-1]
+            del self.linebuf[-1]
+            return line
+
+        buildup_line = ''
+
+        while 1:
+            # read the line, make it None if EOF
+            line = self.file.readline()
+            if line == '': line = None
+
+            if self.strip_comments and line:
+
+                # Look for the first "#" in the line.  If none, never
+                # mind.  If we find one and it's the first character, or
+                # is not preceded by "\", then it starts a comment --
+                # strip the comment, strip whitespace before it, and
+                # carry on.  Otherwise, it's just an escaped "#", so
+                # unescape it (and any other escaped "#"'s that might be
+                # lurking in there) and otherwise leave the line alone.
+
+                pos = line.find("#")
+                if pos == -1:           # no "#" -- no comments
+                    pass
+
+                # It's definitely a comment -- either "#" is the first
+                # character, or it's elsewhere and unescaped.
+                elif pos == 0 or line[pos-1] != "\\":
+                    # Have to preserve the trailing newline, because it's
+                    # the job of a later step (rstrip_ws) to remove it --
+                    # and if rstrip_ws is false, we'd better preserve it!
+                    # (NB. this means that if the final line is all comment
+                    # and has no trailing newline, we will think that it's
+                    # EOF; I think that's OK.)
+                    eol = (line[-1] == '\n') and '\n' or ''
+                    line = line[0:pos] + eol
+
+                    # If all that's left is whitespace, then skip line
+                    # *now*, before we try to join it to 'buildup_line' --
+                    # that way constructs like
+                    #   hello \\
+                    #   # comment that should be ignored
+                    #   there
+                    # result in "hello there".
+                    if line.strip() == "":
+                        continue
+
+                else:                   # it's an escaped "#"
+                    line = line.replace("\\#", "#")
+
+
+            # did previous line end with a backslash? then accumulate
+            if self.join_lines and buildup_line:
+                # oops: end of file
+                if line is None:
+                    self.warn ("continuation line immediately precedes "
+                               "end-of-file")
+                    return buildup_line
+
+                if self.collapse_join:
+                    line = line.lstrip()
+                line = buildup_line + line
+
+                # careful: pay attention to line number when incrementing it
+                if isinstance(self.current_line, list):
+                    self.current_line[1] = self.current_line[1] + 1
+                else:
+                    self.current_line = [self.current_line,
+                                         self.current_line+1]
+            # just an ordinary line, read it as usual
+            else:
+                if line is None:        # eof
+                    return None
+
+                # still have to be careful about incrementing the line number!
+                if isinstance(self.current_line, list):
+                    self.current_line = self.current_line[1] + 1
+                else:
+                    self.current_line = self.current_line + 1
+
+
+            # strip whitespace however the client wants (leading and
+            # trailing, or one or the other, or neither)
+            if self.lstrip_ws and self.rstrip_ws:
+                line = line.strip()
+            elif self.lstrip_ws:
+                line = line.lstrip()
+            elif self.rstrip_ws:
+                line = line.rstrip()
+
+            # blank line (whether we rstrip'ed or not)? skip to next line
+            # if appropriate
+            if (line == '' or line == '\n') and self.skip_blanks:
+                continue
+
+            if self.join_lines:
+                if line[-1] == '\\':
+                    buildup_line = line[:-1]
+                    continue
+
+                if line[-2:] == '\\\n':
+                    buildup_line = line[0:-2] + '\n'
+                    continue
+
+            # well, I guess there's some actual content there: return it
+            return line
+
+    # readline ()
+
+
+    def readlines (self):
+        """Read and return the list of all logical lines remaining in the
+           current file."""
+
+        lines = []
+        while 1:
+            line = self.readline()
+            if line is None:
+                return lines
+            lines.append (line)
+
+
+    def unreadline (self, line):
+        """Push 'line' (a string) onto an internal buffer that will be
+           checked by future 'readline()' calls.  Handy for implementing
+           a parser with line-at-a-time lookahead."""
+
+        self.linebuf.append (line)
diff --git a/src/main/resources/PythonLibs/distutils/unixccompiler.py b/src/main/resources/PythonLibs/distutils/unixccompiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..2aa1cb1d27795bb8adc16e082556f5bce0bd716f
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/unixccompiler.py
@@ -0,0 +1,288 @@
+"""distutils.unixccompiler
+
+Contains the UnixCCompiler class, a subclass of CCompiler that handles
+the "typical" Unix-style command-line C compiler:
+  * macros defined with -Dname[=value]
+  * macros undefined with -Uname
+  * include search directories specified with -Idir
+  * libraries specified with -lllib
+  * library search directories specified with -Ldir
+  * compile handled by 'cc' (or similar) executable with -c option:
+    compiles .c to .o
+  * link static library handled by 'ar' command (possibly with 'ranlib')
+  * link shared library handled by 'cc -shared'
+"""
+
+__revision__ = "$Id$"
+
+import os, sys, re
+from types import StringType, NoneType
+
+from distutils import sysconfig
+from distutils.dep_util import newer
+from distutils.ccompiler import \
+     CCompiler, gen_preprocess_options, gen_lib_options
+from distutils.errors import \
+     DistutilsExecError, CompileError, LibError, LinkError
+from distutils import log
+
+if sys.platform == 'darwin':
+    import _osx_support
+
+# XXX Things not currently handled:
+#   * optimization/debug/warning flags; we just use whatever's in Python's
+#     Makefile and live with it.  Is this adequate?  If not, we might
+#     have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
+#     SunCCompiler, and I suspect down that road lies madness.
+#   * even if we don't know a warning flag from an optimization flag,
+#     we need some way for outsiders to feed preprocessor/compiler/linker
+#     flags in to us -- eg. a sysadmin might want to mandate certain flags
+#     via a site config file, or a user might want to set something for
+#     compiling this module distribution only via the setup.py command
+#     line, whatever.  As long as these options come from something on the
+#     current system, they can be as system-dependent as they like, and we
+#     should just happily stuff them into the preprocessor/compiler/linker
+#     options and carry on.
+
+
+class UnixCCompiler(CCompiler):
+
+    compiler_type = 'unix'
+
+    # These are used by CCompiler in two places: the constructor sets
+    # instance attributes 'preprocessor', 'compiler', etc. from them, and
+    # 'set_executable()' allows any of these to be set.  The defaults here
+    # are pretty generic; they will probably have to be set by an outsider
+    # (eg. using information discovered by the sysconfig about building
+    # Python extensions).
+    executables = {'preprocessor' : None,
+                   'compiler'     : ["cc"],
+                   'compiler_so'  : ["cc"],
+                   'compiler_cxx' : ["cc"],
+                   'linker_so'    : ["cc", "-shared"],
+                   'linker_exe'   : ["cc"],
+                   'archiver'     : ["ar", "-cr"],
+                   'ranlib'       : None,
+                  }
+
+    if sys.platform[:6] == "darwin":
+        executables['ranlib'] = ["ranlib"]
+
+    # Needed for the filename generation methods provided by the base
+    # class, CCompiler.  NB. whoever instantiates/uses a particular
+    # UnixCCompiler instance should set 'shared_lib_ext' -- we set a
+    # reasonable common default here, but it's not necessarily used on all
+    # Unices!
+
+    src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"]
+    obj_extension = ".o"
+    static_lib_extension = ".a"
+    shared_lib_extension = ".so"
+    dylib_lib_extension = ".dylib"
+    static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
+    if sys.platform == "cygwin":
+        exe_extension = ".exe"
+
+    def preprocess(self, source,
+                   output_file=None, macros=None, include_dirs=None,
+                   extra_preargs=None, extra_postargs=None):
+        ignore, macros, include_dirs = \
+            self._fix_compile_args(None, macros, include_dirs)
+        pp_opts = gen_preprocess_options(macros, include_dirs)
+        pp_args = self.preprocessor + pp_opts
+        if output_file:
+            pp_args.extend(['-o', output_file])
+        if extra_preargs:
+            pp_args[:0] = extra_preargs
+        if extra_postargs:
+            pp_args.extend(extra_postargs)
+        pp_args.append(source)
+
+        # We need to preprocess: either we're being forced to, or we're
+        # generating output to stdout, or there's a target output file and
+        # the source file is newer than the target (or the target doesn't
+        # exist).
+        if self.force or output_file is None or newer(source, output_file):
+            if output_file:
+                self.mkpath(os.path.dirname(output_file))
+            try:
+                self.spawn(pp_args)
+            except DistutilsExecError, msg:
+                raise CompileError, msg
+
+    def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+        compiler_so = self.compiler_so
+        if sys.platform == 'darwin':
+            compiler_so = _osx_support.compiler_fixup(compiler_so,
+                                                    cc_args + extra_postargs)
+        try:
+            self.spawn(compiler_so + cc_args + [src, '-o', obj] +
+                       extra_postargs)
+        except DistutilsExecError, msg:
+            raise CompileError, msg
+
+    def create_static_lib(self, objects, output_libname,
+                          output_dir=None, debug=0, target_lang=None):
+        objects, output_dir = self._fix_object_args(objects, output_dir)
+
+        output_filename = \
+            self.library_filename(output_libname, output_dir=output_dir)
+
+        if self._need_link(objects, output_filename):
+            self.mkpath(os.path.dirname(output_filename))
+            self.spawn(self.archiver +
+                       [output_filename] +
+                       objects + self.objects)
+
+            # Not many Unices required ranlib anymore -- SunOS 4.x is, I
+            # think the only major Unix that does.  Maybe we need some
+            # platform intelligence here to skip ranlib if it's not
+            # needed -- or maybe Python's configure script took care of
+            # it for us, hence the check for leading colon.
+            if self.ranlib:
+                try:
+                    self.spawn(self.ranlib + [output_filename])
+                except DistutilsExecError, msg:
+                    raise LibError, msg
+        else:
+            log.debug("skipping %s (up-to-date)", output_filename)
+
+    def link(self, target_desc, objects,
+             output_filename, output_dir=None, libraries=None,
+             library_dirs=None, runtime_library_dirs=None,
+             export_symbols=None, debug=0, extra_preargs=None,
+             extra_postargs=None, build_temp=None, target_lang=None):
+        objects, output_dir = self._fix_object_args(objects, output_dir)
+        libraries, library_dirs, runtime_library_dirs = \
+            self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
+
+        lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
+                                   libraries)
+        if type(output_dir) not in (StringType, NoneType):
+            raise TypeError, "'output_dir' must be a string or None"
+        if output_dir is not None:
+            output_filename = os.path.join(output_dir, output_filename)
+
+        if self._need_link(objects, output_filename):
+            ld_args = (objects + self.objects +
+                       lib_opts + ['-o', output_filename])
+            if debug:
+                ld_args[:0] = ['-g']
+            if extra_preargs:
+                ld_args[:0] = extra_preargs
+            if extra_postargs:
+                ld_args.extend(extra_postargs)
+            self.mkpath(os.path.dirname(output_filename))
+            try:
+                if target_desc == CCompiler.EXECUTABLE:
+                    linker = self.linker_exe[:]
+                else:
+                    linker = self.linker_so[:]
+                if target_lang == "c++" and self.compiler_cxx:
+                    # skip over environment variable settings if /usr/bin/env
+                    # is used to set up the linker's environment.
+                    # This is needed on OSX. Note: this assumes that the
+                    # normal and C++ compiler have the same environment
+                    # settings.
+                    i = 0
+                    if os.path.basename(linker[0]) == "env":
+                        i = 1
+                        while '=' in linker[i]:
+                            i = i + 1
+
+                    linker[i] = self.compiler_cxx[i]
+
+                if sys.platform == 'darwin':
+                    linker = _osx_support.compiler_fixup(linker, ld_args)
+
+                self.spawn(linker + ld_args)
+            except DistutilsExecError, msg:
+                raise LinkError, msg
+        else:
+            log.debug("skipping %s (up-to-date)", output_filename)
+
+    # -- Miscellaneous methods -----------------------------------------
+    # These are all used by the 'gen_lib_options() function, in
+    # ccompiler.py.
+
+    def library_dir_option(self, dir):
+        return "-L" + dir
+
+    def _is_gcc(self, compiler_name):
+        return "gcc" in compiler_name or "g++" in compiler_name
+
+    def runtime_library_dir_option(self, dir):
+        # XXX Hackish, at the very least.  See Python bug #445902:
+        # http://sourceforge.net/tracker/index.php
+        #   ?func=detail&aid=445902&group_id=5470&atid=105470
+        # Linkers on different platforms need different options to
+        # specify that directories need to be added to the list of
+        # directories searched for dependencies when a dynamic library
+        # is sought.  GCC has to be told to pass the -R option through
+        # to the linker, whereas other compilers just know this.
+        # Other compilers may need something slightly different.  At
+        # this time, there's no way to determine this information from
+        # the configuration data stored in the Python installation, so
+        # we use this hack.
+        compiler = os.path.basename(sysconfig.get_config_var("CC"))
+        if sys.platform[:6] == "darwin":
+            # MacOSX's linker doesn't understand the -R flag at all
+            return "-L" + dir
+        elif sys.platform[:5] == "hp-ux":
+            if self._is_gcc(compiler):
+                return ["-Wl,+s", "-L" + dir]
+            return ["+s", "-L" + dir]
+        elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":
+            return ["-rpath", dir]
+        elif self._is_gcc(compiler):
+            return "-Wl,-R" + dir
+        else:
+            return "-R" + dir
+
+    def library_option(self, lib):
+        return "-l" + lib
+
+    def find_library_file(self, dirs, lib, debug=0):
+        shared_f = self.library_filename(lib, lib_type='shared')
+        dylib_f = self.library_filename(lib, lib_type='dylib')
+        static_f = self.library_filename(lib, lib_type='static')
+
+        if sys.platform == 'darwin':
+            # On OSX users can specify an alternate SDK using
+            # '-isysroot', calculate the SDK root if it is specified
+            # (and use it further on)
+            cflags = sysconfig.get_config_var('CFLAGS')
+            m = re.search(r'-isysroot\s+(\S+)', cflags)
+            if m is None:
+                sysroot = '/'
+            else:
+                sysroot = m.group(1)
+
+
+
+        for dir in dirs:
+            shared = os.path.join(dir, shared_f)
+            dylib = os.path.join(dir, dylib_f)
+            static = os.path.join(dir, static_f)
+
+            if sys.platform == 'darwin' and (
+                dir.startswith('/System/') or (
+                dir.startswith('/usr/') and not dir.startswith('/usr/local/'))):
+
+                shared = os.path.join(sysroot, dir[1:], shared_f)
+                dylib = os.path.join(sysroot, dir[1:], dylib_f)
+                static = os.path.join(sysroot, dir[1:], static_f)
+
+            # We're second-guessing the linker here, with not much hard
+            # data to go on: GCC seems to prefer the shared library, so I'm
+            # assuming that *all* Unix C compilers do.  And of course I'm
+            # ignoring even GCC's "-static" option.  So sue me.
+            if os.path.exists(dylib):
+                return dylib
+            elif os.path.exists(shared):
+                return shared
+            elif os.path.exists(static):
+                return static
+
+        # Oops, didn't find it in *any* of 'dirs'
+        return None
diff --git a/src/main/resources/PythonLibs/distutils/util.py b/src/main/resources/PythonLibs/distutils/util.py
new file mode 100644
index 0000000000000000000000000000000000000000..570da737124bb994fb3d3e3a76d523382f10fa69
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/util.py
@@ -0,0 +1,580 @@
+"""distutils.util
+
+Miscellaneous utility functions -- anything that doesn't fit into
+one of the other *util.py modules.
+"""
+
+__revision__ = "$Id: util.py 83588 2010-08-02 21:35:06Z ezio.melotti $"
+
+import sys, os, string, re
+from distutils.errors import DistutilsPlatformError
+from distutils.dep_util import newer
+from distutils.spawn import spawn
+from distutils import log
+from distutils.errors import DistutilsByteCompileError
+
+def get_platform ():
+    """Return a string that identifies the current platform.  This is used
+    mainly to distinguish platform-specific build directories and
+    platform-specific built distributions.  Typically includes the OS name
+    and version and the architecture (as supplied by 'os.uname()'),
+    although the exact information included depends on the OS; eg. for IRIX
+    the architecture isn't particularly important (IRIX only runs on SGI
+    hardware), but for Linux the kernel version isn't particularly
+    important.
+
+    Examples of returned values:
+       linux-i586
+       linux-alpha (?)
+       solaris-2.6-sun4u
+       irix-5.3
+       irix64-6.2
+
+    Windows will return one of:
+       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
+       win-ia64 (64bit Windows on Itanium)
+       win32 (all others - specifically, sys.platform is returned)
+
+    For other non-POSIX platforms, currently just returns 'sys.platform'.
+    """
+    if os.name == 'nt':
+        # sniff sys.version for architecture.
+        prefix = " bit ("
+        i = string.find(sys.version, prefix)
+        if i == -1:
+            return sys.platform
+        j = string.find(sys.version, ")", i)
+        look = sys.version[i+len(prefix):j].lower()
+        if look=='amd64':
+            return 'win-amd64'
+        if look=='itanium':
+            return 'win-ia64'
+        return sys.platform
+
+    if os.name != "posix" or not hasattr(os, 'uname'):
+        # XXX what about the architecture? NT is Intel or Alpha,
+        # Mac OS is M68k or PPC, etc.
+        return sys.platform
+
+    # Try to distinguish various flavours of Unix
+
+    (osname, host, release, version, machine) = os.uname()
+
+    # Convert the OS name to lowercase, remove '/' characters
+    # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
+    osname = string.lower(osname)
+    osname = string.replace(osname, '/', '')
+    machine = string.replace(machine, ' ', '_')
+    machine = string.replace(machine, '/', '-')
+
+    if osname[:5] == "linux":
+        # At least on Linux/Intel, 'machine' is the processor --
+        # i386, etc.
+        # XXX what about Alpha, SPARC, etc?
+        return  "%s-%s" % (osname, machine)
+    elif osname[:5] == "sunos":
+        if release[0] >= "5":           # SunOS 5 == Solaris 2
+            osname = "solaris"
+            release = "%d.%s" % (int(release[0]) - 3, release[2:])
+        # fall through to standard osname-release-machine representation
+    elif osname[:4] == "irix":              # could be "irix64"!
+        return "%s-%s" % (osname, release)
+    elif osname[:3] == "aix":
+        return "%s-%s.%s" % (osname, version, release)
+    elif osname[:6] == "cygwin":
+        osname = "cygwin"
+        rel_re = re.compile (r'[\d.]+')
+        m = rel_re.match(release)
+        if m:
+            release = m.group()
+    elif osname[:6] == "darwin":
+        #
+        # For our purposes, we'll assume that the system version from
+        # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
+        # to. This makes the compatibility story a bit more sane because the
+        # machine is going to compile and link as if it were
+        # MACOSX_DEPLOYMENT_TARGET.
+        from distutils.sysconfig import get_config_vars
+        cfgvars = get_config_vars()
+
+        macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET')
+        if not macver:
+            macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
+
+        if 1:
+            # Always calculate the release of the running machine,
+            # needed to determine if we can build fat binaries or not.
+
+            macrelease = macver
+            # Get the system version. Reading this plist is a documented
+            # way to get the system version (see the documentation for
+            # the Gestalt Manager)
+            try:
+                f = open('/System/Library/CoreServices/SystemVersion.plist')
+            except IOError:
+                # We're on a plain darwin box, fall back to the default
+                # behaviour.
+                pass
+            else:
+                m = re.search(
+                        r'<key>ProductUserVisibleVersion</key>\s*' +
+                        r'<string>(.*?)</string>', f.read())
+                f.close()
+                if m is not None:
+                    macrelease = '.'.join(m.group(1).split('.')[:2])
+                # else: fall back to the default behaviour
+
+        if not macver:
+            macver = macrelease
+
+        if macver:
+            from distutils.sysconfig import get_config_vars
+            release = macver
+            osname = "macosx"
+
+            if (macrelease + '.') >= '10.4.' and \
+                    '-arch' in get_config_vars().get('CFLAGS', '').strip():
+                # The universal build will build fat binaries, but not on
+                # systems before 10.4
+                #
+                # Try to detect 4-way universal builds, those have machine-type
+                # 'universal' instead of 'fat'.
+
+                machine = 'fat'
+                cflags = get_config_vars().get('CFLAGS')
+
+                archs = re.findall('-arch\s+(\S+)', cflags)
+                archs = tuple(sorted(set(archs)))
+
+                if len(archs) == 1:
+                    machine = archs[0]
+                elif archs == ('i386', 'ppc'):
+                    machine = 'fat'
+                elif archs == ('i386', 'x86_64'):
+                    machine = 'intel'
+                elif archs == ('i386', 'ppc', 'x86_64'):
+                    machine = 'fat3'
+                elif archs == ('ppc64', 'x86_64'):
+                    machine = 'fat64'
+                elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
+                    machine = 'universal'
+                else:
+                    raise ValueError(
+                       "Don't know machine value for archs=%r"%(archs,))
+
+            elif machine == 'i386':
+                # On OSX the machine type returned by uname is always the
+                # 32-bit variant, even if the executable architecture is
+                # the 64-bit variant
+                if sys.maxint >= 2**32:
+                    machine = 'x86_64'
+
+            elif machine in ('PowerPC', 'Power_Macintosh'):
+                # Pick a sane name for the PPC architecture.
+                machine = 'ppc'
+
+                # See 'i386' case
+                if sys.maxint >= 2**32:
+                    machine = 'ppc64'
+
+    return "%s-%s-%s" % (osname, release, machine)
+
+# get_platform ()
+
+
+def convert_path (pathname):
+    """Return 'pathname' as a name that will work on the native filesystem,
+    i.e. split it on '/' and put it back together again using the current
+    directory separator.  Needed because filenames in the setup script are
+    always supplied in Unix style, and have to be converted to the local
+    convention before we can actually use them in the filesystem.  Raises
+    ValueError on non-Unix-ish systems if 'pathname' either starts or
+    ends with a slash.
+    """
+    if os.sep == '/':
+        return pathname
+    if not pathname:
+        return pathname
+    if pathname[0] == '/':
+        raise ValueError, "path '%s' cannot be absolute" % pathname
+    if pathname[-1] == '/':
+        raise ValueError, "path '%s' cannot end with '/'" % pathname
+
+    paths = string.split(pathname, '/')
+    while '.' in paths:
+        paths.remove('.')
+    if not paths:
+        return os.curdir
+    return os.path.join(*paths)
+
+# convert_path ()
+
+
+def change_root (new_root, pathname):
+    """Return 'pathname' with 'new_root' prepended.  If 'pathname' is
+    relative, this is equivalent to "os.path.join(new_root,pathname)".
+    Otherwise, it requires making 'pathname' relative and then joining the
+    two, which is tricky on DOS/Windows and Mac OS.
+    """
+    os_name = os._name if sys.platform.startswith('java') else os.name
+    if os_name == 'posix':
+        if not os.path.isabs(pathname):
+            return os.path.join(new_root, pathname)
+        else:
+            return os.path.join(new_root, pathname[1:])
+
+    elif os_name == 'nt':
+        (drive, path) = os.path.splitdrive(pathname)
+        if path[0] == '\\':
+            path = path[1:]
+        return os.path.join(new_root, path)
+
+    elif os_name == 'os2':
+        (drive, path) = os.path.splitdrive(pathname)
+        if path[0] == os.sep:
+            path = path[1:]
+        return os.path.join(new_root, path)
+
+    elif os_name == 'mac':
+        if not os.path.isabs(pathname):
+            return os.path.join(new_root, pathname)
+        else:
+            # Chop off volume name from start of path
+            elements = string.split(pathname, ":", 1)
+            pathname = ":" + elements[1]
+            return os.path.join(new_root, pathname)
+
+    else:
+        raise DistutilsPlatformError, \
+              "nothing known about platform '%s'" % os_name
+
+
+_environ_checked = 0
+def check_environ ():
+    """Ensure that 'os.environ' has all the environment variables we
+    guarantee that users can use in config files, command-line options,
+    etc.  Currently this includes:
+      HOME - user's home directory (Unix only)
+      PLAT - description of the current platform, including hardware
+             and OS (see 'get_platform()')
+    """
+    global _environ_checked
+    if _environ_checked:
+        return
+
+    if os.name == 'posix' and 'HOME' not in os.environ:
+        import pwd
+        os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
+
+    if 'PLAT' not in os.environ:
+        os.environ['PLAT'] = get_platform()
+
+    _environ_checked = 1
+
+
+def subst_vars (s, local_vars):
+    """Perform shell/Perl-style variable substitution on 'string'.  Every
+    occurrence of '$' followed by a name is considered a variable, and
+    variable is substituted by the value found in the 'local_vars'
+    dictionary, or in 'os.environ' if it's not in 'local_vars'.
+    'os.environ' is first checked/augmented to guarantee that it contains
+    certain values: see 'check_environ()'.  Raise ValueError for any
+    variables not found in either 'local_vars' or 'os.environ'.
+    """
+    check_environ()
+    def _subst (match, local_vars=local_vars):
+        var_name = match.group(1)
+        if var_name in local_vars:
+            return str(local_vars[var_name])
+        else:
+            return os.environ[var_name]
+
+    try:
+        return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
+    except KeyError, var:
+        raise ValueError, "invalid variable '$%s'" % var
+
+# subst_vars ()
+
+
+def grok_environment_error (exc, prefix="error: "):
+    """Generate a useful error message from an EnvironmentError (IOError or
+    OSError) exception object.  Handles Python 1.5.1 and 1.5.2 styles, and
+    does what it can to deal with exception objects that don't have a
+    filename (which happens when the error is due to a two-file operation,
+    such as 'rename()' or 'link()'.  Returns the error message as a string
+    prefixed with 'prefix'.
+    """
+    # check for Python 1.5.2-style {IO,OS}Error exception objects
+    if hasattr(exc, 'filename') and hasattr(exc, 'strerror'):
+        if exc.filename:
+            error = prefix + "%s: %s" % (exc.filename, exc.strerror)
+        else:
+            # two-argument functions in posix module don't
+            # include the filename in the exception object!
+            error = prefix + "%s" % exc.strerror
+    else:
+        error = prefix + str(exc[-1])
+
+    return error
+
+
+# Needed by 'split_quoted()'
+_wordchars_re = _squote_re = _dquote_re = None
+def _init_regex():
+    global _wordchars_re, _squote_re, _dquote_re
+    _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
+    _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
+    _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
+
+def split_quoted (s):
+    """Split a string up according to Unix shell-like rules for quotes and
+    backslashes.  In short: words are delimited by spaces, as long as those
+    spaces are not escaped by a backslash, or inside a quoted string.
+    Single and double quotes are equivalent, and the quote characters can
+    be backslash-escaped.  The backslash is stripped from any two-character
+    escape sequence, leaving only the escaped character.  The quote
+    characters are stripped from any quoted string.  Returns a list of
+    words.
+    """
+
+    # This is a nice algorithm for splitting up a single string, since it
+    # doesn't require character-by-character examination.  It was a little
+    # bit of a brain-bender to get it working right, though...
+    if _wordchars_re is None: _init_regex()
+
+    s = string.strip(s)
+    words = []
+    pos = 0
+
+    while s:
+        m = _wordchars_re.match(s, pos)
+        end = m.end()
+        if end == len(s):
+            words.append(s[:end])
+            break
+
+        if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
+            words.append(s[:end])       # we definitely have a word delimiter
+            s = string.lstrip(s[end:])
+            pos = 0
+
+        elif s[end] == '\\':            # preserve whatever is being escaped;
+                                        # will become part of the current word
+            s = s[:end] + s[end+1:]
+            pos = end+1
+
+        else:
+            if s[end] == "'":           # slurp singly-quoted string
+                m = _squote_re.match(s, end)
+            elif s[end] == '"':         # slurp doubly-quoted string
+                m = _dquote_re.match(s, end)
+            else:
+                raise RuntimeError, \
+                      "this can't happen (bad char '%c')" % s[end]
+
+            if m is None:
+                raise ValueError, \
+                      "bad string (mismatched %s quotes?)" % s[end]
+
+            (beg, end) = m.span()
+            s = s[:beg] + s[beg+1:end-1] + s[end:]
+            pos = m.end() - 2
+
+        if pos >= len(s):
+            words.append(s)
+            break
+
+    return words
+
+# split_quoted ()
+
+
+def execute (func, args, msg=None, verbose=0, dry_run=0):
+    """Perform some action that affects the outside world (eg.  by
+    writing to the filesystem).  Such actions are special because they
+    are disabled by the 'dry_run' flag.  This method takes care of all
+    that bureaucracy for you; all you have to do is supply the
+    function to call and an argument tuple for it (to embody the
+    "external action" being performed), and an optional message to
+    print.
+    """
+    if msg is None:
+        msg = "%s%r" % (func.__name__, args)
+        if msg[-2:] == ',)':        # correct for singleton tuple
+            msg = msg[0:-2] + ')'
+
+    log.info(msg)
+    if not dry_run:
+        func(*args)
+
+
+def strtobool (val):
+    """Convert a string representation of truth to true (1) or false (0).
+
+    True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
+    are 'n', 'no', 'f', 'false', 'off', and '0'.  Raises ValueError if
+    'val' is anything else.
+    """
+    val = string.lower(val)
+    if val in ('y', 'yes', 't', 'true', 'on', '1'):
+        return 1
+    elif val in ('n', 'no', 'f', 'false', 'off', '0'):
+        return 0
+    else:
+        raise ValueError, "invalid truth value %r" % (val,)
+
+
+def byte_compile (py_files,
+                  optimize=0, force=0,
+                  prefix=None, base_dir=None,
+                  verbose=1, dry_run=0,
+                  direct=None):
+    """Byte-compile a collection of Python source files to either .pyc
+    or .pyo files in the same directory.  'py_files' is a list of files
+    to compile; any files that don't end in ".py" are silently skipped.
+    'optimize' must be one of the following:
+      0 - don't optimize (generate .pyc)
+      1 - normal optimization (like "python -O")
+      2 - extra optimization (like "python -OO")
+    If 'force' is true, all files are recompiled regardless of
+    timestamps.
+
+    The source filename encoded in each bytecode file defaults to the
+    filenames listed in 'py_files'; you can modify these with 'prefix' and
+    'basedir'.  'prefix' is a string that will be stripped off of each
+    source filename, and 'base_dir' is a directory name that will be
+    prepended (after 'prefix' is stripped).  You can supply either or both
+    (or neither) of 'prefix' and 'base_dir', as you wish.
+
+    If 'dry_run' is true, doesn't actually do anything that would
+    affect the filesystem.
+
+    Byte-compilation is either done directly in this interpreter process
+    with the standard py_compile module, or indirectly by writing a
+    temporary script and executing it.  Normally, you should let
+    'byte_compile()' figure out to use direct compilation or not (see
+    the source for details).  The 'direct' flag is used by the script
+    generated in indirect mode; unless you know what you're doing, leave
+    it set to None.
+    """
+    # nothing is done if sys.dont_write_bytecode is True
+    if sys.dont_write_bytecode:
+        raise DistutilsByteCompileError('byte-compiling is disabled.')
+
+    # First, if the caller didn't force us into direct or indirect mode,
+    # figure out which mode we should be in.  We take a conservative
+    # approach: choose direct mode *only* if the current interpreter is
+    # in debug mode and optimize is 0.  If we're not in debug mode (-O
+    # or -OO), we don't know which level of optimization this
+    # interpreter is running with, so we can't do direct
+    # byte-compilation and be certain that it's the right thing.  Thus,
+    # always compile indirectly if the current interpreter is in either
+    # optimize mode, or if either optimization level was requested by
+    # the caller.
+    if direct is None:
+        direct = (__debug__ and optimize == 0)
+
+    # "Indirect" byte-compilation: write a temporary script and then
+    # run it with the appropriate flags.
+    if not direct:
+        try:
+            from tempfile import mkstemp
+            (script_fd, script_name) = mkstemp(".py")
+        except ImportError:
+            from tempfile import mktemp
+            (script_fd, script_name) = None, mktemp(".py")
+        log.info("writing byte-compilation script '%s'", script_name)
+        if not dry_run:
+            if script_fd is not None:
+                script = os.fdopen(script_fd, "w")
+            else:
+                script = open(script_name, "w")
+
+            script.write("""\
+from distutils.util import byte_compile
+files = [
+""")
+
+            # XXX would be nice to write absolute filenames, just for
+            # safety's sake (script should be more robust in the face of
+            # chdir'ing before running it).  But this requires abspath'ing
+            # 'prefix' as well, and that breaks the hack in build_lib's
+            # 'byte_compile()' method that carefully tacks on a trailing
+            # slash (os.sep really) to make sure the prefix here is "just
+            # right".  This whole prefix business is rather delicate -- the
+            # problem is that it's really a directory, but I'm treating it
+            # as a dumb string, so trailing slashes and so forth matter.
+
+            #py_files = map(os.path.abspath, py_files)
+            #if prefix:
+            #    prefix = os.path.abspath(prefix)
+
+            script.write(string.join(map(repr, py_files), ",\n") + "]\n")
+            script.write("""
+byte_compile(files, optimize=%r, force=%r,
+             prefix=%r, base_dir=%r,
+             verbose=%r, dry_run=0,
+             direct=1)
+""" % (optimize, force, prefix, base_dir, verbose))
+
+            script.close()
+
+        cmd = [sys.executable, script_name]
+        if optimize == 1:
+            cmd.insert(1, "-O")
+        elif optimize == 2:
+            cmd.insert(1, "-OO")
+        spawn(cmd, dry_run=dry_run)
+        execute(os.remove, (script_name,), "removing %s" % script_name,
+                dry_run=dry_run)
+
+    # "Direct" byte-compilation: use the py_compile module to compile
+    # right here, right now.  Note that the script generated in indirect
+    # mode simply calls 'byte_compile()' in direct mode, a weird sort of
+    # cross-process recursion.  Hey, it works!
+    else:
+        from py_compile import compile
+
+        for file in py_files:
+            if file[-3:] != ".py":
+                # This lets us be lazy and not filter filenames in
+                # the "install_lib" command.
+                continue
+
+            # Terminology from the py_compile module:
+            #   cfile - byte-compiled file
+            #   dfile - purported source filename (same as 'file' by default)
+            if sys.platform.startswith('java'):
+                cfile = file[:-3] + '$py.class'
+            else:
+                cfile = file + (__debug__ and "c" or "o")
+            dfile = file
+            if prefix:
+                if file[:len(prefix)] != prefix:
+                    raise ValueError, \
+                          ("invalid prefix: filename %r doesn't start with %r"
+                           % (file, prefix))
+                dfile = dfile[len(prefix):]
+            if base_dir:
+                dfile = os.path.join(base_dir, dfile)
+
+            cfile_base = os.path.basename(cfile)
+            if direct:
+                if force or newer(file, cfile):
+                    log.info("byte-compiling %s to %s", file, cfile_base)
+                    if not dry_run:
+                        compile(file, cfile, dfile)
+                else:
+                    log.debug("skipping byte-compilation of %s to %s",
+                              file, cfile_base)
+
+# byte_compile ()
+
+def rfc822_escape (header):
+    """Return a version of the string escaped for inclusion in an
+    RFC-822 header, by ensuring there are 8 spaces space after each newline.
+    """
+    lines = string.split(header, '\n')
+    header = string.join(lines, '\n' + 8*' ')
+    return header
diff --git a/src/main/resources/PythonLibs/distutils/version.py b/src/main/resources/PythonLibs/distutils/version.py
new file mode 100644
index 0000000000000000000000000000000000000000..0fb5b6e20411b765360a25b69954877af5de44fd
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/version.py
@@ -0,0 +1,299 @@
+#
+# distutils/version.py
+#
+# Implements multiple version numbering conventions for the
+# Python Module Distribution Utilities.
+#
+# $Id$
+#
+
+"""Provides classes to represent module version numbers (one class for
+each style of version numbering).  There are currently two such classes
+implemented: StrictVersion and LooseVersion.
+
+Every version number class implements the following interface:
+  * the 'parse' method takes a string and parses it to some internal
+    representation; if the string is an invalid version number,
+    'parse' raises a ValueError exception
+  * the class constructor takes an optional string argument which,
+    if supplied, is passed to 'parse'
+  * __str__ reconstructs the string that was passed to 'parse' (or
+    an equivalent string -- ie. one that will generate an equivalent
+    version number instance)
+  * __repr__ generates Python code to recreate the version number instance
+  * __cmp__ compares the current instance with either another instance
+    of the same class or a string (which will be parsed to an instance
+    of the same class, thus must follow the same rules)
+"""
+
+import string, re
+from types import StringType
+
+class Version:
+    """Abstract base class for version numbering classes.  Just provides
+    constructor (__init__) and reproducer (__repr__), because those
+    seem to be the same for all version numbering classes.
+    """
+
+    def __init__ (self, vstring=None):
+        if vstring:
+            self.parse(vstring)
+
+    def __repr__ (self):
+        return "%s ('%s')" % (self.__class__.__name__, str(self))
+
+
+# Interface for version-number classes -- must be implemented
+# by the following classes (the concrete ones -- Version should
+# be treated as an abstract class).
+#    __init__ (string) - create and take same action as 'parse'
+#                        (string parameter is optional)
+#    parse (string)    - convert a string representation to whatever
+#                        internal representation is appropriate for
+#                        this style of version numbering
+#    __str__ (self)    - convert back to a string; should be very similar
+#                        (if not identical to) the string supplied to parse
+#    __repr__ (self)   - generate Python code to recreate
+#                        the instance
+#    __cmp__ (self, other) - compare two version numbers ('other' may
+#                        be an unparsed version string, or another
+#                        instance of your version class)
+
+
+class StrictVersion (Version):
+
+    """Version numbering for anal retentives and software idealists.
+    Implements the standard interface for version number classes as
+    described above.  A version number consists of two or three
+    dot-separated numeric components, with an optional "pre-release" tag
+    on the end.  The pre-release tag consists of the letter 'a' or 'b'
+    followed by a number.  If the numeric components of two version
+    numbers are equal, then one with a pre-release tag will always
+    be deemed earlier (lesser) than one without.
+
+    The following are valid version numbers (shown in the order that
+    would be obtained by sorting according to the supplied cmp function):
+
+        0.4       0.4.0  (these two are equivalent)
+        0.4.1
+        0.5a1
+        0.5b3
+        0.5
+        0.9.6
+        1.0
+        1.0.4a3
+        1.0.4b1
+        1.0.4
+
+    The following are examples of invalid version numbers:
+
+        1
+        2.7.2.2
+        1.3.a4
+        1.3pl1
+        1.3c4
+
+    The rationale for this version numbering system will be explained
+    in the distutils documentation.
+    """
+
+    version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$',
+                            re.VERBOSE)
+
+
+    def parse (self, vstring):
+        match = self.version_re.match(vstring)
+        if not match:
+            raise ValueError, "invalid version number '%s'" % vstring
+
+        (major, minor, patch, prerelease, prerelease_num) = \
+            match.group(1, 2, 4, 5, 6)
+
+        if patch:
+            self.version = tuple(map(string.atoi, [major, minor, patch]))
+        else:
+            self.version = tuple(map(string.atoi, [major, minor]) + [0])
+
+        if prerelease:
+            self.prerelease = (prerelease[0], string.atoi(prerelease_num))
+        else:
+            self.prerelease = None
+
+
+    def __str__ (self):
+
+        if self.version[2] == 0:
+            vstring = string.join(map(str, self.version[0:2]), '.')
+        else:
+            vstring = string.join(map(str, self.version), '.')
+
+        if self.prerelease:
+            vstring = vstring + self.prerelease[0] + str(self.prerelease[1])
+
+        return vstring
+
+
+    def __cmp__ (self, other):
+        if isinstance(other, StringType):
+            other = StrictVersion(other)
+
+        compare = cmp(self.version, other.version)
+        if (compare == 0):              # have to compare prerelease
+
+            # case 1: neither has prerelease; they're equal
+            # case 2: self has prerelease, other doesn't; other is greater
+            # case 3: self doesn't have prerelease, other does: self is greater
+            # case 4: both have prerelease: must compare them!
+
+            if (not self.prerelease and not other.prerelease):
+                return 0
+            elif (self.prerelease and not other.prerelease):
+                return -1
+            elif (not self.prerelease and other.prerelease):
+                return 1
+            elif (self.prerelease and other.prerelease):
+                return cmp(self.prerelease, other.prerelease)
+
+        else:                           # numeric versions don't match --
+            return compare              # prerelease stuff doesn't matter
+
+
+# end class StrictVersion
+
+
+# The rules according to Greg Stein:
+# 1) a version number has 1 or more numbers separated by a period or by
+#    sequences of letters. If only periods, then these are compared
+#    left-to-right to determine an ordering.
+# 2) sequences of letters are part of the tuple for comparison and are
+#    compared lexicographically
+# 3) recognize the numeric components may have leading zeroes
+#
+# The LooseVersion class below implements these rules: a version number
+# string is split up into a tuple of integer and string components, and
+# comparison is a simple tuple comparison.  This means that version
+# numbers behave in a predictable and obvious way, but a way that might
+# not necessarily be how people *want* version numbers to behave.  There
+# wouldn't be a problem if people could stick to purely numeric version
+# numbers: just split on period and compare the numbers as tuples.
+# However, people insist on putting letters into their version numbers;
+# the most common purpose seems to be:
+#   - indicating a "pre-release" version
+#     ('alpha', 'beta', 'a', 'b', 'pre', 'p')
+#   - indicating a post-release patch ('p', 'pl', 'patch')
+# but of course this can't cover all version number schemes, and there's
+# no way to know what a programmer means without asking him.
+#
+# The problem is what to do with letters (and other non-numeric
+# characters) in a version number.  The current implementation does the
+# obvious and predictable thing: keep them as strings and compare
+# lexically within a tuple comparison.  This has the desired effect if
+# an appended letter sequence implies something "post-release":
+# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002".
+#
+# However, if letters in a version number imply a pre-release version,
+# the "obvious" thing isn't correct.  Eg. you would expect that
+# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison
+# implemented here, this just isn't so.
+#
+# Two possible solutions come to mind.  The first is to tie the
+# comparison algorithm to a particular set of semantic rules, as has
+# been done in the StrictVersion class above.  This works great as long
+# as everyone can go along with bondage and discipline.  Hopefully a
+# (large) subset of Python module programmers will agree that the
+# particular flavour of bondage and discipline provided by StrictVersion
+# provides enough benefit to be worth using, and will submit their
+# version numbering scheme to its domination.  The free-thinking
+# anarchists in the lot will never give in, though, and something needs
+# to be done to accommodate them.
+#
+# Perhaps a "moderately strict" version class could be implemented that
+# lets almost anything slide (syntactically), and makes some heuristic
+# assumptions about non-digits in version number strings.  This could
+# sink into special-case-hell, though; if I was as talented and
+# idiosyncratic as Larry Wall, I'd go ahead and implement a class that
+# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is
+# just as happy dealing with things like "2g6" and "1.13++".  I don't
+# think I'm smart enough to do it right though.
+#
+# In any case, I've coded the test suite for this module (see
+# ../test/test_version.py) specifically to fail on things like comparing
+# "1.2a2" and "1.2".  That's not because the *code* is doing anything
+# wrong, it's because the simple, obvious design doesn't match my
+# complicated, hairy expectations for real-world version numbers.  It
+# would be a snap to fix the test suite to say, "Yep, LooseVersion does
+# the Right Thing" (ie. the code matches the conception).  But I'd rather
+# have a conception that matches common notions about version numbers.
+
+class LooseVersion (Version):
+
+    """Version numbering for anarchists and software realists.
+    Implements the standard interface for version number classes as
+    described above.  A version number consists of a series of numbers,
+    separated by either periods or strings of letters.  When comparing
+    version numbers, the numeric components will be compared
+    numerically, and the alphabetic components lexically.  The following
+    are all valid version numbers, in no particular order:
+
+        1.5.1
+        1.5.2b2
+        161
+        3.10a
+        8.02
+        3.4j
+        1996.07.12
+        3.2.pl0
+        3.1.1.6
+        2g6
+        11g
+        0.960923
+        2.2beta29
+        1.13++
+        5.5.kw
+        2.0b1pl0
+
+    In fact, there is no such thing as an invalid version number under
+    this scheme; the rules for comparison are simple and predictable,
+    but may not always give the results you want (for some definition
+    of "want").
+    """
+
+    component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)
+
+    def __init__ (self, vstring=None):
+        if vstring:
+            self.parse(vstring)
+
+
+    def parse (self, vstring):
+        # I've given up on thinking I can reconstruct the version string
+        # from the parsed tuple -- so I just store the string here for
+        # use by __str__
+        self.vstring = vstring
+        components = filter(lambda x: x and x != '.',
+                            self.component_re.split(vstring))
+        for i in range(len(components)):
+            try:
+                components[i] = int(components[i])
+            except ValueError:
+                pass
+
+        self.version = components
+
+
+    def __str__ (self):
+        return self.vstring
+
+
+    def __repr__ (self):
+        return "LooseVersion ('%s')" % str(self)
+
+
+    def __cmp__ (self, other):
+        if isinstance(other, StringType):
+            other = LooseVersion(other)
+
+        return cmp(self.version, other.version)
+
+
+# end class LooseVersion
diff --git a/src/main/resources/PythonLibs/distutils/versionpredicate.py b/src/main/resources/PythonLibs/distutils/versionpredicate.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba8b6c021b20082b713c8c23ba1ce8526b191e70
--- /dev/null
+++ b/src/main/resources/PythonLibs/distutils/versionpredicate.py
@@ -0,0 +1,164 @@
+"""Module for parsing and testing package version predicate strings.
+"""
+import re
+import distutils.version
+import operator
+
+
+re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)")
+# (package) (rest)
+
+re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses
+re_splitComparison = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$")
+# (comp) (version)
+
+
+def splitUp(pred):
+    """Parse a single version comparison.
+
+    Return (comparison string, StrictVersion)
+    """
+    res = re_splitComparison.match(pred)
+    if not res:
+        raise ValueError("bad package restriction syntax: %r" % pred)
+    comp, verStr = res.groups()
+    return (comp, distutils.version.StrictVersion(verStr))
+
+compmap = {"<": operator.lt, "<=": operator.le, "==": operator.eq,
+           ">": operator.gt, ">=": operator.ge, "!=": operator.ne}
+
+class VersionPredicate:
+    """Parse and test package version predicates.
+
+    >>> v = VersionPredicate('pyepat.abc (>1.0, <3333.3a1, !=1555.1b3)')
+
+    The `name` attribute provides the full dotted name that is given::
+
+    >>> v.name
+    'pyepat.abc'
+
+    The str() of a `VersionPredicate` provides a normalized
+    human-readable version of the expression::
+
+    >>> print v
+    pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3)
+
+    The `satisfied_by()` method can be used to determine with a given
+    version number is included in the set described by the version
+    restrictions::
+
+    >>> v.satisfied_by('1.1')
+    True
+    >>> v.satisfied_by('1.4')
+    True
+    >>> v.satisfied_by('1.0')
+    False
+    >>> v.satisfied_by('4444.4')
+    False
+    >>> v.satisfied_by('1555.1b3')
+    False
+
+    `VersionPredicate` is flexible in accepting extra whitespace::
+
+    >>> v = VersionPredicate(' pat( ==  0.1  )  ')
+    >>> v.name
+    'pat'
+    >>> v.satisfied_by('0.1')
+    True
+    >>> v.satisfied_by('0.2')
+    False
+
+    If any version numbers passed in do not conform to the
+    restrictions of `StrictVersion`, a `ValueError` is raised::
+
+    >>> v = VersionPredicate('p1.p2.p3.p4(>=1.0, <=1.3a1, !=1.2zb3)')
+    Traceback (most recent call last):
+      ...
+    ValueError: invalid version number '1.2zb3'
+
+    It the module or package name given does not conform to what's
+    allowed as a legal module or package name, `ValueError` is
+    raised::
+
+    >>> v = VersionPredicate('foo-bar')
+    Traceback (most recent call last):
+      ...
+    ValueError: expected parenthesized list: '-bar'
+
+    >>> v = VersionPredicate('foo bar (12.21)')
+    Traceback (most recent call last):
+      ...
+    ValueError: expected parenthesized list: 'bar (12.21)'
+
+    """
+
+    def __init__(self, versionPredicateStr):
+        """Parse a version predicate string.
+        """
+        # Fields:
+        #    name:  package name
+        #    pred:  list of (comparison string, StrictVersion)
+
+        versionPredicateStr = versionPredicateStr.strip()
+        if not versionPredicateStr:
+            raise ValueError("empty package restriction")
+        match = re_validPackage.match(versionPredicateStr)
+        if not match:
+            raise ValueError("bad package name in %r" % versionPredicateStr)
+        self.name, paren = match.groups()
+        paren = paren.strip()
+        if paren:
+            match = re_paren.match(paren)
+            if not match:
+                raise ValueError("expected parenthesized list: %r" % paren)
+            str = match.groups()[0]
+            self.pred = [splitUp(aPred) for aPred in str.split(",")]
+            if not self.pred:
+                raise ValueError("empty parenthesized list in %r"
+                                 % versionPredicateStr)
+        else:
+            self.pred = []
+
+    def __str__(self):
+        if self.pred:
+            seq = [cond + " " + str(ver) for cond, ver in self.pred]
+            return self.name + " (" + ", ".join(seq) + ")"
+        else:
+            return self.name
+
+    def satisfied_by(self, version):
+        """True if version is compatible with all the predicates in self.
+        The parameter version must be acceptable to the StrictVersion
+        constructor.  It may be either a string or StrictVersion.
+        """
+        for cond, ver in self.pred:
+            if not compmap[cond](version, ver):
+                return False
+        return True
+
+
+_provision_rx = None
+
+def split_provision(value):
+    """Return the name and optional version number of a provision.
+
+    The version number, if given, will be returned as a `StrictVersion`
+    instance, otherwise it will be `None`.
+
+    >>> split_provision('mypkg')
+    ('mypkg', None)
+    >>> split_provision(' mypkg( 1.2 ) ')
+    ('mypkg', StrictVersion ('1.2'))
+    """
+    global _provision_rx
+    if _provision_rx is None:
+        _provision_rx = re.compile(
+            "([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$")
+    value = value.strip()
+    m = _provision_rx.match(value)
+    if not m:
+        raise ValueError("illegal provides specification: %r" % value)
+    ver = m.group(2) or None
+    if ver:
+        ver = distutils.version.StrictVersion(ver)
+    return m.group(1), ver
diff --git a/src/main/resources/PythonLibs/doctest.py b/src/main/resources/PythonLibs/doctest.py
new file mode 100644
index 0000000000000000000000000000000000000000..66765e738da32bbd14e0233f7f2d9b923572360f
--- /dev/null
+++ b/src/main/resources/PythonLibs/doctest.py
@@ -0,0 +1,2798 @@
+# Module doctest.
+# Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org).
+# Major enhancements and refactoring by:
+#     Jim Fulton
+#     Edward Loper
+
+# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+
+r"""Module doctest -- a framework for running examples in docstrings.
+
+In simplest use, end each module M to be tested with:
+
+def _test():
+    import doctest
+    doctest.testmod()
+
+if __name__ == "__main__":
+    _test()
+
+Then running the module as a script will cause the examples in the
+docstrings to get executed and verified:
+
+python M.py
+
+This won't display anything unless an example fails, in which case the
+failing example(s) and the cause(s) of the failure(s) are printed to stdout
+(why not stderr? because stderr is a lame hack <0.2 wink>), and the final
+line of output is "Test failed.".
+
+Run it with the -v switch instead:
+
+python M.py -v
+
+and a detailed report of all examples tried is printed to stdout, along
+with assorted summaries at the end.
+
+You can force verbose mode by passing "verbose=True" to testmod, or prohibit
+it by passing "verbose=False".  In either of those cases, sys.argv is not
+examined by testmod.
+
+There are a variety of other ways to run doctests, including integration
+with the unittest framework, and support for running non-Python text
+files containing doctests.  There are also many ways to override parts
+of doctest's default behaviors.  See the Library Reference Manual for
+details.
+"""
+
+__docformat__ = 'reStructuredText en'
+
+__all__ = [
+    # 0, Option Flags
+    'register_optionflag',
+    'DONT_ACCEPT_TRUE_FOR_1',
+    'DONT_ACCEPT_BLANKLINE',
+    'NORMALIZE_WHITESPACE',
+    'ELLIPSIS',
+    'SKIP',
+    'IGNORE_EXCEPTION_DETAIL',
+    'COMPARISON_FLAGS',
+    'REPORT_UDIFF',
+    'REPORT_CDIFF',
+    'REPORT_NDIFF',
+    'REPORT_ONLY_FIRST_FAILURE',
+    'REPORTING_FLAGS',
+    # 1. Utility Functions
+    # 2. Example & DocTest
+    'Example',
+    'DocTest',
+    # 3. Doctest Parser
+    'DocTestParser',
+    # 4. Doctest Finder
+    'DocTestFinder',
+    # 5. Doctest Runner
+    'DocTestRunner',
+    'OutputChecker',
+    'DocTestFailure',
+    'UnexpectedException',
+    'DebugRunner',
+    # 6. Test Functions
+    'testmod',
+    'testfile',
+    'run_docstring_examples',
+    # 7. Tester
+    'Tester',
+    # 8. Unittest Support
+    'DocTestSuite',
+    'DocFileSuite',
+    'set_unittest_reportflags',
+    # 9. Debugging Support
+    'script_from_examples',
+    'testsource',
+    'debug_src',
+    'debug',
+]
+
+import __future__
+
+import sys, traceback, inspect, linecache, os, re
+import unittest, difflib, pdb, tempfile
+import warnings
+from StringIO import StringIO
+from collections import namedtuple
+
+TestResults = namedtuple('TestResults', 'failed attempted')
+
+# There are 4 basic classes:
+#  - Example: a <source, want> pair, plus an intra-docstring line number.
+#  - DocTest: a collection of examples, parsed from a docstring, plus
+#    info about where the docstring came from (name, filename, lineno).
+#  - DocTestFinder: extracts DocTests from a given object's docstring and
+#    its contained objects' docstrings.
+#  - DocTestRunner: runs DocTest cases, and accumulates statistics.
+#
+# So the basic picture is:
+#
+#                             list of:
+# +------+                   +---------+                   +-------+
+# |object| --DocTestFinder-> | DocTest | --DocTestRunner-> |results|
+# +------+                   +---------+                   +-------+
+#                            | Example |
+#                            |   ...   |
+#                            | Example |
+#                            +---------+
+
+# Option constants.
+
+OPTIONFLAGS_BY_NAME = {}
+def register_optionflag(name):
+    # Create a new flag unless `name` is already known.
+    return OPTIONFLAGS_BY_NAME.setdefault(name, 1 << len(OPTIONFLAGS_BY_NAME))
+
+DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1')
+DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')
+NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
+ELLIPSIS = register_optionflag('ELLIPSIS')
+SKIP = register_optionflag('SKIP')
+IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL')
+
+COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 |
+                    DONT_ACCEPT_BLANKLINE |
+                    NORMALIZE_WHITESPACE |
+                    ELLIPSIS |
+                    SKIP |
+                    IGNORE_EXCEPTION_DETAIL)
+
+REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
+REPORT_CDIFF = register_optionflag('REPORT_CDIFF')
+REPORT_NDIFF = register_optionflag('REPORT_NDIFF')
+REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE')
+
+REPORTING_FLAGS = (REPORT_UDIFF |
+                   REPORT_CDIFF |
+                   REPORT_NDIFF |
+                   REPORT_ONLY_FIRST_FAILURE)
+
+# Special string markers for use in `want` strings:
+BLANKLINE_MARKER = '<BLANKLINE>'
+ELLIPSIS_MARKER = '...'
+
+######################################################################
+## Table of Contents
+######################################################################
+#  1. Utility Functions
+#  2. Example & DocTest -- store test cases
+#  3. DocTest Parser -- extracts examples from strings
+#  4. DocTest Finder -- extracts test cases from objects
+#  5. DocTest Runner -- runs test cases
+#  6. Test Functions -- convenient wrappers for testing
+#  7. Tester Class -- for backwards compatibility
+#  8. Unittest Support
+#  9. Debugging Support
+# 10. Example Usage
+
+######################################################################
+## 1. Utility Functions
+######################################################################
+
+def _extract_future_flags(globs):
+    """
+    Return the compiler-flags associated with the future features that
+    have been imported into the given namespace (globs).
+    """
+    flags = 0
+    for fname in __future__.all_feature_names:
+        feature = globs.get(fname, None)
+        if feature is getattr(__future__, fname):
+            flags |= feature.compiler_flag
+    return flags
+
+def _normalize_module(module, depth=2):
+    """
+    Return the module specified by `module`.  In particular:
+      - If `module` is a module, then return module.
+      - If `module` is a string, then import and return the
+        module with that name.
+      - If `module` is None, then return the calling module.
+        The calling module is assumed to be the module of
+        the stack frame at the given depth in the call stack.
+    """
+    if inspect.ismodule(module):
+        return module
+    elif isinstance(module, (str, unicode)):
+        return __import__(module, globals(), locals(), ["*"])
+    elif module is None:
+        return sys.modules[sys._getframe(depth).f_globals['__name__']]
+    else:
+        raise TypeError("Expected a module, string, or None")
+
+def _load_testfile(filename, package, module_relative):
+    if module_relative:
+        package = _normalize_module(package, 3)
+        filename = _module_relative_path(package, filename)
+        if hasattr(package, '__loader__'):
+            if hasattr(package.__loader__, 'get_data'):
+                file_contents = package.__loader__.get_data(filename)
+                # get_data() opens files as 'rb', so one must do the equivalent
+                # conversion as universal newlines would do.
+                return file_contents.replace(os.linesep, '\n'), filename
+    with open(filename) as f:
+        return f.read(), filename
+
+# Use sys.stdout encoding for ouput.
+_encoding = getattr(sys.__stdout__, 'encoding', None) or 'utf-8'
+
+def _indent(s, indent=4):
+    """
+    Add the given number of space characters to the beginning of
+    every non-blank line in `s`, and return the result.
+    If the string `s` is Unicode, it is encoded using the stdout
+    encoding and the `backslashreplace` error handler.
+    """
+    if isinstance(s, unicode):
+        s = s.encode(_encoding, 'backslashreplace')
+    # This regexp matches the start of non-blank lines:
+    return re.sub('(?m)^(?!$)', indent*' ', s)
+
+def _exception_traceback(exc_info):
+    """
+    Return a string containing a traceback message for the given
+    exc_info tuple (as returned by sys.exc_info()).
+    """
+    # Get a traceback message.
+    excout = StringIO()
+    exc_type, exc_val, exc_tb = exc_info
+    traceback.print_exception(exc_type, exc_val, exc_tb, file=excout)
+    return excout.getvalue()
+
+# Override some StringIO methods.
+class _SpoofOut(StringIO):
+    def getvalue(self):
+        result = StringIO.getvalue(self)
+        # If anything at all was written, make sure there's a trailing
+        # newline.  There's no way for the expected output to indicate
+        # that a trailing newline is missing.
+        if result and not result.endswith("\n"):
+            result += "\n"
+        # Prevent softspace from screwing up the next test case, in
+        # case they used print with a trailing comma in an example.
+        if hasattr(self, "softspace"):
+            del self.softspace
+        return result
+
+    def truncate(self,   size=None):
+        StringIO.truncate(self, size)
+        if hasattr(self, "softspace"):
+            del self.softspace
+        if not self.buf:
+            # Reset it to an empty string, to make sure it's not unicode.
+            self.buf = ''
+
+# Worst-case linear-time ellipsis matching.
+def _ellipsis_match(want, got):
+    """
+    Essentially the only subtle case:
+    >>> _ellipsis_match('aa...aa', 'aaa')
+    False
+    """
+    if ELLIPSIS_MARKER not in want:
+        return want == got
+
+    # Find "the real" strings.
+    ws = want.split(ELLIPSIS_MARKER)
+    assert len(ws) >= 2
+
+    # Deal with exact matches possibly needed at one or both ends.
+    startpos, endpos = 0, len(got)
+    w = ws[0]
+    if w:   # starts with exact match
+        if got.startswith(w):
+            startpos = len(w)
+            del ws[0]
+        else:
+            return False
+    w = ws[-1]
+    if w:   # ends with exact match
+        if got.endswith(w):
+            endpos -= len(w)
+            del ws[-1]
+        else:
+            return False
+
+    if startpos > endpos:
+        # Exact end matches required more characters than we have, as in
+        # _ellipsis_match('aa...aa', 'aaa')
+        return False
+
+    # For the rest, we only need to find the leftmost non-overlapping
+    # match for each piece.  If there's no overall match that way alone,
+    # there's no overall match period.
+    for w in ws:
+        # w may be '' at times, if there are consecutive ellipses, or
+        # due to an ellipsis at the start or end of `want`.  That's OK.
+        # Search for an empty string succeeds, and doesn't change startpos.
+        startpos = got.find(w, startpos, endpos)
+        if startpos < 0:
+            return False
+        startpos += len(w)
+
+    return True
+
+def _comment_line(line):
+    "Return a commented form of the given line"
+    line = line.rstrip()
+    if line:
+        return '# '+line
+    else:
+        return '#'
+
+class _OutputRedirectingPdb(pdb.Pdb):
+    """
+    A specialized version of the python debugger that redirects stdout
+    to a given stream when interacting with the user.  Stdout is *not*
+    redirected when traced code is executed.
+    """
+    def __init__(self, out):
+        self.__out = out
+        self.__debugger_used = False
+        pdb.Pdb.__init__(self, stdout=out)
+        # still use input() to get user input
+        self.use_rawinput = 1
+
+    def set_trace(self, frame=None):
+        self.__debugger_used = True
+        if frame is None:
+            frame = sys._getframe().f_back
+        pdb.Pdb.set_trace(self, frame)
+
+    def set_continue(self):
+        # Calling set_continue unconditionally would break unit test
+        # coverage reporting, as Bdb.set_continue calls sys.settrace(None).
+        if self.__debugger_used:
+            pdb.Pdb.set_continue(self)
+
+    def trace_dispatch(self, *args):
+        # Redirect stdout to the given stream.
+        save_stdout = sys.stdout
+        sys.stdout = self.__out
+        # Call Pdb's trace dispatch method.
+        try:
+            return pdb.Pdb.trace_dispatch(self, *args)
+        finally:
+            sys.stdout = save_stdout
+
+# [XX] Normalize with respect to os.path.pardir?
+def _module_relative_path(module, path):
+    if not inspect.ismodule(module):
+        raise TypeError, 'Expected a module: %r' % module
+    if path.startswith('/'):
+        raise ValueError, 'Module-relative files may not have absolute paths'
+
+    # Find the base directory for the path.
+    if hasattr(module, '__file__'):
+        # A normal module/package
+        basedir = os.path.split(module.__file__)[0]
+    elif module.__name__ == '__main__':
+        # An interactive session.
+        if len(sys.argv)>0 and sys.argv[0] != '':
+            basedir = os.path.split(sys.argv[0])[0]
+        else:
+            basedir = os.curdir
+    else:
+        # A module w/o __file__ (this includes builtins)
+        raise ValueError("Can't resolve paths relative to the module " +
+                         module + " (it has no __file__)")
+
+    # Combine the base directory and the path.
+    return os.path.join(basedir, *(path.split('/')))
+
+######################################################################
+## 2. Example & DocTest
+######################################################################
+## - An "example" is a <source, want> pair, where "source" is a
+##   fragment of source code, and "want" is the expected output for
+##   "source."  The Example class also includes information about
+##   where the example was extracted from.
+##
+## - A "doctest" is a collection of examples, typically extracted from
+##   a string (such as an object's docstring).  The DocTest class also
+##   includes information about where the string was extracted from.
+
+class Example:
+    """
+    A single doctest example, consisting of source code and expected
+    output.  `Example` defines the following attributes:
+
+      - source: A single Python statement, always ending with a newline.
+        The constructor adds a newline if needed.
+
+      - want: The expected output from running the source code (either
+        from stdout, or a traceback in case of exception).  `want` ends
+        with a newline unless it's empty, in which case it's an empty
+        string.  The constructor adds a newline if needed.
+
+      - exc_msg: The exception message generated by the example, if
+        the example is expected to generate an exception; or `None` if
+        it is not expected to generate an exception.  This exception
+        message is compared against the return value of
+        `traceback.format_exception_only()`.  `exc_msg` ends with a
+        newline unless it's `None`.  The constructor adds a newline
+        if needed.
+
+      - lineno: The line number within the DocTest string containing
+        this Example where the Example begins.  This line number is
+        zero-based, with respect to the beginning of the DocTest.
+
+      - indent: The example's indentation in the DocTest string.
+        I.e., the number of space characters that preceed the
+        example's first prompt.
+
+      - options: A dictionary mapping from option flags to True or
+        False, which is used to override default options for this
+        example.  Any option flags not contained in this dictionary
+        are left at their default value (as specified by the
+        DocTestRunner's optionflags).  By default, no options are set.
+    """
+    def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
+                 options=None):
+        # Normalize inputs.
+        if not source.endswith('\n'):
+            source += '\n'
+        if want and not want.endswith('\n'):
+            want += '\n'
+        if exc_msg is not None and not exc_msg.endswith('\n'):
+            exc_msg += '\n'
+        # Store properties.
+        self.source = source
+        self.want = want
+        self.lineno = lineno
+        self.indent = indent
+        if options is None: options = {}
+        self.options = options
+        self.exc_msg = exc_msg
+
+    def __eq__(self, other):
+        if type(self) is not type(other):
+            return NotImplemented
+
+        return self.source == other.source and \
+               self.want == other.want and \
+               self.lineno == other.lineno and \
+               self.indent == other.indent and \
+               self.options == other.options and \
+               self.exc_msg == other.exc_msg
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __hash__(self):
+        return hash((self.source, self.want, self.lineno, self.indent,
+                     self.exc_msg))
+
+
+class DocTest:
+    """
+    A collection of doctest examples that should be run in a single
+    namespace.  Each `DocTest` defines the following attributes:
+
+      - examples: the list of examples.
+
+      - globs: The namespace (aka globals) that the examples should
+        be run in.
+
+      - name: A name identifying the DocTest (typically, the name of
+        the object whose docstring this DocTest was extracted from).
+
+      - filename: The name of the file that this DocTest was extracted
+        from, or `None` if the filename is unknown.
+
+      - lineno: The line number within filename where this DocTest
+        begins, or `None` if the line number is unavailable.  This
+        line number is zero-based, with respect to the beginning of
+        the file.
+
+      - docstring: The string that the examples were extracted from,
+        or `None` if the string is unavailable.
+    """
+    def __init__(self, examples, globs, name, filename, lineno, docstring):
+        """
+        Create a new DocTest containing the given examples.  The
+        DocTest's globals are initialized with a copy of `globs`.
+        """
+        assert not isinstance(examples, basestring), \
+               "DocTest no longer accepts str; use DocTestParser instead"
+        self.examples = examples
+        self.docstring = docstring
+        self.globs = globs.copy()
+        self.name = name
+        self.filename = filename
+        self.lineno = lineno
+
+    def __repr__(self):
+        if len(self.examples) == 0:
+            examples = 'no examples'
+        elif len(self.examples) == 1:
+            examples = '1 example'
+        else:
+            examples = '%d examples' % len(self.examples)
+        return ('<DocTest %s from %s:%s (%s)>' %
+                (self.name, self.filename, self.lineno, examples))
+
+    def __eq__(self, other):
+        if type(self) is not type(other):
+            return NotImplemented
+
+        return self.examples == other.examples and \
+               self.docstring == other.docstring and \
+               self.globs == other.globs and \
+               self.name == other.name and \
+               self.filename == other.filename and \
+               self.lineno == other.lineno
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __hash__(self):
+        return hash((self.docstring, self.name, self.filename, self.lineno))
+
+    # This lets us sort tests by name:
+    def __cmp__(self, other):
+        if not isinstance(other, DocTest):
+            return -1
+        return cmp((self.name, self.filename, self.lineno, id(self)),
+                   (other.name, other.filename, other.lineno, id(other)))
+
+######################################################################
+## 3. DocTestParser
+######################################################################
+
+class DocTestParser:
+    """
+    A class used to parse strings containing doctest examples.
+    """
+    # This regular expression is used to find doctest examples in a
+    # string.  It defines three groups: `source` is the source code
+    # (including leading indentation and prompts); `indent` is the
+    # indentation of the first (PS1) line of the source code; and
+    # `want` is the expected output (including leading indentation).
+    _EXAMPLE_RE = re.compile(r'''
+        # Source consists of a PS1 line followed by zero or more PS2 lines.
+        (?P<source>
+            (?:^(?P<indent> [ ]*) >>>    .*)    # PS1 line
+            (?:\n           [ ]*  \.\.\. .*)*)  # PS2 lines
+        \n?
+        # Want consists of any non-blank lines that do not start with PS1.
+        (?P<want> (?:(?![ ]*$)    # Not a blank line
+                     (?![ ]*>>>)  # Not a line starting with PS1
+                     .*$\n?       # But any other line
+                  )*)
+        ''', re.MULTILINE | re.VERBOSE)
+
+    # A regular expression for handling `want` strings that contain
+    # expected exceptions.  It divides `want` into three pieces:
+    #    - the traceback header line (`hdr`)
+    #    - the traceback stack (`stack`)
+    #    - the exception message (`msg`), as generated by
+    #      traceback.format_exception_only()
+    # `msg` may have multiple lines.  We assume/require that the
+    # exception message is the first non-indented line starting with a word
+    # character following the traceback header line.
+    _EXCEPTION_RE = re.compile(r"""
+        # Grab the traceback header.  Different versions of Python have
+        # said different things on the first traceback line.
+        ^(?P<hdr> Traceback\ \(
+            (?: most\ recent\ call\ last
+            |   innermost\ last
+            ) \) :
+        )
+        \s* $                # toss trailing whitespace on the header.
+        (?P<stack> .*?)      # don't blink: absorb stuff until...
+        ^ (?P<msg> \w+ .*)   #     a line *starts* with alphanum.
+        """, re.VERBOSE | re.MULTILINE | re.DOTALL)
+
+    # A callable returning a true value iff its argument is a blank line
+    # or contains a single comment.
+    _IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match
+
+    def parse(self, string, name='<string>'):
+        """
+        Divide the given string into examples and intervening text,
+        and return them as a list of alternating Examples and strings.
+        Line numbers for the Examples are 0-based.  The optional
+        argument `name` is a name identifying this string, and is only
+        used for error messages.
+        """
+        string = string.expandtabs()
+        # If all lines begin with the same indentation, then strip it.
+        min_indent = self._min_indent(string)
+        if min_indent > 0:
+            string = '\n'.join([l[min_indent:] for l in string.split('\n')])
+
+        output = []
+        charno, lineno = 0, 0
+        # Find all doctest examples in the string:
+        for m in self._EXAMPLE_RE.finditer(string):
+            # Add the pre-example text to `output`.
+            output.append(string[charno:m.start()])
+            # Update lineno (lines before this example)
+            lineno += string.count('\n', charno, m.start())
+            # Extract info from the regexp match.
+            (source, options, want, exc_msg) = \
+                     self._parse_example(m, name, lineno)
+            # Create an Example, and add it to the list.
+            if not self._IS_BLANK_OR_COMMENT(source):
+                output.append( Example(source, want, exc_msg,
+                                    lineno=lineno,
+                                    indent=min_indent+len(m.group('indent')),
+                                    options=options) )
+            # Update lineno (lines inside this example)
+            lineno += string.count('\n', m.start(), m.end())
+            # Update charno.
+            charno = m.end()
+        # Add any remaining post-example text to `output`.
+        output.append(string[charno:])
+        return output
+
+    def get_doctest(self, string, globs, name, filename, lineno):
+        """
+        Extract all doctest examples from the given string, and
+        collect them into a `DocTest` object.
+
+        `globs`, `name`, `filename`, and `lineno` are attributes for
+        the new `DocTest` object.  See the documentation for `DocTest`
+        for more information.
+        """
+        return DocTest(self.get_examples(string, name), globs,
+                       name, filename, lineno, string)
+
+    def get_examples(self, string, name='<string>'):
+        """
+        Extract all doctest examples from the given string, and return
+        them as a list of `Example` objects.  Line numbers are
+        0-based, because it's most common in doctests that nothing
+        interesting appears on the same line as opening triple-quote,
+        and so the first interesting line is called \"line 1\" then.
+
+        The optional argument `name` is a name identifying this
+        string, and is only used for error messages.
+        """
+        return [x for x in self.parse(string, name)
+                if isinstance(x, Example)]
+
+    def _parse_example(self, m, name, lineno):
+        """
+        Given a regular expression match from `_EXAMPLE_RE` (`m`),
+        return a pair `(source, want)`, where `source` is the matched
+        example's source code (with prompts and indentation stripped);
+        and `want` is the example's expected output (with indentation
+        stripped).
+
+        `name` is the string's name, and `lineno` is the line number
+        where the example starts; both are used for error messages.
+        """
+        # Get the example's indentation level.
+        indent = len(m.group('indent'))
+
+        # Divide source into lines; check that they're properly
+        # indented; and then strip their indentation & prompts.
+        source_lines = m.group('source').split('\n')
+        self._check_prompt_blank(source_lines, indent, name, lineno)
+        self._check_prefix(source_lines[1:], ' '*indent + '.', name, lineno)
+        source = '\n'.join([sl[indent+4:] for sl in source_lines])
+
+        # Divide want into lines; check that it's properly indented; and
+        # then strip the indentation.  Spaces before the last newline should
+        # be preserved, so plain rstrip() isn't good enough.
+        want = m.group('want')
+        want_lines = want.split('\n')
+        if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
+            del want_lines[-1]  # forget final newline & spaces after it
+        self._check_prefix(want_lines, ' '*indent, name,
+                           lineno + len(source_lines))
+        want = '\n'.join([wl[indent:] for wl in want_lines])
+
+        # If `want` contains a traceback message, then extract it.
+        m = self._EXCEPTION_RE.match(want)
+        if m:
+            exc_msg = m.group('msg')
+        else:
+            exc_msg = None
+
+        # Extract options from the source.
+        options = self._find_options(source, name, lineno)
+
+        return source, options, want, exc_msg
+
+    # This regular expression looks for option directives in the
+    # source code of an example.  Option directives are comments
+    # starting with "doctest:".  Warning: this may give false
+    # positives for string-literals that contain the string
+    # "#doctest:".  Eliminating these false positives would require
+    # actually parsing the string; but we limit them by ignoring any
+    # line containing "#doctest:" that is *followed* by a quote mark.
+    _OPTION_DIRECTIVE_RE = re.compile(r'#\s*doctest:\s*([^\n\'"]*)$',
+                                      re.MULTILINE)
+
+    def _find_options(self, source, name, lineno):
+        """
+        Return a dictionary containing option overrides extracted from
+        option directives in the given source string.
+
+        `name` is the string's name, and `lineno` is the line number
+        where the example starts; both are used for error messages.
+        """
+        options = {}
+        # (note: with the current regexp, this will match at most once:)
+        for m in self._OPTION_DIRECTIVE_RE.finditer(source):
+            option_strings = m.group(1).replace(',', ' ').split()
+            for option in option_strings:
+                if (option[0] not in '+-' or
+                    option[1:] not in OPTIONFLAGS_BY_NAME):
+                    raise ValueError('line %r of the doctest for %s '
+                                     'has an invalid option: %r' %
+                                     (lineno+1, name, option))
+                flag = OPTIONFLAGS_BY_NAME[option[1:]]
+                options[flag] = (option[0] == '+')
+        if options and self._IS_BLANK_OR_COMMENT(source):
+            raise ValueError('line %r of the doctest for %s has an option '
+                             'directive on a line with no example: %r' %
+                             (lineno, name, source))
+        return options
+
+    # This regular expression finds the indentation of every non-blank
+    # line in a string.
+    _INDENT_RE = re.compile('^([ ]*)(?=\S)', re.MULTILINE)
+
+    def _min_indent(self, s):
+        "Return the minimum indentation of any non-blank line in `s`"
+        indents = [len(indent) for indent in self._INDENT_RE.findall(s)]
+        if len(indents) > 0:
+            return min(indents)
+        else:
+            return 0
+
+    def _check_prompt_blank(self, lines, indent, name, lineno):
+        """
+        Given the lines of a source string (including prompts and
+        leading indentation), check to make sure that every prompt is
+        followed by a space character.  If any line is not followed by
+        a space character, then raise ValueError.
+        """
+        for i, line in enumerate(lines):
+            if len(line) >= indent+4 and line[indent+3] != ' ':
+                raise ValueError('line %r of the docstring for %s '
+                                 'lacks blank after %s: %r' %
+                                 (lineno+i+1, name,
+                                  line[indent:indent+3], line))
+
+    def _check_prefix(self, lines, prefix, name, lineno):
+        """
+        Check that every line in the given list starts with the given
+        prefix; if any line does not, then raise a ValueError.
+        """
+        for i, line in enumerate(lines):
+            if line and not line.startswith(prefix):
+                raise ValueError('line %r of the docstring for %s has '
+                                 'inconsistent leading whitespace: %r' %
+                                 (lineno+i+1, name, line))
+
+
+######################################################################
+## 4. DocTest Finder
+######################################################################
+
+class DocTestFinder:
+    """
+    A class used to extract the DocTests that are relevant to a given
+    object, from its docstring and the docstrings of its contained
+    objects.  Doctests can currently be extracted from the following
+    object types: modules, functions, classes, methods, staticmethods,
+    classmethods, and properties.
+    """
+
+    def __init__(self, verbose=False, parser=DocTestParser(),
+                 recurse=True, exclude_empty=True):
+        """
+        Create a new doctest finder.
+
+        The optional argument `parser` specifies a class or
+        function that should be used to create new DocTest objects (or
+        objects that implement the same interface as DocTest).  The
+        signature for this factory function should match the signature
+        of the DocTest constructor.
+
+        If the optional argument `recurse` is false, then `find` will
+        only examine the given object, and not any contained objects.
+
+        If the optional argument `exclude_empty` is false, then `find`
+        will include tests for objects with empty docstrings.
+        """
+        self._parser = parser
+        self._verbose = verbose
+        self._recurse = recurse
+        self._exclude_empty = exclude_empty
+
+    def find(self, obj, name=None, module=None, globs=None, extraglobs=None):
+        """
+        Return a list of the DocTests that are defined by the given
+        object's docstring, or by any of its contained objects'
+        docstrings.
+
+        The optional parameter `module` is the module that contains
+        the given object.  If the module is not specified or is None, then
+        the test finder will attempt to automatically determine the
+        correct module.  The object's module is used:
+
+            - As a default namespace, if `globs` is not specified.
+            - To prevent the DocTestFinder from extracting DocTests
+              from objects that are imported from other modules.
+            - To find the name of the file containing the object.
+            - To help find the line number of the object within its
+              file.
+
+        Contained objects whose module does not match `module` are ignored.
+
+        If `module` is False, no attempt to find the module will be made.
+        This is obscure, of use mostly in tests:  if `module` is False, or
+        is None but cannot be found automatically, then all objects are
+        considered to belong to the (non-existent) module, so all contained
+        objects will (recursively) be searched for doctests.
+
+        The globals for each DocTest is formed by combining `globs`
+        and `extraglobs` (bindings in `extraglobs` override bindings
+        in `globs`).  A new copy of the globals dictionary is created
+        for each DocTest.  If `globs` is not specified, then it
+        defaults to the module's `__dict__`, if specified, or {}
+        otherwise.  If `extraglobs` is not specified, then it defaults
+        to {}.
+
+        """
+        # If name was not specified, then extract it from the object.
+        if name is None:
+            name = getattr(obj, '__name__', None)
+            if name is None:
+                raise ValueError("DocTestFinder.find: name must be given "
+                        "when obj.__name__ doesn't exist: %r" %
+                                 (type(obj),))
+
+        # Find the module that contains the given object (if obj is
+        # a module, then module=obj.).  Note: this may fail, in which
+        # case module will be None.
+        if module is False:
+            module = None
+        elif module is None:
+            module = inspect.getmodule(obj)
+
+        # Read the module's source code.  This is used by
+        # DocTestFinder._find_lineno to find the line number for a
+        # given object's docstring.
+        try:
+            file = inspect.getsourcefile(obj) or inspect.getfile(obj)
+            if module is not None:
+                # Supply the module globals in case the module was
+                # originally loaded via a PEP 302 loader and
+                # file is not a valid filesystem path
+                source_lines = linecache.getlines(file, module.__dict__)
+            else:
+                # No access to a loader, so assume it's a normal
+                # filesystem path
+                source_lines = linecache.getlines(file)
+            if not source_lines:
+                source_lines = None
+        except TypeError:
+            source_lines = None
+
+        # Initialize globals, and merge in extraglobs.
+        if globs is None:
+            if module is None:
+                globs = {}
+            else:
+                globs = module.__dict__.copy()
+        else:
+            globs = globs.copy()
+        if extraglobs is not None:
+            globs.update(extraglobs)
+        if '__name__' not in globs:
+            globs['__name__'] = '__main__'  # provide a default module name
+
+        # Recursively expore `obj`, extracting DocTests.
+        tests = []
+        self._find(tests, obj, name, module, source_lines, globs, {})
+        # Sort the tests by alpha order of names, for consistency in
+        # verbose-mode output.  This was a feature of doctest in Pythons
+        # <= 2.3 that got lost by accident in 2.4.  It was repaired in
+        # 2.4.4 and 2.5.
+        tests.sort()
+        return tests
+
+    def _from_module(self, module, object):
+        """
+        Return true if the given object is defined in the given
+        module.
+        """
+        if module is None:
+            return True
+        elif inspect.getmodule(object) is not None:
+            return module is inspect.getmodule(object)
+        elif inspect.isfunction(object):
+            return module.__dict__ is object.func_globals
+        elif inspect.isclass(object):
+            return module.__name__ == object.__module__
+        elif hasattr(object, '__module__'):
+            return module.__name__ == object.__module__
+        elif isinstance(object, property):
+            return True # [XX] no way not be sure.
+        else:
+            raise ValueError("object must be a class or function")
+
+    def _find(self, tests, obj, name, module, source_lines, globs, seen):
+        """
+        Find tests for the given object and any contained objects, and
+        add them to `tests`.
+        """
+        if self._verbose:
+            print 'Finding tests in %s' % name
+
+        # If we've already processed this object, then ignore it.
+        if id(obj) in seen:
+            return
+        seen[id(obj)] = 1
+
+        # Find a test for this object, and add it to the list of tests.
+        test = self._get_test(obj, name, module, globs, source_lines)
+        if test is not None:
+            tests.append(test)
+
+        # Look for tests in a module's contained objects.
+        if inspect.ismodule(obj) and self._recurse:
+            for valname, val in obj.__dict__.items():
+                valname = '%s.%s' % (name, valname)
+                # Recurse to functions & classes.
+                if ((inspect.isfunction(val) or inspect.isclass(val)) and
+                    self._from_module(module, val)):
+                    self._find(tests, val, valname, module, source_lines,
+                               globs, seen)
+
+        # Look for tests in a module's __test__ dictionary.
+        if inspect.ismodule(obj) and self._recurse:
+            for valname, val in getattr(obj, '__test__', {}).items():
+                if not isinstance(valname, basestring):
+                    raise ValueError("DocTestFinder.find: __test__ keys "
+                                     "must be strings: %r" %
+                                     (type(valname),))
+                if not (inspect.isfunction(val) or inspect.isclass(val) or
+                        inspect.ismethod(val) or inspect.ismodule(val) or
+                        isinstance(val, basestring)):
+                    raise ValueError("DocTestFinder.find: __test__ values "
+                                     "must be strings, functions, methods, "
+                                     "classes, or modules: %r" %
+                                     (type(val),))
+                valname = '%s.__test__.%s' % (name, valname)
+                self._find(tests, val, valname, module, source_lines,
+                           globs, seen)
+
+        # Look for tests in a class's contained objects.
+        if inspect.isclass(obj) and self._recurse:
+            for valname, val in obj.__dict__.items():
+                # Special handling for staticmethod/classmethod.
+                if isinstance(val, staticmethod):
+                    val = getattr(obj, valname)
+                if isinstance(val, classmethod):
+                    val = getattr(obj, valname).im_func
+
+                # Recurse to methods, properties, and nested classes.
+                if ((inspect.isfunction(val) or inspect.isclass(val) or
+                      isinstance(val, property)) and
+                      self._from_module(module, val)):
+                    valname = '%s.%s' % (name, valname)
+                    self._find(tests, val, valname, module, source_lines,
+                               globs, seen)
+
+    def _get_test(self, obj, name, module, globs, source_lines):
+        """
+        Return a DocTest for the given object, if it defines a docstring;
+        otherwise, return None.
+        """
+        # Extract the object's docstring.  If it doesn't have one,
+        # then return None (no test for this object).
+        if isinstance(obj, basestring):
+            docstring = obj
+        else:
+            try:
+                if obj.__doc__ is None:
+                    docstring = ''
+                else:
+                    docstring = obj.__doc__
+                    if not isinstance(docstring, basestring):
+                        docstring = str(docstring)
+            except (TypeError, AttributeError):
+                docstring = ''
+
+        # Find the docstring's location in the file.
+        lineno = self._find_lineno(obj, source_lines)
+
+        # Don't bother if the docstring is empty.
+        if self._exclude_empty and not docstring:
+            return None
+
+        # Return a DocTest for this object.
+        if module is None:
+            filename = None
+        else:
+            filename = getattr(module, '__file__', module.__name__)
+            if filename[-4:] in (".pyc", ".pyo"):
+                filename = filename[:-1]
+            elif filename.endswith('$py.class'):
+                filename = '%s.py' % filename[:-9]
+        return self._parser.get_doctest(docstring, globs, name,
+                                        filename, lineno)
+
+    def _find_lineno(self, obj, source_lines):
+        """
+        Return a line number of the given object's docstring.  Note:
+        this method assumes that the object has a docstring.
+        """
+        lineno = None
+
+        # Find the line number for modules.
+        if inspect.ismodule(obj):
+            lineno = 0
+
+        # Find the line number for classes.
+        # Note: this could be fooled if a class is defined multiple
+        # times in a single file.
+        if inspect.isclass(obj):
+            if source_lines is None:
+                return None
+            pat = re.compile(r'^\s*class\s*%s\b' %
+                             getattr(obj, '__name__', '-'))
+            for i, line in enumerate(source_lines):
+                if pat.match(line):
+                    lineno = i
+                    break
+
+        # Find the line number for functions & methods.
+        if inspect.ismethod(obj): obj = obj.im_func
+        if inspect.isfunction(obj): obj = obj.func_code
+        if inspect.istraceback(obj): obj = obj.tb_frame
+        if inspect.isframe(obj): obj = obj.f_code
+        if inspect.iscode(obj):
+            lineno = getattr(obj, 'co_firstlineno', None)-1
+
+        # Find the line number where the docstring starts.  Assume
+        # that it's the first line that begins with a quote mark.
+        # Note: this could be fooled by a multiline function
+        # signature, where a continuation line begins with a quote
+        # mark.
+        if lineno is not None:
+            if source_lines is None:
+                return lineno+1
+            pat = re.compile('(^|.*:)\s*\w*("|\')')
+            for lineno in range(lineno, len(source_lines)):
+                if pat.match(source_lines[lineno]):
+                    return lineno
+
+        # We couldn't find the line number.
+        return None
+
+######################################################################
+## 5. DocTest Runner
+######################################################################
+
+class DocTestRunner:
+    """
+    A class used to run DocTest test cases, and accumulate statistics.
+    The `run` method is used to process a single DocTest case.  It
+    returns a tuple `(f, t)`, where `t` is the number of test cases
+    tried, and `f` is the number of test cases that failed.
+
+        >>> tests = DocTestFinder().find(_TestClass)
+        >>> runner = DocTestRunner(verbose=False)
+        >>> tests.sort(key = lambda test: test.name)
+        >>> for test in tests:
+        ...     print test.name, '->', runner.run(test)
+        _TestClass -> TestResults(failed=0, attempted=2)
+        _TestClass.__init__ -> TestResults(failed=0, attempted=2)
+        _TestClass.get -> TestResults(failed=0, attempted=2)
+        _TestClass.square -> TestResults(failed=0, attempted=1)
+
+    The `summarize` method prints a summary of all the test cases that
+    have been run by the runner, and returns an aggregated `(f, t)`
+    tuple:
+
+        >>> runner.summarize(verbose=1)
+        4 items passed all tests:
+           2 tests in _TestClass
+           2 tests in _TestClass.__init__
+           2 tests in _TestClass.get
+           1 tests in _TestClass.square
+        7 tests in 4 items.
+        7 passed and 0 failed.
+        Test passed.
+        TestResults(failed=0, attempted=7)
+
+    The aggregated number of tried examples and failed examples is
+    also available via the `tries` and `failures` attributes:
+
+        >>> runner.tries
+        7
+        >>> runner.failures
+        0
+
+    The comparison between expected outputs and actual outputs is done
+    by an `OutputChecker`.  This comparison may be customized with a
+    number of option flags; see the documentation for `testmod` for
+    more information.  If the option flags are insufficient, then the
+    comparison may also be customized by passing a subclass of
+    `OutputChecker` to the constructor.
+
+    The test runner's display output can be controlled in two ways.
+    First, an output function (`out) can be passed to
+    `TestRunner.run`; this function will be called with strings that
+    should be displayed.  It defaults to `sys.stdout.write`.  If
+    capturing the output is not sufficient, then the display output
+    can be also customized by subclassing DocTestRunner, and
+    overriding the methods `report_start`, `report_success`,
+    `report_unexpected_exception`, and `report_failure`.
+    """
+    # This divider string is used to separate failure messages, and to
+    # separate sections of the summary.
+    DIVIDER = "*" * 70
+
+    def __init__(self, checker=None, verbose=None, optionflags=0):
+        """
+        Create a new test runner.
+
+        Optional keyword arg `checker` is the `OutputChecker` that
+        should be used to compare the expected outputs and actual
+        outputs of doctest examples.
+
+        Optional keyword arg 'verbose' prints lots of stuff if true,
+        only failures if false; by default, it's true iff '-v' is in
+        sys.argv.
+
+        Optional argument `optionflags` can be used to control how the
+        test runner compares expected output to actual output, and how
+        it displays failures.  See the documentation for `testmod` for
+        more information.
+        """
+        self._checker = checker or OutputChecker()
+        if verbose is None:
+            verbose = '-v' in sys.argv
+        self._verbose = verbose
+        self.optionflags = optionflags
+        self.original_optionflags = optionflags
+
+        # Keep track of the examples we've run.
+        self.tries = 0
+        self.failures = 0
+        self._name2ft = {}
+
+        # Create a fake output target for capturing doctest output.
+        self._fakeout = _SpoofOut()
+
+    #/////////////////////////////////////////////////////////////////
+    # Reporting methods
+    #/////////////////////////////////////////////////////////////////
+
+    def report_start(self, out, test, example):
+        """
+        Report that the test runner is about to process the given
+        example.  (Only displays a message if verbose=True)
+        """
+        if self._verbose:
+            if example.want:
+                out('Trying:\n' + _indent(example.source) +
+                    'Expecting:\n' + _indent(example.want))
+            else:
+                out('Trying:\n' + _indent(example.source) +
+                    'Expecting nothing\n')
+
+    def report_success(self, out, test, example, got):
+        """
+        Report that the given example ran successfully.  (Only
+        displays a message if verbose=True)
+        """
+        if self._verbose:
+            out("ok\n")
+
+    def report_failure(self, out, test, example, got):
+        """
+        Report that the given example failed.
+        """
+        out(self._failure_header(test, example) +
+            self._checker.output_difference(example, got, self.optionflags))
+
+    def report_unexpected_exception(self, out, test, example, exc_info):
+        """
+        Report that the given example raised an unexpected exception.
+        """
+        out(self._failure_header(test, example) +
+            'Exception raised:\n' + _indent(_exception_traceback(exc_info)))
+
+    def _failure_header(self, test, example):
+        out = [self.DIVIDER]
+        if test.filename:
+            if test.lineno is not None and example.lineno is not None:
+                lineno = test.lineno + example.lineno + 1
+            else:
+                lineno = '?'
+            out.append('File "%s", line %s, in %s' %
+                       (test.filename, lineno, test.name))
+        else:
+            out.append('Line %s, in %s' % (example.lineno+1, test.name))
+        out.append('Failed example:')
+        source = example.source
+        out.append(_indent(source))
+        return '\n'.join(out)
+
+    #/////////////////////////////////////////////////////////////////
+    # DocTest Running
+    #/////////////////////////////////////////////////////////////////
+
+    def __run(self, test, compileflags, out):
+        """
+        Run the examples in `test`.  Write the outcome of each example
+        with one of the `DocTestRunner.report_*` methods, using the
+        writer function `out`.  `compileflags` is the set of compiler
+        flags that should be used to execute examples.  Return a tuple
+        `(f, t)`, where `t` is the number of examples tried, and `f`
+        is the number of examples that failed.  The examples are run
+        in the namespace `test.globs`.
+        """
+        # Keep track of the number of failures and tries.
+        failures = tries = 0
+
+        # Save the option flags (since option directives can be used
+        # to modify them).
+        original_optionflags = self.optionflags
+
+        SUCCESS, FAILURE, BOOM = range(3) # `outcome` state
+
+        check = self._checker.check_output
+
+        # Process each example.
+        for examplenum, example in enumerate(test.examples):
+
+            # If REPORT_ONLY_FIRST_FAILURE is set, then suppress
+            # reporting after the first failure.
+            quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
+                     failures > 0)
+
+            # Merge in the example's options.
+            self.optionflags = original_optionflags
+            if example.options:
+                for (optionflag, val) in example.options.items():
+                    if val:
+                        self.optionflags |= optionflag
+                    else:
+                        self.optionflags &= ~optionflag
+
+            # If 'SKIP' is set, then skip this example.
+            if self.optionflags & SKIP:
+                continue
+
+            # Record that we started this example.
+            tries += 1
+            if not quiet:
+                self.report_start(out, test, example)
+
+            # Use a special filename for compile(), so we can retrieve
+            # the source code during interactive debugging (see
+            # __patched_linecache_getlines).
+            filename = '<doctest %s[%d]>' % (test.name, examplenum)
+
+            # Run the example in the given context (globs), and record
+            # any exception that gets raised.  (But don't intercept
+            # keyboard interrupts.)
+            try:
+                # Don't blink!  This is where the user's code gets run.
+                exec compile(example.source, filename, "single",
+                             compileflags, 1) in test.globs
+                self.debugger.set_continue() # ==== Example Finished ====
+                exception = None
+            except KeyboardInterrupt:
+                raise
+            except:
+                exception = sys.exc_info()
+                self.debugger.set_continue() # ==== Example Finished ====
+
+            got = self._fakeout.getvalue()  # the actual output
+            self._fakeout.truncate(0)
+            outcome = FAILURE   # guilty until proved innocent or insane
+
+            # If the example executed without raising any exceptions,
+            # verify its output.
+            if exception is None:
+                if check(example.want, got, self.optionflags):
+                    outcome = SUCCESS
+
+            # The example raised an exception:  check if it was expected.
+            else:
+                exc_info = sys.exc_info()
+                exc_msg = traceback.format_exception_only(*exc_info[:2])[-1]
+                if not quiet:
+                    got += _exception_traceback(exc_info)
+
+                # If `example.exc_msg` is None, then we weren't expecting
+                # an exception.
+                if example.exc_msg is None:
+                    outcome = BOOM
+
+                # We expected an exception:  see whether it matches.
+                elif check(example.exc_msg, exc_msg, self.optionflags):
+                    outcome = SUCCESS
+
+                # Another chance if they didn't care about the detail.
+                elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
+                    m1 = re.match(r'(?:[^:]*\.)?([^:]*:)', example.exc_msg)
+                    m2 = re.match(r'(?:[^:]*\.)?([^:]*:)', exc_msg)
+                    if m1 and m2 and check(m1.group(1), m2.group(1),
+                                           self.optionflags):
+                        outcome = SUCCESS
+
+            # Report the outcome.
+            if outcome is SUCCESS:
+                if not quiet:
+                    self.report_success(out, test, example, got)
+            elif outcome is FAILURE:
+                if not quiet:
+                    self.report_failure(out, test, example, got)
+                failures += 1
+            elif outcome is BOOM:
+                if not quiet:
+                    self.report_unexpected_exception(out, test, example,
+                                                     exc_info)
+                failures += 1
+            else:
+                assert False, ("unknown outcome", outcome)
+
+        # Restore the option flags (in case they were modified)
+        self.optionflags = original_optionflags
+
+        # Record and return the number of failures and tries.
+        self.__record_outcome(test, failures, tries)
+        return TestResults(failures, tries)
+
+    def __record_outcome(self, test, f, t):
+        """
+        Record the fact that the given DocTest (`test`) generated `f`
+        failures out of `t` tried examples.
+        """
+        f2, t2 = self._name2ft.get(test.name, (0,0))
+        self._name2ft[test.name] = (f+f2, t+t2)
+        self.failures += f
+        self.tries += t
+
+    __LINECACHE_FILENAME_RE = re.compile(r'<doctest '
+                                         r'(?P<name>.+)'
+                                         r'\[(?P<examplenum>\d+)\]>$')
+    def __patched_linecache_getlines(self, filename, module_globals=None):
+        m = self.__LINECACHE_FILENAME_RE.match(filename)
+        if m and m.group('name') == self.test.name:
+            example = self.test.examples[int(m.group('examplenum'))]
+            source = example.source
+            if isinstance(source, unicode):
+                source = source.encode('ascii', 'backslashreplace')
+            return source.splitlines(True)
+        else:
+            return self.save_linecache_getlines(filename, module_globals)
+
+    def run(self, test, compileflags=None, out=None, clear_globs=True):
+        """
+        Run the examples in `test`, and display the results using the
+        writer function `out`.
+
+        The examples are run in the namespace `test.globs`.  If
+        `clear_globs` is true (the default), then this namespace will
+        be cleared after the test runs, to help with garbage
+        collection.  If you would like to examine the namespace after
+        the test completes, then use `clear_globs=False`.
+
+        `compileflags` gives the set of flags that should be used by
+        the Python compiler when running the examples.  If not
+        specified, then it will default to the set of future-import
+        flags that apply to `globs`.
+
+        The output of each example is checked using
+        `DocTestRunner.check_output`, and the results are formatted by
+        the `DocTestRunner.report_*` methods.
+        """
+        self.test = test
+
+        if compileflags is None:
+            compileflags = _extract_future_flags(test.globs)
+
+        save_stdout = sys.stdout
+        if out is None:
+            out = save_stdout.write
+        sys.stdout = self._fakeout
+
+        # Patch pdb.set_trace to restore sys.stdout during interactive
+        # debugging (so it's not still redirected to self._fakeout).
+        # Note that the interactive output will go to *our*
+        # save_stdout, even if that's not the real sys.stdout; this
+        # allows us to write test cases for the set_trace behavior.
+        save_set_trace = pdb.set_trace
+        self.debugger = _OutputRedirectingPdb(save_stdout)
+        self.debugger.reset()
+        pdb.set_trace = self.debugger.set_trace
+
+        # Patch linecache.getlines, so we can see the example's source
+        # when we're inside the debugger.
+        self.save_linecache_getlines = linecache.getlines
+        linecache.getlines = self.__patched_linecache_getlines
+
+        # Make sure sys.displayhook just prints the value to stdout
+        save_displayhook = sys.displayhook
+        sys.displayhook = sys.__displayhook__
+
+        try:
+            return self.__run(test, compileflags, out)
+        finally:
+            sys.stdout = save_stdout
+            pdb.set_trace = save_set_trace
+            linecache.getlines = self.save_linecache_getlines
+            sys.displayhook = save_displayhook
+            if clear_globs:
+                test.globs.clear()
+
+    #/////////////////////////////////////////////////////////////////
+    # Summarization
+    #/////////////////////////////////////////////////////////////////
+    def summarize(self, verbose=None):
+        """
+        Print a summary of all the test cases that have been run by
+        this DocTestRunner, and return a tuple `(f, t)`, where `f` is
+        the total number of failed examples, and `t` is the total
+        number of tried examples.
+
+        The optional `verbose` argument controls how detailed the
+        summary is.  If the verbosity is not specified, then the
+        DocTestRunner's verbosity is used.
+        """
+        if verbose is None:
+            verbose = self._verbose
+        notests = []
+        passed = []
+        failed = []
+        totalt = totalf = 0
+        for x in self._name2ft.items():
+            name, (f, t) = x
+            assert f <= t
+            totalt += t
+            totalf += f
+            if t == 0:
+                notests.append(name)
+            elif f == 0:
+                passed.append( (name, t) )
+            else:
+                failed.append(x)
+        if verbose:
+            if notests:
+                print len(notests), "items had no tests:"
+                notests.sort()
+                for thing in notests:
+                    print "   ", thing
+            if passed:
+                print len(passed), "items passed all tests:"
+                passed.sort()
+                for thing, count in passed:
+                    print " %3d tests in %s" % (count, thing)
+        if failed:
+            print self.DIVIDER
+            print len(failed), "items had failures:"
+            failed.sort()
+            for thing, (f, t) in failed:
+                print " %3d of %3d in %s" % (f, t, thing)
+        if verbose:
+            print totalt, "tests in", len(self._name2ft), "items."
+            print totalt - totalf, "passed and", totalf, "failed."
+        if totalf:
+            print "***Test Failed***", totalf, "failures."
+        elif verbose:
+            print "Test passed."
+        return TestResults(totalf, totalt)
+
+    #/////////////////////////////////////////////////////////////////
+    # Backward compatibility cruft to maintain doctest.master.
+    #/////////////////////////////////////////////////////////////////
+    def merge(self, other):
+        d = self._name2ft
+        for name, (f, t) in other._name2ft.items():
+            if name in d:
+                # Don't print here by default, since doing
+                #     so breaks some of the buildbots
+                #print "*** DocTestRunner.merge: '" + name + "' in both" \
+                #    " testers; summing outcomes."
+                f2, t2 = d[name]
+                f = f + f2
+                t = t + t2
+            d[name] = f, t
+
+class OutputChecker:
+    """
+    A class used to check the whether the actual output from a doctest
+    example matches the expected output.  `OutputChecker` defines two
+    methods: `check_output`, which compares a given pair of outputs,
+    and returns true if they match; and `output_difference`, which
+    returns a string describing the differences between two outputs.
+    """
+    def check_output(self, want, got, optionflags):
+        """
+        Return True iff the actual output from an example (`got`)
+        matches the expected output (`want`).  These strings are
+        always considered to match if they are identical; but
+        depending on what option flags the test runner is using,
+        several non-exact match types are also possible.  See the
+        documentation for `TestRunner` for more information about
+        option flags.
+        """
+        # Handle the common case first, for efficiency:
+        # if they're string-identical, always return true.
+        if got == want:
+            return True
+
+        # The values True and False replaced 1 and 0 as the return
+        # value for boolean comparisons in Python 2.3.
+        if not (optionflags & DONT_ACCEPT_TRUE_FOR_1):
+            if (got,want) == ("True\n", "1\n"):
+                return True
+            if (got,want) == ("False\n", "0\n"):
+                return True
+
+        # <BLANKLINE> can be used as a special sequence to signify a
+        # blank line, unless the DONT_ACCEPT_BLANKLINE flag is used.
+        if not (optionflags & DONT_ACCEPT_BLANKLINE):
+            # Replace <BLANKLINE> in want with a blank line.
+            want = re.sub('(?m)^%s\s*?$' % re.escape(BLANKLINE_MARKER),
+                          '', want)
+            # If a line in got contains only spaces, then remove the
+            # spaces.
+            got = re.sub('(?m)^\s*?$', '', got)
+            if got == want:
+                return True
+
+        # This flag causes doctest to ignore any differences in the
+        # contents of whitespace strings.  Note that this can be used
+        # in conjunction with the ELLIPSIS flag.
+        if optionflags & NORMALIZE_WHITESPACE:
+            got = ' '.join(got.split())
+            want = ' '.join(want.split())
+            if got == want:
+                return True
+
+        # The ELLIPSIS flag says to let the sequence "..." in `want`
+        # match any substring in `got`.
+        if optionflags & ELLIPSIS:
+            if _ellipsis_match(want, got):
+                return True
+
+        # We didn't find any match; return false.
+        return False
+
+    # Should we do a fancy diff?
+    def _do_a_fancy_diff(self, want, got, optionflags):
+        # Not unless they asked for a fancy diff.
+        if not optionflags & (REPORT_UDIFF |
+                              REPORT_CDIFF |
+                              REPORT_NDIFF):
+            return False
+
+        # If expected output uses ellipsis, a meaningful fancy diff is
+        # too hard ... or maybe not.  In two real-life failures Tim saw,
+        # a diff was a major help anyway, so this is commented out.
+        # [todo] _ellipsis_match() knows which pieces do and don't match,
+        # and could be the basis for a kick-ass diff in this case.
+        ##if optionflags & ELLIPSIS and ELLIPSIS_MARKER in want:
+        ##    return False
+
+        # ndiff does intraline difference marking, so can be useful even
+        # for 1-line differences.
+        if optionflags & REPORT_NDIFF:
+            return True
+
+        # The other diff types need at least a few lines to be helpful.
+        return want.count('\n') > 2 and got.count('\n') > 2
+
+    def output_difference(self, example, got, optionflags):
+        """
+        Return a string describing the differences between the
+        expected output for a given example (`example`) and the actual
+        output (`got`).  `optionflags` is the set of option flags used
+        to compare `want` and `got`.
+        """
+        want = example.want
+        # If <BLANKLINE>s are being used, then replace blank lines
+        # with <BLANKLINE> in the actual output string.
+        if not (optionflags & DONT_ACCEPT_BLANKLINE):
+            got = re.sub('(?m)^[ ]*(?=\n)', BLANKLINE_MARKER, got)
+
+        # Check if we should use diff.
+        if self._do_a_fancy_diff(want, got, optionflags):
+            # Split want & got into lines.
+            want_lines = want.splitlines(True)  # True == keep line ends
+            got_lines = got.splitlines(True)
+            # Use difflib to find their differences.
+            if optionflags & REPORT_UDIFF:
+                diff = difflib.unified_diff(want_lines, got_lines, n=2)
+                diff = list(diff)[2:] # strip the diff header
+                kind = 'unified diff with -expected +actual'
+            elif optionflags & REPORT_CDIFF:
+                diff = difflib.context_diff(want_lines, got_lines, n=2)
+                diff = list(diff)[2:] # strip the diff header
+                kind = 'context diff with expected followed by actual'
+            elif optionflags & REPORT_NDIFF:
+                engine = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
+                diff = list(engine.compare(want_lines, got_lines))
+                kind = 'ndiff with -expected +actual'
+            else:
+                assert 0, 'Bad diff option'
+            # Remove trailing whitespace on diff output.
+            diff = [line.rstrip() + '\n' for line in diff]
+            return 'Differences (%s):\n' % kind + _indent(''.join(diff))
+
+        # If we're not using diff, then simply list the expected
+        # output followed by the actual output.
+        if want and got:
+            return 'Expected:\n%sGot:\n%s' % (_indent(want), _indent(got))
+        elif want:
+            return 'Expected:\n%sGot nothing\n' % _indent(want)
+        elif got:
+            return 'Expected nothing\nGot:\n%s' % _indent(got)
+        else:
+            return 'Expected nothing\nGot nothing\n'
+
+class DocTestFailure(Exception):
+    """A DocTest example has failed in debugging mode.
+
+    The exception instance has variables:
+
+    - test: the DocTest object being run
+
+    - example: the Example object that failed
+
+    - got: the actual output
+    """
+    def __init__(self, test, example, got):
+        self.test = test
+        self.example = example
+        self.got = got
+
+    def __str__(self):
+        return str(self.test)
+
+class UnexpectedException(Exception):
+    """A DocTest example has encountered an unexpected exception
+
+    The exception instance has variables:
+
+    - test: the DocTest object being run
+
+    - example: the Example object that failed
+
+    - exc_info: the exception info
+    """
+    def __init__(self, test, example, exc_info):
+        self.test = test
+        self.example = example
+        self.exc_info = exc_info
+
+    def __str__(self):
+        return str(self.test)
+
+class DebugRunner(DocTestRunner):
+    r"""Run doc tests but raise an exception as soon as there is a failure.
+
+       If an unexpected exception occurs, an UnexpectedException is raised.
+       It contains the test, the example, and the original exception:
+
+         >>> runner = DebugRunner(verbose=False)
+         >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42',
+         ...                                    {}, 'foo', 'foo.py', 0)
+         >>> try:
+         ...     runner.run(test)
+         ... except UnexpectedException, failure:
+         ...     pass
+
+         >>> failure.test is test
+         True
+
+         >>> failure.example.want
+         '42\n'
+
+         >>> exc_info = failure.exc_info
+         >>> raise exc_info[0], exc_info[1], exc_info[2]
+         Traceback (most recent call last):
+         ...
+         KeyError
+
+       We wrap the original exception to give the calling application
+       access to the test and example information.
+
+       If the output doesn't match, then a DocTestFailure is raised:
+
+         >>> test = DocTestParser().get_doctest('''
+         ...      >>> x = 1
+         ...      >>> x
+         ...      2
+         ...      ''', {}, 'foo', 'foo.py', 0)
+
+         >>> try:
+         ...    runner.run(test)
+         ... except DocTestFailure, failure:
+         ...    pass
+
+       DocTestFailure objects provide access to the test:
+
+         >>> failure.test is test
+         True
+
+       As well as to the example:
+
+         >>> failure.example.want
+         '2\n'
+
+       and the actual output:
+
+         >>> failure.got
+         '1\n'
+
+       If a failure or error occurs, the globals are left intact:
+
+         >>> if '__builtins__' in test.globs:
+         ...     del test.globs['__builtins__']
+         >>> test.globs
+         {'x': 1}
+
+         >>> test = DocTestParser().get_doctest('''
+         ...      >>> x = 2
+         ...      >>> raise KeyError
+         ...      ''', {}, 'foo', 'foo.py', 0)
+
+         >>> runner.run(test)
+         Traceback (most recent call last):
+         ...
+         UnexpectedException: <DocTest foo from foo.py:0 (2 examples)>
+
+         >>> if '__builtins__' in test.globs:
+         ...     del test.globs['__builtins__']
+         >>> test.globs
+         {'x': 2}
+
+       But the globals are cleared if there is no error:
+
+         >>> test = DocTestParser().get_doctest('''
+         ...      >>> x = 2
+         ...      ''', {}, 'foo', 'foo.py', 0)
+
+         >>> runner.run(test)
+         TestResults(failed=0, attempted=1)
+
+         >>> test.globs
+         {}
+
+       """
+
+    def run(self, test, compileflags=None, out=None, clear_globs=True):
+        r = DocTestRunner.run(self, test, compileflags, out, False)
+        if clear_globs:
+            test.globs.clear()
+        return r
+
+    def report_unexpected_exception(self, out, test, example, exc_info):
+        raise UnexpectedException(test, example, exc_info)
+
+    def report_failure(self, out, test, example, got):
+        raise DocTestFailure(test, example, got)
+
+######################################################################
+## 6. Test Functions
+######################################################################
+# These should be backwards compatible.
+
+# For backward compatibility, a global instance of a DocTestRunner
+# class, updated by testmod.
+master = None
+
+def testmod(m=None, name=None, globs=None, verbose=None,
+            report=True, optionflags=0, extraglobs=None,
+            raise_on_error=False, exclude_empty=False):
+    """m=None, name=None, globs=None, verbose=None, report=True,
+       optionflags=0, extraglobs=None, raise_on_error=False,
+       exclude_empty=False
+
+    Test examples in docstrings in functions and classes reachable
+    from module m (or the current module if m is not supplied), starting
+    with m.__doc__.
+
+    Also test examples reachable from dict m.__test__ if it exists and is
+    not None.  m.__test__ maps names to functions, classes and strings;
+    function and class docstrings are tested even if the name is private;
+    strings are tested directly, as if they were docstrings.
+
+    Return (#failures, #tests).
+
+    See help(doctest) for an overview.
+
+    Optional keyword arg "name" gives the name of the module; by default
+    use m.__name__.
+
+    Optional keyword arg "globs" gives a dict to be used as the globals
+    when executing examples; by default, use m.__dict__.  A copy of this
+    dict is actually used for each docstring, so that each docstring's
+    examples start with a clean slate.
+
+    Optional keyword arg "extraglobs" gives a dictionary that should be
+    merged into the globals that are used to execute examples.  By
+    default, no extra globals are used.  This is new in 2.4.
+
+    Optional keyword arg "verbose" prints lots of stuff if true, prints
+    only failures if false; by default, it's true iff "-v" is in sys.argv.
+
+    Optional keyword arg "report" prints a summary at the end when true,
+    else prints nothing at the end.  In verbose mode, the summary is
+    detailed, else very brief (in fact, empty if all tests passed).
+
+    Optional keyword arg "optionflags" or's together module constants,
+    and defaults to 0.  This is new in 2.3.  Possible values (see the
+    docs for details):
+
+        DONT_ACCEPT_TRUE_FOR_1
+        DONT_ACCEPT_BLANKLINE
+        NORMALIZE_WHITESPACE
+        ELLIPSIS
+        SKIP
+        IGNORE_EXCEPTION_DETAIL
+        REPORT_UDIFF
+        REPORT_CDIFF
+        REPORT_NDIFF
+        REPORT_ONLY_FIRST_FAILURE
+
+    Optional keyword arg "raise_on_error" raises an exception on the
+    first unexpected exception or failure. This allows failures to be
+    post-mortem debugged.
+
+    Advanced tomfoolery:  testmod runs methods of a local instance of
+    class doctest.Tester, then merges the results into (or creates)
+    global Tester instance doctest.master.  Methods of doctest.master
+    can be called directly too, if you want to do something unusual.
+    Passing report=0 to testmod is especially useful then, to delay
+    displaying a summary.  Invoke doctest.master.summarize(verbose)
+    when you're done fiddling.
+    """
+    global master
+
+    # If no module was given, then use __main__.
+    if m is None:
+        # DWA - m will still be None if this wasn't invoked from the command
+        # line, in which case the following TypeError is about as good an error
+        # as we should expect
+        m = sys.modules.get('__main__')
+
+    # Check that we were actually given a module.
+    if not inspect.ismodule(m):
+        raise TypeError("testmod: module required; %r" % (m,))
+
+    # If no name was given, then use the module's name.
+    if name is None:
+        name = m.__name__
+
+    # Find, parse, and run all tests in the given module.
+    finder = DocTestFinder(exclude_empty=exclude_empty)
+
+    if raise_on_error:
+        runner = DebugRunner(verbose=verbose, optionflags=optionflags)
+    else:
+        runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+
+    for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
+        runner.run(test)
+
+    if report:
+        runner.summarize()
+
+    if master is None:
+        master = runner
+    else:
+        master.merge(runner)
+
+    return TestResults(runner.failures, runner.tries)
+
+def testfile(filename, module_relative=True, name=None, package=None,
+             globs=None, verbose=None, report=True, optionflags=0,
+             extraglobs=None, raise_on_error=False, parser=DocTestParser(),
+             encoding=None):
+    """
+    Test examples in the given file.  Return (#failures, #tests).
+
+    Optional keyword arg "module_relative" specifies how filenames
+    should be interpreted:
+
+      - If "module_relative" is True (the default), then "filename"
+         specifies a module-relative path.  By default, this path is
+         relative to the calling module's directory; but if the
+         "package" argument is specified, then it is relative to that
+         package.  To ensure os-independence, "filename" should use
+         "/" characters to separate path segments, and should not
+         be an absolute path (i.e., it may not begin with "/").
+
+      - If "module_relative" is False, then "filename" specifies an
+        os-specific path.  The path may be absolute or relative (to
+        the current working directory).
+
+    Optional keyword arg "name" gives the name of the test; by default
+    use the file's basename.
+
+    Optional keyword argument "package" is a Python package or the
+    name of a Python package whose directory should be used as the
+    base directory for a module relative filename.  If no package is
+    specified, then the calling module's directory is used as the base
+    directory for module relative filenames.  It is an error to
+    specify "package" if "module_relative" is False.
+
+    Optional keyword arg "globs" gives a dict to be used as the globals
+    when executing examples; by default, use {}.  A copy of this dict
+    is actually used for each docstring, so that each docstring's
+    examples start with a clean slate.
+
+    Optional keyword arg "extraglobs" gives a dictionary that should be
+    merged into the globals that are used to execute examples.  By
+    default, no extra globals are used.
+
+    Optional keyword arg "verbose" prints lots of stuff if true, prints
+    only failures if false; by default, it's true iff "-v" is in sys.argv.
+
+    Optional keyword arg "report" prints a summary at the end when true,
+    else prints nothing at the end.  In verbose mode, the summary is
+    detailed, else very brief (in fact, empty if all tests passed).
+
+    Optional keyword arg "optionflags" or's together module constants,
+    and defaults to 0.  Possible values (see the docs for details):
+
+        DONT_ACCEPT_TRUE_FOR_1
+        DONT_ACCEPT_BLANKLINE
+        NORMALIZE_WHITESPACE
+        ELLIPSIS
+        SKIP
+        IGNORE_EXCEPTION_DETAIL
+        REPORT_UDIFF
+        REPORT_CDIFF
+        REPORT_NDIFF
+        REPORT_ONLY_FIRST_FAILURE
+
+    Optional keyword arg "raise_on_error" raises an exception on the
+    first unexpected exception or failure. This allows failures to be
+    post-mortem debugged.
+
+    Optional keyword arg "parser" specifies a DocTestParser (or
+    subclass) that should be used to extract tests from the files.
+
+    Optional keyword arg "encoding" specifies an encoding that should
+    be used to convert the file to unicode.
+
+    Advanced tomfoolery:  testmod runs methods of a local instance of
+    class doctest.Tester, then merges the results into (or creates)
+    global Tester instance doctest.master.  Methods of doctest.master
+    can be called directly too, if you want to do something unusual.
+    Passing report=0 to testmod is especially useful then, to delay
+    displaying a summary.  Invoke doctest.master.summarize(verbose)
+    when you're done fiddling.
+    """
+    global master
+
+    if package and not module_relative:
+        raise ValueError("Package may only be specified for module-"
+                         "relative paths.")
+
+    # Relativize the path
+    text, filename = _load_testfile(filename, package, module_relative)
+
+    # If no name was given, then use the file's name.
+    if name is None:
+        name = os.path.basename(filename)
+
+    # Assemble the globals.
+    if globs is None:
+        globs = {}
+    else:
+        globs = globs.copy()
+    if extraglobs is not None:
+        globs.update(extraglobs)
+    if '__name__' not in globs:
+        globs['__name__'] = '__main__'
+
+    if raise_on_error:
+        runner = DebugRunner(verbose=verbose, optionflags=optionflags)
+    else:
+        runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+
+    if encoding is not None:
+        text = text.decode(encoding)
+
+    # Read the file, convert it to a test, and run it.
+    test = parser.get_doctest(text, globs, name, filename, 0)
+    runner.run(test)
+
+    if report:
+        runner.summarize()
+
+    if master is None:
+        master = runner
+    else:
+        master.merge(runner)
+
+    return TestResults(runner.failures, runner.tries)
+
+def run_docstring_examples(f, globs, verbose=False, name="NoName",
+                           compileflags=None, optionflags=0):
+    """
+    Test examples in the given object's docstring (`f`), using `globs`
+    as globals.  Optional argument `name` is used in failure messages.
+    If the optional argument `verbose` is true, then generate output
+    even if there are no failures.
+
+    `compileflags` gives the set of flags that should be used by the
+    Python compiler when running the examples.  If not specified, then
+    it will default to the set of future-import flags that apply to
+    `globs`.
+
+    Optional keyword arg `optionflags` specifies options for the
+    testing and output.  See the documentation for `testmod` for more
+    information.
+    """
+    # Find, parse, and run all tests in the given module.
+    finder = DocTestFinder(verbose=verbose, recurse=False)
+    runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+    for test in finder.find(f, name, globs=globs):
+        runner.run(test, compileflags=compileflags)
+
+######################################################################
+## 7. Tester
+######################################################################
+# This is provided only for backwards compatibility.  It's not
+# actually used in any way.
+
+class Tester:
+    def __init__(self, mod=None, globs=None, verbose=None, optionflags=0):
+
+        warnings.warn("class Tester is deprecated; "
+                      "use class doctest.DocTestRunner instead",
+                      DeprecationWarning, stacklevel=2)
+        if mod is None and globs is None:
+            raise TypeError("Tester.__init__: must specify mod or globs")
+        if mod is not None and not inspect.ismodule(mod):
+            raise TypeError("Tester.__init__: mod must be a module; %r" %
+                            (mod,))
+        if globs is None:
+            globs = mod.__dict__
+        self.globs = globs
+
+        self.verbose = verbose
+        self.optionflags = optionflags
+        self.testfinder = DocTestFinder()
+        self.testrunner = DocTestRunner(verbose=verbose,
+                                        optionflags=optionflags)
+
+    def runstring(self, s, name):
+        test = DocTestParser().get_doctest(s, self.globs, name, None, None)
+        if self.verbose:
+            print "Running string", name
+        (f,t) = self.testrunner.run(test)
+        if self.verbose:
+            print f, "of", t, "examples failed in string", name
+        return TestResults(f,t)
+
+    def rundoc(self, object, name=None, module=None):
+        f = t = 0
+        tests = self.testfinder.find(object, name, module=module,
+                                     globs=self.globs)
+        for test in tests:
+            (f2, t2) = self.testrunner.run(test)
+            (f,t) = (f+f2, t+t2)
+        return TestResults(f,t)
+
+    def rundict(self, d, name, module=None):
+        import types
+        m = types.ModuleType(name)
+        m.__dict__.update(d)
+        if module is None:
+            module = False
+        return self.rundoc(m, name, module)
+
+    def run__test__(self, d, name):
+        import types
+        m = types.ModuleType(name)
+        m.__test__ = d
+        return self.rundoc(m, name)
+
+    def summarize(self, verbose=None):
+        return self.testrunner.summarize(verbose)
+
+    def merge(self, other):
+        self.testrunner.merge(other.testrunner)
+
+######################################################################
+## 8. Unittest Support
+######################################################################
+
+_unittest_reportflags = 0
+
+def set_unittest_reportflags(flags):
+    """Sets the unittest option flags.
+
+    The old flag is returned so that a runner could restore the old
+    value if it wished to:
+
+      >>> import doctest
+      >>> old = doctest._unittest_reportflags
+      >>> doctest.set_unittest_reportflags(REPORT_NDIFF |
+      ...                          REPORT_ONLY_FIRST_FAILURE) == old
+      True
+
+      >>> doctest._unittest_reportflags == (REPORT_NDIFF |
+      ...                                   REPORT_ONLY_FIRST_FAILURE)
+      True
+
+    Only reporting flags can be set:
+
+      >>> doctest.set_unittest_reportflags(ELLIPSIS)
+      Traceback (most recent call last):
+      ...
+      ValueError: ('Only reporting flags allowed', 8)
+
+      >>> doctest.set_unittest_reportflags(old) == (REPORT_NDIFF |
+      ...                                   REPORT_ONLY_FIRST_FAILURE)
+      True
+    """
+    global _unittest_reportflags
+
+    if (flags & REPORTING_FLAGS) != flags:
+        raise ValueError("Only reporting flags allowed", flags)
+    old = _unittest_reportflags
+    _unittest_reportflags = flags
+    return old
+
+
+class DocTestCase(unittest.TestCase):
+
+    def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
+                 checker=None):
+
+        unittest.TestCase.__init__(self)
+        self._dt_optionflags = optionflags
+        self._dt_checker = checker
+        self._dt_test = test
+        self._dt_setUp = setUp
+        self._dt_tearDown = tearDown
+
+    def setUp(self):
+        test = self._dt_test
+
+        if self._dt_setUp is not None:
+            self._dt_setUp(test)
+
+    def tearDown(self):
+        test = self._dt_test
+
+        if self._dt_tearDown is not None:
+            self._dt_tearDown(test)
+
+        test.globs.clear()
+
+    def runTest(self):
+        test = self._dt_test
+        old = sys.stdout
+        new = StringIO()
+        optionflags = self._dt_optionflags
+
+        if not (optionflags & REPORTING_FLAGS):
+            # The option flags don't include any reporting flags,
+            # so add the default reporting flags
+            optionflags |= _unittest_reportflags
+
+        runner = DocTestRunner(optionflags=optionflags,
+                               checker=self._dt_checker, verbose=False)
+
+        try:
+            runner.DIVIDER = "-"*70
+            failures, tries = runner.run(
+                test, out=new.write, clear_globs=False)
+        finally:
+            sys.stdout = old
+
+        if failures:
+            raise self.failureException(self.format_failure(new.getvalue()))
+
+    def format_failure(self, err):
+        test = self._dt_test
+        if test.lineno is None:
+            lineno = 'unknown line number'
+        else:
+            lineno = '%s' % test.lineno
+        lname = '.'.join(test.name.split('.')[-1:])
+        return ('Failed doctest test for %s\n'
+                '  File "%s", line %s, in %s\n\n%s'
+                % (test.name, test.filename, lineno, lname, err)
+                )
+
+    def debug(self):
+        r"""Run the test case without results and without catching exceptions
+
+           The unit test framework includes a debug method on test cases
+           and test suites to support post-mortem debugging.  The test code
+           is run in such a way that errors are not caught.  This way a
+           caller can catch the errors and initiate post-mortem debugging.
+
+           The DocTestCase provides a debug method that raises
+           UnexpectedException errors if there is an unexpected
+           exception:
+
+             >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42',
+             ...                {}, 'foo', 'foo.py', 0)
+             >>> case = DocTestCase(test)
+             >>> try:
+             ...     case.debug()
+             ... except UnexpectedException, failure:
+             ...     pass
+
+           The UnexpectedException contains the test, the example, and
+           the original exception:
+
+             >>> failure.test is test
+             True
+
+             >>> failure.example.want
+             '42\n'
+
+             >>> exc_info = failure.exc_info
+             >>> raise exc_info[0], exc_info[1], exc_info[2]
+             Traceback (most recent call last):
+             ...
+             KeyError
+
+           If the output doesn't match, then a DocTestFailure is raised:
+
+             >>> test = DocTestParser().get_doctest('''
+             ...      >>> x = 1
+             ...      >>> x
+             ...      2
+             ...      ''', {}, 'foo', 'foo.py', 0)
+             >>> case = DocTestCase(test)
+
+             >>> try:
+             ...    case.debug()
+             ... except DocTestFailure, failure:
+             ...    pass
+
+           DocTestFailure objects provide access to the test:
+
+             >>> failure.test is test
+             True
+
+           As well as to the example:
+
+             >>> failure.example.want
+             '2\n'
+
+           and the actual output:
+
+             >>> failure.got
+             '1\n'
+
+           """
+
+        self.setUp()
+        runner = DebugRunner(optionflags=self._dt_optionflags,
+                             checker=self._dt_checker, verbose=False)
+        runner.run(self._dt_test, clear_globs=False)
+        self.tearDown()
+
+    def id(self):
+        return self._dt_test.name
+
+    def __eq__(self, other):
+        if type(self) is not type(other):
+            return NotImplemented
+
+        return self._dt_test == other._dt_test and \
+               self._dt_optionflags == other._dt_optionflags and \
+               self._dt_setUp == other._dt_setUp and \
+               self._dt_tearDown == other._dt_tearDown and \
+               self._dt_checker == other._dt_checker
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __hash__(self):
+        return hash((self._dt_optionflags, self._dt_setUp, self._dt_tearDown,
+                     self._dt_checker))
+
+    def __repr__(self):
+        name = self._dt_test.name.split('.')
+        return "%s (%s)" % (name[-1], '.'.join(name[:-1]))
+
+    __str__ = __repr__
+
+    def shortDescription(self):
+        return "Doctest: " + self._dt_test.name
+
+class SkipDocTestCase(DocTestCase):
+    def __init__(self, module):
+        self.module = module
+        DocTestCase.__init__(self, None)
+
+    def setUp(self):
+        self.skipTest("DocTestSuite will not work with -O2 and above")
+
+    def test_skip(self):
+        pass
+
+    def shortDescription(self):
+        return "Skipping tests from %s" % self.module.__name__
+
+    __str__ = shortDescription
+
+
+def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None,
+                 **options):
+    """
+    Convert doctest tests for a module to a unittest test suite.
+
+    This converts each documentation string in a module that
+    contains doctest tests to a unittest test case.  If any of the
+    tests in a doc string fail, then the test case fails.  An exception
+    is raised showing the name of the file containing the test and a
+    (sometimes approximate) line number.
+
+    The `module` argument provides the module to be tested.  The argument
+    can be either a module or a module name.
+
+    If no argument is given, the calling module is used.
+
+    A number of options may be provided as keyword arguments:
+
+    setUp
+      A set-up function.  This is called before running the
+      tests in each file. The setUp function will be passed a DocTest
+      object.  The setUp function can access the test globals as the
+      globs attribute of the test passed.
+
+    tearDown
+      A tear-down function.  This is called after running the
+      tests in each file.  The tearDown function will be passed a DocTest
+      object.  The tearDown function can access the test globals as the
+      globs attribute of the test passed.
+
+    globs
+      A dictionary containing initial global variables for the tests.
+
+    optionflags
+       A set of doctest option flags expressed as an integer.
+    """
+
+    if test_finder is None:
+        test_finder = DocTestFinder()
+
+    module = _normalize_module(module)
+    tests = test_finder.find(module, globs=globs, extraglobs=extraglobs)
+
+    if not tests and sys.flags.optimize >=2:
+        # Skip doctests when running with -O2
+        suite = unittest.TestSuite()
+        suite.addTest(SkipDocTestCase(module))
+        return suite
+    elif not tests:
+        # Why do we want to do this? Because it reveals a bug that might
+        # otherwise be hidden.
+        # It is probably a bug that this exception is not also raised if the
+        # number of doctest examples in tests is zero (i.e. if no doctest
+        # examples were found).  However, we should probably not be raising
+        # an exception at all here, though it is too late to make this change
+        # for a maintenance release.  See also issue #14649.
+        raise ValueError(module, "has no docstrings")
+
+    tests.sort()
+    suite = unittest.TestSuite()
+
+    for test in tests:
+        if len(test.examples) == 0:
+            continue
+        if not test.filename:
+            filename = module.__file__
+            if filename[-4:] in (".pyc", ".pyo"):
+                filename = filename[:-1]
+            elif filename.endswith('$py.class'):
+                filename = '%s.py' % filename[:-9]
+            test.filename = filename
+        suite.addTest(DocTestCase(test, **options))
+
+    return suite
+
+class DocFileCase(DocTestCase):
+
+    def id(self):
+        return '_'.join(self._dt_test.name.split('.'))
+
+    def __repr__(self):
+        return self._dt_test.filename
+    __str__ = __repr__
+
+    def format_failure(self, err):
+        return ('Failed doctest test for %s\n  File "%s", line 0\n\n%s'
+                % (self._dt_test.name, self._dt_test.filename, err)
+                )
+
+def DocFileTest(path, module_relative=True, package=None,
+                globs=None, parser=DocTestParser(),
+                encoding=None, **options):
+    if globs is None:
+        globs = {}
+    else:
+        globs = globs.copy()
+
+    if package and not module_relative:
+        raise ValueError("Package may only be specified for module-"
+                         "relative paths.")
+
+    # Relativize the path.
+    doc, path = _load_testfile(path, package, module_relative)
+
+    if "__file__" not in globs:
+        globs["__file__"] = path
+
+    # Find the file and read it.
+    name = os.path.basename(path)
+
+    # If an encoding is specified, use it to convert the file to unicode
+    if encoding is not None:
+        doc = doc.decode(encoding)
+
+    # Convert it to a test, and wrap it in a DocFileCase.
+    test = parser.get_doctest(doc, globs, name, path, 0)
+    return DocFileCase(test, **options)
+
+def DocFileSuite(*paths, **kw):
+    """A unittest suite for one or more doctest files.
+
+    The path to each doctest file is given as a string; the
+    interpretation of that string depends on the keyword argument
+    "module_relative".
+
+    A number of options may be provided as keyword arguments:
+
+    module_relative
+      If "module_relative" is True, then the given file paths are
+      interpreted as os-independent module-relative paths.  By
+      default, these paths are relative to the calling module's
+      directory; but if the "package" argument is specified, then
+      they are relative to that package.  To ensure os-independence,
+      "filename" should use "/" characters to separate path
+      segments, and may not be an absolute path (i.e., it may not
+      begin with "/").
+
+      If "module_relative" is False, then the given file paths are
+      interpreted as os-specific paths.  These paths may be absolute
+      or relative (to the current working directory).
+
+    package
+      A Python package or the name of a Python package whose directory
+      should be used as the base directory for module relative paths.
+      If "package" is not specified, then the calling module's
+      directory is used as the base directory for module relative
+      filenames.  It is an error to specify "package" if
+      "module_relative" is False.
+
+    setUp
+      A set-up function.  This is called before running the
+      tests in each file. The setUp function will be passed a DocTest
+      object.  The setUp function can access the test globals as the
+      globs attribute of the test passed.
+
+    tearDown
+      A tear-down function.  This is called after running the
+      tests in each file.  The tearDown function will be passed a DocTest
+      object.  The tearDown function can access the test globals as the
+      globs attribute of the test passed.
+
+    globs
+      A dictionary containing initial global variables for the tests.
+
+    optionflags
+      A set of doctest option flags expressed as an integer.
+
+    parser
+      A DocTestParser (or subclass) that should be used to extract
+      tests from the files.
+
+    encoding
+      An encoding that will be used to convert the files to unicode.
+    """
+    suite = unittest.TestSuite()
+
+    # We do this here so that _normalize_module is called at the right
+    # level.  If it were called in DocFileTest, then this function
+    # would be the caller and we might guess the package incorrectly.
+    if kw.get('module_relative', True):
+        kw['package'] = _normalize_module(kw.get('package'))
+
+    for path in paths:
+        suite.addTest(DocFileTest(path, **kw))
+
+    return suite
+
+######################################################################
+## 9. Debugging Support
+######################################################################
+
+def script_from_examples(s):
+    r"""Extract script from text with examples.
+
+       Converts text with examples to a Python script.  Example input is
+       converted to regular code.  Example output and all other words
+       are converted to comments:
+
+       >>> text = '''
+       ...       Here are examples of simple math.
+       ...
+       ...           Python has super accurate integer addition
+       ...
+       ...           >>> 2 + 2
+       ...           5
+       ...
+       ...           And very friendly error messages:
+       ...
+       ...           >>> 1/0
+       ...           To Infinity
+       ...           And
+       ...           Beyond
+       ...
+       ...           You can use logic if you want:
+       ...
+       ...           >>> if 0:
+       ...           ...    blah
+       ...           ...    blah
+       ...           ...
+       ...
+       ...           Ho hum
+       ...           '''
+
+       >>> print script_from_examples(text)
+       # Here are examples of simple math.
+       #
+       #     Python has super accurate integer addition
+       #
+       2 + 2
+       # Expected:
+       ## 5
+       #
+       #     And very friendly error messages:
+       #
+       1/0
+       # Expected:
+       ## To Infinity
+       ## And
+       ## Beyond
+       #
+       #     You can use logic if you want:
+       #
+       if 0:
+          blah
+          blah
+       #
+       #     Ho hum
+       <BLANKLINE>
+       """
+    output = []
+    for piece in DocTestParser().parse(s):
+        if isinstance(piece, Example):
+            # Add the example's source code (strip trailing NL)
+            output.append(piece.source[:-1])
+            # Add the expected output:
+            want = piece.want
+            if want:
+                output.append('# Expected:')
+                output += ['## '+l for l in want.split('\n')[:-1]]
+        else:
+            # Add non-example text.
+            output += [_comment_line(l)
+                       for l in piece.split('\n')[:-1]]
+
+    # Trim junk on both ends.
+    while output and output[-1] == '#':
+        output.pop()
+    while output and output[0] == '#':
+        output.pop(0)
+    # Combine the output, and return it.
+    # Add a courtesy newline to prevent exec from choking (see bug #1172785)
+    return '\n'.join(output) + '\n'
+
+def testsource(module, name):
+    """Extract the test sources from a doctest docstring as a script.
+
+    Provide the module (or dotted name of the module) containing the
+    test to be debugged and the name (within the module) of the object
+    with the doc string with tests to be debugged.
+    """
+    module = _normalize_module(module)
+    tests = DocTestFinder().find(module)
+    test = [t for t in tests if t.name == name]
+    if not test:
+        raise ValueError(name, "not found in tests")
+    test = test[0]
+    testsrc = script_from_examples(test.docstring)
+    return testsrc
+
+def debug_src(src, pm=False, globs=None):
+    """Debug a single doctest docstring, in argument `src`'"""
+    testsrc = script_from_examples(src)
+    debug_script(testsrc, pm, globs)
+
+def debug_script(src, pm=False, globs=None):
+    "Debug a test script.  `src` is the script, as a string."
+    import pdb
+
+    # Note that tempfile.NameTemporaryFile() cannot be used.  As the
+    # docs say, a file so created cannot be opened by name a second time
+    # on modern Windows boxes, and execfile() needs to open it.
+    srcfilename = tempfile.mktemp(".py", "doctestdebug")
+    f = open(srcfilename, 'w')
+    f.write(src)
+    f.close()
+
+    try:
+        if globs:
+            globs = globs.copy()
+        else:
+            globs = {}
+
+        if pm:
+            try:
+                execfile(srcfilename, globs, globs)
+            except:
+                print sys.exc_info()[1]
+                pdb.post_mortem(sys.exc_info()[2])
+        else:
+            # Note that %r is vital here.  '%s' instead can, e.g., cause
+            # backslashes to get treated as metacharacters on Windows.
+            pdb.run("execfile(%r)" % srcfilename, globs, globs)
+
+    finally:
+        os.remove(srcfilename)
+
+def debug(module, name, pm=False):
+    """Debug a single doctest docstring.
+
+    Provide the module (or dotted name of the module) containing the
+    test to be debugged and the name (within the module) of the object
+    with the docstring with tests to be debugged.
+    """
+    module = _normalize_module(module)
+    testsrc = testsource(module, name)
+    debug_script(testsrc, pm, module.__dict__)
+
+######################################################################
+## 10. Example Usage
+######################################################################
+class _TestClass:
+    """
+    A pointless class, for sanity-checking of docstring testing.
+
+    Methods:
+        square()
+        get()
+
+    >>> _TestClass(13).get() + _TestClass(-12).get()
+    1
+    >>> hex(_TestClass(13).square().get())
+    '0xa9'
+    """
+
+    def __init__(self, val):
+        """val -> _TestClass object with associated value val.
+
+        >>> t = _TestClass(123)
+        >>> print t.get()
+        123
+        """
+
+        self.val = val
+
+    def square(self):
+        """square() -> square TestClass's associated value
+
+        >>> _TestClass(13).square().get()
+        169
+        """
+
+        self.val = self.val ** 2
+        return self
+
+    def get(self):
+        """get() -> return TestClass's associated value.
+
+        >>> x = _TestClass(-42)
+        >>> print x.get()
+        -42
+        """
+
+        return self.val
+
+__test__ = {"_TestClass": _TestClass,
+            "string": r"""
+                      Example of a string object, searched as-is.
+                      >>> x = 1; y = 2
+                      >>> x + y, x * y
+                      (3, 2)
+                      """,
+
+            "bool-int equivalence": r"""
+                                    In 2.2, boolean expressions displayed
+                                    0 or 1.  By default, we still accept
+                                    them.  This can be disabled by passing
+                                    DONT_ACCEPT_TRUE_FOR_1 to the new
+                                    optionflags argument.
+                                    >>> 4 == 4
+                                    1
+                                    >>> 4 == 4
+                                    True
+                                    >>> 4 > 4
+                                    0
+                                    >>> 4 > 4
+                                    False
+                                    """,
+
+            "blank lines": r"""
+                Blank lines can be marked with <BLANKLINE>:
+                    >>> print 'foo\n\nbar\n'
+                    foo
+                    <BLANKLINE>
+                    bar
+                    <BLANKLINE>
+            """,
+
+            "ellipsis": r"""
+                If the ellipsis flag is used, then '...' can be used to
+                elide substrings in the desired output:
+                    >>> print range(1000) #doctest: +ELLIPSIS
+                    [0, 1, 2, ..., 999]
+            """,
+
+            "whitespace normalization": r"""
+                If the whitespace normalization flag is used, then
+                differences in whitespace are ignored.
+                    >>> print range(30) #doctest: +NORMALIZE_WHITESPACE
+                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+                     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+                     27, 28, 29]
+            """,
+           }
+
+
+def _test():
+    testfiles = [arg for arg in sys.argv[1:] if arg and arg[0] != '-']
+    if not testfiles:
+        name = os.path.basename(sys.argv[0])
+        if '__loader__' in globals():          # python -m
+            name, _ = os.path.splitext(name)
+        print("usage: {0} [-v] file ...".format(name))
+        return 2
+    for filename in testfiles:
+        if filename.endswith(".py"):
+            # It is a module -- insert its dir into sys.path and try to
+            # import it. If it is part of a package, that possibly
+            # won't work because of package imports.
+            dirname, filename = os.path.split(filename)
+            sys.path.insert(0, dirname)
+            m = __import__(filename[:-3])
+            del sys.path[0]
+            failures, _ = testmod(m)
+        else:
+            failures, _ = testfile(filename, module_relative=False)
+        if failures:
+            return 1
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(_test())
diff --git a/src/main/resources/PythonLibs/dumbdbm.py b/src/main/resources/PythonLibs/dumbdbm.py
new file mode 100644
index 0000000000000000000000000000000000000000..fb54a93041b4d33c94a10524544a92fe1002266e
--- /dev/null
+++ b/src/main/resources/PythonLibs/dumbdbm.py
@@ -0,0 +1,250 @@
+"""A dumb and slow but simple dbm clone.
+
+For database spam, spam.dir contains the index (a text file),
+spam.bak *may* contain a backup of the index (also a text file),
+while spam.dat contains the data (a binary file).
+
+XXX TO DO:
+
+- seems to contain a bug when updating...
+
+- reclaim free space (currently, space once occupied by deleted or expanded
+items is never reused)
+
+- support concurrent access (currently, if two processes take turns making
+updates, they can mess up the index)
+
+- support efficient access to large databases (currently, the whole index
+is read when the database is opened, and some updates rewrite the whole index)
+
+- support opening for read-only (flag = 'm')
+
+"""
+
+import os as _os
+import __builtin__
+import UserDict
+
+_open = __builtin__.open
+
+_BLOCKSIZE = 512
+
+error = IOError                         # For anydbm
+
+class _Database(UserDict.DictMixin):
+
+    # The on-disk directory and data files can remain in mutually
+    # inconsistent states for an arbitrarily long time (see comments
+    # at the end of __setitem__).  This is only repaired when _commit()
+    # gets called.  One place _commit() gets called is from __del__(),
+    # and if that occurs at program shutdown time, module globals may
+    # already have gotten rebound to None.  Since it's crucial that
+    # _commit() finish successfully, we can't ignore shutdown races
+    # here, and _commit() must not reference any globals.
+    _os = _os       # for _commit()
+    _open = _open   # for _commit()
+
+    def __init__(self, filebasename, mode):
+        self._mode = mode
+
+        # The directory file is a text file.  Each line looks like
+        #    "%r, (%d, %d)\n" % (key, pos, siz)
+        # where key is the string key, pos is the offset into the dat
+        # file of the associated value's first byte, and siz is the number
+        # of bytes in the associated value.
+        self._dirfile = filebasename + _os.extsep + 'dir'
+
+        # The data file is a binary file pointed into by the directory
+        # file, and holds the values associated with keys.  Each value
+        # begins at a _BLOCKSIZE-aligned byte offset, and is a raw
+        # binary 8-bit string value.
+        self._datfile = filebasename + _os.extsep + 'dat'
+        self._bakfile = filebasename + _os.extsep + 'bak'
+
+        # The index is an in-memory dict, mirroring the directory file.
+        self._index = None  # maps keys to (pos, siz) pairs
+
+        # Mod by Jack: create data file if needed
+        try:
+            f = _open(self._datfile, 'r')
+        except IOError:
+            f = _open(self._datfile, 'w')
+            self._chmod(self._datfile)
+        f.close()
+        self._update()
+
+    # Read directory file into the in-memory index dict.
+    def _update(self):
+        self._index = {}
+        try:
+            f = _open(self._dirfile)
+        except IOError:
+            pass
+        else:
+            for line in f:
+                line = line.rstrip()
+                key, pos_and_siz_pair = eval(line)
+                self._index[key] = pos_and_siz_pair
+            f.close()
+
+    # Write the index dict to the directory file.  The original directory
+    # file (if any) is renamed with a .bak extension first.  If a .bak
+    # file currently exists, it's deleted.
+    def _commit(self):
+        # CAUTION:  It's vital that _commit() succeed, and _commit() can
+        # be called from __del__().  Therefore we must never reference a
+        # global in this routine.
+        if self._index is None:
+            return  # nothing to do
+
+        try:
+            self._os.unlink(self._bakfile)
+        except self._os.error:
+            pass
+
+        try:
+            self._os.rename(self._dirfile, self._bakfile)
+        except self._os.error:
+            pass
+
+        f = self._open(self._dirfile, 'w')
+        self._chmod(self._dirfile)
+        for key, pos_and_siz_pair in self._index.iteritems():
+            f.write("%r, %r\n" % (key, pos_and_siz_pair))
+        f.close()
+
+    sync = _commit
+
+    def __getitem__(self, key):
+        pos, siz = self._index[key]     # may raise KeyError
+        f = _open(self._datfile, 'rb')
+        f.seek(pos)
+        dat = f.read(siz)
+        f.close()
+        return dat
+
+    # Append val to the data file, starting at a _BLOCKSIZE-aligned
+    # offset.  The data file is first padded with NUL bytes (if needed)
+    # to get to an aligned offset.  Return pair
+    #     (starting offset of val, len(val))
+    def _addval(self, val):
+        f = _open(self._datfile, 'rb+')
+        f.seek(0, 2)
+        pos = int(f.tell())
+        npos = ((pos + _BLOCKSIZE - 1) // _BLOCKSIZE) * _BLOCKSIZE
+        f.write('\0'*(npos-pos))
+        pos = npos
+        f.write(val)
+        f.close()
+        return (pos, len(val))
+
+    # Write val to the data file, starting at offset pos.  The caller
+    # is responsible for ensuring that there's enough room starting at
+    # pos to hold val, without overwriting some other value.  Return
+    # pair (pos, len(val)).
+    def _setval(self, pos, val):
+        f = _open(self._datfile, 'rb+')
+        f.seek(pos)
+        f.write(val)
+        f.close()
+        return (pos, len(val))
+
+    # key is a new key whose associated value starts in the data file
+    # at offset pos and with length siz.  Add an index record to
+    # the in-memory index dict, and append one to the directory file.
+    def _addkey(self, key, pos_and_siz_pair):
+        self._index[key] = pos_and_siz_pair
+        f = _open(self._dirfile, 'a')
+        self._chmod(self._dirfile)
+        f.write("%r, %r\n" % (key, pos_and_siz_pair))
+        f.close()
+
+    def __setitem__(self, key, val):
+        if not type(key) == type('') == type(val):
+            raise TypeError, "keys and values must be strings"
+        if key not in self._index:
+            self._addkey(key, self._addval(val))
+        else:
+            # See whether the new value is small enough to fit in the
+            # (padded) space currently occupied by the old value.
+            pos, siz = self._index[key]
+            oldblocks = (siz + _BLOCKSIZE - 1) // _BLOCKSIZE
+            newblocks = (len(val) + _BLOCKSIZE - 1) // _BLOCKSIZE
+            if newblocks <= oldblocks:
+                self._index[key] = self._setval(pos, val)
+            else:
+                # The new value doesn't fit in the (padded) space used
+                # by the old value.  The blocks used by the old value are
+                # forever lost.
+                self._index[key] = self._addval(val)
+
+            # Note that _index may be out of synch with the directory
+            # file now:  _setval() and _addval() don't update the directory
+            # file.  This also means that the on-disk directory and data
+            # files are in a mutually inconsistent state, and they'll
+            # remain that way until _commit() is called.  Note that this
+            # is a disaster (for the database) if the program crashes
+            # (so that _commit() never gets called).
+
+    def __delitem__(self, key):
+        # The blocks used by the associated value are lost.
+        del self._index[key]
+        # XXX It's unclear why we do a _commit() here (the code always
+        # XXX has, so I'm not changing it).  _setitem__ doesn't try to
+        # XXX keep the directory file in synch.  Why should we?  Or
+        # XXX why shouldn't __setitem__?
+        self._commit()
+
+    def keys(self):
+        return self._index.keys()
+
+    def has_key(self, key):
+        return key in self._index
+
+    def __contains__(self, key):
+        return key in self._index
+
+    def iterkeys(self):
+        return self._index.iterkeys()
+    __iter__ = iterkeys
+
+    def __len__(self):
+        return len(self._index)
+
+    def close(self):
+        self._commit()
+        self._index = self._datfile = self._dirfile = self._bakfile = None
+
+    __del__ = close
+
+    def _chmod (self, file):
+        if hasattr(self._os, 'chmod'):
+            self._os.chmod(file, self._mode)
+
+
+def open(file, flag=None, mode=0666):
+    """Open the database file, filename, and return corresponding object.
+
+    The flag argument, used to control how the database is opened in the
+    other DBM implementations, is ignored in the dumbdbm module; the
+    database is always opened for update, and will be created if it does
+    not exist.
+
+    The optional mode argument is the UNIX mode of the file, used only when
+    the database has to be created.  It defaults to octal code 0666 (and
+    will be modified by the prevailing umask).
+
+    """
+    # flag argument is currently ignored
+
+    # Modify mode depending on the umask
+    try:
+        um = _os.umask(0)
+        _os.umask(um)
+    except AttributeError:
+        pass
+    else:
+        # Turn off any bits that are set in the umask
+        mode = mode & (~um)
+
+    return _Database(file, mode)
diff --git a/src/main/resources/PythonLibs/dummy_thread.py b/src/main/resources/PythonLibs/dummy_thread.py
new file mode 100644
index 0000000000000000000000000000000000000000..198dc49dba39e6550bc1c1c701009a7a43d2a93d
--- /dev/null
+++ b/src/main/resources/PythonLibs/dummy_thread.py
@@ -0,0 +1,145 @@
+"""Drop-in replacement for the thread module.
+
+Meant to be used as a brain-dead substitute so that threaded code does
+not need to be rewritten for when the thread module is not present.
+
+Suggested usage is::
+
+    try:
+        import thread
+    except ImportError:
+        import dummy_thread as thread
+
+"""
+# Exports only things specified by thread documentation;
+# skipping obsolete synonyms allocate(), start_new(), exit_thread().
+__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock',
+           'interrupt_main', 'LockType']
+
+import traceback as _traceback
+
+class error(Exception):
+    """Dummy implementation of thread.error."""
+
+    def __init__(self, *args):
+        self.args = args
+
+def start_new_thread(function, args, kwargs={}):
+    """Dummy implementation of thread.start_new_thread().
+
+    Compatibility is maintained by making sure that ``args`` is a
+    tuple and ``kwargs`` is a dictionary.  If an exception is raised
+    and it is SystemExit (which can be done by thread.exit()) it is
+    caught and nothing is done; all other exceptions are printed out
+    by using traceback.print_exc().
+
+    If the executed function calls interrupt_main the KeyboardInterrupt will be
+    raised when the function returns.
+
+    """
+    if type(args) != type(tuple()):
+        raise TypeError("2nd arg must be a tuple")
+    if type(kwargs) != type(dict()):
+        raise TypeError("3rd arg must be a dict")
+    global _main
+    _main = False
+    try:
+        function(*args, **kwargs)
+    except SystemExit:
+        pass
+    except:
+        _traceback.print_exc()
+    _main = True
+    global _interrupt
+    if _interrupt:
+        _interrupt = False
+        raise KeyboardInterrupt
+
+def exit():
+    """Dummy implementation of thread.exit()."""
+    raise SystemExit
+
+def get_ident():
+    """Dummy implementation of thread.get_ident().
+
+    Since this module should only be used when threadmodule is not
+    available, it is safe to assume that the current process is the
+    only thread.  Thus a constant can be safely returned.
+    """
+    return -1
+
+def allocate_lock():
+    """Dummy implementation of thread.allocate_lock()."""
+    return LockType()
+
+def stack_size(size=None):
+    """Dummy implementation of thread.stack_size()."""
+    if size is not None:
+        raise error("setting thread stack size not supported")
+    return 0
+
+class LockType(object):
+    """Class implementing dummy implementation of thread.LockType.
+
+    Compatibility is maintained by maintaining self.locked_status
+    which is a boolean that stores the state of the lock.  Pickling of
+    the lock, though, should not be done since if the thread module is
+    then used with an unpickled ``lock()`` from here problems could
+    occur from this class not having atomic methods.
+
+    """
+
+    def __init__(self):
+        self.locked_status = False
+
+    def acquire(self, waitflag=None):
+        """Dummy implementation of acquire().
+
+        For blocking calls, self.locked_status is automatically set to
+        True and returned appropriately based on value of
+        ``waitflag``.  If it is non-blocking, then the value is
+        actually checked and not set if it is already acquired.  This
+        is all done so that threading.Condition's assert statements
+        aren't triggered and throw a little fit.
+
+        """
+        if waitflag is None or waitflag:
+            self.locked_status = True
+            return True
+        else:
+            if not self.locked_status:
+                self.locked_status = True
+                return True
+            else:
+                return False
+
+    __enter__ = acquire
+
+    def __exit__(self, typ, val, tb):
+        self.release()
+
+    def release(self):
+        """Release the dummy lock."""
+        # XXX Perhaps shouldn't actually bother to test?  Could lead
+        #     to problems for complex, threaded code.
+        if not self.locked_status:
+            raise error
+        self.locked_status = False
+        return True
+
+    def locked(self):
+        return self.locked_status
+
+# Used to signal that interrupt_main was called in a "thread"
+_interrupt = False
+# True when not executing in a "thread"
+_main = True
+
+def interrupt_main():
+    """Set _interrupt flag to True to have start_new_thread raise
+    KeyboardInterrupt upon exiting."""
+    if _main:
+        raise KeyboardInterrupt
+    else:
+        global _interrupt
+        _interrupt = True
diff --git a/src/main/resources/PythonLibs/dummy_threading.py b/src/main/resources/PythonLibs/dummy_threading.py
new file mode 100644
index 0000000000000000000000000000000000000000..81028a3d4e8a05aaa6ad3b85757b013e0c829c4d
--- /dev/null
+++ b/src/main/resources/PythonLibs/dummy_threading.py
@@ -0,0 +1,78 @@
+"""Faux ``threading`` version using ``dummy_thread`` instead of ``thread``.
+
+The module ``_dummy_threading`` is added to ``sys.modules`` in order
+to not have ``threading`` considered imported.  Had ``threading`` been
+directly imported it would have made all subsequent imports succeed
+regardless of whether ``thread`` was available which is not desired.
+
+"""
+from sys import modules as sys_modules
+
+import dummy_thread
+
+# Declaring now so as to not have to nest ``try``s to get proper clean-up.
+holding_thread = False
+holding_threading = False
+holding__threading_local = False
+
+try:
+    # Could have checked if ``thread`` was not in sys.modules and gone
+    # a different route, but decided to mirror technique used with
+    # ``threading`` below.
+    if 'thread' in sys_modules:
+        held_thread = sys_modules['thread']
+        holding_thread = True
+    # Must have some module named ``thread`` that implements its API
+    # in order to initially import ``threading``.
+    sys_modules['thread'] = sys_modules['dummy_thread']
+
+    if 'threading' in sys_modules:
+        # If ``threading`` is already imported, might as well prevent
+        # trying to import it more than needed by saving it if it is
+        # already imported before deleting it.
+        held_threading = sys_modules['threading']
+        holding_threading = True
+        del sys_modules['threading']
+
+    if '_threading_local' in sys_modules:
+        # If ``_threading_local`` is already imported, might as well prevent
+        # trying to import it more than needed by saving it if it is
+        # already imported before deleting it.
+        held__threading_local = sys_modules['_threading_local']
+        holding__threading_local = True
+        del sys_modules['_threading_local']
+
+    import threading
+    # Need a copy of the code kept somewhere...
+    sys_modules['_dummy_threading'] = sys_modules['threading']
+    del sys_modules['threading']
+    sys_modules['_dummy__threading_local'] = sys_modules['_threading_local']
+    del sys_modules['_threading_local']
+    from _dummy_threading import *
+    from _dummy_threading import __all__
+
+finally:
+    # Put back ``threading`` if we overwrote earlier
+
+    if holding_threading:
+        sys_modules['threading'] = held_threading
+        del held_threading
+    del holding_threading
+
+    # Put back ``_threading_local`` if we overwrote earlier
+
+    if holding__threading_local:
+        sys_modules['_threading_local'] = held__threading_local
+        del held__threading_local
+    del holding__threading_local
+
+    # Put back ``thread`` if we overwrote, else del the entry we made
+    if holding_thread:
+        sys_modules['thread'] = held_thread
+        del held_thread
+    else:
+        del sys_modules['thread']
+    del holding_thread
+
+    del dummy_thread
+    del sys_modules
diff --git a/src/main/resources/PythonLibs/email/__init__.py b/src/main/resources/PythonLibs/email/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..a780ebe339bde909541c72dbf8396c1c04d26c2c
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/__init__.py
@@ -0,0 +1,123 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""A package for parsing, handling, and generating email messages."""
+
+__version__ = '4.0.3'
+
+__all__ = [
+    # Old names
+    'base64MIME',
+    'Charset',
+    'Encoders',
+    'Errors',
+    'Generator',
+    'Header',
+    'Iterators',
+    'Message',
+    'MIMEAudio',
+    'MIMEBase',
+    'MIMEImage',
+    'MIMEMessage',
+    'MIMEMultipart',
+    'MIMENonMultipart',
+    'MIMEText',
+    'Parser',
+    'quopriMIME',
+    'Utils',
+    'message_from_string',
+    'message_from_file',
+    # new names
+    'base64mime',
+    'charset',
+    'encoders',
+    'errors',
+    'generator',
+    'header',
+    'iterators',
+    'message',
+    'mime',
+    'parser',
+    'quoprimime',
+    'utils',
+    ]
+
+
+
+# Some convenience routines.  Don't import Parser and Message as side-effects
+# of importing email since those cascadingly import most of the rest of the
+# email package.
+def message_from_string(s, *args, **kws):
+    """Parse a string into a Message object model.
+
+    Optional _class and strict are passed to the Parser constructor.
+    """
+    from email.parser import Parser
+    return Parser(*args, **kws).parsestr(s)
+
+
+def message_from_file(fp, *args, **kws):
+    """Read a file and parse its contents into a Message object model.
+
+    Optional _class and strict are passed to the Parser constructor.
+    """
+    from email.parser import Parser
+    return Parser(*args, **kws).parse(fp)
+
+
+
+# Lazy loading to provide name mapping from new-style names (PEP 8 compatible
+# email 4.0 module names), to old-style names (email 3.0 module names).
+import sys
+
+class LazyImporter(object):
+    def __init__(self, module_name):
+        self.__name__ = 'email.' + module_name
+
+    def __getattr__(self, name):
+        __import__(self.__name__)
+        mod = sys.modules[self.__name__]
+        self.__dict__.update(mod.__dict__)
+        return getattr(mod, name)
+
+
+_LOWERNAMES = [
+    # email.<old name> -> email.<new name is lowercased old name>
+    'Charset',
+    'Encoders',
+    'Errors',
+    'FeedParser',
+    'Generator',
+    'Header',
+    'Iterators',
+    'Message',
+    'Parser',
+    'Utils',
+    'base64MIME',
+    'quopriMIME',
+    ]
+
+_MIMENAMES = [
+    # email.MIME<old name> -> email.mime.<new name is lowercased old name>
+    'Audio',
+    'Base',
+    'Image',
+    'Message',
+    'Multipart',
+    'NonMultipart',
+    'Text',
+    ]
+
+for _name in _LOWERNAMES:
+    importer = LazyImporter(_name.lower())
+    sys.modules['email.' + _name] = importer
+    setattr(sys.modules['email'], _name, importer)
+
+
+import email.mime
+for _name in _MIMENAMES:
+    importer = LazyImporter('mime.' + _name.lower())
+    sys.modules['email.MIME' + _name] = importer
+    setattr(sys.modules['email'], 'MIME' + _name, importer)
+    setattr(sys.modules['email.mime'], _name, importer)
diff --git a/src/main/resources/PythonLibs/email/_parseaddr.py b/src/main/resources/PythonLibs/email/_parseaddr.py
new file mode 100644
index 0000000000000000000000000000000000000000..690db2c22d34d358b6707d6befa0fcf96e6373bc
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/_parseaddr.py
@@ -0,0 +1,497 @@
+# Copyright (C) 2002-2007 Python Software Foundation
+# Contact: email-sig@python.org
+
+"""Email address parsing code.
+
+Lifted directly from rfc822.py.  This should eventually be rewritten.
+"""
+
+__all__ = [
+    'mktime_tz',
+    'parsedate',
+    'parsedate_tz',
+    'quote',
+    ]
+
+import time, calendar
+
+SPACE = ' '
+EMPTYSTRING = ''
+COMMASPACE = ', '
+
+# Parse a date field
+_monthnames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul',
+               'aug', 'sep', 'oct', 'nov', 'dec',
+               'january', 'february', 'march', 'april', 'may', 'june', 'july',
+               'august', 'september', 'october', 'november', 'december']
+
+_daynames = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
+
+# The timezone table does not include the military time zones defined
+# in RFC822, other than Z.  According to RFC1123, the description in
+# RFC822 gets the signs wrong, so we can't rely on any such time
+# zones.  RFC1123 recommends that numeric timezone indicators be used
+# instead of timezone names.
+
+_timezones = {'UT':0, 'UTC':0, 'GMT':0, 'Z':0,
+              'AST': -400, 'ADT': -300,  # Atlantic (used in Canada)
+              'EST': -500, 'EDT': -400,  # Eastern
+              'CST': -600, 'CDT': -500,  # Central
+              'MST': -700, 'MDT': -600,  # Mountain
+              'PST': -800, 'PDT': -700   # Pacific
+              }
+
+
+def parsedate_tz(data):
+    """Convert a date string to a time tuple.
+
+    Accounts for military timezones.
+    """
+    data = data.split()
+    # The FWS after the comma after the day-of-week is optional, so search and
+    # adjust for this.
+    if data[0].endswith(',') or data[0].lower() in _daynames:
+        # There's a dayname here. Skip it
+        del data[0]
+    else:
+        i = data[0].rfind(',')
+        if i >= 0:
+            data[0] = data[0][i+1:]
+    if len(data) == 3: # RFC 850 date, deprecated
+        stuff = data[0].split('-')
+        if len(stuff) == 3:
+            data = stuff + data[1:]
+    if len(data) == 4:
+        s = data[3]
+        i = s.find('+')
+        if i > 0:
+            data[3:] = [s[:i], s[i+1:]]
+        else:
+            data.append('') # Dummy tz
+    if len(data) < 5:
+        return None
+    data = data[:5]
+    [dd, mm, yy, tm, tz] = data
+    mm = mm.lower()
+    if mm not in _monthnames:
+        dd, mm = mm, dd.lower()
+        if mm not in _monthnames:
+            return None
+    mm = _monthnames.index(mm) + 1
+    if mm > 12:
+        mm -= 12
+    if dd[-1] == ',':
+        dd = dd[:-1]
+    i = yy.find(':')
+    if i > 0:
+        yy, tm = tm, yy
+    if yy[-1] == ',':
+        yy = yy[:-1]
+    if not yy[0].isdigit():
+        yy, tz = tz, yy
+    if tm[-1] == ',':
+        tm = tm[:-1]
+    tm = tm.split(':')
+    if len(tm) == 2:
+        [thh, tmm] = tm
+        tss = '0'
+    elif len(tm) == 3:
+        [thh, tmm, tss] = tm
+    else:
+        return None
+    try:
+        yy = int(yy)
+        dd = int(dd)
+        thh = int(thh)
+        tmm = int(tmm)
+        tss = int(tss)
+    except ValueError:
+        return None
+    # Check for a yy specified in two-digit format, then convert it to the
+    # appropriate four-digit format, according to the POSIX standard. RFC 822
+    # calls for a two-digit yy, but RFC 2822 (which obsoletes RFC 822)
+    # mandates a 4-digit yy. For more information, see the documentation for
+    # the time module.
+    if yy < 100:
+        # The year is between 1969 and 1999 (inclusive).
+        if yy > 68:
+            yy += 1900
+        # The year is between 2000 and 2068 (inclusive).
+        else:
+            yy += 2000
+    tzoffset = None
+    tz = tz.upper()
+    if tz in _timezones:
+        tzoffset = _timezones[tz]
+    else:
+        try:
+            tzoffset = int(tz)
+        except ValueError:
+            pass
+    # Convert a timezone offset into seconds ; -0500 -> -18000
+    if tzoffset:
+        if tzoffset < 0:
+            tzsign = -1
+            tzoffset = -tzoffset
+        else:
+            tzsign = 1
+        tzoffset = tzsign * ( (tzoffset//100)*3600 + (tzoffset % 100)*60)
+    # Daylight Saving Time flag is set to -1, since DST is unknown.
+    return yy, mm, dd, thh, tmm, tss, 0, 1, -1, tzoffset
+
+
+def parsedate(data):
+    """Convert a time string to a time tuple."""
+    t = parsedate_tz(data)
+    if isinstance(t, tuple):
+        return t[:9]
+    else:
+        return t
+
+
+def mktime_tz(data):
+    """Turn a 10-tuple as returned by parsedate_tz() into a POSIX timestamp."""
+    if data[9] is None:
+        # No zone info, so localtime is better assumption than GMT
+        return time.mktime(data[:8] + (-1,))
+    else:
+        t = calendar.timegm(data)
+        return t - data[9]
+
+
+def quote(str):
+    """Prepare string to be used in a quoted string.
+
+    Turns backslash and double quote characters into quoted pairs.  These
+    are the only characters that need to be quoted inside a quoted string.
+    Does not add the surrounding double quotes.
+    """
+    return str.replace('\\', '\\\\').replace('"', '\\"')
+
+
+class AddrlistClass:
+    """Address parser class by Ben Escoto.
+
+    To understand what this class does, it helps to have a copy of RFC 2822 in
+    front of you.
+
+    Note: this class interface is deprecated and may be removed in the future.
+    Use rfc822.AddressList instead.
+    """
+
+    def __init__(self, field):
+        """Initialize a new instance.
+
+        `field' is an unparsed address header field, containing
+        one or more addresses.
+        """
+        self.specials = '()<>@,:;.\"[]'
+        self.pos = 0
+        self.LWS = ' \t'
+        self.CR = '\r\n'
+        self.FWS = self.LWS + self.CR
+        self.atomends = self.specials + self.LWS + self.CR
+        # Note that RFC 2822 now specifies `.' as obs-phrase, meaning that it
+        # is obsolete syntax.  RFC 2822 requires that we recognize obsolete
+        # syntax, so allow dots in phrases.
+        self.phraseends = self.atomends.replace('.', '')
+        self.field = field
+        self.commentlist = []
+
+    def gotonext(self):
+        """Parse up to the start of the next address."""
+        while self.pos < len(self.field):
+            if self.field[self.pos] in self.LWS + '\n\r':
+                self.pos += 1
+            elif self.field[self.pos] == '(':
+                self.commentlist.append(self.getcomment())
+            else:
+                break
+
+    def getaddrlist(self):
+        """Parse all addresses.
+
+        Returns a list containing all of the addresses.
+        """
+        result = []
+        while self.pos < len(self.field):
+            ad = self.getaddress()
+            if ad:
+                result += ad
+            else:
+                result.append(('', ''))
+        return result
+
+    def getaddress(self):
+        """Parse the next address."""
+        self.commentlist = []
+        self.gotonext()
+
+        oldpos = self.pos
+        oldcl = self.commentlist
+        plist = self.getphraselist()
+
+        self.gotonext()
+        returnlist = []
+
+        if self.pos >= len(self.field):
+            # Bad email address technically, no domain.
+            if plist:
+                returnlist = [(SPACE.join(self.commentlist), plist[0])]
+
+        elif self.field[self.pos] in '.@':
+            # email address is just an addrspec
+            # this isn't very efficient since we start over
+            self.pos = oldpos
+            self.commentlist = oldcl
+            addrspec = self.getaddrspec()
+            returnlist = [(SPACE.join(self.commentlist), addrspec)]
+
+        elif self.field[self.pos] == ':':
+            # address is a group
+            returnlist = []
+
+            fieldlen = len(self.field)
+            self.pos += 1
+            while self.pos < len(self.field):
+                self.gotonext()
+                if self.pos < fieldlen and self.field[self.pos] == ';':
+                    self.pos += 1
+                    break
+                returnlist = returnlist + self.getaddress()
+
+        elif self.field[self.pos] == '<':
+            # Address is a phrase then a route addr
+            routeaddr = self.getrouteaddr()
+
+            if self.commentlist:
+                returnlist = [(SPACE.join(plist) + ' (' +
+                               ' '.join(self.commentlist) + ')', routeaddr)]
+            else:
+                returnlist = [(SPACE.join(plist), routeaddr)]
+
+        else:
+            if plist:
+                returnlist = [(SPACE.join(self.commentlist), plist[0])]
+            elif self.field[self.pos] in self.specials:
+                self.pos += 1
+
+        self.gotonext()
+        if self.pos < len(self.field) and self.field[self.pos] == ',':
+            self.pos += 1
+        return returnlist
+
+    def getrouteaddr(self):
+        """Parse a route address (Return-path value).
+
+        This method just skips all the route stuff and returns the addrspec.
+        """
+        if self.field[self.pos] != '<':
+            return
+
+        expectroute = False
+        self.pos += 1
+        self.gotonext()
+        adlist = ''
+        while self.pos < len(self.field):
+            if expectroute:
+                self.getdomain()
+                expectroute = False
+            elif self.field[self.pos] == '>':
+                self.pos += 1
+                break
+            elif self.field[self.pos] == '@':
+                self.pos += 1
+                expectroute = True
+            elif self.field[self.pos] == ':':
+                self.pos += 1
+            else:
+                adlist = self.getaddrspec()
+                self.pos += 1
+                break
+            self.gotonext()
+
+        return adlist
+
+    def getaddrspec(self):
+        """Parse an RFC 2822 addr-spec."""
+        aslist = []
+
+        self.gotonext()
+        while self.pos < len(self.field):
+            if self.field[self.pos] == '.':
+                aslist.append('.')
+                self.pos += 1
+            elif self.field[self.pos] == '"':
+                aslist.append('"%s"' % quote(self.getquote()))
+            elif self.field[self.pos] in self.atomends:
+                break
+            else:
+                aslist.append(self.getatom())
+            self.gotonext()
+
+        if self.pos >= len(self.field) or self.field[self.pos] != '@':
+            return EMPTYSTRING.join(aslist)
+
+        aslist.append('@')
+        self.pos += 1
+        self.gotonext()
+        return EMPTYSTRING.join(aslist) + self.getdomain()
+
+    def getdomain(self):
+        """Get the complete domain name from an address."""
+        sdlist = []
+        while self.pos < len(self.field):
+            if self.field[self.pos] in self.LWS:
+                self.pos += 1
+            elif self.field[self.pos] == '(':
+                self.commentlist.append(self.getcomment())
+            elif self.field[self.pos] == '[':
+                sdlist.append(self.getdomainliteral())
+            elif self.field[self.pos] == '.':
+                self.pos += 1
+                sdlist.append('.')
+            elif self.field[self.pos] in self.atomends:
+                break
+            else:
+                sdlist.append(self.getatom())
+        return EMPTYSTRING.join(sdlist)
+
+    def getdelimited(self, beginchar, endchars, allowcomments=True):
+        """Parse a header fragment delimited by special characters.
+
+        `beginchar' is the start character for the fragment.
+        If self is not looking at an instance of `beginchar' then
+        getdelimited returns the empty string.
+
+        `endchars' is a sequence of allowable end-delimiting characters.
+        Parsing stops when one of these is encountered.
+
+        If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed
+        within the parsed fragment.
+        """
+        if self.field[self.pos] != beginchar:
+            return ''
+
+        slist = ['']
+        quote = False
+        self.pos += 1
+        while self.pos < len(self.field):
+            if quote:
+                slist.append(self.field[self.pos])
+                quote = False
+            elif self.field[self.pos] in endchars:
+                self.pos += 1
+                break
+            elif allowcomments and self.field[self.pos] == '(':
+                slist.append(self.getcomment())
+                continue        # have already advanced pos from getcomment
+            elif self.field[self.pos] == '\\':
+                quote = True
+            else:
+                slist.append(self.field[self.pos])
+            self.pos += 1
+
+        return EMPTYSTRING.join(slist)
+
+    def getquote(self):
+        """Get a quote-delimited fragment from self's field."""
+        return self.getdelimited('"', '"\r', False)
+
+    def getcomment(self):
+        """Get a parenthesis-delimited fragment from self's field."""
+        return self.getdelimited('(', ')\r', True)
+
+    def getdomainliteral(self):
+        """Parse an RFC 2822 domain-literal."""
+        return '[%s]' % self.getdelimited('[', ']\r', False)
+
+    def getatom(self, atomends=None):
+        """Parse an RFC 2822 atom.
+
+        Optional atomends specifies a different set of end token delimiters
+        (the default is to use self.atomends).  This is used e.g. in
+        getphraselist() since phrase endings must not include the `.' (which
+        is legal in phrases)."""
+        atomlist = ['']
+        if atomends is None:
+            atomends = self.atomends
+
+        while self.pos < len(self.field):
+            if self.field[self.pos] in atomends:
+                break
+            else:
+                atomlist.append(self.field[self.pos])
+            self.pos += 1
+
+        return EMPTYSTRING.join(atomlist)
+
+    def getphraselist(self):
+        """Parse a sequence of RFC 2822 phrases.
+
+        A phrase is a sequence of words, which are in turn either RFC 2822
+        atoms or quoted-strings.  Phrases are canonicalized by squeezing all
+        runs of continuous whitespace into one space.
+        """
+        plist = []
+
+        while self.pos < len(self.field):
+            if self.field[self.pos] in self.FWS:
+                self.pos += 1
+            elif self.field[self.pos] == '"':
+                plist.append(self.getquote())
+            elif self.field[self.pos] == '(':
+                self.commentlist.append(self.getcomment())
+            elif self.field[self.pos] in self.phraseends:
+                break
+            else:
+                plist.append(self.getatom(self.phraseends))
+
+        return plist
+
+class AddressList(AddrlistClass):
+    """An AddressList encapsulates a list of parsed RFC 2822 addresses."""
+    def __init__(self, field):
+        AddrlistClass.__init__(self, field)
+        if field:
+            self.addresslist = self.getaddrlist()
+        else:
+            self.addresslist = []
+
+    def __len__(self):
+        return len(self.addresslist)
+
+    def __add__(self, other):
+        # Set union
+        newaddr = AddressList(None)
+        newaddr.addresslist = self.addresslist[:]
+        for x in other.addresslist:
+            if not x in self.addresslist:
+                newaddr.addresslist.append(x)
+        return newaddr
+
+    def __iadd__(self, other):
+        # Set union, in-place
+        for x in other.addresslist:
+            if not x in self.addresslist:
+                self.addresslist.append(x)
+        return self
+
+    def __sub__(self, other):
+        # Set difference
+        newaddr = AddressList(None)
+        for x in self.addresslist:
+            if not x in other.addresslist:
+                newaddr.addresslist.append(x)
+        return newaddr
+
+    def __isub__(self, other):
+        # Set difference, in-place
+        for x in other.addresslist:
+            if x in self.addresslist:
+                self.addresslist.remove(x)
+        return self
+
+    def __getitem__(self, index):
+        # Make indexing, slices, and 'in' work
+        return self.addresslist[index]
diff --git a/src/main/resources/PythonLibs/email/base64mime.py b/src/main/resources/PythonLibs/email/base64mime.py
new file mode 100644
index 0000000000000000000000000000000000000000..4aa800026d650f33971729ba67d00bb1931547f9
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/base64mime.py
@@ -0,0 +1,183 @@
+# Copyright (C) 2002-2006 Python Software Foundation
+# Author: Ben Gertzfield
+# Contact: email-sig@python.org
+
+"""Base64 content transfer encoding per RFCs 2045-2047.
+
+This module handles the content transfer encoding method defined in RFC 2045
+to encode arbitrary 8-bit data using the three 8-bit bytes in four 7-bit
+characters encoding known as Base64.
+
+It is used in the MIME standards for email to attach images, audio, and text
+using some 8-bit character sets to messages.
+
+This module provides an interface to encode and decode both headers and bodies
+with Base64 encoding.
+
+RFC 2045 defines a method for including character set information in an
+`encoded-word' in a header.  This method is commonly used for 8-bit real names
+in To:, From:, Cc:, etc. fields, as well as Subject: lines.
+
+This module does not do the line wrapping or end-of-line character conversion
+necessary for proper internationalized headers; it only does dumb encoding and
+decoding.  To deal with the various line wrapping issues, use the email.header
+module.
+"""
+
+__all__ = [
+    'base64_len',
+    'body_decode',
+    'body_encode',
+    'decode',
+    'decodestring',
+    'encode',
+    'encodestring',
+    'header_encode',
+    ]
+
+
+from binascii import b2a_base64, a2b_base64
+from email.utils import fix_eols
+
+CRLF = '\r\n'
+NL = '\n'
+EMPTYSTRING = ''
+
+# See also Charset.py
+MISC_LEN = 7
+
+
+
+# Helpers
+def base64_len(s):
+    """Return the length of s when it is encoded with base64."""
+    groups_of_3, leftover = divmod(len(s), 3)
+    # 4 bytes out for each 3 bytes (or nonzero fraction thereof) in.
+    # Thanks, Tim!
+    n = groups_of_3 * 4
+    if leftover:
+        n += 4
+    return n
+
+
+
+def header_encode(header, charset='iso-8859-1', keep_eols=False,
+                  maxlinelen=76, eol=NL):
+    """Encode a single header line with Base64 encoding in a given charset.
+
+    Defined in RFC 2045, this Base64 encoding is identical to normal Base64
+    encoding, except that each line must be intelligently wrapped (respecting
+    the Base64 encoding), and subsequent lines must start with a space.
+
+    charset names the character set to use to encode the header.  It defaults
+    to iso-8859-1.
+
+    End-of-line characters (\\r, \\n, \\r\\n) will be automatically converted
+    to the canonical email line separator \\r\\n unless the keep_eols
+    parameter is True (the default is False).
+
+    Each line of the header will be terminated in the value of eol, which
+    defaults to "\\n".  Set this to "\\r\\n" if you are using the result of
+    this function directly in email.
+
+    The resulting string will be in the form:
+
+    "=?charset?b?WW/5ciBtYXp66XLrIHf8eiBhIGhhbXBzdGHuciBBIFlv+XIgbWF6euly?=\\n
+      =?charset?b?6yB3/HogYSBoYW1wc3Rh7nIgQkMgWW/5ciBtYXp66XLrIHf8eiBhIGhh?="
+
+    with each line wrapped at, at most, maxlinelen characters (defaults to 76
+    characters).
+    """
+    # Return empty headers unchanged
+    if not header:
+        return header
+
+    if not keep_eols:
+        header = fix_eols(header)
+
+    # Base64 encode each line, in encoded chunks no greater than maxlinelen in
+    # length, after the RFC chrome is added in.
+    base64ed = []
+    max_encoded = maxlinelen - len(charset) - MISC_LEN
+    max_unencoded = max_encoded * 3 // 4
+
+    for i in range(0, len(header), max_unencoded):
+        base64ed.append(b2a_base64(header[i:i+max_unencoded]))
+
+    # Now add the RFC chrome to each encoded chunk
+    lines = []
+    for line in base64ed:
+        # Ignore the last character of each line if it is a newline
+        if line.endswith(NL):
+            line = line[:-1]
+        # Add the chrome
+        lines.append('=?%s?b?%s?=' % (charset, line))
+    # Glue the lines together and return it.  BAW: should we be able to
+    # specify the leading whitespace in the joiner?
+    joiner = eol + ' '
+    return joiner.join(lines)
+
+
+
+def encode(s, binary=True, maxlinelen=76, eol=NL):
+    """Encode a string with base64.
+
+    Each line will be wrapped at, at most, maxlinelen characters (defaults to
+    76 characters).
+
+    If binary is False, end-of-line characters will be converted to the
+    canonical email end-of-line sequence \\r\\n.  Otherwise they will be left
+    verbatim (this is the default).
+
+    Each line of encoded text will end with eol, which defaults to "\\n".  Set
+    this to "\\r\\n" if you will be using the result of this function directly
+    in an email.
+    """
+    if not s:
+        return s
+
+    if not binary:
+        s = fix_eols(s)
+
+    encvec = []
+    max_unencoded = maxlinelen * 3 // 4
+    for i in range(0, len(s), max_unencoded):
+        # BAW: should encode() inherit b2a_base64()'s dubious behavior in
+        # adding a newline to the encoded string?
+        enc = b2a_base64(s[i:i + max_unencoded])
+        if enc.endswith(NL) and eol != NL:
+            enc = enc[:-1] + eol
+        encvec.append(enc)
+    return EMPTYSTRING.join(encvec)
+
+
+# For convenience and backwards compatibility w/ standard base64 module
+body_encode = encode
+encodestring = encode
+
+
+
+def decode(s, convert_eols=None):
+    """Decode a raw base64 string.
+
+    If convert_eols is set to a string value, all canonical email linefeeds,
+    e.g. "\\r\\n", in the decoded text will be converted to the value of
+    convert_eols.  os.linesep is a good choice for convert_eols if you are
+    decoding a text attachment.
+
+    This function does not parse a full MIME header value encoded with
+    base64 (like =?iso-8895-1?b?bmloISBuaWgh?=) -- please use the high
+    level email.header class for that functionality.
+    """
+    if not s:
+        return s
+
+    dec = a2b_base64(s)
+    if convert_eols:
+        return dec.replace(CRLF, convert_eols)
+    return dec
+
+
+# For convenience and backwards compatibility w/ standard base64 module
+body_decode = decode
+decodestring = decode
diff --git a/src/main/resources/PythonLibs/email/charset.py b/src/main/resources/PythonLibs/email/charset.py
new file mode 100644
index 0000000000000000000000000000000000000000..dddaa76c55d760614b52a383b98f0db6dc45dfdb
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/charset.py
@@ -0,0 +1,397 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Ben Gertzfield, Barry Warsaw
+# Contact: email-sig@python.org
+
+__all__ = [
+    'Charset',
+    'add_alias',
+    'add_charset',
+    'add_codec',
+    ]
+
+import codecs
+import email.base64mime
+import email.quoprimime
+
+from email import errors
+from email.encoders import encode_7or8bit
+
+
+
+# Flags for types of header encodings
+QP          = 1 # Quoted-Printable
+BASE64      = 2 # Base64
+SHORTEST    = 3 # the shorter of QP and base64, but only for headers
+
+# In "=?charset?q?hello_world?=", the =?, ?q?, and ?= add up to 7
+MISC_LEN = 7
+
+DEFAULT_CHARSET = 'us-ascii'
+
+
+
+# Defaults
+CHARSETS = {
+    # input        header enc  body enc output conv
+    'iso-8859-1':  (QP,        QP,      None),
+    'iso-8859-2':  (QP,        QP,      None),
+    'iso-8859-3':  (QP,        QP,      None),
+    'iso-8859-4':  (QP,        QP,      None),
+    # iso-8859-5 is Cyrillic, and not especially used
+    # iso-8859-6 is Arabic, also not particularly used
+    # iso-8859-7 is Greek, QP will not make it readable
+    # iso-8859-8 is Hebrew, QP will not make it readable
+    'iso-8859-9':  (QP,        QP,      None),
+    'iso-8859-10': (QP,        QP,      None),
+    # iso-8859-11 is Thai, QP will not make it readable
+    'iso-8859-13': (QP,        QP,      None),
+    'iso-8859-14': (QP,        QP,      None),
+    'iso-8859-15': (QP,        QP,      None),
+    'iso-8859-16': (QP,        QP,      None),
+    'windows-1252':(QP,        QP,      None),
+    'viscii':      (QP,        QP,      None),
+    'us-ascii':    (None,      None,    None),
+    'big5':        (BASE64,    BASE64,  None),
+    'gb2312':      (BASE64,    BASE64,  None),
+    'euc-jp':      (BASE64,    None,    'iso-2022-jp'),
+    'shift_jis':   (BASE64,    None,    'iso-2022-jp'),
+    'iso-2022-jp': (BASE64,    None,    None),
+    'koi8-r':      (BASE64,    BASE64,  None),
+    'utf-8':       (SHORTEST,  BASE64, 'utf-8'),
+    # We're making this one up to represent raw unencoded 8-bit
+    '8bit':        (None,      BASE64, 'utf-8'),
+    }
+
+# Aliases for other commonly-used names for character sets.  Map
+# them to the real ones used in email.
+ALIASES = {
+    'latin_1': 'iso-8859-1',
+    'latin-1': 'iso-8859-1',
+    'latin_2': 'iso-8859-2',
+    'latin-2': 'iso-8859-2',
+    'latin_3': 'iso-8859-3',
+    'latin-3': 'iso-8859-3',
+    'latin_4': 'iso-8859-4',
+    'latin-4': 'iso-8859-4',
+    'latin_5': 'iso-8859-9',
+    'latin-5': 'iso-8859-9',
+    'latin_6': 'iso-8859-10',
+    'latin-6': 'iso-8859-10',
+    'latin_7': 'iso-8859-13',
+    'latin-7': 'iso-8859-13',
+    'latin_8': 'iso-8859-14',
+    'latin-8': 'iso-8859-14',
+    'latin_9': 'iso-8859-15',
+    'latin-9': 'iso-8859-15',
+    'latin_10':'iso-8859-16',
+    'latin-10':'iso-8859-16',
+    'cp949':   'ks_c_5601-1987',
+    'euc_jp':  'euc-jp',
+    'euc_kr':  'euc-kr',
+    'ascii':   'us-ascii',
+    }
+
+
+# Map charsets to their Unicode codec strings.
+CODEC_MAP = {
+    'gb2312':      'eucgb2312_cn',
+    'big5':        'big5_tw',
+    # Hack: We don't want *any* conversion for stuff marked us-ascii, as all
+    # sorts of garbage might be sent to us in the guise of 7-bit us-ascii.
+    # Let that stuff pass through without conversion to/from Unicode.
+    'us-ascii':    None,
+    }
+
+
+
+# Convenience functions for extending the above mappings
+def add_charset(charset, header_enc=None, body_enc=None, output_charset=None):
+    """Add character set properties to the global registry.
+
+    charset is the input character set, and must be the canonical name of a
+    character set.
+
+    Optional header_enc and body_enc is either Charset.QP for
+    quoted-printable, Charset.BASE64 for base64 encoding, Charset.SHORTEST for
+    the shortest of qp or base64 encoding, or None for no encoding.  SHORTEST
+    is only valid for header_enc.  It describes how message headers and
+    message bodies in the input charset are to be encoded.  Default is no
+    encoding.
+
+    Optional output_charset is the character set that the output should be
+    in.  Conversions will proceed from input charset, to Unicode, to the
+    output charset when the method Charset.convert() is called.  The default
+    is to output in the same character set as the input.
+
+    Both input_charset and output_charset must have Unicode codec entries in
+    the module's charset-to-codec mapping; use add_codec(charset, codecname)
+    to add codecs the module does not know about.  See the codecs module's
+    documentation for more information.
+    """
+    if body_enc == SHORTEST:
+        raise ValueError('SHORTEST not allowed for body_enc')
+    CHARSETS[charset] = (header_enc, body_enc, output_charset)
+
+
+def add_alias(alias, canonical):
+    """Add a character set alias.
+
+    alias is the alias name, e.g. latin-1
+    canonical is the character set's canonical name, e.g. iso-8859-1
+    """
+    ALIASES[alias] = canonical
+
+
+def add_codec(charset, codecname):
+    """Add a codec that map characters in the given charset to/from Unicode.
+
+    charset is the canonical name of a character set.  codecname is the name
+    of a Python codec, as appropriate for the second argument to the unicode()
+    built-in, or to the encode() method of a Unicode string.
+    """
+    CODEC_MAP[charset] = codecname
+
+
+
+class Charset:
+    """Map character sets to their email properties.
+
+    This class provides information about the requirements imposed on email
+    for a specific character set.  It also provides convenience routines for
+    converting between character sets, given the availability of the
+    applicable codecs.  Given a character set, it will do its best to provide
+    information on how to use that character set in an email in an
+    RFC-compliant way.
+
+    Certain character sets must be encoded with quoted-printable or base64
+    when used in email headers or bodies.  Certain character sets must be
+    converted outright, and are not allowed in email.  Instances of this
+    module expose the following information about a character set:
+
+    input_charset: The initial character set specified.  Common aliases
+                   are converted to their `official' email names (e.g. latin_1
+                   is converted to iso-8859-1).  Defaults to 7-bit us-ascii.
+
+    header_encoding: If the character set must be encoded before it can be
+                     used in an email header, this attribute will be set to
+                     Charset.QP (for quoted-printable), Charset.BASE64 (for
+                     base64 encoding), or Charset.SHORTEST for the shortest of
+                     QP or BASE64 encoding.  Otherwise, it will be None.
+
+    body_encoding: Same as header_encoding, but describes the encoding for the
+                   mail message's body, which indeed may be different than the
+                   header encoding.  Charset.SHORTEST is not allowed for
+                   body_encoding.
+
+    output_charset: Some character sets must be converted before the can be
+                    used in email headers or bodies.  If the input_charset is
+                    one of them, this attribute will contain the name of the
+                    charset output will be converted to.  Otherwise, it will
+                    be None.
+
+    input_codec: The name of the Python codec used to convert the
+                 input_charset to Unicode.  If no conversion codec is
+                 necessary, this attribute will be None.
+
+    output_codec: The name of the Python codec used to convert Unicode
+                  to the output_charset.  If no conversion codec is necessary,
+                  this attribute will have the same value as the input_codec.
+    """
+    def __init__(self, input_charset=DEFAULT_CHARSET):
+        # RFC 2046, $4.1.2 says charsets are not case sensitive.  We coerce to
+        # unicode because its .lower() is locale insensitive.  If the argument
+        # is already a unicode, we leave it at that, but ensure that the
+        # charset is ASCII, as the standard (RFC XXX) requires.
+        try:
+            if isinstance(input_charset, unicode):
+                input_charset.encode('ascii')
+            else:
+                input_charset = unicode(input_charset, 'ascii')
+        except UnicodeError:
+            raise errors.CharsetError(input_charset)
+        input_charset = input_charset.lower().encode('ascii')
+        # Set the input charset after filtering through the aliases and/or codecs
+        if not (input_charset in ALIASES or input_charset in CHARSETS):
+            try:
+                input_charset = codecs.lookup(input_charset).name
+            except LookupError:
+                pass
+        self.input_charset = ALIASES.get(input_charset, input_charset)
+        # We can try to guess which encoding and conversion to use by the
+        # charset_map dictionary.  Try that first, but let the user override
+        # it.
+        henc, benc, conv = CHARSETS.get(self.input_charset,
+                                        (SHORTEST, BASE64, None))
+        if not conv:
+            conv = self.input_charset
+        # Set the attributes, allowing the arguments to override the default.
+        self.header_encoding = henc
+        self.body_encoding = benc
+        self.output_charset = ALIASES.get(conv, conv)
+        # Now set the codecs.  If one isn't defined for input_charset,
+        # guess and try a Unicode codec with the same name as input_codec.
+        self.input_codec = CODEC_MAP.get(self.input_charset,
+                                         self.input_charset)
+        self.output_codec = CODEC_MAP.get(self.output_charset,
+                                          self.output_charset)
+
+    def __str__(self):
+        return self.input_charset.lower()
+
+    __repr__ = __str__
+
+    def __eq__(self, other):
+        return str(self) == str(other).lower()
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def get_body_encoding(self):
+        """Return the content-transfer-encoding used for body encoding.
+
+        This is either the string `quoted-printable' or `base64' depending on
+        the encoding used, or it is a function in which case you should call
+        the function with a single argument, the Message object being
+        encoded.  The function should then set the Content-Transfer-Encoding
+        header itself to whatever is appropriate.
+
+        Returns "quoted-printable" if self.body_encoding is QP.
+        Returns "base64" if self.body_encoding is BASE64.
+        Returns "7bit" otherwise.
+        """
+        assert self.body_encoding != SHORTEST
+        if self.body_encoding == QP:
+            return 'quoted-printable'
+        elif self.body_encoding == BASE64:
+            return 'base64'
+        else:
+            return encode_7or8bit
+
+    def convert(self, s):
+        """Convert a string from the input_codec to the output_codec."""
+        if self.input_codec != self.output_codec:
+            return unicode(s, self.input_codec).encode(self.output_codec)
+        else:
+            return s
+
+    def to_splittable(self, s):
+        """Convert a possibly multibyte string to a safely splittable format.
+
+        Uses the input_codec to try and convert the string to Unicode, so it
+        can be safely split on character boundaries (even for multibyte
+        characters).
+
+        Returns the string as-is if it isn't known how to convert it to
+        Unicode with the input_charset.
+
+        Characters that could not be converted to Unicode will be replaced
+        with the Unicode replacement character U+FFFD.
+        """
+        if isinstance(s, unicode) or self.input_codec is None:
+            return s
+        try:
+            return unicode(s, self.input_codec, 'replace')
+        except LookupError:
+            # Input codec not installed on system, so return the original
+            # string unchanged.
+            return s
+
+    def from_splittable(self, ustr, to_output=True):
+        """Convert a splittable string back into an encoded string.
+
+        Uses the proper codec to try and convert the string from Unicode back
+        into an encoded format.  Return the string as-is if it is not Unicode,
+        or if it could not be converted from Unicode.
+
+        Characters that could not be converted from Unicode will be replaced
+        with an appropriate character (usually '?').
+
+        If to_output is True (the default), uses output_codec to convert to an
+        encoded format.  If to_output is False, uses input_codec.
+        """
+        if to_output:
+            codec = self.output_codec
+        else:
+            codec = self.input_codec
+        if not isinstance(ustr, unicode) or codec is None:
+            return ustr
+        try:
+            return ustr.encode(codec, 'replace')
+        except LookupError:
+            # Output codec not installed
+            return ustr
+
+    def get_output_charset(self):
+        """Return the output character set.
+
+        This is self.output_charset if that is not None, otherwise it is
+        self.input_charset.
+        """
+        return self.output_charset or self.input_charset
+
+    def encoded_header_len(self, s):
+        """Return the length of the encoded header string."""
+        cset = self.get_output_charset()
+        # The len(s) of a 7bit encoding is len(s)
+        if self.header_encoding == BASE64:
+            return email.base64mime.base64_len(s) + len(cset) + MISC_LEN
+        elif self.header_encoding == QP:
+            return email.quoprimime.header_quopri_len(s) + len(cset) + MISC_LEN
+        elif self.header_encoding == SHORTEST:
+            lenb64 = email.base64mime.base64_len(s)
+            lenqp = email.quoprimime.header_quopri_len(s)
+            return min(lenb64, lenqp) + len(cset) + MISC_LEN
+        else:
+            return len(s)
+
+    def header_encode(self, s, convert=False):
+        """Header-encode a string, optionally converting it to output_charset.
+
+        If convert is True, the string will be converted from the input
+        charset to the output charset automatically.  This is not useful for
+        multibyte character sets, which have line length issues (multibyte
+        characters must be split on a character, not a byte boundary); use the
+        high-level Header class to deal with these issues.  convert defaults
+        to False.
+
+        The type of encoding (base64 or quoted-printable) will be based on
+        self.header_encoding.
+        """
+        cset = self.get_output_charset()
+        if convert:
+            s = self.convert(s)
+        # 7bit/8bit encodings return the string unchanged (modulo conversions)
+        if self.header_encoding == BASE64:
+            return email.base64mime.header_encode(s, cset)
+        elif self.header_encoding == QP:
+            return email.quoprimime.header_encode(s, cset, maxlinelen=None)
+        elif self.header_encoding == SHORTEST:
+            lenb64 = email.base64mime.base64_len(s)
+            lenqp = email.quoprimime.header_quopri_len(s)
+            if lenb64 < lenqp:
+                return email.base64mime.header_encode(s, cset)
+            else:
+                return email.quoprimime.header_encode(s, cset, maxlinelen=None)
+        else:
+            return s
+
+    def body_encode(self, s, convert=True):
+        """Body-encode a string and convert it to output_charset.
+
+        If convert is True (the default), the string will be converted from
+        the input charset to output charset automatically.  Unlike
+        header_encode(), there are no issues with byte boundaries and
+        multibyte charsets in email bodies, so this is usually pretty safe.
+
+        The type of encoding (base64 or quoted-printable) will be based on
+        self.body_encoding.
+        """
+        if convert:
+            s = self.convert(s)
+        # 7bit/8bit encodings return the string unchanged (module conversions)
+        if self.body_encoding is BASE64:
+            return email.base64mime.body_encode(s)
+        elif self.body_encoding is QP:
+            return email.quoprimime.body_encode(s)
+        else:
+            return s
diff --git a/src/main/resources/PythonLibs/email/encoders.py b/src/main/resources/PythonLibs/email/encoders.py
new file mode 100644
index 0000000000000000000000000000000000000000..af45e62c333100021a7c8f8e51f85769d8eba0ac
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/encoders.py
@@ -0,0 +1,82 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Encodings and related functions."""
+
+__all__ = [
+    'encode_7or8bit',
+    'encode_base64',
+    'encode_noop',
+    'encode_quopri',
+    ]
+
+import base64
+
+from quopri import encodestring as _encodestring
+
+
+
+def _qencode(s):
+    enc = _encodestring(s, quotetabs=True)
+    # Must encode spaces, which quopri.encodestring() doesn't do
+    return enc.replace(' ', '=20')
+
+
+def _bencode(s):
+    # We can't quite use base64.encodestring() since it tacks on a "courtesy
+    # newline".  Blech!
+    if not s:
+        return s
+    hasnewline = (s[-1] == '\n')
+    value = base64.encodestring(s)
+    if not hasnewline and value[-1] == '\n':
+        return value[:-1]
+    return value
+
+
+
+def encode_base64(msg):
+    """Encode the message's payload in Base64.
+
+    Also, add an appropriate Content-Transfer-Encoding header.
+    """
+    orig = msg.get_payload()
+    encdata = _bencode(orig)
+    msg.set_payload(encdata)
+    msg['Content-Transfer-Encoding'] = 'base64'
+
+
+
+def encode_quopri(msg):
+    """Encode the message's payload in quoted-printable.
+
+    Also, add an appropriate Content-Transfer-Encoding header.
+    """
+    orig = msg.get_payload()
+    encdata = _qencode(orig)
+    msg.set_payload(encdata)
+    msg['Content-Transfer-Encoding'] = 'quoted-printable'
+
+
+
+def encode_7or8bit(msg):
+    """Set the Content-Transfer-Encoding header to 7bit or 8bit."""
+    orig = msg.get_payload()
+    if orig is None:
+        # There's no payload.  For backwards compatibility we use 7bit
+        msg['Content-Transfer-Encoding'] = '7bit'
+        return
+    # We play a trick to make this go fast.  If encoding to ASCII succeeds, we
+    # know the data must be 7bit, otherwise treat it as 8bit.
+    try:
+        orig.encode('ascii')
+    except UnicodeError:
+        msg['Content-Transfer-Encoding'] = '8bit'
+    else:
+        msg['Content-Transfer-Encoding'] = '7bit'
+
+
+
+def encode_noop(msg):
+    """Do nothing."""
diff --git a/src/main/resources/PythonLibs/email/errors.py b/src/main/resources/PythonLibs/email/errors.py
new file mode 100644
index 0000000000000000000000000000000000000000..d52a624601f09216ba49f727c6b3fd1853b9ef68
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/errors.py
@@ -0,0 +1,57 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""email package exception classes."""
+
+
+
+class MessageError(Exception):
+    """Base class for errors in the email package."""
+
+
+class MessageParseError(MessageError):
+    """Base class for message parsing errors."""
+
+
+class HeaderParseError(MessageParseError):
+    """Error while parsing headers."""
+
+
+class BoundaryError(MessageParseError):
+    """Couldn't find terminating boundary."""
+
+
+class MultipartConversionError(MessageError, TypeError):
+    """Conversion to a multipart is prohibited."""
+
+
+class CharsetError(MessageError):
+    """An illegal charset was given."""
+
+
+
+# These are parsing defects which the parser was able to work around.
+class MessageDefect:
+    """Base class for a message defect."""
+
+    def __init__(self, line=None):
+        self.line = line
+
+class NoBoundaryInMultipartDefect(MessageDefect):
+    """A message claimed to be a multipart but had no boundary parameter."""
+
+class StartBoundaryNotFoundDefect(MessageDefect):
+    """The claimed start boundary was never found."""
+
+class FirstHeaderLineIsContinuationDefect(MessageDefect):
+    """A message had a continuation line as its first header line."""
+
+class MisplacedEnvelopeHeaderDefect(MessageDefect):
+    """A 'Unix-from' header was found in the middle of a header block."""
+
+class MalformedHeaderDefect(MessageDefect):
+    """Found a header that was missing a colon, or was otherwise malformed."""
+
+class MultipartInvariantViolationDefect(MessageDefect):
+    """A message claimed to be a multipart but no subparts were found."""
diff --git a/src/main/resources/PythonLibs/email/feedparser.py b/src/main/resources/PythonLibs/email/feedparser.py
new file mode 100644
index 0000000000000000000000000000000000000000..15db26d22a275698dcf59fabe4f86c41fee6984d
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/feedparser.py
@@ -0,0 +1,484 @@
+# Copyright (C) 2004-2006 Python Software Foundation
+# Authors: Baxter, Wouters and Warsaw
+# Contact: email-sig@python.org
+
+"""FeedParser - An email feed parser.
+
+The feed parser implements an interface for incrementally parsing an email
+message, line by line.  This has advantages for certain applications, such as
+those reading email messages off a socket.
+
+FeedParser.feed() is the primary interface for pushing new data into the
+parser.  It returns when there's nothing more it can do with the available
+data.  When you have no more data to push into the parser, call .close().
+This completes the parsing and returns the root message object.
+
+The other advantage of this parser is that it will never raise a parsing
+exception.  Instead, when it finds something unexpected, it adds a 'defect' to
+the current message.  Defects are just instances that live on the message
+object's .defects attribute.
+"""
+
+__all__ = ['FeedParser']
+
+import re
+
+from email import errors
+from email import message
+
+NLCRE = re.compile('\r\n|\r|\n')
+NLCRE_bol = re.compile('(\r\n|\r|\n)')
+NLCRE_eol = re.compile('(\r\n|\r|\n)\Z')
+NLCRE_crack = re.compile('(\r\n|\r|\n)')
+# RFC 2822 $3.6.8 Optional fields.  ftext is %d33-57 / %d59-126, Any character
+# except controls, SP, and ":".
+headerRE = re.compile(r'^(From |[\041-\071\073-\176]{1,}:|[\t ])')
+EMPTYSTRING = ''
+NL = '\n'
+
+NeedMoreData = object()
+
+
+
+class BufferedSubFile(object):
+    """A file-ish object that can have new data loaded into it.
+
+    You can also push and pop line-matching predicates onto a stack.  When the
+    current predicate matches the current line, a false EOF response
+    (i.e. empty string) is returned instead.  This lets the parser adhere to a
+    simple abstraction -- it parses until EOF closes the current message.
+    """
+    def __init__(self):
+        # The last partial line pushed into this object.
+        self._partial = ''
+        # The list of full, pushed lines, in reverse order
+        self._lines = []
+        # The stack of false-EOF checking predicates.
+        self._eofstack = []
+        # A flag indicating whether the file has been closed or not.
+        self._closed = False
+
+    def push_eof_matcher(self, pred):
+        self._eofstack.append(pred)
+
+    def pop_eof_matcher(self):
+        return self._eofstack.pop()
+
+    def close(self):
+        # Don't forget any trailing partial line.
+        self._lines.append(self._partial)
+        self._partial = ''
+        self._closed = True
+
+    def readline(self):
+        if not self._lines:
+            if self._closed:
+                return ''
+            return NeedMoreData
+        # Pop the line off the stack and see if it matches the current
+        # false-EOF predicate.
+        line = self._lines.pop()
+        # RFC 2046, section 5.1.2 requires us to recognize outer level
+        # boundaries at any level of inner nesting.  Do this, but be sure it's
+        # in the order of most to least nested.
+        for ateof in self._eofstack[::-1]:
+            if ateof(line):
+                # We're at the false EOF.  But push the last line back first.
+                self._lines.append(line)
+                return ''
+        return line
+
+    def unreadline(self, line):
+        # Let the consumer push a line back into the buffer.
+        assert line is not NeedMoreData
+        self._lines.append(line)
+
+    def push(self, data):
+        """Push some new data into this object."""
+        # Handle any previous leftovers
+        data, self._partial = self._partial + data, ''
+        # Crack into lines, but preserve the newlines on the end of each
+        parts = NLCRE_crack.split(data)
+        # The *ahem* interesting behaviour of re.split when supplied grouping
+        # parentheses is that the last element of the resulting list is the
+        # data after the final RE.  In the case of a NL/CR terminated string,
+        # this is the empty string.
+        self._partial = parts.pop()
+        #GAN 29Mar09  bugs 1555570, 1721862  Confusion at 8K boundary ending with \r:
+        # is there a \n to follow later?
+        if not self._partial and parts and parts[-1].endswith('\r'):
+            self._partial = parts.pop(-2)+parts.pop()
+        # parts is a list of strings, alternating between the line contents
+        # and the eol character(s).  Gather up a list of lines after
+        # re-attaching the newlines.
+        lines = []
+        for i in range(len(parts) // 2):
+            lines.append(parts[i*2] + parts[i*2+1])
+        self.pushlines(lines)
+
+    def pushlines(self, lines):
+        # Reverse and insert at the front of the lines.
+        self._lines[:0] = lines[::-1]
+
+    def is_closed(self):
+        return self._closed
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        line = self.readline()
+        if line == '':
+            raise StopIteration
+        return line
+
+
+
+class FeedParser:
+    """A feed-style parser of email."""
+
+    def __init__(self, _factory=message.Message):
+        """_factory is called with no arguments to create a new message obj"""
+        self._factory = _factory
+        self._input = BufferedSubFile()
+        self._msgstack = []
+        self._parse = self._parsegen().next
+        self._cur = None
+        self._last = None
+        self._headersonly = False
+
+    # Non-public interface for supporting Parser's headersonly flag
+    def _set_headersonly(self):
+        self._headersonly = True
+
+    def feed(self, data):
+        """Push more data into the parser."""
+        self._input.push(data)
+        self._call_parse()
+
+    def _call_parse(self):
+        try:
+            self._parse()
+        except StopIteration:
+            pass
+
+    def close(self):
+        """Parse all remaining data and return the root message object."""
+        self._input.close()
+        self._call_parse()
+        root = self._pop_message()
+        assert not self._msgstack
+        # Look for final set of defects
+        if root.get_content_maintype() == 'multipart' \
+               and not root.is_multipart():
+            root.defects.append(errors.MultipartInvariantViolationDefect())
+        return root
+
+    def _new_message(self):
+        msg = self._factory()
+        if self._cur and self._cur.get_content_type() == 'multipart/digest':
+            msg.set_default_type('message/rfc822')
+        if self._msgstack:
+            self._msgstack[-1].attach(msg)
+        self._msgstack.append(msg)
+        self._cur = msg
+        self._last = msg
+
+    def _pop_message(self):
+        retval = self._msgstack.pop()
+        if self._msgstack:
+            self._cur = self._msgstack[-1]
+        else:
+            self._cur = None
+        return retval
+
+    def _parsegen(self):
+        # Create a new message and start by parsing headers.
+        self._new_message()
+        headers = []
+        # Collect the headers, searching for a line that doesn't match the RFC
+        # 2822 header or continuation pattern (including an empty line).
+        for line in self._input:
+            if line is NeedMoreData:
+                yield NeedMoreData
+                continue
+            if not headerRE.match(line):
+                # If we saw the RFC defined header/body separator
+                # (i.e. newline), just throw it away. Otherwise the line is
+                # part of the body so push it back.
+                if not NLCRE.match(line):
+                    self._input.unreadline(line)
+                break
+            headers.append(line)
+        # Done with the headers, so parse them and figure out what we're
+        # supposed to see in the body of the message.
+        self._parse_headers(headers)
+        # Headers-only parsing is a backwards compatibility hack, which was
+        # necessary in the older parser, which could raise errors.  All
+        # remaining lines in the input are thrown into the message body.
+        if self._headersonly:
+            lines = []
+            while True:
+                line = self._input.readline()
+                if line is NeedMoreData:
+                    yield NeedMoreData
+                    continue
+                if line == '':
+                    break
+                lines.append(line)
+            self._cur.set_payload(EMPTYSTRING.join(lines))
+            return
+        if self._cur.get_content_type() == 'message/delivery-status':
+            # message/delivery-status contains blocks of headers separated by
+            # a blank line.  We'll represent each header block as a separate
+            # nested message object, but the processing is a bit different
+            # than standard message/* types because there is no body for the
+            # nested messages.  A blank line separates the subparts.
+            while True:
+                self._input.push_eof_matcher(NLCRE.match)
+                for retval in self._parsegen():
+                    if retval is NeedMoreData:
+                        yield NeedMoreData
+                        continue
+                    break
+                msg = self._pop_message()
+                # We need to pop the EOF matcher in order to tell if we're at
+                # the end of the current file, not the end of the last block
+                # of message headers.
+                self._input.pop_eof_matcher()
+                # The input stream must be sitting at the newline or at the
+                # EOF.  We want to see if we're at the end of this subpart, so
+                # first consume the blank line, then test the next line to see
+                # if we're at this subpart's EOF.
+                while True:
+                    line = self._input.readline()
+                    if line is NeedMoreData:
+                        yield NeedMoreData
+                        continue
+                    break
+                while True:
+                    line = self._input.readline()
+                    if line is NeedMoreData:
+                        yield NeedMoreData
+                        continue
+                    break
+                if line == '':
+                    break
+                # Not at EOF so this is a line we're going to need.
+                self._input.unreadline(line)
+            return
+        if self._cur.get_content_maintype() == 'message':
+            # The message claims to be a message/* type, then what follows is
+            # another RFC 2822 message.
+            for retval in self._parsegen():
+                if retval is NeedMoreData:
+                    yield NeedMoreData
+                    continue
+                break
+            self._pop_message()
+            return
+        if self._cur.get_content_maintype() == 'multipart':
+            boundary = self._cur.get_boundary()
+            if boundary is None:
+                # The message /claims/ to be a multipart but it has not
+                # defined a boundary.  That's a problem which we'll handle by
+                # reading everything until the EOF and marking the message as
+                # defective.
+                self._cur.defects.append(errors.NoBoundaryInMultipartDefect())
+                lines = []
+                for line in self._input:
+                    if line is NeedMoreData:
+                        yield NeedMoreData
+                        continue
+                    lines.append(line)
+                self._cur.set_payload(EMPTYSTRING.join(lines))
+                return
+            # Create a line match predicate which matches the inter-part
+            # boundary as well as the end-of-multipart boundary.  Don't push
+            # this onto the input stream until we've scanned past the
+            # preamble.
+            separator = '--' + boundary
+            boundaryre = re.compile(
+                '(?P<sep>' + re.escape(separator) +
+                r')(?P<end>--)?(?P<ws>[ \t]*)(?P<linesep>\r\n|\r|\n)?$')
+            capturing_preamble = True
+            preamble = []
+            linesep = False
+            while True:
+                line = self._input.readline()
+                if line is NeedMoreData:
+                    yield NeedMoreData
+                    continue
+                if line == '':
+                    break
+                mo = boundaryre.match(line)
+                if mo:
+                    # If we're looking at the end boundary, we're done with
+                    # this multipart.  If there was a newline at the end of
+                    # the closing boundary, then we need to initialize the
+                    # epilogue with the empty string (see below).
+                    if mo.group('end'):
+                        linesep = mo.group('linesep')
+                        break
+                    # We saw an inter-part boundary.  Were we in the preamble?
+                    if capturing_preamble:
+                        if preamble:
+                            # According to RFC 2046, the last newline belongs
+                            # to the boundary.
+                            lastline = preamble[-1]
+                            eolmo = NLCRE_eol.search(lastline)
+                            if eolmo:
+                                preamble[-1] = lastline[:-len(eolmo.group(0))]
+                            self._cur.preamble = EMPTYSTRING.join(preamble)
+                        capturing_preamble = False
+                        self._input.unreadline(line)
+                        continue
+                    # We saw a boundary separating two parts.  Consume any
+                    # multiple boundary lines that may be following.  Our
+                    # interpretation of RFC 2046 BNF grammar does not produce
+                    # body parts within such double boundaries.
+                    while True:
+                        line = self._input.readline()
+                        if line is NeedMoreData:
+                            yield NeedMoreData
+                            continue
+                        mo = boundaryre.match(line)
+                        if not mo:
+                            self._input.unreadline(line)
+                            break
+                    # Recurse to parse this subpart; the input stream points
+                    # at the subpart's first line.
+                    self._input.push_eof_matcher(boundaryre.match)
+                    for retval in self._parsegen():
+                        if retval is NeedMoreData:
+                            yield NeedMoreData
+                            continue
+                        break
+                    # Because of RFC 2046, the newline preceding the boundary
+                    # separator actually belongs to the boundary, not the
+                    # previous subpart's payload (or epilogue if the previous
+                    # part is a multipart).
+                    if self._last.get_content_maintype() == 'multipart':
+                        epilogue = self._last.epilogue
+                        if epilogue == '':
+                            self._last.epilogue = None
+                        elif epilogue is not None:
+                            mo = NLCRE_eol.search(epilogue)
+                            if mo:
+                                end = len(mo.group(0))
+                                self._last.epilogue = epilogue[:-end]
+                    else:
+                        payload = self._last.get_payload()
+                        if isinstance(payload, basestring):
+                            mo = NLCRE_eol.search(payload)
+                            if mo:
+                                payload = payload[:-len(mo.group(0))]
+                                self._last.set_payload(payload)
+                    self._input.pop_eof_matcher()
+                    self._pop_message()
+                    # Set the multipart up for newline cleansing, which will
+                    # happen if we're in a nested multipart.
+                    self._last = self._cur
+                else:
+                    # I think we must be in the preamble
+                    assert capturing_preamble
+                    preamble.append(line)
+            # We've seen either the EOF or the end boundary.  If we're still
+            # capturing the preamble, we never saw the start boundary.  Note
+            # that as a defect and store the captured text as the payload.
+            # Everything from here to the EOF is epilogue.
+            if capturing_preamble:
+                self._cur.defects.append(errors.StartBoundaryNotFoundDefect())
+                self._cur.set_payload(EMPTYSTRING.join(preamble))
+                epilogue = []
+                for line in self._input:
+                    if line is NeedMoreData:
+                        yield NeedMoreData
+                        continue
+                self._cur.epilogue = EMPTYSTRING.join(epilogue)
+                return
+            # If the end boundary ended in a newline, we'll need to make sure
+            # the epilogue isn't None
+            if linesep:
+                epilogue = ['']
+            else:
+                epilogue = []
+            for line in self._input:
+                if line is NeedMoreData:
+                    yield NeedMoreData
+                    continue
+                epilogue.append(line)
+            # Any CRLF at the front of the epilogue is not technically part of
+            # the epilogue.  Also, watch out for an empty string epilogue,
+            # which means a single newline.
+            if epilogue:
+                firstline = epilogue[0]
+                bolmo = NLCRE_bol.match(firstline)
+                if bolmo:
+                    epilogue[0] = firstline[len(bolmo.group(0)):]
+            self._cur.epilogue = EMPTYSTRING.join(epilogue)
+            return
+        # Otherwise, it's some non-multipart type, so the entire rest of the
+        # file contents becomes the payload.
+        lines = []
+        for line in self._input:
+            if line is NeedMoreData:
+                yield NeedMoreData
+                continue
+            lines.append(line)
+        self._cur.set_payload(EMPTYSTRING.join(lines))
+
+    def _parse_headers(self, lines):
+        # Passed a list of lines that make up the headers for the current msg
+        lastheader = ''
+        lastvalue = []
+        for lineno, line in enumerate(lines):
+            # Check for continuation
+            if line[0] in ' \t':
+                if not lastheader:
+                    # The first line of the headers was a continuation.  This
+                    # is illegal, so let's note the defect, store the illegal
+                    # line, and ignore it for purposes of headers.
+                    defect = errors.FirstHeaderLineIsContinuationDefect(line)
+                    self._cur.defects.append(defect)
+                    continue
+                lastvalue.append(line)
+                continue
+            if lastheader:
+                # XXX reconsider the joining of folded lines
+                lhdr = EMPTYSTRING.join(lastvalue)[:-1].rstrip('\r\n')
+                self._cur[lastheader] = lhdr
+                lastheader, lastvalue = '', []
+            # Check for envelope header, i.e. unix-from
+            if line.startswith('From '):
+                if lineno == 0:
+                    # Strip off the trailing newline
+                    mo = NLCRE_eol.search(line)
+                    if mo:
+                        line = line[:-len(mo.group(0))]
+                    self._cur.set_unixfrom(line)
+                    continue
+                elif lineno == len(lines) - 1:
+                    # Something looking like a unix-from at the end - it's
+                    # probably the first line of the body, so push back the
+                    # line and stop.
+                    self._input.unreadline(line)
+                    return
+                else:
+                    # Weirdly placed unix-from line.  Note this as a defect
+                    # and ignore it.
+                    defect = errors.MisplacedEnvelopeHeaderDefect(line)
+                    self._cur.defects.append(defect)
+                    continue
+            # Split the line on the colon separating field name from value.
+            i = line.find(':')
+            if i < 0:
+                defect = errors.MalformedHeaderDefect(line)
+                self._cur.defects.append(defect)
+                continue
+            lastheader = line[:i]
+            lastvalue = [line[i+1:].lstrip()]
+        # Done with all the lines, so handle the last header.
+        if lastheader:
+            # XXX reconsider the joining of folded lines
+            self._cur[lastheader] = EMPTYSTRING.join(lastvalue).rstrip('\r\n')
diff --git a/src/main/resources/PythonLibs/email/generator.py b/src/main/resources/PythonLibs/email/generator.py
new file mode 100644
index 0000000000000000000000000000000000000000..5626ab91eb57da6b0fbe54885dd71e6b17b12ec7
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/generator.py
@@ -0,0 +1,372 @@
+# Copyright (C) 2001-2010 Python Software Foundation
+# Contact: email-sig@python.org
+
+"""Classes to generate plain text from a message object tree."""
+
+__all__ = ['Generator', 'DecodedGenerator']
+
+import re
+import sys
+import time
+import random
+import warnings
+
+from cStringIO import StringIO
+from email.header import Header
+
+UNDERSCORE = '_'
+NL = '\n'
+
+fcre = re.compile(r'^From ', re.MULTILINE)
+
+def _is8bitstring(s):
+    if isinstance(s, str):
+        try:
+            unicode(s, 'us-ascii')
+        except UnicodeError:
+            return True
+    return False
+
+
+
+class Generator:
+    """Generates output from a Message object tree.
+
+    This basic generator writes the message to the given file object as plain
+    text.
+    """
+    #
+    # Public interface
+    #
+
+    def __init__(self, outfp, mangle_from_=True, maxheaderlen=78):
+        """Create the generator for message flattening.
+
+        outfp is the output file-like object for writing the message to.  It
+        must have a write() method.
+
+        Optional mangle_from_ is a flag that, when True (the default), escapes
+        From_ lines in the body of the message by putting a `>' in front of
+        them.
+
+        Optional maxheaderlen specifies the longest length for a non-continued
+        header.  When a header line is longer (in characters, with tabs
+        expanded to 8 spaces) than maxheaderlen, the header will split as
+        defined in the Header class.  Set maxheaderlen to zero to disable
+        header wrapping.  The default is 78, as recommended (but not required)
+        by RFC 2822.
+        """
+        self._fp = outfp
+        self._mangle_from_ = mangle_from_
+        self._maxheaderlen = maxheaderlen
+
+    def write(self, s):
+        # Just delegate to the file object
+        self._fp.write(s)
+
+    def flatten(self, msg, unixfrom=False):
+        """Print the message object tree rooted at msg to the output file
+        specified when the Generator instance was created.
+
+        unixfrom is a flag that forces the printing of a Unix From_ delimiter
+        before the first object in the message tree.  If the original message
+        has no From_ delimiter, a `standard' one is crafted.  By default, this
+        is False to inhibit the printing of any From_ delimiter.
+
+        Note that for subobjects, no From_ line is printed.
+        """
+        if unixfrom:
+            ufrom = msg.get_unixfrom()
+            if not ufrom:
+                ufrom = 'From nobody ' + time.ctime(time.time())
+            print >> self._fp, ufrom
+        self._write(msg)
+
+    def clone(self, fp):
+        """Clone this generator with the exact same options."""
+        return self.__class__(fp, self._mangle_from_, self._maxheaderlen)
+
+    #
+    # Protected interface - undocumented ;/
+    #
+
+    def _write(self, msg):
+        # We can't write the headers yet because of the following scenario:
+        # say a multipart message includes the boundary string somewhere in
+        # its body.  We'd have to calculate the new boundary /before/ we write
+        # the headers so that we can write the correct Content-Type:
+        # parameter.
+        #
+        # The way we do this, so as to make the _handle_*() methods simpler,
+        # is to cache any subpart writes into a StringIO.  The we write the
+        # headers and the StringIO contents.  That way, subpart handlers can
+        # Do The Right Thing, and can still modify the Content-Type: header if
+        # necessary.
+        oldfp = self._fp
+        try:
+            self._fp = sfp = StringIO()
+            self._dispatch(msg)
+        finally:
+            self._fp = oldfp
+        # Write the headers.  First we see if the message object wants to
+        # handle that itself.  If not, we'll do it generically.
+        meth = getattr(msg, '_write_headers', None)
+        if meth is None:
+            self._write_headers(msg)
+        else:
+            meth(self)
+        self._fp.write(sfp.getvalue())
+
+    def _dispatch(self, msg):
+        # Get the Content-Type: for the message, then try to dispatch to
+        # self._handle_<maintype>_<subtype>().  If there's no handler for the
+        # full MIME type, then dispatch to self._handle_<maintype>().  If
+        # that's missing too, then dispatch to self._writeBody().
+        main = msg.get_content_maintype()
+        sub = msg.get_content_subtype()
+        specific = UNDERSCORE.join((main, sub)).replace('-', '_')
+        meth = getattr(self, '_handle_' + specific, None)
+        if meth is None:
+            generic = main.replace('-', '_')
+            meth = getattr(self, '_handle_' + generic, None)
+            if meth is None:
+                meth = self._writeBody
+        meth(msg)
+
+    #
+    # Default handlers
+    #
+
+    def _write_headers(self, msg):
+        for h, v in msg.items():
+            print >> self._fp, '%s:' % h,
+            if self._maxheaderlen == 0:
+                # Explicit no-wrapping
+                print >> self._fp, v
+            elif isinstance(v, Header):
+                # Header instances know what to do
+                print >> self._fp, v.encode()
+            elif _is8bitstring(v):
+                # If we have raw 8bit data in a byte string, we have no idea
+                # what the encoding is.  There is no safe way to split this
+                # string.  If it's ascii-subset, then we could do a normal
+                # ascii split, but if it's multibyte then we could break the
+                # string.  There's no way to know so the least harm seems to
+                # be to not split the string and risk it being too long.
+                print >> self._fp, v
+            else:
+                # Header's got lots of smarts, so use it.  Note that this is
+                # fundamentally broken though because we lose idempotency when
+                # the header string is continued with tabs.  It will now be
+                # continued with spaces.  This was reversedly broken before we
+                # fixed bug 1974.  Either way, we lose.
+                print >> self._fp, Header(
+                    v, maxlinelen=self._maxheaderlen, header_name=h).encode()
+        # A blank line always separates headers from body
+        print >> self._fp
+
+    #
+    # Handlers for writing types and subtypes
+    #
+
+    def _handle_text(self, msg):
+        payload = msg.get_payload()
+        if payload is None:
+            return
+        if not isinstance(payload, basestring):
+            raise TypeError('string payload expected: %s' % type(payload))
+        if self._mangle_from_:
+            payload = fcre.sub('>From ', payload)
+        self._fp.write(payload)
+
+    # Default body handler
+    _writeBody = _handle_text
+
+    def _handle_multipart(self, msg):
+        # The trick here is to write out each part separately, merge them all
+        # together, and then make sure that the boundary we've chosen isn't
+        # present in the payload.
+        msgtexts = []
+        subparts = msg.get_payload()
+        if subparts is None:
+            subparts = []
+        elif isinstance(subparts, basestring):
+            # e.g. a non-strict parse of a message with no starting boundary.
+            self._fp.write(subparts)
+            return
+        elif not isinstance(subparts, list):
+            # Scalar payload
+            subparts = [subparts]
+        for part in subparts:
+            s = StringIO()
+            g = self.clone(s)
+            g.flatten(part, unixfrom=False)
+            msgtexts.append(s.getvalue())
+        # BAW: What about boundaries that are wrapped in double-quotes?
+        boundary = msg.get_boundary()
+        if not boundary:
+            # Create a boundary that doesn't appear in any of the
+            # message texts.
+            alltext = NL.join(msgtexts)
+            boundary = _make_boundary(alltext)
+            msg.set_boundary(boundary)
+        # If there's a preamble, write it out, with a trailing CRLF
+        if msg.preamble is not None:
+            if self._mangle_from_:
+                preamble = fcre.sub('>From ', msg.preamble)
+            else:
+                preamble = msg.preamble
+            print >> self._fp, preamble
+        # dash-boundary transport-padding CRLF
+        print >> self._fp, '--' + boundary
+        # body-part
+        if msgtexts:
+            self._fp.write(msgtexts.pop(0))
+        # *encapsulation
+        # --> delimiter transport-padding
+        # --> CRLF body-part
+        for body_part in msgtexts:
+            # delimiter transport-padding CRLF
+            print >> self._fp, '\n--' + boundary
+            # body-part
+            self._fp.write(body_part)
+        # close-delimiter transport-padding
+        self._fp.write('\n--' + boundary + '--')
+        if msg.epilogue is not None:
+            print >> self._fp
+            if self._mangle_from_:
+                epilogue = fcre.sub('>From ', msg.epilogue)
+            else:
+                epilogue = msg.epilogue
+            self._fp.write(epilogue)
+
+    def _handle_multipart_signed(self, msg):
+        # The contents of signed parts has to stay unmodified in order to keep
+        # the signature intact per RFC1847 2.1, so we disable header wrapping.
+        # RDM: This isn't enough to completely preserve the part, but it helps.
+        old_maxheaderlen = self._maxheaderlen
+        try:
+            self._maxheaderlen = 0
+            self._handle_multipart(msg)
+        finally:
+            self._maxheaderlen = old_maxheaderlen
+
+    def _handle_message_delivery_status(self, msg):
+        # We can't just write the headers directly to self's file object
+        # because this will leave an extra newline between the last header
+        # block and the boundary.  Sigh.
+        blocks = []
+        for part in msg.get_payload():
+            s = StringIO()
+            g = self.clone(s)
+            g.flatten(part, unixfrom=False)
+            text = s.getvalue()
+            lines = text.split('\n')
+            # Strip off the unnecessary trailing empty line
+            if lines and lines[-1] == '':
+                blocks.append(NL.join(lines[:-1]))
+            else:
+                blocks.append(text)
+        # Now join all the blocks with an empty line.  This has the lovely
+        # effect of separating each block with an empty line, but not adding
+        # an extra one after the last one.
+        self._fp.write(NL.join(blocks))
+
+    def _handle_message(self, msg):
+        s = StringIO()
+        g = self.clone(s)
+        # The payload of a message/rfc822 part should be a multipart sequence
+        # of length 1.  The zeroth element of the list should be the Message
+        # object for the subpart.  Extract that object, stringify it, and
+        # write it out.
+        # Except, it turns out, when it's a string instead, which happens when
+        # and only when HeaderParser is used on a message of mime type
+        # message/rfc822.  Such messages are generated by, for example,
+        # Groupwise when forwarding unadorned messages.  (Issue 7970.)  So
+        # in that case we just emit the string body.
+        payload = msg.get_payload()
+        if isinstance(payload, list):
+            g.flatten(msg.get_payload(0), unixfrom=False)
+            payload = s.getvalue()
+        self._fp.write(payload)
+
+
+
+_FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]'
+
+class DecodedGenerator(Generator):
+    """Generates a text representation of a message.
+
+    Like the Generator base class, except that non-text parts are substituted
+    with a format string representing the part.
+    """
+    def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, fmt=None):
+        """Like Generator.__init__() except that an additional optional
+        argument is allowed.
+
+        Walks through all subparts of a message.  If the subpart is of main
+        type `text', then it prints the decoded payload of the subpart.
+
+        Otherwise, fmt is a format string that is used instead of the message
+        payload.  fmt is expanded with the following keywords (in
+        %(keyword)s format):
+
+        type       : Full MIME type of the non-text part
+        maintype   : Main MIME type of the non-text part
+        subtype    : Sub-MIME type of the non-text part
+        filename   : Filename of the non-text part
+        description: Description associated with the non-text part
+        encoding   : Content transfer encoding of the non-text part
+
+        The default value for fmt is None, meaning
+
+        [Non-text (%(type)s) part of message omitted, filename %(filename)s]
+        """
+        Generator.__init__(self, outfp, mangle_from_, maxheaderlen)
+        if fmt is None:
+            self._fmt = _FMT
+        else:
+            self._fmt = fmt
+
+    def _dispatch(self, msg):
+        for part in msg.walk():
+            maintype = part.get_content_maintype()
+            if maintype == 'text':
+                print >> self, part.get_payload(decode=True)
+            elif maintype == 'multipart':
+                # Just skip this
+                pass
+            else:
+                print >> self, self._fmt % {
+                    'type'       : part.get_content_type(),
+                    'maintype'   : part.get_content_maintype(),
+                    'subtype'    : part.get_content_subtype(),
+                    'filename'   : part.get_filename('[no filename]'),
+                    'description': part.get('Content-Description',
+                                            '[no description]'),
+                    'encoding'   : part.get('Content-Transfer-Encoding',
+                                            '[no encoding]'),
+                    }
+
+
+
+# Helper
+_width = len(repr(sys.maxint-1))
+_fmt = '%%0%dd' % _width
+
+def _make_boundary(text=None):
+    # Craft a random boundary.  If text is given, ensure that the chosen
+    # boundary doesn't appear in the text.
+    token = random.randrange(sys.maxint)
+    boundary = ('=' * 15) + (_fmt % token) + '=='
+    if text is None:
+        return boundary
+    b = boundary
+    counter = 0
+    while True:
+        cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
+        if not cre.search(text):
+            break
+        b = boundary + '.' + str(counter)
+        counter += 1
+    return b
diff --git a/src/main/resources/PythonLibs/email/header.py b/src/main/resources/PythonLibs/email/header.py
new file mode 100644
index 0000000000000000000000000000000000000000..2cf870fd575f9a3d8109d17ac3c30989f2b414db
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/header.py
@@ -0,0 +1,514 @@
+# Copyright (C) 2002-2006 Python Software Foundation
+# Author: Ben Gertzfield, Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Header encoding and decoding functionality."""
+
+__all__ = [
+    'Header',
+    'decode_header',
+    'make_header',
+    ]
+
+import re
+import binascii
+
+import email.quoprimime
+import email.base64mime
+
+from email.errors import HeaderParseError
+from email.charset import Charset
+
+NL = '\n'
+SPACE = ' '
+USPACE = u' '
+SPACE8 = ' ' * 8
+UEMPTYSTRING = u''
+
+MAXLINELEN = 76
+
+USASCII = Charset('us-ascii')
+UTF8 = Charset('utf-8')
+
+# Match encoded-word strings in the form =?charset?q?Hello_World?=
+ecre = re.compile(r'''
+  =\?                   # literal =?
+  (?P<charset>[^?]*?)   # non-greedy up to the next ? is the charset
+  \?                    # literal ?
+  (?P<encoding>[qb])    # either a "q" or a "b", case insensitive
+  \?                    # literal ?
+  (?P<encoded>.*?)      # non-greedy up to the next ?= is the encoded string
+  \?=                   # literal ?=
+  (?=[ \t]|$)           # whitespace or the end of the string
+  ''', re.VERBOSE | re.IGNORECASE | re.MULTILINE)
+
+# Field name regexp, including trailing colon, but not separating whitespace,
+# according to RFC 2822.  Character range is from tilde to exclamation mark.
+# For use with .match()
+fcre = re.compile(r'[\041-\176]+:$')
+
+# Find a header embedded in a putative header value.  Used to check for
+# header injection attack.
+_embeded_header = re.compile(r'\n[^ \t]+:')
+
+
+
+# Helpers
+_max_append = email.quoprimime._max_append
+
+
+
+def decode_header(header):
+    """Decode a message header value without converting charset.
+
+    Returns a list of (decoded_string, charset) pairs containing each of the
+    decoded parts of the header.  Charset is None for non-encoded parts of the
+    header, otherwise a lower-case string containing the name of the character
+    set specified in the encoded string.
+
+    An email.errors.HeaderParseError may be raised when certain decoding error
+    occurs (e.g. a base64 decoding exception).
+    """
+    # If no encoding, just return the header
+    header = str(header)
+    if not ecre.search(header):
+        return [(header, None)]
+    decoded = []
+    dec = ''
+    for line in header.splitlines():
+        # This line might not have an encoding in it
+        if not ecre.search(line):
+            decoded.append((line, None))
+            continue
+        parts = ecre.split(line)
+        while parts:
+            unenc = parts.pop(0).strip()
+            if unenc:
+                # Should we continue a long line?
+                if decoded and decoded[-1][1] is None:
+                    decoded[-1] = (decoded[-1][0] + SPACE + unenc, None)
+                else:
+                    decoded.append((unenc, None))
+            if parts:
+                charset, encoding = [s.lower() for s in parts[0:2]]
+                encoded = parts[2]
+                dec = None
+                if encoding == 'q':
+                    dec = email.quoprimime.header_decode(encoded)
+                elif encoding == 'b':
+                    paderr = len(encoded) % 4   # Postel's law: add missing padding
+                    if paderr:
+                        encoded += '==='[:4 - paderr]
+                    try:
+                        dec = email.base64mime.decode(encoded)
+                    except binascii.Error:
+                        # Turn this into a higher level exception.  BAW: Right
+                        # now we throw the lower level exception away but
+                        # when/if we get exception chaining, we'll preserve it.
+                        raise HeaderParseError
+                if dec is None:
+                    dec = encoded
+
+                if decoded and decoded[-1][1] == charset:
+                    decoded[-1] = (decoded[-1][0] + dec, decoded[-1][1])
+                else:
+                    decoded.append((dec, charset))
+            del parts[0:3]
+    return decoded
+
+
+
+def make_header(decoded_seq, maxlinelen=None, header_name=None,
+                continuation_ws=' '):
+    """Create a Header from a sequence of pairs as returned by decode_header()
+
+    decode_header() takes a header value string and returns a sequence of
+    pairs of the format (decoded_string, charset) where charset is the string
+    name of the character set.
+
+    This function takes one of those sequence of pairs and returns a Header
+    instance.  Optional maxlinelen, header_name, and continuation_ws are as in
+    the Header constructor.
+    """
+    h = Header(maxlinelen=maxlinelen, header_name=header_name,
+               continuation_ws=continuation_ws)
+    for s, charset in decoded_seq:
+        # None means us-ascii but we can simply pass it on to h.append()
+        if charset is not None and not isinstance(charset, Charset):
+            charset = Charset(charset)
+        h.append(s, charset)
+    return h
+
+
+
+class Header:
+    def __init__(self, s=None, charset=None,
+                 maxlinelen=None, header_name=None,
+                 continuation_ws=' ', errors='strict'):
+        """Create a MIME-compliant header that can contain many character sets.
+
+        Optional s is the initial header value.  If None, the initial header
+        value is not set.  You can later append to the header with .append()
+        method calls.  s may be a byte string or a Unicode string, but see the
+        .append() documentation for semantics.
+
+        Optional charset serves two purposes: it has the same meaning as the
+        charset argument to the .append() method.  It also sets the default
+        character set for all subsequent .append() calls that omit the charset
+        argument.  If charset is not provided in the constructor, the us-ascii
+        charset is used both as s's initial charset and as the default for
+        subsequent .append() calls.
+
+        The maximum line length can be specified explicit via maxlinelen.  For
+        splitting the first line to a shorter value (to account for the field
+        header which isn't included in s, e.g. `Subject') pass in the name of
+        the field in header_name.  The default maxlinelen is 76.
+
+        continuation_ws must be RFC 2822 compliant folding whitespace (usually
+        either a space or a hard tab) which will be prepended to continuation
+        lines.
+
+        errors is passed through to the .append() call.
+        """
+        if charset is None:
+            charset = USASCII
+        if not isinstance(charset, Charset):
+            charset = Charset(charset)
+        self._charset = charset
+        self._continuation_ws = continuation_ws
+        cws_expanded_len = len(continuation_ws.replace('\t', SPACE8))
+        # BAW: I believe `chunks' and `maxlinelen' should be non-public.
+        self._chunks = []
+        if s is not None:
+            self.append(s, charset, errors)
+        if maxlinelen is None:
+            maxlinelen = MAXLINELEN
+        if header_name is None:
+            # We don't know anything about the field header so the first line
+            # is the same length as subsequent lines.
+            self._firstlinelen = maxlinelen
+        else:
+            # The first line should be shorter to take into account the field
+            # header.  Also subtract off 2 extra for the colon and space.
+            self._firstlinelen = maxlinelen - len(header_name) - 2
+        # Second and subsequent lines should subtract off the length in
+        # columns of the continuation whitespace prefix.
+        self._maxlinelen = maxlinelen - cws_expanded_len
+
+    def __str__(self):
+        """A synonym for self.encode()."""
+        return self.encode()
+
+    def __unicode__(self):
+        """Helper for the built-in unicode function."""
+        uchunks = []
+        lastcs = None
+        for s, charset in self._chunks:
+            # We must preserve spaces between encoded and non-encoded word
+            # boundaries, which means for us we need to add a space when we go
+            # from a charset to None/us-ascii, or from None/us-ascii to a
+            # charset.  Only do this for the second and subsequent chunks.
+            nextcs = charset
+            if uchunks:
+                if lastcs not in (None, 'us-ascii'):
+                    if nextcs in (None, 'us-ascii'):
+                        uchunks.append(USPACE)
+                        nextcs = None
+                elif nextcs not in (None, 'us-ascii'):
+                    uchunks.append(USPACE)
+            lastcs = nextcs
+            uchunks.append(unicode(s, str(charset)))
+        return UEMPTYSTRING.join(uchunks)
+
+    # Rich comparison operators for equality only.  BAW: does it make sense to
+    # have or explicitly disable <, <=, >, >= operators?
+    def __eq__(self, other):
+        # other may be a Header or a string.  Both are fine so coerce
+        # ourselves to a string, swap the args and do another comparison.
+        return other == self.encode()
+
+    def __ne__(self, other):
+        return not self == other
+
+    def append(self, s, charset=None, errors='strict'):
+        """Append a string to the MIME header.
+
+        Optional charset, if given, should be a Charset instance or the name
+        of a character set (which will be converted to a Charset instance).  A
+        value of None (the default) means that the charset given in the
+        constructor is used.
+
+        s may be a byte string or a Unicode string.  If it is a byte string
+        (i.e. isinstance(s, str) is true), then charset is the encoding of
+        that byte string, and a UnicodeError will be raised if the string
+        cannot be decoded with that charset.  If s is a Unicode string, then
+        charset is a hint specifying the character set of the characters in
+        the string.  In this case, when producing an RFC 2822 compliant header
+        using RFC 2047 rules, the Unicode string will be encoded using the
+        following charsets in order: us-ascii, the charset hint, utf-8.  The
+        first character set not to provoke a UnicodeError is used.
+
+        Optional `errors' is passed as the third argument to any unicode() or
+        ustr.encode() call.
+        """
+        if charset is None:
+            charset = self._charset
+        elif not isinstance(charset, Charset):
+            charset = Charset(charset)
+        # If the charset is our faux 8bit charset, leave the string unchanged
+        if charset != '8bit':
+            # We need to test that the string can be converted to unicode and
+            # back to a byte string, given the input and output codecs of the
+            # charset.
+            if isinstance(s, str):
+                # Possibly raise UnicodeError if the byte string can't be
+                # converted to a unicode with the input codec of the charset.
+                incodec = charset.input_codec or 'us-ascii'
+                ustr = unicode(s, incodec, errors)
+                # Now make sure that the unicode could be converted back to a
+                # byte string with the output codec, which may be different
+                # than the iput coded.  Still, use the original byte string.
+                outcodec = charset.output_codec or 'us-ascii'
+                ustr.encode(outcodec, errors)
+            elif isinstance(s, unicode):
+                # Now we have to be sure the unicode string can be converted
+                # to a byte string with a reasonable output codec.  We want to
+                # use the byte string in the chunk.
+                for charset in USASCII, charset, UTF8:
+                    try:
+                        outcodec = charset.output_codec or 'us-ascii'
+                        s = s.encode(outcodec, errors)
+                        break
+                    except UnicodeError:
+                        pass
+                else:
+                    assert False, 'utf-8 conversion failed'
+        self._chunks.append((s, charset))
+
+    def _split(self, s, charset, maxlinelen, splitchars):
+        # Split up a header safely for use with encode_chunks.
+        splittable = charset.to_splittable(s)
+        encoded = charset.from_splittable(splittable, True)
+        elen = charset.encoded_header_len(encoded)
+        # If the line's encoded length first, just return it
+        if elen <= maxlinelen:
+            return [(encoded, charset)]
+        # If we have undetermined raw 8bit characters sitting in a byte
+        # string, we really don't know what the right thing to do is.  We
+        # can't really split it because it might be multibyte data which we
+        # could break if we split it between pairs.  The least harm seems to
+        # be to not split the header at all, but that means they could go out
+        # longer than maxlinelen.
+        if charset == '8bit':
+            return [(s, charset)]
+        # BAW: I'm not sure what the right test here is.  What we're trying to
+        # do is be faithful to RFC 2822's recommendation that ($2.2.3):
+        #
+        # "Note: Though structured field bodies are defined in such a way that
+        #  folding can take place between many of the lexical tokens (and even
+        #  within some of the lexical tokens), folding SHOULD be limited to
+        #  placing the CRLF at higher-level syntactic breaks."
+        #
+        # For now, I can only imagine doing this when the charset is us-ascii,
+        # although it's possible that other charsets may also benefit from the
+        # higher-level syntactic breaks.
+        elif charset == 'us-ascii':
+            return self._split_ascii(s, charset, maxlinelen, splitchars)
+        # BAW: should we use encoded?
+        elif elen == len(s):
+            # We can split on _maxlinelen boundaries because we know that the
+            # encoding won't change the size of the string
+            splitpnt = maxlinelen
+            first = charset.from_splittable(splittable[:splitpnt], False)
+            last = charset.from_splittable(splittable[splitpnt:], False)
+        else:
+            # Binary search for split point
+            first, last = _binsplit(splittable, charset, maxlinelen)
+        # first is of the proper length so just wrap it in the appropriate
+        # chrome.  last must be recursively split.
+        fsplittable = charset.to_splittable(first)
+        fencoded = charset.from_splittable(fsplittable, True)
+        chunk = [(fencoded, charset)]
+        return chunk + self._split(last, charset, self._maxlinelen, splitchars)
+
+    def _split_ascii(self, s, charset, firstlen, splitchars):
+        chunks = _split_ascii(s, firstlen, self._maxlinelen,
+                              self._continuation_ws, splitchars)
+        return zip(chunks, [charset]*len(chunks))
+
+    def _encode_chunks(self, newchunks, maxlinelen):
+        # MIME-encode a header with many different charsets and/or encodings.
+        #
+        # Given a list of pairs (string, charset), return a MIME-encoded
+        # string suitable for use in a header field.  Each pair may have
+        # different charsets and/or encodings, and the resulting header will
+        # accurately reflect each setting.
+        #
+        # Each encoding can be email.utils.QP (quoted-printable, for
+        # ASCII-like character sets like iso-8859-1), email.utils.BASE64
+        # (Base64, for non-ASCII like character sets like KOI8-R and
+        # iso-2022-jp), or None (no encoding).
+        #
+        # Each pair will be represented on a separate line; the resulting
+        # string will be in the format:
+        #
+        # =?charset1?q?Mar=EDa_Gonz=E1lez_Alonso?=\n
+        #  =?charset2?b?SvxyZ2VuIEL2aW5n?="
+        chunks = []
+        for header, charset in newchunks:
+            if not header:
+                continue
+            if charset is None or charset.header_encoding is None:
+                s = header
+            else:
+                s = charset.header_encode(header)
+            # Don't add more folding whitespace than necessary
+            if chunks and chunks[-1].endswith(' '):
+                extra = ''
+            else:
+                extra = ' '
+            _max_append(chunks, s, maxlinelen, extra)
+        joiner = NL + self._continuation_ws
+        return joiner.join(chunks)
+
+    def encode(self, splitchars=';, '):
+        """Encode a message header into an RFC-compliant format.
+
+        There are many issues involved in converting a given string for use in
+        an email header.  Only certain character sets are readable in most
+        email clients, and as header strings can only contain a subset of
+        7-bit ASCII, care must be taken to properly convert and encode (with
+        Base64 or quoted-printable) header strings.  In addition, there is a
+        75-character length limit on any given encoded header field, so
+        line-wrapping must be performed, even with double-byte character sets.
+
+        This method will do its best to convert the string to the correct
+        character set used in email, and encode and line wrap it safely with
+        the appropriate scheme for that character set.
+
+        If the given charset is not known or an error occurs during
+        conversion, this function will return the header untouched.
+
+        Optional splitchars is a string containing characters to split long
+        ASCII lines on, in rough support of RFC 2822's `highest level
+        syntactic breaks'.  This doesn't affect RFC 2047 encoded lines.
+        """
+        newchunks = []
+        maxlinelen = self._firstlinelen
+        lastlen = 0
+        for s, charset in self._chunks:
+            # The first bit of the next chunk should be just long enough to
+            # fill the next line.  Don't forget the space separating the
+            # encoded words.
+            targetlen = maxlinelen - lastlen - 1
+            if targetlen < charset.encoded_header_len(''):
+                # Stick it on the next line
+                targetlen = maxlinelen
+            newchunks += self._split(s, charset, targetlen, splitchars)
+            lastchunk, lastcharset = newchunks[-1]
+            lastlen = lastcharset.encoded_header_len(lastchunk)
+        value = self._encode_chunks(newchunks, maxlinelen)
+        if _embeded_header.search(value):
+            raise HeaderParseError("header value appears to contain "
+                "an embedded header: {!r}".format(value))
+        return value
+
+
+
+def _split_ascii(s, firstlen, restlen, continuation_ws, splitchars):
+    lines = []
+    maxlen = firstlen
+    for line in s.splitlines():
+        # Ignore any leading whitespace (i.e. continuation whitespace) already
+        # on the line, since we'll be adding our own.
+        line = line.lstrip()
+        if len(line) < maxlen:
+            lines.append(line)
+            maxlen = restlen
+            continue
+        # Attempt to split the line at the highest-level syntactic break
+        # possible.  Note that we don't have a lot of smarts about field
+        # syntax; we just try to break on semi-colons, then commas, then
+        # whitespace.
+        for ch in splitchars:
+            if ch in line:
+                break
+        else:
+            # There's nothing useful to split the line on, not even spaces, so
+            # just append this line unchanged
+            lines.append(line)
+            maxlen = restlen
+            continue
+        # Now split the line on the character plus trailing whitespace
+        cre = re.compile(r'%s\s*' % ch)
+        if ch in ';,':
+            eol = ch
+        else:
+            eol = ''
+        joiner = eol + ' '
+        joinlen = len(joiner)
+        wslen = len(continuation_ws.replace('\t', SPACE8))
+        this = []
+        linelen = 0
+        for part in cre.split(line):
+            curlen = linelen + max(0, len(this)-1) * joinlen
+            partlen = len(part)
+            onfirstline = not lines
+            # We don't want to split after the field name, if we're on the
+            # first line and the field name is present in the header string.
+            if ch == ' ' and onfirstline and \
+                   len(this) == 1 and fcre.match(this[0]):
+                this.append(part)
+                linelen += partlen
+            elif curlen + partlen > maxlen:
+                if this:
+                    lines.append(joiner.join(this) + eol)
+                # If this part is longer than maxlen and we aren't already
+                # splitting on whitespace, try to recursively split this line
+                # on whitespace.
+                if partlen > maxlen and ch != ' ':
+                    subl = _split_ascii(part, maxlen, restlen,
+                                        continuation_ws, ' ')
+                    lines.extend(subl[:-1])
+                    this = [subl[-1]]
+                else:
+                    this = [part]
+                linelen = wslen + len(this[-1])
+                maxlen = restlen
+            else:
+                this.append(part)
+                linelen += partlen
+        # Put any left over parts on a line by themselves
+        if this:
+            lines.append(joiner.join(this))
+    return lines
+
+
+
+def _binsplit(splittable, charset, maxlinelen):
+    i = 0
+    j = len(splittable)
+    while i < j:
+        # Invariants:
+        # 1. splittable[:k] fits for all k <= i (note that we *assume*,
+        #    at the start, that splittable[:0] fits).
+        # 2. splittable[:k] does not fit for any k > j (at the start,
+        #    this means we shouldn't look at any k > len(splittable)).
+        # 3. We don't know about splittable[:k] for k in i+1..j.
+        # 4. We want to set i to the largest k that fits, with i <= k <= j.
+        #
+        m = (i+j+1) >> 1  # ceiling((i+j)/2); i < m <= j
+        chunk = charset.from_splittable(splittable[:m], True)
+        chunklen = charset.encoded_header_len(chunk)
+        if chunklen <= maxlinelen:
+            # m is acceptable, so is a new lower bound.
+            i = m
+        else:
+            # m is not acceptable, so final i must be < m.
+            j = m - 1
+    # i == j.  Invariant #1 implies that splittable[:i] fits, and
+    # invariant #2 implies that splittable[:i+1] does not fit, so i
+    # is what we're looking for.
+    first = charset.from_splittable(splittable[:i], False)
+    last  = charset.from_splittable(splittable[i:], False)
+    return first, last
diff --git a/src/main/resources/PythonLibs/email/iterators.py b/src/main/resources/PythonLibs/email/iterators.py
new file mode 100644
index 0000000000000000000000000000000000000000..e99f2280da3814421db67c476902cbeab96280c7
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/iterators.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Various types of useful iterators and generators."""
+
+__all__ = [
+    'body_line_iterator',
+    'typed_subpart_iterator',
+    'walk',
+    # Do not include _structure() since it's part of the debugging API.
+    ]
+
+import sys
+from cStringIO import StringIO
+
+
+
+# This function will become a method of the Message class
+def walk(self):
+    """Walk over the message tree, yielding each subpart.
+
+    The walk is performed in depth-first order.  This method is a
+    generator.
+    """
+    yield self
+    if self.is_multipart():
+        for subpart in self.get_payload():
+            for subsubpart in subpart.walk():
+                yield subsubpart
+
+
+
+# These two functions are imported into the Iterators.py interface module.
+def body_line_iterator(msg, decode=False):
+    """Iterate over the parts, returning string payloads line-by-line.
+
+    Optional decode (default False) is passed through to .get_payload().
+    """
+    for subpart in msg.walk():
+        payload = subpart.get_payload(decode=decode)
+        if isinstance(payload, basestring):
+            for line in StringIO(payload):
+                yield line
+
+
+def typed_subpart_iterator(msg, maintype='text', subtype=None):
+    """Iterate over the subparts with a given MIME type.
+
+    Use `maintype' as the main MIME type to match against; this defaults to
+    "text".  Optional `subtype' is the MIME subtype to match against; if
+    omitted, only the main type is matched.
+    """
+    for subpart in msg.walk():
+        if subpart.get_content_maintype() == maintype:
+            if subtype is None or subpart.get_content_subtype() == subtype:
+                yield subpart
+
+
+
+def _structure(msg, fp=None, level=0, include_default=False):
+    """A handy debugging aid"""
+    if fp is None:
+        fp = sys.stdout
+    tab = ' ' * (level * 4)
+    print >> fp, tab + msg.get_content_type(),
+    if include_default:
+        print >> fp, '[%s]' % msg.get_default_type()
+    else:
+        print >> fp
+    if msg.is_multipart():
+        for subpart in msg.get_payload():
+            _structure(subpart, fp, level+1, include_default)
diff --git a/src/main/resources/PythonLibs/email/message.py b/src/main/resources/PythonLibs/email/message.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c93370984c0d040dde803bd88101c2bbde0d1ea
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/message.py
@@ -0,0 +1,797 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Basic message object for the email package object model."""
+
+__all__ = ['Message']
+
+import re
+import uu
+import binascii
+import warnings
+from cStringIO import StringIO
+
+# Intrapackage imports
+import email.charset
+from email import utils
+from email import errors
+
+SEMISPACE = '; '
+
+# Regular expression that matches `special' characters in parameters, the
+# existence of which force quoting of the parameter value.
+tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
+
+
+# Helper functions
+def _splitparam(param):
+    # Split header parameters.  BAW: this may be too simple.  It isn't
+    # strictly RFC 2045 (section 5.1) compliant, but it catches most headers
+    # found in the wild.  We may eventually need a full fledged parser
+    # eventually.
+    a, sep, b = param.partition(';')
+    if not sep:
+        return a.strip(), None
+    return a.strip(), b.strip()
+
+def _formatparam(param, value=None, quote=True):
+    """Convenience function to format and return a key=value pair.
+
+    This will quote the value if needed or if quote is true.  If value is a
+    three tuple (charset, language, value), it will be encoded according
+    to RFC2231 rules.
+    """
+    if value is not None and len(value) > 0:
+        # A tuple is used for RFC 2231 encoded parameter values where items
+        # are (charset, language, value).  charset is a string, not a Charset
+        # instance.
+        if isinstance(value, tuple):
+            # Encode as per RFC 2231
+            param += '*'
+            value = utils.encode_rfc2231(value[2], value[0], value[1])
+        # BAW: Please check this.  I think that if quote is set it should
+        # force quoting even if not necessary.
+        if quote or tspecials.search(value):
+            return '%s="%s"' % (param, utils.quote(value))
+        else:
+            return '%s=%s' % (param, value)
+    else:
+        return param
+
+def _parseparam(s):
+    plist = []
+    while s[:1] == ';':
+        s = s[1:]
+        end = s.find(';')
+        while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
+            end = s.find(';', end + 1)
+        if end < 0:
+            end = len(s)
+        f = s[:end]
+        if '=' in f:
+            i = f.index('=')
+            f = f[:i].strip().lower() + '=' + f[i+1:].strip()
+        plist.append(f.strip())
+        s = s[end:]
+    return plist
+
+
+def _unquotevalue(value):
+    # This is different than utils.collapse_rfc2231_value() because it doesn't
+    # try to convert the value to a unicode.  Message.get_param() and
+    # Message.get_params() are both currently defined to return the tuple in
+    # the face of RFC 2231 parameters.
+    if isinstance(value, tuple):
+        return value[0], value[1], utils.unquote(value[2])
+    else:
+        return utils.unquote(value)
+
+
+
+class Message:
+    """Basic message object.
+
+    A message object is defined as something that has a bunch of RFC 2822
+    headers and a payload.  It may optionally have an envelope header
+    (a.k.a. Unix-From or From_ header).  If the message is a container (i.e. a
+    multipart or a message/rfc822), then the payload is a list of Message
+    objects, otherwise it is a string.
+
+    Message objects implement part of the `mapping' interface, which assumes
+    there is exactly one occurrence of the header per message.  Some headers
+    do in fact appear multiple times (e.g. Received) and for those headers,
+    you must use the explicit API to set or get all the headers.  Not all of
+    the mapping methods are implemented.
+    """
+    def __init__(self):
+        self._headers = []
+        self._unixfrom = None
+        self._payload = None
+        self._charset = None
+        # Defaults for multipart messages
+        self.preamble = self.epilogue = None
+        self.defects = []
+        # Default content type
+        self._default_type = 'text/plain'
+
+    def __str__(self):
+        """Return the entire formatted message as a string.
+        This includes the headers, body, and envelope header.
+        """
+        return self.as_string(unixfrom=True)
+
+    def as_string(self, unixfrom=False):
+        """Return the entire formatted message as a string.
+        Optional `unixfrom' when True, means include the Unix From_ envelope
+        header.
+
+        This is a convenience method and may not generate the message exactly
+        as you intend because by default it mangles lines that begin with
+        "From ".  For more flexibility, use the flatten() method of a
+        Generator instance.
+        """
+        from email.generator import Generator
+        fp = StringIO()
+        g = Generator(fp)
+        g.flatten(self, unixfrom=unixfrom)
+        return fp.getvalue()
+
+    def is_multipart(self):
+        """Return True if the message consists of multiple parts."""
+        return isinstance(self._payload, list)
+
+    #
+    # Unix From_ line
+    #
+    def set_unixfrom(self, unixfrom):
+        self._unixfrom = unixfrom
+
+    def get_unixfrom(self):
+        return self._unixfrom
+
+    #
+    # Payload manipulation.
+    #
+    def attach(self, payload):
+        """Add the given payload to the current payload.
+
+        The current payload will always be a list of objects after this method
+        is called.  If you want to set the payload to a scalar object, use
+        set_payload() instead.
+        """
+        if self._payload is None:
+            self._payload = [payload]
+        else:
+            self._payload.append(payload)
+
+    def get_payload(self, i=None, decode=False):
+        """Return a reference to the payload.
+
+        The payload will either be a list object or a string.  If you mutate
+        the list object, you modify the message's payload in place.  Optional
+        i returns that index into the payload.
+
+        Optional decode is a flag indicating whether the payload should be
+        decoded or not, according to the Content-Transfer-Encoding header
+        (default is False).
+
+        When True and the message is not a multipart, the payload will be
+        decoded if this header's value is `quoted-printable' or `base64'.  If
+        some other encoding is used, or the header is missing, or if the
+        payload has bogus data (i.e. bogus base64 or uuencoded data), the
+        payload is returned as-is.
+
+        If the message is a multipart and the decode flag is True, then None
+        is returned.
+        """
+        if i is None:
+            payload = self._payload
+        elif not isinstance(self._payload, list):
+            raise TypeError('Expected list, got %s' % type(self._payload))
+        else:
+            payload = self._payload[i]
+        if decode:
+            if self.is_multipart():
+                return None
+            cte = self.get('content-transfer-encoding', '').lower()
+            if cte == 'quoted-printable':
+                return utils._qdecode(payload)
+            elif cte == 'base64':
+                try:
+                    return utils._bdecode(payload)
+                except binascii.Error:
+                    # Incorrect padding
+                    return payload
+            elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'):
+                sfp = StringIO()
+                try:
+                    uu.decode(StringIO(payload+'\n'), sfp, quiet=True)
+                    payload = sfp.getvalue()
+                except uu.Error:
+                    # Some decoding problem
+                    return payload
+        # Everything else, including encodings with 8bit or 7bit are returned
+        # unchanged.
+        return payload
+
+    def set_payload(self, payload, charset=None):
+        """Set the payload to the given value.
+
+        Optional charset sets the message's default character set.  See
+        set_charset() for details.
+        """
+        self._payload = payload
+        if charset is not None:
+            self.set_charset(charset)
+
+    def set_charset(self, charset):
+        """Set the charset of the payload to a given character set.
+
+        charset can be a Charset instance, a string naming a character set, or
+        None.  If it is a string it will be converted to a Charset instance.
+        If charset is None, the charset parameter will be removed from the
+        Content-Type field.  Anything else will generate a TypeError.
+
+        The message will be assumed to be of type text/* encoded with
+        charset.input_charset.  It will be converted to charset.output_charset
+        and encoded properly, if needed, when generating the plain text
+        representation of the message.  MIME headers (MIME-Version,
+        Content-Type, Content-Transfer-Encoding) will be added as needed.
+
+        """
+        if charset is None:
+            self.del_param('charset')
+            self._charset = None
+            return
+        if isinstance(charset, basestring):
+            charset = email.charset.Charset(charset)
+        if not isinstance(charset, email.charset.Charset):
+            raise TypeError(charset)
+        # BAW: should we accept strings that can serve as arguments to the
+        # Charset constructor?
+        self._charset = charset
+        if 'MIME-Version' not in self:
+            self.add_header('MIME-Version', '1.0')
+        if 'Content-Type' not in self:
+            self.add_header('Content-Type', 'text/plain',
+                            charset=charset.get_output_charset())
+        else:
+            self.set_param('charset', charset.get_output_charset())
+        if isinstance(self._payload, unicode):
+            self._payload = self._payload.encode(charset.output_charset)
+        if str(charset) != charset.get_output_charset():
+            self._payload = charset.body_encode(self._payload)
+        if 'Content-Transfer-Encoding' not in self:
+            cte = charset.get_body_encoding()
+            try:
+                cte(self)
+            except TypeError:
+                self._payload = charset.body_encode(self._payload)
+                self.add_header('Content-Transfer-Encoding', cte)
+
+    def get_charset(self):
+        """Return the Charset instance associated with the message's payload.
+        """
+        return self._charset
+
+    #
+    # MAPPING INTERFACE (partial)
+    #
+    def __len__(self):
+        """Return the total number of headers, including duplicates."""
+        return len(self._headers)
+
+    def __getitem__(self, name):
+        """Get a header value.
+
+        Return None if the header is missing instead of raising an exception.
+
+        Note that if the header appeared multiple times, exactly which
+        occurrence gets returned is undefined.  Use get_all() to get all
+        the values matching a header field name.
+        """
+        return self.get(name)
+
+    def __setitem__(self, name, val):
+        """Set the value of a header.
+
+        Note: this does not overwrite an existing header with the same field
+        name.  Use __delitem__() first to delete any existing headers.
+        """
+        self._headers.append((name, val))
+
+    def __delitem__(self, name):
+        """Delete all occurrences of a header, if present.
+
+        Does not raise an exception if the header is missing.
+        """
+        name = name.lower()
+        newheaders = []
+        for k, v in self._headers:
+            if k.lower() != name:
+                newheaders.append((k, v))
+        self._headers = newheaders
+
+    def __contains__(self, name):
+        return name.lower() in [k.lower() for k, v in self._headers]
+
+    def has_key(self, name):
+        """Return true if the message contains the header."""
+        missing = object()
+        return self.get(name, missing) is not missing
+
+    def keys(self):
+        """Return a list of all the message's header field names.
+
+        These will be sorted in the order they appeared in the original
+        message, or were added to the message, and may contain duplicates.
+        Any fields deleted and re-inserted are always appended to the header
+        list.
+        """
+        return [k for k, v in self._headers]
+
+    def values(self):
+        """Return a list of all the message's header values.
+
+        These will be sorted in the order they appeared in the original
+        message, or were added to the message, and may contain duplicates.
+        Any fields deleted and re-inserted are always appended to the header
+        list.
+        """
+        return [v for k, v in self._headers]
+
+    def items(self):
+        """Get all the message's header fields and values.
+
+        These will be sorted in the order they appeared in the original
+        message, or were added to the message, and may contain duplicates.
+        Any fields deleted and re-inserted are always appended to the header
+        list.
+        """
+        return self._headers[:]
+
+    def get(self, name, failobj=None):
+        """Get a header value.
+
+        Like __getitem__() but return failobj instead of None when the field
+        is missing.
+        """
+        name = name.lower()
+        for k, v in self._headers:
+            if k.lower() == name:
+                return v
+        return failobj
+
+    #
+    # Additional useful stuff
+    #
+
+    def get_all(self, name, failobj=None):
+        """Return a list of all the values for the named field.
+
+        These will be sorted in the order they appeared in the original
+        message, and may contain duplicates.  Any fields deleted and
+        re-inserted are always appended to the header list.
+
+        If no such fields exist, failobj is returned (defaults to None).
+        """
+        values = []
+        name = name.lower()
+        for k, v in self._headers:
+            if k.lower() == name:
+                values.append(v)
+        if not values:
+            return failobj
+        return values
+
+    def add_header(self, _name, _value, **_params):
+        """Extended header setting.
+
+        name is the header field to add.  keyword arguments can be used to set
+        additional parameters for the header field, with underscores converted
+        to dashes.  Normally the parameter will be added as key="value" unless
+        value is None, in which case only the key will be added.  If a
+        parameter value contains non-ASCII characters it must be specified as a
+        three-tuple of (charset, language, value), in which case it will be
+        encoded according to RFC2231 rules.
+
+        Example:
+
+        msg.add_header('content-disposition', 'attachment', filename='bud.gif')
+        """
+        parts = []
+        for k, v in _params.items():
+            if v is None:
+                parts.append(k.replace('_', '-'))
+            else:
+                parts.append(_formatparam(k.replace('_', '-'), v))
+        if _value is not None:
+            parts.insert(0, _value)
+        self._headers.append((_name, SEMISPACE.join(parts)))
+
+    def replace_header(self, _name, _value):
+        """Replace a header.
+
+        Replace the first matching header found in the message, retaining
+        header order and case.  If no matching header was found, a KeyError is
+        raised.
+        """
+        _name = _name.lower()
+        for i, (k, v) in zip(range(len(self._headers)), self._headers):
+            if k.lower() == _name:
+                self._headers[i] = (k, _value)
+                break
+        else:
+            raise KeyError(_name)
+
+    #
+    # Use these three methods instead of the three above.
+    #
+
+    def get_content_type(self):
+        """Return the message's content type.
+
+        The returned string is coerced to lower case of the form
+        `maintype/subtype'.  If there was no Content-Type header in the
+        message, the default type as given by get_default_type() will be
+        returned.  Since according to RFC 2045, messages always have a default
+        type this will always return a value.
+
+        RFC 2045 defines a message's default type to be text/plain unless it
+        appears inside a multipart/digest container, in which case it would be
+        message/rfc822.
+        """
+        missing = object()
+        value = self.get('content-type', missing)
+        if value is missing:
+            # This should have no parameters
+            return self.get_default_type()
+        ctype = _splitparam(value)[0].lower()
+        # RFC 2045, section 5.2 says if its invalid, use text/plain
+        if ctype.count('/') != 1:
+            return 'text/plain'
+        return ctype
+
+    def get_content_maintype(self):
+        """Return the message's main content type.
+
+        This is the `maintype' part of the string returned by
+        get_content_type().
+        """
+        ctype = self.get_content_type()
+        return ctype.split('/')[0]
+
+    def get_content_subtype(self):
+        """Returns the message's sub-content type.
+
+        This is the `subtype' part of the string returned by
+        get_content_type().
+        """
+        ctype = self.get_content_type()
+        return ctype.split('/')[1]
+
+    def get_default_type(self):
+        """Return the `default' content type.
+
+        Most messages have a default content type of text/plain, except for
+        messages that are subparts of multipart/digest containers.  Such
+        subparts have a default content type of message/rfc822.
+        """
+        return self._default_type
+
+    def set_default_type(self, ctype):
+        """Set the `default' content type.
+
+        ctype should be either "text/plain" or "message/rfc822", although this
+        is not enforced.  The default content type is not stored in the
+        Content-Type header.
+        """
+        self._default_type = ctype
+
+    def _get_params_preserve(self, failobj, header):
+        # Like get_params() but preserves the quoting of values.  BAW:
+        # should this be part of the public interface?
+        missing = object()
+        value = self.get(header, missing)
+        if value is missing:
+            return failobj
+        params = []
+        for p in _parseparam(';' + value):
+            try:
+                name, val = p.split('=', 1)
+                name = name.strip()
+                val = val.strip()
+            except ValueError:
+                # Must have been a bare attribute
+                name = p.strip()
+                val = ''
+            params.append((name, val))
+        params = utils.decode_params(params)
+        return params
+
+    def get_params(self, failobj=None, header='content-type', unquote=True):
+        """Return the message's Content-Type parameters, as a list.
+
+        The elements of the returned list are 2-tuples of key/value pairs, as
+        split on the `=' sign.  The left hand side of the `=' is the key,
+        while the right hand side is the value.  If there is no `=' sign in
+        the parameter the value is the empty string.  The value is as
+        described in the get_param() method.
+
+        Optional failobj is the object to return if there is no Content-Type
+        header.  Optional header is the header to search instead of
+        Content-Type.  If unquote is True, the value is unquoted.
+        """
+        missing = object()
+        params = self._get_params_preserve(missing, header)
+        if params is missing:
+            return failobj
+        if unquote:
+            return [(k, _unquotevalue(v)) for k, v in params]
+        else:
+            return params
+
+    def get_param(self, param, failobj=None, header='content-type',
+                  unquote=True):
+        """Return the parameter value if found in the Content-Type header.
+
+        Optional failobj is the object to return if there is no Content-Type
+        header, or the Content-Type header has no such parameter.  Optional
+        header is the header to search instead of Content-Type.
+
+        Parameter keys are always compared case insensitively.  The return
+        value can either be a string, or a 3-tuple if the parameter was RFC
+        2231 encoded.  When it's a 3-tuple, the elements of the value are of
+        the form (CHARSET, LANGUAGE, VALUE).  Note that both CHARSET and
+        LANGUAGE can be None, in which case you should consider VALUE to be
+        encoded in the us-ascii charset.  You can usually ignore LANGUAGE.
+
+        Your application should be prepared to deal with 3-tuple return
+        values, and can convert the parameter to a Unicode string like so:
+
+            param = msg.get_param('foo')
+            if isinstance(param, tuple):
+                param = unicode(param[2], param[0] or 'us-ascii')
+
+        In any case, the parameter value (either the returned string, or the
+        VALUE item in the 3-tuple) is always unquoted, unless unquote is set
+        to False.
+        """
+        if header not in self:
+            return failobj
+        for k, v in self._get_params_preserve(failobj, header):
+            if k.lower() == param.lower():
+                if unquote:
+                    return _unquotevalue(v)
+                else:
+                    return v
+        return failobj
+
+    def set_param(self, param, value, header='Content-Type', requote=True,
+                  charset=None, language=''):
+        """Set a parameter in the Content-Type header.
+
+        If the parameter already exists in the header, its value will be
+        replaced with the new value.
+
+        If header is Content-Type and has not yet been defined for this
+        message, it will be set to "text/plain" and the new parameter and
+        value will be appended as per RFC 2045.
+
+        An alternate header can specified in the header argument, and all
+        parameters will be quoted as necessary unless requote is False.
+
+        If charset is specified, the parameter will be encoded according to RFC
+        2231.  Optional language specifies the RFC 2231 language, defaulting
+        to the empty string.  Both charset and language should be strings.
+        """
+        if not isinstance(value, tuple) and charset:
+            value = (charset, language, value)
+
+        if header not in self and header.lower() == 'content-type':
+            ctype = 'text/plain'
+        else:
+            ctype = self.get(header)
+        if not self.get_param(param, header=header):
+            if not ctype:
+                ctype = _formatparam(param, value, requote)
+            else:
+                ctype = SEMISPACE.join(
+                    [ctype, _formatparam(param, value, requote)])
+        else:
+            ctype = ''
+            for old_param, old_value in self.get_params(header=header,
+                                                        unquote=requote):
+                append_param = ''
+                if old_param.lower() == param.lower():
+                    append_param = _formatparam(param, value, requote)
+                else:
+                    append_param = _formatparam(old_param, old_value, requote)
+                if not ctype:
+                    ctype = append_param
+                else:
+                    ctype = SEMISPACE.join([ctype, append_param])
+        if ctype != self.get(header):
+            del self[header]
+            self[header] = ctype
+
+    def del_param(self, param, header='content-type', requote=True):
+        """Remove the given parameter completely from the Content-Type header.
+
+        The header will be re-written in place without the parameter or its
+        value. All values will be quoted as necessary unless requote is
+        False.  Optional header specifies an alternative to the Content-Type
+        header.
+        """
+        if header not in self:
+            return
+        new_ctype = ''
+        for p, v in self.get_params(header=header, unquote=requote):
+            if p.lower() != param.lower():
+                if not new_ctype:
+                    new_ctype = _formatparam(p, v, requote)
+                else:
+                    new_ctype = SEMISPACE.join([new_ctype,
+                                                _formatparam(p, v, requote)])
+        if new_ctype != self.get(header):
+            del self[header]
+            self[header] = new_ctype
+
+    def set_type(self, type, header='Content-Type', requote=True):
+        """Set the main type and subtype for the Content-Type header.
+
+        type must be a string in the form "maintype/subtype", otherwise a
+        ValueError is raised.
+
+        This method replaces the Content-Type header, keeping all the
+        parameters in place.  If requote is False, this leaves the existing
+        header's quoting as is.  Otherwise, the parameters will be quoted (the
+        default).
+
+        An alternative header can be specified in the header argument.  When
+        the Content-Type header is set, we'll always also add a MIME-Version
+        header.
+        """
+        # BAW: should we be strict?
+        if not type.count('/') == 1:
+            raise ValueError
+        # Set the Content-Type, you get a MIME-Version
+        if header.lower() == 'content-type':
+            del self['mime-version']
+            self['MIME-Version'] = '1.0'
+        if header not in self:
+            self[header] = type
+            return
+        params = self.get_params(header=header, unquote=requote)
+        del self[header]
+        self[header] = type
+        # Skip the first param; it's the old type.
+        for p, v in params[1:]:
+            self.set_param(p, v, header, requote)
+
+    def get_filename(self, failobj=None):
+        """Return the filename associated with the payload if present.
+
+        The filename is extracted from the Content-Disposition header's
+        `filename' parameter, and it is unquoted.  If that header is missing
+        the `filename' parameter, this method falls back to looking for the
+        `name' parameter.
+        """
+        missing = object()
+        filename = self.get_param('filename', missing, 'content-disposition')
+        if filename is missing:
+            filename = self.get_param('name', missing, 'content-type')
+        if filename is missing:
+            return failobj
+        return utils.collapse_rfc2231_value(filename).strip()
+
+    def get_boundary(self, failobj=None):
+        """Return the boundary associated with the payload if present.
+
+        The boundary is extracted from the Content-Type header's `boundary'
+        parameter, and it is unquoted.
+        """
+        missing = object()
+        boundary = self.get_param('boundary', missing)
+        if boundary is missing:
+            return failobj
+        # RFC 2046 says that boundaries may begin but not end in w/s
+        return utils.collapse_rfc2231_value(boundary).rstrip()
+
+    def set_boundary(self, boundary):
+        """Set the boundary parameter in Content-Type to 'boundary'.
+
+        This is subtly different than deleting the Content-Type header and
+        adding a new one with a new boundary parameter via add_header().  The
+        main difference is that using the set_boundary() method preserves the
+        order of the Content-Type header in the original message.
+
+        HeaderParseError is raised if the message has no Content-Type header.
+        """
+        missing = object()
+        params = self._get_params_preserve(missing, 'content-type')
+        if params is missing:
+            # There was no Content-Type header, and we don't know what type
+            # to set it to, so raise an exception.
+            raise errors.HeaderParseError('No Content-Type header found')
+        newparams = []
+        foundp = False
+        for pk, pv in params:
+            if pk.lower() == 'boundary':
+                newparams.append(('boundary', '"%s"' % boundary))
+                foundp = True
+            else:
+                newparams.append((pk, pv))
+        if not foundp:
+            # The original Content-Type header had no boundary attribute.
+            # Tack one on the end.  BAW: should we raise an exception
+            # instead???
+            newparams.append(('boundary', '"%s"' % boundary))
+        # Replace the existing Content-Type header with the new value
+        newheaders = []
+        for h, v in self._headers:
+            if h.lower() == 'content-type':
+                parts = []
+                for k, v in newparams:
+                    if v == '':
+                        parts.append(k)
+                    else:
+                        parts.append('%s=%s' % (k, v))
+                newheaders.append((h, SEMISPACE.join(parts)))
+
+            else:
+                newheaders.append((h, v))
+        self._headers = newheaders
+
+    def get_content_charset(self, failobj=None):
+        """Return the charset parameter of the Content-Type header.
+
+        The returned string is always coerced to lower case.  If there is no
+        Content-Type header, or if that header has no charset parameter,
+        failobj is returned.
+        """
+        missing = object()
+        charset = self.get_param('charset', missing)
+        if charset is missing:
+            return failobj
+        if isinstance(charset, tuple):
+            # RFC 2231 encoded, so decode it, and it better end up as ascii.
+            pcharset = charset[0] or 'us-ascii'
+            try:
+                # LookupError will be raised if the charset isn't known to
+                # Python.  UnicodeError will be raised if the encoded text
+                # contains a character not in the charset.
+                charset = unicode(charset[2], pcharset).encode('us-ascii')
+            except (LookupError, UnicodeError):
+                charset = charset[2]
+        # charset character must be in us-ascii range
+        try:
+            if isinstance(charset, str):
+                charset = unicode(charset, 'us-ascii')
+            charset = charset.encode('us-ascii')
+        except UnicodeError:
+            return failobj
+        # RFC 2046, $4.1.2 says charsets are not case sensitive
+        return charset.lower()
+
+    def get_charsets(self, failobj=None):
+        """Return a list containing the charset(s) used in this message.
+
+        The returned list of items describes the Content-Type headers'
+        charset parameter for this message and all the subparts in its
+        payload.
+
+        Each item will either be a string (the value of the charset parameter
+        in the Content-Type header of that part) or the value of the
+        'failobj' parameter (defaults to None), if the part does not have a
+        main MIME type of "text", or the charset is not defined.
+
+        The list will contain one string for each part of the message, plus
+        one for the container message (i.e. self), so that a non-multipart
+        message will still return a list of length 1.
+        """
+        return [part.get_content_charset(failobj) for part in self.walk()]
+
+    # I.e. def walk(self): ...
+    from email.iterators import walk
diff --git a/src/main/resources/PythonLibs/email/mime/__init__.py b/src/main/resources/PythonLibs/email/mime/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/main/resources/PythonLibs/email/mime/application.py b/src/main/resources/PythonLibs/email/mime/application.py
new file mode 100644
index 0000000000000000000000000000000000000000..f5c5905564f690dc36a5d8afef5958bc0283281f
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/mime/application.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Keith Dart
+# Contact: email-sig@python.org
+
+"""Class representing application/* type MIME documents."""
+
+__all__ = ["MIMEApplication"]
+
+from email import encoders
+from email.mime.nonmultipart import MIMENonMultipart
+
+
+class MIMEApplication(MIMENonMultipart):
+    """Class for generating application/* MIME documents."""
+
+    def __init__(self, _data, _subtype='octet-stream',
+                 _encoder=encoders.encode_base64, **_params):
+        """Create an application/* type MIME document.
+
+        _data is a string containing the raw application data.
+
+        _subtype is the MIME content type subtype, defaulting to
+        'octet-stream'.
+
+        _encoder is a function which will perform the actual encoding for
+        transport of the application data, defaulting to base64 encoding.
+
+        Any additional keyword arguments are passed to the base class
+        constructor, which turns them into parameters on the Content-Type
+        header.
+        """
+        if _subtype is None:
+            raise TypeError('Invalid application MIME subtype')
+        MIMENonMultipart.__init__(self, 'application', _subtype, **_params)
+        self.set_payload(_data)
+        _encoder(self)
diff --git a/src/main/resources/PythonLibs/email/mime/audio.py b/src/main/resources/PythonLibs/email/mime/audio.py
new file mode 100644
index 0000000000000000000000000000000000000000..c7290c4b1c27dda6fe4a97f6c3d79ac6924bafd3
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/mime/audio.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Anthony Baxter
+# Contact: email-sig@python.org
+
+"""Class representing audio/* type MIME documents."""
+
+__all__ = ['MIMEAudio']
+
+import sndhdr
+
+from cStringIO import StringIO
+from email import encoders
+from email.mime.nonmultipart import MIMENonMultipart
+
+
+
+_sndhdr_MIMEmap = {'au'  : 'basic',
+                   'wav' :'x-wav',
+                   'aiff':'x-aiff',
+                   'aifc':'x-aiff',
+                   }
+
+# There are others in sndhdr that don't have MIME types. :(
+# Additional ones to be added to sndhdr? midi, mp3, realaudio, wma??
+def _whatsnd(data):
+    """Try to identify a sound file type.
+
+    sndhdr.what() has a pretty cruddy interface, unfortunately.  This is why
+    we re-do it here.  It would be easier to reverse engineer the Unix 'file'
+    command and use the standard 'magic' file, as shipped with a modern Unix.
+    """
+    hdr = data[:512]
+    fakefile = StringIO(hdr)
+    for testfn in sndhdr.tests:
+        res = testfn(hdr, fakefile)
+        if res is not None:
+            return _sndhdr_MIMEmap.get(res[0])
+    return None
+
+
+
+class MIMEAudio(MIMENonMultipart):
+    """Class for generating audio/* MIME documents."""
+
+    def __init__(self, _audiodata, _subtype=None,
+                 _encoder=encoders.encode_base64, **_params):
+        """Create an audio/* type MIME document.
+
+        _audiodata is a string containing the raw audio data.  If this data
+        can be decoded by the standard Python `sndhdr' module, then the
+        subtype will be automatically included in the Content-Type header.
+        Otherwise, you can specify  the specific audio subtype via the
+        _subtype parameter.  If _subtype is not given, and no subtype can be
+        guessed, a TypeError is raised.
+
+        _encoder is a function which will perform the actual encoding for
+        transport of the image data.  It takes one argument, which is this
+        Image instance.  It should use get_payload() and set_payload() to
+        change the payload to the encoded form.  It should also add any
+        Content-Transfer-Encoding or other headers to the message as
+        necessary.  The default encoding is Base64.
+
+        Any additional keyword arguments are passed to the base class
+        constructor, which turns them into parameters on the Content-Type
+        header.
+        """
+        if _subtype is None:
+            _subtype = _whatsnd(_audiodata)
+        if _subtype is None:
+            raise TypeError('Could not find audio MIME subtype')
+        MIMENonMultipart.__init__(self, 'audio', _subtype, **_params)
+        self.set_payload(_audiodata)
+        _encoder(self)
diff --git a/src/main/resources/PythonLibs/email/mime/base.py b/src/main/resources/PythonLibs/email/mime/base.py
new file mode 100644
index 0000000000000000000000000000000000000000..ac919258b15ba8e678fde8a979ba2f93828930db
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/mime/base.py
@@ -0,0 +1,26 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Base class for MIME specializations."""
+
+__all__ = ['MIMEBase']
+
+from email import message
+
+
+
+class MIMEBase(message.Message):
+    """Base class for MIME specializations."""
+
+    def __init__(self, _maintype, _subtype, **_params):
+        """This constructor adds a Content-Type: and a MIME-Version: header.
+
+        The Content-Type: header is taken from the _maintype and _subtype
+        arguments.  Additional parameters for this header are taken from the
+        keyword arguments.
+        """
+        message.Message.__init__(self)
+        ctype = '%s/%s' % (_maintype, _subtype)
+        self.add_header('Content-Type', ctype, **_params)
+        self['MIME-Version'] = '1.0'
diff --git a/src/main/resources/PythonLibs/email/mime/image.py b/src/main/resources/PythonLibs/email/mime/image.py
new file mode 100644
index 0000000000000000000000000000000000000000..5563823239b8be88893d6d03a39fb1a206c65285
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/mime/image.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Class representing image/* type MIME documents."""
+
+__all__ = ['MIMEImage']
+
+import imghdr
+
+from email import encoders
+from email.mime.nonmultipart import MIMENonMultipart
+
+
+
+class MIMEImage(MIMENonMultipart):
+    """Class for generating image/* type MIME documents."""
+
+    def __init__(self, _imagedata, _subtype=None,
+                 _encoder=encoders.encode_base64, **_params):
+        """Create an image/* type MIME document.
+
+        _imagedata is a string containing the raw image data.  If this data
+        can be decoded by the standard Python `imghdr' module, then the
+        subtype will be automatically included in the Content-Type header.
+        Otherwise, you can specify the specific image subtype via the _subtype
+        parameter.
+
+        _encoder is a function which will perform the actual encoding for
+        transport of the image data.  It takes one argument, which is this
+        Image instance.  It should use get_payload() and set_payload() to
+        change the payload to the encoded form.  It should also add any
+        Content-Transfer-Encoding or other headers to the message as
+        necessary.  The default encoding is Base64.
+
+        Any additional keyword arguments are passed to the base class
+        constructor, which turns them into parameters on the Content-Type
+        header.
+        """
+        if _subtype is None:
+            _subtype = imghdr.what(None, _imagedata)
+        if _subtype is None:
+            raise TypeError('Could not guess image MIME subtype')
+        MIMENonMultipart.__init__(self, 'image', _subtype, **_params)
+        self.set_payload(_imagedata)
+        _encoder(self)
diff --git a/src/main/resources/PythonLibs/email/mime/message.py b/src/main/resources/PythonLibs/email/mime/message.py
new file mode 100644
index 0000000000000000000000000000000000000000..275dbfd088652abedbf062ef99521261510141b4
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/mime/message.py
@@ -0,0 +1,34 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Class representing message/* MIME documents."""
+
+__all__ = ['MIMEMessage']
+
+from email import message
+from email.mime.nonmultipart import MIMENonMultipart
+
+
+
+class MIMEMessage(MIMENonMultipart):
+    """Class representing message/* MIME documents."""
+
+    def __init__(self, _msg, _subtype='rfc822'):
+        """Create a message/* type MIME document.
+
+        _msg is a message object and must be an instance of Message, or a
+        derived class of Message, otherwise a TypeError is raised.
+
+        Optional _subtype defines the subtype of the contained message.  The
+        default is "rfc822" (this is defined by the MIME standard, even though
+        the term "rfc822" is technically outdated by RFC 2822).
+        """
+        MIMENonMultipart.__init__(self, 'message', _subtype)
+        if not isinstance(_msg, message.Message):
+            raise TypeError('Argument is not an instance of Message')
+        # It's convenient to use this base class method.  We need to do it
+        # this way or we'll get an exception
+        message.Message.attach(self, _msg)
+        # And be sure our default type is set correctly
+        self.set_default_type('message/rfc822')
diff --git a/src/main/resources/PythonLibs/email/mime/multipart.py b/src/main/resources/PythonLibs/email/mime/multipart.py
new file mode 100644
index 0000000000000000000000000000000000000000..96618650c519c5cdf38cd2dbfe6ddba8d78ec63f
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/mime/multipart.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2002-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Base class for MIME multipart/* type messages."""
+
+__all__ = ['MIMEMultipart']
+
+from email.mime.base import MIMEBase
+
+
+
+class MIMEMultipart(MIMEBase):
+    """Base class for MIME multipart/* type messages."""
+
+    def __init__(self, _subtype='mixed', boundary=None, _subparts=None,
+                 **_params):
+        """Creates a multipart/* type message.
+
+        By default, creates a multipart/mixed message, with proper
+        Content-Type and MIME-Version headers.
+
+        _subtype is the subtype of the multipart content type, defaulting to
+        `mixed'.
+
+        boundary is the multipart boundary string.  By default it is
+        calculated as needed.
+
+        _subparts is a sequence of initial subparts for the payload.  It
+        must be an iterable object, such as a list.  You can always
+        attach new subparts to the message by using the attach() method.
+
+        Additional parameters for the Content-Type header are taken from the
+        keyword arguments (or passed into the _params argument).
+        """
+        MIMEBase.__init__(self, 'multipart', _subtype, **_params)
+
+        # Initialise _payload to an empty list as the Message superclass's
+        # implementation of is_multipart assumes that _payload is a list for
+        # multipart messages.
+        self._payload = []
+
+        if _subparts:
+            for p in _subparts:
+                self.attach(p)
+        if boundary:
+            self.set_boundary(boundary)
diff --git a/src/main/resources/PythonLibs/email/mime/nonmultipart.py b/src/main/resources/PythonLibs/email/mime/nonmultipart.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc3b9eb4dcfbf8ef4621ee7e545cc237dcf12e09
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/mime/nonmultipart.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2002-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Base class for MIME type messages that are not multipart."""
+
+__all__ = ['MIMENonMultipart']
+
+from email import errors
+from email.mime.base import MIMEBase
+
+
+
+class MIMENonMultipart(MIMEBase):
+    """Base class for MIME multipart/* type messages."""
+
+    def attach(self, payload):
+        # The public API prohibits attaching multiple subparts to MIMEBase
+        # derived subtypes since none of them are, by definition, of content
+        # type multipart/*
+        raise errors.MultipartConversionError(
+            'Cannot attach additional subparts to non-multipart/*')
diff --git a/src/main/resources/PythonLibs/email/mime/text.py b/src/main/resources/PythonLibs/email/mime/text.py
new file mode 100644
index 0000000000000000000000000000000000000000..5747db5d670c8082999cc6f089dcc416db07ddba
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/mime/text.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Class representing text/* type MIME documents."""
+
+__all__ = ['MIMEText']
+
+from email.encoders import encode_7or8bit
+from email.mime.nonmultipart import MIMENonMultipart
+
+
+
+class MIMEText(MIMENonMultipart):
+    """Class for generating text/* type MIME documents."""
+
+    def __init__(self, _text, _subtype='plain', _charset='us-ascii'):
+        """Create a text/* type MIME document.
+
+        _text is the string for this message object.
+
+        _subtype is the MIME sub content type, defaulting to "plain".
+
+        _charset is the character set parameter added to the Content-Type
+        header.  This defaults to "us-ascii".  Note that as a side-effect, the
+        Content-Transfer-Encoding header will also be set.
+        """
+        MIMENonMultipart.__init__(self, 'text', _subtype,
+                                  **{'charset': _charset})
+        self.set_payload(_text, _charset)
diff --git a/src/main/resources/PythonLibs/email/parser.py b/src/main/resources/PythonLibs/email/parser.py
new file mode 100644
index 0000000000000000000000000000000000000000..2fcaf25456273b94cbde5b7a55bc4ab7613affbf
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/parser.py
@@ -0,0 +1,91 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw, Thomas Wouters, Anthony Baxter
+# Contact: email-sig@python.org
+
+"""A parser of RFC 2822 and MIME email messages."""
+
+__all__ = ['Parser', 'HeaderParser']
+
+import warnings
+from cStringIO import StringIO
+
+from email.feedparser import FeedParser
+from email.message import Message
+
+
+
+class Parser:
+    def __init__(self, *args, **kws):
+        """Parser of RFC 2822 and MIME email messages.
+
+        Creates an in-memory object tree representing the email message, which
+        can then be manipulated and turned over to a Generator to return the
+        textual representation of the message.
+
+        The string must be formatted as a block of RFC 2822 headers and header
+        continuation lines, optionally preceeded by a `Unix-from' header.  The
+        header block is terminated either by the end of the string or by a
+        blank line.
+
+        _class is the class to instantiate for new message objects when they
+        must be created.  This class must have a constructor that can take
+        zero arguments.  Default is Message.Message.
+        """
+        if len(args) >= 1:
+            if '_class' in kws:
+                raise TypeError("Multiple values for keyword arg '_class'")
+            kws['_class'] = args[0]
+        if len(args) == 2:
+            if 'strict' in kws:
+                raise TypeError("Multiple values for keyword arg 'strict'")
+            kws['strict'] = args[1]
+        if len(args) > 2:
+            raise TypeError('Too many arguments')
+        if '_class' in kws:
+            self._class = kws['_class']
+            del kws['_class']
+        else:
+            self._class = Message
+        if 'strict' in kws:
+            warnings.warn("'strict' argument is deprecated (and ignored)",
+                          DeprecationWarning, 2)
+            del kws['strict']
+        if kws:
+            raise TypeError('Unexpected keyword arguments')
+
+    def parse(self, fp, headersonly=False):
+        """Create a message structure from the data in a file.
+
+        Reads all the data from the file and returns the root of the message
+        structure.  Optional headersonly is a flag specifying whether to stop
+        parsing after reading the headers or not.  The default is False,
+        meaning it parses the entire contents of the file.
+        """
+        feedparser = FeedParser(self._class)
+        if headersonly:
+            feedparser._set_headersonly()
+        while True:
+            data = fp.read(8192)
+            if not data:
+                break
+            feedparser.feed(data)
+        return feedparser.close()
+
+    def parsestr(self, text, headersonly=False):
+        """Create a message structure from a string.
+
+        Returns the root of the message structure.  Optional headersonly is a
+        flag specifying whether to stop parsing after reading the headers or
+        not.  The default is False, meaning it parses the entire contents of
+        the file.
+        """
+        return self.parse(StringIO(text), headersonly=headersonly)
+
+
+
+class HeaderParser(Parser):
+    def parse(self, fp, headersonly=True):
+        return Parser.parse(self, fp, True)
+
+    def parsestr(self, text, headersonly=True):
+        return Parser.parsestr(self, text, True)
diff --git a/src/main/resources/PythonLibs/email/quoprimime.py b/src/main/resources/PythonLibs/email/quoprimime.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c18a9e04efb23beb8d6089d514d0d0a577c6e40
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/quoprimime.py
@@ -0,0 +1,336 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Ben Gertzfield
+# Contact: email-sig@python.org
+
+"""Quoted-printable content transfer encoding per RFCs 2045-2047.
+
+This module handles the content transfer encoding method defined in RFC 2045
+to encode US ASCII-like 8-bit data called `quoted-printable'.  It is used to
+safely encode text that is in a character set similar to the 7-bit US ASCII
+character set, but that includes some 8-bit characters that are normally not
+allowed in email bodies or headers.
+
+Quoted-printable is very space-inefficient for encoding binary files; use the
+email.base64mime module for that instead.
+
+This module provides an interface to encode and decode both headers and bodies
+with quoted-printable encoding.
+
+RFC 2045 defines a method for including character set information in an
+`encoded-word' in a header.  This method is commonly used for 8-bit real names
+in To:/From:/Cc: etc. fields, as well as Subject: lines.
+
+This module does not do the line wrapping or end-of-line character
+conversion necessary for proper internationalized headers; it only
+does dumb encoding and decoding.  To deal with the various line
+wrapping issues, use the email.header module.
+"""
+
+__all__ = [
+    'body_decode',
+    'body_encode',
+    'body_quopri_check',
+    'body_quopri_len',
+    'decode',
+    'decodestring',
+    'encode',
+    'encodestring',
+    'header_decode',
+    'header_encode',
+    'header_quopri_check',
+    'header_quopri_len',
+    'quote',
+    'unquote',
+    ]
+
+import re
+
+from string import hexdigits
+from email.utils import fix_eols
+
+CRLF = '\r\n'
+NL = '\n'
+
+# See also Charset.py
+MISC_LEN = 7
+
+hqre = re.compile(r'[^-a-zA-Z0-9!*+/ ]')
+bqre = re.compile(r'[^ !-<>-~\t]')
+
+
+
+# Helpers
+def header_quopri_check(c):
+    """Return True if the character should be escaped with header quopri."""
+    return bool(hqre.match(c))
+
+
+def body_quopri_check(c):
+    """Return True if the character should be escaped with body quopri."""
+    return bool(bqre.match(c))
+
+
+def header_quopri_len(s):
+    """Return the length of str when it is encoded with header quopri."""
+    count = 0
+    for c in s:
+        if hqre.match(c):
+            count += 3
+        else:
+            count += 1
+    return count
+
+
+def body_quopri_len(str):
+    """Return the length of str when it is encoded with body quopri."""
+    count = 0
+    for c in str:
+        if bqre.match(c):
+            count += 3
+        else:
+            count += 1
+    return count
+
+
+def _max_append(L, s, maxlen, extra=''):
+    if not L:
+        L.append(s.lstrip())
+    elif len(L[-1]) + len(s) <= maxlen:
+        L[-1] += extra + s
+    else:
+        L.append(s.lstrip())
+
+
+def unquote(s):
+    """Turn a string in the form =AB to the ASCII character with value 0xab"""
+    return chr(int(s[1:3], 16))
+
+
+def quote(c):
+    return "=%02X" % ord(c)
+
+
+
+def header_encode(header, charset="iso-8859-1", keep_eols=False,
+                  maxlinelen=76, eol=NL):
+    """Encode a single header line with quoted-printable (like) encoding.
+
+    Defined in RFC 2045, this `Q' encoding is similar to quoted-printable, but
+    used specifically for email header fields to allow charsets with mostly 7
+    bit characters (and some 8 bit) to remain more or less readable in non-RFC
+    2045 aware mail clients.
+
+    charset names the character set to use to encode the header.  It defaults
+    to iso-8859-1.
+
+    The resulting string will be in the form:
+
+    "=?charset?q?I_f=E2rt_in_your_g=E8n=E8ral_dire=E7tion?\\n
+      =?charset?q?Silly_=C8nglish_Kn=EEghts?="
+
+    with each line wrapped safely at, at most, maxlinelen characters (defaults
+    to 76 characters).  If maxlinelen is None, the entire string is encoded in
+    one chunk with no splitting.
+
+    End-of-line characters (\\r, \\n, \\r\\n) will be automatically converted
+    to the canonical email line separator \\r\\n unless the keep_eols
+    parameter is True (the default is False).
+
+    Each line of the header will be terminated in the value of eol, which
+    defaults to "\\n".  Set this to "\\r\\n" if you are using the result of
+    this function directly in email.
+    """
+    # Return empty headers unchanged
+    if not header:
+        return header
+
+    if not keep_eols:
+        header = fix_eols(header)
+
+    # Quopri encode each line, in encoded chunks no greater than maxlinelen in
+    # length, after the RFC chrome is added in.
+    quoted = []
+    if maxlinelen is None:
+        # An obnoxiously large number that's good enough
+        max_encoded = 100000
+    else:
+        max_encoded = maxlinelen - len(charset) - MISC_LEN - 1
+
+    for c in header:
+        # Space may be represented as _ instead of =20 for readability
+        if c == ' ':
+            _max_append(quoted, '_', max_encoded)
+        # These characters can be included verbatim
+        elif not hqre.match(c):
+            _max_append(quoted, c, max_encoded)
+        # Otherwise, replace with hex value like =E2
+        else:
+            _max_append(quoted, "=%02X" % ord(c), max_encoded)
+
+    # Now add the RFC chrome to each encoded chunk and glue the chunks
+    # together.  BAW: should we be able to specify the leading whitespace in
+    # the joiner?
+    joiner = eol + ' '
+    return joiner.join(['=?%s?q?%s?=' % (charset, line) for line in quoted])
+
+
+
+def encode(body, binary=False, maxlinelen=76, eol=NL):
+    """Encode with quoted-printable, wrapping at maxlinelen characters.
+
+    If binary is False (the default), end-of-line characters will be converted
+    to the canonical email end-of-line sequence \\r\\n.  Otherwise they will
+    be left verbatim.
+
+    Each line of encoded text will end with eol, which defaults to "\\n".  Set
+    this to "\\r\\n" if you will be using the result of this function directly
+    in an email.
+
+    Each line will be wrapped at, at most, maxlinelen characters (defaults to
+    76 characters).  Long lines will have the `soft linefeed' quoted-printable
+    character "=" appended to them, so the decoded text will be identical to
+    the original text.
+    """
+    if not body:
+        return body
+
+    if not binary:
+        body = fix_eols(body)
+
+    # BAW: We're accumulating the body text by string concatenation.  That
+    # can't be very efficient, but I don't have time now to rewrite it.  It
+    # just feels like this algorithm could be more efficient.
+    encoded_body = ''
+    lineno = -1
+    # Preserve line endings here so we can check later to see an eol needs to
+    # be added to the output later.
+    lines = body.splitlines(1)
+    for line in lines:
+        # But strip off line-endings for processing this line.
+        if line.endswith(CRLF):
+            line = line[:-2]
+        elif line[-1] in CRLF:
+            line = line[:-1]
+
+        lineno += 1
+        encoded_line = ''
+        prev = None
+        linelen = len(line)
+        # Now we need to examine every character to see if it needs to be
+        # quopri encoded.  BAW: again, string concatenation is inefficient.
+        for j in range(linelen):
+            c = line[j]
+            prev = c
+            if bqre.match(c):
+                c = quote(c)
+            elif j+1 == linelen:
+                # Check for whitespace at end of line; special case
+                if c not in ' \t':
+                    encoded_line += c
+                prev = c
+                continue
+            # Check to see to see if the line has reached its maximum length
+            if len(encoded_line) + len(c) >= maxlinelen:
+                encoded_body += encoded_line + '=' + eol
+                encoded_line = ''
+            encoded_line += c
+        # Now at end of line..
+        if prev and prev in ' \t':
+            # Special case for whitespace at end of file
+            if lineno + 1 == len(lines):
+                prev = quote(prev)
+                if len(encoded_line) + len(prev) > maxlinelen:
+                    encoded_body += encoded_line + '=' + eol + prev
+                else:
+                    encoded_body += encoded_line + prev
+            # Just normal whitespace at end of line
+            else:
+                encoded_body += encoded_line + prev + '=' + eol
+            encoded_line = ''
+        # Now look at the line we just finished and it has a line ending, we
+        # need to add eol to the end of the line.
+        if lines[lineno].endswith(CRLF) or lines[lineno][-1] in CRLF:
+            encoded_body += encoded_line + eol
+        else:
+            encoded_body += encoded_line
+        encoded_line = ''
+    return encoded_body
+
+
+# For convenience and backwards compatibility w/ standard base64 module
+body_encode = encode
+encodestring = encode
+
+
+
+# BAW: I'm not sure if the intent was for the signature of this function to be
+# the same as base64MIME.decode() or not...
+def decode(encoded, eol=NL):
+    """Decode a quoted-printable string.
+
+    Lines are separated with eol, which defaults to \\n.
+    """
+    if not encoded:
+        return encoded
+    # BAW: see comment in encode() above.  Again, we're building up the
+    # decoded string with string concatenation, which could be done much more
+    # efficiently.
+    decoded = ''
+
+    for line in encoded.splitlines():
+        line = line.rstrip()
+        if not line:
+            decoded += eol
+            continue
+
+        i = 0
+        n = len(line)
+        while i < n:
+            c = line[i]
+            if c != '=':
+                decoded += c
+                i += 1
+            # Otherwise, c == "=".  Are we at the end of the line?  If so, add
+            # a soft line break.
+            elif i+1 == n:
+                i += 1
+                continue
+            # Decode if in form =AB
+            elif i+2 < n and line[i+1] in hexdigits and line[i+2] in hexdigits:
+                decoded += unquote(line[i:i+3])
+                i += 3
+            # Otherwise, not in form =AB, pass literally
+            else:
+                decoded += c
+                i += 1
+
+            if i == n:
+                decoded += eol
+    # Special case if original string did not end with eol
+    if not encoded.endswith(eol) and decoded.endswith(eol):
+        decoded = decoded[:-1]
+    return decoded
+
+
+# For convenience and backwards compatibility w/ standard base64 module
+body_decode = decode
+decodestring = decode
+
+
+
+def _unquote_match(match):
+    """Turn a match in the form =AB to the ASCII character with value 0xab"""
+    s = match.group(0)
+    return unquote(s)
+
+
+# Header decoding is done a bit differently
+def header_decode(s):
+    """Decode a string encoded with RFC 2045 MIME header `Q' encoding.
+
+    This function does not parse a full MIME header value encoded with
+    quoted-printable (like =?iso-8895-1?q?Hello_World?=) -- please use
+    the high level email.header class for that functionality.
+    """
+    s = s.replace('_', ' ')
+    return re.sub(r'=[a-fA-F0-9]{2}', _unquote_match, s)
diff --git a/src/main/resources/PythonLibs/email/utils.py b/src/main/resources/PythonLibs/email/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..c976021e0e0584c6ee56d5aa32b0034c531349c5
--- /dev/null
+++ b/src/main/resources/PythonLibs/email/utils.py
@@ -0,0 +1,324 @@
+# Copyright (C) 2001-2010 Python Software Foundation
+# Author: Barry Warsaw
+# Contact: email-sig@python.org
+
+"""Miscellaneous utilities."""
+
+__all__ = [
+    'collapse_rfc2231_value',
+    'decode_params',
+    'decode_rfc2231',
+    'encode_rfc2231',
+    'formataddr',
+    'formatdate',
+    'getaddresses',
+    'make_msgid',
+    'mktime_tz',
+    'parseaddr',
+    'parsedate',
+    'parsedate_tz',
+    'unquote',
+    ]
+
+import os
+import re
+import time
+import base64
+import random
+import socket
+import urllib
+import warnings
+
+from email._parseaddr import quote
+from email._parseaddr import AddressList as _AddressList
+from email._parseaddr import mktime_tz
+
+# We need wormarounds for bugs in these methods in older Pythons (see below)
+from email._parseaddr import parsedate as _parsedate
+from email._parseaddr import parsedate_tz as _parsedate_tz
+
+from quopri import decodestring as _qdecode
+
+# Intrapackage imports
+from email.encoders import _bencode, _qencode
+
+COMMASPACE = ', '
+EMPTYSTRING = ''
+UEMPTYSTRING = u''
+CRLF = '\r\n'
+TICK = "'"
+
+specialsre = re.compile(r'[][\\()<>@,:;".]')
+escapesre = re.compile(r'[][\\()"]')
+
+
+
+# Helpers
+
+def _identity(s):
+    return s
+
+
+def _bdecode(s):
+    """Decodes a base64 string.
+
+    This function is equivalent to base64.decodestring and it's retained only
+    for backward compatibility. It used to remove the last \\n of the decoded
+    string, if it had any (see issue 7143).
+    """
+    if not s:
+        return s
+    return base64.decodestring(s)
+
+
+
+def fix_eols(s):
+    """Replace all line-ending characters with \\r\\n."""
+    # Fix newlines with no preceding carriage return
+    s = re.sub(r'(?<!\r)\n', CRLF, s)
+    # Fix carriage returns with no following newline
+    s = re.sub(r'\r(?!\n)', CRLF, s)
+    return s
+
+
+
+def formataddr(pair):
+    """The inverse of parseaddr(), this takes a 2-tuple of the form
+    (realname, email_address) and returns the string value suitable
+    for an RFC 2822 From, To or Cc header.
+
+    If the first element of pair is false, then the second element is
+    returned unmodified.
+    """
+    name, address = pair
+    if name:
+        quotes = ''
+        if specialsre.search(name):
+            quotes = '"'
+        name = escapesre.sub(r'\\\g<0>', name)
+        return '%s%s%s <%s>' % (quotes, name, quotes, address)
+    return address
+
+
+
+def getaddresses(fieldvalues):
+    """Return a list of (REALNAME, EMAIL) for each fieldvalue."""
+    all = COMMASPACE.join(fieldvalues)
+    a = _AddressList(all)
+    return a.addresslist
+
+
+
+ecre = re.compile(r'''
+  =\?                   # literal =?
+  (?P<charset>[^?]*?)   # non-greedy up to the next ? is the charset
+  \?                    # literal ?
+  (?P<encoding>[qb])    # either a "q" or a "b", case insensitive
+  \?                    # literal ?
+  (?P<atom>.*?)         # non-greedy up to the next ?= is the atom
+  \?=                   # literal ?=
+  ''', re.VERBOSE | re.IGNORECASE)
+
+
+
+def formatdate(timeval=None, localtime=False, usegmt=False):
+    """Returns a date string as specified by RFC 2822, e.g.:
+
+    Fri, 09 Nov 2001 01:08:47 -0000
+
+    Optional timeval if given is a floating point time value as accepted by
+    gmtime() and localtime(), otherwise the current time is used.
+
+    Optional localtime is a flag that when True, interprets timeval, and
+    returns a date relative to the local timezone instead of UTC, properly
+    taking daylight savings time into account.
+
+    Optional argument usegmt means that the timezone is written out as
+    an ascii string, not numeric one (so "GMT" instead of "+0000"). This
+    is needed for HTTP, and is only used when localtime==False.
+    """
+    # Note: we cannot use strftime() because that honors the locale and RFC
+    # 2822 requires that day and month names be the English abbreviations.
+    if timeval is None:
+        timeval = time.time()
+    if localtime:
+        now = time.localtime(timeval)
+        # Calculate timezone offset, based on whether the local zone has
+        # daylight savings time, and whether DST is in effect.
+        if time.daylight and now[-1]:
+            offset = time.altzone
+        else:
+            offset = time.timezone
+        hours, minutes = divmod(abs(offset), 3600)
+        # Remember offset is in seconds west of UTC, but the timezone is in
+        # minutes east of UTC, so the signs differ.
+        if offset > 0:
+            sign = '-'
+        else:
+            sign = '+'
+        zone = '%s%02d%02d' % (sign, hours, minutes // 60)
+    else:
+        now = time.gmtime(timeval)
+        # Timezone offset is always -0000
+        if usegmt:
+            zone = 'GMT'
+        else:
+            zone = '-0000'
+    return '%s, %02d %s %04d %02d:%02d:%02d %s' % (
+        ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][now[6]],
+        now[2],
+        ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+         'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][now[1] - 1],
+        now[0], now[3], now[4], now[5],
+        zone)
+
+
+
+def make_msgid(idstring=None):
+    """Returns a string suitable for RFC 2822 compliant Message-ID, e.g:
+
+    <20020201195627.33539.96671@nightshade.la.mastaler.com>
+
+    Optional idstring if given is a string used to strengthen the
+    uniqueness of the message id.
+    """
+    timeval = time.time()
+    utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval))
+    pid = os.getpid()
+    randint = random.randrange(100000)
+    if idstring is None:
+        idstring = ''
+    else:
+        idstring = '.' + idstring
+    idhost = socket.getfqdn()
+    msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, idhost)
+    return msgid
+
+
+
+# These functions are in the standalone mimelib version only because they've
+# subsequently been fixed in the latest Python versions.  We use this to worm
+# around broken older Pythons.
+def parsedate(data):
+    if not data:
+        return None
+    return _parsedate(data)
+
+
+def parsedate_tz(data):
+    if not data:
+        return None
+    return _parsedate_tz(data)
+
+
+def parseaddr(addr):
+    addrs = _AddressList(addr).addresslist
+    if not addrs:
+        return '', ''
+    return addrs[0]
+
+
+# rfc822.unquote() doesn't properly de-backslash-ify in Python pre-2.3.
+def unquote(str):
+    """Remove quotes from a string."""
+    if len(str) > 1:
+        if str.startswith('"') and str.endswith('"'):
+            return str[1:-1].replace('\\\\', '\\').replace('\\"', '"')
+        if str.startswith('<') and str.endswith('>'):
+            return str[1:-1]
+    return str
+
+
+
+# RFC2231-related functions - parameter encoding and decoding
+def decode_rfc2231(s):
+    """Decode string according to RFC 2231"""
+    parts = s.split(TICK, 2)
+    if len(parts) <= 2:
+        return None, None, s
+    return parts
+
+
+def encode_rfc2231(s, charset=None, language=None):
+    """Encode string according to RFC 2231.
+
+    If neither charset nor language is given, then s is returned as-is.  If
+    charset is given but not language, the string is encoded using the empty
+    string for language.
+    """
+    import urllib
+    s = urllib.quote(s, safe='')
+    if charset is None and language is None:
+        return s
+    if language is None:
+        language = ''
+    return "%s'%s'%s" % (charset, language, s)
+
+
+rfc2231_continuation = re.compile(r'^(?P<name>\w+)\*((?P<num>[0-9]+)\*?)?$')
+
+def decode_params(params):
+    """Decode parameters list according to RFC 2231.
+
+    params is a sequence of 2-tuples containing (param name, string value).
+    """
+    # Copy params so we don't mess with the original
+    params = params[:]
+    new_params = []
+    # Map parameter's name to a list of continuations.  The values are a
+    # 3-tuple of the continuation number, the string value, and a flag
+    # specifying whether a particular segment is %-encoded.
+    rfc2231_params = {}
+    name, value = params.pop(0)
+    new_params.append((name, value))
+    while params:
+        name, value = params.pop(0)
+        if name.endswith('*'):
+            encoded = True
+        else:
+            encoded = False
+        value = unquote(value)
+        mo = rfc2231_continuation.match(name)
+        if mo:
+            name, num = mo.group('name', 'num')
+            if num is not None:
+                num = int(num)
+            rfc2231_params.setdefault(name, []).append((num, value, encoded))
+        else:
+            new_params.append((name, '"%s"' % quote(value)))
+    if rfc2231_params:
+        for name, continuations in rfc2231_params.items():
+            value = []
+            extended = False
+            # Sort by number
+            continuations.sort()
+            # And now append all values in numerical order, converting
+            # %-encodings for the encoded segments.  If any of the
+            # continuation names ends in a *, then the entire string, after
+            # decoding segments and concatenating, must have the charset and
+            # language specifiers at the beginning of the string.
+            for num, s, encoded in continuations:
+                if encoded:
+                    s = urllib.unquote(s)
+                    extended = True
+                value.append(s)
+            value = quote(EMPTYSTRING.join(value))
+            if extended:
+                charset, language, value = decode_rfc2231(value)
+                new_params.append((name, (charset, language, '"%s"' % value)))
+            else:
+                new_params.append((name, '"%s"' % value))
+    return new_params
+
+def collapse_rfc2231_value(value, errors='replace',
+                           fallback_charset='us-ascii'):
+    if isinstance(value, tuple):
+        rawval = unquote(value[2])
+        charset = value[0] or 'us-ascii'
+        try:
+            return unicode(rawval, charset, errors)
+        except LookupError:
+            # XXX charset is unknown to Python.
+            return unicode(rawval, fallback_charset, errors)
+    else:
+        return unquote(value)
diff --git a/src/main/resources/PythonLibs/encodings/__init__.py b/src/main/resources/PythonLibs/encodings/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..b85ca823aecb5e7f005882d57dc893f84e9ac367
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/__init__.py
@@ -0,0 +1,157 @@
+""" Standard "encodings" Package
+
+    Standard Python encoding modules are stored in this package
+    directory.
+
+    Codec modules must have names corresponding to normalized encoding
+    names as defined in the normalize_encoding() function below, e.g.
+    'utf-8' must be implemented by the module 'utf_8.py'.
+
+    Each codec module must export the following interface:
+
+    * getregentry() -> codecs.CodecInfo object
+    The getregentry() API must a CodecInfo object with encoder, decoder,
+    incrementalencoder, incrementaldecoder, streamwriter and streamreader
+    atttributes which adhere to the Python Codec Interface Standard.
+
+    In addition, a module may optionally also define the following
+    APIs which are then used by the package's codec search function:
+
+    * getaliases() -> sequence of encoding name strings to use as aliases
+
+    Alias names returned by getaliases() must be normalized encoding
+    names as defined by normalize_encoding().
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""#"
+
+import codecs
+from encodings import aliases
+import __builtin__
+
+_cache = {}
+_unknown = '--unknown--'
+_import_tail = ['*']
+_norm_encoding_map = ('                                              . '
+                      '0123456789       ABCDEFGHIJKLMNOPQRSTUVWXYZ     '
+                      ' abcdefghijklmnopqrstuvwxyz                     '
+                      '                                                '
+                      '                                                '
+                      '                ')
+_aliases = aliases.aliases
+
+class CodecRegistryError(LookupError, SystemError):
+    pass
+
+def normalize_encoding(encoding):
+
+    """ Normalize an encoding name.
+
+        Normalization works as follows: all non-alphanumeric
+        characters except the dot used for Python package names are
+        collapsed and replaced with a single underscore, e.g. '  -;#'
+        becomes '_'. Leading and trailing underscores are removed.
+
+        Note that encoding names should be ASCII only; if they do use
+        non-ASCII characters, these must be Latin-1 compatible.
+
+    """
+    # Make sure we have an 8-bit string, because .translate() works
+    # differently for Unicode strings.
+    if hasattr(__builtin__, "unicode") and isinstance(encoding, unicode):
+        # Note that .encode('latin-1') does *not* use the codec
+        # registry, so this call doesn't recurse. (See unicodeobject.c
+        # PyUnicode_AsEncodedString() for details)
+        encoding = encoding.encode('latin-1')
+    return '_'.join(encoding.translate(_norm_encoding_map).split())
+
+def search_function(encoding):
+
+    # Cache lookup
+    entry = _cache.get(encoding, _unknown)
+    if entry is not _unknown:
+        return entry
+
+    # Import the module:
+    #
+    # First try to find an alias for the normalized encoding
+    # name and lookup the module using the aliased name, then try to
+    # lookup the module using the standard import scheme, i.e. first
+    # try in the encodings package, then at top-level.
+    #
+    norm_encoding = normalize_encoding(encoding)
+    aliased_encoding = _aliases.get(norm_encoding) or \
+                       _aliases.get(norm_encoding.replace('.', '_'))
+    if aliased_encoding is not None:
+        modnames = [aliased_encoding,
+                    norm_encoding]
+    else:
+        modnames = [norm_encoding]
+    for modname in modnames:
+        if not modname or '.' in modname:
+            continue
+        try:
+            # Import is absolute to prevent the possibly malicious import of a
+            # module with side-effects that is not in the 'encodings' package.
+            mod = __import__('encodings.' + modname, fromlist=_import_tail,
+                             level=0)
+        except ImportError:
+            pass
+        else:
+            break
+    else:
+        mod = None
+
+    try:
+        getregentry = mod.getregentry
+    except AttributeError:
+        # Not a codec module
+        mod = None
+
+    if mod is None:
+        # Cache misses
+        _cache[encoding] = None
+        return None
+
+    # Now ask the module for the registry entry
+    entry = getregentry()
+    if not isinstance(entry, codecs.CodecInfo):
+        if not 4 <= len(entry) <= 7:
+            raise CodecRegistryError,\
+                 'module "%s" (%s) failed to register' % \
+                  (mod.__name__, mod.__file__)
+        if not hasattr(entry[0], '__call__') or \
+           not hasattr(entry[1], '__call__') or \
+           (entry[2] is not None and not hasattr(entry[2], '__call__')) or \
+           (entry[3] is not None and not hasattr(entry[3], '__call__')) or \
+           (len(entry) > 4 and entry[4] is not None and not hasattr(entry[4], '__call__')) or \
+           (len(entry) > 5 and entry[5] is not None and not hasattr(entry[5], '__call__')):
+            raise CodecRegistryError,\
+                'incompatible codecs in module "%s" (%s)' % \
+                (mod.__name__, mod.__file__)
+        if len(entry)<7 or entry[6] is None:
+            entry += (None,)*(6-len(entry)) + (mod.__name__.split(".", 1)[1],)
+        entry = codecs.CodecInfo(*entry)
+
+    # Cache the codec registry entry
+    _cache[encoding] = entry
+
+    # Register its aliases (without overwriting previously registered
+    # aliases)
+    try:
+        codecaliases = mod.getaliases()
+    except AttributeError:
+        pass
+    else:
+        for alias in codecaliases:
+            if alias not in _aliases:
+                _aliases[alias] = modname
+
+    # Return the registry entry
+    return entry
+
+# Register the search_function in the Python codec registry
+codecs.register(search_function)
diff --git a/src/main/resources/PythonLibs/encodings/aliases.py b/src/main/resources/PythonLibs/encodings/aliases.py
new file mode 100644
index 0000000000000000000000000000000000000000..a54cf774b7b1dd5f6079dc4b6b07320055326404
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/aliases.py
@@ -0,0 +1,527 @@
+""" Encoding Aliases Support
+
+    This module is used by the encodings package search function to
+    map encodings names to module names.
+
+    Note that the search function normalizes the encoding names before
+    doing the lookup, so the mapping will have to map normalized
+    encoding names to module names.
+
+    Contents:
+
+        The following aliases dictionary contains mappings of all IANA
+        character set names for which the Python core library provides
+        codecs. In addition to these, a few Python specific codec
+        aliases have also been added.
+
+"""
+aliases = {
+
+    # Please keep this list sorted alphabetically by value !
+
+    # ascii codec
+    '646'                : 'ascii',
+    'ansi_x3.4_1968'     : 'ascii',
+    'ansi_x3_4_1968'     : 'ascii', # some email headers use this non-standard name
+    'ansi_x3.4_1986'     : 'ascii',
+    'cp367'              : 'ascii',
+    'csascii'            : 'ascii',
+    'ibm367'             : 'ascii',
+    'iso646_us'          : 'ascii',
+    'iso_646.irv_1991'   : 'ascii',
+    'iso_ir_6'           : 'ascii',
+    'us'                 : 'ascii',
+    'us_ascii'           : 'ascii',
+
+    # base64_codec codec
+    'base64'             : 'base64_codec',
+    'base_64'            : 'base64_codec',
+
+    # big5 codec
+    'big5_tw'            : 'big5',
+    'csbig5'             : 'big5',
+
+    # big5hkscs codec
+    'big5_hkscs'         : 'big5hkscs',
+    'hkscs'              : 'big5hkscs',
+
+    # bz2_codec codec
+    'bz2'                : 'bz2_codec',
+
+    # cp037 codec
+    '037'                : 'cp037',
+    'csibm037'           : 'cp037',
+    'ebcdic_cp_ca'       : 'cp037',
+    'ebcdic_cp_nl'       : 'cp037',
+    'ebcdic_cp_us'       : 'cp037',
+    'ebcdic_cp_wt'       : 'cp037',
+    'ibm037'             : 'cp037',
+    'ibm039'             : 'cp037',
+
+    # cp1026 codec
+    '1026'               : 'cp1026',
+    'csibm1026'          : 'cp1026',
+    'ibm1026'            : 'cp1026',
+
+    # cp1140 codec
+    '1140'               : 'cp1140',
+    'ibm1140'            : 'cp1140',
+
+    # cp1250 codec
+    '1250'               : 'cp1250',
+    'windows_1250'       : 'cp1250',
+
+    # cp1251 codec
+    '1251'               : 'cp1251',
+    'windows_1251'       : 'cp1251',
+
+    # cp1252 codec
+    '1252'               : 'cp1252',
+    'windows_1252'       : 'cp1252',
+
+    # cp1253 codec
+    '1253'               : 'cp1253',
+    'windows_1253'       : 'cp1253',
+
+    # cp1254 codec
+    '1254'               : 'cp1254',
+    'windows_1254'       : 'cp1254',
+
+    # cp1255 codec
+    '1255'               : 'cp1255',
+    'windows_1255'       : 'cp1255',
+
+    # cp1256 codec
+    '1256'               : 'cp1256',
+    'windows_1256'       : 'cp1256',
+
+    # cp1257 codec
+    '1257'               : 'cp1257',
+    'windows_1257'       : 'cp1257',
+
+    # cp1258 codec
+    '1258'               : 'cp1258',
+    'windows_1258'       : 'cp1258',
+
+    # cp424 codec
+    '424'                : 'cp424',
+    'csibm424'           : 'cp424',
+    'ebcdic_cp_he'       : 'cp424',
+    'ibm424'             : 'cp424',
+
+    # cp437 codec
+    '437'                : 'cp437',
+    'cspc8codepage437'   : 'cp437',
+    'ibm437'             : 'cp437',
+
+    # cp500 codec
+    '500'                : 'cp500',
+    'csibm500'           : 'cp500',
+    'ebcdic_cp_be'       : 'cp500',
+    'ebcdic_cp_ch'       : 'cp500',
+    'ibm500'             : 'cp500',
+
+    # cp775 codec
+    '775'                : 'cp775',
+    'cspc775baltic'      : 'cp775',
+    'ibm775'             : 'cp775',
+
+    # cp850 codec
+    '850'                : 'cp850',
+    'cspc850multilingual' : 'cp850',
+    'ibm850'             : 'cp850',
+
+    # cp852 codec
+    '852'                : 'cp852',
+    'cspcp852'           : 'cp852',
+    'ibm852'             : 'cp852',
+
+    # cp855 codec
+    '855'                : 'cp855',
+    'csibm855'           : 'cp855',
+    'ibm855'             : 'cp855',
+
+    # cp857 codec
+    '857'                : 'cp857',
+    'csibm857'           : 'cp857',
+    'ibm857'             : 'cp857',
+
+    # cp858 codec
+    '858'                : 'cp858',
+    'csibm858'           : 'cp858',
+    'ibm858'             : 'cp858',
+
+    # cp860 codec
+    '860'                : 'cp860',
+    'csibm860'           : 'cp860',
+    'ibm860'             : 'cp860',
+
+    # cp861 codec
+    '861'                : 'cp861',
+    'cp_is'              : 'cp861',
+    'csibm861'           : 'cp861',
+    'ibm861'             : 'cp861',
+
+    # cp862 codec
+    '862'                : 'cp862',
+    'cspc862latinhebrew' : 'cp862',
+    'ibm862'             : 'cp862',
+
+    # cp863 codec
+    '863'                : 'cp863',
+    'csibm863'           : 'cp863',
+    'ibm863'             : 'cp863',
+
+    # cp864 codec
+    '864'                : 'cp864',
+    'csibm864'           : 'cp864',
+    'ibm864'             : 'cp864',
+
+    # cp865 codec
+    '865'                : 'cp865',
+    'csibm865'           : 'cp865',
+    'ibm865'             : 'cp865',
+
+    # cp866 codec
+    '866'                : 'cp866',
+    'csibm866'           : 'cp866',
+    'ibm866'             : 'cp866',
+
+    # cp869 codec
+    '869'                : 'cp869',
+    'cp_gr'              : 'cp869',
+    'csibm869'           : 'cp869',
+    'ibm869'             : 'cp869',
+
+    # cp932 codec
+    '932'                : 'cp932',
+    'ms932'              : 'cp932',
+    'mskanji'            : 'cp932',
+    'ms_kanji'           : 'cp932',
+
+    # cp949 codec
+    '949'                : 'cp949',
+    'ms949'              : 'cp949',
+    'uhc'                : 'cp949',
+
+    # cp950 codec
+    '950'                : 'cp950',
+    'ms950'              : 'cp950',
+
+    # euc_jis_2004 codec
+    'jisx0213'           : 'euc_jis_2004',
+    'eucjis2004'         : 'euc_jis_2004',
+    'euc_jis2004'        : 'euc_jis_2004',
+
+    # euc_jisx0213 codec
+    'eucjisx0213'        : 'euc_jisx0213',
+
+    # euc_jp codec
+    'eucjp'              : 'euc_jp',
+    'ujis'               : 'euc_jp',
+    'u_jis'              : 'euc_jp',
+
+    # euc_kr codec
+    'euckr'              : 'euc_kr',
+    'korean'             : 'euc_kr',
+    'ksc5601'            : 'euc_kr',
+    'ks_c_5601'          : 'euc_kr',
+    'ks_c_5601_1987'     : 'euc_kr',
+    'ksx1001'            : 'euc_kr',
+    'ks_x_1001'          : 'euc_kr',
+
+    # gb18030 codec
+    'gb18030_2000'       : 'gb18030',
+
+    # gb2312 codec
+    'chinese'            : 'gb2312',
+    'csiso58gb231280'    : 'gb2312',
+    'euc_cn'             : 'gb2312',
+    'euccn'              : 'gb2312',
+    'eucgb2312_cn'       : 'gb2312',
+    'gb2312_1980'        : 'gb2312',
+    'gb2312_80'          : 'gb2312',
+    'iso_ir_58'          : 'gb2312',
+
+    # gbk codec
+    '936'                : 'gbk',
+    'cp936'              : 'gbk',
+    'ms936'              : 'gbk',
+
+    # hex_codec codec
+    'hex'                : 'hex_codec',
+
+    # hp_roman8 codec
+    'roman8'             : 'hp_roman8',
+    'r8'                 : 'hp_roman8',
+    'csHPRoman8'         : 'hp_roman8',
+
+    # hz codec
+    'hzgb'               : 'hz',
+    'hz_gb'              : 'hz',
+    'hz_gb_2312'         : 'hz',
+
+    # iso2022_jp codec
+    'csiso2022jp'        : 'iso2022_jp',
+    'iso2022jp'          : 'iso2022_jp',
+    'iso_2022_jp'        : 'iso2022_jp',
+
+    # iso2022_jp_1 codec
+    'iso2022jp_1'        : 'iso2022_jp_1',
+    'iso_2022_jp_1'      : 'iso2022_jp_1',
+
+    # iso2022_jp_2 codec
+    'iso2022jp_2'        : 'iso2022_jp_2',
+    'iso_2022_jp_2'      : 'iso2022_jp_2',
+
+    # iso2022_jp_2004 codec
+    'iso_2022_jp_2004'   : 'iso2022_jp_2004',
+    'iso2022jp_2004'     : 'iso2022_jp_2004',
+
+    # iso2022_jp_3 codec
+    'iso2022jp_3'        : 'iso2022_jp_3',
+    'iso_2022_jp_3'      : 'iso2022_jp_3',
+
+    # iso2022_jp_ext codec
+    'iso2022jp_ext'      : 'iso2022_jp_ext',
+    'iso_2022_jp_ext'    : 'iso2022_jp_ext',
+
+    # iso2022_kr codec
+    'csiso2022kr'        : 'iso2022_kr',
+    'iso2022kr'          : 'iso2022_kr',
+    'iso_2022_kr'        : 'iso2022_kr',
+
+    # iso8859_10 codec
+    'csisolatin6'        : 'iso8859_10',
+    'iso_8859_10'        : 'iso8859_10',
+    'iso_8859_10_1992'   : 'iso8859_10',
+    'iso_ir_157'         : 'iso8859_10',
+    'l6'                 : 'iso8859_10',
+    'latin6'             : 'iso8859_10',
+
+    # iso8859_11 codec
+    'thai'               : 'iso8859_11',
+    'iso_8859_11'        : 'iso8859_11',
+    'iso_8859_11_2001'   : 'iso8859_11',
+
+    # iso8859_13 codec
+    'iso_8859_13'        : 'iso8859_13',
+    'l7'                 : 'iso8859_13',
+    'latin7'             : 'iso8859_13',
+
+    # iso8859_14 codec
+    'iso_8859_14'        : 'iso8859_14',
+    'iso_8859_14_1998'   : 'iso8859_14',
+    'iso_celtic'         : 'iso8859_14',
+    'iso_ir_199'         : 'iso8859_14',
+    'l8'                 : 'iso8859_14',
+    'latin8'             : 'iso8859_14',
+
+    # iso8859_15 codec
+    'iso_8859_15'        : 'iso8859_15',
+    'l9'                 : 'iso8859_15',
+    'latin9'             : 'iso8859_15',
+
+    # iso8859_16 codec
+    'iso_8859_16'        : 'iso8859_16',
+    'iso_8859_16_2001'   : 'iso8859_16',
+    'iso_ir_226'         : 'iso8859_16',
+    'l10'                : 'iso8859_16',
+    'latin10'            : 'iso8859_16',
+
+    # iso8859_2 codec
+    'csisolatin2'        : 'iso8859_2',
+    'iso_8859_2'         : 'iso8859_2',
+    'iso_8859_2_1987'    : 'iso8859_2',
+    'iso_ir_101'         : 'iso8859_2',
+    'l2'                 : 'iso8859_2',
+    'latin2'             : 'iso8859_2',
+
+    # iso8859_3 codec
+    'csisolatin3'        : 'iso8859_3',
+    'iso_8859_3'         : 'iso8859_3',
+    'iso_8859_3_1988'    : 'iso8859_3',
+    'iso_ir_109'         : 'iso8859_3',
+    'l3'                 : 'iso8859_3',
+    'latin3'             : 'iso8859_3',
+
+    # iso8859_4 codec
+    'csisolatin4'        : 'iso8859_4',
+    'iso_8859_4'         : 'iso8859_4',
+    'iso_8859_4_1988'    : 'iso8859_4',
+    'iso_ir_110'         : 'iso8859_4',
+    'l4'                 : 'iso8859_4',
+    'latin4'             : 'iso8859_4',
+
+    # iso8859_5 codec
+    'csisolatincyrillic' : 'iso8859_5',
+    'cyrillic'           : 'iso8859_5',
+    'iso_8859_5'         : 'iso8859_5',
+    'iso_8859_5_1988'    : 'iso8859_5',
+    'iso_ir_144'         : 'iso8859_5',
+
+    # iso8859_6 codec
+    'arabic'             : 'iso8859_6',
+    'asmo_708'           : 'iso8859_6',
+    'csisolatinarabic'   : 'iso8859_6',
+    'ecma_114'           : 'iso8859_6',
+    'iso_8859_6'         : 'iso8859_6',
+    'iso_8859_6_1987'    : 'iso8859_6',
+    'iso_ir_127'         : 'iso8859_6',
+
+    # iso8859_7 codec
+    'csisolatingreek'    : 'iso8859_7',
+    'ecma_118'           : 'iso8859_7',
+    'elot_928'           : 'iso8859_7',
+    'greek'              : 'iso8859_7',
+    'greek8'             : 'iso8859_7',
+    'iso_8859_7'         : 'iso8859_7',
+    'iso_8859_7_1987'    : 'iso8859_7',
+    'iso_ir_126'         : 'iso8859_7',
+
+    # iso8859_8 codec
+    'csisolatinhebrew'   : 'iso8859_8',
+    'hebrew'             : 'iso8859_8',
+    'iso_8859_8'         : 'iso8859_8',
+    'iso_8859_8_1988'    : 'iso8859_8',
+    'iso_ir_138'         : 'iso8859_8',
+
+    # iso8859_9 codec
+    'csisolatin5'        : 'iso8859_9',
+    'iso_8859_9'         : 'iso8859_9',
+    'iso_8859_9_1989'    : 'iso8859_9',
+    'iso_ir_148'         : 'iso8859_9',
+    'l5'                 : 'iso8859_9',
+    'latin5'             : 'iso8859_9',
+
+    # johab codec
+    'cp1361'             : 'johab',
+    'ms1361'             : 'johab',
+
+    # koi8_r codec
+    'cskoi8r'            : 'koi8_r',
+
+    # latin_1 codec
+    #
+    # Note that the latin_1 codec is implemented internally in C and a
+    # lot faster than the charmap codec iso8859_1 which uses the same
+    # encoding. This is why we discourage the use of the iso8859_1
+    # codec and alias it to latin_1 instead.
+    #
+    '8859'               : 'latin_1',
+    'cp819'              : 'latin_1',
+    'csisolatin1'        : 'latin_1',
+    'ibm819'             : 'latin_1',
+    'iso8859'            : 'latin_1',
+    'iso8859_1'          : 'latin_1',
+    'iso_8859_1'         : 'latin_1',
+    'iso_8859_1_1987'    : 'latin_1',
+    'iso_ir_100'         : 'latin_1',
+    'l1'                 : 'latin_1',
+    'latin'              : 'latin_1',
+    'latin1'             : 'latin_1',
+
+    # mac_cyrillic codec
+    'maccyrillic'        : 'mac_cyrillic',
+
+    # mac_greek codec
+    'macgreek'           : 'mac_greek',
+
+    # mac_iceland codec
+    'maciceland'         : 'mac_iceland',
+
+    # mac_latin2 codec
+    'maccentraleurope'   : 'mac_latin2',
+    'maclatin2'          : 'mac_latin2',
+
+    # mac_roman codec
+    'macroman'           : 'mac_roman',
+
+    # mac_turkish codec
+    'macturkish'         : 'mac_turkish',
+
+    # mbcs codec
+    'dbcs'               : 'mbcs',
+
+    # ptcp154 codec
+    'csptcp154'          : 'ptcp154',
+    'pt154'              : 'ptcp154',
+    'cp154'              : 'ptcp154',
+    'cyrillic_asian'     : 'ptcp154',
+
+    # quopri_codec codec
+    'quopri'             : 'quopri_codec',
+    'quoted_printable'   : 'quopri_codec',
+    'quotedprintable'    : 'quopri_codec',
+
+    # rot_13 codec
+    'rot13'              : 'rot_13',
+
+    # shift_jis codec
+    'csshiftjis'         : 'shift_jis',
+    'shiftjis'           : 'shift_jis',
+    'sjis'               : 'shift_jis',
+    's_jis'              : 'shift_jis',
+
+    # shift_jis_2004 codec
+    'shiftjis2004'       : 'shift_jis_2004',
+    'sjis_2004'          : 'shift_jis_2004',
+    's_jis_2004'         : 'shift_jis_2004',
+
+    # shift_jisx0213 codec
+    'shiftjisx0213'      : 'shift_jisx0213',
+    'sjisx0213'          : 'shift_jisx0213',
+    's_jisx0213'         : 'shift_jisx0213',
+
+    # tactis codec
+    'tis260'             : 'tactis',
+
+    # tis_620 codec
+    'tis620'             : 'tis_620',
+    'tis_620_0'          : 'tis_620',
+    'tis_620_2529_0'     : 'tis_620',
+    'tis_620_2529_1'     : 'tis_620',
+    'iso_ir_166'         : 'tis_620',
+
+    # utf_16 codec
+    'u16'                : 'utf_16',
+    'utf16'              : 'utf_16',
+
+    # utf_16_be codec
+    'unicodebigunmarked' : 'utf_16_be',
+    'utf_16be'           : 'utf_16_be',
+
+    # utf_16_le codec
+    'unicodelittleunmarked' : 'utf_16_le',
+    'utf_16le'           : 'utf_16_le',
+
+    # utf_32 codec
+    'u32'                : 'utf_32',
+    'utf32'              : 'utf_32',
+
+    # utf_32_be codec
+    'utf_32be'           : 'utf_32_be',
+
+    # utf_32_le codec
+    'utf_32le'           : 'utf_32_le',
+
+    # utf_7 codec
+    'u7'                 : 'utf_7',
+    'utf7'               : 'utf_7',
+    'unicode_1_1_utf_7'  : 'utf_7',
+
+    # utf_8 codec
+    'u8'                 : 'utf_8',
+    'utf'                : 'utf_8',
+    'utf8'               : 'utf_8',
+    'utf8_ucs2'          : 'utf_8',
+    'utf8_ucs4'          : 'utf_8',
+
+    # uu_codec codec
+    'uu'                 : 'uu_codec',
+
+    # zlib_codec codec
+    'zip'                : 'zlib_codec',
+    'zlib'               : 'zlib_codec',
+
+}
diff --git a/src/main/resources/PythonLibs/encodings/ascii.py b/src/main/resources/PythonLibs/encodings/ascii.py
new file mode 100644
index 0000000000000000000000000000000000000000..2033cde97484a9ba86f9008dabd15ac846c663ee
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/ascii.py
@@ -0,0 +1,50 @@
+""" Python 'ascii' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    # Note: Binding these as C functions will result in the class not
+    # converting them to methods. This is intended.
+    encode = codecs.ascii_encode
+    decode = codecs.ascii_decode
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.ascii_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.ascii_decode(input, self.errors)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+class StreamConverter(StreamWriter,StreamReader):
+
+    encode = codecs.ascii_decode
+    decode = codecs.ascii_encode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='ascii',
+        encode=Codec.encode,
+        decode=Codec.decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/base64_codec.py b/src/main/resources/PythonLibs/encodings/base64_codec.py
new file mode 100644
index 0000000000000000000000000000000000000000..f84e7808e99433f8666b986d5abb35d446047065
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/base64_codec.py
@@ -0,0 +1,79 @@
+""" Python 'base64_codec' Codec - base64 content transfer encoding
+
+    Unlike most of the other codecs which target Unicode, this codec
+    will return Python string objects for both encode and decode.
+
+    Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+"""
+import codecs, base64
+
+### Codec APIs
+
+def base64_encode(input,errors='strict'):
+
+    """ Encodes the object input and returns a tuple (output
+        object, length consumed).
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    output = base64.encodestring(input)
+    return (output, len(input))
+
+def base64_decode(input,errors='strict'):
+
+    """ Decodes the object input and returns a tuple (output
+        object, length consumed).
+
+        input must be an object which provides the bf_getreadbuf
+        buffer slot. Python strings, buffer objects and memory
+        mapped files are examples of objects providing this slot.
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    output = base64.decodestring(input)
+    return (output, len(input))
+
+class Codec(codecs.Codec):
+
+    def encode(self, input,errors='strict'):
+        return base64_encode(input,errors)
+    def decode(self, input,errors='strict'):
+        return base64_decode(input,errors)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        assert self.errors == 'strict'
+        return base64.encodestring(input)
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        assert self.errors == 'strict'
+        return base64.decodestring(input)
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='base64',
+        encode=base64_encode,
+        decode=base64_decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/big5.py b/src/main/resources/PythonLibs/encodings/big5.py
new file mode 100644
index 0000000000000000000000000000000000000000..7adeb0e1605274414014ee7849c36b203f7589f7
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/big5.py
@@ -0,0 +1,39 @@
+#
+# big5.py: Python Unicode Codec for BIG5
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_tw, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_tw.getcodec('big5')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='big5',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/big5hkscs.py b/src/main/resources/PythonLibs/encodings/big5hkscs.py
new file mode 100644
index 0000000000000000000000000000000000000000..350df37baaedafcd75120723bf8e9b85a7e2a4b8
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/big5hkscs.py
@@ -0,0 +1,39 @@
+#
+# big5hkscs.py: Python Unicode Codec for BIG5HKSCS
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_hk, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_hk.getcodec('big5hkscs')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='big5hkscs',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/bz2_codec.py b/src/main/resources/PythonLibs/encodings/bz2_codec.py
new file mode 100644
index 0000000000000000000000000000000000000000..054b36b401a66e54ba39c6a96485a9d0f19c9713
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/bz2_codec.py
@@ -0,0 +1,102 @@
+""" Python 'bz2_codec' Codec - bz2 compression encoding
+
+    Unlike most of the other codecs which target Unicode, this codec
+    will return Python string objects for both encode and decode.
+
+    Adapted by Raymond Hettinger from zlib_codec.py which was written
+    by Marc-Andre Lemburg (mal@lemburg.com).
+
+"""
+import codecs
+import bz2 # this codec needs the optional bz2 module !
+
+### Codec APIs
+
+def bz2_encode(input,errors='strict'):
+
+    """ Encodes the object input and returns a tuple (output
+        object, length consumed).
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    output = bz2.compress(input)
+    return (output, len(input))
+
+def bz2_decode(input,errors='strict'):
+
+    """ Decodes the object input and returns a tuple (output
+        object, length consumed).
+
+        input must be an object which provides the bf_getreadbuf
+        buffer slot. Python strings, buffer objects and memory
+        mapped files are examples of objects providing this slot.
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    output = bz2.decompress(input)
+    return (output, len(input))
+
+class Codec(codecs.Codec):
+
+    def encode(self, input, errors='strict'):
+        return bz2_encode(input, errors)
+    def decode(self, input, errors='strict'):
+        return bz2_decode(input, errors)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def __init__(self, errors='strict'):
+        assert errors == 'strict'
+        self.errors = errors
+        self.compressobj = bz2.BZ2Compressor()
+
+    def encode(self, input, final=False):
+        if final:
+            c = self.compressobj.compress(input)
+            return c + self.compressobj.flush()
+        else:
+            return self.compressobj.compress(input)
+
+    def reset(self):
+        self.compressobj = bz2.BZ2Compressor()
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def __init__(self, errors='strict'):
+        assert errors == 'strict'
+        self.errors = errors
+        self.decompressobj = bz2.BZ2Decompressor()
+
+    def decode(self, input, final=False):
+        try:
+            return self.decompressobj.decompress(input)
+        except EOFError:
+            return ''
+
+    def reset(self):
+        self.decompressobj = bz2.BZ2Decompressor()
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name="bz2",
+        encode=bz2_encode,
+        decode=bz2_decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/charmap.py b/src/main/resources/PythonLibs/encodings/charmap.py
new file mode 100644
index 0000000000000000000000000000000000000000..81189b161a64ad2edbe9172597d848e64b28b28c
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/charmap.py
@@ -0,0 +1,69 @@
+""" Generic Python Character Mapping Codec.
+
+    Use this codec directly rather than through the automatic
+    conversion mechanisms supplied by unicode() and .encode().
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    # Note: Binding these as C functions will result in the class not
+    # converting them to methods. This is intended.
+    encode = codecs.charmap_encode
+    decode = codecs.charmap_decode
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def __init__(self, errors='strict', mapping=None):
+        codecs.IncrementalEncoder.__init__(self, errors)
+        self.mapping = mapping
+
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input, self.errors, self.mapping)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def __init__(self, errors='strict', mapping=None):
+        codecs.IncrementalDecoder.__init__(self, errors)
+        self.mapping = mapping
+
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input, self.errors, self.mapping)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+
+    def __init__(self,stream,errors='strict',mapping=None):
+        codecs.StreamWriter.__init__(self,stream,errors)
+        self.mapping = mapping
+
+    def encode(self,input,errors='strict'):
+        return Codec.encode(input,errors,self.mapping)
+
+class StreamReader(Codec,codecs.StreamReader):
+
+    def __init__(self,stream,errors='strict',mapping=None):
+        codecs.StreamReader.__init__(self,stream,errors)
+        self.mapping = mapping
+
+    def decode(self,input,errors='strict'):
+        return Codec.decode(input,errors,self.mapping)
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='charmap',
+        encode=Codec.encode,
+        decode=Codec.decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/cp037.py b/src/main/resources/PythonLibs/encodings/cp037.py
new file mode 100644
index 0000000000000000000000000000000000000000..c802b899af2eed0d366bb79f6f371c92de3bcebf
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp037.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp037 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP037.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp037',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x9c'     #  0x04 -> CONTROL
+    u'\t'       #  0x05 -> HORIZONTAL TABULATION
+    u'\x86'     #  0x06 -> CONTROL
+    u'\x7f'     #  0x07 -> DELETE
+    u'\x97'     #  0x08 -> CONTROL
+    u'\x8d'     #  0x09 -> CONTROL
+    u'\x8e'     #  0x0A -> CONTROL
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x9d'     #  0x14 -> CONTROL
+    u'\x85'     #  0x15 -> CONTROL
+    u'\x08'     #  0x16 -> BACKSPACE
+    u'\x87'     #  0x17 -> CONTROL
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x92'     #  0x1A -> CONTROL
+    u'\x8f'     #  0x1B -> CONTROL
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u'\x80'     #  0x20 -> CONTROL
+    u'\x81'     #  0x21 -> CONTROL
+    u'\x82'     #  0x22 -> CONTROL
+    u'\x83'     #  0x23 -> CONTROL
+    u'\x84'     #  0x24 -> CONTROL
+    u'\n'       #  0x25 -> LINE FEED
+    u'\x17'     #  0x26 -> END OF TRANSMISSION BLOCK
+    u'\x1b'     #  0x27 -> ESCAPE
+    u'\x88'     #  0x28 -> CONTROL
+    u'\x89'     #  0x29 -> CONTROL
+    u'\x8a'     #  0x2A -> CONTROL
+    u'\x8b'     #  0x2B -> CONTROL
+    u'\x8c'     #  0x2C -> CONTROL
+    u'\x05'     #  0x2D -> ENQUIRY
+    u'\x06'     #  0x2E -> ACKNOWLEDGE
+    u'\x07'     #  0x2F -> BELL
+    u'\x90'     #  0x30 -> CONTROL
+    u'\x91'     #  0x31 -> CONTROL
+    u'\x16'     #  0x32 -> SYNCHRONOUS IDLE
+    u'\x93'     #  0x33 -> CONTROL
+    u'\x94'     #  0x34 -> CONTROL
+    u'\x95'     #  0x35 -> CONTROL
+    u'\x96'     #  0x36 -> CONTROL
+    u'\x04'     #  0x37 -> END OF TRANSMISSION
+    u'\x98'     #  0x38 -> CONTROL
+    u'\x99'     #  0x39 -> CONTROL
+    u'\x9a'     #  0x3A -> CONTROL
+    u'\x9b'     #  0x3B -> CONTROL
+    u'\x14'     #  0x3C -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x3D -> NEGATIVE ACKNOWLEDGE
+    u'\x9e'     #  0x3E -> CONTROL
+    u'\x1a'     #  0x3F -> SUBSTITUTE
+    u' '        #  0x40 -> SPACE
+    u'\xa0'     #  0x41 -> NO-BREAK SPACE
+    u'\xe2'     #  0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x43 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x44 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0x45 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe3'     #  0x46 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x47 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x48 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xf1'     #  0x49 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xa2'     #  0x4A -> CENT SIGN
+    u'.'        #  0x4B -> FULL STOP
+    u'<'        #  0x4C -> LESS-THAN SIGN
+    u'('        #  0x4D -> LEFT PARENTHESIS
+    u'+'        #  0x4E -> PLUS SIGN
+    u'|'        #  0x4F -> VERTICAL LINE
+    u'&'        #  0x50 -> AMPERSAND
+    u'\xe9'     #  0x51 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x53 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x54 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xed'     #  0x55 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x57 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xec'     #  0x58 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xdf'     #  0x59 -> LATIN SMALL LETTER SHARP S (GERMAN)
+    u'!'        #  0x5A -> EXCLAMATION MARK
+    u'$'        #  0x5B -> DOLLAR SIGN
+    u'*'        #  0x5C -> ASTERISK
+    u')'        #  0x5D -> RIGHT PARENTHESIS
+    u';'        #  0x5E -> SEMICOLON
+    u'\xac'     #  0x5F -> NOT SIGN
+    u'-'        #  0x60 -> HYPHEN-MINUS
+    u'/'        #  0x61 -> SOLIDUS
+    u'\xc2'     #  0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc4'     #  0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc0'     #  0x64 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0x65 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc3'     #  0x66 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc5'     #  0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc7'     #  0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xd1'     #  0x69 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xa6'     #  0x6A -> BROKEN BAR
+    u','        #  0x6B -> COMMA
+    u'%'        #  0x6C -> PERCENT SIGN
+    u'_'        #  0x6D -> LOW LINE
+    u'>'        #  0x6E -> GREATER-THAN SIGN
+    u'?'        #  0x6F -> QUESTION MARK
+    u'\xf8'     #  0x70 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xc9'     #  0x71 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0x74 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0x75 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0x78 -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'`'        #  0x79 -> GRAVE ACCENT
+    u':'        #  0x7A -> COLON
+    u'#'        #  0x7B -> NUMBER SIGN
+    u'@'        #  0x7C -> COMMERCIAL AT
+    u"'"        #  0x7D -> APOSTROPHE
+    u'='        #  0x7E -> EQUALS SIGN
+    u'"'        #  0x7F -> QUOTATION MARK
+    u'\xd8'     #  0x80 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'a'        #  0x81 -> LATIN SMALL LETTER A
+    u'b'        #  0x82 -> LATIN SMALL LETTER B
+    u'c'        #  0x83 -> LATIN SMALL LETTER C
+    u'd'        #  0x84 -> LATIN SMALL LETTER D
+    u'e'        #  0x85 -> LATIN SMALL LETTER E
+    u'f'        #  0x86 -> LATIN SMALL LETTER F
+    u'g'        #  0x87 -> LATIN SMALL LETTER G
+    u'h'        #  0x88 -> LATIN SMALL LETTER H
+    u'i'        #  0x89 -> LATIN SMALL LETTER I
+    u'\xab'     #  0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xf0'     #  0x8C -> LATIN SMALL LETTER ETH (ICELANDIC)
+    u'\xfd'     #  0x8D -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xfe'     #  0x8E -> LATIN SMALL LETTER THORN (ICELANDIC)
+    u'\xb1'     #  0x8F -> PLUS-MINUS SIGN
+    u'\xb0'     #  0x90 -> DEGREE SIGN
+    u'j'        #  0x91 -> LATIN SMALL LETTER J
+    u'k'        #  0x92 -> LATIN SMALL LETTER K
+    u'l'        #  0x93 -> LATIN SMALL LETTER L
+    u'm'        #  0x94 -> LATIN SMALL LETTER M
+    u'n'        #  0x95 -> LATIN SMALL LETTER N
+    u'o'        #  0x96 -> LATIN SMALL LETTER O
+    u'p'        #  0x97 -> LATIN SMALL LETTER P
+    u'q'        #  0x98 -> LATIN SMALL LETTER Q
+    u'r'        #  0x99 -> LATIN SMALL LETTER R
+    u'\xaa'     #  0x9A -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x9B -> MASCULINE ORDINAL INDICATOR
+    u'\xe6'     #  0x9C -> LATIN SMALL LIGATURE AE
+    u'\xb8'     #  0x9D -> CEDILLA
+    u'\xc6'     #  0x9E -> LATIN CAPITAL LIGATURE AE
+    u'\xa4'     #  0x9F -> CURRENCY SIGN
+    u'\xb5'     #  0xA0 -> MICRO SIGN
+    u'~'        #  0xA1 -> TILDE
+    u's'        #  0xA2 -> LATIN SMALL LETTER S
+    u't'        #  0xA3 -> LATIN SMALL LETTER T
+    u'u'        #  0xA4 -> LATIN SMALL LETTER U
+    u'v'        #  0xA5 -> LATIN SMALL LETTER V
+    u'w'        #  0xA6 -> LATIN SMALL LETTER W
+    u'x'        #  0xA7 -> LATIN SMALL LETTER X
+    u'y'        #  0xA8 -> LATIN SMALL LETTER Y
+    u'z'        #  0xA9 -> LATIN SMALL LETTER Z
+    u'\xa1'     #  0xAA -> INVERTED EXCLAMATION MARK
+    u'\xbf'     #  0xAB -> INVERTED QUESTION MARK
+    u'\xd0'     #  0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC)
+    u'\xdd'     #  0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xde'     #  0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC)
+    u'\xae'     #  0xAF -> REGISTERED SIGN
+    u'^'        #  0xB0 -> CIRCUMFLEX ACCENT
+    u'\xa3'     #  0xB1 -> POUND SIGN
+    u'\xa5'     #  0xB2 -> YEN SIGN
+    u'\xb7'     #  0xB3 -> MIDDLE DOT
+    u'\xa9'     #  0xB4 -> COPYRIGHT SIGN
+    u'\xa7'     #  0xB5 -> SECTION SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xbc'     #  0xB7 -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xB8 -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xB9 -> VULGAR FRACTION THREE QUARTERS
+    u'['        #  0xBA -> LEFT SQUARE BRACKET
+    u']'        #  0xBB -> RIGHT SQUARE BRACKET
+    u'\xaf'     #  0xBC -> MACRON
+    u'\xa8'     #  0xBD -> DIAERESIS
+    u'\xb4'     #  0xBE -> ACUTE ACCENT
+    u'\xd7'     #  0xBF -> MULTIPLICATION SIGN
+    u'{'        #  0xC0 -> LEFT CURLY BRACKET
+    u'A'        #  0xC1 -> LATIN CAPITAL LETTER A
+    u'B'        #  0xC2 -> LATIN CAPITAL LETTER B
+    u'C'        #  0xC3 -> LATIN CAPITAL LETTER C
+    u'D'        #  0xC4 -> LATIN CAPITAL LETTER D
+    u'E'        #  0xC5 -> LATIN CAPITAL LETTER E
+    u'F'        #  0xC6 -> LATIN CAPITAL LETTER F
+    u'G'        #  0xC7 -> LATIN CAPITAL LETTER G
+    u'H'        #  0xC8 -> LATIN CAPITAL LETTER H
+    u'I'        #  0xC9 -> LATIN CAPITAL LETTER I
+    u'\xad'     #  0xCA -> SOFT HYPHEN
+    u'\xf4'     #  0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0xCC -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf2'     #  0xCD -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xCE -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf5'     #  0xCF -> LATIN SMALL LETTER O WITH TILDE
+    u'}'        #  0xD0 -> RIGHT CURLY BRACKET
+    u'J'        #  0xD1 -> LATIN CAPITAL LETTER J
+    u'K'        #  0xD2 -> LATIN CAPITAL LETTER K
+    u'L'        #  0xD3 -> LATIN CAPITAL LETTER L
+    u'M'        #  0xD4 -> LATIN CAPITAL LETTER M
+    u'N'        #  0xD5 -> LATIN CAPITAL LETTER N
+    u'O'        #  0xD6 -> LATIN CAPITAL LETTER O
+    u'P'        #  0xD7 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0xD8 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0xD9 -> LATIN CAPITAL LETTER R
+    u'\xb9'     #  0xDA -> SUPERSCRIPT ONE
+    u'\xfb'     #  0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xDC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xf9'     #  0xDD -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xDE -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xff'     #  0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\\'       #  0xE0 -> REVERSE SOLIDUS
+    u'\xf7'     #  0xE1 -> DIVISION SIGN
+    u'S'        #  0xE2 -> LATIN CAPITAL LETTER S
+    u'T'        #  0xE3 -> LATIN CAPITAL LETTER T
+    u'U'        #  0xE4 -> LATIN CAPITAL LETTER U
+    u'V'        #  0xE5 -> LATIN CAPITAL LETTER V
+    u'W'        #  0xE6 -> LATIN CAPITAL LETTER W
+    u'X'        #  0xE7 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0xE8 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0xE9 -> LATIN CAPITAL LETTER Z
+    u'\xb2'     #  0xEA -> SUPERSCRIPT TWO
+    u'\xd4'     #  0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd6'     #  0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd2'     #  0xED -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd5'     #  0xEF -> LATIN CAPITAL LETTER O WITH TILDE
+    u'0'        #  0xF0 -> DIGIT ZERO
+    u'1'        #  0xF1 -> DIGIT ONE
+    u'2'        #  0xF2 -> DIGIT TWO
+    u'3'        #  0xF3 -> DIGIT THREE
+    u'4'        #  0xF4 -> DIGIT FOUR
+    u'5'        #  0xF5 -> DIGIT FIVE
+    u'6'        #  0xF6 -> DIGIT SIX
+    u'7'        #  0xF7 -> DIGIT SEVEN
+    u'8'        #  0xF8 -> DIGIT EIGHT
+    u'9'        #  0xF9 -> DIGIT NINE
+    u'\xb3'     #  0xFA -> SUPERSCRIPT THREE
+    u'\xdb'     #  0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xd9'     #  0xFD -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xFE -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\x9f'     #  0xFF -> CONTROL
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1006.py b/src/main/resources/PythonLibs/encodings/cp1006.py
new file mode 100644
index 0000000000000000000000000000000000000000..e21e804eb9b6e03f4c637036eb1167530e9cce34
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1006.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1006 generated from 'MAPPINGS/VENDORS/MISC/CP1006.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1006',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u06f0'   #  0xA1 -> EXTENDED ARABIC-INDIC DIGIT ZERO
+    u'\u06f1'   #  0xA2 -> EXTENDED ARABIC-INDIC DIGIT ONE
+    u'\u06f2'   #  0xA3 -> EXTENDED ARABIC-INDIC DIGIT TWO
+    u'\u06f3'   #  0xA4 -> EXTENDED ARABIC-INDIC DIGIT THREE
+    u'\u06f4'   #  0xA5 -> EXTENDED ARABIC-INDIC DIGIT FOUR
+    u'\u06f5'   #  0xA6 -> EXTENDED ARABIC-INDIC DIGIT FIVE
+    u'\u06f6'   #  0xA7 -> EXTENDED ARABIC-INDIC DIGIT SIX
+    u'\u06f7'   #  0xA8 -> EXTENDED ARABIC-INDIC DIGIT SEVEN
+    u'\u06f8'   #  0xA9 -> EXTENDED ARABIC-INDIC DIGIT EIGHT
+    u'\u06f9'   #  0xAA -> EXTENDED ARABIC-INDIC DIGIT NINE
+    u'\u060c'   #  0xAB -> ARABIC COMMA
+    u'\u061b'   #  0xAC -> ARABIC SEMICOLON
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\u061f'   #  0xAE -> ARABIC QUESTION MARK
+    u'\ufe81'   #  0xAF -> ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+    u'\ufe8d'   #  0xB0 -> ARABIC LETTER ALEF ISOLATED FORM
+    u'\ufe8e'   #  0xB1 -> ARABIC LETTER ALEF FINAL FORM
+    u'\ufe8e'   #  0xB2 -> ARABIC LETTER ALEF FINAL FORM
+    u'\ufe8f'   #  0xB3 -> ARABIC LETTER BEH ISOLATED FORM
+    u'\ufe91'   #  0xB4 -> ARABIC LETTER BEH INITIAL FORM
+    u'\ufb56'   #  0xB5 -> ARABIC LETTER PEH ISOLATED FORM
+    u'\ufb58'   #  0xB6 -> ARABIC LETTER PEH INITIAL FORM
+    u'\ufe93'   #  0xB7 -> ARABIC LETTER TEH MARBUTA ISOLATED FORM
+    u'\ufe95'   #  0xB8 -> ARABIC LETTER TEH ISOLATED FORM
+    u'\ufe97'   #  0xB9 -> ARABIC LETTER TEH INITIAL FORM
+    u'\ufb66'   #  0xBA -> ARABIC LETTER TTEH ISOLATED FORM
+    u'\ufb68'   #  0xBB -> ARABIC LETTER TTEH INITIAL FORM
+    u'\ufe99'   #  0xBC -> ARABIC LETTER THEH ISOLATED FORM
+    u'\ufe9b'   #  0xBD -> ARABIC LETTER THEH INITIAL FORM
+    u'\ufe9d'   #  0xBE -> ARABIC LETTER JEEM ISOLATED FORM
+    u'\ufe9f'   #  0xBF -> ARABIC LETTER JEEM INITIAL FORM
+    u'\ufb7a'   #  0xC0 -> ARABIC LETTER TCHEH ISOLATED FORM
+    u'\ufb7c'   #  0xC1 -> ARABIC LETTER TCHEH INITIAL FORM
+    u'\ufea1'   #  0xC2 -> ARABIC LETTER HAH ISOLATED FORM
+    u'\ufea3'   #  0xC3 -> ARABIC LETTER HAH INITIAL FORM
+    u'\ufea5'   #  0xC4 -> ARABIC LETTER KHAH ISOLATED FORM
+    u'\ufea7'   #  0xC5 -> ARABIC LETTER KHAH INITIAL FORM
+    u'\ufea9'   #  0xC6 -> ARABIC LETTER DAL ISOLATED FORM
+    u'\ufb84'   #  0xC7 -> ARABIC LETTER DAHAL ISOLATED FORMN
+    u'\ufeab'   #  0xC8 -> ARABIC LETTER THAL ISOLATED FORM
+    u'\ufead'   #  0xC9 -> ARABIC LETTER REH ISOLATED FORM
+    u'\ufb8c'   #  0xCA -> ARABIC LETTER RREH ISOLATED FORM
+    u'\ufeaf'   #  0xCB -> ARABIC LETTER ZAIN ISOLATED FORM
+    u'\ufb8a'   #  0xCC -> ARABIC LETTER JEH ISOLATED FORM
+    u'\ufeb1'   #  0xCD -> ARABIC LETTER SEEN ISOLATED FORM
+    u'\ufeb3'   #  0xCE -> ARABIC LETTER SEEN INITIAL FORM
+    u'\ufeb5'   #  0xCF -> ARABIC LETTER SHEEN ISOLATED FORM
+    u'\ufeb7'   #  0xD0 -> ARABIC LETTER SHEEN INITIAL FORM
+    u'\ufeb9'   #  0xD1 -> ARABIC LETTER SAD ISOLATED FORM
+    u'\ufebb'   #  0xD2 -> ARABIC LETTER SAD INITIAL FORM
+    u'\ufebd'   #  0xD3 -> ARABIC LETTER DAD ISOLATED FORM
+    u'\ufebf'   #  0xD4 -> ARABIC LETTER DAD INITIAL FORM
+    u'\ufec1'   #  0xD5 -> ARABIC LETTER TAH ISOLATED FORM
+    u'\ufec5'   #  0xD6 -> ARABIC LETTER ZAH ISOLATED FORM
+    u'\ufec9'   #  0xD7 -> ARABIC LETTER AIN ISOLATED FORM
+    u'\ufeca'   #  0xD8 -> ARABIC LETTER AIN FINAL FORM
+    u'\ufecb'   #  0xD9 -> ARABIC LETTER AIN INITIAL FORM
+    u'\ufecc'   #  0xDA -> ARABIC LETTER AIN MEDIAL FORM
+    u'\ufecd'   #  0xDB -> ARABIC LETTER GHAIN ISOLATED FORM
+    u'\ufece'   #  0xDC -> ARABIC LETTER GHAIN FINAL FORM
+    u'\ufecf'   #  0xDD -> ARABIC LETTER GHAIN INITIAL FORM
+    u'\ufed0'   #  0xDE -> ARABIC LETTER GHAIN MEDIAL FORM
+    u'\ufed1'   #  0xDF -> ARABIC LETTER FEH ISOLATED FORM
+    u'\ufed3'   #  0xE0 -> ARABIC LETTER FEH INITIAL FORM
+    u'\ufed5'   #  0xE1 -> ARABIC LETTER QAF ISOLATED FORM
+    u'\ufed7'   #  0xE2 -> ARABIC LETTER QAF INITIAL FORM
+    u'\ufed9'   #  0xE3 -> ARABIC LETTER KAF ISOLATED FORM
+    u'\ufedb'   #  0xE4 -> ARABIC LETTER KAF INITIAL FORM
+    u'\ufb92'   #  0xE5 -> ARABIC LETTER GAF ISOLATED FORM
+    u'\ufb94'   #  0xE6 -> ARABIC LETTER GAF INITIAL FORM
+    u'\ufedd'   #  0xE7 -> ARABIC LETTER LAM ISOLATED FORM
+    u'\ufedf'   #  0xE8 -> ARABIC LETTER LAM INITIAL FORM
+    u'\ufee0'   #  0xE9 -> ARABIC LETTER LAM MEDIAL FORM
+    u'\ufee1'   #  0xEA -> ARABIC LETTER MEEM ISOLATED FORM
+    u'\ufee3'   #  0xEB -> ARABIC LETTER MEEM INITIAL FORM
+    u'\ufb9e'   #  0xEC -> ARABIC LETTER NOON GHUNNA ISOLATED FORM
+    u'\ufee5'   #  0xED -> ARABIC LETTER NOON ISOLATED FORM
+    u'\ufee7'   #  0xEE -> ARABIC LETTER NOON INITIAL FORM
+    u'\ufe85'   #  0xEF -> ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+    u'\ufeed'   #  0xF0 -> ARABIC LETTER WAW ISOLATED FORM
+    u'\ufba6'   #  0xF1 -> ARABIC LETTER HEH GOAL ISOLATED FORM
+    u'\ufba8'   #  0xF2 -> ARABIC LETTER HEH GOAL INITIAL FORM
+    u'\ufba9'   #  0xF3 -> ARABIC LETTER HEH GOAL MEDIAL FORM
+    u'\ufbaa'   #  0xF4 -> ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM
+    u'\ufe80'   #  0xF5 -> ARABIC LETTER HAMZA ISOLATED FORM
+    u'\ufe89'   #  0xF6 -> ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM
+    u'\ufe8a'   #  0xF7 -> ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM
+    u'\ufe8b'   #  0xF8 -> ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+    u'\ufef1'   #  0xF9 -> ARABIC LETTER YEH ISOLATED FORM
+    u'\ufef2'   #  0xFA -> ARABIC LETTER YEH FINAL FORM
+    u'\ufef3'   #  0xFB -> ARABIC LETTER YEH INITIAL FORM
+    u'\ufbb0'   #  0xFC -> ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM
+    u'\ufbae'   #  0xFD -> ARABIC LETTER YEH BARREE ISOLATED FORM
+    u'\ufe7c'   #  0xFE -> ARABIC SHADDA ISOLATED FORM
+    u'\ufe7d'   #  0xFF -> ARABIC SHADDA MEDIAL FORM
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1026.py b/src/main/resources/PythonLibs/encodings/cp1026.py
new file mode 100644
index 0000000000000000000000000000000000000000..45bbe626fdf78f9d3d6fe6fc12dd25dcf4acb3d4
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1026.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1026 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP1026.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1026',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x9c'     #  0x04 -> CONTROL
+    u'\t'       #  0x05 -> HORIZONTAL TABULATION
+    u'\x86'     #  0x06 -> CONTROL
+    u'\x7f'     #  0x07 -> DELETE
+    u'\x97'     #  0x08 -> CONTROL
+    u'\x8d'     #  0x09 -> CONTROL
+    u'\x8e'     #  0x0A -> CONTROL
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x9d'     #  0x14 -> CONTROL
+    u'\x85'     #  0x15 -> CONTROL
+    u'\x08'     #  0x16 -> BACKSPACE
+    u'\x87'     #  0x17 -> CONTROL
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x92'     #  0x1A -> CONTROL
+    u'\x8f'     #  0x1B -> CONTROL
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u'\x80'     #  0x20 -> CONTROL
+    u'\x81'     #  0x21 -> CONTROL
+    u'\x82'     #  0x22 -> CONTROL
+    u'\x83'     #  0x23 -> CONTROL
+    u'\x84'     #  0x24 -> CONTROL
+    u'\n'       #  0x25 -> LINE FEED
+    u'\x17'     #  0x26 -> END OF TRANSMISSION BLOCK
+    u'\x1b'     #  0x27 -> ESCAPE
+    u'\x88'     #  0x28 -> CONTROL
+    u'\x89'     #  0x29 -> CONTROL
+    u'\x8a'     #  0x2A -> CONTROL
+    u'\x8b'     #  0x2B -> CONTROL
+    u'\x8c'     #  0x2C -> CONTROL
+    u'\x05'     #  0x2D -> ENQUIRY
+    u'\x06'     #  0x2E -> ACKNOWLEDGE
+    u'\x07'     #  0x2F -> BELL
+    u'\x90'     #  0x30 -> CONTROL
+    u'\x91'     #  0x31 -> CONTROL
+    u'\x16'     #  0x32 -> SYNCHRONOUS IDLE
+    u'\x93'     #  0x33 -> CONTROL
+    u'\x94'     #  0x34 -> CONTROL
+    u'\x95'     #  0x35 -> CONTROL
+    u'\x96'     #  0x36 -> CONTROL
+    u'\x04'     #  0x37 -> END OF TRANSMISSION
+    u'\x98'     #  0x38 -> CONTROL
+    u'\x99'     #  0x39 -> CONTROL
+    u'\x9a'     #  0x3A -> CONTROL
+    u'\x9b'     #  0x3B -> CONTROL
+    u'\x14'     #  0x3C -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x3D -> NEGATIVE ACKNOWLEDGE
+    u'\x9e'     #  0x3E -> CONTROL
+    u'\x1a'     #  0x3F -> SUBSTITUTE
+    u' '        #  0x40 -> SPACE
+    u'\xa0'     #  0x41 -> NO-BREAK SPACE
+    u'\xe2'     #  0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x43 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x44 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0x45 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe3'     #  0x46 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x47 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'{'        #  0x48 -> LEFT CURLY BRACKET
+    u'\xf1'     #  0x49 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xc7'     #  0x4A -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'.'        #  0x4B -> FULL STOP
+    u'<'        #  0x4C -> LESS-THAN SIGN
+    u'('        #  0x4D -> LEFT PARENTHESIS
+    u'+'        #  0x4E -> PLUS SIGN
+    u'!'        #  0x4F -> EXCLAMATION MARK
+    u'&'        #  0x50 -> AMPERSAND
+    u'\xe9'     #  0x51 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x53 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x54 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xed'     #  0x55 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x57 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xec'     #  0x58 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xdf'     #  0x59 -> LATIN SMALL LETTER SHARP S (GERMAN)
+    u'\u011e'   #  0x5A -> LATIN CAPITAL LETTER G WITH BREVE
+    u'\u0130'   #  0x5B -> LATIN CAPITAL LETTER I WITH DOT ABOVE
+    u'*'        #  0x5C -> ASTERISK
+    u')'        #  0x5D -> RIGHT PARENTHESIS
+    u';'        #  0x5E -> SEMICOLON
+    u'^'        #  0x5F -> CIRCUMFLEX ACCENT
+    u'-'        #  0x60 -> HYPHEN-MINUS
+    u'/'        #  0x61 -> SOLIDUS
+    u'\xc2'     #  0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc4'     #  0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc0'     #  0x64 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0x65 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc3'     #  0x66 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc5'     #  0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'['        #  0x68 -> LEFT SQUARE BRACKET
+    u'\xd1'     #  0x69 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\u015f'   #  0x6A -> LATIN SMALL LETTER S WITH CEDILLA
+    u','        #  0x6B -> COMMA
+    u'%'        #  0x6C -> PERCENT SIGN
+    u'_'        #  0x6D -> LOW LINE
+    u'>'        #  0x6E -> GREATER-THAN SIGN
+    u'?'        #  0x6F -> QUESTION MARK
+    u'\xf8'     #  0x70 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xc9'     #  0x71 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0x74 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0x75 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0x78 -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\u0131'   #  0x79 -> LATIN SMALL LETTER DOTLESS I
+    u':'        #  0x7A -> COLON
+    u'\xd6'     #  0x7B -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\u015e'   #  0x7C -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u"'"        #  0x7D -> APOSTROPHE
+    u'='        #  0x7E -> EQUALS SIGN
+    u'\xdc'     #  0x7F -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xd8'     #  0x80 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'a'        #  0x81 -> LATIN SMALL LETTER A
+    u'b'        #  0x82 -> LATIN SMALL LETTER B
+    u'c'        #  0x83 -> LATIN SMALL LETTER C
+    u'd'        #  0x84 -> LATIN SMALL LETTER D
+    u'e'        #  0x85 -> LATIN SMALL LETTER E
+    u'f'        #  0x86 -> LATIN SMALL LETTER F
+    u'g'        #  0x87 -> LATIN SMALL LETTER G
+    u'h'        #  0x88 -> LATIN SMALL LETTER H
+    u'i'        #  0x89 -> LATIN SMALL LETTER I
+    u'\xab'     #  0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'}'        #  0x8C -> RIGHT CURLY BRACKET
+    u'`'        #  0x8D -> GRAVE ACCENT
+    u'\xa6'     #  0x8E -> BROKEN BAR
+    u'\xb1'     #  0x8F -> PLUS-MINUS SIGN
+    u'\xb0'     #  0x90 -> DEGREE SIGN
+    u'j'        #  0x91 -> LATIN SMALL LETTER J
+    u'k'        #  0x92 -> LATIN SMALL LETTER K
+    u'l'        #  0x93 -> LATIN SMALL LETTER L
+    u'm'        #  0x94 -> LATIN SMALL LETTER M
+    u'n'        #  0x95 -> LATIN SMALL LETTER N
+    u'o'        #  0x96 -> LATIN SMALL LETTER O
+    u'p'        #  0x97 -> LATIN SMALL LETTER P
+    u'q'        #  0x98 -> LATIN SMALL LETTER Q
+    u'r'        #  0x99 -> LATIN SMALL LETTER R
+    u'\xaa'     #  0x9A -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x9B -> MASCULINE ORDINAL INDICATOR
+    u'\xe6'     #  0x9C -> LATIN SMALL LIGATURE AE
+    u'\xb8'     #  0x9D -> CEDILLA
+    u'\xc6'     #  0x9E -> LATIN CAPITAL LIGATURE AE
+    u'\xa4'     #  0x9F -> CURRENCY SIGN
+    u'\xb5'     #  0xA0 -> MICRO SIGN
+    u'\xf6'     #  0xA1 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u's'        #  0xA2 -> LATIN SMALL LETTER S
+    u't'        #  0xA3 -> LATIN SMALL LETTER T
+    u'u'        #  0xA4 -> LATIN SMALL LETTER U
+    u'v'        #  0xA5 -> LATIN SMALL LETTER V
+    u'w'        #  0xA6 -> LATIN SMALL LETTER W
+    u'x'        #  0xA7 -> LATIN SMALL LETTER X
+    u'y'        #  0xA8 -> LATIN SMALL LETTER Y
+    u'z'        #  0xA9 -> LATIN SMALL LETTER Z
+    u'\xa1'     #  0xAA -> INVERTED EXCLAMATION MARK
+    u'\xbf'     #  0xAB -> INVERTED QUESTION MARK
+    u']'        #  0xAC -> RIGHT SQUARE BRACKET
+    u'$'        #  0xAD -> DOLLAR SIGN
+    u'@'        #  0xAE -> COMMERCIAL AT
+    u'\xae'     #  0xAF -> REGISTERED SIGN
+    u'\xa2'     #  0xB0 -> CENT SIGN
+    u'\xa3'     #  0xB1 -> POUND SIGN
+    u'\xa5'     #  0xB2 -> YEN SIGN
+    u'\xb7'     #  0xB3 -> MIDDLE DOT
+    u'\xa9'     #  0xB4 -> COPYRIGHT SIGN
+    u'\xa7'     #  0xB5 -> SECTION SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xbc'     #  0xB7 -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xB8 -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xB9 -> VULGAR FRACTION THREE QUARTERS
+    u'\xac'     #  0xBA -> NOT SIGN
+    u'|'        #  0xBB -> VERTICAL LINE
+    u'\xaf'     #  0xBC -> MACRON
+    u'\xa8'     #  0xBD -> DIAERESIS
+    u'\xb4'     #  0xBE -> ACUTE ACCENT
+    u'\xd7'     #  0xBF -> MULTIPLICATION SIGN
+    u'\xe7'     #  0xC0 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'A'        #  0xC1 -> LATIN CAPITAL LETTER A
+    u'B'        #  0xC2 -> LATIN CAPITAL LETTER B
+    u'C'        #  0xC3 -> LATIN CAPITAL LETTER C
+    u'D'        #  0xC4 -> LATIN CAPITAL LETTER D
+    u'E'        #  0xC5 -> LATIN CAPITAL LETTER E
+    u'F'        #  0xC6 -> LATIN CAPITAL LETTER F
+    u'G'        #  0xC7 -> LATIN CAPITAL LETTER G
+    u'H'        #  0xC8 -> LATIN CAPITAL LETTER H
+    u'I'        #  0xC9 -> LATIN CAPITAL LETTER I
+    u'\xad'     #  0xCA -> SOFT HYPHEN
+    u'\xf4'     #  0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'~'        #  0xCC -> TILDE
+    u'\xf2'     #  0xCD -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xCE -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf5'     #  0xCF -> LATIN SMALL LETTER O WITH TILDE
+    u'\u011f'   #  0xD0 -> LATIN SMALL LETTER G WITH BREVE
+    u'J'        #  0xD1 -> LATIN CAPITAL LETTER J
+    u'K'        #  0xD2 -> LATIN CAPITAL LETTER K
+    u'L'        #  0xD3 -> LATIN CAPITAL LETTER L
+    u'M'        #  0xD4 -> LATIN CAPITAL LETTER M
+    u'N'        #  0xD5 -> LATIN CAPITAL LETTER N
+    u'O'        #  0xD6 -> LATIN CAPITAL LETTER O
+    u'P'        #  0xD7 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0xD8 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0xD9 -> LATIN CAPITAL LETTER R
+    u'\xb9'     #  0xDA -> SUPERSCRIPT ONE
+    u'\xfb'     #  0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\\'       #  0xDC -> REVERSE SOLIDUS
+    u'\xf9'     #  0xDD -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xDE -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xff'     #  0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\xfc'     #  0xE0 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xf7'     #  0xE1 -> DIVISION SIGN
+    u'S'        #  0xE2 -> LATIN CAPITAL LETTER S
+    u'T'        #  0xE3 -> LATIN CAPITAL LETTER T
+    u'U'        #  0xE4 -> LATIN CAPITAL LETTER U
+    u'V'        #  0xE5 -> LATIN CAPITAL LETTER V
+    u'W'        #  0xE6 -> LATIN CAPITAL LETTER W
+    u'X'        #  0xE7 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0xE8 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0xE9 -> LATIN CAPITAL LETTER Z
+    u'\xb2'     #  0xEA -> SUPERSCRIPT TWO
+    u'\xd4'     #  0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'#'        #  0xEC -> NUMBER SIGN
+    u'\xd2'     #  0xED -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd5'     #  0xEF -> LATIN CAPITAL LETTER O WITH TILDE
+    u'0'        #  0xF0 -> DIGIT ZERO
+    u'1'        #  0xF1 -> DIGIT ONE
+    u'2'        #  0xF2 -> DIGIT TWO
+    u'3'        #  0xF3 -> DIGIT THREE
+    u'4'        #  0xF4 -> DIGIT FOUR
+    u'5'        #  0xF5 -> DIGIT FIVE
+    u'6'        #  0xF6 -> DIGIT SIX
+    u'7'        #  0xF7 -> DIGIT SEVEN
+    u'8'        #  0xF8 -> DIGIT EIGHT
+    u'9'        #  0xF9 -> DIGIT NINE
+    u'\xb3'     #  0xFA -> SUPERSCRIPT THREE
+    u'\xdb'     #  0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'"'        #  0xFC -> QUOTATION MARK
+    u'\xd9'     #  0xFD -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xFE -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\x9f'     #  0xFF -> CONTROL
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1140.py b/src/main/resources/PythonLibs/encodings/cp1140.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e507fd8530762fea37044237408b54604cacff1
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1140.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1140 generated from 'python-mappings/CP1140.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1140',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x9c'     #  0x04 -> CONTROL
+    u'\t'       #  0x05 -> HORIZONTAL TABULATION
+    u'\x86'     #  0x06 -> CONTROL
+    u'\x7f'     #  0x07 -> DELETE
+    u'\x97'     #  0x08 -> CONTROL
+    u'\x8d'     #  0x09 -> CONTROL
+    u'\x8e'     #  0x0A -> CONTROL
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x9d'     #  0x14 -> CONTROL
+    u'\x85'     #  0x15 -> CONTROL
+    u'\x08'     #  0x16 -> BACKSPACE
+    u'\x87'     #  0x17 -> CONTROL
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x92'     #  0x1A -> CONTROL
+    u'\x8f'     #  0x1B -> CONTROL
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u'\x80'     #  0x20 -> CONTROL
+    u'\x81'     #  0x21 -> CONTROL
+    u'\x82'     #  0x22 -> CONTROL
+    u'\x83'     #  0x23 -> CONTROL
+    u'\x84'     #  0x24 -> CONTROL
+    u'\n'       #  0x25 -> LINE FEED
+    u'\x17'     #  0x26 -> END OF TRANSMISSION BLOCK
+    u'\x1b'     #  0x27 -> ESCAPE
+    u'\x88'     #  0x28 -> CONTROL
+    u'\x89'     #  0x29 -> CONTROL
+    u'\x8a'     #  0x2A -> CONTROL
+    u'\x8b'     #  0x2B -> CONTROL
+    u'\x8c'     #  0x2C -> CONTROL
+    u'\x05'     #  0x2D -> ENQUIRY
+    u'\x06'     #  0x2E -> ACKNOWLEDGE
+    u'\x07'     #  0x2F -> BELL
+    u'\x90'     #  0x30 -> CONTROL
+    u'\x91'     #  0x31 -> CONTROL
+    u'\x16'     #  0x32 -> SYNCHRONOUS IDLE
+    u'\x93'     #  0x33 -> CONTROL
+    u'\x94'     #  0x34 -> CONTROL
+    u'\x95'     #  0x35 -> CONTROL
+    u'\x96'     #  0x36 -> CONTROL
+    u'\x04'     #  0x37 -> END OF TRANSMISSION
+    u'\x98'     #  0x38 -> CONTROL
+    u'\x99'     #  0x39 -> CONTROL
+    u'\x9a'     #  0x3A -> CONTROL
+    u'\x9b'     #  0x3B -> CONTROL
+    u'\x14'     #  0x3C -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x3D -> NEGATIVE ACKNOWLEDGE
+    u'\x9e'     #  0x3E -> CONTROL
+    u'\x1a'     #  0x3F -> SUBSTITUTE
+    u' '        #  0x40 -> SPACE
+    u'\xa0'     #  0x41 -> NO-BREAK SPACE
+    u'\xe2'     #  0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x43 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x44 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0x45 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe3'     #  0x46 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x47 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x48 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xf1'     #  0x49 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xa2'     #  0x4A -> CENT SIGN
+    u'.'        #  0x4B -> FULL STOP
+    u'<'        #  0x4C -> LESS-THAN SIGN
+    u'('        #  0x4D -> LEFT PARENTHESIS
+    u'+'        #  0x4E -> PLUS SIGN
+    u'|'        #  0x4F -> VERTICAL LINE
+    u'&'        #  0x50 -> AMPERSAND
+    u'\xe9'     #  0x51 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x53 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x54 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xed'     #  0x55 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x57 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xec'     #  0x58 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xdf'     #  0x59 -> LATIN SMALL LETTER SHARP S (GERMAN)
+    u'!'        #  0x5A -> EXCLAMATION MARK
+    u'$'        #  0x5B -> DOLLAR SIGN
+    u'*'        #  0x5C -> ASTERISK
+    u')'        #  0x5D -> RIGHT PARENTHESIS
+    u';'        #  0x5E -> SEMICOLON
+    u'\xac'     #  0x5F -> NOT SIGN
+    u'-'        #  0x60 -> HYPHEN-MINUS
+    u'/'        #  0x61 -> SOLIDUS
+    u'\xc2'     #  0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc4'     #  0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc0'     #  0x64 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0x65 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc3'     #  0x66 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc5'     #  0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc7'     #  0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xd1'     #  0x69 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xa6'     #  0x6A -> BROKEN BAR
+    u','        #  0x6B -> COMMA
+    u'%'        #  0x6C -> PERCENT SIGN
+    u'_'        #  0x6D -> LOW LINE
+    u'>'        #  0x6E -> GREATER-THAN SIGN
+    u'?'        #  0x6F -> QUESTION MARK
+    u'\xf8'     #  0x70 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xc9'     #  0x71 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0x74 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0x75 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0x78 -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'`'        #  0x79 -> GRAVE ACCENT
+    u':'        #  0x7A -> COLON
+    u'#'        #  0x7B -> NUMBER SIGN
+    u'@'        #  0x7C -> COMMERCIAL AT
+    u"'"        #  0x7D -> APOSTROPHE
+    u'='        #  0x7E -> EQUALS SIGN
+    u'"'        #  0x7F -> QUOTATION MARK
+    u'\xd8'     #  0x80 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'a'        #  0x81 -> LATIN SMALL LETTER A
+    u'b'        #  0x82 -> LATIN SMALL LETTER B
+    u'c'        #  0x83 -> LATIN SMALL LETTER C
+    u'd'        #  0x84 -> LATIN SMALL LETTER D
+    u'e'        #  0x85 -> LATIN SMALL LETTER E
+    u'f'        #  0x86 -> LATIN SMALL LETTER F
+    u'g'        #  0x87 -> LATIN SMALL LETTER G
+    u'h'        #  0x88 -> LATIN SMALL LETTER H
+    u'i'        #  0x89 -> LATIN SMALL LETTER I
+    u'\xab'     #  0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xf0'     #  0x8C -> LATIN SMALL LETTER ETH (ICELANDIC)
+    u'\xfd'     #  0x8D -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xfe'     #  0x8E -> LATIN SMALL LETTER THORN (ICELANDIC)
+    u'\xb1'     #  0x8F -> PLUS-MINUS SIGN
+    u'\xb0'     #  0x90 -> DEGREE SIGN
+    u'j'        #  0x91 -> LATIN SMALL LETTER J
+    u'k'        #  0x92 -> LATIN SMALL LETTER K
+    u'l'        #  0x93 -> LATIN SMALL LETTER L
+    u'm'        #  0x94 -> LATIN SMALL LETTER M
+    u'n'        #  0x95 -> LATIN SMALL LETTER N
+    u'o'        #  0x96 -> LATIN SMALL LETTER O
+    u'p'        #  0x97 -> LATIN SMALL LETTER P
+    u'q'        #  0x98 -> LATIN SMALL LETTER Q
+    u'r'        #  0x99 -> LATIN SMALL LETTER R
+    u'\xaa'     #  0x9A -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x9B -> MASCULINE ORDINAL INDICATOR
+    u'\xe6'     #  0x9C -> LATIN SMALL LIGATURE AE
+    u'\xb8'     #  0x9D -> CEDILLA
+    u'\xc6'     #  0x9E -> LATIN CAPITAL LIGATURE AE
+    u'\u20ac'   #  0x9F -> EURO SIGN
+    u'\xb5'     #  0xA0 -> MICRO SIGN
+    u'~'        #  0xA1 -> TILDE
+    u's'        #  0xA2 -> LATIN SMALL LETTER S
+    u't'        #  0xA3 -> LATIN SMALL LETTER T
+    u'u'        #  0xA4 -> LATIN SMALL LETTER U
+    u'v'        #  0xA5 -> LATIN SMALL LETTER V
+    u'w'        #  0xA6 -> LATIN SMALL LETTER W
+    u'x'        #  0xA7 -> LATIN SMALL LETTER X
+    u'y'        #  0xA8 -> LATIN SMALL LETTER Y
+    u'z'        #  0xA9 -> LATIN SMALL LETTER Z
+    u'\xa1'     #  0xAA -> INVERTED EXCLAMATION MARK
+    u'\xbf'     #  0xAB -> INVERTED QUESTION MARK
+    u'\xd0'     #  0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC)
+    u'\xdd'     #  0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xde'     #  0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC)
+    u'\xae'     #  0xAF -> REGISTERED SIGN
+    u'^'        #  0xB0 -> CIRCUMFLEX ACCENT
+    u'\xa3'     #  0xB1 -> POUND SIGN
+    u'\xa5'     #  0xB2 -> YEN SIGN
+    u'\xb7'     #  0xB3 -> MIDDLE DOT
+    u'\xa9'     #  0xB4 -> COPYRIGHT SIGN
+    u'\xa7'     #  0xB5 -> SECTION SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xbc'     #  0xB7 -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xB8 -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xB9 -> VULGAR FRACTION THREE QUARTERS
+    u'['        #  0xBA -> LEFT SQUARE BRACKET
+    u']'        #  0xBB -> RIGHT SQUARE BRACKET
+    u'\xaf'     #  0xBC -> MACRON
+    u'\xa8'     #  0xBD -> DIAERESIS
+    u'\xb4'     #  0xBE -> ACUTE ACCENT
+    u'\xd7'     #  0xBF -> MULTIPLICATION SIGN
+    u'{'        #  0xC0 -> LEFT CURLY BRACKET
+    u'A'        #  0xC1 -> LATIN CAPITAL LETTER A
+    u'B'        #  0xC2 -> LATIN CAPITAL LETTER B
+    u'C'        #  0xC3 -> LATIN CAPITAL LETTER C
+    u'D'        #  0xC4 -> LATIN CAPITAL LETTER D
+    u'E'        #  0xC5 -> LATIN CAPITAL LETTER E
+    u'F'        #  0xC6 -> LATIN CAPITAL LETTER F
+    u'G'        #  0xC7 -> LATIN CAPITAL LETTER G
+    u'H'        #  0xC8 -> LATIN CAPITAL LETTER H
+    u'I'        #  0xC9 -> LATIN CAPITAL LETTER I
+    u'\xad'     #  0xCA -> SOFT HYPHEN
+    u'\xf4'     #  0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0xCC -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf2'     #  0xCD -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xCE -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf5'     #  0xCF -> LATIN SMALL LETTER O WITH TILDE
+    u'}'        #  0xD0 -> RIGHT CURLY BRACKET
+    u'J'        #  0xD1 -> LATIN CAPITAL LETTER J
+    u'K'        #  0xD2 -> LATIN CAPITAL LETTER K
+    u'L'        #  0xD3 -> LATIN CAPITAL LETTER L
+    u'M'        #  0xD4 -> LATIN CAPITAL LETTER M
+    u'N'        #  0xD5 -> LATIN CAPITAL LETTER N
+    u'O'        #  0xD6 -> LATIN CAPITAL LETTER O
+    u'P'        #  0xD7 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0xD8 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0xD9 -> LATIN CAPITAL LETTER R
+    u'\xb9'     #  0xDA -> SUPERSCRIPT ONE
+    u'\xfb'     #  0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xDC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xf9'     #  0xDD -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xDE -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xff'     #  0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\\'       #  0xE0 -> REVERSE SOLIDUS
+    u'\xf7'     #  0xE1 -> DIVISION SIGN
+    u'S'        #  0xE2 -> LATIN CAPITAL LETTER S
+    u'T'        #  0xE3 -> LATIN CAPITAL LETTER T
+    u'U'        #  0xE4 -> LATIN CAPITAL LETTER U
+    u'V'        #  0xE5 -> LATIN CAPITAL LETTER V
+    u'W'        #  0xE6 -> LATIN CAPITAL LETTER W
+    u'X'        #  0xE7 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0xE8 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0xE9 -> LATIN CAPITAL LETTER Z
+    u'\xb2'     #  0xEA -> SUPERSCRIPT TWO
+    u'\xd4'     #  0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd6'     #  0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd2'     #  0xED -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd5'     #  0xEF -> LATIN CAPITAL LETTER O WITH TILDE
+    u'0'        #  0xF0 -> DIGIT ZERO
+    u'1'        #  0xF1 -> DIGIT ONE
+    u'2'        #  0xF2 -> DIGIT TWO
+    u'3'        #  0xF3 -> DIGIT THREE
+    u'4'        #  0xF4 -> DIGIT FOUR
+    u'5'        #  0xF5 -> DIGIT FIVE
+    u'6'        #  0xF6 -> DIGIT SIX
+    u'7'        #  0xF7 -> DIGIT SEVEN
+    u'8'        #  0xF8 -> DIGIT EIGHT
+    u'9'        #  0xF9 -> DIGIT NINE
+    u'\xb3'     #  0xFA -> SUPERSCRIPT THREE
+    u'\xdb'     #  0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xd9'     #  0xFD -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xFE -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\x9f'     #  0xFF -> CONTROL
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1250.py b/src/main/resources/PythonLibs/encodings/cp1250.py
new file mode 100644
index 0000000000000000000000000000000000000000..d620b893358ab5c37a239846862b0dd754ad0a17
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1250.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1250 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1250',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\ufffe'   #  0x81 -> UNDEFINED
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\ufffe'   #  0x83 -> UNDEFINED
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\ufffe'   #  0x88 -> UNDEFINED
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\u0160'   #  0x8A -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u015a'   #  0x8C -> LATIN CAPITAL LETTER S WITH ACUTE
+    u'\u0164'   #  0x8D -> LATIN CAPITAL LETTER T WITH CARON
+    u'\u017d'   #  0x8E -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\u0179'   #  0x8F -> LATIN CAPITAL LETTER Z WITH ACUTE
+    u'\ufffe'   #  0x90 -> UNDEFINED
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\ufffe'   #  0x98 -> UNDEFINED
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\u0161'   #  0x9A -> LATIN SMALL LETTER S WITH CARON
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\u015b'   #  0x9C -> LATIN SMALL LETTER S WITH ACUTE
+    u'\u0165'   #  0x9D -> LATIN SMALL LETTER T WITH CARON
+    u'\u017e'   #  0x9E -> LATIN SMALL LETTER Z WITH CARON
+    u'\u017a'   #  0x9F -> LATIN SMALL LETTER Z WITH ACUTE
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u02c7'   #  0xA1 -> CARON
+    u'\u02d8'   #  0xA2 -> BREVE
+    u'\u0141'   #  0xA3 -> LATIN CAPITAL LETTER L WITH STROKE
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\u0104'   #  0xA5 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u015e'   #  0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\u017b'   #  0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u02db'   #  0xB2 -> OGONEK
+    u'\u0142'   #  0xB3 -> LATIN SMALL LETTER L WITH STROKE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\u0105'   #  0xB9 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u015f'   #  0xBA -> LATIN SMALL LETTER S WITH CEDILLA
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u013d'   #  0xBC -> LATIN CAPITAL LETTER L WITH CARON
+    u'\u02dd'   #  0xBD -> DOUBLE ACUTE ACCENT
+    u'\u013e'   #  0xBE -> LATIN SMALL LETTER L WITH CARON
+    u'\u017c'   #  0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\u0154'   #  0xC0 -> LATIN CAPITAL LETTER R WITH ACUTE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\u0102'   #  0xC3 -> LATIN CAPITAL LETTER A WITH BREVE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\u0139'   #  0xC5 -> LATIN CAPITAL LETTER L WITH ACUTE
+    u'\u0106'   #  0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\u010c'   #  0xC8 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\u0118'   #  0xCA -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\u011a'   #  0xCC -> LATIN CAPITAL LETTER E WITH CARON
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\u010e'   #  0xCF -> LATIN CAPITAL LETTER D WITH CARON
+    u'\u0110'   #  0xD0 -> LATIN CAPITAL LETTER D WITH STROKE
+    u'\u0143'   #  0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE
+    u'\u0147'   #  0xD2 -> LATIN CAPITAL LETTER N WITH CARON
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\u0150'   #  0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\u0158'   #  0xD8 -> LATIN CAPITAL LETTER R WITH CARON
+    u'\u016e'   #  0xD9 -> LATIN CAPITAL LETTER U WITH RING ABOVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\u0170'   #  0xDB -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xdd'     #  0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\u0162'   #  0xDE -> LATIN CAPITAL LETTER T WITH CEDILLA
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\u0155'   #  0xE0 -> LATIN SMALL LETTER R WITH ACUTE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\u0103'   #  0xE3 -> LATIN SMALL LETTER A WITH BREVE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u013a'   #  0xE5 -> LATIN SMALL LETTER L WITH ACUTE
+    u'\u0107'   #  0xE6 -> LATIN SMALL LETTER C WITH ACUTE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\u010d'   #  0xE8 -> LATIN SMALL LETTER C WITH CARON
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\u0119'   #  0xEA -> LATIN SMALL LETTER E WITH OGONEK
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\u011b'   #  0xEC -> LATIN SMALL LETTER E WITH CARON
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\u010f'   #  0xEF -> LATIN SMALL LETTER D WITH CARON
+    u'\u0111'   #  0xF0 -> LATIN SMALL LETTER D WITH STROKE
+    u'\u0144'   #  0xF1 -> LATIN SMALL LETTER N WITH ACUTE
+    u'\u0148'   #  0xF2 -> LATIN SMALL LETTER N WITH CARON
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\u0151'   #  0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\u0159'   #  0xF8 -> LATIN SMALL LETTER R WITH CARON
+    u'\u016f'   #  0xF9 -> LATIN SMALL LETTER U WITH RING ABOVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\u0171'   #  0xFB -> LATIN SMALL LETTER U WITH DOUBLE ACUTE
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xfd'     #  0xFD -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\u0163'   #  0xFE -> LATIN SMALL LETTER T WITH CEDILLA
+    u'\u02d9'   #  0xFF -> DOT ABOVE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1251.py b/src/main/resources/PythonLibs/encodings/cp1251.py
new file mode 100644
index 0000000000000000000000000000000000000000..216771fa4cc9ff1a5faf1fe5b480c5b8bb1a030a
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1251.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1251 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1251',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u0402'   #  0x80 -> CYRILLIC CAPITAL LETTER DJE
+    u'\u0403'   #  0x81 -> CYRILLIC CAPITAL LETTER GJE
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u0453'   #  0x83 -> CYRILLIC SMALL LETTER GJE
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\u20ac'   #  0x88 -> EURO SIGN
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\u0409'   #  0x8A -> CYRILLIC CAPITAL LETTER LJE
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u040a'   #  0x8C -> CYRILLIC CAPITAL LETTER NJE
+    u'\u040c'   #  0x8D -> CYRILLIC CAPITAL LETTER KJE
+    u'\u040b'   #  0x8E -> CYRILLIC CAPITAL LETTER TSHE
+    u'\u040f'   #  0x8F -> CYRILLIC CAPITAL LETTER DZHE
+    u'\u0452'   #  0x90 -> CYRILLIC SMALL LETTER DJE
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\ufffe'   #  0x98 -> UNDEFINED
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\u0459'   #  0x9A -> CYRILLIC SMALL LETTER LJE
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\u045a'   #  0x9C -> CYRILLIC SMALL LETTER NJE
+    u'\u045c'   #  0x9D -> CYRILLIC SMALL LETTER KJE
+    u'\u045b'   #  0x9E -> CYRILLIC SMALL LETTER TSHE
+    u'\u045f'   #  0x9F -> CYRILLIC SMALL LETTER DZHE
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u040e'   #  0xA1 -> CYRILLIC CAPITAL LETTER SHORT U
+    u'\u045e'   #  0xA2 -> CYRILLIC SMALL LETTER SHORT U
+    u'\u0408'   #  0xA3 -> CYRILLIC CAPITAL LETTER JE
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\u0490'   #  0xA5 -> CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\u0401'   #  0xA8 -> CYRILLIC CAPITAL LETTER IO
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u0404'   #  0xAA -> CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\u0407'   #  0xAF -> CYRILLIC CAPITAL LETTER YI
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u0406'   #  0xB2 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\u0456'   #  0xB3 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\u0491'   #  0xB4 -> CYRILLIC SMALL LETTER GHE WITH UPTURN
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\u0451'   #  0xB8 -> CYRILLIC SMALL LETTER IO
+    u'\u2116'   #  0xB9 -> NUMERO SIGN
+    u'\u0454'   #  0xBA -> CYRILLIC SMALL LETTER UKRAINIAN IE
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u0458'   #  0xBC -> CYRILLIC SMALL LETTER JE
+    u'\u0405'   #  0xBD -> CYRILLIC CAPITAL LETTER DZE
+    u'\u0455'   #  0xBE -> CYRILLIC SMALL LETTER DZE
+    u'\u0457'   #  0xBF -> CYRILLIC SMALL LETTER YI
+    u'\u0410'   #  0xC0 -> CYRILLIC CAPITAL LETTER A
+    u'\u0411'   #  0xC1 -> CYRILLIC CAPITAL LETTER BE
+    u'\u0412'   #  0xC2 -> CYRILLIC CAPITAL LETTER VE
+    u'\u0413'   #  0xC3 -> CYRILLIC CAPITAL LETTER GHE
+    u'\u0414'   #  0xC4 -> CYRILLIC CAPITAL LETTER DE
+    u'\u0415'   #  0xC5 -> CYRILLIC CAPITAL LETTER IE
+    u'\u0416'   #  0xC6 -> CYRILLIC CAPITAL LETTER ZHE
+    u'\u0417'   #  0xC7 -> CYRILLIC CAPITAL LETTER ZE
+    u'\u0418'   #  0xC8 -> CYRILLIC CAPITAL LETTER I
+    u'\u0419'   #  0xC9 -> CYRILLIC CAPITAL LETTER SHORT I
+    u'\u041a'   #  0xCA -> CYRILLIC CAPITAL LETTER KA
+    u'\u041b'   #  0xCB -> CYRILLIC CAPITAL LETTER EL
+    u'\u041c'   #  0xCC -> CYRILLIC CAPITAL LETTER EM
+    u'\u041d'   #  0xCD -> CYRILLIC CAPITAL LETTER EN
+    u'\u041e'   #  0xCE -> CYRILLIC CAPITAL LETTER O
+    u'\u041f'   #  0xCF -> CYRILLIC CAPITAL LETTER PE
+    u'\u0420'   #  0xD0 -> CYRILLIC CAPITAL LETTER ER
+    u'\u0421'   #  0xD1 -> CYRILLIC CAPITAL LETTER ES
+    u'\u0422'   #  0xD2 -> CYRILLIC CAPITAL LETTER TE
+    u'\u0423'   #  0xD3 -> CYRILLIC CAPITAL LETTER U
+    u'\u0424'   #  0xD4 -> CYRILLIC CAPITAL LETTER EF
+    u'\u0425'   #  0xD5 -> CYRILLIC CAPITAL LETTER HA
+    u'\u0426'   #  0xD6 -> CYRILLIC CAPITAL LETTER TSE
+    u'\u0427'   #  0xD7 -> CYRILLIC CAPITAL LETTER CHE
+    u'\u0428'   #  0xD8 -> CYRILLIC CAPITAL LETTER SHA
+    u'\u0429'   #  0xD9 -> CYRILLIC CAPITAL LETTER SHCHA
+    u'\u042a'   #  0xDA -> CYRILLIC CAPITAL LETTER HARD SIGN
+    u'\u042b'   #  0xDB -> CYRILLIC CAPITAL LETTER YERU
+    u'\u042c'   #  0xDC -> CYRILLIC CAPITAL LETTER SOFT SIGN
+    u'\u042d'   #  0xDD -> CYRILLIC CAPITAL LETTER E
+    u'\u042e'   #  0xDE -> CYRILLIC CAPITAL LETTER YU
+    u'\u042f'   #  0xDF -> CYRILLIC CAPITAL LETTER YA
+    u'\u0430'   #  0xE0 -> CYRILLIC SMALL LETTER A
+    u'\u0431'   #  0xE1 -> CYRILLIC SMALL LETTER BE
+    u'\u0432'   #  0xE2 -> CYRILLIC SMALL LETTER VE
+    u'\u0433'   #  0xE3 -> CYRILLIC SMALL LETTER GHE
+    u'\u0434'   #  0xE4 -> CYRILLIC SMALL LETTER DE
+    u'\u0435'   #  0xE5 -> CYRILLIC SMALL LETTER IE
+    u'\u0436'   #  0xE6 -> CYRILLIC SMALL LETTER ZHE
+    u'\u0437'   #  0xE7 -> CYRILLIC SMALL LETTER ZE
+    u'\u0438'   #  0xE8 -> CYRILLIC SMALL LETTER I
+    u'\u0439'   #  0xE9 -> CYRILLIC SMALL LETTER SHORT I
+    u'\u043a'   #  0xEA -> CYRILLIC SMALL LETTER KA
+    u'\u043b'   #  0xEB -> CYRILLIC SMALL LETTER EL
+    u'\u043c'   #  0xEC -> CYRILLIC SMALL LETTER EM
+    u'\u043d'   #  0xED -> CYRILLIC SMALL LETTER EN
+    u'\u043e'   #  0xEE -> CYRILLIC SMALL LETTER O
+    u'\u043f'   #  0xEF -> CYRILLIC SMALL LETTER PE
+    u'\u0440'   #  0xF0 -> CYRILLIC SMALL LETTER ER
+    u'\u0441'   #  0xF1 -> CYRILLIC SMALL LETTER ES
+    u'\u0442'   #  0xF2 -> CYRILLIC SMALL LETTER TE
+    u'\u0443'   #  0xF3 -> CYRILLIC SMALL LETTER U
+    u'\u0444'   #  0xF4 -> CYRILLIC SMALL LETTER EF
+    u'\u0445'   #  0xF5 -> CYRILLIC SMALL LETTER HA
+    u'\u0446'   #  0xF6 -> CYRILLIC SMALL LETTER TSE
+    u'\u0447'   #  0xF7 -> CYRILLIC SMALL LETTER CHE
+    u'\u0448'   #  0xF8 -> CYRILLIC SMALL LETTER SHA
+    u'\u0449'   #  0xF9 -> CYRILLIC SMALL LETTER SHCHA
+    u'\u044a'   #  0xFA -> CYRILLIC SMALL LETTER HARD SIGN
+    u'\u044b'   #  0xFB -> CYRILLIC SMALL LETTER YERU
+    u'\u044c'   #  0xFC -> CYRILLIC SMALL LETTER SOFT SIGN
+    u'\u044d'   #  0xFD -> CYRILLIC SMALL LETTER E
+    u'\u044e'   #  0xFE -> CYRILLIC SMALL LETTER YU
+    u'\u044f'   #  0xFF -> CYRILLIC SMALL LETTER YA
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1252.py b/src/main/resources/PythonLibs/encodings/cp1252.py
new file mode 100644
index 0000000000000000000000000000000000000000..e60a328db40385dbffd823e1ff0e38619aaa4115
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1252.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1252 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1252',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\ufffe'   #  0x81 -> UNDEFINED
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u0192'   #  0x83 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\u02c6'   #  0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\u0160'   #  0x8A -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u0152'   #  0x8C -> LATIN CAPITAL LIGATURE OE
+    u'\ufffe'   #  0x8D -> UNDEFINED
+    u'\u017d'   #  0x8E -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\ufffe'   #  0x8F -> UNDEFINED
+    u'\ufffe'   #  0x90 -> UNDEFINED
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\u02dc'   #  0x98 -> SMALL TILDE
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\u0161'   #  0x9A -> LATIN SMALL LETTER S WITH CARON
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\u0153'   #  0x9C -> LATIN SMALL LIGATURE OE
+    u'\ufffe'   #  0x9D -> UNDEFINED
+    u'\u017e'   #  0x9E -> LATIN SMALL LETTER Z WITH CARON
+    u'\u0178'   #  0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\xa1'     #  0xA1 -> INVERTED EXCLAMATION MARK
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\xaa'     #  0xAA -> FEMININE ORDINAL INDICATOR
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\xba'     #  0xBA -> MASCULINE ORDINAL INDICATOR
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\xbf'     #  0xBF -> INVERTED QUESTION MARK
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc3'     #  0xC3 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcc'     #  0xCC -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xd0'     #  0xD0 -> LATIN CAPITAL LETTER ETH
+    u'\xd1'     #  0xD1 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd2'     #  0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xdd'     #  0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xde'     #  0xDE -> LATIN CAPITAL LETTER THORN
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0xE3 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xec'     #  0xEC -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf0'     #  0xF0 -> LATIN SMALL LETTER ETH
+    u'\xf1'     #  0xF1 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf2'     #  0xF2 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xfd'     #  0xFD -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xfe'     #  0xFE -> LATIN SMALL LETTER THORN
+    u'\xff'     #  0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1253.py b/src/main/resources/PythonLibs/encodings/cp1253.py
new file mode 100644
index 0000000000000000000000000000000000000000..49f6cccbd2334d8a022132194ff09325a52a5275
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1253.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1253 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1253.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1253',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\ufffe'   #  0x81 -> UNDEFINED
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u0192'   #  0x83 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\ufffe'   #  0x88 -> UNDEFINED
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\ufffe'   #  0x8A -> UNDEFINED
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\ufffe'   #  0x8C -> UNDEFINED
+    u'\ufffe'   #  0x8D -> UNDEFINED
+    u'\ufffe'   #  0x8E -> UNDEFINED
+    u'\ufffe'   #  0x8F -> UNDEFINED
+    u'\ufffe'   #  0x90 -> UNDEFINED
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\ufffe'   #  0x98 -> UNDEFINED
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\ufffe'   #  0x9A -> UNDEFINED
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\ufffe'   #  0x9C -> UNDEFINED
+    u'\ufffe'   #  0x9D -> UNDEFINED
+    u'\ufffe'   #  0x9E -> UNDEFINED
+    u'\ufffe'   #  0x9F -> UNDEFINED
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0385'   #  0xA1 -> GREEK DIALYTIKA TONOS
+    u'\u0386'   #  0xA2 -> GREEK CAPITAL LETTER ALPHA WITH TONOS
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\ufffe'   #  0xAA -> UNDEFINED
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\u2015'   #  0xAF -> HORIZONTAL BAR
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\u0384'   #  0xB4 -> GREEK TONOS
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\u0388'   #  0xB8 -> GREEK CAPITAL LETTER EPSILON WITH TONOS
+    u'\u0389'   #  0xB9 -> GREEK CAPITAL LETTER ETA WITH TONOS
+    u'\u038a'   #  0xBA -> GREEK CAPITAL LETTER IOTA WITH TONOS
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u038c'   #  0xBC -> GREEK CAPITAL LETTER OMICRON WITH TONOS
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\u038e'   #  0xBE -> GREEK CAPITAL LETTER UPSILON WITH TONOS
+    u'\u038f'   #  0xBF -> GREEK CAPITAL LETTER OMEGA WITH TONOS
+    u'\u0390'   #  0xC0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+    u'\u0391'   #  0xC1 -> GREEK CAPITAL LETTER ALPHA
+    u'\u0392'   #  0xC2 -> GREEK CAPITAL LETTER BETA
+    u'\u0393'   #  0xC3 -> GREEK CAPITAL LETTER GAMMA
+    u'\u0394'   #  0xC4 -> GREEK CAPITAL LETTER DELTA
+    u'\u0395'   #  0xC5 -> GREEK CAPITAL LETTER EPSILON
+    u'\u0396'   #  0xC6 -> GREEK CAPITAL LETTER ZETA
+    u'\u0397'   #  0xC7 -> GREEK CAPITAL LETTER ETA
+    u'\u0398'   #  0xC8 -> GREEK CAPITAL LETTER THETA
+    u'\u0399'   #  0xC9 -> GREEK CAPITAL LETTER IOTA
+    u'\u039a'   #  0xCA -> GREEK CAPITAL LETTER KAPPA
+    u'\u039b'   #  0xCB -> GREEK CAPITAL LETTER LAMDA
+    u'\u039c'   #  0xCC -> GREEK CAPITAL LETTER MU
+    u'\u039d'   #  0xCD -> GREEK CAPITAL LETTER NU
+    u'\u039e'   #  0xCE -> GREEK CAPITAL LETTER XI
+    u'\u039f'   #  0xCF -> GREEK CAPITAL LETTER OMICRON
+    u'\u03a0'   #  0xD0 -> GREEK CAPITAL LETTER PI
+    u'\u03a1'   #  0xD1 -> GREEK CAPITAL LETTER RHO
+    u'\ufffe'   #  0xD2 -> UNDEFINED
+    u'\u03a3'   #  0xD3 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03a4'   #  0xD4 -> GREEK CAPITAL LETTER TAU
+    u'\u03a5'   #  0xD5 -> GREEK CAPITAL LETTER UPSILON
+    u'\u03a6'   #  0xD6 -> GREEK CAPITAL LETTER PHI
+    u'\u03a7'   #  0xD7 -> GREEK CAPITAL LETTER CHI
+    u'\u03a8'   #  0xD8 -> GREEK CAPITAL LETTER PSI
+    u'\u03a9'   #  0xD9 -> GREEK CAPITAL LETTER OMEGA
+    u'\u03aa'   #  0xDA -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    u'\u03ab'   #  0xDB -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    u'\u03ac'   #  0xDC -> GREEK SMALL LETTER ALPHA WITH TONOS
+    u'\u03ad'   #  0xDD -> GREEK SMALL LETTER EPSILON WITH TONOS
+    u'\u03ae'   #  0xDE -> GREEK SMALL LETTER ETA WITH TONOS
+    u'\u03af'   #  0xDF -> GREEK SMALL LETTER IOTA WITH TONOS
+    u'\u03b0'   #  0xE0 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+    u'\u03b1'   #  0xE1 -> GREEK SMALL LETTER ALPHA
+    u'\u03b2'   #  0xE2 -> GREEK SMALL LETTER BETA
+    u'\u03b3'   #  0xE3 -> GREEK SMALL LETTER GAMMA
+    u'\u03b4'   #  0xE4 -> GREEK SMALL LETTER DELTA
+    u'\u03b5'   #  0xE5 -> GREEK SMALL LETTER EPSILON
+    u'\u03b6'   #  0xE6 -> GREEK SMALL LETTER ZETA
+    u'\u03b7'   #  0xE7 -> GREEK SMALL LETTER ETA
+    u'\u03b8'   #  0xE8 -> GREEK SMALL LETTER THETA
+    u'\u03b9'   #  0xE9 -> GREEK SMALL LETTER IOTA
+    u'\u03ba'   #  0xEA -> GREEK SMALL LETTER KAPPA
+    u'\u03bb'   #  0xEB -> GREEK SMALL LETTER LAMDA
+    u'\u03bc'   #  0xEC -> GREEK SMALL LETTER MU
+    u'\u03bd'   #  0xED -> GREEK SMALL LETTER NU
+    u'\u03be'   #  0xEE -> GREEK SMALL LETTER XI
+    u'\u03bf'   #  0xEF -> GREEK SMALL LETTER OMICRON
+    u'\u03c0'   #  0xF0 -> GREEK SMALL LETTER PI
+    u'\u03c1'   #  0xF1 -> GREEK SMALL LETTER RHO
+    u'\u03c2'   #  0xF2 -> GREEK SMALL LETTER FINAL SIGMA
+    u'\u03c3'   #  0xF3 -> GREEK SMALL LETTER SIGMA
+    u'\u03c4'   #  0xF4 -> GREEK SMALL LETTER TAU
+    u'\u03c5'   #  0xF5 -> GREEK SMALL LETTER UPSILON
+    u'\u03c6'   #  0xF6 -> GREEK SMALL LETTER PHI
+    u'\u03c7'   #  0xF7 -> GREEK SMALL LETTER CHI
+    u'\u03c8'   #  0xF8 -> GREEK SMALL LETTER PSI
+    u'\u03c9'   #  0xF9 -> GREEK SMALL LETTER OMEGA
+    u'\u03ca'   #  0xFA -> GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    u'\u03cb'   #  0xFB -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    u'\u03cc'   #  0xFC -> GREEK SMALL LETTER OMICRON WITH TONOS
+    u'\u03cd'   #  0xFD -> GREEK SMALL LETTER UPSILON WITH TONOS
+    u'\u03ce'   #  0xFE -> GREEK SMALL LETTER OMEGA WITH TONOS
+    u'\ufffe'   #  0xFF -> UNDEFINED
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1254.py b/src/main/resources/PythonLibs/encodings/cp1254.py
new file mode 100644
index 0000000000000000000000000000000000000000..65530ab546178e127225c459cd1ca9ef8cd65aa0
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1254.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1254 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1254.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1254',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\ufffe'   #  0x81 -> UNDEFINED
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u0192'   #  0x83 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\u02c6'   #  0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\u0160'   #  0x8A -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u0152'   #  0x8C -> LATIN CAPITAL LIGATURE OE
+    u'\ufffe'   #  0x8D -> UNDEFINED
+    u'\ufffe'   #  0x8E -> UNDEFINED
+    u'\ufffe'   #  0x8F -> UNDEFINED
+    u'\ufffe'   #  0x90 -> UNDEFINED
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\u02dc'   #  0x98 -> SMALL TILDE
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\u0161'   #  0x9A -> LATIN SMALL LETTER S WITH CARON
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\u0153'   #  0x9C -> LATIN SMALL LIGATURE OE
+    u'\ufffe'   #  0x9D -> UNDEFINED
+    u'\ufffe'   #  0x9E -> UNDEFINED
+    u'\u0178'   #  0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\xa1'     #  0xA1 -> INVERTED EXCLAMATION MARK
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\xaa'     #  0xAA -> FEMININE ORDINAL INDICATOR
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\xba'     #  0xBA -> MASCULINE ORDINAL INDICATOR
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\xbf'     #  0xBF -> INVERTED QUESTION MARK
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc3'     #  0xC3 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcc'     #  0xCC -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\u011e'   #  0xD0 -> LATIN CAPITAL LETTER G WITH BREVE
+    u'\xd1'     #  0xD1 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd2'     #  0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u0130'   #  0xDD -> LATIN CAPITAL LETTER I WITH DOT ABOVE
+    u'\u015e'   #  0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0xE3 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xec'     #  0xEC -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\u011f'   #  0xF0 -> LATIN SMALL LETTER G WITH BREVE
+    u'\xf1'     #  0xF1 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf2'     #  0xF2 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u0131'   #  0xFD -> LATIN SMALL LETTER DOTLESS I
+    u'\u015f'   #  0xFE -> LATIN SMALL LETTER S WITH CEDILLA
+    u'\xff'     #  0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1255.py b/src/main/resources/PythonLibs/encodings/cp1255.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd1456fab6e0b416891f0bc24a220cf2e74fe04f
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1255.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1255 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1255.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1255',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\ufffe'   #  0x81 -> UNDEFINED
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u0192'   #  0x83 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\u02c6'   #  0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\ufffe'   #  0x8A -> UNDEFINED
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\ufffe'   #  0x8C -> UNDEFINED
+    u'\ufffe'   #  0x8D -> UNDEFINED
+    u'\ufffe'   #  0x8E -> UNDEFINED
+    u'\ufffe'   #  0x8F -> UNDEFINED
+    u'\ufffe'   #  0x90 -> UNDEFINED
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\u02dc'   #  0x98 -> SMALL TILDE
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\ufffe'   #  0x9A -> UNDEFINED
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\ufffe'   #  0x9C -> UNDEFINED
+    u'\ufffe'   #  0x9D -> UNDEFINED
+    u'\ufffe'   #  0x9E -> UNDEFINED
+    u'\ufffe'   #  0x9F -> UNDEFINED
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\xa1'     #  0xA1 -> INVERTED EXCLAMATION MARK
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\u20aa'   #  0xA4 -> NEW SHEQEL SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\xd7'     #  0xAA -> MULTIPLICATION SIGN
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\xf7'     #  0xBA -> DIVISION SIGN
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\xbf'     #  0xBF -> INVERTED QUESTION MARK
+    u'\u05b0'   #  0xC0 -> HEBREW POINT SHEVA
+    u'\u05b1'   #  0xC1 -> HEBREW POINT HATAF SEGOL
+    u'\u05b2'   #  0xC2 -> HEBREW POINT HATAF PATAH
+    u'\u05b3'   #  0xC3 -> HEBREW POINT HATAF QAMATS
+    u'\u05b4'   #  0xC4 -> HEBREW POINT HIRIQ
+    u'\u05b5'   #  0xC5 -> HEBREW POINT TSERE
+    u'\u05b6'   #  0xC6 -> HEBREW POINT SEGOL
+    u'\u05b7'   #  0xC7 -> HEBREW POINT PATAH
+    u'\u05b8'   #  0xC8 -> HEBREW POINT QAMATS
+    u'\u05b9'   #  0xC9 -> HEBREW POINT HOLAM
+    u'\ufffe'   #  0xCA -> UNDEFINED
+    u'\u05bb'   #  0xCB -> HEBREW POINT QUBUTS
+    u'\u05bc'   #  0xCC -> HEBREW POINT DAGESH OR MAPIQ
+    u'\u05bd'   #  0xCD -> HEBREW POINT METEG
+    u'\u05be'   #  0xCE -> HEBREW PUNCTUATION MAQAF
+    u'\u05bf'   #  0xCF -> HEBREW POINT RAFE
+    u'\u05c0'   #  0xD0 -> HEBREW PUNCTUATION PASEQ
+    u'\u05c1'   #  0xD1 -> HEBREW POINT SHIN DOT
+    u'\u05c2'   #  0xD2 -> HEBREW POINT SIN DOT
+    u'\u05c3'   #  0xD3 -> HEBREW PUNCTUATION SOF PASUQ
+    u'\u05f0'   #  0xD4 -> HEBREW LIGATURE YIDDISH DOUBLE VAV
+    u'\u05f1'   #  0xD5 -> HEBREW LIGATURE YIDDISH VAV YOD
+    u'\u05f2'   #  0xD6 -> HEBREW LIGATURE YIDDISH DOUBLE YOD
+    u'\u05f3'   #  0xD7 -> HEBREW PUNCTUATION GERESH
+    u'\u05f4'   #  0xD8 -> HEBREW PUNCTUATION GERSHAYIM
+    u'\ufffe'   #  0xD9 -> UNDEFINED
+    u'\ufffe'   #  0xDA -> UNDEFINED
+    u'\ufffe'   #  0xDB -> UNDEFINED
+    u'\ufffe'   #  0xDC -> UNDEFINED
+    u'\ufffe'   #  0xDD -> UNDEFINED
+    u'\ufffe'   #  0xDE -> UNDEFINED
+    u'\ufffe'   #  0xDF -> UNDEFINED
+    u'\u05d0'   #  0xE0 -> HEBREW LETTER ALEF
+    u'\u05d1'   #  0xE1 -> HEBREW LETTER BET
+    u'\u05d2'   #  0xE2 -> HEBREW LETTER GIMEL
+    u'\u05d3'   #  0xE3 -> HEBREW LETTER DALET
+    u'\u05d4'   #  0xE4 -> HEBREW LETTER HE
+    u'\u05d5'   #  0xE5 -> HEBREW LETTER VAV
+    u'\u05d6'   #  0xE6 -> HEBREW LETTER ZAYIN
+    u'\u05d7'   #  0xE7 -> HEBREW LETTER HET
+    u'\u05d8'   #  0xE8 -> HEBREW LETTER TET
+    u'\u05d9'   #  0xE9 -> HEBREW LETTER YOD
+    u'\u05da'   #  0xEA -> HEBREW LETTER FINAL KAF
+    u'\u05db'   #  0xEB -> HEBREW LETTER KAF
+    u'\u05dc'   #  0xEC -> HEBREW LETTER LAMED
+    u'\u05dd'   #  0xED -> HEBREW LETTER FINAL MEM
+    u'\u05de'   #  0xEE -> HEBREW LETTER MEM
+    u'\u05df'   #  0xEF -> HEBREW LETTER FINAL NUN
+    u'\u05e0'   #  0xF0 -> HEBREW LETTER NUN
+    u'\u05e1'   #  0xF1 -> HEBREW LETTER SAMEKH
+    u'\u05e2'   #  0xF2 -> HEBREW LETTER AYIN
+    u'\u05e3'   #  0xF3 -> HEBREW LETTER FINAL PE
+    u'\u05e4'   #  0xF4 -> HEBREW LETTER PE
+    u'\u05e5'   #  0xF5 -> HEBREW LETTER FINAL TSADI
+    u'\u05e6'   #  0xF6 -> HEBREW LETTER TSADI
+    u'\u05e7'   #  0xF7 -> HEBREW LETTER QOF
+    u'\u05e8'   #  0xF8 -> HEBREW LETTER RESH
+    u'\u05e9'   #  0xF9 -> HEBREW LETTER SHIN
+    u'\u05ea'   #  0xFA -> HEBREW LETTER TAV
+    u'\ufffe'   #  0xFB -> UNDEFINED
+    u'\ufffe'   #  0xFC -> UNDEFINED
+    u'\u200e'   #  0xFD -> LEFT-TO-RIGHT MARK
+    u'\u200f'   #  0xFE -> RIGHT-TO-LEFT MARK
+    u'\ufffe'   #  0xFF -> UNDEFINED
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1256.py b/src/main/resources/PythonLibs/encodings/cp1256.py
new file mode 100644
index 0000000000000000000000000000000000000000..302b5fa0662a6cda6f165da5ae94067052b71c9f
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1256.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1256 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1256.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1256',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\u067e'   #  0x81 -> ARABIC LETTER PEH
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u0192'   #  0x83 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\u02c6'   #  0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\u0679'   #  0x8A -> ARABIC LETTER TTEH
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u0152'   #  0x8C -> LATIN CAPITAL LIGATURE OE
+    u'\u0686'   #  0x8D -> ARABIC LETTER TCHEH
+    u'\u0698'   #  0x8E -> ARABIC LETTER JEH
+    u'\u0688'   #  0x8F -> ARABIC LETTER DDAL
+    u'\u06af'   #  0x90 -> ARABIC LETTER GAF
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\u06a9'   #  0x98 -> ARABIC LETTER KEHEH
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\u0691'   #  0x9A -> ARABIC LETTER RREH
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\u0153'   #  0x9C -> LATIN SMALL LIGATURE OE
+    u'\u200c'   #  0x9D -> ZERO WIDTH NON-JOINER
+    u'\u200d'   #  0x9E -> ZERO WIDTH JOINER
+    u'\u06ba'   #  0x9F -> ARABIC LETTER NOON GHUNNA
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u060c'   #  0xA1 -> ARABIC COMMA
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u06be'   #  0xAA -> ARABIC LETTER HEH DOACHASHMEE
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\u061b'   #  0xBA -> ARABIC SEMICOLON
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\u061f'   #  0xBF -> ARABIC QUESTION MARK
+    u'\u06c1'   #  0xC0 -> ARABIC LETTER HEH GOAL
+    u'\u0621'   #  0xC1 -> ARABIC LETTER HAMZA
+    u'\u0622'   #  0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE
+    u'\u0623'   #  0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE
+    u'\u0624'   #  0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE
+    u'\u0625'   #  0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW
+    u'\u0626'   #  0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE
+    u'\u0627'   #  0xC7 -> ARABIC LETTER ALEF
+    u'\u0628'   #  0xC8 -> ARABIC LETTER BEH
+    u'\u0629'   #  0xC9 -> ARABIC LETTER TEH MARBUTA
+    u'\u062a'   #  0xCA -> ARABIC LETTER TEH
+    u'\u062b'   #  0xCB -> ARABIC LETTER THEH
+    u'\u062c'   #  0xCC -> ARABIC LETTER JEEM
+    u'\u062d'   #  0xCD -> ARABIC LETTER HAH
+    u'\u062e'   #  0xCE -> ARABIC LETTER KHAH
+    u'\u062f'   #  0xCF -> ARABIC LETTER DAL
+    u'\u0630'   #  0xD0 -> ARABIC LETTER THAL
+    u'\u0631'   #  0xD1 -> ARABIC LETTER REH
+    u'\u0632'   #  0xD2 -> ARABIC LETTER ZAIN
+    u'\u0633'   #  0xD3 -> ARABIC LETTER SEEN
+    u'\u0634'   #  0xD4 -> ARABIC LETTER SHEEN
+    u'\u0635'   #  0xD5 -> ARABIC LETTER SAD
+    u'\u0636'   #  0xD6 -> ARABIC LETTER DAD
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\u0637'   #  0xD8 -> ARABIC LETTER TAH
+    u'\u0638'   #  0xD9 -> ARABIC LETTER ZAH
+    u'\u0639'   #  0xDA -> ARABIC LETTER AIN
+    u'\u063a'   #  0xDB -> ARABIC LETTER GHAIN
+    u'\u0640'   #  0xDC -> ARABIC TATWEEL
+    u'\u0641'   #  0xDD -> ARABIC LETTER FEH
+    u'\u0642'   #  0xDE -> ARABIC LETTER QAF
+    u'\u0643'   #  0xDF -> ARABIC LETTER KAF
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\u0644'   #  0xE1 -> ARABIC LETTER LAM
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\u0645'   #  0xE3 -> ARABIC LETTER MEEM
+    u'\u0646'   #  0xE4 -> ARABIC LETTER NOON
+    u'\u0647'   #  0xE5 -> ARABIC LETTER HEH
+    u'\u0648'   #  0xE6 -> ARABIC LETTER WAW
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\u0649'   #  0xEC -> ARABIC LETTER ALEF MAKSURA
+    u'\u064a'   #  0xED -> ARABIC LETTER YEH
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\u064b'   #  0xF0 -> ARABIC FATHATAN
+    u'\u064c'   #  0xF1 -> ARABIC DAMMATAN
+    u'\u064d'   #  0xF2 -> ARABIC KASRATAN
+    u'\u064e'   #  0xF3 -> ARABIC FATHA
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\u064f'   #  0xF5 -> ARABIC DAMMA
+    u'\u0650'   #  0xF6 -> ARABIC KASRA
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\u0651'   #  0xF8 -> ARABIC SHADDA
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\u0652'   #  0xFA -> ARABIC SUKUN
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u200e'   #  0xFD -> LEFT-TO-RIGHT MARK
+    u'\u200f'   #  0xFE -> RIGHT-TO-LEFT MARK
+    u'\u06d2'   #  0xFF -> ARABIC LETTER YEH BARREE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1257.py b/src/main/resources/PythonLibs/encodings/cp1257.py
new file mode 100644
index 0000000000000000000000000000000000000000..53a6b29d5b00e86798614570d0e4188866f56bab
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1257.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1257 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1257.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1257',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\ufffe'   #  0x81 -> UNDEFINED
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\ufffe'   #  0x83 -> UNDEFINED
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\ufffe'   #  0x88 -> UNDEFINED
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\ufffe'   #  0x8A -> UNDEFINED
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\ufffe'   #  0x8C -> UNDEFINED
+    u'\xa8'     #  0x8D -> DIAERESIS
+    u'\u02c7'   #  0x8E -> CARON
+    u'\xb8'     #  0x8F -> CEDILLA
+    u'\ufffe'   #  0x90 -> UNDEFINED
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\ufffe'   #  0x98 -> UNDEFINED
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\ufffe'   #  0x9A -> UNDEFINED
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\ufffe'   #  0x9C -> UNDEFINED
+    u'\xaf'     #  0x9D -> MACRON
+    u'\u02db'   #  0x9E -> OGONEK
+    u'\ufffe'   #  0x9F -> UNDEFINED
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\ufffe'   #  0xA1 -> UNDEFINED
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\ufffe'   #  0xA5 -> UNDEFINED
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xd8'     #  0xA8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u0156'   #  0xAA -> LATIN CAPITAL LETTER R WITH CEDILLA
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xc6'     #  0xAF -> LATIN CAPITAL LETTER AE
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xf8'     #  0xB8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\u0157'   #  0xBA -> LATIN SMALL LETTER R WITH CEDILLA
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\xe6'     #  0xBF -> LATIN SMALL LETTER AE
+    u'\u0104'   #  0xC0 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\u012e'   #  0xC1 -> LATIN CAPITAL LETTER I WITH OGONEK
+    u'\u0100'   #  0xC2 -> LATIN CAPITAL LETTER A WITH MACRON
+    u'\u0106'   #  0xC3 -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\u0118'   #  0xC6 -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\u0112'   #  0xC7 -> LATIN CAPITAL LETTER E WITH MACRON
+    u'\u010c'   #  0xC8 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\u0179'   #  0xCA -> LATIN CAPITAL LETTER Z WITH ACUTE
+    u'\u0116'   #  0xCB -> LATIN CAPITAL LETTER E WITH DOT ABOVE
+    u'\u0122'   #  0xCC -> LATIN CAPITAL LETTER G WITH CEDILLA
+    u'\u0136'   #  0xCD -> LATIN CAPITAL LETTER K WITH CEDILLA
+    u'\u012a'   #  0xCE -> LATIN CAPITAL LETTER I WITH MACRON
+    u'\u013b'   #  0xCF -> LATIN CAPITAL LETTER L WITH CEDILLA
+    u'\u0160'   #  0xD0 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u0143'   #  0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE
+    u'\u0145'   #  0xD2 -> LATIN CAPITAL LETTER N WITH CEDILLA
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\u014c'   #  0xD4 -> LATIN CAPITAL LETTER O WITH MACRON
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\u0172'   #  0xD8 -> LATIN CAPITAL LETTER U WITH OGONEK
+    u'\u0141'   #  0xD9 -> LATIN CAPITAL LETTER L WITH STROKE
+    u'\u015a'   #  0xDA -> LATIN CAPITAL LETTER S WITH ACUTE
+    u'\u016a'   #  0xDB -> LATIN CAPITAL LETTER U WITH MACRON
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u017b'   #  0xDD -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\u017d'   #  0xDE -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\u0105'   #  0xE0 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u012f'   #  0xE1 -> LATIN SMALL LETTER I WITH OGONEK
+    u'\u0101'   #  0xE2 -> LATIN SMALL LETTER A WITH MACRON
+    u'\u0107'   #  0xE3 -> LATIN SMALL LETTER C WITH ACUTE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\u0119'   #  0xE6 -> LATIN SMALL LETTER E WITH OGONEK
+    u'\u0113'   #  0xE7 -> LATIN SMALL LETTER E WITH MACRON
+    u'\u010d'   #  0xE8 -> LATIN SMALL LETTER C WITH CARON
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\u017a'   #  0xEA -> LATIN SMALL LETTER Z WITH ACUTE
+    u'\u0117'   #  0xEB -> LATIN SMALL LETTER E WITH DOT ABOVE
+    u'\u0123'   #  0xEC -> LATIN SMALL LETTER G WITH CEDILLA
+    u'\u0137'   #  0xED -> LATIN SMALL LETTER K WITH CEDILLA
+    u'\u012b'   #  0xEE -> LATIN SMALL LETTER I WITH MACRON
+    u'\u013c'   #  0xEF -> LATIN SMALL LETTER L WITH CEDILLA
+    u'\u0161'   #  0xF0 -> LATIN SMALL LETTER S WITH CARON
+    u'\u0144'   #  0xF1 -> LATIN SMALL LETTER N WITH ACUTE
+    u'\u0146'   #  0xF2 -> LATIN SMALL LETTER N WITH CEDILLA
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\u014d'   #  0xF4 -> LATIN SMALL LETTER O WITH MACRON
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\u0173'   #  0xF8 -> LATIN SMALL LETTER U WITH OGONEK
+    u'\u0142'   #  0xF9 -> LATIN SMALL LETTER L WITH STROKE
+    u'\u015b'   #  0xFA -> LATIN SMALL LETTER S WITH ACUTE
+    u'\u016b'   #  0xFB -> LATIN SMALL LETTER U WITH MACRON
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u017c'   #  0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\u017e'   #  0xFE -> LATIN SMALL LETTER Z WITH CARON
+    u'\u02d9'   #  0xFF -> DOT ABOVE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp1258.py b/src/main/resources/PythonLibs/encodings/cp1258.py
new file mode 100644
index 0000000000000000000000000000000000000000..4b25d8e7e801e7b8e15c7599da717490f4b6d34b
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp1258.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp1258 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1258.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp1258',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\ufffe'   #  0x81 -> UNDEFINED
+    u'\u201a'   #  0x82 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u0192'   #  0x83 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u201e'   #  0x84 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\u2020'   #  0x86 -> DAGGER
+    u'\u2021'   #  0x87 -> DOUBLE DAGGER
+    u'\u02c6'   #  0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u2030'   #  0x89 -> PER MILLE SIGN
+    u'\ufffe'   #  0x8A -> UNDEFINED
+    u'\u2039'   #  0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u0152'   #  0x8C -> LATIN CAPITAL LIGATURE OE
+    u'\ufffe'   #  0x8D -> UNDEFINED
+    u'\ufffe'   #  0x8E -> UNDEFINED
+    u'\ufffe'   #  0x8F -> UNDEFINED
+    u'\ufffe'   #  0x90 -> UNDEFINED
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\u02dc'   #  0x98 -> SMALL TILDE
+    u'\u2122'   #  0x99 -> TRADE MARK SIGN
+    u'\ufffe'   #  0x9A -> UNDEFINED
+    u'\u203a'   #  0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\u0153'   #  0x9C -> LATIN SMALL LIGATURE OE
+    u'\ufffe'   #  0x9D -> UNDEFINED
+    u'\ufffe'   #  0x9E -> UNDEFINED
+    u'\u0178'   #  0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\xa1'     #  0xA1 -> INVERTED EXCLAMATION MARK
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\xaa'     #  0xAA -> FEMININE ORDINAL INDICATOR
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\xba'     #  0xBA -> MASCULINE ORDINAL INDICATOR
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\xbf'     #  0xBF -> INVERTED QUESTION MARK
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\u0102'   #  0xC3 -> LATIN CAPITAL LETTER A WITH BREVE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\u0300'   #  0xCC -> COMBINING GRAVE ACCENT
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\u0110'   #  0xD0 -> LATIN CAPITAL LETTER D WITH STROKE
+    u'\xd1'     #  0xD1 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\u0309'   #  0xD2 -> COMBINING HOOK ABOVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\u01a0'   #  0xD5 -> LATIN CAPITAL LETTER O WITH HORN
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u01af'   #  0xDD -> LATIN CAPITAL LETTER U WITH HORN
+    u'\u0303'   #  0xDE -> COMBINING TILDE
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\u0103'   #  0xE3 -> LATIN SMALL LETTER A WITH BREVE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\u0301'   #  0xEC -> COMBINING ACUTE ACCENT
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\u0111'   #  0xF0 -> LATIN SMALL LETTER D WITH STROKE
+    u'\xf1'     #  0xF1 -> LATIN SMALL LETTER N WITH TILDE
+    u'\u0323'   #  0xF2 -> COMBINING DOT BELOW
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\u01a1'   #  0xF5 -> LATIN SMALL LETTER O WITH HORN
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u01b0'   #  0xFD -> LATIN SMALL LETTER U WITH HORN
+    u'\u20ab'   #  0xFE -> DONG SIGN
+    u'\xff'     #  0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp424.py b/src/main/resources/PythonLibs/encodings/cp424.py
new file mode 100644
index 0000000000000000000000000000000000000000..d3ade2277687900698f62b2e087f59c064cb9955
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp424.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp424 generated from 'MAPPINGS/VENDORS/MISC/CP424.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp424',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x9c'     #  0x04 -> SELECT
+    u'\t'       #  0x05 -> HORIZONTAL TABULATION
+    u'\x86'     #  0x06 -> REQUIRED NEW LINE
+    u'\x7f'     #  0x07 -> DELETE
+    u'\x97'     #  0x08 -> GRAPHIC ESCAPE
+    u'\x8d'     #  0x09 -> SUPERSCRIPT
+    u'\x8e'     #  0x0A -> REPEAT
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x9d'     #  0x14 -> RESTORE/ENABLE PRESENTATION
+    u'\x85'     #  0x15 -> NEW LINE
+    u'\x08'     #  0x16 -> BACKSPACE
+    u'\x87'     #  0x17 -> PROGRAM OPERATOR COMMUNICATION
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x92'     #  0x1A -> UNIT BACK SPACE
+    u'\x8f'     #  0x1B -> CUSTOMER USE ONE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u'\x80'     #  0x20 -> DIGIT SELECT
+    u'\x81'     #  0x21 -> START OF SIGNIFICANCE
+    u'\x82'     #  0x22 -> FIELD SEPARATOR
+    u'\x83'     #  0x23 -> WORD UNDERSCORE
+    u'\x84'     #  0x24 -> BYPASS OR INHIBIT PRESENTATION
+    u'\n'       #  0x25 -> LINE FEED
+    u'\x17'     #  0x26 -> END OF TRANSMISSION BLOCK
+    u'\x1b'     #  0x27 -> ESCAPE
+    u'\x88'     #  0x28 -> SET ATTRIBUTE
+    u'\x89'     #  0x29 -> START FIELD EXTENDED
+    u'\x8a'     #  0x2A -> SET MODE OR SWITCH
+    u'\x8b'     #  0x2B -> CONTROL SEQUENCE PREFIX
+    u'\x8c'     #  0x2C -> MODIFY FIELD ATTRIBUTE
+    u'\x05'     #  0x2D -> ENQUIRY
+    u'\x06'     #  0x2E -> ACKNOWLEDGE
+    u'\x07'     #  0x2F -> BELL
+    u'\x90'     #  0x30 -> <reserved>
+    u'\x91'     #  0x31 -> <reserved>
+    u'\x16'     #  0x32 -> SYNCHRONOUS IDLE
+    u'\x93'     #  0x33 -> INDEX RETURN
+    u'\x94'     #  0x34 -> PRESENTATION POSITION
+    u'\x95'     #  0x35 -> TRANSPARENT
+    u'\x96'     #  0x36 -> NUMERIC BACKSPACE
+    u'\x04'     #  0x37 -> END OF TRANSMISSION
+    u'\x98'     #  0x38 -> SUBSCRIPT
+    u'\x99'     #  0x39 -> INDENT TABULATION
+    u'\x9a'     #  0x3A -> REVERSE FORM FEED
+    u'\x9b'     #  0x3B -> CUSTOMER USE THREE
+    u'\x14'     #  0x3C -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x3D -> NEGATIVE ACKNOWLEDGE
+    u'\x9e'     #  0x3E -> <reserved>
+    u'\x1a'     #  0x3F -> SUBSTITUTE
+    u' '        #  0x40 -> SPACE
+    u'\u05d0'   #  0x41 -> HEBREW LETTER ALEF
+    u'\u05d1'   #  0x42 -> HEBREW LETTER BET
+    u'\u05d2'   #  0x43 -> HEBREW LETTER GIMEL
+    u'\u05d3'   #  0x44 -> HEBREW LETTER DALET
+    u'\u05d4'   #  0x45 -> HEBREW LETTER HE
+    u'\u05d5'   #  0x46 -> HEBREW LETTER VAV
+    u'\u05d6'   #  0x47 -> HEBREW LETTER ZAYIN
+    u'\u05d7'   #  0x48 -> HEBREW LETTER HET
+    u'\u05d8'   #  0x49 -> HEBREW LETTER TET
+    u'\xa2'     #  0x4A -> CENT SIGN
+    u'.'        #  0x4B -> FULL STOP
+    u'<'        #  0x4C -> LESS-THAN SIGN
+    u'('        #  0x4D -> LEFT PARENTHESIS
+    u'+'        #  0x4E -> PLUS SIGN
+    u'|'        #  0x4F -> VERTICAL LINE
+    u'&'        #  0x50 -> AMPERSAND
+    u'\u05d9'   #  0x51 -> HEBREW LETTER YOD
+    u'\u05da'   #  0x52 -> HEBREW LETTER FINAL KAF
+    u'\u05db'   #  0x53 -> HEBREW LETTER KAF
+    u'\u05dc'   #  0x54 -> HEBREW LETTER LAMED
+    u'\u05dd'   #  0x55 -> HEBREW LETTER FINAL MEM
+    u'\u05de'   #  0x56 -> HEBREW LETTER MEM
+    u'\u05df'   #  0x57 -> HEBREW LETTER FINAL NUN
+    u'\u05e0'   #  0x58 -> HEBREW LETTER NUN
+    u'\u05e1'   #  0x59 -> HEBREW LETTER SAMEKH
+    u'!'        #  0x5A -> EXCLAMATION MARK
+    u'$'        #  0x5B -> DOLLAR SIGN
+    u'*'        #  0x5C -> ASTERISK
+    u')'        #  0x5D -> RIGHT PARENTHESIS
+    u';'        #  0x5E -> SEMICOLON
+    u'\xac'     #  0x5F -> NOT SIGN
+    u'-'        #  0x60 -> HYPHEN-MINUS
+    u'/'        #  0x61 -> SOLIDUS
+    u'\u05e2'   #  0x62 -> HEBREW LETTER AYIN
+    u'\u05e3'   #  0x63 -> HEBREW LETTER FINAL PE
+    u'\u05e4'   #  0x64 -> HEBREW LETTER PE
+    u'\u05e5'   #  0x65 -> HEBREW LETTER FINAL TSADI
+    u'\u05e6'   #  0x66 -> HEBREW LETTER TSADI
+    u'\u05e7'   #  0x67 -> HEBREW LETTER QOF
+    u'\u05e8'   #  0x68 -> HEBREW LETTER RESH
+    u'\u05e9'   #  0x69 -> HEBREW LETTER SHIN
+    u'\xa6'     #  0x6A -> BROKEN BAR
+    u','        #  0x6B -> COMMA
+    u'%'        #  0x6C -> PERCENT SIGN
+    u'_'        #  0x6D -> LOW LINE
+    u'>'        #  0x6E -> GREATER-THAN SIGN
+    u'?'        #  0x6F -> QUESTION MARK
+    u'\ufffe'   #  0x70 -> UNDEFINED
+    u'\u05ea'   #  0x71 -> HEBREW LETTER TAV
+    u'\ufffe'   #  0x72 -> UNDEFINED
+    u'\ufffe'   #  0x73 -> UNDEFINED
+    u'\xa0'     #  0x74 -> NO-BREAK SPACE
+    u'\ufffe'   #  0x75 -> UNDEFINED
+    u'\ufffe'   #  0x76 -> UNDEFINED
+    u'\ufffe'   #  0x77 -> UNDEFINED
+    u'\u2017'   #  0x78 -> DOUBLE LOW LINE
+    u'`'        #  0x79 -> GRAVE ACCENT
+    u':'        #  0x7A -> COLON
+    u'#'        #  0x7B -> NUMBER SIGN
+    u'@'        #  0x7C -> COMMERCIAL AT
+    u"'"        #  0x7D -> APOSTROPHE
+    u'='        #  0x7E -> EQUALS SIGN
+    u'"'        #  0x7F -> QUOTATION MARK
+    u'\ufffe'   #  0x80 -> UNDEFINED
+    u'a'        #  0x81 -> LATIN SMALL LETTER A
+    u'b'        #  0x82 -> LATIN SMALL LETTER B
+    u'c'        #  0x83 -> LATIN SMALL LETTER C
+    u'd'        #  0x84 -> LATIN SMALL LETTER D
+    u'e'        #  0x85 -> LATIN SMALL LETTER E
+    u'f'        #  0x86 -> LATIN SMALL LETTER F
+    u'g'        #  0x87 -> LATIN SMALL LETTER G
+    u'h'        #  0x88 -> LATIN SMALL LETTER H
+    u'i'        #  0x89 -> LATIN SMALL LETTER I
+    u'\xab'     #  0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\ufffe'   #  0x8C -> UNDEFINED
+    u'\ufffe'   #  0x8D -> UNDEFINED
+    u'\ufffe'   #  0x8E -> UNDEFINED
+    u'\xb1'     #  0x8F -> PLUS-MINUS SIGN
+    u'\xb0'     #  0x90 -> DEGREE SIGN
+    u'j'        #  0x91 -> LATIN SMALL LETTER J
+    u'k'        #  0x92 -> LATIN SMALL LETTER K
+    u'l'        #  0x93 -> LATIN SMALL LETTER L
+    u'm'        #  0x94 -> LATIN SMALL LETTER M
+    u'n'        #  0x95 -> LATIN SMALL LETTER N
+    u'o'        #  0x96 -> LATIN SMALL LETTER O
+    u'p'        #  0x97 -> LATIN SMALL LETTER P
+    u'q'        #  0x98 -> LATIN SMALL LETTER Q
+    u'r'        #  0x99 -> LATIN SMALL LETTER R
+    u'\ufffe'   #  0x9A -> UNDEFINED
+    u'\ufffe'   #  0x9B -> UNDEFINED
+    u'\ufffe'   #  0x9C -> UNDEFINED
+    u'\xb8'     #  0x9D -> CEDILLA
+    u'\ufffe'   #  0x9E -> UNDEFINED
+    u'\xa4'     #  0x9F -> CURRENCY SIGN
+    u'\xb5'     #  0xA0 -> MICRO SIGN
+    u'~'        #  0xA1 -> TILDE
+    u's'        #  0xA2 -> LATIN SMALL LETTER S
+    u't'        #  0xA3 -> LATIN SMALL LETTER T
+    u'u'        #  0xA4 -> LATIN SMALL LETTER U
+    u'v'        #  0xA5 -> LATIN SMALL LETTER V
+    u'w'        #  0xA6 -> LATIN SMALL LETTER W
+    u'x'        #  0xA7 -> LATIN SMALL LETTER X
+    u'y'        #  0xA8 -> LATIN SMALL LETTER Y
+    u'z'        #  0xA9 -> LATIN SMALL LETTER Z
+    u'\ufffe'   #  0xAA -> UNDEFINED
+    u'\ufffe'   #  0xAB -> UNDEFINED
+    u'\ufffe'   #  0xAC -> UNDEFINED
+    u'\ufffe'   #  0xAD -> UNDEFINED
+    u'\ufffe'   #  0xAE -> UNDEFINED
+    u'\xae'     #  0xAF -> REGISTERED SIGN
+    u'^'        #  0xB0 -> CIRCUMFLEX ACCENT
+    u'\xa3'     #  0xB1 -> POUND SIGN
+    u'\xa5'     #  0xB2 -> YEN SIGN
+    u'\xb7'     #  0xB3 -> MIDDLE DOT
+    u'\xa9'     #  0xB4 -> COPYRIGHT SIGN
+    u'\xa7'     #  0xB5 -> SECTION SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xbc'     #  0xB7 -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xB8 -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xB9 -> VULGAR FRACTION THREE QUARTERS
+    u'['        #  0xBA -> LEFT SQUARE BRACKET
+    u']'        #  0xBB -> RIGHT SQUARE BRACKET
+    u'\xaf'     #  0xBC -> MACRON
+    u'\xa8'     #  0xBD -> DIAERESIS
+    u'\xb4'     #  0xBE -> ACUTE ACCENT
+    u'\xd7'     #  0xBF -> MULTIPLICATION SIGN
+    u'{'        #  0xC0 -> LEFT CURLY BRACKET
+    u'A'        #  0xC1 -> LATIN CAPITAL LETTER A
+    u'B'        #  0xC2 -> LATIN CAPITAL LETTER B
+    u'C'        #  0xC3 -> LATIN CAPITAL LETTER C
+    u'D'        #  0xC4 -> LATIN CAPITAL LETTER D
+    u'E'        #  0xC5 -> LATIN CAPITAL LETTER E
+    u'F'        #  0xC6 -> LATIN CAPITAL LETTER F
+    u'G'        #  0xC7 -> LATIN CAPITAL LETTER G
+    u'H'        #  0xC8 -> LATIN CAPITAL LETTER H
+    u'I'        #  0xC9 -> LATIN CAPITAL LETTER I
+    u'\xad'     #  0xCA -> SOFT HYPHEN
+    u'\ufffe'   #  0xCB -> UNDEFINED
+    u'\ufffe'   #  0xCC -> UNDEFINED
+    u'\ufffe'   #  0xCD -> UNDEFINED
+    u'\ufffe'   #  0xCE -> UNDEFINED
+    u'\ufffe'   #  0xCF -> UNDEFINED
+    u'}'        #  0xD0 -> RIGHT CURLY BRACKET
+    u'J'        #  0xD1 -> LATIN CAPITAL LETTER J
+    u'K'        #  0xD2 -> LATIN CAPITAL LETTER K
+    u'L'        #  0xD3 -> LATIN CAPITAL LETTER L
+    u'M'        #  0xD4 -> LATIN CAPITAL LETTER M
+    u'N'        #  0xD5 -> LATIN CAPITAL LETTER N
+    u'O'        #  0xD6 -> LATIN CAPITAL LETTER O
+    u'P'        #  0xD7 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0xD8 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0xD9 -> LATIN CAPITAL LETTER R
+    u'\xb9'     #  0xDA -> SUPERSCRIPT ONE
+    u'\ufffe'   #  0xDB -> UNDEFINED
+    u'\ufffe'   #  0xDC -> UNDEFINED
+    u'\ufffe'   #  0xDD -> UNDEFINED
+    u'\ufffe'   #  0xDE -> UNDEFINED
+    u'\ufffe'   #  0xDF -> UNDEFINED
+    u'\\'       #  0xE0 -> REVERSE SOLIDUS
+    u'\xf7'     #  0xE1 -> DIVISION SIGN
+    u'S'        #  0xE2 -> LATIN CAPITAL LETTER S
+    u'T'        #  0xE3 -> LATIN CAPITAL LETTER T
+    u'U'        #  0xE4 -> LATIN CAPITAL LETTER U
+    u'V'        #  0xE5 -> LATIN CAPITAL LETTER V
+    u'W'        #  0xE6 -> LATIN CAPITAL LETTER W
+    u'X'        #  0xE7 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0xE8 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0xE9 -> LATIN CAPITAL LETTER Z
+    u'\xb2'     #  0xEA -> SUPERSCRIPT TWO
+    u'\ufffe'   #  0xEB -> UNDEFINED
+    u'\ufffe'   #  0xEC -> UNDEFINED
+    u'\ufffe'   #  0xED -> UNDEFINED
+    u'\ufffe'   #  0xEE -> UNDEFINED
+    u'\ufffe'   #  0xEF -> UNDEFINED
+    u'0'        #  0xF0 -> DIGIT ZERO
+    u'1'        #  0xF1 -> DIGIT ONE
+    u'2'        #  0xF2 -> DIGIT TWO
+    u'3'        #  0xF3 -> DIGIT THREE
+    u'4'        #  0xF4 -> DIGIT FOUR
+    u'5'        #  0xF5 -> DIGIT FIVE
+    u'6'        #  0xF6 -> DIGIT SIX
+    u'7'        #  0xF7 -> DIGIT SEVEN
+    u'8'        #  0xF8 -> DIGIT EIGHT
+    u'9'        #  0xF9 -> DIGIT NINE
+    u'\xb3'     #  0xFA -> SUPERSCRIPT THREE
+    u'\ufffe'   #  0xFB -> UNDEFINED
+    u'\ufffe'   #  0xFC -> UNDEFINED
+    u'\ufffe'   #  0xFD -> UNDEFINED
+    u'\ufffe'   #  0xFE -> UNDEFINED
+    u'\x9f'     #  0xFF -> EIGHT ONES
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp437.py b/src/main/resources/PythonLibs/encodings/cp437.py
new file mode 100644
index 0000000000000000000000000000000000000000..52cd8829428cbb923f10403b5a02c40b7cc2bb85
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp437.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec cp437 generated from 'VENDORS/MICSFT/PC/CP437.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp437',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x0085: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0086: 0x00e5,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0089: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x008a: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x008b: 0x00ef,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x008c: 0x00ee,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x008d: 0x00ec,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x008e: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x008f: 0x00c5,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00e6,     #  LATIN SMALL LIGATURE AE
+    0x0092: 0x00c6,     #  LATIN CAPITAL LIGATURE AE
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x0095: 0x00f2,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x0096: 0x00fb,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x0097: 0x00f9,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x0098: 0x00ff,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x0099: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00a2,     #  CENT SIGN
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00a5,     #  YEN SIGN
+    0x009e: 0x20a7,     #  PESETA SIGN
+    0x009f: 0x0192,     #  LATIN SMALL LETTER F WITH HOOK
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00f1,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00a5: 0x00d1,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00a6: 0x00aa,     #  FEMININE ORDINAL INDICATOR
+    0x00a7: 0x00ba,     #  MASCULINE ORDINAL INDICATOR
+    0x00a8: 0x00bf,     #  INVERTED QUESTION MARK
+    0x00a9: 0x2310,     #  REVERSED NOT SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00a1,     #  INVERTED EXCLAMATION MARK
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x2561,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x00b6: 0x2562,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x00b7: 0x2556,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x00b8: 0x2555,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x255c,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x00be: 0x255b,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x255e,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x00c7: 0x255f,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x2567,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x00d0: 0x2568,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x00d1: 0x2564,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x00d2: 0x2565,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x00d3: 0x2559,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x00d4: 0x2558,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x00d5: 0x2552,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x00d6: 0x2553,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x00d7: 0x256b,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x00d8: 0x256a,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x03b1,     #  GREEK SMALL LETTER ALPHA
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x0393,     #  GREEK CAPITAL LETTER GAMMA
+    0x00e3: 0x03c0,     #  GREEK SMALL LETTER PI
+    0x00e4: 0x03a3,     #  GREEK CAPITAL LETTER SIGMA
+    0x00e5: 0x03c3,     #  GREEK SMALL LETTER SIGMA
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x03c4,     #  GREEK SMALL LETTER TAU
+    0x00e8: 0x03a6,     #  GREEK CAPITAL LETTER PHI
+    0x00e9: 0x0398,     #  GREEK CAPITAL LETTER THETA
+    0x00ea: 0x03a9,     #  GREEK CAPITAL LETTER OMEGA
+    0x00eb: 0x03b4,     #  GREEK SMALL LETTER DELTA
+    0x00ec: 0x221e,     #  INFINITY
+    0x00ed: 0x03c6,     #  GREEK SMALL LETTER PHI
+    0x00ee: 0x03b5,     #  GREEK SMALL LETTER EPSILON
+    0x00ef: 0x2229,     #  INTERSECTION
+    0x00f0: 0x2261,     #  IDENTICAL TO
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2265,     #  GREATER-THAN OR EQUAL TO
+    0x00f3: 0x2264,     #  LESS-THAN OR EQUAL TO
+    0x00f4: 0x2320,     #  TOP HALF INTEGRAL
+    0x00f5: 0x2321,     #  BOTTOM HALF INTEGRAL
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x2248,     #  ALMOST EQUAL TO
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x221a,     #  SQUARE ROOT
+    0x00fc: 0x207f,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x0085 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe5'     #  0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x008a -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xef'     #  0x008b -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xee'     #  0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xec'     #  0x008d -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xc4'     #  0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xe6'     #  0x0091 -> LATIN SMALL LIGATURE AE
+    u'\xc6'     #  0x0092 -> LATIN CAPITAL LIGATURE AE
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf2'     #  0x0095 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xfb'     #  0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xf9'     #  0x0097 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xff'     #  0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\xd6'     #  0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xa2'     #  0x009b -> CENT SIGN
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xa5'     #  0x009d -> YEN SIGN
+    u'\u20a7'   #  0x009e -> PESETA SIGN
+    u'\u0192'   #  0x009f -> LATIN SMALL LETTER F WITH HOOK
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf1'     #  0x00a4 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xd1'     #  0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xaa'     #  0x00a6 -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x00a7 -> MASCULINE ORDINAL INDICATOR
+    u'\xbf'     #  0x00a8 -> INVERTED QUESTION MARK
+    u'\u2310'   #  0x00a9 -> REVERSED NOT SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xa1'     #  0x00ad -> INVERTED EXCLAMATION MARK
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u03b1'   #  0x00e0 -> GREEK SMALL LETTER ALPHA
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\u0393'   #  0x00e2 -> GREEK CAPITAL LETTER GAMMA
+    u'\u03c0'   #  0x00e3 -> GREEK SMALL LETTER PI
+    u'\u03a3'   #  0x00e4 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03c3'   #  0x00e5 -> GREEK SMALL LETTER SIGMA
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\u03c4'   #  0x00e7 -> GREEK SMALL LETTER TAU
+    u'\u03a6'   #  0x00e8 -> GREEK CAPITAL LETTER PHI
+    u'\u0398'   #  0x00e9 -> GREEK CAPITAL LETTER THETA
+    u'\u03a9'   #  0x00ea -> GREEK CAPITAL LETTER OMEGA
+    u'\u03b4'   #  0x00eb -> GREEK SMALL LETTER DELTA
+    u'\u221e'   #  0x00ec -> INFINITY
+    u'\u03c6'   #  0x00ed -> GREEK SMALL LETTER PHI
+    u'\u03b5'   #  0x00ee -> GREEK SMALL LETTER EPSILON
+    u'\u2229'   #  0x00ef -> INTERSECTION
+    u'\u2261'   #  0x00f0 -> IDENTICAL TO
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2265'   #  0x00f2 -> GREATER-THAN OR EQUAL TO
+    u'\u2264'   #  0x00f3 -> LESS-THAN OR EQUAL TO
+    u'\u2320'   #  0x00f4 -> TOP HALF INTEGRAL
+    u'\u2321'   #  0x00f5 -> BOTTOM HALF INTEGRAL
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\u2248'   #  0x00f7 -> ALMOST EQUAL TO
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\u221a'   #  0x00fb -> SQUARE ROOT
+    u'\u207f'   #  0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a1: 0x00ad,     #  INVERTED EXCLAMATION MARK
+    0x00a2: 0x009b,     #  CENT SIGN
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a5: 0x009d,     #  YEN SIGN
+    0x00aa: 0x00a6,     #  FEMININE ORDINAL INDICATOR
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00ba: 0x00a7,     #  MASCULINE ORDINAL INDICATOR
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00bf: 0x00a8,     #  INVERTED QUESTION MARK
+    0x00c4: 0x008e,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c5: 0x008f,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x00c6: 0x0092,     #  LATIN CAPITAL LIGATURE AE
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00d1: 0x00a5,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00d6: 0x0099,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e0: 0x0085,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e4: 0x0084,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e5: 0x0086,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x00e6: 0x0091,     #  LATIN SMALL LIGATURE AE
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008a,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0088,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00eb: 0x0089,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ec: 0x008d,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00ee: 0x008c,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x00ef: 0x008b,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x00f1: 0x00a4,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00f2: 0x0095,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f6: 0x0094,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f9: 0x0097,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fb: 0x0096,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x00ff: 0x0098,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x0192: 0x009f,     #  LATIN SMALL LETTER F WITH HOOK
+    0x0393: 0x00e2,     #  GREEK CAPITAL LETTER GAMMA
+    0x0398: 0x00e9,     #  GREEK CAPITAL LETTER THETA
+    0x03a3: 0x00e4,     #  GREEK CAPITAL LETTER SIGMA
+    0x03a6: 0x00e8,     #  GREEK CAPITAL LETTER PHI
+    0x03a9: 0x00ea,     #  GREEK CAPITAL LETTER OMEGA
+    0x03b1: 0x00e0,     #  GREEK SMALL LETTER ALPHA
+    0x03b4: 0x00eb,     #  GREEK SMALL LETTER DELTA
+    0x03b5: 0x00ee,     #  GREEK SMALL LETTER EPSILON
+    0x03c0: 0x00e3,     #  GREEK SMALL LETTER PI
+    0x03c3: 0x00e5,     #  GREEK SMALL LETTER SIGMA
+    0x03c4: 0x00e7,     #  GREEK SMALL LETTER TAU
+    0x03c6: 0x00ed,     #  GREEK SMALL LETTER PHI
+    0x207f: 0x00fc,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x20a7: 0x009e,     #  PESETA SIGN
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x221a: 0x00fb,     #  SQUARE ROOT
+    0x221e: 0x00ec,     #  INFINITY
+    0x2229: 0x00ef,     #  INTERSECTION
+    0x2248: 0x00f7,     #  ALMOST EQUAL TO
+    0x2261: 0x00f0,     #  IDENTICAL TO
+    0x2264: 0x00f3,     #  LESS-THAN OR EQUAL TO
+    0x2265: 0x00f2,     #  GREATER-THAN OR EQUAL TO
+    0x2310: 0x00a9,     #  REVERSED NOT SIGN
+    0x2320: 0x00f4,     #  TOP HALF INTEGRAL
+    0x2321: 0x00f5,     #  BOTTOM HALF INTEGRAL
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2552: 0x00d5,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x2553: 0x00d6,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2555: 0x00b8,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x2556: 0x00b7,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x2558: 0x00d4,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x2559: 0x00d3,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255b: 0x00be,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x255c: 0x00bd,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x255e: 0x00c6,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x255f: 0x00c7,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2561: 0x00b5,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x2562: 0x00b6,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2564: 0x00d1,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x2565: 0x00d2,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2567: 0x00cf,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x2568: 0x00d0,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256a: 0x00d8,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x256b: 0x00d7,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp500.py b/src/main/resources/PythonLibs/encodings/cp500.py
new file mode 100644
index 0000000000000000000000000000000000000000..60766c0393b4047f44d8d174d74b0a547007d72d
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp500.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp500 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP500.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp500',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x9c'     #  0x04 -> CONTROL
+    u'\t'       #  0x05 -> HORIZONTAL TABULATION
+    u'\x86'     #  0x06 -> CONTROL
+    u'\x7f'     #  0x07 -> DELETE
+    u'\x97'     #  0x08 -> CONTROL
+    u'\x8d'     #  0x09 -> CONTROL
+    u'\x8e'     #  0x0A -> CONTROL
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x9d'     #  0x14 -> CONTROL
+    u'\x85'     #  0x15 -> CONTROL
+    u'\x08'     #  0x16 -> BACKSPACE
+    u'\x87'     #  0x17 -> CONTROL
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x92'     #  0x1A -> CONTROL
+    u'\x8f'     #  0x1B -> CONTROL
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u'\x80'     #  0x20 -> CONTROL
+    u'\x81'     #  0x21 -> CONTROL
+    u'\x82'     #  0x22 -> CONTROL
+    u'\x83'     #  0x23 -> CONTROL
+    u'\x84'     #  0x24 -> CONTROL
+    u'\n'       #  0x25 -> LINE FEED
+    u'\x17'     #  0x26 -> END OF TRANSMISSION BLOCK
+    u'\x1b'     #  0x27 -> ESCAPE
+    u'\x88'     #  0x28 -> CONTROL
+    u'\x89'     #  0x29 -> CONTROL
+    u'\x8a'     #  0x2A -> CONTROL
+    u'\x8b'     #  0x2B -> CONTROL
+    u'\x8c'     #  0x2C -> CONTROL
+    u'\x05'     #  0x2D -> ENQUIRY
+    u'\x06'     #  0x2E -> ACKNOWLEDGE
+    u'\x07'     #  0x2F -> BELL
+    u'\x90'     #  0x30 -> CONTROL
+    u'\x91'     #  0x31 -> CONTROL
+    u'\x16'     #  0x32 -> SYNCHRONOUS IDLE
+    u'\x93'     #  0x33 -> CONTROL
+    u'\x94'     #  0x34 -> CONTROL
+    u'\x95'     #  0x35 -> CONTROL
+    u'\x96'     #  0x36 -> CONTROL
+    u'\x04'     #  0x37 -> END OF TRANSMISSION
+    u'\x98'     #  0x38 -> CONTROL
+    u'\x99'     #  0x39 -> CONTROL
+    u'\x9a'     #  0x3A -> CONTROL
+    u'\x9b'     #  0x3B -> CONTROL
+    u'\x14'     #  0x3C -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x3D -> NEGATIVE ACKNOWLEDGE
+    u'\x9e'     #  0x3E -> CONTROL
+    u'\x1a'     #  0x3F -> SUBSTITUTE
+    u' '        #  0x40 -> SPACE
+    u'\xa0'     #  0x41 -> NO-BREAK SPACE
+    u'\xe2'     #  0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x43 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x44 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0x45 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe3'     #  0x46 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x47 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x48 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xf1'     #  0x49 -> LATIN SMALL LETTER N WITH TILDE
+    u'['        #  0x4A -> LEFT SQUARE BRACKET
+    u'.'        #  0x4B -> FULL STOP
+    u'<'        #  0x4C -> LESS-THAN SIGN
+    u'('        #  0x4D -> LEFT PARENTHESIS
+    u'+'        #  0x4E -> PLUS SIGN
+    u'!'        #  0x4F -> EXCLAMATION MARK
+    u'&'        #  0x50 -> AMPERSAND
+    u'\xe9'     #  0x51 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x53 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x54 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xed'     #  0x55 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x57 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xec'     #  0x58 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xdf'     #  0x59 -> LATIN SMALL LETTER SHARP S (GERMAN)
+    u']'        #  0x5A -> RIGHT SQUARE BRACKET
+    u'$'        #  0x5B -> DOLLAR SIGN
+    u'*'        #  0x5C -> ASTERISK
+    u')'        #  0x5D -> RIGHT PARENTHESIS
+    u';'        #  0x5E -> SEMICOLON
+    u'^'        #  0x5F -> CIRCUMFLEX ACCENT
+    u'-'        #  0x60 -> HYPHEN-MINUS
+    u'/'        #  0x61 -> SOLIDUS
+    u'\xc2'     #  0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc4'     #  0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc0'     #  0x64 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0x65 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc3'     #  0x66 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc5'     #  0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc7'     #  0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xd1'     #  0x69 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xa6'     #  0x6A -> BROKEN BAR
+    u','        #  0x6B -> COMMA
+    u'%'        #  0x6C -> PERCENT SIGN
+    u'_'        #  0x6D -> LOW LINE
+    u'>'        #  0x6E -> GREATER-THAN SIGN
+    u'?'        #  0x6F -> QUESTION MARK
+    u'\xf8'     #  0x70 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xc9'     #  0x71 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0x74 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0x75 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0x78 -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'`'        #  0x79 -> GRAVE ACCENT
+    u':'        #  0x7A -> COLON
+    u'#'        #  0x7B -> NUMBER SIGN
+    u'@'        #  0x7C -> COMMERCIAL AT
+    u"'"        #  0x7D -> APOSTROPHE
+    u'='        #  0x7E -> EQUALS SIGN
+    u'"'        #  0x7F -> QUOTATION MARK
+    u'\xd8'     #  0x80 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'a'        #  0x81 -> LATIN SMALL LETTER A
+    u'b'        #  0x82 -> LATIN SMALL LETTER B
+    u'c'        #  0x83 -> LATIN SMALL LETTER C
+    u'd'        #  0x84 -> LATIN SMALL LETTER D
+    u'e'        #  0x85 -> LATIN SMALL LETTER E
+    u'f'        #  0x86 -> LATIN SMALL LETTER F
+    u'g'        #  0x87 -> LATIN SMALL LETTER G
+    u'h'        #  0x88 -> LATIN SMALL LETTER H
+    u'i'        #  0x89 -> LATIN SMALL LETTER I
+    u'\xab'     #  0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xf0'     #  0x8C -> LATIN SMALL LETTER ETH (ICELANDIC)
+    u'\xfd'     #  0x8D -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xfe'     #  0x8E -> LATIN SMALL LETTER THORN (ICELANDIC)
+    u'\xb1'     #  0x8F -> PLUS-MINUS SIGN
+    u'\xb0'     #  0x90 -> DEGREE SIGN
+    u'j'        #  0x91 -> LATIN SMALL LETTER J
+    u'k'        #  0x92 -> LATIN SMALL LETTER K
+    u'l'        #  0x93 -> LATIN SMALL LETTER L
+    u'm'        #  0x94 -> LATIN SMALL LETTER M
+    u'n'        #  0x95 -> LATIN SMALL LETTER N
+    u'o'        #  0x96 -> LATIN SMALL LETTER O
+    u'p'        #  0x97 -> LATIN SMALL LETTER P
+    u'q'        #  0x98 -> LATIN SMALL LETTER Q
+    u'r'        #  0x99 -> LATIN SMALL LETTER R
+    u'\xaa'     #  0x9A -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x9B -> MASCULINE ORDINAL INDICATOR
+    u'\xe6'     #  0x9C -> LATIN SMALL LIGATURE AE
+    u'\xb8'     #  0x9D -> CEDILLA
+    u'\xc6'     #  0x9E -> LATIN CAPITAL LIGATURE AE
+    u'\xa4'     #  0x9F -> CURRENCY SIGN
+    u'\xb5'     #  0xA0 -> MICRO SIGN
+    u'~'        #  0xA1 -> TILDE
+    u's'        #  0xA2 -> LATIN SMALL LETTER S
+    u't'        #  0xA3 -> LATIN SMALL LETTER T
+    u'u'        #  0xA4 -> LATIN SMALL LETTER U
+    u'v'        #  0xA5 -> LATIN SMALL LETTER V
+    u'w'        #  0xA6 -> LATIN SMALL LETTER W
+    u'x'        #  0xA7 -> LATIN SMALL LETTER X
+    u'y'        #  0xA8 -> LATIN SMALL LETTER Y
+    u'z'        #  0xA9 -> LATIN SMALL LETTER Z
+    u'\xa1'     #  0xAA -> INVERTED EXCLAMATION MARK
+    u'\xbf'     #  0xAB -> INVERTED QUESTION MARK
+    u'\xd0'     #  0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC)
+    u'\xdd'     #  0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xde'     #  0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC)
+    u'\xae'     #  0xAF -> REGISTERED SIGN
+    u'\xa2'     #  0xB0 -> CENT SIGN
+    u'\xa3'     #  0xB1 -> POUND SIGN
+    u'\xa5'     #  0xB2 -> YEN SIGN
+    u'\xb7'     #  0xB3 -> MIDDLE DOT
+    u'\xa9'     #  0xB4 -> COPYRIGHT SIGN
+    u'\xa7'     #  0xB5 -> SECTION SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xbc'     #  0xB7 -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xB8 -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xB9 -> VULGAR FRACTION THREE QUARTERS
+    u'\xac'     #  0xBA -> NOT SIGN
+    u'|'        #  0xBB -> VERTICAL LINE
+    u'\xaf'     #  0xBC -> MACRON
+    u'\xa8'     #  0xBD -> DIAERESIS
+    u'\xb4'     #  0xBE -> ACUTE ACCENT
+    u'\xd7'     #  0xBF -> MULTIPLICATION SIGN
+    u'{'        #  0xC0 -> LEFT CURLY BRACKET
+    u'A'        #  0xC1 -> LATIN CAPITAL LETTER A
+    u'B'        #  0xC2 -> LATIN CAPITAL LETTER B
+    u'C'        #  0xC3 -> LATIN CAPITAL LETTER C
+    u'D'        #  0xC4 -> LATIN CAPITAL LETTER D
+    u'E'        #  0xC5 -> LATIN CAPITAL LETTER E
+    u'F'        #  0xC6 -> LATIN CAPITAL LETTER F
+    u'G'        #  0xC7 -> LATIN CAPITAL LETTER G
+    u'H'        #  0xC8 -> LATIN CAPITAL LETTER H
+    u'I'        #  0xC9 -> LATIN CAPITAL LETTER I
+    u'\xad'     #  0xCA -> SOFT HYPHEN
+    u'\xf4'     #  0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0xCC -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf2'     #  0xCD -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xCE -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf5'     #  0xCF -> LATIN SMALL LETTER O WITH TILDE
+    u'}'        #  0xD0 -> RIGHT CURLY BRACKET
+    u'J'        #  0xD1 -> LATIN CAPITAL LETTER J
+    u'K'        #  0xD2 -> LATIN CAPITAL LETTER K
+    u'L'        #  0xD3 -> LATIN CAPITAL LETTER L
+    u'M'        #  0xD4 -> LATIN CAPITAL LETTER M
+    u'N'        #  0xD5 -> LATIN CAPITAL LETTER N
+    u'O'        #  0xD6 -> LATIN CAPITAL LETTER O
+    u'P'        #  0xD7 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0xD8 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0xD9 -> LATIN CAPITAL LETTER R
+    u'\xb9'     #  0xDA -> SUPERSCRIPT ONE
+    u'\xfb'     #  0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xDC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xf9'     #  0xDD -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xDE -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xff'     #  0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\\'       #  0xE0 -> REVERSE SOLIDUS
+    u'\xf7'     #  0xE1 -> DIVISION SIGN
+    u'S'        #  0xE2 -> LATIN CAPITAL LETTER S
+    u'T'        #  0xE3 -> LATIN CAPITAL LETTER T
+    u'U'        #  0xE4 -> LATIN CAPITAL LETTER U
+    u'V'        #  0xE5 -> LATIN CAPITAL LETTER V
+    u'W'        #  0xE6 -> LATIN CAPITAL LETTER W
+    u'X'        #  0xE7 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0xE8 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0xE9 -> LATIN CAPITAL LETTER Z
+    u'\xb2'     #  0xEA -> SUPERSCRIPT TWO
+    u'\xd4'     #  0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd6'     #  0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd2'     #  0xED -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd5'     #  0xEF -> LATIN CAPITAL LETTER O WITH TILDE
+    u'0'        #  0xF0 -> DIGIT ZERO
+    u'1'        #  0xF1 -> DIGIT ONE
+    u'2'        #  0xF2 -> DIGIT TWO
+    u'3'        #  0xF3 -> DIGIT THREE
+    u'4'        #  0xF4 -> DIGIT FOUR
+    u'5'        #  0xF5 -> DIGIT FIVE
+    u'6'        #  0xF6 -> DIGIT SIX
+    u'7'        #  0xF7 -> DIGIT SEVEN
+    u'8'        #  0xF8 -> DIGIT EIGHT
+    u'9'        #  0xF9 -> DIGIT NINE
+    u'\xb3'     #  0xFA -> SUPERSCRIPT THREE
+    u'\xdb'     #  0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xd9'     #  0xFD -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xFE -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\x9f'     #  0xFF -> CONTROL
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp720.py b/src/main/resources/PythonLibs/encodings/cp720.py
new file mode 100644
index 0000000000000000000000000000000000000000..5c96d9813cf26dc245dcd55b64452be0a333e681
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp720.py
@@ -0,0 +1,309 @@
+"""Python Character Mapping Codec cp720 generated on Windows:
+Vista 6.0.6002 SP2 Multiprocessor Free with the command:
+  python Tools/unicode/genwincodec.py 720
+"""#"
+
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp720',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\x80'
+    u'\x81'
+    u'\xe9'     #  0x82 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x83 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\x84'
+    u'\xe0'     #  0x85 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\x86'
+    u'\xe7'     #  0x87 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x88 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x89 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x8A -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xef'     #  0x8B -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xee'     #  0x8C -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\x8d'
+    u'\x8e'
+    u'\x8f'
+    u'\x90'
+    u'\u0651'   #  0x91 -> ARABIC SHADDA
+    u'\u0652'   #  0x92 -> ARABIC SUKUN
+    u'\xf4'     #  0x93 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xa4'     #  0x94 -> CURRENCY SIGN
+    u'\u0640'   #  0x95 -> ARABIC TATWEEL
+    u'\xfb'     #  0x96 -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xf9'     #  0x97 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\u0621'   #  0x98 -> ARABIC LETTER HAMZA
+    u'\u0622'   #  0x99 -> ARABIC LETTER ALEF WITH MADDA ABOVE
+    u'\u0623'   #  0x9A -> ARABIC LETTER ALEF WITH HAMZA ABOVE
+    u'\u0624'   #  0x9B -> ARABIC LETTER WAW WITH HAMZA ABOVE
+    u'\xa3'     #  0x9C -> POUND SIGN
+    u'\u0625'   #  0x9D -> ARABIC LETTER ALEF WITH HAMZA BELOW
+    u'\u0626'   #  0x9E -> ARABIC LETTER YEH WITH HAMZA ABOVE
+    u'\u0627'   #  0x9F -> ARABIC LETTER ALEF
+    u'\u0628'   #  0xA0 -> ARABIC LETTER BEH
+    u'\u0629'   #  0xA1 -> ARABIC LETTER TEH MARBUTA
+    u'\u062a'   #  0xA2 -> ARABIC LETTER TEH
+    u'\u062b'   #  0xA3 -> ARABIC LETTER THEH
+    u'\u062c'   #  0xA4 -> ARABIC LETTER JEEM
+    u'\u062d'   #  0xA5 -> ARABIC LETTER HAH
+    u'\u062e'   #  0xA6 -> ARABIC LETTER KHAH
+    u'\u062f'   #  0xA7 -> ARABIC LETTER DAL
+    u'\u0630'   #  0xA8 -> ARABIC LETTER THAL
+    u'\u0631'   #  0xA9 -> ARABIC LETTER REH
+    u'\u0632'   #  0xAA -> ARABIC LETTER ZAIN
+    u'\u0633'   #  0xAB -> ARABIC LETTER SEEN
+    u'\u0634'   #  0xAC -> ARABIC LETTER SHEEN
+    u'\u0635'   #  0xAD -> ARABIC LETTER SAD
+    u'\xab'     #  0xAE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xAF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0xB0 -> LIGHT SHADE
+    u'\u2592'   #  0xB1 -> MEDIUM SHADE
+    u'\u2593'   #  0xB2 -> DARK SHADE
+    u'\u2502'   #  0xB3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0xB4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0xB5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0xB6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0xB7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0xB8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0xB9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0xBA -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0xBB -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0xBC -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0xBD -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0xBE -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0xBF -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0xC0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0xC1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0xC2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0xC3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0xC4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0xC5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0xC6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0xC7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0xC8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0xC9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0xCA -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0xCB -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0xCC -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0xCD -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0xCE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0xCF -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0xD0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0xD1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0xD2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0xD3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0xD4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0xD5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0xD6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0xD7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0xD8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0xD9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0xDA -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0xDB -> FULL BLOCK
+    u'\u2584'   #  0xDC -> LOWER HALF BLOCK
+    u'\u258c'   #  0xDD -> LEFT HALF BLOCK
+    u'\u2590'   #  0xDE -> RIGHT HALF BLOCK
+    u'\u2580'   #  0xDF -> UPPER HALF BLOCK
+    u'\u0636'   #  0xE0 -> ARABIC LETTER DAD
+    u'\u0637'   #  0xE1 -> ARABIC LETTER TAH
+    u'\u0638'   #  0xE2 -> ARABIC LETTER ZAH
+    u'\u0639'   #  0xE3 -> ARABIC LETTER AIN
+    u'\u063a'   #  0xE4 -> ARABIC LETTER GHAIN
+    u'\u0641'   #  0xE5 -> ARABIC LETTER FEH
+    u'\xb5'     #  0xE6 -> MICRO SIGN
+    u'\u0642'   #  0xE7 -> ARABIC LETTER QAF
+    u'\u0643'   #  0xE8 -> ARABIC LETTER KAF
+    u'\u0644'   #  0xE9 -> ARABIC LETTER LAM
+    u'\u0645'   #  0xEA -> ARABIC LETTER MEEM
+    u'\u0646'   #  0xEB -> ARABIC LETTER NOON
+    u'\u0647'   #  0xEC -> ARABIC LETTER HEH
+    u'\u0648'   #  0xED -> ARABIC LETTER WAW
+    u'\u0649'   #  0xEE -> ARABIC LETTER ALEF MAKSURA
+    u'\u064a'   #  0xEF -> ARABIC LETTER YEH
+    u'\u2261'   #  0xF0 -> IDENTICAL TO
+    u'\u064b'   #  0xF1 -> ARABIC FATHATAN
+    u'\u064c'   #  0xF2 -> ARABIC DAMMATAN
+    u'\u064d'   #  0xF3 -> ARABIC KASRATAN
+    u'\u064e'   #  0xF4 -> ARABIC FATHA
+    u'\u064f'   #  0xF5 -> ARABIC DAMMA
+    u'\u0650'   #  0xF6 -> ARABIC KASRA
+    u'\u2248'   #  0xF7 -> ALMOST EQUAL TO
+    u'\xb0'     #  0xF8 -> DEGREE SIGN
+    u'\u2219'   #  0xF9 -> BULLET OPERATOR
+    u'\xb7'     #  0xFA -> MIDDLE DOT
+    u'\u221a'   #  0xFB -> SQUARE ROOT
+    u'\u207f'   #  0xFC -> SUPERSCRIPT LATIN SMALL LETTER N
+    u'\xb2'     #  0xFD -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0xFE -> BLACK SQUARE
+    u'\xa0'     #  0xFF -> NO-BREAK SPACE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp737.py b/src/main/resources/PythonLibs/encodings/cp737.py
new file mode 100644
index 0000000000000000000000000000000000000000..d6544482d2ddbdc6c4db296952db7081a9d9478a
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp737.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec cp737 generated from 'VENDORS/MICSFT/PC/CP737.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp737',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x0391,     #  GREEK CAPITAL LETTER ALPHA
+    0x0081: 0x0392,     #  GREEK CAPITAL LETTER BETA
+    0x0082: 0x0393,     #  GREEK CAPITAL LETTER GAMMA
+    0x0083: 0x0394,     #  GREEK CAPITAL LETTER DELTA
+    0x0084: 0x0395,     #  GREEK CAPITAL LETTER EPSILON
+    0x0085: 0x0396,     #  GREEK CAPITAL LETTER ZETA
+    0x0086: 0x0397,     #  GREEK CAPITAL LETTER ETA
+    0x0087: 0x0398,     #  GREEK CAPITAL LETTER THETA
+    0x0088: 0x0399,     #  GREEK CAPITAL LETTER IOTA
+    0x0089: 0x039a,     #  GREEK CAPITAL LETTER KAPPA
+    0x008a: 0x039b,     #  GREEK CAPITAL LETTER LAMDA
+    0x008b: 0x039c,     #  GREEK CAPITAL LETTER MU
+    0x008c: 0x039d,     #  GREEK CAPITAL LETTER NU
+    0x008d: 0x039e,     #  GREEK CAPITAL LETTER XI
+    0x008e: 0x039f,     #  GREEK CAPITAL LETTER OMICRON
+    0x008f: 0x03a0,     #  GREEK CAPITAL LETTER PI
+    0x0090: 0x03a1,     #  GREEK CAPITAL LETTER RHO
+    0x0091: 0x03a3,     #  GREEK CAPITAL LETTER SIGMA
+    0x0092: 0x03a4,     #  GREEK CAPITAL LETTER TAU
+    0x0093: 0x03a5,     #  GREEK CAPITAL LETTER UPSILON
+    0x0094: 0x03a6,     #  GREEK CAPITAL LETTER PHI
+    0x0095: 0x03a7,     #  GREEK CAPITAL LETTER CHI
+    0x0096: 0x03a8,     #  GREEK CAPITAL LETTER PSI
+    0x0097: 0x03a9,     #  GREEK CAPITAL LETTER OMEGA
+    0x0098: 0x03b1,     #  GREEK SMALL LETTER ALPHA
+    0x0099: 0x03b2,     #  GREEK SMALL LETTER BETA
+    0x009a: 0x03b3,     #  GREEK SMALL LETTER GAMMA
+    0x009b: 0x03b4,     #  GREEK SMALL LETTER DELTA
+    0x009c: 0x03b5,     #  GREEK SMALL LETTER EPSILON
+    0x009d: 0x03b6,     #  GREEK SMALL LETTER ZETA
+    0x009e: 0x03b7,     #  GREEK SMALL LETTER ETA
+    0x009f: 0x03b8,     #  GREEK SMALL LETTER THETA
+    0x00a0: 0x03b9,     #  GREEK SMALL LETTER IOTA
+    0x00a1: 0x03ba,     #  GREEK SMALL LETTER KAPPA
+    0x00a2: 0x03bb,     #  GREEK SMALL LETTER LAMDA
+    0x00a3: 0x03bc,     #  GREEK SMALL LETTER MU
+    0x00a4: 0x03bd,     #  GREEK SMALL LETTER NU
+    0x00a5: 0x03be,     #  GREEK SMALL LETTER XI
+    0x00a6: 0x03bf,     #  GREEK SMALL LETTER OMICRON
+    0x00a7: 0x03c0,     #  GREEK SMALL LETTER PI
+    0x00a8: 0x03c1,     #  GREEK SMALL LETTER RHO
+    0x00a9: 0x03c3,     #  GREEK SMALL LETTER SIGMA
+    0x00aa: 0x03c2,     #  GREEK SMALL LETTER FINAL SIGMA
+    0x00ab: 0x03c4,     #  GREEK SMALL LETTER TAU
+    0x00ac: 0x03c5,     #  GREEK SMALL LETTER UPSILON
+    0x00ad: 0x03c6,     #  GREEK SMALL LETTER PHI
+    0x00ae: 0x03c7,     #  GREEK SMALL LETTER CHI
+    0x00af: 0x03c8,     #  GREEK SMALL LETTER PSI
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x2561,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x00b6: 0x2562,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x00b7: 0x2556,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x00b8: 0x2555,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x255c,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x00be: 0x255b,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x255e,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x00c7: 0x255f,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x2567,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x00d0: 0x2568,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x00d1: 0x2564,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x00d2: 0x2565,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x00d3: 0x2559,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x00d4: 0x2558,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x00d5: 0x2552,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x00d6: 0x2553,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x00d7: 0x256b,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x00d8: 0x256a,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x03c9,     #  GREEK SMALL LETTER OMEGA
+    0x00e1: 0x03ac,     #  GREEK SMALL LETTER ALPHA WITH TONOS
+    0x00e2: 0x03ad,     #  GREEK SMALL LETTER EPSILON WITH TONOS
+    0x00e3: 0x03ae,     #  GREEK SMALL LETTER ETA WITH TONOS
+    0x00e4: 0x03ca,     #  GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    0x00e5: 0x03af,     #  GREEK SMALL LETTER IOTA WITH TONOS
+    0x00e6: 0x03cc,     #  GREEK SMALL LETTER OMICRON WITH TONOS
+    0x00e7: 0x03cd,     #  GREEK SMALL LETTER UPSILON WITH TONOS
+    0x00e8: 0x03cb,     #  GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    0x00e9: 0x03ce,     #  GREEK SMALL LETTER OMEGA WITH TONOS
+    0x00ea: 0x0386,     #  GREEK CAPITAL LETTER ALPHA WITH TONOS
+    0x00eb: 0x0388,     #  GREEK CAPITAL LETTER EPSILON WITH TONOS
+    0x00ec: 0x0389,     #  GREEK CAPITAL LETTER ETA WITH TONOS
+    0x00ed: 0x038a,     #  GREEK CAPITAL LETTER IOTA WITH TONOS
+    0x00ee: 0x038c,     #  GREEK CAPITAL LETTER OMICRON WITH TONOS
+    0x00ef: 0x038e,     #  GREEK CAPITAL LETTER UPSILON WITH TONOS
+    0x00f0: 0x038f,     #  GREEK CAPITAL LETTER OMEGA WITH TONOS
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2265,     #  GREATER-THAN OR EQUAL TO
+    0x00f3: 0x2264,     #  LESS-THAN OR EQUAL TO
+    0x00f4: 0x03aa,     #  GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    0x00f5: 0x03ab,     #  GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x2248,     #  ALMOST EQUAL TO
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x221a,     #  SQUARE ROOT
+    0x00fc: 0x207f,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\u0391'   #  0x0080 -> GREEK CAPITAL LETTER ALPHA
+    u'\u0392'   #  0x0081 -> GREEK CAPITAL LETTER BETA
+    u'\u0393'   #  0x0082 -> GREEK CAPITAL LETTER GAMMA
+    u'\u0394'   #  0x0083 -> GREEK CAPITAL LETTER DELTA
+    u'\u0395'   #  0x0084 -> GREEK CAPITAL LETTER EPSILON
+    u'\u0396'   #  0x0085 -> GREEK CAPITAL LETTER ZETA
+    u'\u0397'   #  0x0086 -> GREEK CAPITAL LETTER ETA
+    u'\u0398'   #  0x0087 -> GREEK CAPITAL LETTER THETA
+    u'\u0399'   #  0x0088 -> GREEK CAPITAL LETTER IOTA
+    u'\u039a'   #  0x0089 -> GREEK CAPITAL LETTER KAPPA
+    u'\u039b'   #  0x008a -> GREEK CAPITAL LETTER LAMDA
+    u'\u039c'   #  0x008b -> GREEK CAPITAL LETTER MU
+    u'\u039d'   #  0x008c -> GREEK CAPITAL LETTER NU
+    u'\u039e'   #  0x008d -> GREEK CAPITAL LETTER XI
+    u'\u039f'   #  0x008e -> GREEK CAPITAL LETTER OMICRON
+    u'\u03a0'   #  0x008f -> GREEK CAPITAL LETTER PI
+    u'\u03a1'   #  0x0090 -> GREEK CAPITAL LETTER RHO
+    u'\u03a3'   #  0x0091 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03a4'   #  0x0092 -> GREEK CAPITAL LETTER TAU
+    u'\u03a5'   #  0x0093 -> GREEK CAPITAL LETTER UPSILON
+    u'\u03a6'   #  0x0094 -> GREEK CAPITAL LETTER PHI
+    u'\u03a7'   #  0x0095 -> GREEK CAPITAL LETTER CHI
+    u'\u03a8'   #  0x0096 -> GREEK CAPITAL LETTER PSI
+    u'\u03a9'   #  0x0097 -> GREEK CAPITAL LETTER OMEGA
+    u'\u03b1'   #  0x0098 -> GREEK SMALL LETTER ALPHA
+    u'\u03b2'   #  0x0099 -> GREEK SMALL LETTER BETA
+    u'\u03b3'   #  0x009a -> GREEK SMALL LETTER GAMMA
+    u'\u03b4'   #  0x009b -> GREEK SMALL LETTER DELTA
+    u'\u03b5'   #  0x009c -> GREEK SMALL LETTER EPSILON
+    u'\u03b6'   #  0x009d -> GREEK SMALL LETTER ZETA
+    u'\u03b7'   #  0x009e -> GREEK SMALL LETTER ETA
+    u'\u03b8'   #  0x009f -> GREEK SMALL LETTER THETA
+    u'\u03b9'   #  0x00a0 -> GREEK SMALL LETTER IOTA
+    u'\u03ba'   #  0x00a1 -> GREEK SMALL LETTER KAPPA
+    u'\u03bb'   #  0x00a2 -> GREEK SMALL LETTER LAMDA
+    u'\u03bc'   #  0x00a3 -> GREEK SMALL LETTER MU
+    u'\u03bd'   #  0x00a4 -> GREEK SMALL LETTER NU
+    u'\u03be'   #  0x00a5 -> GREEK SMALL LETTER XI
+    u'\u03bf'   #  0x00a6 -> GREEK SMALL LETTER OMICRON
+    u'\u03c0'   #  0x00a7 -> GREEK SMALL LETTER PI
+    u'\u03c1'   #  0x00a8 -> GREEK SMALL LETTER RHO
+    u'\u03c3'   #  0x00a9 -> GREEK SMALL LETTER SIGMA
+    u'\u03c2'   #  0x00aa -> GREEK SMALL LETTER FINAL SIGMA
+    u'\u03c4'   #  0x00ab -> GREEK SMALL LETTER TAU
+    u'\u03c5'   #  0x00ac -> GREEK SMALL LETTER UPSILON
+    u'\u03c6'   #  0x00ad -> GREEK SMALL LETTER PHI
+    u'\u03c7'   #  0x00ae -> GREEK SMALL LETTER CHI
+    u'\u03c8'   #  0x00af -> GREEK SMALL LETTER PSI
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u03c9'   #  0x00e0 -> GREEK SMALL LETTER OMEGA
+    u'\u03ac'   #  0x00e1 -> GREEK SMALL LETTER ALPHA WITH TONOS
+    u'\u03ad'   #  0x00e2 -> GREEK SMALL LETTER EPSILON WITH TONOS
+    u'\u03ae'   #  0x00e3 -> GREEK SMALL LETTER ETA WITH TONOS
+    u'\u03ca'   #  0x00e4 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    u'\u03af'   #  0x00e5 -> GREEK SMALL LETTER IOTA WITH TONOS
+    u'\u03cc'   #  0x00e6 -> GREEK SMALL LETTER OMICRON WITH TONOS
+    u'\u03cd'   #  0x00e7 -> GREEK SMALL LETTER UPSILON WITH TONOS
+    u'\u03cb'   #  0x00e8 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    u'\u03ce'   #  0x00e9 -> GREEK SMALL LETTER OMEGA WITH TONOS
+    u'\u0386'   #  0x00ea -> GREEK CAPITAL LETTER ALPHA WITH TONOS
+    u'\u0388'   #  0x00eb -> GREEK CAPITAL LETTER EPSILON WITH TONOS
+    u'\u0389'   #  0x00ec -> GREEK CAPITAL LETTER ETA WITH TONOS
+    u'\u038a'   #  0x00ed -> GREEK CAPITAL LETTER IOTA WITH TONOS
+    u'\u038c'   #  0x00ee -> GREEK CAPITAL LETTER OMICRON WITH TONOS
+    u'\u038e'   #  0x00ef -> GREEK CAPITAL LETTER UPSILON WITH TONOS
+    u'\u038f'   #  0x00f0 -> GREEK CAPITAL LETTER OMEGA WITH TONOS
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2265'   #  0x00f2 -> GREATER-THAN OR EQUAL TO
+    u'\u2264'   #  0x00f3 -> LESS-THAN OR EQUAL TO
+    u'\u03aa'   #  0x00f4 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    u'\u03ab'   #  0x00f5 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\u2248'   #  0x00f7 -> ALMOST EQUAL TO
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\u221a'   #  0x00fb -> SQUARE ROOT
+    u'\u207f'   #  0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x0386: 0x00ea,     #  GREEK CAPITAL LETTER ALPHA WITH TONOS
+    0x0388: 0x00eb,     #  GREEK CAPITAL LETTER EPSILON WITH TONOS
+    0x0389: 0x00ec,     #  GREEK CAPITAL LETTER ETA WITH TONOS
+    0x038a: 0x00ed,     #  GREEK CAPITAL LETTER IOTA WITH TONOS
+    0x038c: 0x00ee,     #  GREEK CAPITAL LETTER OMICRON WITH TONOS
+    0x038e: 0x00ef,     #  GREEK CAPITAL LETTER UPSILON WITH TONOS
+    0x038f: 0x00f0,     #  GREEK CAPITAL LETTER OMEGA WITH TONOS
+    0x0391: 0x0080,     #  GREEK CAPITAL LETTER ALPHA
+    0x0392: 0x0081,     #  GREEK CAPITAL LETTER BETA
+    0x0393: 0x0082,     #  GREEK CAPITAL LETTER GAMMA
+    0x0394: 0x0083,     #  GREEK CAPITAL LETTER DELTA
+    0x0395: 0x0084,     #  GREEK CAPITAL LETTER EPSILON
+    0x0396: 0x0085,     #  GREEK CAPITAL LETTER ZETA
+    0x0397: 0x0086,     #  GREEK CAPITAL LETTER ETA
+    0x0398: 0x0087,     #  GREEK CAPITAL LETTER THETA
+    0x0399: 0x0088,     #  GREEK CAPITAL LETTER IOTA
+    0x039a: 0x0089,     #  GREEK CAPITAL LETTER KAPPA
+    0x039b: 0x008a,     #  GREEK CAPITAL LETTER LAMDA
+    0x039c: 0x008b,     #  GREEK CAPITAL LETTER MU
+    0x039d: 0x008c,     #  GREEK CAPITAL LETTER NU
+    0x039e: 0x008d,     #  GREEK CAPITAL LETTER XI
+    0x039f: 0x008e,     #  GREEK CAPITAL LETTER OMICRON
+    0x03a0: 0x008f,     #  GREEK CAPITAL LETTER PI
+    0x03a1: 0x0090,     #  GREEK CAPITAL LETTER RHO
+    0x03a3: 0x0091,     #  GREEK CAPITAL LETTER SIGMA
+    0x03a4: 0x0092,     #  GREEK CAPITAL LETTER TAU
+    0x03a5: 0x0093,     #  GREEK CAPITAL LETTER UPSILON
+    0x03a6: 0x0094,     #  GREEK CAPITAL LETTER PHI
+    0x03a7: 0x0095,     #  GREEK CAPITAL LETTER CHI
+    0x03a8: 0x0096,     #  GREEK CAPITAL LETTER PSI
+    0x03a9: 0x0097,     #  GREEK CAPITAL LETTER OMEGA
+    0x03aa: 0x00f4,     #  GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    0x03ab: 0x00f5,     #  GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    0x03ac: 0x00e1,     #  GREEK SMALL LETTER ALPHA WITH TONOS
+    0x03ad: 0x00e2,     #  GREEK SMALL LETTER EPSILON WITH TONOS
+    0x03ae: 0x00e3,     #  GREEK SMALL LETTER ETA WITH TONOS
+    0x03af: 0x00e5,     #  GREEK SMALL LETTER IOTA WITH TONOS
+    0x03b1: 0x0098,     #  GREEK SMALL LETTER ALPHA
+    0x03b2: 0x0099,     #  GREEK SMALL LETTER BETA
+    0x03b3: 0x009a,     #  GREEK SMALL LETTER GAMMA
+    0x03b4: 0x009b,     #  GREEK SMALL LETTER DELTA
+    0x03b5: 0x009c,     #  GREEK SMALL LETTER EPSILON
+    0x03b6: 0x009d,     #  GREEK SMALL LETTER ZETA
+    0x03b7: 0x009e,     #  GREEK SMALL LETTER ETA
+    0x03b8: 0x009f,     #  GREEK SMALL LETTER THETA
+    0x03b9: 0x00a0,     #  GREEK SMALL LETTER IOTA
+    0x03ba: 0x00a1,     #  GREEK SMALL LETTER KAPPA
+    0x03bb: 0x00a2,     #  GREEK SMALL LETTER LAMDA
+    0x03bc: 0x00a3,     #  GREEK SMALL LETTER MU
+    0x03bd: 0x00a4,     #  GREEK SMALL LETTER NU
+    0x03be: 0x00a5,     #  GREEK SMALL LETTER XI
+    0x03bf: 0x00a6,     #  GREEK SMALL LETTER OMICRON
+    0x03c0: 0x00a7,     #  GREEK SMALL LETTER PI
+    0x03c1: 0x00a8,     #  GREEK SMALL LETTER RHO
+    0x03c2: 0x00aa,     #  GREEK SMALL LETTER FINAL SIGMA
+    0x03c3: 0x00a9,     #  GREEK SMALL LETTER SIGMA
+    0x03c4: 0x00ab,     #  GREEK SMALL LETTER TAU
+    0x03c5: 0x00ac,     #  GREEK SMALL LETTER UPSILON
+    0x03c6: 0x00ad,     #  GREEK SMALL LETTER PHI
+    0x03c7: 0x00ae,     #  GREEK SMALL LETTER CHI
+    0x03c8: 0x00af,     #  GREEK SMALL LETTER PSI
+    0x03c9: 0x00e0,     #  GREEK SMALL LETTER OMEGA
+    0x03ca: 0x00e4,     #  GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    0x03cb: 0x00e8,     #  GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    0x03cc: 0x00e6,     #  GREEK SMALL LETTER OMICRON WITH TONOS
+    0x03cd: 0x00e7,     #  GREEK SMALL LETTER UPSILON WITH TONOS
+    0x03ce: 0x00e9,     #  GREEK SMALL LETTER OMEGA WITH TONOS
+    0x207f: 0x00fc,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x221a: 0x00fb,     #  SQUARE ROOT
+    0x2248: 0x00f7,     #  ALMOST EQUAL TO
+    0x2264: 0x00f3,     #  LESS-THAN OR EQUAL TO
+    0x2265: 0x00f2,     #  GREATER-THAN OR EQUAL TO
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2552: 0x00d5,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x2553: 0x00d6,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2555: 0x00b8,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x2556: 0x00b7,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x2558: 0x00d4,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x2559: 0x00d3,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255b: 0x00be,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x255c: 0x00bd,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x255e: 0x00c6,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x255f: 0x00c7,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2561: 0x00b5,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x2562: 0x00b6,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2564: 0x00d1,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x2565: 0x00d2,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2567: 0x00cf,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x2568: 0x00d0,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256a: 0x00d8,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x256b: 0x00d7,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp775.py b/src/main/resources/PythonLibs/encodings/cp775.py
new file mode 100644
index 0000000000000000000000000000000000000000..6a456a5825e4c3682bd08ab8abe52df7425f65d1
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp775.py
@@ -0,0 +1,697 @@
+""" Python Character Mapping Codec cp775 generated from 'VENDORS/MICSFT/PC/CP775.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp775',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x0106,     #  LATIN CAPITAL LETTER C WITH ACUTE
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x0101,     #  LATIN SMALL LETTER A WITH MACRON
+    0x0084: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x0085: 0x0123,     #  LATIN SMALL LETTER G WITH CEDILLA
+    0x0086: 0x00e5,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x0087: 0x0107,     #  LATIN SMALL LETTER C WITH ACUTE
+    0x0088: 0x0142,     #  LATIN SMALL LETTER L WITH STROKE
+    0x0089: 0x0113,     #  LATIN SMALL LETTER E WITH MACRON
+    0x008a: 0x0156,     #  LATIN CAPITAL LETTER R WITH CEDILLA
+    0x008b: 0x0157,     #  LATIN SMALL LETTER R WITH CEDILLA
+    0x008c: 0x012b,     #  LATIN SMALL LETTER I WITH MACRON
+    0x008d: 0x0179,     #  LATIN CAPITAL LETTER Z WITH ACUTE
+    0x008e: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x008f: 0x00c5,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00e6,     #  LATIN SMALL LIGATURE AE
+    0x0092: 0x00c6,     #  LATIN CAPITAL LIGATURE AE
+    0x0093: 0x014d,     #  LATIN SMALL LETTER O WITH MACRON
+    0x0094: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x0095: 0x0122,     #  LATIN CAPITAL LETTER G WITH CEDILLA
+    0x0096: 0x00a2,     #  CENT SIGN
+    0x0097: 0x015a,     #  LATIN CAPITAL LETTER S WITH ACUTE
+    0x0098: 0x015b,     #  LATIN SMALL LETTER S WITH ACUTE
+    0x0099: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00f8,     #  LATIN SMALL LETTER O WITH STROKE
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00d8,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x009e: 0x00d7,     #  MULTIPLICATION SIGN
+    0x009f: 0x00a4,     #  CURRENCY SIGN
+    0x00a0: 0x0100,     #  LATIN CAPITAL LETTER A WITH MACRON
+    0x00a1: 0x012a,     #  LATIN CAPITAL LETTER I WITH MACRON
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x017b,     #  LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    0x00a4: 0x017c,     #  LATIN SMALL LETTER Z WITH DOT ABOVE
+    0x00a5: 0x017a,     #  LATIN SMALL LETTER Z WITH ACUTE
+    0x00a6: 0x201d,     #  RIGHT DOUBLE QUOTATION MARK
+    0x00a7: 0x00a6,     #  BROKEN BAR
+    0x00a8: 0x00a9,     #  COPYRIGHT SIGN
+    0x00a9: 0x00ae,     #  REGISTERED SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x0141,     #  LATIN CAPITAL LETTER L WITH STROKE
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x0104,     #  LATIN CAPITAL LETTER A WITH OGONEK
+    0x00b6: 0x010c,     #  LATIN CAPITAL LETTER C WITH CARON
+    0x00b7: 0x0118,     #  LATIN CAPITAL LETTER E WITH OGONEK
+    0x00b8: 0x0116,     #  LATIN CAPITAL LETTER E WITH DOT ABOVE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x012e,     #  LATIN CAPITAL LETTER I WITH OGONEK
+    0x00be: 0x0160,     #  LATIN CAPITAL LETTER S WITH CARON
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x0172,     #  LATIN CAPITAL LETTER U WITH OGONEK
+    0x00c7: 0x016a,     #  LATIN CAPITAL LETTER U WITH MACRON
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x017d,     #  LATIN CAPITAL LETTER Z WITH CARON
+    0x00d0: 0x0105,     #  LATIN SMALL LETTER A WITH OGONEK
+    0x00d1: 0x010d,     #  LATIN SMALL LETTER C WITH CARON
+    0x00d2: 0x0119,     #  LATIN SMALL LETTER E WITH OGONEK
+    0x00d3: 0x0117,     #  LATIN SMALL LETTER E WITH DOT ABOVE
+    0x00d4: 0x012f,     #  LATIN SMALL LETTER I WITH OGONEK
+    0x00d5: 0x0161,     #  LATIN SMALL LETTER S WITH CARON
+    0x00d6: 0x0173,     #  LATIN SMALL LETTER U WITH OGONEK
+    0x00d7: 0x016b,     #  LATIN SMALL LETTER U WITH MACRON
+    0x00d8: 0x017e,     #  LATIN SMALL LETTER Z WITH CARON
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x00d3,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S (GERMAN)
+    0x00e2: 0x014c,     #  LATIN CAPITAL LETTER O WITH MACRON
+    0x00e3: 0x0143,     #  LATIN CAPITAL LETTER N WITH ACUTE
+    0x00e4: 0x00f5,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00e5: 0x00d5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x0144,     #  LATIN SMALL LETTER N WITH ACUTE
+    0x00e8: 0x0136,     #  LATIN CAPITAL LETTER K WITH CEDILLA
+    0x00e9: 0x0137,     #  LATIN SMALL LETTER K WITH CEDILLA
+    0x00ea: 0x013b,     #  LATIN CAPITAL LETTER L WITH CEDILLA
+    0x00eb: 0x013c,     #  LATIN SMALL LETTER L WITH CEDILLA
+    0x00ec: 0x0146,     #  LATIN SMALL LETTER N WITH CEDILLA
+    0x00ed: 0x0112,     #  LATIN CAPITAL LETTER E WITH MACRON
+    0x00ee: 0x0145,     #  LATIN CAPITAL LETTER N WITH CEDILLA
+    0x00ef: 0x2019,     #  RIGHT SINGLE QUOTATION MARK
+    0x00f0: 0x00ad,     #  SOFT HYPHEN
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x201c,     #  LEFT DOUBLE QUOTATION MARK
+    0x00f3: 0x00be,     #  VULGAR FRACTION THREE QUARTERS
+    0x00f4: 0x00b6,     #  PILCROW SIGN
+    0x00f5: 0x00a7,     #  SECTION SIGN
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x201e,     #  DOUBLE LOW-9 QUOTATION MARK
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x00b9,     #  SUPERSCRIPT ONE
+    0x00fc: 0x00b3,     #  SUPERSCRIPT THREE
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\u0106'   #  0x0080 -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\u0101'   #  0x0083 -> LATIN SMALL LETTER A WITH MACRON
+    u'\xe4'     #  0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u0123'   #  0x0085 -> LATIN SMALL LETTER G WITH CEDILLA
+    u'\xe5'     #  0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\u0107'   #  0x0087 -> LATIN SMALL LETTER C WITH ACUTE
+    u'\u0142'   #  0x0088 -> LATIN SMALL LETTER L WITH STROKE
+    u'\u0113'   #  0x0089 -> LATIN SMALL LETTER E WITH MACRON
+    u'\u0156'   #  0x008a -> LATIN CAPITAL LETTER R WITH CEDILLA
+    u'\u0157'   #  0x008b -> LATIN SMALL LETTER R WITH CEDILLA
+    u'\u012b'   #  0x008c -> LATIN SMALL LETTER I WITH MACRON
+    u'\u0179'   #  0x008d -> LATIN CAPITAL LETTER Z WITH ACUTE
+    u'\xc4'     #  0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xe6'     #  0x0091 -> LATIN SMALL LIGATURE AE
+    u'\xc6'     #  0x0092 -> LATIN CAPITAL LIGATURE AE
+    u'\u014d'   #  0x0093 -> LATIN SMALL LETTER O WITH MACRON
+    u'\xf6'     #  0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\u0122'   #  0x0095 -> LATIN CAPITAL LETTER G WITH CEDILLA
+    u'\xa2'     #  0x0096 -> CENT SIGN
+    u'\u015a'   #  0x0097 -> LATIN CAPITAL LETTER S WITH ACUTE
+    u'\u015b'   #  0x0098 -> LATIN SMALL LETTER S WITH ACUTE
+    u'\xd6'     #  0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xf8'     #  0x009b -> LATIN SMALL LETTER O WITH STROKE
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xd8'     #  0x009d -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd7'     #  0x009e -> MULTIPLICATION SIGN
+    u'\xa4'     #  0x009f -> CURRENCY SIGN
+    u'\u0100'   #  0x00a0 -> LATIN CAPITAL LETTER A WITH MACRON
+    u'\u012a'   #  0x00a1 -> LATIN CAPITAL LETTER I WITH MACRON
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\u017b'   #  0x00a3 -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\u017c'   #  0x00a4 -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\u017a'   #  0x00a5 -> LATIN SMALL LETTER Z WITH ACUTE
+    u'\u201d'   #  0x00a6 -> RIGHT DOUBLE QUOTATION MARK
+    u'\xa6'     #  0x00a7 -> BROKEN BAR
+    u'\xa9'     #  0x00a8 -> COPYRIGHT SIGN
+    u'\xae'     #  0x00a9 -> REGISTERED SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\u0141'   #  0x00ad -> LATIN CAPITAL LETTER L WITH STROKE
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u0104'   #  0x00b5 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\u010c'   #  0x00b6 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\u0118'   #  0x00b7 -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\u0116'   #  0x00b8 -> LATIN CAPITAL LETTER E WITH DOT ABOVE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u012e'   #  0x00bd -> LATIN CAPITAL LETTER I WITH OGONEK
+    u'\u0160'   #  0x00be -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u0172'   #  0x00c6 -> LATIN CAPITAL LETTER U WITH OGONEK
+    u'\u016a'   #  0x00c7 -> LATIN CAPITAL LETTER U WITH MACRON
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u017d'   #  0x00cf -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\u0105'   #  0x00d0 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u010d'   #  0x00d1 -> LATIN SMALL LETTER C WITH CARON
+    u'\u0119'   #  0x00d2 -> LATIN SMALL LETTER E WITH OGONEK
+    u'\u0117'   #  0x00d3 -> LATIN SMALL LETTER E WITH DOT ABOVE
+    u'\u012f'   #  0x00d4 -> LATIN SMALL LETTER I WITH OGONEK
+    u'\u0161'   #  0x00d5 -> LATIN SMALL LETTER S WITH CARON
+    u'\u0173'   #  0x00d6 -> LATIN SMALL LETTER U WITH OGONEK
+    u'\u016b'   #  0x00d7 -> LATIN SMALL LETTER U WITH MACRON
+    u'\u017e'   #  0x00d8 -> LATIN SMALL LETTER Z WITH CARON
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\xd3'     #  0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S (GERMAN)
+    u'\u014c'   #  0x00e2 -> LATIN CAPITAL LETTER O WITH MACRON
+    u'\u0143'   #  0x00e3 -> LATIN CAPITAL LETTER N WITH ACUTE
+    u'\xf5'     #  0x00e4 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xd5'     #  0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\u0144'   #  0x00e7 -> LATIN SMALL LETTER N WITH ACUTE
+    u'\u0136'   #  0x00e8 -> LATIN CAPITAL LETTER K WITH CEDILLA
+    u'\u0137'   #  0x00e9 -> LATIN SMALL LETTER K WITH CEDILLA
+    u'\u013b'   #  0x00ea -> LATIN CAPITAL LETTER L WITH CEDILLA
+    u'\u013c'   #  0x00eb -> LATIN SMALL LETTER L WITH CEDILLA
+    u'\u0146'   #  0x00ec -> LATIN SMALL LETTER N WITH CEDILLA
+    u'\u0112'   #  0x00ed -> LATIN CAPITAL LETTER E WITH MACRON
+    u'\u0145'   #  0x00ee -> LATIN CAPITAL LETTER N WITH CEDILLA
+    u'\u2019'   #  0x00ef -> RIGHT SINGLE QUOTATION MARK
+    u'\xad'     #  0x00f0 -> SOFT HYPHEN
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u201c'   #  0x00f2 -> LEFT DOUBLE QUOTATION MARK
+    u'\xbe'     #  0x00f3 -> VULGAR FRACTION THREE QUARTERS
+    u'\xb6'     #  0x00f4 -> PILCROW SIGN
+    u'\xa7'     #  0x00f5 -> SECTION SIGN
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\u201e'   #  0x00f7 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\xb9'     #  0x00fb -> SUPERSCRIPT ONE
+    u'\xb3'     #  0x00fc -> SUPERSCRIPT THREE
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a2: 0x0096,     #  CENT SIGN
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a4: 0x009f,     #  CURRENCY SIGN
+    0x00a6: 0x00a7,     #  BROKEN BAR
+    0x00a7: 0x00f5,     #  SECTION SIGN
+    0x00a9: 0x00a8,     #  COPYRIGHT SIGN
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00ad: 0x00f0,     #  SOFT HYPHEN
+    0x00ae: 0x00a9,     #  REGISTERED SIGN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b3: 0x00fc,     #  SUPERSCRIPT THREE
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b6: 0x00f4,     #  PILCROW SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00b9: 0x00fb,     #  SUPERSCRIPT ONE
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00be: 0x00f3,     #  VULGAR FRACTION THREE QUARTERS
+    0x00c4: 0x008e,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c5: 0x008f,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x00c6: 0x0092,     #  LATIN CAPITAL LIGATURE AE
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00d3: 0x00e0,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00d5: 0x00e5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00d6: 0x0099,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00d7: 0x009e,     #  MULTIPLICATION SIGN
+    0x00d8: 0x009d,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S (GERMAN)
+    0x00e4: 0x0084,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e5: 0x0086,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x00e6: 0x0091,     #  LATIN SMALL LIGATURE AE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f5: 0x00e4,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00f6: 0x0094,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f8: 0x009b,     #  LATIN SMALL LETTER O WITH STROKE
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0100: 0x00a0,     #  LATIN CAPITAL LETTER A WITH MACRON
+    0x0101: 0x0083,     #  LATIN SMALL LETTER A WITH MACRON
+    0x0104: 0x00b5,     #  LATIN CAPITAL LETTER A WITH OGONEK
+    0x0105: 0x00d0,     #  LATIN SMALL LETTER A WITH OGONEK
+    0x0106: 0x0080,     #  LATIN CAPITAL LETTER C WITH ACUTE
+    0x0107: 0x0087,     #  LATIN SMALL LETTER C WITH ACUTE
+    0x010c: 0x00b6,     #  LATIN CAPITAL LETTER C WITH CARON
+    0x010d: 0x00d1,     #  LATIN SMALL LETTER C WITH CARON
+    0x0112: 0x00ed,     #  LATIN CAPITAL LETTER E WITH MACRON
+    0x0113: 0x0089,     #  LATIN SMALL LETTER E WITH MACRON
+    0x0116: 0x00b8,     #  LATIN CAPITAL LETTER E WITH DOT ABOVE
+    0x0117: 0x00d3,     #  LATIN SMALL LETTER E WITH DOT ABOVE
+    0x0118: 0x00b7,     #  LATIN CAPITAL LETTER E WITH OGONEK
+    0x0119: 0x00d2,     #  LATIN SMALL LETTER E WITH OGONEK
+    0x0122: 0x0095,     #  LATIN CAPITAL LETTER G WITH CEDILLA
+    0x0123: 0x0085,     #  LATIN SMALL LETTER G WITH CEDILLA
+    0x012a: 0x00a1,     #  LATIN CAPITAL LETTER I WITH MACRON
+    0x012b: 0x008c,     #  LATIN SMALL LETTER I WITH MACRON
+    0x012e: 0x00bd,     #  LATIN CAPITAL LETTER I WITH OGONEK
+    0x012f: 0x00d4,     #  LATIN SMALL LETTER I WITH OGONEK
+    0x0136: 0x00e8,     #  LATIN CAPITAL LETTER K WITH CEDILLA
+    0x0137: 0x00e9,     #  LATIN SMALL LETTER K WITH CEDILLA
+    0x013b: 0x00ea,     #  LATIN CAPITAL LETTER L WITH CEDILLA
+    0x013c: 0x00eb,     #  LATIN SMALL LETTER L WITH CEDILLA
+    0x0141: 0x00ad,     #  LATIN CAPITAL LETTER L WITH STROKE
+    0x0142: 0x0088,     #  LATIN SMALL LETTER L WITH STROKE
+    0x0143: 0x00e3,     #  LATIN CAPITAL LETTER N WITH ACUTE
+    0x0144: 0x00e7,     #  LATIN SMALL LETTER N WITH ACUTE
+    0x0145: 0x00ee,     #  LATIN CAPITAL LETTER N WITH CEDILLA
+    0x0146: 0x00ec,     #  LATIN SMALL LETTER N WITH CEDILLA
+    0x014c: 0x00e2,     #  LATIN CAPITAL LETTER O WITH MACRON
+    0x014d: 0x0093,     #  LATIN SMALL LETTER O WITH MACRON
+    0x0156: 0x008a,     #  LATIN CAPITAL LETTER R WITH CEDILLA
+    0x0157: 0x008b,     #  LATIN SMALL LETTER R WITH CEDILLA
+    0x015a: 0x0097,     #  LATIN CAPITAL LETTER S WITH ACUTE
+    0x015b: 0x0098,     #  LATIN SMALL LETTER S WITH ACUTE
+    0x0160: 0x00be,     #  LATIN CAPITAL LETTER S WITH CARON
+    0x0161: 0x00d5,     #  LATIN SMALL LETTER S WITH CARON
+    0x016a: 0x00c7,     #  LATIN CAPITAL LETTER U WITH MACRON
+    0x016b: 0x00d7,     #  LATIN SMALL LETTER U WITH MACRON
+    0x0172: 0x00c6,     #  LATIN CAPITAL LETTER U WITH OGONEK
+    0x0173: 0x00d6,     #  LATIN SMALL LETTER U WITH OGONEK
+    0x0179: 0x008d,     #  LATIN CAPITAL LETTER Z WITH ACUTE
+    0x017a: 0x00a5,     #  LATIN SMALL LETTER Z WITH ACUTE
+    0x017b: 0x00a3,     #  LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    0x017c: 0x00a4,     #  LATIN SMALL LETTER Z WITH DOT ABOVE
+    0x017d: 0x00cf,     #  LATIN CAPITAL LETTER Z WITH CARON
+    0x017e: 0x00d8,     #  LATIN SMALL LETTER Z WITH CARON
+    0x2019: 0x00ef,     #  RIGHT SINGLE QUOTATION MARK
+    0x201c: 0x00f2,     #  LEFT DOUBLE QUOTATION MARK
+    0x201d: 0x00a6,     #  RIGHT DOUBLE QUOTATION MARK
+    0x201e: 0x00f7,     #  DOUBLE LOW-9 QUOTATION MARK
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp850.py b/src/main/resources/PythonLibs/encodings/cp850.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c8478c8b205a8ce69eac95a00b75f319d49c5e1
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp850.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP850.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp850',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x0085: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0086: 0x00e5,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0089: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x008a: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x008b: 0x00ef,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x008c: 0x00ee,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x008d: 0x00ec,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x008e: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x008f: 0x00c5,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00e6,     #  LATIN SMALL LIGATURE AE
+    0x0092: 0x00c6,     #  LATIN CAPITAL LIGATURE AE
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x0095: 0x00f2,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x0096: 0x00fb,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x0097: 0x00f9,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x0098: 0x00ff,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x0099: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00f8,     #  LATIN SMALL LETTER O WITH STROKE
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00d8,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x009e: 0x00d7,     #  MULTIPLICATION SIGN
+    0x009f: 0x0192,     #  LATIN SMALL LETTER F WITH HOOK
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00f1,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00a5: 0x00d1,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00a6: 0x00aa,     #  FEMININE ORDINAL INDICATOR
+    0x00a7: 0x00ba,     #  MASCULINE ORDINAL INDICATOR
+    0x00a8: 0x00bf,     #  INVERTED QUESTION MARK
+    0x00a9: 0x00ae,     #  REGISTERED SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00a1,     #  INVERTED EXCLAMATION MARK
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x00c1,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00b6: 0x00c2,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00b7: 0x00c0,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x00b8: 0x00a9,     #  COPYRIGHT SIGN
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x00a2,     #  CENT SIGN
+    0x00be: 0x00a5,     #  YEN SIGN
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x00e3,     #  LATIN SMALL LETTER A WITH TILDE
+    0x00c7: 0x00c3,     #  LATIN CAPITAL LETTER A WITH TILDE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x00a4,     #  CURRENCY SIGN
+    0x00d0: 0x00f0,     #  LATIN SMALL LETTER ETH
+    0x00d1: 0x00d0,     #  LATIN CAPITAL LETTER ETH
+    0x00d2: 0x00ca,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x00d3: 0x00cb,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00d4: 0x00c8,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x00d5: 0x0131,     #  LATIN SMALL LETTER DOTLESS I
+    0x00d6: 0x00cd,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00d7: 0x00ce,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00d8: 0x00cf,     #  LATIN CAPITAL LETTER I WITH DIAERESIS
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x00a6,     #  BROKEN BAR
+    0x00de: 0x00cc,     #  LATIN CAPITAL LETTER I WITH GRAVE
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x00d3,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x00d4,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00e3: 0x00d2,     #  LATIN CAPITAL LETTER O WITH GRAVE
+    0x00e4: 0x00f5,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00e5: 0x00d5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x00fe,     #  LATIN SMALL LETTER THORN
+    0x00e8: 0x00de,     #  LATIN CAPITAL LETTER THORN
+    0x00e9: 0x00da,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00ea: 0x00db,     #  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    0x00eb: 0x00d9,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x00ec: 0x00fd,     #  LATIN SMALL LETTER Y WITH ACUTE
+    0x00ed: 0x00dd,     #  LATIN CAPITAL LETTER Y WITH ACUTE
+    0x00ee: 0x00af,     #  MACRON
+    0x00ef: 0x00b4,     #  ACUTE ACCENT
+    0x00f0: 0x00ad,     #  SOFT HYPHEN
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2017,     #  DOUBLE LOW LINE
+    0x00f3: 0x00be,     #  VULGAR FRACTION THREE QUARTERS
+    0x00f4: 0x00b6,     #  PILCROW SIGN
+    0x00f5: 0x00a7,     #  SECTION SIGN
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x00b8,     #  CEDILLA
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x00a8,     #  DIAERESIS
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x00b9,     #  SUPERSCRIPT ONE
+    0x00fc: 0x00b3,     #  SUPERSCRIPT THREE
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x0085 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe5'     #  0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x008a -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xef'     #  0x008b -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xee'     #  0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xec'     #  0x008d -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xc4'     #  0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xe6'     #  0x0091 -> LATIN SMALL LIGATURE AE
+    u'\xc6'     #  0x0092 -> LATIN CAPITAL LIGATURE AE
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf2'     #  0x0095 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xfb'     #  0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xf9'     #  0x0097 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xff'     #  0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\xd6'     #  0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xf8'     #  0x009b -> LATIN SMALL LETTER O WITH STROKE
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xd8'     #  0x009d -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd7'     #  0x009e -> MULTIPLICATION SIGN
+    u'\u0192'   #  0x009f -> LATIN SMALL LETTER F WITH HOOK
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf1'     #  0x00a4 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xd1'     #  0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xaa'     #  0x00a6 -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x00a7 -> MASCULINE ORDINAL INDICATOR
+    u'\xbf'     #  0x00a8 -> INVERTED QUESTION MARK
+    u'\xae'     #  0x00a9 -> REGISTERED SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xa1'     #  0x00ad -> INVERTED EXCLAMATION MARK
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\xc1'     #  0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc0'     #  0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xa9'     #  0x00b8 -> COPYRIGHT SIGN
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\xa2'     #  0x00bd -> CENT SIGN
+    u'\xa5'     #  0x00be -> YEN SIGN
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\xe3'     #  0x00c6 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xc3'     #  0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\xa4'     #  0x00cf -> CURRENCY SIGN
+    u'\xf0'     #  0x00d0 -> LATIN SMALL LETTER ETH
+    u'\xd0'     #  0x00d1 -> LATIN CAPITAL LETTER ETH
+    u'\xca'     #  0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\u0131'   #  0x00d5 -> LATIN SMALL LETTER DOTLESS I
+    u'\xcd'     #  0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\xa6'     #  0x00dd -> BROKEN BAR
+    u'\xcc'     #  0x00de -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\xd3'     #  0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\xd4'     #  0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd2'     #  0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xf5'     #  0x00e4 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xd5'     #  0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\xfe'     #  0x00e7 -> LATIN SMALL LETTER THORN
+    u'\xde'     #  0x00e8 -> LATIN CAPITAL LETTER THORN
+    u'\xda'     #  0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xd9'     #  0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xfd'     #  0x00ec -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xdd'     #  0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xaf'     #  0x00ee -> MACRON
+    u'\xb4'     #  0x00ef -> ACUTE ACCENT
+    u'\xad'     #  0x00f0 -> SOFT HYPHEN
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2017'   #  0x00f2 -> DOUBLE LOW LINE
+    u'\xbe'     #  0x00f3 -> VULGAR FRACTION THREE QUARTERS
+    u'\xb6'     #  0x00f4 -> PILCROW SIGN
+    u'\xa7'     #  0x00f5 -> SECTION SIGN
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\xb8'     #  0x00f7 -> CEDILLA
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\xa8'     #  0x00f9 -> DIAERESIS
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\xb9'     #  0x00fb -> SUPERSCRIPT ONE
+    u'\xb3'     #  0x00fc -> SUPERSCRIPT THREE
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a1: 0x00ad,     #  INVERTED EXCLAMATION MARK
+    0x00a2: 0x00bd,     #  CENT SIGN
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a4: 0x00cf,     #  CURRENCY SIGN
+    0x00a5: 0x00be,     #  YEN SIGN
+    0x00a6: 0x00dd,     #  BROKEN BAR
+    0x00a7: 0x00f5,     #  SECTION SIGN
+    0x00a8: 0x00f9,     #  DIAERESIS
+    0x00a9: 0x00b8,     #  COPYRIGHT SIGN
+    0x00aa: 0x00a6,     #  FEMININE ORDINAL INDICATOR
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00ad: 0x00f0,     #  SOFT HYPHEN
+    0x00ae: 0x00a9,     #  REGISTERED SIGN
+    0x00af: 0x00ee,     #  MACRON
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b3: 0x00fc,     #  SUPERSCRIPT THREE
+    0x00b4: 0x00ef,     #  ACUTE ACCENT
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b6: 0x00f4,     #  PILCROW SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00b8: 0x00f7,     #  CEDILLA
+    0x00b9: 0x00fb,     #  SUPERSCRIPT ONE
+    0x00ba: 0x00a7,     #  MASCULINE ORDINAL INDICATOR
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00be: 0x00f3,     #  VULGAR FRACTION THREE QUARTERS
+    0x00bf: 0x00a8,     #  INVERTED QUESTION MARK
+    0x00c0: 0x00b7,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x00c1: 0x00b5,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00c2: 0x00b6,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00c3: 0x00c7,     #  LATIN CAPITAL LETTER A WITH TILDE
+    0x00c4: 0x008e,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c5: 0x008f,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x00c6: 0x0092,     #  LATIN CAPITAL LIGATURE AE
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c8: 0x00d4,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00ca: 0x00d2,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x00cb: 0x00d3,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00cc: 0x00de,     #  LATIN CAPITAL LETTER I WITH GRAVE
+    0x00cd: 0x00d6,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00ce: 0x00d7,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00cf: 0x00d8,     #  LATIN CAPITAL LETTER I WITH DIAERESIS
+    0x00d0: 0x00d1,     #  LATIN CAPITAL LETTER ETH
+    0x00d1: 0x00a5,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00d2: 0x00e3,     #  LATIN CAPITAL LETTER O WITH GRAVE
+    0x00d3: 0x00e0,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00d4: 0x00e2,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00d5: 0x00e5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00d6: 0x0099,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00d7: 0x009e,     #  MULTIPLICATION SIGN
+    0x00d8: 0x009d,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x00d9: 0x00eb,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x00da: 0x00e9,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00db: 0x00ea,     #  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00dd: 0x00ed,     #  LATIN CAPITAL LETTER Y WITH ACUTE
+    0x00de: 0x00e8,     #  LATIN CAPITAL LETTER THORN
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e0: 0x0085,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e3: 0x00c6,     #  LATIN SMALL LETTER A WITH TILDE
+    0x00e4: 0x0084,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e5: 0x0086,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x00e6: 0x0091,     #  LATIN SMALL LIGATURE AE
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008a,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0088,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00eb: 0x0089,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ec: 0x008d,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00ee: 0x008c,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x00ef: 0x008b,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x00f0: 0x00d0,     #  LATIN SMALL LETTER ETH
+    0x00f1: 0x00a4,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00f2: 0x0095,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f5: 0x00e4,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00f6: 0x0094,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f8: 0x009b,     #  LATIN SMALL LETTER O WITH STROKE
+    0x00f9: 0x0097,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fb: 0x0096,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x00fd: 0x00ec,     #  LATIN SMALL LETTER Y WITH ACUTE
+    0x00fe: 0x00e7,     #  LATIN SMALL LETTER THORN
+    0x00ff: 0x0098,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x0131: 0x00d5,     #  LATIN SMALL LETTER DOTLESS I
+    0x0192: 0x009f,     #  LATIN SMALL LETTER F WITH HOOK
+    0x2017: 0x00f2,     #  DOUBLE LOW LINE
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp852.py b/src/main/resources/PythonLibs/encodings/cp852.py
new file mode 100644
index 0000000000000000000000000000000000000000..069d5473b500050939696adeb78c41ae0ac9bdce
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp852.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP852.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp852',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x0085: 0x016f,     #  LATIN SMALL LETTER U WITH RING ABOVE
+    0x0086: 0x0107,     #  LATIN SMALL LETTER C WITH ACUTE
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x0142,     #  LATIN SMALL LETTER L WITH STROKE
+    0x0089: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x008a: 0x0150,     #  LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+    0x008b: 0x0151,     #  LATIN SMALL LETTER O WITH DOUBLE ACUTE
+    0x008c: 0x00ee,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x008d: 0x0179,     #  LATIN CAPITAL LETTER Z WITH ACUTE
+    0x008e: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x008f: 0x0106,     #  LATIN CAPITAL LETTER C WITH ACUTE
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x0139,     #  LATIN CAPITAL LETTER L WITH ACUTE
+    0x0092: 0x013a,     #  LATIN SMALL LETTER L WITH ACUTE
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x0095: 0x013d,     #  LATIN CAPITAL LETTER L WITH CARON
+    0x0096: 0x013e,     #  LATIN SMALL LETTER L WITH CARON
+    0x0097: 0x015a,     #  LATIN CAPITAL LETTER S WITH ACUTE
+    0x0098: 0x015b,     #  LATIN SMALL LETTER S WITH ACUTE
+    0x0099: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x0164,     #  LATIN CAPITAL LETTER T WITH CARON
+    0x009c: 0x0165,     #  LATIN SMALL LETTER T WITH CARON
+    0x009d: 0x0141,     #  LATIN CAPITAL LETTER L WITH STROKE
+    0x009e: 0x00d7,     #  MULTIPLICATION SIGN
+    0x009f: 0x010d,     #  LATIN SMALL LETTER C WITH CARON
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x0104,     #  LATIN CAPITAL LETTER A WITH OGONEK
+    0x00a5: 0x0105,     #  LATIN SMALL LETTER A WITH OGONEK
+    0x00a6: 0x017d,     #  LATIN CAPITAL LETTER Z WITH CARON
+    0x00a7: 0x017e,     #  LATIN SMALL LETTER Z WITH CARON
+    0x00a8: 0x0118,     #  LATIN CAPITAL LETTER E WITH OGONEK
+    0x00a9: 0x0119,     #  LATIN SMALL LETTER E WITH OGONEK
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x017a,     #  LATIN SMALL LETTER Z WITH ACUTE
+    0x00ac: 0x010c,     #  LATIN CAPITAL LETTER C WITH CARON
+    0x00ad: 0x015f,     #  LATIN SMALL LETTER S WITH CEDILLA
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x00c1,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00b6: 0x00c2,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00b7: 0x011a,     #  LATIN CAPITAL LETTER E WITH CARON
+    0x00b8: 0x015e,     #  LATIN CAPITAL LETTER S WITH CEDILLA
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x017b,     #  LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    0x00be: 0x017c,     #  LATIN SMALL LETTER Z WITH DOT ABOVE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x0102,     #  LATIN CAPITAL LETTER A WITH BREVE
+    0x00c7: 0x0103,     #  LATIN SMALL LETTER A WITH BREVE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x00a4,     #  CURRENCY SIGN
+    0x00d0: 0x0111,     #  LATIN SMALL LETTER D WITH STROKE
+    0x00d1: 0x0110,     #  LATIN CAPITAL LETTER D WITH STROKE
+    0x00d2: 0x010e,     #  LATIN CAPITAL LETTER D WITH CARON
+    0x00d3: 0x00cb,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00d4: 0x010f,     #  LATIN SMALL LETTER D WITH CARON
+    0x00d5: 0x0147,     #  LATIN CAPITAL LETTER N WITH CARON
+    0x00d6: 0x00cd,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00d7: 0x00ce,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00d8: 0x011b,     #  LATIN SMALL LETTER E WITH CARON
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x0162,     #  LATIN CAPITAL LETTER T WITH CEDILLA
+    0x00de: 0x016e,     #  LATIN CAPITAL LETTER U WITH RING ABOVE
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x00d3,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x00d4,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00e3: 0x0143,     #  LATIN CAPITAL LETTER N WITH ACUTE
+    0x00e4: 0x0144,     #  LATIN SMALL LETTER N WITH ACUTE
+    0x00e5: 0x0148,     #  LATIN SMALL LETTER N WITH CARON
+    0x00e6: 0x0160,     #  LATIN CAPITAL LETTER S WITH CARON
+    0x00e7: 0x0161,     #  LATIN SMALL LETTER S WITH CARON
+    0x00e8: 0x0154,     #  LATIN CAPITAL LETTER R WITH ACUTE
+    0x00e9: 0x00da,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00ea: 0x0155,     #  LATIN SMALL LETTER R WITH ACUTE
+    0x00eb: 0x0170,     #  LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+    0x00ec: 0x00fd,     #  LATIN SMALL LETTER Y WITH ACUTE
+    0x00ed: 0x00dd,     #  LATIN CAPITAL LETTER Y WITH ACUTE
+    0x00ee: 0x0163,     #  LATIN SMALL LETTER T WITH CEDILLA
+    0x00ef: 0x00b4,     #  ACUTE ACCENT
+    0x00f0: 0x00ad,     #  SOFT HYPHEN
+    0x00f1: 0x02dd,     #  DOUBLE ACUTE ACCENT
+    0x00f2: 0x02db,     #  OGONEK
+    0x00f3: 0x02c7,     #  CARON
+    0x00f4: 0x02d8,     #  BREVE
+    0x00f5: 0x00a7,     #  SECTION SIGN
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x00b8,     #  CEDILLA
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x00a8,     #  DIAERESIS
+    0x00fa: 0x02d9,     #  DOT ABOVE
+    0x00fb: 0x0171,     #  LATIN SMALL LETTER U WITH DOUBLE ACUTE
+    0x00fc: 0x0158,     #  LATIN CAPITAL LETTER R WITH CARON
+    0x00fd: 0x0159,     #  LATIN SMALL LETTER R WITH CARON
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u016f'   #  0x0085 -> LATIN SMALL LETTER U WITH RING ABOVE
+    u'\u0107'   #  0x0086 -> LATIN SMALL LETTER C WITH ACUTE
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\u0142'   #  0x0088 -> LATIN SMALL LETTER L WITH STROKE
+    u'\xeb'     #  0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\u0150'   #  0x008a -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+    u'\u0151'   #  0x008b -> LATIN SMALL LETTER O WITH DOUBLE ACUTE
+    u'\xee'     #  0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\u0179'   #  0x008d -> LATIN CAPITAL LETTER Z WITH ACUTE
+    u'\xc4'     #  0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\u0106'   #  0x008f -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\u0139'   #  0x0091 -> LATIN CAPITAL LETTER L WITH ACUTE
+    u'\u013a'   #  0x0092 -> LATIN SMALL LETTER L WITH ACUTE
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\u013d'   #  0x0095 -> LATIN CAPITAL LETTER L WITH CARON
+    u'\u013e'   #  0x0096 -> LATIN SMALL LETTER L WITH CARON
+    u'\u015a'   #  0x0097 -> LATIN CAPITAL LETTER S WITH ACUTE
+    u'\u015b'   #  0x0098 -> LATIN SMALL LETTER S WITH ACUTE
+    u'\xd6'     #  0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u0164'   #  0x009b -> LATIN CAPITAL LETTER T WITH CARON
+    u'\u0165'   #  0x009c -> LATIN SMALL LETTER T WITH CARON
+    u'\u0141'   #  0x009d -> LATIN CAPITAL LETTER L WITH STROKE
+    u'\xd7'     #  0x009e -> MULTIPLICATION SIGN
+    u'\u010d'   #  0x009f -> LATIN SMALL LETTER C WITH CARON
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\u0104'   #  0x00a4 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\u0105'   #  0x00a5 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u017d'   #  0x00a6 -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\u017e'   #  0x00a7 -> LATIN SMALL LETTER Z WITH CARON
+    u'\u0118'   #  0x00a8 -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\u0119'   #  0x00a9 -> LATIN SMALL LETTER E WITH OGONEK
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\u017a'   #  0x00ab -> LATIN SMALL LETTER Z WITH ACUTE
+    u'\u010c'   #  0x00ac -> LATIN CAPITAL LETTER C WITH CARON
+    u'\u015f'   #  0x00ad -> LATIN SMALL LETTER S WITH CEDILLA
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\xc1'     #  0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\u011a'   #  0x00b7 -> LATIN CAPITAL LETTER E WITH CARON
+    u'\u015e'   #  0x00b8 -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u017b'   #  0x00bd -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\u017c'   #  0x00be -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u0102'   #  0x00c6 -> LATIN CAPITAL LETTER A WITH BREVE
+    u'\u0103'   #  0x00c7 -> LATIN SMALL LETTER A WITH BREVE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\xa4'     #  0x00cf -> CURRENCY SIGN
+    u'\u0111'   #  0x00d0 -> LATIN SMALL LETTER D WITH STROKE
+    u'\u0110'   #  0x00d1 -> LATIN CAPITAL LETTER D WITH STROKE
+    u'\u010e'   #  0x00d2 -> LATIN CAPITAL LETTER D WITH CARON
+    u'\xcb'     #  0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\u010f'   #  0x00d4 -> LATIN SMALL LETTER D WITH CARON
+    u'\u0147'   #  0x00d5 -> LATIN CAPITAL LETTER N WITH CARON
+    u'\xcd'     #  0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\u011b'   #  0x00d8 -> LATIN SMALL LETTER E WITH CARON
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u0162'   #  0x00dd -> LATIN CAPITAL LETTER T WITH CEDILLA
+    u'\u016e'   #  0x00de -> LATIN CAPITAL LETTER U WITH RING ABOVE
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\xd3'     #  0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\xd4'     #  0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\u0143'   #  0x00e3 -> LATIN CAPITAL LETTER N WITH ACUTE
+    u'\u0144'   #  0x00e4 -> LATIN SMALL LETTER N WITH ACUTE
+    u'\u0148'   #  0x00e5 -> LATIN SMALL LETTER N WITH CARON
+    u'\u0160'   #  0x00e6 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u0161'   #  0x00e7 -> LATIN SMALL LETTER S WITH CARON
+    u'\u0154'   #  0x00e8 -> LATIN CAPITAL LETTER R WITH ACUTE
+    u'\xda'     #  0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\u0155'   #  0x00ea -> LATIN SMALL LETTER R WITH ACUTE
+    u'\u0170'   #  0x00eb -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+    u'\xfd'     #  0x00ec -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xdd'     #  0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\u0163'   #  0x00ee -> LATIN SMALL LETTER T WITH CEDILLA
+    u'\xb4'     #  0x00ef -> ACUTE ACCENT
+    u'\xad'     #  0x00f0 -> SOFT HYPHEN
+    u'\u02dd'   #  0x00f1 -> DOUBLE ACUTE ACCENT
+    u'\u02db'   #  0x00f2 -> OGONEK
+    u'\u02c7'   #  0x00f3 -> CARON
+    u'\u02d8'   #  0x00f4 -> BREVE
+    u'\xa7'     #  0x00f5 -> SECTION SIGN
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\xb8'     #  0x00f7 -> CEDILLA
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\xa8'     #  0x00f9 -> DIAERESIS
+    u'\u02d9'   #  0x00fa -> DOT ABOVE
+    u'\u0171'   #  0x00fb -> LATIN SMALL LETTER U WITH DOUBLE ACUTE
+    u'\u0158'   #  0x00fc -> LATIN CAPITAL LETTER R WITH CARON
+    u'\u0159'   #  0x00fd -> LATIN SMALL LETTER R WITH CARON
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a4: 0x00cf,     #  CURRENCY SIGN
+    0x00a7: 0x00f5,     #  SECTION SIGN
+    0x00a8: 0x00f9,     #  DIAERESIS
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00ad: 0x00f0,     #  SOFT HYPHEN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b4: 0x00ef,     #  ACUTE ACCENT
+    0x00b8: 0x00f7,     #  CEDILLA
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00c1: 0x00b5,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00c2: 0x00b6,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00c4: 0x008e,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00cb: 0x00d3,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00cd: 0x00d6,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00ce: 0x00d7,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00d3: 0x00e0,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00d4: 0x00e2,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00d6: 0x0099,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00d7: 0x009e,     #  MULTIPLICATION SIGN
+    0x00da: 0x00e9,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00dd: 0x00ed,     #  LATIN CAPITAL LETTER Y WITH ACUTE
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e4: 0x0084,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00eb: 0x0089,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00ee: 0x008c,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f6: 0x0094,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x00fd: 0x00ec,     #  LATIN SMALL LETTER Y WITH ACUTE
+    0x0102: 0x00c6,     #  LATIN CAPITAL LETTER A WITH BREVE
+    0x0103: 0x00c7,     #  LATIN SMALL LETTER A WITH BREVE
+    0x0104: 0x00a4,     #  LATIN CAPITAL LETTER A WITH OGONEK
+    0x0105: 0x00a5,     #  LATIN SMALL LETTER A WITH OGONEK
+    0x0106: 0x008f,     #  LATIN CAPITAL LETTER C WITH ACUTE
+    0x0107: 0x0086,     #  LATIN SMALL LETTER C WITH ACUTE
+    0x010c: 0x00ac,     #  LATIN CAPITAL LETTER C WITH CARON
+    0x010d: 0x009f,     #  LATIN SMALL LETTER C WITH CARON
+    0x010e: 0x00d2,     #  LATIN CAPITAL LETTER D WITH CARON
+    0x010f: 0x00d4,     #  LATIN SMALL LETTER D WITH CARON
+    0x0110: 0x00d1,     #  LATIN CAPITAL LETTER D WITH STROKE
+    0x0111: 0x00d0,     #  LATIN SMALL LETTER D WITH STROKE
+    0x0118: 0x00a8,     #  LATIN CAPITAL LETTER E WITH OGONEK
+    0x0119: 0x00a9,     #  LATIN SMALL LETTER E WITH OGONEK
+    0x011a: 0x00b7,     #  LATIN CAPITAL LETTER E WITH CARON
+    0x011b: 0x00d8,     #  LATIN SMALL LETTER E WITH CARON
+    0x0139: 0x0091,     #  LATIN CAPITAL LETTER L WITH ACUTE
+    0x013a: 0x0092,     #  LATIN SMALL LETTER L WITH ACUTE
+    0x013d: 0x0095,     #  LATIN CAPITAL LETTER L WITH CARON
+    0x013e: 0x0096,     #  LATIN SMALL LETTER L WITH CARON
+    0x0141: 0x009d,     #  LATIN CAPITAL LETTER L WITH STROKE
+    0x0142: 0x0088,     #  LATIN SMALL LETTER L WITH STROKE
+    0x0143: 0x00e3,     #  LATIN CAPITAL LETTER N WITH ACUTE
+    0x0144: 0x00e4,     #  LATIN SMALL LETTER N WITH ACUTE
+    0x0147: 0x00d5,     #  LATIN CAPITAL LETTER N WITH CARON
+    0x0148: 0x00e5,     #  LATIN SMALL LETTER N WITH CARON
+    0x0150: 0x008a,     #  LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+    0x0151: 0x008b,     #  LATIN SMALL LETTER O WITH DOUBLE ACUTE
+    0x0154: 0x00e8,     #  LATIN CAPITAL LETTER R WITH ACUTE
+    0x0155: 0x00ea,     #  LATIN SMALL LETTER R WITH ACUTE
+    0x0158: 0x00fc,     #  LATIN CAPITAL LETTER R WITH CARON
+    0x0159: 0x00fd,     #  LATIN SMALL LETTER R WITH CARON
+    0x015a: 0x0097,     #  LATIN CAPITAL LETTER S WITH ACUTE
+    0x015b: 0x0098,     #  LATIN SMALL LETTER S WITH ACUTE
+    0x015e: 0x00b8,     #  LATIN CAPITAL LETTER S WITH CEDILLA
+    0x015f: 0x00ad,     #  LATIN SMALL LETTER S WITH CEDILLA
+    0x0160: 0x00e6,     #  LATIN CAPITAL LETTER S WITH CARON
+    0x0161: 0x00e7,     #  LATIN SMALL LETTER S WITH CARON
+    0x0162: 0x00dd,     #  LATIN CAPITAL LETTER T WITH CEDILLA
+    0x0163: 0x00ee,     #  LATIN SMALL LETTER T WITH CEDILLA
+    0x0164: 0x009b,     #  LATIN CAPITAL LETTER T WITH CARON
+    0x0165: 0x009c,     #  LATIN SMALL LETTER T WITH CARON
+    0x016e: 0x00de,     #  LATIN CAPITAL LETTER U WITH RING ABOVE
+    0x016f: 0x0085,     #  LATIN SMALL LETTER U WITH RING ABOVE
+    0x0170: 0x00eb,     #  LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+    0x0171: 0x00fb,     #  LATIN SMALL LETTER U WITH DOUBLE ACUTE
+    0x0179: 0x008d,     #  LATIN CAPITAL LETTER Z WITH ACUTE
+    0x017a: 0x00ab,     #  LATIN SMALL LETTER Z WITH ACUTE
+    0x017b: 0x00bd,     #  LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    0x017c: 0x00be,     #  LATIN SMALL LETTER Z WITH DOT ABOVE
+    0x017d: 0x00a6,     #  LATIN CAPITAL LETTER Z WITH CARON
+    0x017e: 0x00a7,     #  LATIN SMALL LETTER Z WITH CARON
+    0x02c7: 0x00f3,     #  CARON
+    0x02d8: 0x00f4,     #  BREVE
+    0x02d9: 0x00fa,     #  DOT ABOVE
+    0x02db: 0x00f2,     #  OGONEK
+    0x02dd: 0x00f1,     #  DOUBLE ACUTE ACCENT
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp855.py b/src/main/resources/PythonLibs/encodings/cp855.py
new file mode 100644
index 0000000000000000000000000000000000000000..241ef9d1e86e4edb1c8452d8aecafb8670c8a2d0
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp855.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP855.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp855',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x0452,     #  CYRILLIC SMALL LETTER DJE
+    0x0081: 0x0402,     #  CYRILLIC CAPITAL LETTER DJE
+    0x0082: 0x0453,     #  CYRILLIC SMALL LETTER GJE
+    0x0083: 0x0403,     #  CYRILLIC CAPITAL LETTER GJE
+    0x0084: 0x0451,     #  CYRILLIC SMALL LETTER IO
+    0x0085: 0x0401,     #  CYRILLIC CAPITAL LETTER IO
+    0x0086: 0x0454,     #  CYRILLIC SMALL LETTER UKRAINIAN IE
+    0x0087: 0x0404,     #  CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    0x0088: 0x0455,     #  CYRILLIC SMALL LETTER DZE
+    0x0089: 0x0405,     #  CYRILLIC CAPITAL LETTER DZE
+    0x008a: 0x0456,     #  CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+    0x008b: 0x0406,     #  CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+    0x008c: 0x0457,     #  CYRILLIC SMALL LETTER YI
+    0x008d: 0x0407,     #  CYRILLIC CAPITAL LETTER YI
+    0x008e: 0x0458,     #  CYRILLIC SMALL LETTER JE
+    0x008f: 0x0408,     #  CYRILLIC CAPITAL LETTER JE
+    0x0090: 0x0459,     #  CYRILLIC SMALL LETTER LJE
+    0x0091: 0x0409,     #  CYRILLIC CAPITAL LETTER LJE
+    0x0092: 0x045a,     #  CYRILLIC SMALL LETTER NJE
+    0x0093: 0x040a,     #  CYRILLIC CAPITAL LETTER NJE
+    0x0094: 0x045b,     #  CYRILLIC SMALL LETTER TSHE
+    0x0095: 0x040b,     #  CYRILLIC CAPITAL LETTER TSHE
+    0x0096: 0x045c,     #  CYRILLIC SMALL LETTER KJE
+    0x0097: 0x040c,     #  CYRILLIC CAPITAL LETTER KJE
+    0x0098: 0x045e,     #  CYRILLIC SMALL LETTER SHORT U
+    0x0099: 0x040e,     #  CYRILLIC CAPITAL LETTER SHORT U
+    0x009a: 0x045f,     #  CYRILLIC SMALL LETTER DZHE
+    0x009b: 0x040f,     #  CYRILLIC CAPITAL LETTER DZHE
+    0x009c: 0x044e,     #  CYRILLIC SMALL LETTER YU
+    0x009d: 0x042e,     #  CYRILLIC CAPITAL LETTER YU
+    0x009e: 0x044a,     #  CYRILLIC SMALL LETTER HARD SIGN
+    0x009f: 0x042a,     #  CYRILLIC CAPITAL LETTER HARD SIGN
+    0x00a0: 0x0430,     #  CYRILLIC SMALL LETTER A
+    0x00a1: 0x0410,     #  CYRILLIC CAPITAL LETTER A
+    0x00a2: 0x0431,     #  CYRILLIC SMALL LETTER BE
+    0x00a3: 0x0411,     #  CYRILLIC CAPITAL LETTER BE
+    0x00a4: 0x0446,     #  CYRILLIC SMALL LETTER TSE
+    0x00a5: 0x0426,     #  CYRILLIC CAPITAL LETTER TSE
+    0x00a6: 0x0434,     #  CYRILLIC SMALL LETTER DE
+    0x00a7: 0x0414,     #  CYRILLIC CAPITAL LETTER DE
+    0x00a8: 0x0435,     #  CYRILLIC SMALL LETTER IE
+    0x00a9: 0x0415,     #  CYRILLIC CAPITAL LETTER IE
+    0x00aa: 0x0444,     #  CYRILLIC SMALL LETTER EF
+    0x00ab: 0x0424,     #  CYRILLIC CAPITAL LETTER EF
+    0x00ac: 0x0433,     #  CYRILLIC SMALL LETTER GHE
+    0x00ad: 0x0413,     #  CYRILLIC CAPITAL LETTER GHE
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x0445,     #  CYRILLIC SMALL LETTER HA
+    0x00b6: 0x0425,     #  CYRILLIC CAPITAL LETTER HA
+    0x00b7: 0x0438,     #  CYRILLIC SMALL LETTER I
+    0x00b8: 0x0418,     #  CYRILLIC CAPITAL LETTER I
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x0439,     #  CYRILLIC SMALL LETTER SHORT I
+    0x00be: 0x0419,     #  CYRILLIC CAPITAL LETTER SHORT I
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x043a,     #  CYRILLIC SMALL LETTER KA
+    0x00c7: 0x041a,     #  CYRILLIC CAPITAL LETTER KA
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x00a4,     #  CURRENCY SIGN
+    0x00d0: 0x043b,     #  CYRILLIC SMALL LETTER EL
+    0x00d1: 0x041b,     #  CYRILLIC CAPITAL LETTER EL
+    0x00d2: 0x043c,     #  CYRILLIC SMALL LETTER EM
+    0x00d3: 0x041c,     #  CYRILLIC CAPITAL LETTER EM
+    0x00d4: 0x043d,     #  CYRILLIC SMALL LETTER EN
+    0x00d5: 0x041d,     #  CYRILLIC CAPITAL LETTER EN
+    0x00d6: 0x043e,     #  CYRILLIC SMALL LETTER O
+    0x00d7: 0x041e,     #  CYRILLIC CAPITAL LETTER O
+    0x00d8: 0x043f,     #  CYRILLIC SMALL LETTER PE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x041f,     #  CYRILLIC CAPITAL LETTER PE
+    0x00de: 0x044f,     #  CYRILLIC SMALL LETTER YA
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x042f,     #  CYRILLIC CAPITAL LETTER YA
+    0x00e1: 0x0440,     #  CYRILLIC SMALL LETTER ER
+    0x00e2: 0x0420,     #  CYRILLIC CAPITAL LETTER ER
+    0x00e3: 0x0441,     #  CYRILLIC SMALL LETTER ES
+    0x00e4: 0x0421,     #  CYRILLIC CAPITAL LETTER ES
+    0x00e5: 0x0442,     #  CYRILLIC SMALL LETTER TE
+    0x00e6: 0x0422,     #  CYRILLIC CAPITAL LETTER TE
+    0x00e7: 0x0443,     #  CYRILLIC SMALL LETTER U
+    0x00e8: 0x0423,     #  CYRILLIC CAPITAL LETTER U
+    0x00e9: 0x0436,     #  CYRILLIC SMALL LETTER ZHE
+    0x00ea: 0x0416,     #  CYRILLIC CAPITAL LETTER ZHE
+    0x00eb: 0x0432,     #  CYRILLIC SMALL LETTER VE
+    0x00ec: 0x0412,     #  CYRILLIC CAPITAL LETTER VE
+    0x00ed: 0x044c,     #  CYRILLIC SMALL LETTER SOFT SIGN
+    0x00ee: 0x042c,     #  CYRILLIC CAPITAL LETTER SOFT SIGN
+    0x00ef: 0x2116,     #  NUMERO SIGN
+    0x00f0: 0x00ad,     #  SOFT HYPHEN
+    0x00f1: 0x044b,     #  CYRILLIC SMALL LETTER YERU
+    0x00f2: 0x042b,     #  CYRILLIC CAPITAL LETTER YERU
+    0x00f3: 0x0437,     #  CYRILLIC SMALL LETTER ZE
+    0x00f4: 0x0417,     #  CYRILLIC CAPITAL LETTER ZE
+    0x00f5: 0x0448,     #  CYRILLIC SMALL LETTER SHA
+    0x00f6: 0x0428,     #  CYRILLIC CAPITAL LETTER SHA
+    0x00f7: 0x044d,     #  CYRILLIC SMALL LETTER E
+    0x00f8: 0x042d,     #  CYRILLIC CAPITAL LETTER E
+    0x00f9: 0x0449,     #  CYRILLIC SMALL LETTER SHCHA
+    0x00fa: 0x0429,     #  CYRILLIC CAPITAL LETTER SHCHA
+    0x00fb: 0x0447,     #  CYRILLIC SMALL LETTER CHE
+    0x00fc: 0x0427,     #  CYRILLIC CAPITAL LETTER CHE
+    0x00fd: 0x00a7,     #  SECTION SIGN
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\u0452'   #  0x0080 -> CYRILLIC SMALL LETTER DJE
+    u'\u0402'   #  0x0081 -> CYRILLIC CAPITAL LETTER DJE
+    u'\u0453'   #  0x0082 -> CYRILLIC SMALL LETTER GJE
+    u'\u0403'   #  0x0083 -> CYRILLIC CAPITAL LETTER GJE
+    u'\u0451'   #  0x0084 -> CYRILLIC SMALL LETTER IO
+    u'\u0401'   #  0x0085 -> CYRILLIC CAPITAL LETTER IO
+    u'\u0454'   #  0x0086 -> CYRILLIC SMALL LETTER UKRAINIAN IE
+    u'\u0404'   #  0x0087 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    u'\u0455'   #  0x0088 -> CYRILLIC SMALL LETTER DZE
+    u'\u0405'   #  0x0089 -> CYRILLIC CAPITAL LETTER DZE
+    u'\u0456'   #  0x008a -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\u0406'   #  0x008b -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\u0457'   #  0x008c -> CYRILLIC SMALL LETTER YI
+    u'\u0407'   #  0x008d -> CYRILLIC CAPITAL LETTER YI
+    u'\u0458'   #  0x008e -> CYRILLIC SMALL LETTER JE
+    u'\u0408'   #  0x008f -> CYRILLIC CAPITAL LETTER JE
+    u'\u0459'   #  0x0090 -> CYRILLIC SMALL LETTER LJE
+    u'\u0409'   #  0x0091 -> CYRILLIC CAPITAL LETTER LJE
+    u'\u045a'   #  0x0092 -> CYRILLIC SMALL LETTER NJE
+    u'\u040a'   #  0x0093 -> CYRILLIC CAPITAL LETTER NJE
+    u'\u045b'   #  0x0094 -> CYRILLIC SMALL LETTER TSHE
+    u'\u040b'   #  0x0095 -> CYRILLIC CAPITAL LETTER TSHE
+    u'\u045c'   #  0x0096 -> CYRILLIC SMALL LETTER KJE
+    u'\u040c'   #  0x0097 -> CYRILLIC CAPITAL LETTER KJE
+    u'\u045e'   #  0x0098 -> CYRILLIC SMALL LETTER SHORT U
+    u'\u040e'   #  0x0099 -> CYRILLIC CAPITAL LETTER SHORT U
+    u'\u045f'   #  0x009a -> CYRILLIC SMALL LETTER DZHE
+    u'\u040f'   #  0x009b -> CYRILLIC CAPITAL LETTER DZHE
+    u'\u044e'   #  0x009c -> CYRILLIC SMALL LETTER YU
+    u'\u042e'   #  0x009d -> CYRILLIC CAPITAL LETTER YU
+    u'\u044a'   #  0x009e -> CYRILLIC SMALL LETTER HARD SIGN
+    u'\u042a'   #  0x009f -> CYRILLIC CAPITAL LETTER HARD SIGN
+    u'\u0430'   #  0x00a0 -> CYRILLIC SMALL LETTER A
+    u'\u0410'   #  0x00a1 -> CYRILLIC CAPITAL LETTER A
+    u'\u0431'   #  0x00a2 -> CYRILLIC SMALL LETTER BE
+    u'\u0411'   #  0x00a3 -> CYRILLIC CAPITAL LETTER BE
+    u'\u0446'   #  0x00a4 -> CYRILLIC SMALL LETTER TSE
+    u'\u0426'   #  0x00a5 -> CYRILLIC CAPITAL LETTER TSE
+    u'\u0434'   #  0x00a6 -> CYRILLIC SMALL LETTER DE
+    u'\u0414'   #  0x00a7 -> CYRILLIC CAPITAL LETTER DE
+    u'\u0435'   #  0x00a8 -> CYRILLIC SMALL LETTER IE
+    u'\u0415'   #  0x00a9 -> CYRILLIC CAPITAL LETTER IE
+    u'\u0444'   #  0x00aa -> CYRILLIC SMALL LETTER EF
+    u'\u0424'   #  0x00ab -> CYRILLIC CAPITAL LETTER EF
+    u'\u0433'   #  0x00ac -> CYRILLIC SMALL LETTER GHE
+    u'\u0413'   #  0x00ad -> CYRILLIC CAPITAL LETTER GHE
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u0445'   #  0x00b5 -> CYRILLIC SMALL LETTER HA
+    u'\u0425'   #  0x00b6 -> CYRILLIC CAPITAL LETTER HA
+    u'\u0438'   #  0x00b7 -> CYRILLIC SMALL LETTER I
+    u'\u0418'   #  0x00b8 -> CYRILLIC CAPITAL LETTER I
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u0439'   #  0x00bd -> CYRILLIC SMALL LETTER SHORT I
+    u'\u0419'   #  0x00be -> CYRILLIC CAPITAL LETTER SHORT I
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u043a'   #  0x00c6 -> CYRILLIC SMALL LETTER KA
+    u'\u041a'   #  0x00c7 -> CYRILLIC CAPITAL LETTER KA
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\xa4'     #  0x00cf -> CURRENCY SIGN
+    u'\u043b'   #  0x00d0 -> CYRILLIC SMALL LETTER EL
+    u'\u041b'   #  0x00d1 -> CYRILLIC CAPITAL LETTER EL
+    u'\u043c'   #  0x00d2 -> CYRILLIC SMALL LETTER EM
+    u'\u041c'   #  0x00d3 -> CYRILLIC CAPITAL LETTER EM
+    u'\u043d'   #  0x00d4 -> CYRILLIC SMALL LETTER EN
+    u'\u041d'   #  0x00d5 -> CYRILLIC CAPITAL LETTER EN
+    u'\u043e'   #  0x00d6 -> CYRILLIC SMALL LETTER O
+    u'\u041e'   #  0x00d7 -> CYRILLIC CAPITAL LETTER O
+    u'\u043f'   #  0x00d8 -> CYRILLIC SMALL LETTER PE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u041f'   #  0x00dd -> CYRILLIC CAPITAL LETTER PE
+    u'\u044f'   #  0x00de -> CYRILLIC SMALL LETTER YA
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u042f'   #  0x00e0 -> CYRILLIC CAPITAL LETTER YA
+    u'\u0440'   #  0x00e1 -> CYRILLIC SMALL LETTER ER
+    u'\u0420'   #  0x00e2 -> CYRILLIC CAPITAL LETTER ER
+    u'\u0441'   #  0x00e3 -> CYRILLIC SMALL LETTER ES
+    u'\u0421'   #  0x00e4 -> CYRILLIC CAPITAL LETTER ES
+    u'\u0442'   #  0x00e5 -> CYRILLIC SMALL LETTER TE
+    u'\u0422'   #  0x00e6 -> CYRILLIC CAPITAL LETTER TE
+    u'\u0443'   #  0x00e7 -> CYRILLIC SMALL LETTER U
+    u'\u0423'   #  0x00e8 -> CYRILLIC CAPITAL LETTER U
+    u'\u0436'   #  0x00e9 -> CYRILLIC SMALL LETTER ZHE
+    u'\u0416'   #  0x00ea -> CYRILLIC CAPITAL LETTER ZHE
+    u'\u0432'   #  0x00eb -> CYRILLIC SMALL LETTER VE
+    u'\u0412'   #  0x00ec -> CYRILLIC CAPITAL LETTER VE
+    u'\u044c'   #  0x00ed -> CYRILLIC SMALL LETTER SOFT SIGN
+    u'\u042c'   #  0x00ee -> CYRILLIC CAPITAL LETTER SOFT SIGN
+    u'\u2116'   #  0x00ef -> NUMERO SIGN
+    u'\xad'     #  0x00f0 -> SOFT HYPHEN
+    u'\u044b'   #  0x00f1 -> CYRILLIC SMALL LETTER YERU
+    u'\u042b'   #  0x00f2 -> CYRILLIC CAPITAL LETTER YERU
+    u'\u0437'   #  0x00f3 -> CYRILLIC SMALL LETTER ZE
+    u'\u0417'   #  0x00f4 -> CYRILLIC CAPITAL LETTER ZE
+    u'\u0448'   #  0x00f5 -> CYRILLIC SMALL LETTER SHA
+    u'\u0428'   #  0x00f6 -> CYRILLIC CAPITAL LETTER SHA
+    u'\u044d'   #  0x00f7 -> CYRILLIC SMALL LETTER E
+    u'\u042d'   #  0x00f8 -> CYRILLIC CAPITAL LETTER E
+    u'\u0449'   #  0x00f9 -> CYRILLIC SMALL LETTER SHCHA
+    u'\u0429'   #  0x00fa -> CYRILLIC CAPITAL LETTER SHCHA
+    u'\u0447'   #  0x00fb -> CYRILLIC SMALL LETTER CHE
+    u'\u0427'   #  0x00fc -> CYRILLIC CAPITAL LETTER CHE
+    u'\xa7'     #  0x00fd -> SECTION SIGN
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a4: 0x00cf,     #  CURRENCY SIGN
+    0x00a7: 0x00fd,     #  SECTION SIGN
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ad: 0x00f0,     #  SOFT HYPHEN
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x0401: 0x0085,     #  CYRILLIC CAPITAL LETTER IO
+    0x0402: 0x0081,     #  CYRILLIC CAPITAL LETTER DJE
+    0x0403: 0x0083,     #  CYRILLIC CAPITAL LETTER GJE
+    0x0404: 0x0087,     #  CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    0x0405: 0x0089,     #  CYRILLIC CAPITAL LETTER DZE
+    0x0406: 0x008b,     #  CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+    0x0407: 0x008d,     #  CYRILLIC CAPITAL LETTER YI
+    0x0408: 0x008f,     #  CYRILLIC CAPITAL LETTER JE
+    0x0409: 0x0091,     #  CYRILLIC CAPITAL LETTER LJE
+    0x040a: 0x0093,     #  CYRILLIC CAPITAL LETTER NJE
+    0x040b: 0x0095,     #  CYRILLIC CAPITAL LETTER TSHE
+    0x040c: 0x0097,     #  CYRILLIC CAPITAL LETTER KJE
+    0x040e: 0x0099,     #  CYRILLIC CAPITAL LETTER SHORT U
+    0x040f: 0x009b,     #  CYRILLIC CAPITAL LETTER DZHE
+    0x0410: 0x00a1,     #  CYRILLIC CAPITAL LETTER A
+    0x0411: 0x00a3,     #  CYRILLIC CAPITAL LETTER BE
+    0x0412: 0x00ec,     #  CYRILLIC CAPITAL LETTER VE
+    0x0413: 0x00ad,     #  CYRILLIC CAPITAL LETTER GHE
+    0x0414: 0x00a7,     #  CYRILLIC CAPITAL LETTER DE
+    0x0415: 0x00a9,     #  CYRILLIC CAPITAL LETTER IE
+    0x0416: 0x00ea,     #  CYRILLIC CAPITAL LETTER ZHE
+    0x0417: 0x00f4,     #  CYRILLIC CAPITAL LETTER ZE
+    0x0418: 0x00b8,     #  CYRILLIC CAPITAL LETTER I
+    0x0419: 0x00be,     #  CYRILLIC CAPITAL LETTER SHORT I
+    0x041a: 0x00c7,     #  CYRILLIC CAPITAL LETTER KA
+    0x041b: 0x00d1,     #  CYRILLIC CAPITAL LETTER EL
+    0x041c: 0x00d3,     #  CYRILLIC CAPITAL LETTER EM
+    0x041d: 0x00d5,     #  CYRILLIC CAPITAL LETTER EN
+    0x041e: 0x00d7,     #  CYRILLIC CAPITAL LETTER O
+    0x041f: 0x00dd,     #  CYRILLIC CAPITAL LETTER PE
+    0x0420: 0x00e2,     #  CYRILLIC CAPITAL LETTER ER
+    0x0421: 0x00e4,     #  CYRILLIC CAPITAL LETTER ES
+    0x0422: 0x00e6,     #  CYRILLIC CAPITAL LETTER TE
+    0x0423: 0x00e8,     #  CYRILLIC CAPITAL LETTER U
+    0x0424: 0x00ab,     #  CYRILLIC CAPITAL LETTER EF
+    0x0425: 0x00b6,     #  CYRILLIC CAPITAL LETTER HA
+    0x0426: 0x00a5,     #  CYRILLIC CAPITAL LETTER TSE
+    0x0427: 0x00fc,     #  CYRILLIC CAPITAL LETTER CHE
+    0x0428: 0x00f6,     #  CYRILLIC CAPITAL LETTER SHA
+    0x0429: 0x00fa,     #  CYRILLIC CAPITAL LETTER SHCHA
+    0x042a: 0x009f,     #  CYRILLIC CAPITAL LETTER HARD SIGN
+    0x042b: 0x00f2,     #  CYRILLIC CAPITAL LETTER YERU
+    0x042c: 0x00ee,     #  CYRILLIC CAPITAL LETTER SOFT SIGN
+    0x042d: 0x00f8,     #  CYRILLIC CAPITAL LETTER E
+    0x042e: 0x009d,     #  CYRILLIC CAPITAL LETTER YU
+    0x042f: 0x00e0,     #  CYRILLIC CAPITAL LETTER YA
+    0x0430: 0x00a0,     #  CYRILLIC SMALL LETTER A
+    0x0431: 0x00a2,     #  CYRILLIC SMALL LETTER BE
+    0x0432: 0x00eb,     #  CYRILLIC SMALL LETTER VE
+    0x0433: 0x00ac,     #  CYRILLIC SMALL LETTER GHE
+    0x0434: 0x00a6,     #  CYRILLIC SMALL LETTER DE
+    0x0435: 0x00a8,     #  CYRILLIC SMALL LETTER IE
+    0x0436: 0x00e9,     #  CYRILLIC SMALL LETTER ZHE
+    0x0437: 0x00f3,     #  CYRILLIC SMALL LETTER ZE
+    0x0438: 0x00b7,     #  CYRILLIC SMALL LETTER I
+    0x0439: 0x00bd,     #  CYRILLIC SMALL LETTER SHORT I
+    0x043a: 0x00c6,     #  CYRILLIC SMALL LETTER KA
+    0x043b: 0x00d0,     #  CYRILLIC SMALL LETTER EL
+    0x043c: 0x00d2,     #  CYRILLIC SMALL LETTER EM
+    0x043d: 0x00d4,     #  CYRILLIC SMALL LETTER EN
+    0x043e: 0x00d6,     #  CYRILLIC SMALL LETTER O
+    0x043f: 0x00d8,     #  CYRILLIC SMALL LETTER PE
+    0x0440: 0x00e1,     #  CYRILLIC SMALL LETTER ER
+    0x0441: 0x00e3,     #  CYRILLIC SMALL LETTER ES
+    0x0442: 0x00e5,     #  CYRILLIC SMALL LETTER TE
+    0x0443: 0x00e7,     #  CYRILLIC SMALL LETTER U
+    0x0444: 0x00aa,     #  CYRILLIC SMALL LETTER EF
+    0x0445: 0x00b5,     #  CYRILLIC SMALL LETTER HA
+    0x0446: 0x00a4,     #  CYRILLIC SMALL LETTER TSE
+    0x0447: 0x00fb,     #  CYRILLIC SMALL LETTER CHE
+    0x0448: 0x00f5,     #  CYRILLIC SMALL LETTER SHA
+    0x0449: 0x00f9,     #  CYRILLIC SMALL LETTER SHCHA
+    0x044a: 0x009e,     #  CYRILLIC SMALL LETTER HARD SIGN
+    0x044b: 0x00f1,     #  CYRILLIC SMALL LETTER YERU
+    0x044c: 0x00ed,     #  CYRILLIC SMALL LETTER SOFT SIGN
+    0x044d: 0x00f7,     #  CYRILLIC SMALL LETTER E
+    0x044e: 0x009c,     #  CYRILLIC SMALL LETTER YU
+    0x044f: 0x00de,     #  CYRILLIC SMALL LETTER YA
+    0x0451: 0x0084,     #  CYRILLIC SMALL LETTER IO
+    0x0452: 0x0080,     #  CYRILLIC SMALL LETTER DJE
+    0x0453: 0x0082,     #  CYRILLIC SMALL LETTER GJE
+    0x0454: 0x0086,     #  CYRILLIC SMALL LETTER UKRAINIAN IE
+    0x0455: 0x0088,     #  CYRILLIC SMALL LETTER DZE
+    0x0456: 0x008a,     #  CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+    0x0457: 0x008c,     #  CYRILLIC SMALL LETTER YI
+    0x0458: 0x008e,     #  CYRILLIC SMALL LETTER JE
+    0x0459: 0x0090,     #  CYRILLIC SMALL LETTER LJE
+    0x045a: 0x0092,     #  CYRILLIC SMALL LETTER NJE
+    0x045b: 0x0094,     #  CYRILLIC SMALL LETTER TSHE
+    0x045c: 0x0096,     #  CYRILLIC SMALL LETTER KJE
+    0x045e: 0x0098,     #  CYRILLIC SMALL LETTER SHORT U
+    0x045f: 0x009a,     #  CYRILLIC SMALL LETTER DZHE
+    0x2116: 0x00ef,     #  NUMERO SIGN
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp856.py b/src/main/resources/PythonLibs/encodings/cp856.py
new file mode 100644
index 0000000000000000000000000000000000000000..203c2c4ca0f9edde3bab1786719b592d624894ce
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp856.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp856 generated from 'MAPPINGS/VENDORS/MISC/CP856.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp856',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u05d0'   #  0x80 -> HEBREW LETTER ALEF
+    u'\u05d1'   #  0x81 -> HEBREW LETTER BET
+    u'\u05d2'   #  0x82 -> HEBREW LETTER GIMEL
+    u'\u05d3'   #  0x83 -> HEBREW LETTER DALET
+    u'\u05d4'   #  0x84 -> HEBREW LETTER HE
+    u'\u05d5'   #  0x85 -> HEBREW LETTER VAV
+    u'\u05d6'   #  0x86 -> HEBREW LETTER ZAYIN
+    u'\u05d7'   #  0x87 -> HEBREW LETTER HET
+    u'\u05d8'   #  0x88 -> HEBREW LETTER TET
+    u'\u05d9'   #  0x89 -> HEBREW LETTER YOD
+    u'\u05da'   #  0x8A -> HEBREW LETTER FINAL KAF
+    u'\u05db'   #  0x8B -> HEBREW LETTER KAF
+    u'\u05dc'   #  0x8C -> HEBREW LETTER LAMED
+    u'\u05dd'   #  0x8D -> HEBREW LETTER FINAL MEM
+    u'\u05de'   #  0x8E -> HEBREW LETTER MEM
+    u'\u05df'   #  0x8F -> HEBREW LETTER FINAL NUN
+    u'\u05e0'   #  0x90 -> HEBREW LETTER NUN
+    u'\u05e1'   #  0x91 -> HEBREW LETTER SAMEKH
+    u'\u05e2'   #  0x92 -> HEBREW LETTER AYIN
+    u'\u05e3'   #  0x93 -> HEBREW LETTER FINAL PE
+    u'\u05e4'   #  0x94 -> HEBREW LETTER PE
+    u'\u05e5'   #  0x95 -> HEBREW LETTER FINAL TSADI
+    u'\u05e6'   #  0x96 -> HEBREW LETTER TSADI
+    u'\u05e7'   #  0x97 -> HEBREW LETTER QOF
+    u'\u05e8'   #  0x98 -> HEBREW LETTER RESH
+    u'\u05e9'   #  0x99 -> HEBREW LETTER SHIN
+    u'\u05ea'   #  0x9A -> HEBREW LETTER TAV
+    u'\ufffe'   #  0x9B -> UNDEFINED
+    u'\xa3'     #  0x9C -> POUND SIGN
+    u'\ufffe'   #  0x9D -> UNDEFINED
+    u'\xd7'     #  0x9E -> MULTIPLICATION SIGN
+    u'\ufffe'   #  0x9F -> UNDEFINED
+    u'\ufffe'   #  0xA0 -> UNDEFINED
+    u'\ufffe'   #  0xA1 -> UNDEFINED
+    u'\ufffe'   #  0xA2 -> UNDEFINED
+    u'\ufffe'   #  0xA3 -> UNDEFINED
+    u'\ufffe'   #  0xA4 -> UNDEFINED
+    u'\ufffe'   #  0xA5 -> UNDEFINED
+    u'\ufffe'   #  0xA6 -> UNDEFINED
+    u'\ufffe'   #  0xA7 -> UNDEFINED
+    u'\ufffe'   #  0xA8 -> UNDEFINED
+    u'\xae'     #  0xA9 -> REGISTERED SIGN
+    u'\xac'     #  0xAA -> NOT SIGN
+    u'\xbd'     #  0xAB -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0xAC -> VULGAR FRACTION ONE QUARTER
+    u'\ufffe'   #  0xAD -> UNDEFINED
+    u'\xab'     #  0xAE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xAF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0xB0 -> LIGHT SHADE
+    u'\u2592'   #  0xB1 -> MEDIUM SHADE
+    u'\u2593'   #  0xB2 -> DARK SHADE
+    u'\u2502'   #  0xB3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0xB4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\ufffe'   #  0xB5 -> UNDEFINED
+    u'\ufffe'   #  0xB6 -> UNDEFINED
+    u'\ufffe'   #  0xB7 -> UNDEFINED
+    u'\xa9'     #  0xB8 -> COPYRIGHT SIGN
+    u'\u2563'   #  0xB9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0xBA -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0xBB -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0xBC -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\xa2'     #  0xBD -> CENT SIGN
+    u'\xa5'     #  0xBE -> YEN SIGN
+    u'\u2510'   #  0xBF -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0xC0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0xC1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0xC2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0xC3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0xC4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0xC5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\ufffe'   #  0xC6 -> UNDEFINED
+    u'\ufffe'   #  0xC7 -> UNDEFINED
+    u'\u255a'   #  0xC8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0xC9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0xCA -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0xCB -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0xCC -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0xCD -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0xCE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\xa4'     #  0xCF -> CURRENCY SIGN
+    u'\ufffe'   #  0xD0 -> UNDEFINED
+    u'\ufffe'   #  0xD1 -> UNDEFINED
+    u'\ufffe'   #  0xD2 -> UNDEFINED
+    u'\ufffe'   #  0xD3 -> UNDEFINEDS
+    u'\ufffe'   #  0xD4 -> UNDEFINED
+    u'\ufffe'   #  0xD5 -> UNDEFINED
+    u'\ufffe'   #  0xD6 -> UNDEFINEDE
+    u'\ufffe'   #  0xD7 -> UNDEFINED
+    u'\ufffe'   #  0xD8 -> UNDEFINED
+    u'\u2518'   #  0xD9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0xDA -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0xDB -> FULL BLOCK
+    u'\u2584'   #  0xDC -> LOWER HALF BLOCK
+    u'\xa6'     #  0xDD -> BROKEN BAR
+    u'\ufffe'   #  0xDE -> UNDEFINED
+    u'\u2580'   #  0xDF -> UPPER HALF BLOCK
+    u'\ufffe'   #  0xE0 -> UNDEFINED
+    u'\ufffe'   #  0xE1 -> UNDEFINED
+    u'\ufffe'   #  0xE2 -> UNDEFINED
+    u'\ufffe'   #  0xE3 -> UNDEFINED
+    u'\ufffe'   #  0xE4 -> UNDEFINED
+    u'\ufffe'   #  0xE5 -> UNDEFINED
+    u'\xb5'     #  0xE6 -> MICRO SIGN
+    u'\ufffe'   #  0xE7 -> UNDEFINED
+    u'\ufffe'   #  0xE8 -> UNDEFINED
+    u'\ufffe'   #  0xE9 -> UNDEFINED
+    u'\ufffe'   #  0xEA -> UNDEFINED
+    u'\ufffe'   #  0xEB -> UNDEFINED
+    u'\ufffe'   #  0xEC -> UNDEFINED
+    u'\ufffe'   #  0xED -> UNDEFINED
+    u'\xaf'     #  0xEE -> MACRON
+    u'\xb4'     #  0xEF -> ACUTE ACCENT
+    u'\xad'     #  0xF0 -> SOFT HYPHEN
+    u'\xb1'     #  0xF1 -> PLUS-MINUS SIGN
+    u'\u2017'   #  0xF2 -> DOUBLE LOW LINE
+    u'\xbe'     #  0xF3 -> VULGAR FRACTION THREE QUARTERS
+    u'\xb6'     #  0xF4 -> PILCROW SIGN
+    u'\xa7'     #  0xF5 -> SECTION SIGN
+    u'\xf7'     #  0xF6 -> DIVISION SIGN
+    u'\xb8'     #  0xF7 -> CEDILLA
+    u'\xb0'     #  0xF8 -> DEGREE SIGN
+    u'\xa8'     #  0xF9 -> DIAERESIS
+    u'\xb7'     #  0xFA -> MIDDLE DOT
+    u'\xb9'     #  0xFB -> SUPERSCRIPT ONE
+    u'\xb3'     #  0xFC -> SUPERSCRIPT THREE
+    u'\xb2'     #  0xFD -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0xFE -> BLACK SQUARE
+    u'\xa0'     #  0xFF -> NO-BREAK SPACE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp857.py b/src/main/resources/PythonLibs/encodings/cp857.py
new file mode 100644
index 0000000000000000000000000000000000000000..c24191b04dc40f4b9544fe49c6a19b1512f5d851
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp857.py
@@ -0,0 +1,694 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP857.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp857',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x0085: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0086: 0x00e5,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0089: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x008a: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x008b: 0x00ef,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x008c: 0x00ee,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x008d: 0x0131,     #  LATIN SMALL LETTER DOTLESS I
+    0x008e: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x008f: 0x00c5,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00e6,     #  LATIN SMALL LIGATURE AE
+    0x0092: 0x00c6,     #  LATIN CAPITAL LIGATURE AE
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x0095: 0x00f2,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x0096: 0x00fb,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x0097: 0x00f9,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x0098: 0x0130,     #  LATIN CAPITAL LETTER I WITH DOT ABOVE
+    0x0099: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00f8,     #  LATIN SMALL LETTER O WITH STROKE
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00d8,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x009e: 0x015e,     #  LATIN CAPITAL LETTER S WITH CEDILLA
+    0x009f: 0x015f,     #  LATIN SMALL LETTER S WITH CEDILLA
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00f1,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00a5: 0x00d1,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00a6: 0x011e,     #  LATIN CAPITAL LETTER G WITH BREVE
+    0x00a7: 0x011f,     #  LATIN SMALL LETTER G WITH BREVE
+    0x00a8: 0x00bf,     #  INVERTED QUESTION MARK
+    0x00a9: 0x00ae,     #  REGISTERED SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00a1,     #  INVERTED EXCLAMATION MARK
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x00c1,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00b6: 0x00c2,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00b7: 0x00c0,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x00b8: 0x00a9,     #  COPYRIGHT SIGN
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x00a2,     #  CENT SIGN
+    0x00be: 0x00a5,     #  YEN SIGN
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x00e3,     #  LATIN SMALL LETTER A WITH TILDE
+    0x00c7: 0x00c3,     #  LATIN CAPITAL LETTER A WITH TILDE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x00a4,     #  CURRENCY SIGN
+    0x00d0: 0x00ba,     #  MASCULINE ORDINAL INDICATOR
+    0x00d1: 0x00aa,     #  FEMININE ORDINAL INDICATOR
+    0x00d2: 0x00ca,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x00d3: 0x00cb,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00d4: 0x00c8,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x00d5: None,       #  UNDEFINED
+    0x00d6: 0x00cd,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00d7: 0x00ce,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00d8: 0x00cf,     #  LATIN CAPITAL LETTER I WITH DIAERESIS
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x00a6,     #  BROKEN BAR
+    0x00de: 0x00cc,     #  LATIN CAPITAL LETTER I WITH GRAVE
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x00d3,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x00d4,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00e3: 0x00d2,     #  LATIN CAPITAL LETTER O WITH GRAVE
+    0x00e4: 0x00f5,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00e5: 0x00d5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: None,       #  UNDEFINED
+    0x00e8: 0x00d7,     #  MULTIPLICATION SIGN
+    0x00e9: 0x00da,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00ea: 0x00db,     #  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    0x00eb: 0x00d9,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x00ed: 0x00ff,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x00ee: 0x00af,     #  MACRON
+    0x00ef: 0x00b4,     #  ACUTE ACCENT
+    0x00f0: 0x00ad,     #  SOFT HYPHEN
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: None,       #  UNDEFINED
+    0x00f3: 0x00be,     #  VULGAR FRACTION THREE QUARTERS
+    0x00f4: 0x00b6,     #  PILCROW SIGN
+    0x00f5: 0x00a7,     #  SECTION SIGN
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x00b8,     #  CEDILLA
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x00a8,     #  DIAERESIS
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x00b9,     #  SUPERSCRIPT ONE
+    0x00fc: 0x00b3,     #  SUPERSCRIPT THREE
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x0085 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe5'     #  0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x008a -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xef'     #  0x008b -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xee'     #  0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\u0131'   #  0x008d -> LATIN SMALL LETTER DOTLESS I
+    u'\xc4'     #  0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xe6'     #  0x0091 -> LATIN SMALL LIGATURE AE
+    u'\xc6'     #  0x0092 -> LATIN CAPITAL LIGATURE AE
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf2'     #  0x0095 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xfb'     #  0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xf9'     #  0x0097 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\u0130'   #  0x0098 -> LATIN CAPITAL LETTER I WITH DOT ABOVE
+    u'\xd6'     #  0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xf8'     #  0x009b -> LATIN SMALL LETTER O WITH STROKE
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xd8'     #  0x009d -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u015e'   #  0x009e -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u'\u015f'   #  0x009f -> LATIN SMALL LETTER S WITH CEDILLA
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf1'     #  0x00a4 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xd1'     #  0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\u011e'   #  0x00a6 -> LATIN CAPITAL LETTER G WITH BREVE
+    u'\u011f'   #  0x00a7 -> LATIN SMALL LETTER G WITH BREVE
+    u'\xbf'     #  0x00a8 -> INVERTED QUESTION MARK
+    u'\xae'     #  0x00a9 -> REGISTERED SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xa1'     #  0x00ad -> INVERTED EXCLAMATION MARK
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\xc1'     #  0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc0'     #  0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xa9'     #  0x00b8 -> COPYRIGHT SIGN
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\xa2'     #  0x00bd -> CENT SIGN
+    u'\xa5'     #  0x00be -> YEN SIGN
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\xe3'     #  0x00c6 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xc3'     #  0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\xa4'     #  0x00cf -> CURRENCY SIGN
+    u'\xba'     #  0x00d0 -> MASCULINE ORDINAL INDICATOR
+    u'\xaa'     #  0x00d1 -> FEMININE ORDINAL INDICATOR
+    u'\xca'     #  0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\ufffe'   #  0x00d5 -> UNDEFINED
+    u'\xcd'     #  0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\xa6'     #  0x00dd -> BROKEN BAR
+    u'\xcc'     #  0x00de -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\xd3'     #  0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\xd4'     #  0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd2'     #  0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xf5'     #  0x00e4 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xd5'     #  0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\ufffe'   #  0x00e7 -> UNDEFINED
+    u'\xd7'     #  0x00e8 -> MULTIPLICATION SIGN
+    u'\xda'     #  0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xd9'     #  0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xec'     #  0x00ec -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xff'     #  0x00ed -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\xaf'     #  0x00ee -> MACRON
+    u'\xb4'     #  0x00ef -> ACUTE ACCENT
+    u'\xad'     #  0x00f0 -> SOFT HYPHEN
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\ufffe'   #  0x00f2 -> UNDEFINED
+    u'\xbe'     #  0x00f3 -> VULGAR FRACTION THREE QUARTERS
+    u'\xb6'     #  0x00f4 -> PILCROW SIGN
+    u'\xa7'     #  0x00f5 -> SECTION SIGN
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\xb8'     #  0x00f7 -> CEDILLA
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\xa8'     #  0x00f9 -> DIAERESIS
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\xb9'     #  0x00fb -> SUPERSCRIPT ONE
+    u'\xb3'     #  0x00fc -> SUPERSCRIPT THREE
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a1: 0x00ad,     #  INVERTED EXCLAMATION MARK
+    0x00a2: 0x00bd,     #  CENT SIGN
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a4: 0x00cf,     #  CURRENCY SIGN
+    0x00a5: 0x00be,     #  YEN SIGN
+    0x00a6: 0x00dd,     #  BROKEN BAR
+    0x00a7: 0x00f5,     #  SECTION SIGN
+    0x00a8: 0x00f9,     #  DIAERESIS
+    0x00a9: 0x00b8,     #  COPYRIGHT SIGN
+    0x00aa: 0x00d1,     #  FEMININE ORDINAL INDICATOR
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00ad: 0x00f0,     #  SOFT HYPHEN
+    0x00ae: 0x00a9,     #  REGISTERED SIGN
+    0x00af: 0x00ee,     #  MACRON
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b3: 0x00fc,     #  SUPERSCRIPT THREE
+    0x00b4: 0x00ef,     #  ACUTE ACCENT
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b6: 0x00f4,     #  PILCROW SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00b8: 0x00f7,     #  CEDILLA
+    0x00b9: 0x00fb,     #  SUPERSCRIPT ONE
+    0x00ba: 0x00d0,     #  MASCULINE ORDINAL INDICATOR
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00be: 0x00f3,     #  VULGAR FRACTION THREE QUARTERS
+    0x00bf: 0x00a8,     #  INVERTED QUESTION MARK
+    0x00c0: 0x00b7,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x00c1: 0x00b5,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00c2: 0x00b6,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00c3: 0x00c7,     #  LATIN CAPITAL LETTER A WITH TILDE
+    0x00c4: 0x008e,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c5: 0x008f,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x00c6: 0x0092,     #  LATIN CAPITAL LIGATURE AE
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c8: 0x00d4,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00ca: 0x00d2,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x00cb: 0x00d3,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00cc: 0x00de,     #  LATIN CAPITAL LETTER I WITH GRAVE
+    0x00cd: 0x00d6,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00ce: 0x00d7,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00cf: 0x00d8,     #  LATIN CAPITAL LETTER I WITH DIAERESIS
+    0x00d1: 0x00a5,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00d2: 0x00e3,     #  LATIN CAPITAL LETTER O WITH GRAVE
+    0x00d3: 0x00e0,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00d4: 0x00e2,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00d5: 0x00e5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00d6: 0x0099,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00d7: 0x00e8,     #  MULTIPLICATION SIGN
+    0x00d8: 0x009d,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x00d9: 0x00eb,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x00da: 0x00e9,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00db: 0x00ea,     #  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e0: 0x0085,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e3: 0x00c6,     #  LATIN SMALL LETTER A WITH TILDE
+    0x00e4: 0x0084,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e5: 0x0086,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x00e6: 0x0091,     #  LATIN SMALL LIGATURE AE
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008a,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0088,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00eb: 0x0089,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ec: 0x00ec,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00ee: 0x008c,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x00ef: 0x008b,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x00f1: 0x00a4,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00f2: 0x0095,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f5: 0x00e4,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00f6: 0x0094,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f8: 0x009b,     #  LATIN SMALL LETTER O WITH STROKE
+    0x00f9: 0x0097,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fb: 0x0096,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x00ff: 0x00ed,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x011e: 0x00a6,     #  LATIN CAPITAL LETTER G WITH BREVE
+    0x011f: 0x00a7,     #  LATIN SMALL LETTER G WITH BREVE
+    0x0130: 0x0098,     #  LATIN CAPITAL LETTER I WITH DOT ABOVE
+    0x0131: 0x008d,     #  LATIN SMALL LETTER DOTLESS I
+    0x015e: 0x009e,     #  LATIN CAPITAL LETTER S WITH CEDILLA
+    0x015f: 0x009f,     #  LATIN SMALL LETTER S WITH CEDILLA
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp858.py b/src/main/resources/PythonLibs/encodings/cp858.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ba7621f8fbe2091a1f383c050393aea49e00d2a
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp858.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec for CP858, modified from cp850.
+
+"""
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp858',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x0085: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0086: 0x00e5,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0089: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x008a: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x008b: 0x00ef,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x008c: 0x00ee,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x008d: 0x00ec,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x008e: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x008f: 0x00c5,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00e6,     #  LATIN SMALL LIGATURE AE
+    0x0092: 0x00c6,     #  LATIN CAPITAL LIGATURE AE
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x0095: 0x00f2,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x0096: 0x00fb,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x0097: 0x00f9,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x0098: 0x00ff,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x0099: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00f8,     #  LATIN SMALL LETTER O WITH STROKE
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00d8,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x009e: 0x00d7,     #  MULTIPLICATION SIGN
+    0x009f: 0x0192,     #  LATIN SMALL LETTER F WITH HOOK
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00f1,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00a5: 0x00d1,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00a6: 0x00aa,     #  FEMININE ORDINAL INDICATOR
+    0x00a7: 0x00ba,     #  MASCULINE ORDINAL INDICATOR
+    0x00a8: 0x00bf,     #  INVERTED QUESTION MARK
+    0x00a9: 0x00ae,     #  REGISTERED SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00a1,     #  INVERTED EXCLAMATION MARK
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x00c1,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00b6: 0x00c2,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00b7: 0x00c0,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x00b8: 0x00a9,     #  COPYRIGHT SIGN
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x00a2,     #  CENT SIGN
+    0x00be: 0x00a5,     #  YEN SIGN
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x00e3,     #  LATIN SMALL LETTER A WITH TILDE
+    0x00c7: 0x00c3,     #  LATIN CAPITAL LETTER A WITH TILDE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x00a4,     #  CURRENCY SIGN
+    0x00d0: 0x00f0,     #  LATIN SMALL LETTER ETH
+    0x00d1: 0x00d0,     #  LATIN CAPITAL LETTER ETH
+    0x00d2: 0x00ca,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x00d3: 0x00cb,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00d4: 0x00c8,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x00d5: 0x20ac,     #  EURO SIGN
+    0x00d6: 0x00cd,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00d7: 0x00ce,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00d8: 0x00cf,     #  LATIN CAPITAL LETTER I WITH DIAERESIS
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x00a6,     #  BROKEN BAR
+    0x00de: 0x00cc,     #  LATIN CAPITAL LETTER I WITH GRAVE
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x00d3,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x00d4,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00e3: 0x00d2,     #  LATIN CAPITAL LETTER O WITH GRAVE
+    0x00e4: 0x00f5,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00e5: 0x00d5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x00fe,     #  LATIN SMALL LETTER THORN
+    0x00e8: 0x00de,     #  LATIN CAPITAL LETTER THORN
+    0x00e9: 0x00da,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00ea: 0x00db,     #  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    0x00eb: 0x00d9,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x00ec: 0x00fd,     #  LATIN SMALL LETTER Y WITH ACUTE
+    0x00ed: 0x00dd,     #  LATIN CAPITAL LETTER Y WITH ACUTE
+    0x00ee: 0x00af,     #  MACRON
+    0x00ef: 0x00b4,     #  ACUTE ACCENT
+    0x00f0: 0x00ad,     #  SOFT HYPHEN
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2017,     #  DOUBLE LOW LINE
+    0x00f3: 0x00be,     #  VULGAR FRACTION THREE QUARTERS
+    0x00f4: 0x00b6,     #  PILCROW SIGN
+    0x00f5: 0x00a7,     #  SECTION SIGN
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x00b8,     #  CEDILLA
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x00a8,     #  DIAERESIS
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x00b9,     #  SUPERSCRIPT ONE
+    0x00fc: 0x00b3,     #  SUPERSCRIPT THREE
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x0085 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe5'     #  0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x008a -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xef'     #  0x008b -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xee'     #  0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xec'     #  0x008d -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xc4'     #  0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xe6'     #  0x0091 -> LATIN SMALL LIGATURE AE
+    u'\xc6'     #  0x0092 -> LATIN CAPITAL LIGATURE AE
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf2'     #  0x0095 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xfb'     #  0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xf9'     #  0x0097 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xff'     #  0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\xd6'     #  0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xf8'     #  0x009b -> LATIN SMALL LETTER O WITH STROKE
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xd8'     #  0x009d -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd7'     #  0x009e -> MULTIPLICATION SIGN
+    u'\u0192'   #  0x009f -> LATIN SMALL LETTER F WITH HOOK
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf1'     #  0x00a4 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xd1'     #  0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xaa'     #  0x00a6 -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x00a7 -> MASCULINE ORDINAL INDICATOR
+    u'\xbf'     #  0x00a8 -> INVERTED QUESTION MARK
+    u'\xae'     #  0x00a9 -> REGISTERED SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xa1'     #  0x00ad -> INVERTED EXCLAMATION MARK
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\xc1'     #  0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc0'     #  0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xa9'     #  0x00b8 -> COPYRIGHT SIGN
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\xa2'     #  0x00bd -> CENT SIGN
+    u'\xa5'     #  0x00be -> YEN SIGN
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\xe3'     #  0x00c6 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xc3'     #  0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\xa4'     #  0x00cf -> CURRENCY SIGN
+    u'\xf0'     #  0x00d0 -> LATIN SMALL LETTER ETH
+    u'\xd0'     #  0x00d1 -> LATIN CAPITAL LETTER ETH
+    u'\xca'     #  0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\u20ac'   #  0x00d5 -> EURO SIGN
+    u'\xcd'     #  0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\xa6'     #  0x00dd -> BROKEN BAR
+    u'\xcc'     #  0x00de -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\xd3'     #  0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\xd4'     #  0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd2'     #  0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xf5'     #  0x00e4 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xd5'     #  0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\xfe'     #  0x00e7 -> LATIN SMALL LETTER THORN
+    u'\xde'     #  0x00e8 -> LATIN CAPITAL LETTER THORN
+    u'\xda'     #  0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xd9'     #  0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xfd'     #  0x00ec -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xdd'     #  0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xaf'     #  0x00ee -> MACRON
+    u'\xb4'     #  0x00ef -> ACUTE ACCENT
+    u'\xad'     #  0x00f0 -> SOFT HYPHEN
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2017'   #  0x00f2 -> DOUBLE LOW LINE
+    u'\xbe'     #  0x00f3 -> VULGAR FRACTION THREE QUARTERS
+    u'\xb6'     #  0x00f4 -> PILCROW SIGN
+    u'\xa7'     #  0x00f5 -> SECTION SIGN
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\xb8'     #  0x00f7 -> CEDILLA
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\xa8'     #  0x00f9 -> DIAERESIS
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\xb9'     #  0x00fb -> SUPERSCRIPT ONE
+    u'\xb3'     #  0x00fc -> SUPERSCRIPT THREE
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a1: 0x00ad,     #  INVERTED EXCLAMATION MARK
+    0x00a2: 0x00bd,     #  CENT SIGN
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a4: 0x00cf,     #  CURRENCY SIGN
+    0x00a5: 0x00be,     #  YEN SIGN
+    0x00a6: 0x00dd,     #  BROKEN BAR
+    0x00a7: 0x00f5,     #  SECTION SIGN
+    0x00a8: 0x00f9,     #  DIAERESIS
+    0x00a9: 0x00b8,     #  COPYRIGHT SIGN
+    0x00aa: 0x00a6,     #  FEMININE ORDINAL INDICATOR
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00ad: 0x00f0,     #  SOFT HYPHEN
+    0x00ae: 0x00a9,     #  REGISTERED SIGN
+    0x00af: 0x00ee,     #  MACRON
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b3: 0x00fc,     #  SUPERSCRIPT THREE
+    0x00b4: 0x00ef,     #  ACUTE ACCENT
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b6: 0x00f4,     #  PILCROW SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00b8: 0x00f7,     #  CEDILLA
+    0x00b9: 0x00fb,     #  SUPERSCRIPT ONE
+    0x00ba: 0x00a7,     #  MASCULINE ORDINAL INDICATOR
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00be: 0x00f3,     #  VULGAR FRACTION THREE QUARTERS
+    0x00bf: 0x00a8,     #  INVERTED QUESTION MARK
+    0x00c0: 0x00b7,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x00c1: 0x00b5,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00c2: 0x00b6,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00c3: 0x00c7,     #  LATIN CAPITAL LETTER A WITH TILDE
+    0x00c4: 0x008e,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c5: 0x008f,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x00c6: 0x0092,     #  LATIN CAPITAL LIGATURE AE
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c8: 0x00d4,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00ca: 0x00d2,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x00cb: 0x00d3,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00cc: 0x00de,     #  LATIN CAPITAL LETTER I WITH GRAVE
+    0x00cd: 0x00d6,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00ce: 0x00d7,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00cf: 0x00d8,     #  LATIN CAPITAL LETTER I WITH DIAERESIS
+    0x00d0: 0x00d1,     #  LATIN CAPITAL LETTER ETH
+    0x00d1: 0x00a5,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00d2: 0x00e3,     #  LATIN CAPITAL LETTER O WITH GRAVE
+    0x00d3: 0x00e0,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00d4: 0x00e2,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00d5: 0x00e5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00d6: 0x0099,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00d7: 0x009e,     #  MULTIPLICATION SIGN
+    0x00d8: 0x009d,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x00d9: 0x00eb,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x00da: 0x00e9,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00db: 0x00ea,     #  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00dd: 0x00ed,     #  LATIN CAPITAL LETTER Y WITH ACUTE
+    0x00de: 0x00e8,     #  LATIN CAPITAL LETTER THORN
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e0: 0x0085,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e3: 0x00c6,     #  LATIN SMALL LETTER A WITH TILDE
+    0x00e4: 0x0084,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e5: 0x0086,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x00e6: 0x0091,     #  LATIN SMALL LIGATURE AE
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008a,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0088,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00eb: 0x0089,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ec: 0x008d,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00ee: 0x008c,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x00ef: 0x008b,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x00f0: 0x00d0,     #  LATIN SMALL LETTER ETH
+    0x00f1: 0x00a4,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00f2: 0x0095,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f5: 0x00e4,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00f6: 0x0094,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f8: 0x009b,     #  LATIN SMALL LETTER O WITH STROKE
+    0x00f9: 0x0097,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fb: 0x0096,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x00fd: 0x00ec,     #  LATIN SMALL LETTER Y WITH ACUTE
+    0x00fe: 0x00e7,     #  LATIN SMALL LETTER THORN
+    0x00ff: 0x0098,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x20ac: 0x00d5,     #  EURO SIGN
+    0x0192: 0x009f,     #  LATIN SMALL LETTER F WITH HOOK
+    0x2017: 0x00f2,     #  DOUBLE LOW LINE
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp860.py b/src/main/resources/PythonLibs/encodings/cp860.py
new file mode 100644
index 0000000000000000000000000000000000000000..4acb0cf36269eff1ff4ba7b4806c0db8fbde1146
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp860.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP860.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp860',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00e3,     #  LATIN SMALL LETTER A WITH TILDE
+    0x0085: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0086: 0x00c1,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0089: 0x00ca,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x008a: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x008b: 0x00cd,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x008c: 0x00d4,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x008d: 0x00ec,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x008e: 0x00c3,     #  LATIN CAPITAL LETTER A WITH TILDE
+    0x008f: 0x00c2,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00c0,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x0092: 0x00c8,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00f5,     #  LATIN SMALL LETTER O WITH TILDE
+    0x0095: 0x00f2,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x0096: 0x00da,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x0097: 0x00f9,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x0098: 0x00cc,     #  LATIN CAPITAL LETTER I WITH GRAVE
+    0x0099: 0x00d5,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00a2,     #  CENT SIGN
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00d9,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x009e: 0x20a7,     #  PESETA SIGN
+    0x009f: 0x00d3,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00f1,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00a5: 0x00d1,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00a6: 0x00aa,     #  FEMININE ORDINAL INDICATOR
+    0x00a7: 0x00ba,     #  MASCULINE ORDINAL INDICATOR
+    0x00a8: 0x00bf,     #  INVERTED QUESTION MARK
+    0x00a9: 0x00d2,     #  LATIN CAPITAL LETTER O WITH GRAVE
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00a1,     #  INVERTED EXCLAMATION MARK
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x2561,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x00b6: 0x2562,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x00b7: 0x2556,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x00b8: 0x2555,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x255c,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x00be: 0x255b,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x255e,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x00c7: 0x255f,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x2567,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x00d0: 0x2568,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x00d1: 0x2564,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x00d2: 0x2565,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x00d3: 0x2559,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x00d4: 0x2558,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x00d5: 0x2552,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x00d6: 0x2553,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x00d7: 0x256b,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x00d8: 0x256a,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x03b1,     #  GREEK SMALL LETTER ALPHA
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x0393,     #  GREEK CAPITAL LETTER GAMMA
+    0x00e3: 0x03c0,     #  GREEK SMALL LETTER PI
+    0x00e4: 0x03a3,     #  GREEK CAPITAL LETTER SIGMA
+    0x00e5: 0x03c3,     #  GREEK SMALL LETTER SIGMA
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x03c4,     #  GREEK SMALL LETTER TAU
+    0x00e8: 0x03a6,     #  GREEK CAPITAL LETTER PHI
+    0x00e9: 0x0398,     #  GREEK CAPITAL LETTER THETA
+    0x00ea: 0x03a9,     #  GREEK CAPITAL LETTER OMEGA
+    0x00eb: 0x03b4,     #  GREEK SMALL LETTER DELTA
+    0x00ec: 0x221e,     #  INFINITY
+    0x00ed: 0x03c6,     #  GREEK SMALL LETTER PHI
+    0x00ee: 0x03b5,     #  GREEK SMALL LETTER EPSILON
+    0x00ef: 0x2229,     #  INTERSECTION
+    0x00f0: 0x2261,     #  IDENTICAL TO
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2265,     #  GREATER-THAN OR EQUAL TO
+    0x00f3: 0x2264,     #  LESS-THAN OR EQUAL TO
+    0x00f4: 0x2320,     #  TOP HALF INTEGRAL
+    0x00f5: 0x2321,     #  BOTTOM HALF INTEGRAL
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x2248,     #  ALMOST EQUAL TO
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x221a,     #  SQUARE ROOT
+    0x00fc: 0x207f,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0x0084 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe0'     #  0x0085 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xc1'     #  0x0086 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xca'     #  0x0089 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xe8'     #  0x008a -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xcd'     #  0x008b -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xd4'     #  0x008c -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xec'     #  0x008d -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xc3'     #  0x008e -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc2'     #  0x008f -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xc0'     #  0x0091 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc8'     #  0x0092 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0x0094 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf2'     #  0x0095 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xda'     #  0x0096 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xf9'     #  0x0097 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xcc'     #  0x0098 -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xd5'     #  0x0099 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xa2'     #  0x009b -> CENT SIGN
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xd9'     #  0x009d -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\u20a7'   #  0x009e -> PESETA SIGN
+    u'\xd3'     #  0x009f -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf1'     #  0x00a4 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xd1'     #  0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xaa'     #  0x00a6 -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x00a7 -> MASCULINE ORDINAL INDICATOR
+    u'\xbf'     #  0x00a8 -> INVERTED QUESTION MARK
+    u'\xd2'     #  0x00a9 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xa1'     #  0x00ad -> INVERTED EXCLAMATION MARK
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u03b1'   #  0x00e0 -> GREEK SMALL LETTER ALPHA
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\u0393'   #  0x00e2 -> GREEK CAPITAL LETTER GAMMA
+    u'\u03c0'   #  0x00e3 -> GREEK SMALL LETTER PI
+    u'\u03a3'   #  0x00e4 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03c3'   #  0x00e5 -> GREEK SMALL LETTER SIGMA
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\u03c4'   #  0x00e7 -> GREEK SMALL LETTER TAU
+    u'\u03a6'   #  0x00e8 -> GREEK CAPITAL LETTER PHI
+    u'\u0398'   #  0x00e9 -> GREEK CAPITAL LETTER THETA
+    u'\u03a9'   #  0x00ea -> GREEK CAPITAL LETTER OMEGA
+    u'\u03b4'   #  0x00eb -> GREEK SMALL LETTER DELTA
+    u'\u221e'   #  0x00ec -> INFINITY
+    u'\u03c6'   #  0x00ed -> GREEK SMALL LETTER PHI
+    u'\u03b5'   #  0x00ee -> GREEK SMALL LETTER EPSILON
+    u'\u2229'   #  0x00ef -> INTERSECTION
+    u'\u2261'   #  0x00f0 -> IDENTICAL TO
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2265'   #  0x00f2 -> GREATER-THAN OR EQUAL TO
+    u'\u2264'   #  0x00f3 -> LESS-THAN OR EQUAL TO
+    u'\u2320'   #  0x00f4 -> TOP HALF INTEGRAL
+    u'\u2321'   #  0x00f5 -> BOTTOM HALF INTEGRAL
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\u2248'   #  0x00f7 -> ALMOST EQUAL TO
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\u221a'   #  0x00fb -> SQUARE ROOT
+    u'\u207f'   #  0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a1: 0x00ad,     #  INVERTED EXCLAMATION MARK
+    0x00a2: 0x009b,     #  CENT SIGN
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00aa: 0x00a6,     #  FEMININE ORDINAL INDICATOR
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00ba: 0x00a7,     #  MASCULINE ORDINAL INDICATOR
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00bf: 0x00a8,     #  INVERTED QUESTION MARK
+    0x00c0: 0x0091,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x00c1: 0x0086,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00c2: 0x008f,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00c3: 0x008e,     #  LATIN CAPITAL LETTER A WITH TILDE
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c8: 0x0092,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00ca: 0x0089,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x00cc: 0x0098,     #  LATIN CAPITAL LETTER I WITH GRAVE
+    0x00cd: 0x008b,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00d1: 0x00a5,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00d2: 0x00a9,     #  LATIN CAPITAL LETTER O WITH GRAVE
+    0x00d3: 0x009f,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00d4: 0x008c,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00d5: 0x0099,     #  LATIN CAPITAL LETTER O WITH TILDE
+    0x00d9: 0x009d,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x00da: 0x0096,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e0: 0x0085,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e3: 0x0084,     #  LATIN SMALL LETTER A WITH TILDE
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008a,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0088,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00ec: 0x008d,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00f1: 0x00a4,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00f2: 0x0095,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f5: 0x0094,     #  LATIN SMALL LETTER O WITH TILDE
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f9: 0x0097,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0393: 0x00e2,     #  GREEK CAPITAL LETTER GAMMA
+    0x0398: 0x00e9,     #  GREEK CAPITAL LETTER THETA
+    0x03a3: 0x00e4,     #  GREEK CAPITAL LETTER SIGMA
+    0x03a6: 0x00e8,     #  GREEK CAPITAL LETTER PHI
+    0x03a9: 0x00ea,     #  GREEK CAPITAL LETTER OMEGA
+    0x03b1: 0x00e0,     #  GREEK SMALL LETTER ALPHA
+    0x03b4: 0x00eb,     #  GREEK SMALL LETTER DELTA
+    0x03b5: 0x00ee,     #  GREEK SMALL LETTER EPSILON
+    0x03c0: 0x00e3,     #  GREEK SMALL LETTER PI
+    0x03c3: 0x00e5,     #  GREEK SMALL LETTER SIGMA
+    0x03c4: 0x00e7,     #  GREEK SMALL LETTER TAU
+    0x03c6: 0x00ed,     #  GREEK SMALL LETTER PHI
+    0x207f: 0x00fc,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x20a7: 0x009e,     #  PESETA SIGN
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x221a: 0x00fb,     #  SQUARE ROOT
+    0x221e: 0x00ec,     #  INFINITY
+    0x2229: 0x00ef,     #  INTERSECTION
+    0x2248: 0x00f7,     #  ALMOST EQUAL TO
+    0x2261: 0x00f0,     #  IDENTICAL TO
+    0x2264: 0x00f3,     #  LESS-THAN OR EQUAL TO
+    0x2265: 0x00f2,     #  GREATER-THAN OR EQUAL TO
+    0x2320: 0x00f4,     #  TOP HALF INTEGRAL
+    0x2321: 0x00f5,     #  BOTTOM HALF INTEGRAL
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2552: 0x00d5,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x2553: 0x00d6,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2555: 0x00b8,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x2556: 0x00b7,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x2558: 0x00d4,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x2559: 0x00d3,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255b: 0x00be,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x255c: 0x00bd,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x255e: 0x00c6,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x255f: 0x00c7,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2561: 0x00b5,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x2562: 0x00b6,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2564: 0x00d1,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x2565: 0x00d2,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2567: 0x00cf,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x2568: 0x00d0,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256a: 0x00d8,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x256b: 0x00d7,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp861.py b/src/main/resources/PythonLibs/encodings/cp861.py
new file mode 100644
index 0000000000000000000000000000000000000000..0939b5b1eefcb2033be8a26d2462d2263093fdb6
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp861.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP861.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp861',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x0085: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0086: 0x00e5,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0089: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x008a: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x008b: 0x00d0,     #  LATIN CAPITAL LETTER ETH
+    0x008c: 0x00f0,     #  LATIN SMALL LETTER ETH
+    0x008d: 0x00de,     #  LATIN CAPITAL LETTER THORN
+    0x008e: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x008f: 0x00c5,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00e6,     #  LATIN SMALL LIGATURE AE
+    0x0092: 0x00c6,     #  LATIN CAPITAL LIGATURE AE
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x0095: 0x00fe,     #  LATIN SMALL LETTER THORN
+    0x0096: 0x00fb,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x0097: 0x00dd,     #  LATIN CAPITAL LETTER Y WITH ACUTE
+    0x0098: 0x00fd,     #  LATIN SMALL LETTER Y WITH ACUTE
+    0x0099: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00f8,     #  LATIN SMALL LETTER O WITH STROKE
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00d8,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x009e: 0x20a7,     #  PESETA SIGN
+    0x009f: 0x0192,     #  LATIN SMALL LETTER F WITH HOOK
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00c1,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00a5: 0x00cd,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00a6: 0x00d3,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00a7: 0x00da,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00a8: 0x00bf,     #  INVERTED QUESTION MARK
+    0x00a9: 0x2310,     #  REVERSED NOT SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00a1,     #  INVERTED EXCLAMATION MARK
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x2561,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x00b6: 0x2562,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x00b7: 0x2556,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x00b8: 0x2555,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x255c,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x00be: 0x255b,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x255e,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x00c7: 0x255f,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x2567,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x00d0: 0x2568,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x00d1: 0x2564,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x00d2: 0x2565,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x00d3: 0x2559,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x00d4: 0x2558,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x00d5: 0x2552,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x00d6: 0x2553,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x00d7: 0x256b,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x00d8: 0x256a,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x03b1,     #  GREEK SMALL LETTER ALPHA
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x0393,     #  GREEK CAPITAL LETTER GAMMA
+    0x00e3: 0x03c0,     #  GREEK SMALL LETTER PI
+    0x00e4: 0x03a3,     #  GREEK CAPITAL LETTER SIGMA
+    0x00e5: 0x03c3,     #  GREEK SMALL LETTER SIGMA
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x03c4,     #  GREEK SMALL LETTER TAU
+    0x00e8: 0x03a6,     #  GREEK CAPITAL LETTER PHI
+    0x00e9: 0x0398,     #  GREEK CAPITAL LETTER THETA
+    0x00ea: 0x03a9,     #  GREEK CAPITAL LETTER OMEGA
+    0x00eb: 0x03b4,     #  GREEK SMALL LETTER DELTA
+    0x00ec: 0x221e,     #  INFINITY
+    0x00ed: 0x03c6,     #  GREEK SMALL LETTER PHI
+    0x00ee: 0x03b5,     #  GREEK SMALL LETTER EPSILON
+    0x00ef: 0x2229,     #  INTERSECTION
+    0x00f0: 0x2261,     #  IDENTICAL TO
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2265,     #  GREATER-THAN OR EQUAL TO
+    0x00f3: 0x2264,     #  LESS-THAN OR EQUAL TO
+    0x00f4: 0x2320,     #  TOP HALF INTEGRAL
+    0x00f5: 0x2321,     #  BOTTOM HALF INTEGRAL
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x2248,     #  ALMOST EQUAL TO
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x221a,     #  SQUARE ROOT
+    0x00fc: 0x207f,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x0085 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe5'     #  0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x008a -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xd0'     #  0x008b -> LATIN CAPITAL LETTER ETH
+    u'\xf0'     #  0x008c -> LATIN SMALL LETTER ETH
+    u'\xde'     #  0x008d -> LATIN CAPITAL LETTER THORN
+    u'\xc4'     #  0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xe6'     #  0x0091 -> LATIN SMALL LIGATURE AE
+    u'\xc6'     #  0x0092 -> LATIN CAPITAL LIGATURE AE
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xfe'     #  0x0095 -> LATIN SMALL LETTER THORN
+    u'\xfb'     #  0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xdd'     #  0x0097 -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xfd'     #  0x0098 -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xd6'     #  0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xf8'     #  0x009b -> LATIN SMALL LETTER O WITH STROKE
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xd8'     #  0x009d -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u20a7'   #  0x009e -> PESETA SIGN
+    u'\u0192'   #  0x009f -> LATIN SMALL LETTER F WITH HOOK
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xc1'     #  0x00a4 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xcd'     #  0x00a5 -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xd3'     #  0x00a6 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xda'     #  0x00a7 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xbf'     #  0x00a8 -> INVERTED QUESTION MARK
+    u'\u2310'   #  0x00a9 -> REVERSED NOT SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xa1'     #  0x00ad -> INVERTED EXCLAMATION MARK
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u03b1'   #  0x00e0 -> GREEK SMALL LETTER ALPHA
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\u0393'   #  0x00e2 -> GREEK CAPITAL LETTER GAMMA
+    u'\u03c0'   #  0x00e3 -> GREEK SMALL LETTER PI
+    u'\u03a3'   #  0x00e4 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03c3'   #  0x00e5 -> GREEK SMALL LETTER SIGMA
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\u03c4'   #  0x00e7 -> GREEK SMALL LETTER TAU
+    u'\u03a6'   #  0x00e8 -> GREEK CAPITAL LETTER PHI
+    u'\u0398'   #  0x00e9 -> GREEK CAPITAL LETTER THETA
+    u'\u03a9'   #  0x00ea -> GREEK CAPITAL LETTER OMEGA
+    u'\u03b4'   #  0x00eb -> GREEK SMALL LETTER DELTA
+    u'\u221e'   #  0x00ec -> INFINITY
+    u'\u03c6'   #  0x00ed -> GREEK SMALL LETTER PHI
+    u'\u03b5'   #  0x00ee -> GREEK SMALL LETTER EPSILON
+    u'\u2229'   #  0x00ef -> INTERSECTION
+    u'\u2261'   #  0x00f0 -> IDENTICAL TO
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2265'   #  0x00f2 -> GREATER-THAN OR EQUAL TO
+    u'\u2264'   #  0x00f3 -> LESS-THAN OR EQUAL TO
+    u'\u2320'   #  0x00f4 -> TOP HALF INTEGRAL
+    u'\u2321'   #  0x00f5 -> BOTTOM HALF INTEGRAL
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\u2248'   #  0x00f7 -> ALMOST EQUAL TO
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\u221a'   #  0x00fb -> SQUARE ROOT
+    u'\u207f'   #  0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a1: 0x00ad,     #  INVERTED EXCLAMATION MARK
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00bf: 0x00a8,     #  INVERTED QUESTION MARK
+    0x00c1: 0x00a4,     #  LATIN CAPITAL LETTER A WITH ACUTE
+    0x00c4: 0x008e,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c5: 0x008f,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x00c6: 0x0092,     #  LATIN CAPITAL LIGATURE AE
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00cd: 0x00a5,     #  LATIN CAPITAL LETTER I WITH ACUTE
+    0x00d0: 0x008b,     #  LATIN CAPITAL LETTER ETH
+    0x00d3: 0x00a6,     #  LATIN CAPITAL LETTER O WITH ACUTE
+    0x00d6: 0x0099,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00d8: 0x009d,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x00da: 0x00a7,     #  LATIN CAPITAL LETTER U WITH ACUTE
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00dd: 0x0097,     #  LATIN CAPITAL LETTER Y WITH ACUTE
+    0x00de: 0x008d,     #  LATIN CAPITAL LETTER THORN
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e0: 0x0085,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e4: 0x0084,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e5: 0x0086,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x00e6: 0x0091,     #  LATIN SMALL LIGATURE AE
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008a,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0088,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00eb: 0x0089,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00f0: 0x008c,     #  LATIN SMALL LETTER ETH
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f6: 0x0094,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f8: 0x009b,     #  LATIN SMALL LETTER O WITH STROKE
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fb: 0x0096,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x00fd: 0x0098,     #  LATIN SMALL LETTER Y WITH ACUTE
+    0x00fe: 0x0095,     #  LATIN SMALL LETTER THORN
+    0x0192: 0x009f,     #  LATIN SMALL LETTER F WITH HOOK
+    0x0393: 0x00e2,     #  GREEK CAPITAL LETTER GAMMA
+    0x0398: 0x00e9,     #  GREEK CAPITAL LETTER THETA
+    0x03a3: 0x00e4,     #  GREEK CAPITAL LETTER SIGMA
+    0x03a6: 0x00e8,     #  GREEK CAPITAL LETTER PHI
+    0x03a9: 0x00ea,     #  GREEK CAPITAL LETTER OMEGA
+    0x03b1: 0x00e0,     #  GREEK SMALL LETTER ALPHA
+    0x03b4: 0x00eb,     #  GREEK SMALL LETTER DELTA
+    0x03b5: 0x00ee,     #  GREEK SMALL LETTER EPSILON
+    0x03c0: 0x00e3,     #  GREEK SMALL LETTER PI
+    0x03c3: 0x00e5,     #  GREEK SMALL LETTER SIGMA
+    0x03c4: 0x00e7,     #  GREEK SMALL LETTER TAU
+    0x03c6: 0x00ed,     #  GREEK SMALL LETTER PHI
+    0x207f: 0x00fc,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x20a7: 0x009e,     #  PESETA SIGN
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x221a: 0x00fb,     #  SQUARE ROOT
+    0x221e: 0x00ec,     #  INFINITY
+    0x2229: 0x00ef,     #  INTERSECTION
+    0x2248: 0x00f7,     #  ALMOST EQUAL TO
+    0x2261: 0x00f0,     #  IDENTICAL TO
+    0x2264: 0x00f3,     #  LESS-THAN OR EQUAL TO
+    0x2265: 0x00f2,     #  GREATER-THAN OR EQUAL TO
+    0x2310: 0x00a9,     #  REVERSED NOT SIGN
+    0x2320: 0x00f4,     #  TOP HALF INTEGRAL
+    0x2321: 0x00f5,     #  BOTTOM HALF INTEGRAL
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2552: 0x00d5,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x2553: 0x00d6,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2555: 0x00b8,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x2556: 0x00b7,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x2558: 0x00d4,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x2559: 0x00d3,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255b: 0x00be,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x255c: 0x00bd,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x255e: 0x00c6,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x255f: 0x00c7,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2561: 0x00b5,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x2562: 0x00b6,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2564: 0x00d1,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x2565: 0x00d2,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2567: 0x00cf,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x2568: 0x00d0,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256a: 0x00d8,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x256b: 0x00d7,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp862.py b/src/main/resources/PythonLibs/encodings/cp862.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea0405ca1ba4c2e280afefc2d4050c35e8077b48
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp862.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP862.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp862',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x05d0,     #  HEBREW LETTER ALEF
+    0x0081: 0x05d1,     #  HEBREW LETTER BET
+    0x0082: 0x05d2,     #  HEBREW LETTER GIMEL
+    0x0083: 0x05d3,     #  HEBREW LETTER DALET
+    0x0084: 0x05d4,     #  HEBREW LETTER HE
+    0x0085: 0x05d5,     #  HEBREW LETTER VAV
+    0x0086: 0x05d6,     #  HEBREW LETTER ZAYIN
+    0x0087: 0x05d7,     #  HEBREW LETTER HET
+    0x0088: 0x05d8,     #  HEBREW LETTER TET
+    0x0089: 0x05d9,     #  HEBREW LETTER YOD
+    0x008a: 0x05da,     #  HEBREW LETTER FINAL KAF
+    0x008b: 0x05db,     #  HEBREW LETTER KAF
+    0x008c: 0x05dc,     #  HEBREW LETTER LAMED
+    0x008d: 0x05dd,     #  HEBREW LETTER FINAL MEM
+    0x008e: 0x05de,     #  HEBREW LETTER MEM
+    0x008f: 0x05df,     #  HEBREW LETTER FINAL NUN
+    0x0090: 0x05e0,     #  HEBREW LETTER NUN
+    0x0091: 0x05e1,     #  HEBREW LETTER SAMEKH
+    0x0092: 0x05e2,     #  HEBREW LETTER AYIN
+    0x0093: 0x05e3,     #  HEBREW LETTER FINAL PE
+    0x0094: 0x05e4,     #  HEBREW LETTER PE
+    0x0095: 0x05e5,     #  HEBREW LETTER FINAL TSADI
+    0x0096: 0x05e6,     #  HEBREW LETTER TSADI
+    0x0097: 0x05e7,     #  HEBREW LETTER QOF
+    0x0098: 0x05e8,     #  HEBREW LETTER RESH
+    0x0099: 0x05e9,     #  HEBREW LETTER SHIN
+    0x009a: 0x05ea,     #  HEBREW LETTER TAV
+    0x009b: 0x00a2,     #  CENT SIGN
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00a5,     #  YEN SIGN
+    0x009e: 0x20a7,     #  PESETA SIGN
+    0x009f: 0x0192,     #  LATIN SMALL LETTER F WITH HOOK
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00f1,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00a5: 0x00d1,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00a6: 0x00aa,     #  FEMININE ORDINAL INDICATOR
+    0x00a7: 0x00ba,     #  MASCULINE ORDINAL INDICATOR
+    0x00a8: 0x00bf,     #  INVERTED QUESTION MARK
+    0x00a9: 0x2310,     #  REVERSED NOT SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00a1,     #  INVERTED EXCLAMATION MARK
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x2561,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x00b6: 0x2562,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x00b7: 0x2556,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x00b8: 0x2555,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x255c,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x00be: 0x255b,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x255e,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x00c7: 0x255f,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x2567,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x00d0: 0x2568,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x00d1: 0x2564,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x00d2: 0x2565,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x00d3: 0x2559,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x00d4: 0x2558,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x00d5: 0x2552,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x00d6: 0x2553,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x00d7: 0x256b,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x00d8: 0x256a,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x03b1,     #  GREEK SMALL LETTER ALPHA
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S (GERMAN)
+    0x00e2: 0x0393,     #  GREEK CAPITAL LETTER GAMMA
+    0x00e3: 0x03c0,     #  GREEK SMALL LETTER PI
+    0x00e4: 0x03a3,     #  GREEK CAPITAL LETTER SIGMA
+    0x00e5: 0x03c3,     #  GREEK SMALL LETTER SIGMA
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x03c4,     #  GREEK SMALL LETTER TAU
+    0x00e8: 0x03a6,     #  GREEK CAPITAL LETTER PHI
+    0x00e9: 0x0398,     #  GREEK CAPITAL LETTER THETA
+    0x00ea: 0x03a9,     #  GREEK CAPITAL LETTER OMEGA
+    0x00eb: 0x03b4,     #  GREEK SMALL LETTER DELTA
+    0x00ec: 0x221e,     #  INFINITY
+    0x00ed: 0x03c6,     #  GREEK SMALL LETTER PHI
+    0x00ee: 0x03b5,     #  GREEK SMALL LETTER EPSILON
+    0x00ef: 0x2229,     #  INTERSECTION
+    0x00f0: 0x2261,     #  IDENTICAL TO
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2265,     #  GREATER-THAN OR EQUAL TO
+    0x00f3: 0x2264,     #  LESS-THAN OR EQUAL TO
+    0x00f4: 0x2320,     #  TOP HALF INTEGRAL
+    0x00f5: 0x2321,     #  BOTTOM HALF INTEGRAL
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x2248,     #  ALMOST EQUAL TO
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x221a,     #  SQUARE ROOT
+    0x00fc: 0x207f,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\u05d0'   #  0x0080 -> HEBREW LETTER ALEF
+    u'\u05d1'   #  0x0081 -> HEBREW LETTER BET
+    u'\u05d2'   #  0x0082 -> HEBREW LETTER GIMEL
+    u'\u05d3'   #  0x0083 -> HEBREW LETTER DALET
+    u'\u05d4'   #  0x0084 -> HEBREW LETTER HE
+    u'\u05d5'   #  0x0085 -> HEBREW LETTER VAV
+    u'\u05d6'   #  0x0086 -> HEBREW LETTER ZAYIN
+    u'\u05d7'   #  0x0087 -> HEBREW LETTER HET
+    u'\u05d8'   #  0x0088 -> HEBREW LETTER TET
+    u'\u05d9'   #  0x0089 -> HEBREW LETTER YOD
+    u'\u05da'   #  0x008a -> HEBREW LETTER FINAL KAF
+    u'\u05db'   #  0x008b -> HEBREW LETTER KAF
+    u'\u05dc'   #  0x008c -> HEBREW LETTER LAMED
+    u'\u05dd'   #  0x008d -> HEBREW LETTER FINAL MEM
+    u'\u05de'   #  0x008e -> HEBREW LETTER MEM
+    u'\u05df'   #  0x008f -> HEBREW LETTER FINAL NUN
+    u'\u05e0'   #  0x0090 -> HEBREW LETTER NUN
+    u'\u05e1'   #  0x0091 -> HEBREW LETTER SAMEKH
+    u'\u05e2'   #  0x0092 -> HEBREW LETTER AYIN
+    u'\u05e3'   #  0x0093 -> HEBREW LETTER FINAL PE
+    u'\u05e4'   #  0x0094 -> HEBREW LETTER PE
+    u'\u05e5'   #  0x0095 -> HEBREW LETTER FINAL TSADI
+    u'\u05e6'   #  0x0096 -> HEBREW LETTER TSADI
+    u'\u05e7'   #  0x0097 -> HEBREW LETTER QOF
+    u'\u05e8'   #  0x0098 -> HEBREW LETTER RESH
+    u'\u05e9'   #  0x0099 -> HEBREW LETTER SHIN
+    u'\u05ea'   #  0x009a -> HEBREW LETTER TAV
+    u'\xa2'     #  0x009b -> CENT SIGN
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xa5'     #  0x009d -> YEN SIGN
+    u'\u20a7'   #  0x009e -> PESETA SIGN
+    u'\u0192'   #  0x009f -> LATIN SMALL LETTER F WITH HOOK
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf1'     #  0x00a4 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xd1'     #  0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xaa'     #  0x00a6 -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x00a7 -> MASCULINE ORDINAL INDICATOR
+    u'\xbf'     #  0x00a8 -> INVERTED QUESTION MARK
+    u'\u2310'   #  0x00a9 -> REVERSED NOT SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xa1'     #  0x00ad -> INVERTED EXCLAMATION MARK
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u03b1'   #  0x00e0 -> GREEK SMALL LETTER ALPHA
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S (GERMAN)
+    u'\u0393'   #  0x00e2 -> GREEK CAPITAL LETTER GAMMA
+    u'\u03c0'   #  0x00e3 -> GREEK SMALL LETTER PI
+    u'\u03a3'   #  0x00e4 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03c3'   #  0x00e5 -> GREEK SMALL LETTER SIGMA
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\u03c4'   #  0x00e7 -> GREEK SMALL LETTER TAU
+    u'\u03a6'   #  0x00e8 -> GREEK CAPITAL LETTER PHI
+    u'\u0398'   #  0x00e9 -> GREEK CAPITAL LETTER THETA
+    u'\u03a9'   #  0x00ea -> GREEK CAPITAL LETTER OMEGA
+    u'\u03b4'   #  0x00eb -> GREEK SMALL LETTER DELTA
+    u'\u221e'   #  0x00ec -> INFINITY
+    u'\u03c6'   #  0x00ed -> GREEK SMALL LETTER PHI
+    u'\u03b5'   #  0x00ee -> GREEK SMALL LETTER EPSILON
+    u'\u2229'   #  0x00ef -> INTERSECTION
+    u'\u2261'   #  0x00f0 -> IDENTICAL TO
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2265'   #  0x00f2 -> GREATER-THAN OR EQUAL TO
+    u'\u2264'   #  0x00f3 -> LESS-THAN OR EQUAL TO
+    u'\u2320'   #  0x00f4 -> TOP HALF INTEGRAL
+    u'\u2321'   #  0x00f5 -> BOTTOM HALF INTEGRAL
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\u2248'   #  0x00f7 -> ALMOST EQUAL TO
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\u221a'   #  0x00fb -> SQUARE ROOT
+    u'\u207f'   #  0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a1: 0x00ad,     #  INVERTED EXCLAMATION MARK
+    0x00a2: 0x009b,     #  CENT SIGN
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a5: 0x009d,     #  YEN SIGN
+    0x00aa: 0x00a6,     #  FEMININE ORDINAL INDICATOR
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00ba: 0x00a7,     #  MASCULINE ORDINAL INDICATOR
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00bf: 0x00a8,     #  INVERTED QUESTION MARK
+    0x00d1: 0x00a5,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S (GERMAN)
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00f1: 0x00a4,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x0192: 0x009f,     #  LATIN SMALL LETTER F WITH HOOK
+    0x0393: 0x00e2,     #  GREEK CAPITAL LETTER GAMMA
+    0x0398: 0x00e9,     #  GREEK CAPITAL LETTER THETA
+    0x03a3: 0x00e4,     #  GREEK CAPITAL LETTER SIGMA
+    0x03a6: 0x00e8,     #  GREEK CAPITAL LETTER PHI
+    0x03a9: 0x00ea,     #  GREEK CAPITAL LETTER OMEGA
+    0x03b1: 0x00e0,     #  GREEK SMALL LETTER ALPHA
+    0x03b4: 0x00eb,     #  GREEK SMALL LETTER DELTA
+    0x03b5: 0x00ee,     #  GREEK SMALL LETTER EPSILON
+    0x03c0: 0x00e3,     #  GREEK SMALL LETTER PI
+    0x03c3: 0x00e5,     #  GREEK SMALL LETTER SIGMA
+    0x03c4: 0x00e7,     #  GREEK SMALL LETTER TAU
+    0x03c6: 0x00ed,     #  GREEK SMALL LETTER PHI
+    0x05d0: 0x0080,     #  HEBREW LETTER ALEF
+    0x05d1: 0x0081,     #  HEBREW LETTER BET
+    0x05d2: 0x0082,     #  HEBREW LETTER GIMEL
+    0x05d3: 0x0083,     #  HEBREW LETTER DALET
+    0x05d4: 0x0084,     #  HEBREW LETTER HE
+    0x05d5: 0x0085,     #  HEBREW LETTER VAV
+    0x05d6: 0x0086,     #  HEBREW LETTER ZAYIN
+    0x05d7: 0x0087,     #  HEBREW LETTER HET
+    0x05d8: 0x0088,     #  HEBREW LETTER TET
+    0x05d9: 0x0089,     #  HEBREW LETTER YOD
+    0x05da: 0x008a,     #  HEBREW LETTER FINAL KAF
+    0x05db: 0x008b,     #  HEBREW LETTER KAF
+    0x05dc: 0x008c,     #  HEBREW LETTER LAMED
+    0x05dd: 0x008d,     #  HEBREW LETTER FINAL MEM
+    0x05de: 0x008e,     #  HEBREW LETTER MEM
+    0x05df: 0x008f,     #  HEBREW LETTER FINAL NUN
+    0x05e0: 0x0090,     #  HEBREW LETTER NUN
+    0x05e1: 0x0091,     #  HEBREW LETTER SAMEKH
+    0x05e2: 0x0092,     #  HEBREW LETTER AYIN
+    0x05e3: 0x0093,     #  HEBREW LETTER FINAL PE
+    0x05e4: 0x0094,     #  HEBREW LETTER PE
+    0x05e5: 0x0095,     #  HEBREW LETTER FINAL TSADI
+    0x05e6: 0x0096,     #  HEBREW LETTER TSADI
+    0x05e7: 0x0097,     #  HEBREW LETTER QOF
+    0x05e8: 0x0098,     #  HEBREW LETTER RESH
+    0x05e9: 0x0099,     #  HEBREW LETTER SHIN
+    0x05ea: 0x009a,     #  HEBREW LETTER TAV
+    0x207f: 0x00fc,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x20a7: 0x009e,     #  PESETA SIGN
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x221a: 0x00fb,     #  SQUARE ROOT
+    0x221e: 0x00ec,     #  INFINITY
+    0x2229: 0x00ef,     #  INTERSECTION
+    0x2248: 0x00f7,     #  ALMOST EQUAL TO
+    0x2261: 0x00f0,     #  IDENTICAL TO
+    0x2264: 0x00f3,     #  LESS-THAN OR EQUAL TO
+    0x2265: 0x00f2,     #  GREATER-THAN OR EQUAL TO
+    0x2310: 0x00a9,     #  REVERSED NOT SIGN
+    0x2320: 0x00f4,     #  TOP HALF INTEGRAL
+    0x2321: 0x00f5,     #  BOTTOM HALF INTEGRAL
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2552: 0x00d5,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x2553: 0x00d6,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2555: 0x00b8,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x2556: 0x00b7,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x2558: 0x00d4,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x2559: 0x00d3,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255b: 0x00be,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x255c: 0x00bd,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x255e: 0x00c6,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x255f: 0x00c7,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2561: 0x00b5,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x2562: 0x00b6,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2564: 0x00d1,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x2565: 0x00d2,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2567: 0x00cf,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x2568: 0x00d0,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256a: 0x00d8,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x256b: 0x00d7,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp863.py b/src/main/resources/PythonLibs/encodings/cp863.py
new file mode 100644
index 0000000000000000000000000000000000000000..62dfabf66ab0d19644b626f1638d4a5c8ef3a7ab
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp863.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP863.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp863',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00c2,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x0085: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0086: 0x00b6,     #  PILCROW SIGN
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0089: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x008a: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x008b: 0x00ef,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x008c: 0x00ee,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x008d: 0x2017,     #  DOUBLE LOW LINE
+    0x008e: 0x00c0,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x008f: 0x00a7,     #  SECTION SIGN
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00c8,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x0092: 0x00ca,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00cb,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x0095: 0x00cf,     #  LATIN CAPITAL LETTER I WITH DIAERESIS
+    0x0096: 0x00fb,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x0097: 0x00f9,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x0098: 0x00a4,     #  CURRENCY SIGN
+    0x0099: 0x00d4,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00a2,     #  CENT SIGN
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00d9,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x009e: 0x00db,     #  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    0x009f: 0x0192,     #  LATIN SMALL LETTER F WITH HOOK
+    0x00a0: 0x00a6,     #  BROKEN BAR
+    0x00a1: 0x00b4,     #  ACUTE ACCENT
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00a8,     #  DIAERESIS
+    0x00a5: 0x00b8,     #  CEDILLA
+    0x00a6: 0x00b3,     #  SUPERSCRIPT THREE
+    0x00a7: 0x00af,     #  MACRON
+    0x00a8: 0x00ce,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00a9: 0x2310,     #  REVERSED NOT SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00be,     #  VULGAR FRACTION THREE QUARTERS
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x2561,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x00b6: 0x2562,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x00b7: 0x2556,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x00b8: 0x2555,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x255c,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x00be: 0x255b,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x255e,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x00c7: 0x255f,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x2567,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x00d0: 0x2568,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x00d1: 0x2564,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x00d2: 0x2565,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x00d3: 0x2559,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x00d4: 0x2558,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x00d5: 0x2552,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x00d6: 0x2553,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x00d7: 0x256b,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x00d8: 0x256a,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x03b1,     #  GREEK SMALL LETTER ALPHA
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x0393,     #  GREEK CAPITAL LETTER GAMMA
+    0x00e3: 0x03c0,     #  GREEK SMALL LETTER PI
+    0x00e4: 0x03a3,     #  GREEK CAPITAL LETTER SIGMA
+    0x00e5: 0x03c3,     #  GREEK SMALL LETTER SIGMA
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x03c4,     #  GREEK SMALL LETTER TAU
+    0x00e8: 0x03a6,     #  GREEK CAPITAL LETTER PHI
+    0x00e9: 0x0398,     #  GREEK CAPITAL LETTER THETA
+    0x00ea: 0x03a9,     #  GREEK CAPITAL LETTER OMEGA
+    0x00eb: 0x03b4,     #  GREEK SMALL LETTER DELTA
+    0x00ec: 0x221e,     #  INFINITY
+    0x00ed: 0x03c6,     #  GREEK SMALL LETTER PHI
+    0x00ee: 0x03b5,     #  GREEK SMALL LETTER EPSILON
+    0x00ef: 0x2229,     #  INTERSECTION
+    0x00f0: 0x2261,     #  IDENTICAL TO
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2265,     #  GREATER-THAN OR EQUAL TO
+    0x00f3: 0x2264,     #  LESS-THAN OR EQUAL TO
+    0x00f4: 0x2320,     #  TOP HALF INTEGRAL
+    0x00f5: 0x2321,     #  BOTTOM HALF INTEGRAL
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x2248,     #  ALMOST EQUAL TO
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x221a,     #  SQUARE ROOT
+    0x00fc: 0x207f,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xc2'     #  0x0084 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xe0'     #  0x0085 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xb6'     #  0x0086 -> PILCROW SIGN
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x008a -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xef'     #  0x008b -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xee'     #  0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\u2017'   #  0x008d -> DOUBLE LOW LINE
+    u'\xc0'     #  0x008e -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xa7'     #  0x008f -> SECTION SIGN
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xc8'     #  0x0091 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xca'     #  0x0092 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xcb'     #  0x0094 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcf'     #  0x0095 -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xfb'     #  0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xf9'     #  0x0097 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xa4'     #  0x0098 -> CURRENCY SIGN
+    u'\xd4'     #  0x0099 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xa2'     #  0x009b -> CENT SIGN
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xd9'     #  0x009d -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xdb'     #  0x009e -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\u0192'   #  0x009f -> LATIN SMALL LETTER F WITH HOOK
+    u'\xa6'     #  0x00a0 -> BROKEN BAR
+    u'\xb4'     #  0x00a1 -> ACUTE ACCENT
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xa8'     #  0x00a4 -> DIAERESIS
+    u'\xb8'     #  0x00a5 -> CEDILLA
+    u'\xb3'     #  0x00a6 -> SUPERSCRIPT THREE
+    u'\xaf'     #  0x00a7 -> MACRON
+    u'\xce'     #  0x00a8 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\u2310'   #  0x00a9 -> REVERSED NOT SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xbe'     #  0x00ad -> VULGAR FRACTION THREE QUARTERS
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u03b1'   #  0x00e0 -> GREEK SMALL LETTER ALPHA
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\u0393'   #  0x00e2 -> GREEK CAPITAL LETTER GAMMA
+    u'\u03c0'   #  0x00e3 -> GREEK SMALL LETTER PI
+    u'\u03a3'   #  0x00e4 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03c3'   #  0x00e5 -> GREEK SMALL LETTER SIGMA
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\u03c4'   #  0x00e7 -> GREEK SMALL LETTER TAU
+    u'\u03a6'   #  0x00e8 -> GREEK CAPITAL LETTER PHI
+    u'\u0398'   #  0x00e9 -> GREEK CAPITAL LETTER THETA
+    u'\u03a9'   #  0x00ea -> GREEK CAPITAL LETTER OMEGA
+    u'\u03b4'   #  0x00eb -> GREEK SMALL LETTER DELTA
+    u'\u221e'   #  0x00ec -> INFINITY
+    u'\u03c6'   #  0x00ed -> GREEK SMALL LETTER PHI
+    u'\u03b5'   #  0x00ee -> GREEK SMALL LETTER EPSILON
+    u'\u2229'   #  0x00ef -> INTERSECTION
+    u'\u2261'   #  0x00f0 -> IDENTICAL TO
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2265'   #  0x00f2 -> GREATER-THAN OR EQUAL TO
+    u'\u2264'   #  0x00f3 -> LESS-THAN OR EQUAL TO
+    u'\u2320'   #  0x00f4 -> TOP HALF INTEGRAL
+    u'\u2321'   #  0x00f5 -> BOTTOM HALF INTEGRAL
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\u2248'   #  0x00f7 -> ALMOST EQUAL TO
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\u221a'   #  0x00fb -> SQUARE ROOT
+    u'\u207f'   #  0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a2: 0x009b,     #  CENT SIGN
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a4: 0x0098,     #  CURRENCY SIGN
+    0x00a6: 0x00a0,     #  BROKEN BAR
+    0x00a7: 0x008f,     #  SECTION SIGN
+    0x00a8: 0x00a4,     #  DIAERESIS
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00af: 0x00a7,     #  MACRON
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b3: 0x00a6,     #  SUPERSCRIPT THREE
+    0x00b4: 0x00a1,     #  ACUTE ACCENT
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b6: 0x0086,     #  PILCROW SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00b8: 0x00a5,     #  CEDILLA
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00be: 0x00ad,     #  VULGAR FRACTION THREE QUARTERS
+    0x00c0: 0x008e,     #  LATIN CAPITAL LETTER A WITH GRAVE
+    0x00c2: 0x0084,     #  LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c8: 0x0091,     #  LATIN CAPITAL LETTER E WITH GRAVE
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00ca: 0x0092,     #  LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    0x00cb: 0x0094,     #  LATIN CAPITAL LETTER E WITH DIAERESIS
+    0x00ce: 0x00a8,     #  LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    0x00cf: 0x0095,     #  LATIN CAPITAL LETTER I WITH DIAERESIS
+    0x00d4: 0x0099,     #  LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    0x00d9: 0x009d,     #  LATIN CAPITAL LETTER U WITH GRAVE
+    0x00db: 0x009e,     #  LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e0: 0x0085,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008a,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0088,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00eb: 0x0089,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ee: 0x008c,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x00ef: 0x008b,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f9: 0x0097,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fb: 0x0096,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0192: 0x009f,     #  LATIN SMALL LETTER F WITH HOOK
+    0x0393: 0x00e2,     #  GREEK CAPITAL LETTER GAMMA
+    0x0398: 0x00e9,     #  GREEK CAPITAL LETTER THETA
+    0x03a3: 0x00e4,     #  GREEK CAPITAL LETTER SIGMA
+    0x03a6: 0x00e8,     #  GREEK CAPITAL LETTER PHI
+    0x03a9: 0x00ea,     #  GREEK CAPITAL LETTER OMEGA
+    0x03b1: 0x00e0,     #  GREEK SMALL LETTER ALPHA
+    0x03b4: 0x00eb,     #  GREEK SMALL LETTER DELTA
+    0x03b5: 0x00ee,     #  GREEK SMALL LETTER EPSILON
+    0x03c0: 0x00e3,     #  GREEK SMALL LETTER PI
+    0x03c3: 0x00e5,     #  GREEK SMALL LETTER SIGMA
+    0x03c4: 0x00e7,     #  GREEK SMALL LETTER TAU
+    0x03c6: 0x00ed,     #  GREEK SMALL LETTER PHI
+    0x2017: 0x008d,     #  DOUBLE LOW LINE
+    0x207f: 0x00fc,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x221a: 0x00fb,     #  SQUARE ROOT
+    0x221e: 0x00ec,     #  INFINITY
+    0x2229: 0x00ef,     #  INTERSECTION
+    0x2248: 0x00f7,     #  ALMOST EQUAL TO
+    0x2261: 0x00f0,     #  IDENTICAL TO
+    0x2264: 0x00f3,     #  LESS-THAN OR EQUAL TO
+    0x2265: 0x00f2,     #  GREATER-THAN OR EQUAL TO
+    0x2310: 0x00a9,     #  REVERSED NOT SIGN
+    0x2320: 0x00f4,     #  TOP HALF INTEGRAL
+    0x2321: 0x00f5,     #  BOTTOM HALF INTEGRAL
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2552: 0x00d5,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x2553: 0x00d6,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2555: 0x00b8,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x2556: 0x00b7,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x2558: 0x00d4,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x2559: 0x00d3,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255b: 0x00be,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x255c: 0x00bd,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x255e: 0x00c6,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x255f: 0x00c7,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2561: 0x00b5,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x2562: 0x00b6,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2564: 0x00d1,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x2565: 0x00d2,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2567: 0x00cf,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x2568: 0x00d0,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256a: 0x00d8,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x256b: 0x00d7,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp864.py b/src/main/resources/PythonLibs/encodings/cp864.py
new file mode 100644
index 0000000000000000000000000000000000000000..02a0e733a8733743343bad41f0c4c4c77dfe86eb
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp864.py
@@ -0,0 +1,690 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP864.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp864',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0025: 0x066a,     #  ARABIC PERCENT SIGN
+    0x0080: 0x00b0,     #  DEGREE SIGN
+    0x0081: 0x00b7,     #  MIDDLE DOT
+    0x0082: 0x2219,     #  BULLET OPERATOR
+    0x0083: 0x221a,     #  SQUARE ROOT
+    0x0084: 0x2592,     #  MEDIUM SHADE
+    0x0085: 0x2500,     #  FORMS LIGHT HORIZONTAL
+    0x0086: 0x2502,     #  FORMS LIGHT VERTICAL
+    0x0087: 0x253c,     #  FORMS LIGHT VERTICAL AND HORIZONTAL
+    0x0088: 0x2524,     #  FORMS LIGHT VERTICAL AND LEFT
+    0x0089: 0x252c,     #  FORMS LIGHT DOWN AND HORIZONTAL
+    0x008a: 0x251c,     #  FORMS LIGHT VERTICAL AND RIGHT
+    0x008b: 0x2534,     #  FORMS LIGHT UP AND HORIZONTAL
+    0x008c: 0x2510,     #  FORMS LIGHT DOWN AND LEFT
+    0x008d: 0x250c,     #  FORMS LIGHT DOWN AND RIGHT
+    0x008e: 0x2514,     #  FORMS LIGHT UP AND RIGHT
+    0x008f: 0x2518,     #  FORMS LIGHT UP AND LEFT
+    0x0090: 0x03b2,     #  GREEK SMALL BETA
+    0x0091: 0x221e,     #  INFINITY
+    0x0092: 0x03c6,     #  GREEK SMALL PHI
+    0x0093: 0x00b1,     #  PLUS-OR-MINUS SIGN
+    0x0094: 0x00bd,     #  FRACTION 1/2
+    0x0095: 0x00bc,     #  FRACTION 1/4
+    0x0096: 0x2248,     #  ALMOST EQUAL TO
+    0x0097: 0x00ab,     #  LEFT POINTING GUILLEMET
+    0x0098: 0x00bb,     #  RIGHT POINTING GUILLEMET
+    0x0099: 0xfef7,     #  ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+    0x009a: 0xfef8,     #  ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+    0x009b: None,       #  UNDEFINED
+    0x009c: None,       #  UNDEFINED
+    0x009d: 0xfefb,     #  ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+    0x009e: 0xfefc,     #  ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+    0x009f: None,       #  UNDEFINED
+    0x00a1: 0x00ad,     #  SOFT HYPHEN
+    0x00a2: 0xfe82,     #  ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+    0x00a5: 0xfe84,     #  ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+    0x00a6: None,       #  UNDEFINED
+    0x00a7: None,       #  UNDEFINED
+    0x00a8: 0xfe8e,     #  ARABIC LETTER ALEF FINAL FORM
+    0x00a9: 0xfe8f,     #  ARABIC LETTER BEH ISOLATED FORM
+    0x00aa: 0xfe95,     #  ARABIC LETTER TEH ISOLATED FORM
+    0x00ab: 0xfe99,     #  ARABIC LETTER THEH ISOLATED FORM
+    0x00ac: 0x060c,     #  ARABIC COMMA
+    0x00ad: 0xfe9d,     #  ARABIC LETTER JEEM ISOLATED FORM
+    0x00ae: 0xfea1,     #  ARABIC LETTER HAH ISOLATED FORM
+    0x00af: 0xfea5,     #  ARABIC LETTER KHAH ISOLATED FORM
+    0x00b0: 0x0660,     #  ARABIC-INDIC DIGIT ZERO
+    0x00b1: 0x0661,     #  ARABIC-INDIC DIGIT ONE
+    0x00b2: 0x0662,     #  ARABIC-INDIC DIGIT TWO
+    0x00b3: 0x0663,     #  ARABIC-INDIC DIGIT THREE
+    0x00b4: 0x0664,     #  ARABIC-INDIC DIGIT FOUR
+    0x00b5: 0x0665,     #  ARABIC-INDIC DIGIT FIVE
+    0x00b6: 0x0666,     #  ARABIC-INDIC DIGIT SIX
+    0x00b7: 0x0667,     #  ARABIC-INDIC DIGIT SEVEN
+    0x00b8: 0x0668,     #  ARABIC-INDIC DIGIT EIGHT
+    0x00b9: 0x0669,     #  ARABIC-INDIC DIGIT NINE
+    0x00ba: 0xfed1,     #  ARABIC LETTER FEH ISOLATED FORM
+    0x00bb: 0x061b,     #  ARABIC SEMICOLON
+    0x00bc: 0xfeb1,     #  ARABIC LETTER SEEN ISOLATED FORM
+    0x00bd: 0xfeb5,     #  ARABIC LETTER SHEEN ISOLATED FORM
+    0x00be: 0xfeb9,     #  ARABIC LETTER SAD ISOLATED FORM
+    0x00bf: 0x061f,     #  ARABIC QUESTION MARK
+    0x00c0: 0x00a2,     #  CENT SIGN
+    0x00c1: 0xfe80,     #  ARABIC LETTER HAMZA ISOLATED FORM
+    0x00c2: 0xfe81,     #  ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+    0x00c3: 0xfe83,     #  ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+    0x00c4: 0xfe85,     #  ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+    0x00c5: 0xfeca,     #  ARABIC LETTER AIN FINAL FORM
+    0x00c6: 0xfe8b,     #  ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+    0x00c7: 0xfe8d,     #  ARABIC LETTER ALEF ISOLATED FORM
+    0x00c8: 0xfe91,     #  ARABIC LETTER BEH INITIAL FORM
+    0x00c9: 0xfe93,     #  ARABIC LETTER TEH MARBUTA ISOLATED FORM
+    0x00ca: 0xfe97,     #  ARABIC LETTER TEH INITIAL FORM
+    0x00cb: 0xfe9b,     #  ARABIC LETTER THEH INITIAL FORM
+    0x00cc: 0xfe9f,     #  ARABIC LETTER JEEM INITIAL FORM
+    0x00cd: 0xfea3,     #  ARABIC LETTER HAH INITIAL FORM
+    0x00ce: 0xfea7,     #  ARABIC LETTER KHAH INITIAL FORM
+    0x00cf: 0xfea9,     #  ARABIC LETTER DAL ISOLATED FORM
+    0x00d0: 0xfeab,     #  ARABIC LETTER THAL ISOLATED FORM
+    0x00d1: 0xfead,     #  ARABIC LETTER REH ISOLATED FORM
+    0x00d2: 0xfeaf,     #  ARABIC LETTER ZAIN ISOLATED FORM
+    0x00d3: 0xfeb3,     #  ARABIC LETTER SEEN INITIAL FORM
+    0x00d4: 0xfeb7,     #  ARABIC LETTER SHEEN INITIAL FORM
+    0x00d5: 0xfebb,     #  ARABIC LETTER SAD INITIAL FORM
+    0x00d6: 0xfebf,     #  ARABIC LETTER DAD INITIAL FORM
+    0x00d7: 0xfec1,     #  ARABIC LETTER TAH ISOLATED FORM
+    0x00d8: 0xfec5,     #  ARABIC LETTER ZAH ISOLATED FORM
+    0x00d9: 0xfecb,     #  ARABIC LETTER AIN INITIAL FORM
+    0x00da: 0xfecf,     #  ARABIC LETTER GHAIN INITIAL FORM
+    0x00db: 0x00a6,     #  BROKEN VERTICAL BAR
+    0x00dc: 0x00ac,     #  NOT SIGN
+    0x00dd: 0x00f7,     #  DIVISION SIGN
+    0x00de: 0x00d7,     #  MULTIPLICATION SIGN
+    0x00df: 0xfec9,     #  ARABIC LETTER AIN ISOLATED FORM
+    0x00e0: 0x0640,     #  ARABIC TATWEEL
+    0x00e1: 0xfed3,     #  ARABIC LETTER FEH INITIAL FORM
+    0x00e2: 0xfed7,     #  ARABIC LETTER QAF INITIAL FORM
+    0x00e3: 0xfedb,     #  ARABIC LETTER KAF INITIAL FORM
+    0x00e4: 0xfedf,     #  ARABIC LETTER LAM INITIAL FORM
+    0x00e5: 0xfee3,     #  ARABIC LETTER MEEM INITIAL FORM
+    0x00e6: 0xfee7,     #  ARABIC LETTER NOON INITIAL FORM
+    0x00e7: 0xfeeb,     #  ARABIC LETTER HEH INITIAL FORM
+    0x00e8: 0xfeed,     #  ARABIC LETTER WAW ISOLATED FORM
+    0x00e9: 0xfeef,     #  ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+    0x00ea: 0xfef3,     #  ARABIC LETTER YEH INITIAL FORM
+    0x00eb: 0xfebd,     #  ARABIC LETTER DAD ISOLATED FORM
+    0x00ec: 0xfecc,     #  ARABIC LETTER AIN MEDIAL FORM
+    0x00ed: 0xfece,     #  ARABIC LETTER GHAIN FINAL FORM
+    0x00ee: 0xfecd,     #  ARABIC LETTER GHAIN ISOLATED FORM
+    0x00ef: 0xfee1,     #  ARABIC LETTER MEEM ISOLATED FORM
+    0x00f0: 0xfe7d,     #  ARABIC SHADDA MEDIAL FORM
+    0x00f1: 0x0651,     #  ARABIC SHADDAH
+    0x00f2: 0xfee5,     #  ARABIC LETTER NOON ISOLATED FORM
+    0x00f3: 0xfee9,     #  ARABIC LETTER HEH ISOLATED FORM
+    0x00f4: 0xfeec,     #  ARABIC LETTER HEH MEDIAL FORM
+    0x00f5: 0xfef0,     #  ARABIC LETTER ALEF MAKSURA FINAL FORM
+    0x00f6: 0xfef2,     #  ARABIC LETTER YEH FINAL FORM
+    0x00f7: 0xfed0,     #  ARABIC LETTER GHAIN MEDIAL FORM
+    0x00f8: 0xfed5,     #  ARABIC LETTER QAF ISOLATED FORM
+    0x00f9: 0xfef5,     #  ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+    0x00fa: 0xfef6,     #  ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+    0x00fb: 0xfedd,     #  ARABIC LETTER LAM ISOLATED FORM
+    0x00fc: 0xfed9,     #  ARABIC LETTER KAF ISOLATED FORM
+    0x00fd: 0xfef1,     #  ARABIC LETTER YEH ISOLATED FORM
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: None,       #  UNDEFINED
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'\u066a'   #  0x0025 -> ARABIC PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xb0'     #  0x0080 -> DEGREE SIGN
+    u'\xb7'     #  0x0081 -> MIDDLE DOT
+    u'\u2219'   #  0x0082 -> BULLET OPERATOR
+    u'\u221a'   #  0x0083 -> SQUARE ROOT
+    u'\u2592'   #  0x0084 -> MEDIUM SHADE
+    u'\u2500'   #  0x0085 -> FORMS LIGHT HORIZONTAL
+    u'\u2502'   #  0x0086 -> FORMS LIGHT VERTICAL
+    u'\u253c'   #  0x0087 -> FORMS LIGHT VERTICAL AND HORIZONTAL
+    u'\u2524'   #  0x0088 -> FORMS LIGHT VERTICAL AND LEFT
+    u'\u252c'   #  0x0089 -> FORMS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x008a -> FORMS LIGHT VERTICAL AND RIGHT
+    u'\u2534'   #  0x008b -> FORMS LIGHT UP AND HORIZONTAL
+    u'\u2510'   #  0x008c -> FORMS LIGHT DOWN AND LEFT
+    u'\u250c'   #  0x008d -> FORMS LIGHT DOWN AND RIGHT
+    u'\u2514'   #  0x008e -> FORMS LIGHT UP AND RIGHT
+    u'\u2518'   #  0x008f -> FORMS LIGHT UP AND LEFT
+    u'\u03b2'   #  0x0090 -> GREEK SMALL BETA
+    u'\u221e'   #  0x0091 -> INFINITY
+    u'\u03c6'   #  0x0092 -> GREEK SMALL PHI
+    u'\xb1'     #  0x0093 -> PLUS-OR-MINUS SIGN
+    u'\xbd'     #  0x0094 -> FRACTION 1/2
+    u'\xbc'     #  0x0095 -> FRACTION 1/4
+    u'\u2248'   #  0x0096 -> ALMOST EQUAL TO
+    u'\xab'     #  0x0097 -> LEFT POINTING GUILLEMET
+    u'\xbb'     #  0x0098 -> RIGHT POINTING GUILLEMET
+    u'\ufef7'   #  0x0099 -> ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+    u'\ufef8'   #  0x009a -> ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+    u'\ufffe'   #  0x009b -> UNDEFINED
+    u'\ufffe'   #  0x009c -> UNDEFINED
+    u'\ufefb'   #  0x009d -> ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+    u'\ufefc'   #  0x009e -> ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+    u'\ufffe'   #  0x009f -> UNDEFINED
+    u'\xa0'     #  0x00a0 -> NON-BREAKING SPACE
+    u'\xad'     #  0x00a1 -> SOFT HYPHEN
+    u'\ufe82'   #  0x00a2 -> ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+    u'\xa3'     #  0x00a3 -> POUND SIGN
+    u'\xa4'     #  0x00a4 -> CURRENCY SIGN
+    u'\ufe84'   #  0x00a5 -> ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+    u'\ufffe'   #  0x00a6 -> UNDEFINED
+    u'\ufffe'   #  0x00a7 -> UNDEFINED
+    u'\ufe8e'   #  0x00a8 -> ARABIC LETTER ALEF FINAL FORM
+    u'\ufe8f'   #  0x00a9 -> ARABIC LETTER BEH ISOLATED FORM
+    u'\ufe95'   #  0x00aa -> ARABIC LETTER TEH ISOLATED FORM
+    u'\ufe99'   #  0x00ab -> ARABIC LETTER THEH ISOLATED FORM
+    u'\u060c'   #  0x00ac -> ARABIC COMMA
+    u'\ufe9d'   #  0x00ad -> ARABIC LETTER JEEM ISOLATED FORM
+    u'\ufea1'   #  0x00ae -> ARABIC LETTER HAH ISOLATED FORM
+    u'\ufea5'   #  0x00af -> ARABIC LETTER KHAH ISOLATED FORM
+    u'\u0660'   #  0x00b0 -> ARABIC-INDIC DIGIT ZERO
+    u'\u0661'   #  0x00b1 -> ARABIC-INDIC DIGIT ONE
+    u'\u0662'   #  0x00b2 -> ARABIC-INDIC DIGIT TWO
+    u'\u0663'   #  0x00b3 -> ARABIC-INDIC DIGIT THREE
+    u'\u0664'   #  0x00b4 -> ARABIC-INDIC DIGIT FOUR
+    u'\u0665'   #  0x00b5 -> ARABIC-INDIC DIGIT FIVE
+    u'\u0666'   #  0x00b6 -> ARABIC-INDIC DIGIT SIX
+    u'\u0667'   #  0x00b7 -> ARABIC-INDIC DIGIT SEVEN
+    u'\u0668'   #  0x00b8 -> ARABIC-INDIC DIGIT EIGHT
+    u'\u0669'   #  0x00b9 -> ARABIC-INDIC DIGIT NINE
+    u'\ufed1'   #  0x00ba -> ARABIC LETTER FEH ISOLATED FORM
+    u'\u061b'   #  0x00bb -> ARABIC SEMICOLON
+    u'\ufeb1'   #  0x00bc -> ARABIC LETTER SEEN ISOLATED FORM
+    u'\ufeb5'   #  0x00bd -> ARABIC LETTER SHEEN ISOLATED FORM
+    u'\ufeb9'   #  0x00be -> ARABIC LETTER SAD ISOLATED FORM
+    u'\u061f'   #  0x00bf -> ARABIC QUESTION MARK
+    u'\xa2'     #  0x00c0 -> CENT SIGN
+    u'\ufe80'   #  0x00c1 -> ARABIC LETTER HAMZA ISOLATED FORM
+    u'\ufe81'   #  0x00c2 -> ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+    u'\ufe83'   #  0x00c3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+    u'\ufe85'   #  0x00c4 -> ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+    u'\ufeca'   #  0x00c5 -> ARABIC LETTER AIN FINAL FORM
+    u'\ufe8b'   #  0x00c6 -> ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+    u'\ufe8d'   #  0x00c7 -> ARABIC LETTER ALEF ISOLATED FORM
+    u'\ufe91'   #  0x00c8 -> ARABIC LETTER BEH INITIAL FORM
+    u'\ufe93'   #  0x00c9 -> ARABIC LETTER TEH MARBUTA ISOLATED FORM
+    u'\ufe97'   #  0x00ca -> ARABIC LETTER TEH INITIAL FORM
+    u'\ufe9b'   #  0x00cb -> ARABIC LETTER THEH INITIAL FORM
+    u'\ufe9f'   #  0x00cc -> ARABIC LETTER JEEM INITIAL FORM
+    u'\ufea3'   #  0x00cd -> ARABIC LETTER HAH INITIAL FORM
+    u'\ufea7'   #  0x00ce -> ARABIC LETTER KHAH INITIAL FORM
+    u'\ufea9'   #  0x00cf -> ARABIC LETTER DAL ISOLATED FORM
+    u'\ufeab'   #  0x00d0 -> ARABIC LETTER THAL ISOLATED FORM
+    u'\ufead'   #  0x00d1 -> ARABIC LETTER REH ISOLATED FORM
+    u'\ufeaf'   #  0x00d2 -> ARABIC LETTER ZAIN ISOLATED FORM
+    u'\ufeb3'   #  0x00d3 -> ARABIC LETTER SEEN INITIAL FORM
+    u'\ufeb7'   #  0x00d4 -> ARABIC LETTER SHEEN INITIAL FORM
+    u'\ufebb'   #  0x00d5 -> ARABIC LETTER SAD INITIAL FORM
+    u'\ufebf'   #  0x00d6 -> ARABIC LETTER DAD INITIAL FORM
+    u'\ufec1'   #  0x00d7 -> ARABIC LETTER TAH ISOLATED FORM
+    u'\ufec5'   #  0x00d8 -> ARABIC LETTER ZAH ISOLATED FORM
+    u'\ufecb'   #  0x00d9 -> ARABIC LETTER AIN INITIAL FORM
+    u'\ufecf'   #  0x00da -> ARABIC LETTER GHAIN INITIAL FORM
+    u'\xa6'     #  0x00db -> BROKEN VERTICAL BAR
+    u'\xac'     #  0x00dc -> NOT SIGN
+    u'\xf7'     #  0x00dd -> DIVISION SIGN
+    u'\xd7'     #  0x00de -> MULTIPLICATION SIGN
+    u'\ufec9'   #  0x00df -> ARABIC LETTER AIN ISOLATED FORM
+    u'\u0640'   #  0x00e0 -> ARABIC TATWEEL
+    u'\ufed3'   #  0x00e1 -> ARABIC LETTER FEH INITIAL FORM
+    u'\ufed7'   #  0x00e2 -> ARABIC LETTER QAF INITIAL FORM
+    u'\ufedb'   #  0x00e3 -> ARABIC LETTER KAF INITIAL FORM
+    u'\ufedf'   #  0x00e4 -> ARABIC LETTER LAM INITIAL FORM
+    u'\ufee3'   #  0x00e5 -> ARABIC LETTER MEEM INITIAL FORM
+    u'\ufee7'   #  0x00e6 -> ARABIC LETTER NOON INITIAL FORM
+    u'\ufeeb'   #  0x00e7 -> ARABIC LETTER HEH INITIAL FORM
+    u'\ufeed'   #  0x00e8 -> ARABIC LETTER WAW ISOLATED FORM
+    u'\ufeef'   #  0x00e9 -> ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+    u'\ufef3'   #  0x00ea -> ARABIC LETTER YEH INITIAL FORM
+    u'\ufebd'   #  0x00eb -> ARABIC LETTER DAD ISOLATED FORM
+    u'\ufecc'   #  0x00ec -> ARABIC LETTER AIN MEDIAL FORM
+    u'\ufece'   #  0x00ed -> ARABIC LETTER GHAIN FINAL FORM
+    u'\ufecd'   #  0x00ee -> ARABIC LETTER GHAIN ISOLATED FORM
+    u'\ufee1'   #  0x00ef -> ARABIC LETTER MEEM ISOLATED FORM
+    u'\ufe7d'   #  0x00f0 -> ARABIC SHADDA MEDIAL FORM
+    u'\u0651'   #  0x00f1 -> ARABIC SHADDAH
+    u'\ufee5'   #  0x00f2 -> ARABIC LETTER NOON ISOLATED FORM
+    u'\ufee9'   #  0x00f3 -> ARABIC LETTER HEH ISOLATED FORM
+    u'\ufeec'   #  0x00f4 -> ARABIC LETTER HEH MEDIAL FORM
+    u'\ufef0'   #  0x00f5 -> ARABIC LETTER ALEF MAKSURA FINAL FORM
+    u'\ufef2'   #  0x00f6 -> ARABIC LETTER YEH FINAL FORM
+    u'\ufed0'   #  0x00f7 -> ARABIC LETTER GHAIN MEDIAL FORM
+    u'\ufed5'   #  0x00f8 -> ARABIC LETTER QAF ISOLATED FORM
+    u'\ufef5'   #  0x00f9 -> ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+    u'\ufef6'   #  0x00fa -> ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+    u'\ufedd'   #  0x00fb -> ARABIC LETTER LAM ISOLATED FORM
+    u'\ufed9'   #  0x00fc -> ARABIC LETTER KAF ISOLATED FORM
+    u'\ufef1'   #  0x00fd -> ARABIC LETTER YEH ISOLATED FORM
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\ufffe'   #  0x00ff -> UNDEFINED
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00a0,     #  NON-BREAKING SPACE
+    0x00a2: 0x00c0,     #  CENT SIGN
+    0x00a3: 0x00a3,     #  POUND SIGN
+    0x00a4: 0x00a4,     #  CURRENCY SIGN
+    0x00a6: 0x00db,     #  BROKEN VERTICAL BAR
+    0x00ab: 0x0097,     #  LEFT POINTING GUILLEMET
+    0x00ac: 0x00dc,     #  NOT SIGN
+    0x00ad: 0x00a1,     #  SOFT HYPHEN
+    0x00b0: 0x0080,     #  DEGREE SIGN
+    0x00b1: 0x0093,     #  PLUS-OR-MINUS SIGN
+    0x00b7: 0x0081,     #  MIDDLE DOT
+    0x00bb: 0x0098,     #  RIGHT POINTING GUILLEMET
+    0x00bc: 0x0095,     #  FRACTION 1/4
+    0x00bd: 0x0094,     #  FRACTION 1/2
+    0x00d7: 0x00de,     #  MULTIPLICATION SIGN
+    0x00f7: 0x00dd,     #  DIVISION SIGN
+    0x03b2: 0x0090,     #  GREEK SMALL BETA
+    0x03c6: 0x0092,     #  GREEK SMALL PHI
+    0x060c: 0x00ac,     #  ARABIC COMMA
+    0x061b: 0x00bb,     #  ARABIC SEMICOLON
+    0x061f: 0x00bf,     #  ARABIC QUESTION MARK
+    0x0640: 0x00e0,     #  ARABIC TATWEEL
+    0x0651: 0x00f1,     #  ARABIC SHADDAH
+    0x0660: 0x00b0,     #  ARABIC-INDIC DIGIT ZERO
+    0x0661: 0x00b1,     #  ARABIC-INDIC DIGIT ONE
+    0x0662: 0x00b2,     #  ARABIC-INDIC DIGIT TWO
+    0x0663: 0x00b3,     #  ARABIC-INDIC DIGIT THREE
+    0x0664: 0x00b4,     #  ARABIC-INDIC DIGIT FOUR
+    0x0665: 0x00b5,     #  ARABIC-INDIC DIGIT FIVE
+    0x0666: 0x00b6,     #  ARABIC-INDIC DIGIT SIX
+    0x0667: 0x00b7,     #  ARABIC-INDIC DIGIT SEVEN
+    0x0668: 0x00b8,     #  ARABIC-INDIC DIGIT EIGHT
+    0x0669: 0x00b9,     #  ARABIC-INDIC DIGIT NINE
+    0x066a: 0x0025,     #  ARABIC PERCENT SIGN
+    0x2219: 0x0082,     #  BULLET OPERATOR
+    0x221a: 0x0083,     #  SQUARE ROOT
+    0x221e: 0x0091,     #  INFINITY
+    0x2248: 0x0096,     #  ALMOST EQUAL TO
+    0x2500: 0x0085,     #  FORMS LIGHT HORIZONTAL
+    0x2502: 0x0086,     #  FORMS LIGHT VERTICAL
+    0x250c: 0x008d,     #  FORMS LIGHT DOWN AND RIGHT
+    0x2510: 0x008c,     #  FORMS LIGHT DOWN AND LEFT
+    0x2514: 0x008e,     #  FORMS LIGHT UP AND RIGHT
+    0x2518: 0x008f,     #  FORMS LIGHT UP AND LEFT
+    0x251c: 0x008a,     #  FORMS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x0088,     #  FORMS LIGHT VERTICAL AND LEFT
+    0x252c: 0x0089,     #  FORMS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x008b,     #  FORMS LIGHT UP AND HORIZONTAL
+    0x253c: 0x0087,     #  FORMS LIGHT VERTICAL AND HORIZONTAL
+    0x2592: 0x0084,     #  MEDIUM SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+    0xfe7d: 0x00f0,     #  ARABIC SHADDA MEDIAL FORM
+    0xfe80: 0x00c1,     #  ARABIC LETTER HAMZA ISOLATED FORM
+    0xfe81: 0x00c2,     #  ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+    0xfe82: 0x00a2,     #  ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+    0xfe83: 0x00c3,     #  ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+    0xfe84: 0x00a5,     #  ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+    0xfe85: 0x00c4,     #  ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+    0xfe8b: 0x00c6,     #  ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+    0xfe8d: 0x00c7,     #  ARABIC LETTER ALEF ISOLATED FORM
+    0xfe8e: 0x00a8,     #  ARABIC LETTER ALEF FINAL FORM
+    0xfe8f: 0x00a9,     #  ARABIC LETTER BEH ISOLATED FORM
+    0xfe91: 0x00c8,     #  ARABIC LETTER BEH INITIAL FORM
+    0xfe93: 0x00c9,     #  ARABIC LETTER TEH MARBUTA ISOLATED FORM
+    0xfe95: 0x00aa,     #  ARABIC LETTER TEH ISOLATED FORM
+    0xfe97: 0x00ca,     #  ARABIC LETTER TEH INITIAL FORM
+    0xfe99: 0x00ab,     #  ARABIC LETTER THEH ISOLATED FORM
+    0xfe9b: 0x00cb,     #  ARABIC LETTER THEH INITIAL FORM
+    0xfe9d: 0x00ad,     #  ARABIC LETTER JEEM ISOLATED FORM
+    0xfe9f: 0x00cc,     #  ARABIC LETTER JEEM INITIAL FORM
+    0xfea1: 0x00ae,     #  ARABIC LETTER HAH ISOLATED FORM
+    0xfea3: 0x00cd,     #  ARABIC LETTER HAH INITIAL FORM
+    0xfea5: 0x00af,     #  ARABIC LETTER KHAH ISOLATED FORM
+    0xfea7: 0x00ce,     #  ARABIC LETTER KHAH INITIAL FORM
+    0xfea9: 0x00cf,     #  ARABIC LETTER DAL ISOLATED FORM
+    0xfeab: 0x00d0,     #  ARABIC LETTER THAL ISOLATED FORM
+    0xfead: 0x00d1,     #  ARABIC LETTER REH ISOLATED FORM
+    0xfeaf: 0x00d2,     #  ARABIC LETTER ZAIN ISOLATED FORM
+    0xfeb1: 0x00bc,     #  ARABIC LETTER SEEN ISOLATED FORM
+    0xfeb3: 0x00d3,     #  ARABIC LETTER SEEN INITIAL FORM
+    0xfeb5: 0x00bd,     #  ARABIC LETTER SHEEN ISOLATED FORM
+    0xfeb7: 0x00d4,     #  ARABIC LETTER SHEEN INITIAL FORM
+    0xfeb9: 0x00be,     #  ARABIC LETTER SAD ISOLATED FORM
+    0xfebb: 0x00d5,     #  ARABIC LETTER SAD INITIAL FORM
+    0xfebd: 0x00eb,     #  ARABIC LETTER DAD ISOLATED FORM
+    0xfebf: 0x00d6,     #  ARABIC LETTER DAD INITIAL FORM
+    0xfec1: 0x00d7,     #  ARABIC LETTER TAH ISOLATED FORM
+    0xfec5: 0x00d8,     #  ARABIC LETTER ZAH ISOLATED FORM
+    0xfec9: 0x00df,     #  ARABIC LETTER AIN ISOLATED FORM
+    0xfeca: 0x00c5,     #  ARABIC LETTER AIN FINAL FORM
+    0xfecb: 0x00d9,     #  ARABIC LETTER AIN INITIAL FORM
+    0xfecc: 0x00ec,     #  ARABIC LETTER AIN MEDIAL FORM
+    0xfecd: 0x00ee,     #  ARABIC LETTER GHAIN ISOLATED FORM
+    0xfece: 0x00ed,     #  ARABIC LETTER GHAIN FINAL FORM
+    0xfecf: 0x00da,     #  ARABIC LETTER GHAIN INITIAL FORM
+    0xfed0: 0x00f7,     #  ARABIC LETTER GHAIN MEDIAL FORM
+    0xfed1: 0x00ba,     #  ARABIC LETTER FEH ISOLATED FORM
+    0xfed3: 0x00e1,     #  ARABIC LETTER FEH INITIAL FORM
+    0xfed5: 0x00f8,     #  ARABIC LETTER QAF ISOLATED FORM
+    0xfed7: 0x00e2,     #  ARABIC LETTER QAF INITIAL FORM
+    0xfed9: 0x00fc,     #  ARABIC LETTER KAF ISOLATED FORM
+    0xfedb: 0x00e3,     #  ARABIC LETTER KAF INITIAL FORM
+    0xfedd: 0x00fb,     #  ARABIC LETTER LAM ISOLATED FORM
+    0xfedf: 0x00e4,     #  ARABIC LETTER LAM INITIAL FORM
+    0xfee1: 0x00ef,     #  ARABIC LETTER MEEM ISOLATED FORM
+    0xfee3: 0x00e5,     #  ARABIC LETTER MEEM INITIAL FORM
+    0xfee5: 0x00f2,     #  ARABIC LETTER NOON ISOLATED FORM
+    0xfee7: 0x00e6,     #  ARABIC LETTER NOON INITIAL FORM
+    0xfee9: 0x00f3,     #  ARABIC LETTER HEH ISOLATED FORM
+    0xfeeb: 0x00e7,     #  ARABIC LETTER HEH INITIAL FORM
+    0xfeec: 0x00f4,     #  ARABIC LETTER HEH MEDIAL FORM
+    0xfeed: 0x00e8,     #  ARABIC LETTER WAW ISOLATED FORM
+    0xfeef: 0x00e9,     #  ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+    0xfef0: 0x00f5,     #  ARABIC LETTER ALEF MAKSURA FINAL FORM
+    0xfef1: 0x00fd,     #  ARABIC LETTER YEH ISOLATED FORM
+    0xfef2: 0x00f6,     #  ARABIC LETTER YEH FINAL FORM
+    0xfef3: 0x00ea,     #  ARABIC LETTER YEH INITIAL FORM
+    0xfef5: 0x00f9,     #  ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+    0xfef6: 0x00fa,     #  ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+    0xfef7: 0x0099,     #  ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+    0xfef8: 0x009a,     #  ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+    0xfefb: 0x009d,     #  ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+    0xfefc: 0x009e,     #  ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp865.py b/src/main/resources/PythonLibs/encodings/cp865.py
new file mode 100644
index 0000000000000000000000000000000000000000..e9f45f1b508b8f86aa72a11caacf4c682411186b
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp865.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP865.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp865',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0081: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x0082: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x0083: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x0084: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x0085: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0086: 0x00e5,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x0087: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x0088: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0089: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x008a: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x008b: 0x00ef,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x008c: 0x00ee,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x008d: 0x00ec,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x008e: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x008f: 0x00c5,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x0090: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0091: 0x00e6,     #  LATIN SMALL LIGATURE AE
+    0x0092: 0x00c6,     #  LATIN CAPITAL LIGATURE AE
+    0x0093: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x0094: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x0095: 0x00f2,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x0096: 0x00fb,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x0097: 0x00f9,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x0098: 0x00ff,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x0099: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x009a: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x009b: 0x00f8,     #  LATIN SMALL LETTER O WITH STROKE
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x00d8,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x009e: 0x20a7,     #  PESETA SIGN
+    0x009f: 0x0192,     #  LATIN SMALL LETTER F WITH HOOK
+    0x00a0: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00a1: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00a2: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00a3: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00a4: 0x00f1,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00a5: 0x00d1,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00a6: 0x00aa,     #  FEMININE ORDINAL INDICATOR
+    0x00a7: 0x00ba,     #  MASCULINE ORDINAL INDICATOR
+    0x00a8: 0x00bf,     #  INVERTED QUESTION MARK
+    0x00a9: 0x2310,     #  REVERSED NOT SIGN
+    0x00aa: 0x00ac,     #  NOT SIGN
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x00bc,     #  VULGAR FRACTION ONE QUARTER
+    0x00ad: 0x00a1,     #  INVERTED EXCLAMATION MARK
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00a4,     #  CURRENCY SIGN
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x2561,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x00b6: 0x2562,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x00b7: 0x2556,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x00b8: 0x2555,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x255c,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x00be: 0x255b,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x255e,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x00c7: 0x255f,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x2567,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x00d0: 0x2568,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x00d1: 0x2564,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x00d2: 0x2565,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x00d3: 0x2559,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x00d4: 0x2558,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x00d5: 0x2552,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x00d6: 0x2553,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x00d7: 0x256b,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x00d8: 0x256a,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x03b1,     #  GREEK SMALL LETTER ALPHA
+    0x00e1: 0x00df,     #  LATIN SMALL LETTER SHARP S
+    0x00e2: 0x0393,     #  GREEK CAPITAL LETTER GAMMA
+    0x00e3: 0x03c0,     #  GREEK SMALL LETTER PI
+    0x00e4: 0x03a3,     #  GREEK CAPITAL LETTER SIGMA
+    0x00e5: 0x03c3,     #  GREEK SMALL LETTER SIGMA
+    0x00e6: 0x00b5,     #  MICRO SIGN
+    0x00e7: 0x03c4,     #  GREEK SMALL LETTER TAU
+    0x00e8: 0x03a6,     #  GREEK CAPITAL LETTER PHI
+    0x00e9: 0x0398,     #  GREEK CAPITAL LETTER THETA
+    0x00ea: 0x03a9,     #  GREEK CAPITAL LETTER OMEGA
+    0x00eb: 0x03b4,     #  GREEK SMALL LETTER DELTA
+    0x00ec: 0x221e,     #  INFINITY
+    0x00ed: 0x03c6,     #  GREEK SMALL LETTER PHI
+    0x00ee: 0x03b5,     #  GREEK SMALL LETTER EPSILON
+    0x00ef: 0x2229,     #  INTERSECTION
+    0x00f0: 0x2261,     #  IDENTICAL TO
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x2265,     #  GREATER-THAN OR EQUAL TO
+    0x00f3: 0x2264,     #  LESS-THAN OR EQUAL TO
+    0x00f4: 0x2320,     #  TOP HALF INTEGRAL
+    0x00f5: 0x2321,     #  BOTTOM HALF INTEGRAL
+    0x00f6: 0x00f7,     #  DIVISION SIGN
+    0x00f7: 0x2248,     #  ALMOST EQUAL TO
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x221a,     #  SQUARE ROOT
+    0x00fc: 0x207f,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x00fd: 0x00b2,     #  SUPERSCRIPT TWO
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\xc7'     #  0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xfc'     #  0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xe9'     #  0x0082 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe2'     #  0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe0'     #  0x0085 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe5'     #  0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x0087 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xea'     #  0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xe8'     #  0x008a -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xef'     #  0x008b -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xee'     #  0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xec'     #  0x008d -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xc4'     #  0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc9'     #  0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xe6'     #  0x0091 -> LATIN SMALL LIGATURE AE
+    u'\xc6'     #  0x0092 -> LATIN CAPITAL LIGATURE AE
+    u'\xf4'     #  0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf2'     #  0x0095 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xfb'     #  0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xf9'     #  0x0097 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xff'     #  0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\xd6'     #  0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xf8'     #  0x009b -> LATIN SMALL LETTER O WITH STROKE
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\xd8'     #  0x009d -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u20a7'   #  0x009e -> PESETA SIGN
+    u'\u0192'   #  0x009f -> LATIN SMALL LETTER F WITH HOOK
+    u'\xe1'     #  0x00a0 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xed'     #  0x00a1 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xf3'     #  0x00a2 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xfa'     #  0x00a3 -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf1'     #  0x00a4 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xd1'     #  0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xaa'     #  0x00a6 -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0x00a7 -> MASCULINE ORDINAL INDICATOR
+    u'\xbf'     #  0x00a8 -> INVERTED QUESTION MARK
+    u'\u2310'   #  0x00a9 -> REVERSED NOT SIGN
+    u'\xac'     #  0x00aa -> NOT SIGN
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\xbc'     #  0x00ac -> VULGAR FRACTION ONE QUARTER
+    u'\xa1'     #  0x00ad -> INVERTED EXCLAMATION MARK
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xa4'     #  0x00af -> CURRENCY SIGN
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u03b1'   #  0x00e0 -> GREEK SMALL LETTER ALPHA
+    u'\xdf'     #  0x00e1 -> LATIN SMALL LETTER SHARP S
+    u'\u0393'   #  0x00e2 -> GREEK CAPITAL LETTER GAMMA
+    u'\u03c0'   #  0x00e3 -> GREEK SMALL LETTER PI
+    u'\u03a3'   #  0x00e4 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03c3'   #  0x00e5 -> GREEK SMALL LETTER SIGMA
+    u'\xb5'     #  0x00e6 -> MICRO SIGN
+    u'\u03c4'   #  0x00e7 -> GREEK SMALL LETTER TAU
+    u'\u03a6'   #  0x00e8 -> GREEK CAPITAL LETTER PHI
+    u'\u0398'   #  0x00e9 -> GREEK CAPITAL LETTER THETA
+    u'\u03a9'   #  0x00ea -> GREEK CAPITAL LETTER OMEGA
+    u'\u03b4'   #  0x00eb -> GREEK SMALL LETTER DELTA
+    u'\u221e'   #  0x00ec -> INFINITY
+    u'\u03c6'   #  0x00ed -> GREEK SMALL LETTER PHI
+    u'\u03b5'   #  0x00ee -> GREEK SMALL LETTER EPSILON
+    u'\u2229'   #  0x00ef -> INTERSECTION
+    u'\u2261'   #  0x00f0 -> IDENTICAL TO
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u2265'   #  0x00f2 -> GREATER-THAN OR EQUAL TO
+    u'\u2264'   #  0x00f3 -> LESS-THAN OR EQUAL TO
+    u'\u2320'   #  0x00f4 -> TOP HALF INTEGRAL
+    u'\u2321'   #  0x00f5 -> BOTTOM HALF INTEGRAL
+    u'\xf7'     #  0x00f6 -> DIVISION SIGN
+    u'\u2248'   #  0x00f7 -> ALMOST EQUAL TO
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\u221a'   #  0x00fb -> SQUARE ROOT
+    u'\u207f'   #  0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N
+    u'\xb2'     #  0x00fd -> SUPERSCRIPT TWO
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a1: 0x00ad,     #  INVERTED EXCLAMATION MARK
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a4: 0x00af,     #  CURRENCY SIGN
+    0x00aa: 0x00a6,     #  FEMININE ORDINAL INDICATOR
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x00aa,     #  NOT SIGN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x00fd,     #  SUPERSCRIPT TWO
+    0x00b5: 0x00e6,     #  MICRO SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x00ba: 0x00a7,     #  MASCULINE ORDINAL INDICATOR
+    0x00bc: 0x00ac,     #  VULGAR FRACTION ONE QUARTER
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x00bf: 0x00a8,     #  INVERTED QUESTION MARK
+    0x00c4: 0x008e,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c5: 0x008f,     #  LATIN CAPITAL LETTER A WITH RING ABOVE
+    0x00c6: 0x0092,     #  LATIN CAPITAL LIGATURE AE
+    0x00c7: 0x0080,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c9: 0x0090,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00d1: 0x00a5,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00d6: 0x0099,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00d8: 0x009d,     #  LATIN CAPITAL LETTER O WITH STROKE
+    0x00dc: 0x009a,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00df: 0x00e1,     #  LATIN SMALL LETTER SHARP S
+    0x00e0: 0x0085,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e1: 0x00a0,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0083,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e4: 0x0084,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e5: 0x0086,     #  LATIN SMALL LETTER A WITH RING ABOVE
+    0x00e6: 0x0091,     #  LATIN SMALL LIGATURE AE
+    0x00e7: 0x0087,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008a,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x0082,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0088,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00eb: 0x0089,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ec: 0x008d,     #  LATIN SMALL LETTER I WITH GRAVE
+    0x00ed: 0x00a1,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00ee: 0x008c,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x00ef: 0x008b,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x00f1: 0x00a4,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00f2: 0x0095,     #  LATIN SMALL LETTER O WITH GRAVE
+    0x00f3: 0x00a2,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0093,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f6: 0x0094,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x00f6,     #  DIVISION SIGN
+    0x00f8: 0x009b,     #  LATIN SMALL LETTER O WITH STROKE
+    0x00f9: 0x0097,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x00fa: 0x00a3,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fb: 0x0096,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x00fc: 0x0081,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x00ff: 0x0098,     #  LATIN SMALL LETTER Y WITH DIAERESIS
+    0x0192: 0x009f,     #  LATIN SMALL LETTER F WITH HOOK
+    0x0393: 0x00e2,     #  GREEK CAPITAL LETTER GAMMA
+    0x0398: 0x00e9,     #  GREEK CAPITAL LETTER THETA
+    0x03a3: 0x00e4,     #  GREEK CAPITAL LETTER SIGMA
+    0x03a6: 0x00e8,     #  GREEK CAPITAL LETTER PHI
+    0x03a9: 0x00ea,     #  GREEK CAPITAL LETTER OMEGA
+    0x03b1: 0x00e0,     #  GREEK SMALL LETTER ALPHA
+    0x03b4: 0x00eb,     #  GREEK SMALL LETTER DELTA
+    0x03b5: 0x00ee,     #  GREEK SMALL LETTER EPSILON
+    0x03c0: 0x00e3,     #  GREEK SMALL LETTER PI
+    0x03c3: 0x00e5,     #  GREEK SMALL LETTER SIGMA
+    0x03c4: 0x00e7,     #  GREEK SMALL LETTER TAU
+    0x03c6: 0x00ed,     #  GREEK SMALL LETTER PHI
+    0x207f: 0x00fc,     #  SUPERSCRIPT LATIN SMALL LETTER N
+    0x20a7: 0x009e,     #  PESETA SIGN
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x221a: 0x00fb,     #  SQUARE ROOT
+    0x221e: 0x00ec,     #  INFINITY
+    0x2229: 0x00ef,     #  INTERSECTION
+    0x2248: 0x00f7,     #  ALMOST EQUAL TO
+    0x2261: 0x00f0,     #  IDENTICAL TO
+    0x2264: 0x00f3,     #  LESS-THAN OR EQUAL TO
+    0x2265: 0x00f2,     #  GREATER-THAN OR EQUAL TO
+    0x2310: 0x00a9,     #  REVERSED NOT SIGN
+    0x2320: 0x00f4,     #  TOP HALF INTEGRAL
+    0x2321: 0x00f5,     #  BOTTOM HALF INTEGRAL
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2552: 0x00d5,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x2553: 0x00d6,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2555: 0x00b8,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x2556: 0x00b7,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x2558: 0x00d4,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x2559: 0x00d3,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255b: 0x00be,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x255c: 0x00bd,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x255e: 0x00c6,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x255f: 0x00c7,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2561: 0x00b5,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x2562: 0x00b6,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2564: 0x00d1,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x2565: 0x00d2,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2567: 0x00cf,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x2568: 0x00d0,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256a: 0x00d8,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x256b: 0x00d7,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp866.py b/src/main/resources/PythonLibs/encodings/cp866.py
new file mode 100644
index 0000000000000000000000000000000000000000..29cd85a3f10b05eac36ef93749ba593a485f816e
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp866.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP866.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp866',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x0410,     #  CYRILLIC CAPITAL LETTER A
+    0x0081: 0x0411,     #  CYRILLIC CAPITAL LETTER BE
+    0x0082: 0x0412,     #  CYRILLIC CAPITAL LETTER VE
+    0x0083: 0x0413,     #  CYRILLIC CAPITAL LETTER GHE
+    0x0084: 0x0414,     #  CYRILLIC CAPITAL LETTER DE
+    0x0085: 0x0415,     #  CYRILLIC CAPITAL LETTER IE
+    0x0086: 0x0416,     #  CYRILLIC CAPITAL LETTER ZHE
+    0x0087: 0x0417,     #  CYRILLIC CAPITAL LETTER ZE
+    0x0088: 0x0418,     #  CYRILLIC CAPITAL LETTER I
+    0x0089: 0x0419,     #  CYRILLIC CAPITAL LETTER SHORT I
+    0x008a: 0x041a,     #  CYRILLIC CAPITAL LETTER KA
+    0x008b: 0x041b,     #  CYRILLIC CAPITAL LETTER EL
+    0x008c: 0x041c,     #  CYRILLIC CAPITAL LETTER EM
+    0x008d: 0x041d,     #  CYRILLIC CAPITAL LETTER EN
+    0x008e: 0x041e,     #  CYRILLIC CAPITAL LETTER O
+    0x008f: 0x041f,     #  CYRILLIC CAPITAL LETTER PE
+    0x0090: 0x0420,     #  CYRILLIC CAPITAL LETTER ER
+    0x0091: 0x0421,     #  CYRILLIC CAPITAL LETTER ES
+    0x0092: 0x0422,     #  CYRILLIC CAPITAL LETTER TE
+    0x0093: 0x0423,     #  CYRILLIC CAPITAL LETTER U
+    0x0094: 0x0424,     #  CYRILLIC CAPITAL LETTER EF
+    0x0095: 0x0425,     #  CYRILLIC CAPITAL LETTER HA
+    0x0096: 0x0426,     #  CYRILLIC CAPITAL LETTER TSE
+    0x0097: 0x0427,     #  CYRILLIC CAPITAL LETTER CHE
+    0x0098: 0x0428,     #  CYRILLIC CAPITAL LETTER SHA
+    0x0099: 0x0429,     #  CYRILLIC CAPITAL LETTER SHCHA
+    0x009a: 0x042a,     #  CYRILLIC CAPITAL LETTER HARD SIGN
+    0x009b: 0x042b,     #  CYRILLIC CAPITAL LETTER YERU
+    0x009c: 0x042c,     #  CYRILLIC CAPITAL LETTER SOFT SIGN
+    0x009d: 0x042d,     #  CYRILLIC CAPITAL LETTER E
+    0x009e: 0x042e,     #  CYRILLIC CAPITAL LETTER YU
+    0x009f: 0x042f,     #  CYRILLIC CAPITAL LETTER YA
+    0x00a0: 0x0430,     #  CYRILLIC SMALL LETTER A
+    0x00a1: 0x0431,     #  CYRILLIC SMALL LETTER BE
+    0x00a2: 0x0432,     #  CYRILLIC SMALL LETTER VE
+    0x00a3: 0x0433,     #  CYRILLIC SMALL LETTER GHE
+    0x00a4: 0x0434,     #  CYRILLIC SMALL LETTER DE
+    0x00a5: 0x0435,     #  CYRILLIC SMALL LETTER IE
+    0x00a6: 0x0436,     #  CYRILLIC SMALL LETTER ZHE
+    0x00a7: 0x0437,     #  CYRILLIC SMALL LETTER ZE
+    0x00a8: 0x0438,     #  CYRILLIC SMALL LETTER I
+    0x00a9: 0x0439,     #  CYRILLIC SMALL LETTER SHORT I
+    0x00aa: 0x043a,     #  CYRILLIC SMALL LETTER KA
+    0x00ab: 0x043b,     #  CYRILLIC SMALL LETTER EL
+    0x00ac: 0x043c,     #  CYRILLIC SMALL LETTER EM
+    0x00ad: 0x043d,     #  CYRILLIC SMALL LETTER EN
+    0x00ae: 0x043e,     #  CYRILLIC SMALL LETTER O
+    0x00af: 0x043f,     #  CYRILLIC SMALL LETTER PE
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x2561,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x00b6: 0x2562,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x00b7: 0x2556,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x00b8: 0x2555,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x255c,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x00be: 0x255b,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x255e,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x00c7: 0x255f,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x2567,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x00d0: 0x2568,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x00d1: 0x2564,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x00d2: 0x2565,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x00d3: 0x2559,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x00d4: 0x2558,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x00d5: 0x2552,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x00d6: 0x2553,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x00d7: 0x256b,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x00d8: 0x256a,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x258c,     #  LEFT HALF BLOCK
+    0x00de: 0x2590,     #  RIGHT HALF BLOCK
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x0440,     #  CYRILLIC SMALL LETTER ER
+    0x00e1: 0x0441,     #  CYRILLIC SMALL LETTER ES
+    0x00e2: 0x0442,     #  CYRILLIC SMALL LETTER TE
+    0x00e3: 0x0443,     #  CYRILLIC SMALL LETTER U
+    0x00e4: 0x0444,     #  CYRILLIC SMALL LETTER EF
+    0x00e5: 0x0445,     #  CYRILLIC SMALL LETTER HA
+    0x00e6: 0x0446,     #  CYRILLIC SMALL LETTER TSE
+    0x00e7: 0x0447,     #  CYRILLIC SMALL LETTER CHE
+    0x00e8: 0x0448,     #  CYRILLIC SMALL LETTER SHA
+    0x00e9: 0x0449,     #  CYRILLIC SMALL LETTER SHCHA
+    0x00ea: 0x044a,     #  CYRILLIC SMALL LETTER HARD SIGN
+    0x00eb: 0x044b,     #  CYRILLIC SMALL LETTER YERU
+    0x00ec: 0x044c,     #  CYRILLIC SMALL LETTER SOFT SIGN
+    0x00ed: 0x044d,     #  CYRILLIC SMALL LETTER E
+    0x00ee: 0x044e,     #  CYRILLIC SMALL LETTER YU
+    0x00ef: 0x044f,     #  CYRILLIC SMALL LETTER YA
+    0x00f0: 0x0401,     #  CYRILLIC CAPITAL LETTER IO
+    0x00f1: 0x0451,     #  CYRILLIC SMALL LETTER IO
+    0x00f2: 0x0404,     #  CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    0x00f3: 0x0454,     #  CYRILLIC SMALL LETTER UKRAINIAN IE
+    0x00f4: 0x0407,     #  CYRILLIC CAPITAL LETTER YI
+    0x00f5: 0x0457,     #  CYRILLIC SMALL LETTER YI
+    0x00f6: 0x040e,     #  CYRILLIC CAPITAL LETTER SHORT U
+    0x00f7: 0x045e,     #  CYRILLIC SMALL LETTER SHORT U
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x2219,     #  BULLET OPERATOR
+    0x00fa: 0x00b7,     #  MIDDLE DOT
+    0x00fb: 0x221a,     #  SQUARE ROOT
+    0x00fc: 0x2116,     #  NUMERO SIGN
+    0x00fd: 0x00a4,     #  CURRENCY SIGN
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\u0410'   #  0x0080 -> CYRILLIC CAPITAL LETTER A
+    u'\u0411'   #  0x0081 -> CYRILLIC CAPITAL LETTER BE
+    u'\u0412'   #  0x0082 -> CYRILLIC CAPITAL LETTER VE
+    u'\u0413'   #  0x0083 -> CYRILLIC CAPITAL LETTER GHE
+    u'\u0414'   #  0x0084 -> CYRILLIC CAPITAL LETTER DE
+    u'\u0415'   #  0x0085 -> CYRILLIC CAPITAL LETTER IE
+    u'\u0416'   #  0x0086 -> CYRILLIC CAPITAL LETTER ZHE
+    u'\u0417'   #  0x0087 -> CYRILLIC CAPITAL LETTER ZE
+    u'\u0418'   #  0x0088 -> CYRILLIC CAPITAL LETTER I
+    u'\u0419'   #  0x0089 -> CYRILLIC CAPITAL LETTER SHORT I
+    u'\u041a'   #  0x008a -> CYRILLIC CAPITAL LETTER KA
+    u'\u041b'   #  0x008b -> CYRILLIC CAPITAL LETTER EL
+    u'\u041c'   #  0x008c -> CYRILLIC CAPITAL LETTER EM
+    u'\u041d'   #  0x008d -> CYRILLIC CAPITAL LETTER EN
+    u'\u041e'   #  0x008e -> CYRILLIC CAPITAL LETTER O
+    u'\u041f'   #  0x008f -> CYRILLIC CAPITAL LETTER PE
+    u'\u0420'   #  0x0090 -> CYRILLIC CAPITAL LETTER ER
+    u'\u0421'   #  0x0091 -> CYRILLIC CAPITAL LETTER ES
+    u'\u0422'   #  0x0092 -> CYRILLIC CAPITAL LETTER TE
+    u'\u0423'   #  0x0093 -> CYRILLIC CAPITAL LETTER U
+    u'\u0424'   #  0x0094 -> CYRILLIC CAPITAL LETTER EF
+    u'\u0425'   #  0x0095 -> CYRILLIC CAPITAL LETTER HA
+    u'\u0426'   #  0x0096 -> CYRILLIC CAPITAL LETTER TSE
+    u'\u0427'   #  0x0097 -> CYRILLIC CAPITAL LETTER CHE
+    u'\u0428'   #  0x0098 -> CYRILLIC CAPITAL LETTER SHA
+    u'\u0429'   #  0x0099 -> CYRILLIC CAPITAL LETTER SHCHA
+    u'\u042a'   #  0x009a -> CYRILLIC CAPITAL LETTER HARD SIGN
+    u'\u042b'   #  0x009b -> CYRILLIC CAPITAL LETTER YERU
+    u'\u042c'   #  0x009c -> CYRILLIC CAPITAL LETTER SOFT SIGN
+    u'\u042d'   #  0x009d -> CYRILLIC CAPITAL LETTER E
+    u'\u042e'   #  0x009e -> CYRILLIC CAPITAL LETTER YU
+    u'\u042f'   #  0x009f -> CYRILLIC CAPITAL LETTER YA
+    u'\u0430'   #  0x00a0 -> CYRILLIC SMALL LETTER A
+    u'\u0431'   #  0x00a1 -> CYRILLIC SMALL LETTER BE
+    u'\u0432'   #  0x00a2 -> CYRILLIC SMALL LETTER VE
+    u'\u0433'   #  0x00a3 -> CYRILLIC SMALL LETTER GHE
+    u'\u0434'   #  0x00a4 -> CYRILLIC SMALL LETTER DE
+    u'\u0435'   #  0x00a5 -> CYRILLIC SMALL LETTER IE
+    u'\u0436'   #  0x00a6 -> CYRILLIC SMALL LETTER ZHE
+    u'\u0437'   #  0x00a7 -> CYRILLIC SMALL LETTER ZE
+    u'\u0438'   #  0x00a8 -> CYRILLIC SMALL LETTER I
+    u'\u0439'   #  0x00a9 -> CYRILLIC SMALL LETTER SHORT I
+    u'\u043a'   #  0x00aa -> CYRILLIC SMALL LETTER KA
+    u'\u043b'   #  0x00ab -> CYRILLIC SMALL LETTER EL
+    u'\u043c'   #  0x00ac -> CYRILLIC SMALL LETTER EM
+    u'\u043d'   #  0x00ad -> CYRILLIC SMALL LETTER EN
+    u'\u043e'   #  0x00ae -> CYRILLIC SMALL LETTER O
+    u'\u043f'   #  0x00af -> CYRILLIC SMALL LETTER PE
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u2561'   #  0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u2562'   #  0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2556'   #  0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2555'   #  0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255c'   #  0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255b'   #  0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u255e'   #  0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u2567'   #  0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2564'   #  0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2559'   #  0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u2558'   #  0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2552'   #  0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u2553'   #  0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u256b'   #  0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256a'   #  0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u258c'   #  0x00dd -> LEFT HALF BLOCK
+    u'\u2590'   #  0x00de -> RIGHT HALF BLOCK
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u0440'   #  0x00e0 -> CYRILLIC SMALL LETTER ER
+    u'\u0441'   #  0x00e1 -> CYRILLIC SMALL LETTER ES
+    u'\u0442'   #  0x00e2 -> CYRILLIC SMALL LETTER TE
+    u'\u0443'   #  0x00e3 -> CYRILLIC SMALL LETTER U
+    u'\u0444'   #  0x00e4 -> CYRILLIC SMALL LETTER EF
+    u'\u0445'   #  0x00e5 -> CYRILLIC SMALL LETTER HA
+    u'\u0446'   #  0x00e6 -> CYRILLIC SMALL LETTER TSE
+    u'\u0447'   #  0x00e7 -> CYRILLIC SMALL LETTER CHE
+    u'\u0448'   #  0x00e8 -> CYRILLIC SMALL LETTER SHA
+    u'\u0449'   #  0x00e9 -> CYRILLIC SMALL LETTER SHCHA
+    u'\u044a'   #  0x00ea -> CYRILLIC SMALL LETTER HARD SIGN
+    u'\u044b'   #  0x00eb -> CYRILLIC SMALL LETTER YERU
+    u'\u044c'   #  0x00ec -> CYRILLIC SMALL LETTER SOFT SIGN
+    u'\u044d'   #  0x00ed -> CYRILLIC SMALL LETTER E
+    u'\u044e'   #  0x00ee -> CYRILLIC SMALL LETTER YU
+    u'\u044f'   #  0x00ef -> CYRILLIC SMALL LETTER YA
+    u'\u0401'   #  0x00f0 -> CYRILLIC CAPITAL LETTER IO
+    u'\u0451'   #  0x00f1 -> CYRILLIC SMALL LETTER IO
+    u'\u0404'   #  0x00f2 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    u'\u0454'   #  0x00f3 -> CYRILLIC SMALL LETTER UKRAINIAN IE
+    u'\u0407'   #  0x00f4 -> CYRILLIC CAPITAL LETTER YI
+    u'\u0457'   #  0x00f5 -> CYRILLIC SMALL LETTER YI
+    u'\u040e'   #  0x00f6 -> CYRILLIC CAPITAL LETTER SHORT U
+    u'\u045e'   #  0x00f7 -> CYRILLIC SMALL LETTER SHORT U
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\u2219'   #  0x00f9 -> BULLET OPERATOR
+    u'\xb7'     #  0x00fa -> MIDDLE DOT
+    u'\u221a'   #  0x00fb -> SQUARE ROOT
+    u'\u2116'   #  0x00fc -> NUMERO SIGN
+    u'\xa4'     #  0x00fd -> CURRENCY SIGN
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a4: 0x00fd,     #  CURRENCY SIGN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b7: 0x00fa,     #  MIDDLE DOT
+    0x0401: 0x00f0,     #  CYRILLIC CAPITAL LETTER IO
+    0x0404: 0x00f2,     #  CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    0x0407: 0x00f4,     #  CYRILLIC CAPITAL LETTER YI
+    0x040e: 0x00f6,     #  CYRILLIC CAPITAL LETTER SHORT U
+    0x0410: 0x0080,     #  CYRILLIC CAPITAL LETTER A
+    0x0411: 0x0081,     #  CYRILLIC CAPITAL LETTER BE
+    0x0412: 0x0082,     #  CYRILLIC CAPITAL LETTER VE
+    0x0413: 0x0083,     #  CYRILLIC CAPITAL LETTER GHE
+    0x0414: 0x0084,     #  CYRILLIC CAPITAL LETTER DE
+    0x0415: 0x0085,     #  CYRILLIC CAPITAL LETTER IE
+    0x0416: 0x0086,     #  CYRILLIC CAPITAL LETTER ZHE
+    0x0417: 0x0087,     #  CYRILLIC CAPITAL LETTER ZE
+    0x0418: 0x0088,     #  CYRILLIC CAPITAL LETTER I
+    0x0419: 0x0089,     #  CYRILLIC CAPITAL LETTER SHORT I
+    0x041a: 0x008a,     #  CYRILLIC CAPITAL LETTER KA
+    0x041b: 0x008b,     #  CYRILLIC CAPITAL LETTER EL
+    0x041c: 0x008c,     #  CYRILLIC CAPITAL LETTER EM
+    0x041d: 0x008d,     #  CYRILLIC CAPITAL LETTER EN
+    0x041e: 0x008e,     #  CYRILLIC CAPITAL LETTER O
+    0x041f: 0x008f,     #  CYRILLIC CAPITAL LETTER PE
+    0x0420: 0x0090,     #  CYRILLIC CAPITAL LETTER ER
+    0x0421: 0x0091,     #  CYRILLIC CAPITAL LETTER ES
+    0x0422: 0x0092,     #  CYRILLIC CAPITAL LETTER TE
+    0x0423: 0x0093,     #  CYRILLIC CAPITAL LETTER U
+    0x0424: 0x0094,     #  CYRILLIC CAPITAL LETTER EF
+    0x0425: 0x0095,     #  CYRILLIC CAPITAL LETTER HA
+    0x0426: 0x0096,     #  CYRILLIC CAPITAL LETTER TSE
+    0x0427: 0x0097,     #  CYRILLIC CAPITAL LETTER CHE
+    0x0428: 0x0098,     #  CYRILLIC CAPITAL LETTER SHA
+    0x0429: 0x0099,     #  CYRILLIC CAPITAL LETTER SHCHA
+    0x042a: 0x009a,     #  CYRILLIC CAPITAL LETTER HARD SIGN
+    0x042b: 0x009b,     #  CYRILLIC CAPITAL LETTER YERU
+    0x042c: 0x009c,     #  CYRILLIC CAPITAL LETTER SOFT SIGN
+    0x042d: 0x009d,     #  CYRILLIC CAPITAL LETTER E
+    0x042e: 0x009e,     #  CYRILLIC CAPITAL LETTER YU
+    0x042f: 0x009f,     #  CYRILLIC CAPITAL LETTER YA
+    0x0430: 0x00a0,     #  CYRILLIC SMALL LETTER A
+    0x0431: 0x00a1,     #  CYRILLIC SMALL LETTER BE
+    0x0432: 0x00a2,     #  CYRILLIC SMALL LETTER VE
+    0x0433: 0x00a3,     #  CYRILLIC SMALL LETTER GHE
+    0x0434: 0x00a4,     #  CYRILLIC SMALL LETTER DE
+    0x0435: 0x00a5,     #  CYRILLIC SMALL LETTER IE
+    0x0436: 0x00a6,     #  CYRILLIC SMALL LETTER ZHE
+    0x0437: 0x00a7,     #  CYRILLIC SMALL LETTER ZE
+    0x0438: 0x00a8,     #  CYRILLIC SMALL LETTER I
+    0x0439: 0x00a9,     #  CYRILLIC SMALL LETTER SHORT I
+    0x043a: 0x00aa,     #  CYRILLIC SMALL LETTER KA
+    0x043b: 0x00ab,     #  CYRILLIC SMALL LETTER EL
+    0x043c: 0x00ac,     #  CYRILLIC SMALL LETTER EM
+    0x043d: 0x00ad,     #  CYRILLIC SMALL LETTER EN
+    0x043e: 0x00ae,     #  CYRILLIC SMALL LETTER O
+    0x043f: 0x00af,     #  CYRILLIC SMALL LETTER PE
+    0x0440: 0x00e0,     #  CYRILLIC SMALL LETTER ER
+    0x0441: 0x00e1,     #  CYRILLIC SMALL LETTER ES
+    0x0442: 0x00e2,     #  CYRILLIC SMALL LETTER TE
+    0x0443: 0x00e3,     #  CYRILLIC SMALL LETTER U
+    0x0444: 0x00e4,     #  CYRILLIC SMALL LETTER EF
+    0x0445: 0x00e5,     #  CYRILLIC SMALL LETTER HA
+    0x0446: 0x00e6,     #  CYRILLIC SMALL LETTER TSE
+    0x0447: 0x00e7,     #  CYRILLIC SMALL LETTER CHE
+    0x0448: 0x00e8,     #  CYRILLIC SMALL LETTER SHA
+    0x0449: 0x00e9,     #  CYRILLIC SMALL LETTER SHCHA
+    0x044a: 0x00ea,     #  CYRILLIC SMALL LETTER HARD SIGN
+    0x044b: 0x00eb,     #  CYRILLIC SMALL LETTER YERU
+    0x044c: 0x00ec,     #  CYRILLIC SMALL LETTER SOFT SIGN
+    0x044d: 0x00ed,     #  CYRILLIC SMALL LETTER E
+    0x044e: 0x00ee,     #  CYRILLIC SMALL LETTER YU
+    0x044f: 0x00ef,     #  CYRILLIC SMALL LETTER YA
+    0x0451: 0x00f1,     #  CYRILLIC SMALL LETTER IO
+    0x0454: 0x00f3,     #  CYRILLIC SMALL LETTER UKRAINIAN IE
+    0x0457: 0x00f5,     #  CYRILLIC SMALL LETTER YI
+    0x045e: 0x00f7,     #  CYRILLIC SMALL LETTER SHORT U
+    0x2116: 0x00fc,     #  NUMERO SIGN
+    0x2219: 0x00f9,     #  BULLET OPERATOR
+    0x221a: 0x00fb,     #  SQUARE ROOT
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2552: 0x00d5,     #  BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    0x2553: 0x00d6,     #  BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2555: 0x00b8,     #  BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    0x2556: 0x00b7,     #  BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x2558: 0x00d4,     #  BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    0x2559: 0x00d3,     #  BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255b: 0x00be,     #  BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    0x255c: 0x00bd,     #  BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x255e: 0x00c6,     #  BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    0x255f: 0x00c7,     #  BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2561: 0x00b5,     #  BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    0x2562: 0x00b6,     #  BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2564: 0x00d1,     #  BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    0x2565: 0x00d2,     #  BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2567: 0x00cf,     #  BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    0x2568: 0x00d0,     #  BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256a: 0x00d8,     #  BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    0x256b: 0x00d7,     #  BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x258c: 0x00dd,     #  LEFT HALF BLOCK
+    0x2590: 0x00de,     #  RIGHT HALF BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp869.py b/src/main/resources/PythonLibs/encodings/cp869.py
new file mode 100644
index 0000000000000000000000000000000000000000..b4dc99bf2540b7767f70bc70ed8e67998c2c0fa7
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp869.py
@@ -0,0 +1,689 @@
+""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP869.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp869',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: None,       #  UNDEFINED
+    0x0081: None,       #  UNDEFINED
+    0x0082: None,       #  UNDEFINED
+    0x0083: None,       #  UNDEFINED
+    0x0084: None,       #  UNDEFINED
+    0x0085: None,       #  UNDEFINED
+    0x0086: 0x0386,     #  GREEK CAPITAL LETTER ALPHA WITH TONOS
+    0x0087: None,       #  UNDEFINED
+    0x0088: 0x00b7,     #  MIDDLE DOT
+    0x0089: 0x00ac,     #  NOT SIGN
+    0x008a: 0x00a6,     #  BROKEN BAR
+    0x008b: 0x2018,     #  LEFT SINGLE QUOTATION MARK
+    0x008c: 0x2019,     #  RIGHT SINGLE QUOTATION MARK
+    0x008d: 0x0388,     #  GREEK CAPITAL LETTER EPSILON WITH TONOS
+    0x008e: 0x2015,     #  HORIZONTAL BAR
+    0x008f: 0x0389,     #  GREEK CAPITAL LETTER ETA WITH TONOS
+    0x0090: 0x038a,     #  GREEK CAPITAL LETTER IOTA WITH TONOS
+    0x0091: 0x03aa,     #  GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    0x0092: 0x038c,     #  GREEK CAPITAL LETTER OMICRON WITH TONOS
+    0x0093: None,       #  UNDEFINED
+    0x0094: None,       #  UNDEFINED
+    0x0095: 0x038e,     #  GREEK CAPITAL LETTER UPSILON WITH TONOS
+    0x0096: 0x03ab,     #  GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    0x0097: 0x00a9,     #  COPYRIGHT SIGN
+    0x0098: 0x038f,     #  GREEK CAPITAL LETTER OMEGA WITH TONOS
+    0x0099: 0x00b2,     #  SUPERSCRIPT TWO
+    0x009a: 0x00b3,     #  SUPERSCRIPT THREE
+    0x009b: 0x03ac,     #  GREEK SMALL LETTER ALPHA WITH TONOS
+    0x009c: 0x00a3,     #  POUND SIGN
+    0x009d: 0x03ad,     #  GREEK SMALL LETTER EPSILON WITH TONOS
+    0x009e: 0x03ae,     #  GREEK SMALL LETTER ETA WITH TONOS
+    0x009f: 0x03af,     #  GREEK SMALL LETTER IOTA WITH TONOS
+    0x00a0: 0x03ca,     #  GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    0x00a1: 0x0390,     #  GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+    0x00a2: 0x03cc,     #  GREEK SMALL LETTER OMICRON WITH TONOS
+    0x00a3: 0x03cd,     #  GREEK SMALL LETTER UPSILON WITH TONOS
+    0x00a4: 0x0391,     #  GREEK CAPITAL LETTER ALPHA
+    0x00a5: 0x0392,     #  GREEK CAPITAL LETTER BETA
+    0x00a6: 0x0393,     #  GREEK CAPITAL LETTER GAMMA
+    0x00a7: 0x0394,     #  GREEK CAPITAL LETTER DELTA
+    0x00a8: 0x0395,     #  GREEK CAPITAL LETTER EPSILON
+    0x00a9: 0x0396,     #  GREEK CAPITAL LETTER ZETA
+    0x00aa: 0x0397,     #  GREEK CAPITAL LETTER ETA
+    0x00ab: 0x00bd,     #  VULGAR FRACTION ONE HALF
+    0x00ac: 0x0398,     #  GREEK CAPITAL LETTER THETA
+    0x00ad: 0x0399,     #  GREEK CAPITAL LETTER IOTA
+    0x00ae: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00af: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00b0: 0x2591,     #  LIGHT SHADE
+    0x00b1: 0x2592,     #  MEDIUM SHADE
+    0x00b2: 0x2593,     #  DARK SHADE
+    0x00b3: 0x2502,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x00b4: 0x2524,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x00b5: 0x039a,     #  GREEK CAPITAL LETTER KAPPA
+    0x00b6: 0x039b,     #  GREEK CAPITAL LETTER LAMDA
+    0x00b7: 0x039c,     #  GREEK CAPITAL LETTER MU
+    0x00b8: 0x039d,     #  GREEK CAPITAL LETTER NU
+    0x00b9: 0x2563,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x00ba: 0x2551,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x00bb: 0x2557,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x00bc: 0x255d,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x00bd: 0x039e,     #  GREEK CAPITAL LETTER XI
+    0x00be: 0x039f,     #  GREEK CAPITAL LETTER OMICRON
+    0x00bf: 0x2510,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x00c0: 0x2514,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x00c1: 0x2534,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x00c2: 0x252c,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x00c3: 0x251c,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x00c4: 0x2500,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x00c5: 0x253c,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x00c6: 0x03a0,     #  GREEK CAPITAL LETTER PI
+    0x00c7: 0x03a1,     #  GREEK CAPITAL LETTER RHO
+    0x00c8: 0x255a,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x00c9: 0x2554,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x00ca: 0x2569,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x00cb: 0x2566,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x00cc: 0x2560,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x00cd: 0x2550,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x00ce: 0x256c,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x00cf: 0x03a3,     #  GREEK CAPITAL LETTER SIGMA
+    0x00d0: 0x03a4,     #  GREEK CAPITAL LETTER TAU
+    0x00d1: 0x03a5,     #  GREEK CAPITAL LETTER UPSILON
+    0x00d2: 0x03a6,     #  GREEK CAPITAL LETTER PHI
+    0x00d3: 0x03a7,     #  GREEK CAPITAL LETTER CHI
+    0x00d4: 0x03a8,     #  GREEK CAPITAL LETTER PSI
+    0x00d5: 0x03a9,     #  GREEK CAPITAL LETTER OMEGA
+    0x00d6: 0x03b1,     #  GREEK SMALL LETTER ALPHA
+    0x00d7: 0x03b2,     #  GREEK SMALL LETTER BETA
+    0x00d8: 0x03b3,     #  GREEK SMALL LETTER GAMMA
+    0x00d9: 0x2518,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x00da: 0x250c,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x00db: 0x2588,     #  FULL BLOCK
+    0x00dc: 0x2584,     #  LOWER HALF BLOCK
+    0x00dd: 0x03b4,     #  GREEK SMALL LETTER DELTA
+    0x00de: 0x03b5,     #  GREEK SMALL LETTER EPSILON
+    0x00df: 0x2580,     #  UPPER HALF BLOCK
+    0x00e0: 0x03b6,     #  GREEK SMALL LETTER ZETA
+    0x00e1: 0x03b7,     #  GREEK SMALL LETTER ETA
+    0x00e2: 0x03b8,     #  GREEK SMALL LETTER THETA
+    0x00e3: 0x03b9,     #  GREEK SMALL LETTER IOTA
+    0x00e4: 0x03ba,     #  GREEK SMALL LETTER KAPPA
+    0x00e5: 0x03bb,     #  GREEK SMALL LETTER LAMDA
+    0x00e6: 0x03bc,     #  GREEK SMALL LETTER MU
+    0x00e7: 0x03bd,     #  GREEK SMALL LETTER NU
+    0x00e8: 0x03be,     #  GREEK SMALL LETTER XI
+    0x00e9: 0x03bf,     #  GREEK SMALL LETTER OMICRON
+    0x00ea: 0x03c0,     #  GREEK SMALL LETTER PI
+    0x00eb: 0x03c1,     #  GREEK SMALL LETTER RHO
+    0x00ec: 0x03c3,     #  GREEK SMALL LETTER SIGMA
+    0x00ed: 0x03c2,     #  GREEK SMALL LETTER FINAL SIGMA
+    0x00ee: 0x03c4,     #  GREEK SMALL LETTER TAU
+    0x00ef: 0x0384,     #  GREEK TONOS
+    0x00f0: 0x00ad,     #  SOFT HYPHEN
+    0x00f1: 0x00b1,     #  PLUS-MINUS SIGN
+    0x00f2: 0x03c5,     #  GREEK SMALL LETTER UPSILON
+    0x00f3: 0x03c6,     #  GREEK SMALL LETTER PHI
+    0x00f4: 0x03c7,     #  GREEK SMALL LETTER CHI
+    0x00f5: 0x00a7,     #  SECTION SIGN
+    0x00f6: 0x03c8,     #  GREEK SMALL LETTER PSI
+    0x00f7: 0x0385,     #  GREEK DIALYTIKA TONOS
+    0x00f8: 0x00b0,     #  DEGREE SIGN
+    0x00f9: 0x00a8,     #  DIAERESIS
+    0x00fa: 0x03c9,     #  GREEK SMALL LETTER OMEGA
+    0x00fb: 0x03cb,     #  GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    0x00fc: 0x03b0,     #  GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+    0x00fd: 0x03ce,     #  GREEK SMALL LETTER OMEGA WITH TONOS
+    0x00fe: 0x25a0,     #  BLACK SQUARE
+    0x00ff: 0x00a0,     #  NO-BREAK SPACE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> NULL
+    u'\x01'     #  0x0001 -> START OF HEADING
+    u'\x02'     #  0x0002 -> START OF TEXT
+    u'\x03'     #  0x0003 -> END OF TEXT
+    u'\x04'     #  0x0004 -> END OF TRANSMISSION
+    u'\x05'     #  0x0005 -> ENQUIRY
+    u'\x06'     #  0x0006 -> ACKNOWLEDGE
+    u'\x07'     #  0x0007 -> BELL
+    u'\x08'     #  0x0008 -> BACKSPACE
+    u'\t'       #  0x0009 -> HORIZONTAL TABULATION
+    u'\n'       #  0x000a -> LINE FEED
+    u'\x0b'     #  0x000b -> VERTICAL TABULATION
+    u'\x0c'     #  0x000c -> FORM FEED
+    u'\r'       #  0x000d -> CARRIAGE RETURN
+    u'\x0e'     #  0x000e -> SHIFT OUT
+    u'\x0f'     #  0x000f -> SHIFT IN
+    u'\x10'     #  0x0010 -> DATA LINK ESCAPE
+    u'\x11'     #  0x0011 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x0012 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x0013 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x0014 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x0015 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x0016 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x0017 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x0018 -> CANCEL
+    u'\x19'     #  0x0019 -> END OF MEDIUM
+    u'\x1a'     #  0x001a -> SUBSTITUTE
+    u'\x1b'     #  0x001b -> ESCAPE
+    u'\x1c'     #  0x001c -> FILE SEPARATOR
+    u'\x1d'     #  0x001d -> GROUP SEPARATOR
+    u'\x1e'     #  0x001e -> RECORD SEPARATOR
+    u'\x1f'     #  0x001f -> UNIT SEPARATOR
+    u' '        #  0x0020 -> SPACE
+    u'!'        #  0x0021 -> EXCLAMATION MARK
+    u'"'        #  0x0022 -> QUOTATION MARK
+    u'#'        #  0x0023 -> NUMBER SIGN
+    u'$'        #  0x0024 -> DOLLAR SIGN
+    u'%'        #  0x0025 -> PERCENT SIGN
+    u'&'        #  0x0026 -> AMPERSAND
+    u"'"        #  0x0027 -> APOSTROPHE
+    u'('        #  0x0028 -> LEFT PARENTHESIS
+    u')'        #  0x0029 -> RIGHT PARENTHESIS
+    u'*'        #  0x002a -> ASTERISK
+    u'+'        #  0x002b -> PLUS SIGN
+    u','        #  0x002c -> COMMA
+    u'-'        #  0x002d -> HYPHEN-MINUS
+    u'.'        #  0x002e -> FULL STOP
+    u'/'        #  0x002f -> SOLIDUS
+    u'0'        #  0x0030 -> DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE
+    u':'        #  0x003a -> COLON
+    u';'        #  0x003b -> SEMICOLON
+    u'<'        #  0x003c -> LESS-THAN SIGN
+    u'='        #  0x003d -> EQUALS SIGN
+    u'>'        #  0x003e -> GREATER-THAN SIGN
+    u'?'        #  0x003f -> QUESTION MARK
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET
+    u'\\'       #  0x005c -> REVERSE SOLIDUS
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT
+    u'_'        #  0x005f -> LOW LINE
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET
+    u'|'        #  0x007c -> VERTICAL LINE
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> DELETE
+    u'\ufffe'   #  0x0080 -> UNDEFINED
+    u'\ufffe'   #  0x0081 -> UNDEFINED
+    u'\ufffe'   #  0x0082 -> UNDEFINED
+    u'\ufffe'   #  0x0083 -> UNDEFINED
+    u'\ufffe'   #  0x0084 -> UNDEFINED
+    u'\ufffe'   #  0x0085 -> UNDEFINED
+    u'\u0386'   #  0x0086 -> GREEK CAPITAL LETTER ALPHA WITH TONOS
+    u'\ufffe'   #  0x0087 -> UNDEFINED
+    u'\xb7'     #  0x0088 -> MIDDLE DOT
+    u'\xac'     #  0x0089 -> NOT SIGN
+    u'\xa6'     #  0x008a -> BROKEN BAR
+    u'\u2018'   #  0x008b -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x008c -> RIGHT SINGLE QUOTATION MARK
+    u'\u0388'   #  0x008d -> GREEK CAPITAL LETTER EPSILON WITH TONOS
+    u'\u2015'   #  0x008e -> HORIZONTAL BAR
+    u'\u0389'   #  0x008f -> GREEK CAPITAL LETTER ETA WITH TONOS
+    u'\u038a'   #  0x0090 -> GREEK CAPITAL LETTER IOTA WITH TONOS
+    u'\u03aa'   #  0x0091 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    u'\u038c'   #  0x0092 -> GREEK CAPITAL LETTER OMICRON WITH TONOS
+    u'\ufffe'   #  0x0093 -> UNDEFINED
+    u'\ufffe'   #  0x0094 -> UNDEFINED
+    u'\u038e'   #  0x0095 -> GREEK CAPITAL LETTER UPSILON WITH TONOS
+    u'\u03ab'   #  0x0096 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    u'\xa9'     #  0x0097 -> COPYRIGHT SIGN
+    u'\u038f'   #  0x0098 -> GREEK CAPITAL LETTER OMEGA WITH TONOS
+    u'\xb2'     #  0x0099 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0x009a -> SUPERSCRIPT THREE
+    u'\u03ac'   #  0x009b -> GREEK SMALL LETTER ALPHA WITH TONOS
+    u'\xa3'     #  0x009c -> POUND SIGN
+    u'\u03ad'   #  0x009d -> GREEK SMALL LETTER EPSILON WITH TONOS
+    u'\u03ae'   #  0x009e -> GREEK SMALL LETTER ETA WITH TONOS
+    u'\u03af'   #  0x009f -> GREEK SMALL LETTER IOTA WITH TONOS
+    u'\u03ca'   #  0x00a0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    u'\u0390'   #  0x00a1 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+    u'\u03cc'   #  0x00a2 -> GREEK SMALL LETTER OMICRON WITH TONOS
+    u'\u03cd'   #  0x00a3 -> GREEK SMALL LETTER UPSILON WITH TONOS
+    u'\u0391'   #  0x00a4 -> GREEK CAPITAL LETTER ALPHA
+    u'\u0392'   #  0x00a5 -> GREEK CAPITAL LETTER BETA
+    u'\u0393'   #  0x00a6 -> GREEK CAPITAL LETTER GAMMA
+    u'\u0394'   #  0x00a7 -> GREEK CAPITAL LETTER DELTA
+    u'\u0395'   #  0x00a8 -> GREEK CAPITAL LETTER EPSILON
+    u'\u0396'   #  0x00a9 -> GREEK CAPITAL LETTER ZETA
+    u'\u0397'   #  0x00aa -> GREEK CAPITAL LETTER ETA
+    u'\xbd'     #  0x00ab -> VULGAR FRACTION ONE HALF
+    u'\u0398'   #  0x00ac -> GREEK CAPITAL LETTER THETA
+    u'\u0399'   #  0x00ad -> GREEK CAPITAL LETTER IOTA
+    u'\xab'     #  0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2591'   #  0x00b0 -> LIGHT SHADE
+    u'\u2592'   #  0x00b1 -> MEDIUM SHADE
+    u'\u2593'   #  0x00b2 -> DARK SHADE
+    u'\u2502'   #  0x00b3 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u2524'   #  0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u039a'   #  0x00b5 -> GREEK CAPITAL LETTER KAPPA
+    u'\u039b'   #  0x00b6 -> GREEK CAPITAL LETTER LAMDA
+    u'\u039c'   #  0x00b7 -> GREEK CAPITAL LETTER MU
+    u'\u039d'   #  0x00b8 -> GREEK CAPITAL LETTER NU
+    u'\u2563'   #  0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2551'   #  0x00ba -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2557'   #  0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u255d'   #  0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u039e'   #  0x00bd -> GREEK CAPITAL LETTER XI
+    u'\u039f'   #  0x00be -> GREEK CAPITAL LETTER OMICRON
+    u'\u2510'   #  0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2534'   #  0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u252c'   #  0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u251c'   #  0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2500'   #  0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u253c'   #  0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u03a0'   #  0x00c6 -> GREEK CAPITAL LETTER PI
+    u'\u03a1'   #  0x00c7 -> GREEK CAPITAL LETTER RHO
+    u'\u255a'   #  0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u2554'   #  0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2569'   #  0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u2566'   #  0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2560'   #  0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2550'   #  0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u256c'   #  0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\u03a3'   #  0x00cf -> GREEK CAPITAL LETTER SIGMA
+    u'\u03a4'   #  0x00d0 -> GREEK CAPITAL LETTER TAU
+    u'\u03a5'   #  0x00d1 -> GREEK CAPITAL LETTER UPSILON
+    u'\u03a6'   #  0x00d2 -> GREEK CAPITAL LETTER PHI
+    u'\u03a7'   #  0x00d3 -> GREEK CAPITAL LETTER CHI
+    u'\u03a8'   #  0x00d4 -> GREEK CAPITAL LETTER PSI
+    u'\u03a9'   #  0x00d5 -> GREEK CAPITAL LETTER OMEGA
+    u'\u03b1'   #  0x00d6 -> GREEK SMALL LETTER ALPHA
+    u'\u03b2'   #  0x00d7 -> GREEK SMALL LETTER BETA
+    u'\u03b3'   #  0x00d8 -> GREEK SMALL LETTER GAMMA
+    u'\u2518'   #  0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u250c'   #  0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2588'   #  0x00db -> FULL BLOCK
+    u'\u2584'   #  0x00dc -> LOWER HALF BLOCK
+    u'\u03b4'   #  0x00dd -> GREEK SMALL LETTER DELTA
+    u'\u03b5'   #  0x00de -> GREEK SMALL LETTER EPSILON
+    u'\u2580'   #  0x00df -> UPPER HALF BLOCK
+    u'\u03b6'   #  0x00e0 -> GREEK SMALL LETTER ZETA
+    u'\u03b7'   #  0x00e1 -> GREEK SMALL LETTER ETA
+    u'\u03b8'   #  0x00e2 -> GREEK SMALL LETTER THETA
+    u'\u03b9'   #  0x00e3 -> GREEK SMALL LETTER IOTA
+    u'\u03ba'   #  0x00e4 -> GREEK SMALL LETTER KAPPA
+    u'\u03bb'   #  0x00e5 -> GREEK SMALL LETTER LAMDA
+    u'\u03bc'   #  0x00e6 -> GREEK SMALL LETTER MU
+    u'\u03bd'   #  0x00e7 -> GREEK SMALL LETTER NU
+    u'\u03be'   #  0x00e8 -> GREEK SMALL LETTER XI
+    u'\u03bf'   #  0x00e9 -> GREEK SMALL LETTER OMICRON
+    u'\u03c0'   #  0x00ea -> GREEK SMALL LETTER PI
+    u'\u03c1'   #  0x00eb -> GREEK SMALL LETTER RHO
+    u'\u03c3'   #  0x00ec -> GREEK SMALL LETTER SIGMA
+    u'\u03c2'   #  0x00ed -> GREEK SMALL LETTER FINAL SIGMA
+    u'\u03c4'   #  0x00ee -> GREEK SMALL LETTER TAU
+    u'\u0384'   #  0x00ef -> GREEK TONOS
+    u'\xad'     #  0x00f0 -> SOFT HYPHEN
+    u'\xb1'     #  0x00f1 -> PLUS-MINUS SIGN
+    u'\u03c5'   #  0x00f2 -> GREEK SMALL LETTER UPSILON
+    u'\u03c6'   #  0x00f3 -> GREEK SMALL LETTER PHI
+    u'\u03c7'   #  0x00f4 -> GREEK SMALL LETTER CHI
+    u'\xa7'     #  0x00f5 -> SECTION SIGN
+    u'\u03c8'   #  0x00f6 -> GREEK SMALL LETTER PSI
+    u'\u0385'   #  0x00f7 -> GREEK DIALYTIKA TONOS
+    u'\xb0'     #  0x00f8 -> DEGREE SIGN
+    u'\xa8'     #  0x00f9 -> DIAERESIS
+    u'\u03c9'   #  0x00fa -> GREEK SMALL LETTER OMEGA
+    u'\u03cb'   #  0x00fb -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    u'\u03b0'   #  0x00fc -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+    u'\u03ce'   #  0x00fd -> GREEK SMALL LETTER OMEGA WITH TONOS
+    u'\u25a0'   #  0x00fe -> BLACK SQUARE
+    u'\xa0'     #  0x00ff -> NO-BREAK SPACE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  NULL
+    0x0001: 0x0001,     #  START OF HEADING
+    0x0002: 0x0002,     #  START OF TEXT
+    0x0003: 0x0003,     #  END OF TEXT
+    0x0004: 0x0004,     #  END OF TRANSMISSION
+    0x0005: 0x0005,     #  ENQUIRY
+    0x0006: 0x0006,     #  ACKNOWLEDGE
+    0x0007: 0x0007,     #  BELL
+    0x0008: 0x0008,     #  BACKSPACE
+    0x0009: 0x0009,     #  HORIZONTAL TABULATION
+    0x000a: 0x000a,     #  LINE FEED
+    0x000b: 0x000b,     #  VERTICAL TABULATION
+    0x000c: 0x000c,     #  FORM FEED
+    0x000d: 0x000d,     #  CARRIAGE RETURN
+    0x000e: 0x000e,     #  SHIFT OUT
+    0x000f: 0x000f,     #  SHIFT IN
+    0x0010: 0x0010,     #  DATA LINK ESCAPE
+    0x0011: 0x0011,     #  DEVICE CONTROL ONE
+    0x0012: 0x0012,     #  DEVICE CONTROL TWO
+    0x0013: 0x0013,     #  DEVICE CONTROL THREE
+    0x0014: 0x0014,     #  DEVICE CONTROL FOUR
+    0x0015: 0x0015,     #  NEGATIVE ACKNOWLEDGE
+    0x0016: 0x0016,     #  SYNCHRONOUS IDLE
+    0x0017: 0x0017,     #  END OF TRANSMISSION BLOCK
+    0x0018: 0x0018,     #  CANCEL
+    0x0019: 0x0019,     #  END OF MEDIUM
+    0x001a: 0x001a,     #  SUBSTITUTE
+    0x001b: 0x001b,     #  ESCAPE
+    0x001c: 0x001c,     #  FILE SEPARATOR
+    0x001d: 0x001d,     #  GROUP SEPARATOR
+    0x001e: 0x001e,     #  RECORD SEPARATOR
+    0x001f: 0x001f,     #  UNIT SEPARATOR
+    0x0020: 0x0020,     #  SPACE
+    0x0021: 0x0021,     #  EXCLAMATION MARK
+    0x0022: 0x0022,     #  QUOTATION MARK
+    0x0023: 0x0023,     #  NUMBER SIGN
+    0x0024: 0x0024,     #  DOLLAR SIGN
+    0x0025: 0x0025,     #  PERCENT SIGN
+    0x0026: 0x0026,     #  AMPERSAND
+    0x0027: 0x0027,     #  APOSTROPHE
+    0x0028: 0x0028,     #  LEFT PARENTHESIS
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS
+    0x002a: 0x002a,     #  ASTERISK
+    0x002b: 0x002b,     #  PLUS SIGN
+    0x002c: 0x002c,     #  COMMA
+    0x002d: 0x002d,     #  HYPHEN-MINUS
+    0x002e: 0x002e,     #  FULL STOP
+    0x002f: 0x002f,     #  SOLIDUS
+    0x0030: 0x0030,     #  DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE
+    0x003a: 0x003a,     #  COLON
+    0x003b: 0x003b,     #  SEMICOLON
+    0x003c: 0x003c,     #  LESS-THAN SIGN
+    0x003d: 0x003d,     #  EQUALS SIGN
+    0x003e: 0x003e,     #  GREATER-THAN SIGN
+    0x003f: 0x003f,     #  QUESTION MARK
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET
+    0x005c: 0x005c,     #  REVERSE SOLIDUS
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT
+    0x005f: 0x005f,     #  LOW LINE
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET
+    0x007c: 0x007c,     #  VERTICAL LINE
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  DELETE
+    0x00a0: 0x00ff,     #  NO-BREAK SPACE
+    0x00a3: 0x009c,     #  POUND SIGN
+    0x00a6: 0x008a,     #  BROKEN BAR
+    0x00a7: 0x00f5,     #  SECTION SIGN
+    0x00a8: 0x00f9,     #  DIAERESIS
+    0x00a9: 0x0097,     #  COPYRIGHT SIGN
+    0x00ab: 0x00ae,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00ac: 0x0089,     #  NOT SIGN
+    0x00ad: 0x00f0,     #  SOFT HYPHEN
+    0x00b0: 0x00f8,     #  DEGREE SIGN
+    0x00b1: 0x00f1,     #  PLUS-MINUS SIGN
+    0x00b2: 0x0099,     #  SUPERSCRIPT TWO
+    0x00b3: 0x009a,     #  SUPERSCRIPT THREE
+    0x00b7: 0x0088,     #  MIDDLE DOT
+    0x00bb: 0x00af,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    0x00bd: 0x00ab,     #  VULGAR FRACTION ONE HALF
+    0x0384: 0x00ef,     #  GREEK TONOS
+    0x0385: 0x00f7,     #  GREEK DIALYTIKA TONOS
+    0x0386: 0x0086,     #  GREEK CAPITAL LETTER ALPHA WITH TONOS
+    0x0388: 0x008d,     #  GREEK CAPITAL LETTER EPSILON WITH TONOS
+    0x0389: 0x008f,     #  GREEK CAPITAL LETTER ETA WITH TONOS
+    0x038a: 0x0090,     #  GREEK CAPITAL LETTER IOTA WITH TONOS
+    0x038c: 0x0092,     #  GREEK CAPITAL LETTER OMICRON WITH TONOS
+    0x038e: 0x0095,     #  GREEK CAPITAL LETTER UPSILON WITH TONOS
+    0x038f: 0x0098,     #  GREEK CAPITAL LETTER OMEGA WITH TONOS
+    0x0390: 0x00a1,     #  GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+    0x0391: 0x00a4,     #  GREEK CAPITAL LETTER ALPHA
+    0x0392: 0x00a5,     #  GREEK CAPITAL LETTER BETA
+    0x0393: 0x00a6,     #  GREEK CAPITAL LETTER GAMMA
+    0x0394: 0x00a7,     #  GREEK CAPITAL LETTER DELTA
+    0x0395: 0x00a8,     #  GREEK CAPITAL LETTER EPSILON
+    0x0396: 0x00a9,     #  GREEK CAPITAL LETTER ZETA
+    0x0397: 0x00aa,     #  GREEK CAPITAL LETTER ETA
+    0x0398: 0x00ac,     #  GREEK CAPITAL LETTER THETA
+    0x0399: 0x00ad,     #  GREEK CAPITAL LETTER IOTA
+    0x039a: 0x00b5,     #  GREEK CAPITAL LETTER KAPPA
+    0x039b: 0x00b6,     #  GREEK CAPITAL LETTER LAMDA
+    0x039c: 0x00b7,     #  GREEK CAPITAL LETTER MU
+    0x039d: 0x00b8,     #  GREEK CAPITAL LETTER NU
+    0x039e: 0x00bd,     #  GREEK CAPITAL LETTER XI
+    0x039f: 0x00be,     #  GREEK CAPITAL LETTER OMICRON
+    0x03a0: 0x00c6,     #  GREEK CAPITAL LETTER PI
+    0x03a1: 0x00c7,     #  GREEK CAPITAL LETTER RHO
+    0x03a3: 0x00cf,     #  GREEK CAPITAL LETTER SIGMA
+    0x03a4: 0x00d0,     #  GREEK CAPITAL LETTER TAU
+    0x03a5: 0x00d1,     #  GREEK CAPITAL LETTER UPSILON
+    0x03a6: 0x00d2,     #  GREEK CAPITAL LETTER PHI
+    0x03a7: 0x00d3,     #  GREEK CAPITAL LETTER CHI
+    0x03a8: 0x00d4,     #  GREEK CAPITAL LETTER PSI
+    0x03a9: 0x00d5,     #  GREEK CAPITAL LETTER OMEGA
+    0x03aa: 0x0091,     #  GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    0x03ab: 0x0096,     #  GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    0x03ac: 0x009b,     #  GREEK SMALL LETTER ALPHA WITH TONOS
+    0x03ad: 0x009d,     #  GREEK SMALL LETTER EPSILON WITH TONOS
+    0x03ae: 0x009e,     #  GREEK SMALL LETTER ETA WITH TONOS
+    0x03af: 0x009f,     #  GREEK SMALL LETTER IOTA WITH TONOS
+    0x03b0: 0x00fc,     #  GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+    0x03b1: 0x00d6,     #  GREEK SMALL LETTER ALPHA
+    0x03b2: 0x00d7,     #  GREEK SMALL LETTER BETA
+    0x03b3: 0x00d8,     #  GREEK SMALL LETTER GAMMA
+    0x03b4: 0x00dd,     #  GREEK SMALL LETTER DELTA
+    0x03b5: 0x00de,     #  GREEK SMALL LETTER EPSILON
+    0x03b6: 0x00e0,     #  GREEK SMALL LETTER ZETA
+    0x03b7: 0x00e1,     #  GREEK SMALL LETTER ETA
+    0x03b8: 0x00e2,     #  GREEK SMALL LETTER THETA
+    0x03b9: 0x00e3,     #  GREEK SMALL LETTER IOTA
+    0x03ba: 0x00e4,     #  GREEK SMALL LETTER KAPPA
+    0x03bb: 0x00e5,     #  GREEK SMALL LETTER LAMDA
+    0x03bc: 0x00e6,     #  GREEK SMALL LETTER MU
+    0x03bd: 0x00e7,     #  GREEK SMALL LETTER NU
+    0x03be: 0x00e8,     #  GREEK SMALL LETTER XI
+    0x03bf: 0x00e9,     #  GREEK SMALL LETTER OMICRON
+    0x03c0: 0x00ea,     #  GREEK SMALL LETTER PI
+    0x03c1: 0x00eb,     #  GREEK SMALL LETTER RHO
+    0x03c2: 0x00ed,     #  GREEK SMALL LETTER FINAL SIGMA
+    0x03c3: 0x00ec,     #  GREEK SMALL LETTER SIGMA
+    0x03c4: 0x00ee,     #  GREEK SMALL LETTER TAU
+    0x03c5: 0x00f2,     #  GREEK SMALL LETTER UPSILON
+    0x03c6: 0x00f3,     #  GREEK SMALL LETTER PHI
+    0x03c7: 0x00f4,     #  GREEK SMALL LETTER CHI
+    0x03c8: 0x00f6,     #  GREEK SMALL LETTER PSI
+    0x03c9: 0x00fa,     #  GREEK SMALL LETTER OMEGA
+    0x03ca: 0x00a0,     #  GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    0x03cb: 0x00fb,     #  GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    0x03cc: 0x00a2,     #  GREEK SMALL LETTER OMICRON WITH TONOS
+    0x03cd: 0x00a3,     #  GREEK SMALL LETTER UPSILON WITH TONOS
+    0x03ce: 0x00fd,     #  GREEK SMALL LETTER OMEGA WITH TONOS
+    0x2015: 0x008e,     #  HORIZONTAL BAR
+    0x2018: 0x008b,     #  LEFT SINGLE QUOTATION MARK
+    0x2019: 0x008c,     #  RIGHT SINGLE QUOTATION MARK
+    0x2500: 0x00c4,     #  BOX DRAWINGS LIGHT HORIZONTAL
+    0x2502: 0x00b3,     #  BOX DRAWINGS LIGHT VERTICAL
+    0x250c: 0x00da,     #  BOX DRAWINGS LIGHT DOWN AND RIGHT
+    0x2510: 0x00bf,     #  BOX DRAWINGS LIGHT DOWN AND LEFT
+    0x2514: 0x00c0,     #  BOX DRAWINGS LIGHT UP AND RIGHT
+    0x2518: 0x00d9,     #  BOX DRAWINGS LIGHT UP AND LEFT
+    0x251c: 0x00c3,     #  BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    0x2524: 0x00b4,     #  BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    0x252c: 0x00c2,     #  BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    0x2534: 0x00c1,     #  BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    0x253c: 0x00c5,     #  BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    0x2550: 0x00cd,     #  BOX DRAWINGS DOUBLE HORIZONTAL
+    0x2551: 0x00ba,     #  BOX DRAWINGS DOUBLE VERTICAL
+    0x2554: 0x00c9,     #  BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    0x2557: 0x00bb,     #  BOX DRAWINGS DOUBLE DOWN AND LEFT
+    0x255a: 0x00c8,     #  BOX DRAWINGS DOUBLE UP AND RIGHT
+    0x255d: 0x00bc,     #  BOX DRAWINGS DOUBLE UP AND LEFT
+    0x2560: 0x00cc,     #  BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    0x2563: 0x00b9,     #  BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    0x2566: 0x00cb,     #  BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    0x2569: 0x00ca,     #  BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    0x256c: 0x00ce,     #  BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    0x2580: 0x00df,     #  UPPER HALF BLOCK
+    0x2584: 0x00dc,     #  LOWER HALF BLOCK
+    0x2588: 0x00db,     #  FULL BLOCK
+    0x2591: 0x00b0,     #  LIGHT SHADE
+    0x2592: 0x00b1,     #  MEDIUM SHADE
+    0x2593: 0x00b2,     #  DARK SHADE
+    0x25a0: 0x00fe,     #  BLACK SQUARE
+}
diff --git a/src/main/resources/PythonLibs/encodings/cp874.py b/src/main/resources/PythonLibs/encodings/cp874.py
new file mode 100644
index 0000000000000000000000000000000000000000..6110f46e5b5cecfe7f1ecd125beeafc33acea006
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp874.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp874 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP874.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp874',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u20ac'   #  0x80 -> EURO SIGN
+    u'\ufffe'   #  0x81 -> UNDEFINED
+    u'\ufffe'   #  0x82 -> UNDEFINED
+    u'\ufffe'   #  0x83 -> UNDEFINED
+    u'\ufffe'   #  0x84 -> UNDEFINED
+    u'\u2026'   #  0x85 -> HORIZONTAL ELLIPSIS
+    u'\ufffe'   #  0x86 -> UNDEFINED
+    u'\ufffe'   #  0x87 -> UNDEFINED
+    u'\ufffe'   #  0x88 -> UNDEFINED
+    u'\ufffe'   #  0x89 -> UNDEFINED
+    u'\ufffe'   #  0x8A -> UNDEFINED
+    u'\ufffe'   #  0x8B -> UNDEFINED
+    u'\ufffe'   #  0x8C -> UNDEFINED
+    u'\ufffe'   #  0x8D -> UNDEFINED
+    u'\ufffe'   #  0x8E -> UNDEFINED
+    u'\ufffe'   #  0x8F -> UNDEFINED
+    u'\ufffe'   #  0x90 -> UNDEFINED
+    u'\u2018'   #  0x91 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0x92 -> RIGHT SINGLE QUOTATION MARK
+    u'\u201c'   #  0x93 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0x94 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2022'   #  0x95 -> BULLET
+    u'\u2013'   #  0x96 -> EN DASH
+    u'\u2014'   #  0x97 -> EM DASH
+    u'\ufffe'   #  0x98 -> UNDEFINED
+    u'\ufffe'   #  0x99 -> UNDEFINED
+    u'\ufffe'   #  0x9A -> UNDEFINED
+    u'\ufffe'   #  0x9B -> UNDEFINED
+    u'\ufffe'   #  0x9C -> UNDEFINED
+    u'\ufffe'   #  0x9D -> UNDEFINED
+    u'\ufffe'   #  0x9E -> UNDEFINED
+    u'\ufffe'   #  0x9F -> UNDEFINED
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0e01'   #  0xA1 -> THAI CHARACTER KO KAI
+    u'\u0e02'   #  0xA2 -> THAI CHARACTER KHO KHAI
+    u'\u0e03'   #  0xA3 -> THAI CHARACTER KHO KHUAT
+    u'\u0e04'   #  0xA4 -> THAI CHARACTER KHO KHWAI
+    u'\u0e05'   #  0xA5 -> THAI CHARACTER KHO KHON
+    u'\u0e06'   #  0xA6 -> THAI CHARACTER KHO RAKHANG
+    u'\u0e07'   #  0xA7 -> THAI CHARACTER NGO NGU
+    u'\u0e08'   #  0xA8 -> THAI CHARACTER CHO CHAN
+    u'\u0e09'   #  0xA9 -> THAI CHARACTER CHO CHING
+    u'\u0e0a'   #  0xAA -> THAI CHARACTER CHO CHANG
+    u'\u0e0b'   #  0xAB -> THAI CHARACTER SO SO
+    u'\u0e0c'   #  0xAC -> THAI CHARACTER CHO CHOE
+    u'\u0e0d'   #  0xAD -> THAI CHARACTER YO YING
+    u'\u0e0e'   #  0xAE -> THAI CHARACTER DO CHADA
+    u'\u0e0f'   #  0xAF -> THAI CHARACTER TO PATAK
+    u'\u0e10'   #  0xB0 -> THAI CHARACTER THO THAN
+    u'\u0e11'   #  0xB1 -> THAI CHARACTER THO NANGMONTHO
+    u'\u0e12'   #  0xB2 -> THAI CHARACTER THO PHUTHAO
+    u'\u0e13'   #  0xB3 -> THAI CHARACTER NO NEN
+    u'\u0e14'   #  0xB4 -> THAI CHARACTER DO DEK
+    u'\u0e15'   #  0xB5 -> THAI CHARACTER TO TAO
+    u'\u0e16'   #  0xB6 -> THAI CHARACTER THO THUNG
+    u'\u0e17'   #  0xB7 -> THAI CHARACTER THO THAHAN
+    u'\u0e18'   #  0xB8 -> THAI CHARACTER THO THONG
+    u'\u0e19'   #  0xB9 -> THAI CHARACTER NO NU
+    u'\u0e1a'   #  0xBA -> THAI CHARACTER BO BAIMAI
+    u'\u0e1b'   #  0xBB -> THAI CHARACTER PO PLA
+    u'\u0e1c'   #  0xBC -> THAI CHARACTER PHO PHUNG
+    u'\u0e1d'   #  0xBD -> THAI CHARACTER FO FA
+    u'\u0e1e'   #  0xBE -> THAI CHARACTER PHO PHAN
+    u'\u0e1f'   #  0xBF -> THAI CHARACTER FO FAN
+    u'\u0e20'   #  0xC0 -> THAI CHARACTER PHO SAMPHAO
+    u'\u0e21'   #  0xC1 -> THAI CHARACTER MO MA
+    u'\u0e22'   #  0xC2 -> THAI CHARACTER YO YAK
+    u'\u0e23'   #  0xC3 -> THAI CHARACTER RO RUA
+    u'\u0e24'   #  0xC4 -> THAI CHARACTER RU
+    u'\u0e25'   #  0xC5 -> THAI CHARACTER LO LING
+    u'\u0e26'   #  0xC6 -> THAI CHARACTER LU
+    u'\u0e27'   #  0xC7 -> THAI CHARACTER WO WAEN
+    u'\u0e28'   #  0xC8 -> THAI CHARACTER SO SALA
+    u'\u0e29'   #  0xC9 -> THAI CHARACTER SO RUSI
+    u'\u0e2a'   #  0xCA -> THAI CHARACTER SO SUA
+    u'\u0e2b'   #  0xCB -> THAI CHARACTER HO HIP
+    u'\u0e2c'   #  0xCC -> THAI CHARACTER LO CHULA
+    u'\u0e2d'   #  0xCD -> THAI CHARACTER O ANG
+    u'\u0e2e'   #  0xCE -> THAI CHARACTER HO NOKHUK
+    u'\u0e2f'   #  0xCF -> THAI CHARACTER PAIYANNOI
+    u'\u0e30'   #  0xD0 -> THAI CHARACTER SARA A
+    u'\u0e31'   #  0xD1 -> THAI CHARACTER MAI HAN-AKAT
+    u'\u0e32'   #  0xD2 -> THAI CHARACTER SARA AA
+    u'\u0e33'   #  0xD3 -> THAI CHARACTER SARA AM
+    u'\u0e34'   #  0xD4 -> THAI CHARACTER SARA I
+    u'\u0e35'   #  0xD5 -> THAI CHARACTER SARA II
+    u'\u0e36'   #  0xD6 -> THAI CHARACTER SARA UE
+    u'\u0e37'   #  0xD7 -> THAI CHARACTER SARA UEE
+    u'\u0e38'   #  0xD8 -> THAI CHARACTER SARA U
+    u'\u0e39'   #  0xD9 -> THAI CHARACTER SARA UU
+    u'\u0e3a'   #  0xDA -> THAI CHARACTER PHINTHU
+    u'\ufffe'   #  0xDB -> UNDEFINED
+    u'\ufffe'   #  0xDC -> UNDEFINED
+    u'\ufffe'   #  0xDD -> UNDEFINED
+    u'\ufffe'   #  0xDE -> UNDEFINED
+    u'\u0e3f'   #  0xDF -> THAI CURRENCY SYMBOL BAHT
+    u'\u0e40'   #  0xE0 -> THAI CHARACTER SARA E
+    u'\u0e41'   #  0xE1 -> THAI CHARACTER SARA AE
+    u'\u0e42'   #  0xE2 -> THAI CHARACTER SARA O
+    u'\u0e43'   #  0xE3 -> THAI CHARACTER SARA AI MAIMUAN
+    u'\u0e44'   #  0xE4 -> THAI CHARACTER SARA AI MAIMALAI
+    u'\u0e45'   #  0xE5 -> THAI CHARACTER LAKKHANGYAO
+    u'\u0e46'   #  0xE6 -> THAI CHARACTER MAIYAMOK
+    u'\u0e47'   #  0xE7 -> THAI CHARACTER MAITAIKHU
+    u'\u0e48'   #  0xE8 -> THAI CHARACTER MAI EK
+    u'\u0e49'   #  0xE9 -> THAI CHARACTER MAI THO
+    u'\u0e4a'   #  0xEA -> THAI CHARACTER MAI TRI
+    u'\u0e4b'   #  0xEB -> THAI CHARACTER MAI CHATTAWA
+    u'\u0e4c'   #  0xEC -> THAI CHARACTER THANTHAKHAT
+    u'\u0e4d'   #  0xED -> THAI CHARACTER NIKHAHIT
+    u'\u0e4e'   #  0xEE -> THAI CHARACTER YAMAKKAN
+    u'\u0e4f'   #  0xEF -> THAI CHARACTER FONGMAN
+    u'\u0e50'   #  0xF0 -> THAI DIGIT ZERO
+    u'\u0e51'   #  0xF1 -> THAI DIGIT ONE
+    u'\u0e52'   #  0xF2 -> THAI DIGIT TWO
+    u'\u0e53'   #  0xF3 -> THAI DIGIT THREE
+    u'\u0e54'   #  0xF4 -> THAI DIGIT FOUR
+    u'\u0e55'   #  0xF5 -> THAI DIGIT FIVE
+    u'\u0e56'   #  0xF6 -> THAI DIGIT SIX
+    u'\u0e57'   #  0xF7 -> THAI DIGIT SEVEN
+    u'\u0e58'   #  0xF8 -> THAI DIGIT EIGHT
+    u'\u0e59'   #  0xF9 -> THAI DIGIT NINE
+    u'\u0e5a'   #  0xFA -> THAI CHARACTER ANGKHANKHU
+    u'\u0e5b'   #  0xFB -> THAI CHARACTER KHOMUT
+    u'\ufffe'   #  0xFC -> UNDEFINED
+    u'\ufffe'   #  0xFD -> UNDEFINED
+    u'\ufffe'   #  0xFE -> UNDEFINED
+    u'\ufffe'   #  0xFF -> UNDEFINED
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp875.py b/src/main/resources/PythonLibs/encodings/cp875.py
new file mode 100644
index 0000000000000000000000000000000000000000..72b160b02f7908d91f18c5a7d873847ec9c1db77
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp875.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec cp875 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP875.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp875',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x9c'     #  0x04 -> CONTROL
+    u'\t'       #  0x05 -> HORIZONTAL TABULATION
+    u'\x86'     #  0x06 -> CONTROL
+    u'\x7f'     #  0x07 -> DELETE
+    u'\x97'     #  0x08 -> CONTROL
+    u'\x8d'     #  0x09 -> CONTROL
+    u'\x8e'     #  0x0A -> CONTROL
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x9d'     #  0x14 -> CONTROL
+    u'\x85'     #  0x15 -> CONTROL
+    u'\x08'     #  0x16 -> BACKSPACE
+    u'\x87'     #  0x17 -> CONTROL
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x92'     #  0x1A -> CONTROL
+    u'\x8f'     #  0x1B -> CONTROL
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u'\x80'     #  0x20 -> CONTROL
+    u'\x81'     #  0x21 -> CONTROL
+    u'\x82'     #  0x22 -> CONTROL
+    u'\x83'     #  0x23 -> CONTROL
+    u'\x84'     #  0x24 -> CONTROL
+    u'\n'       #  0x25 -> LINE FEED
+    u'\x17'     #  0x26 -> END OF TRANSMISSION BLOCK
+    u'\x1b'     #  0x27 -> ESCAPE
+    u'\x88'     #  0x28 -> CONTROL
+    u'\x89'     #  0x29 -> CONTROL
+    u'\x8a'     #  0x2A -> CONTROL
+    u'\x8b'     #  0x2B -> CONTROL
+    u'\x8c'     #  0x2C -> CONTROL
+    u'\x05'     #  0x2D -> ENQUIRY
+    u'\x06'     #  0x2E -> ACKNOWLEDGE
+    u'\x07'     #  0x2F -> BELL
+    u'\x90'     #  0x30 -> CONTROL
+    u'\x91'     #  0x31 -> CONTROL
+    u'\x16'     #  0x32 -> SYNCHRONOUS IDLE
+    u'\x93'     #  0x33 -> CONTROL
+    u'\x94'     #  0x34 -> CONTROL
+    u'\x95'     #  0x35 -> CONTROL
+    u'\x96'     #  0x36 -> CONTROL
+    u'\x04'     #  0x37 -> END OF TRANSMISSION
+    u'\x98'     #  0x38 -> CONTROL
+    u'\x99'     #  0x39 -> CONTROL
+    u'\x9a'     #  0x3A -> CONTROL
+    u'\x9b'     #  0x3B -> CONTROL
+    u'\x14'     #  0x3C -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x3D -> NEGATIVE ACKNOWLEDGE
+    u'\x9e'     #  0x3E -> CONTROL
+    u'\x1a'     #  0x3F -> SUBSTITUTE
+    u' '        #  0x40 -> SPACE
+    u'\u0391'   #  0x41 -> GREEK CAPITAL LETTER ALPHA
+    u'\u0392'   #  0x42 -> GREEK CAPITAL LETTER BETA
+    u'\u0393'   #  0x43 -> GREEK CAPITAL LETTER GAMMA
+    u'\u0394'   #  0x44 -> GREEK CAPITAL LETTER DELTA
+    u'\u0395'   #  0x45 -> GREEK CAPITAL LETTER EPSILON
+    u'\u0396'   #  0x46 -> GREEK CAPITAL LETTER ZETA
+    u'\u0397'   #  0x47 -> GREEK CAPITAL LETTER ETA
+    u'\u0398'   #  0x48 -> GREEK CAPITAL LETTER THETA
+    u'\u0399'   #  0x49 -> GREEK CAPITAL LETTER IOTA
+    u'['        #  0x4A -> LEFT SQUARE BRACKET
+    u'.'        #  0x4B -> FULL STOP
+    u'<'        #  0x4C -> LESS-THAN SIGN
+    u'('        #  0x4D -> LEFT PARENTHESIS
+    u'+'        #  0x4E -> PLUS SIGN
+    u'!'        #  0x4F -> EXCLAMATION MARK
+    u'&'        #  0x50 -> AMPERSAND
+    u'\u039a'   #  0x51 -> GREEK CAPITAL LETTER KAPPA
+    u'\u039b'   #  0x52 -> GREEK CAPITAL LETTER LAMDA
+    u'\u039c'   #  0x53 -> GREEK CAPITAL LETTER MU
+    u'\u039d'   #  0x54 -> GREEK CAPITAL LETTER NU
+    u'\u039e'   #  0x55 -> GREEK CAPITAL LETTER XI
+    u'\u039f'   #  0x56 -> GREEK CAPITAL LETTER OMICRON
+    u'\u03a0'   #  0x57 -> GREEK CAPITAL LETTER PI
+    u'\u03a1'   #  0x58 -> GREEK CAPITAL LETTER RHO
+    u'\u03a3'   #  0x59 -> GREEK CAPITAL LETTER SIGMA
+    u']'        #  0x5A -> RIGHT SQUARE BRACKET
+    u'$'        #  0x5B -> DOLLAR SIGN
+    u'*'        #  0x5C -> ASTERISK
+    u')'        #  0x5D -> RIGHT PARENTHESIS
+    u';'        #  0x5E -> SEMICOLON
+    u'^'        #  0x5F -> CIRCUMFLEX ACCENT
+    u'-'        #  0x60 -> HYPHEN-MINUS
+    u'/'        #  0x61 -> SOLIDUS
+    u'\u03a4'   #  0x62 -> GREEK CAPITAL LETTER TAU
+    u'\u03a5'   #  0x63 -> GREEK CAPITAL LETTER UPSILON
+    u'\u03a6'   #  0x64 -> GREEK CAPITAL LETTER PHI
+    u'\u03a7'   #  0x65 -> GREEK CAPITAL LETTER CHI
+    u'\u03a8'   #  0x66 -> GREEK CAPITAL LETTER PSI
+    u'\u03a9'   #  0x67 -> GREEK CAPITAL LETTER OMEGA
+    u'\u03aa'   #  0x68 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    u'\u03ab'   #  0x69 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    u'|'        #  0x6A -> VERTICAL LINE
+    u','        #  0x6B -> COMMA
+    u'%'        #  0x6C -> PERCENT SIGN
+    u'_'        #  0x6D -> LOW LINE
+    u'>'        #  0x6E -> GREATER-THAN SIGN
+    u'?'        #  0x6F -> QUESTION MARK
+    u'\xa8'     #  0x70 -> DIAERESIS
+    u'\u0386'   #  0x71 -> GREEK CAPITAL LETTER ALPHA WITH TONOS
+    u'\u0388'   #  0x72 -> GREEK CAPITAL LETTER EPSILON WITH TONOS
+    u'\u0389'   #  0x73 -> GREEK CAPITAL LETTER ETA WITH TONOS
+    u'\xa0'     #  0x74 -> NO-BREAK SPACE
+    u'\u038a'   #  0x75 -> GREEK CAPITAL LETTER IOTA WITH TONOS
+    u'\u038c'   #  0x76 -> GREEK CAPITAL LETTER OMICRON WITH TONOS
+    u'\u038e'   #  0x77 -> GREEK CAPITAL LETTER UPSILON WITH TONOS
+    u'\u038f'   #  0x78 -> GREEK CAPITAL LETTER OMEGA WITH TONOS
+    u'`'        #  0x79 -> GRAVE ACCENT
+    u':'        #  0x7A -> COLON
+    u'#'        #  0x7B -> NUMBER SIGN
+    u'@'        #  0x7C -> COMMERCIAL AT
+    u"'"        #  0x7D -> APOSTROPHE
+    u'='        #  0x7E -> EQUALS SIGN
+    u'"'        #  0x7F -> QUOTATION MARK
+    u'\u0385'   #  0x80 -> GREEK DIALYTIKA TONOS
+    u'a'        #  0x81 -> LATIN SMALL LETTER A
+    u'b'        #  0x82 -> LATIN SMALL LETTER B
+    u'c'        #  0x83 -> LATIN SMALL LETTER C
+    u'd'        #  0x84 -> LATIN SMALL LETTER D
+    u'e'        #  0x85 -> LATIN SMALL LETTER E
+    u'f'        #  0x86 -> LATIN SMALL LETTER F
+    u'g'        #  0x87 -> LATIN SMALL LETTER G
+    u'h'        #  0x88 -> LATIN SMALL LETTER H
+    u'i'        #  0x89 -> LATIN SMALL LETTER I
+    u'\u03b1'   #  0x8A -> GREEK SMALL LETTER ALPHA
+    u'\u03b2'   #  0x8B -> GREEK SMALL LETTER BETA
+    u'\u03b3'   #  0x8C -> GREEK SMALL LETTER GAMMA
+    u'\u03b4'   #  0x8D -> GREEK SMALL LETTER DELTA
+    u'\u03b5'   #  0x8E -> GREEK SMALL LETTER EPSILON
+    u'\u03b6'   #  0x8F -> GREEK SMALL LETTER ZETA
+    u'\xb0'     #  0x90 -> DEGREE SIGN
+    u'j'        #  0x91 -> LATIN SMALL LETTER J
+    u'k'        #  0x92 -> LATIN SMALL LETTER K
+    u'l'        #  0x93 -> LATIN SMALL LETTER L
+    u'm'        #  0x94 -> LATIN SMALL LETTER M
+    u'n'        #  0x95 -> LATIN SMALL LETTER N
+    u'o'        #  0x96 -> LATIN SMALL LETTER O
+    u'p'        #  0x97 -> LATIN SMALL LETTER P
+    u'q'        #  0x98 -> LATIN SMALL LETTER Q
+    u'r'        #  0x99 -> LATIN SMALL LETTER R
+    u'\u03b7'   #  0x9A -> GREEK SMALL LETTER ETA
+    u'\u03b8'   #  0x9B -> GREEK SMALL LETTER THETA
+    u'\u03b9'   #  0x9C -> GREEK SMALL LETTER IOTA
+    u'\u03ba'   #  0x9D -> GREEK SMALL LETTER KAPPA
+    u'\u03bb'   #  0x9E -> GREEK SMALL LETTER LAMDA
+    u'\u03bc'   #  0x9F -> GREEK SMALL LETTER MU
+    u'\xb4'     #  0xA0 -> ACUTE ACCENT
+    u'~'        #  0xA1 -> TILDE
+    u's'        #  0xA2 -> LATIN SMALL LETTER S
+    u't'        #  0xA3 -> LATIN SMALL LETTER T
+    u'u'        #  0xA4 -> LATIN SMALL LETTER U
+    u'v'        #  0xA5 -> LATIN SMALL LETTER V
+    u'w'        #  0xA6 -> LATIN SMALL LETTER W
+    u'x'        #  0xA7 -> LATIN SMALL LETTER X
+    u'y'        #  0xA8 -> LATIN SMALL LETTER Y
+    u'z'        #  0xA9 -> LATIN SMALL LETTER Z
+    u'\u03bd'   #  0xAA -> GREEK SMALL LETTER NU
+    u'\u03be'   #  0xAB -> GREEK SMALL LETTER XI
+    u'\u03bf'   #  0xAC -> GREEK SMALL LETTER OMICRON
+    u'\u03c0'   #  0xAD -> GREEK SMALL LETTER PI
+    u'\u03c1'   #  0xAE -> GREEK SMALL LETTER RHO
+    u'\u03c3'   #  0xAF -> GREEK SMALL LETTER SIGMA
+    u'\xa3'     #  0xB0 -> POUND SIGN
+    u'\u03ac'   #  0xB1 -> GREEK SMALL LETTER ALPHA WITH TONOS
+    u'\u03ad'   #  0xB2 -> GREEK SMALL LETTER EPSILON WITH TONOS
+    u'\u03ae'   #  0xB3 -> GREEK SMALL LETTER ETA WITH TONOS
+    u'\u03ca'   #  0xB4 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    u'\u03af'   #  0xB5 -> GREEK SMALL LETTER IOTA WITH TONOS
+    u'\u03cc'   #  0xB6 -> GREEK SMALL LETTER OMICRON WITH TONOS
+    u'\u03cd'   #  0xB7 -> GREEK SMALL LETTER UPSILON WITH TONOS
+    u'\u03cb'   #  0xB8 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    u'\u03ce'   #  0xB9 -> GREEK SMALL LETTER OMEGA WITH TONOS
+    u'\u03c2'   #  0xBA -> GREEK SMALL LETTER FINAL SIGMA
+    u'\u03c4'   #  0xBB -> GREEK SMALL LETTER TAU
+    u'\u03c5'   #  0xBC -> GREEK SMALL LETTER UPSILON
+    u'\u03c6'   #  0xBD -> GREEK SMALL LETTER PHI
+    u'\u03c7'   #  0xBE -> GREEK SMALL LETTER CHI
+    u'\u03c8'   #  0xBF -> GREEK SMALL LETTER PSI
+    u'{'        #  0xC0 -> LEFT CURLY BRACKET
+    u'A'        #  0xC1 -> LATIN CAPITAL LETTER A
+    u'B'        #  0xC2 -> LATIN CAPITAL LETTER B
+    u'C'        #  0xC3 -> LATIN CAPITAL LETTER C
+    u'D'        #  0xC4 -> LATIN CAPITAL LETTER D
+    u'E'        #  0xC5 -> LATIN CAPITAL LETTER E
+    u'F'        #  0xC6 -> LATIN CAPITAL LETTER F
+    u'G'        #  0xC7 -> LATIN CAPITAL LETTER G
+    u'H'        #  0xC8 -> LATIN CAPITAL LETTER H
+    u'I'        #  0xC9 -> LATIN CAPITAL LETTER I
+    u'\xad'     #  0xCA -> SOFT HYPHEN
+    u'\u03c9'   #  0xCB -> GREEK SMALL LETTER OMEGA
+    u'\u0390'   #  0xCC -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+    u'\u03b0'   #  0xCD -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+    u'\u2018'   #  0xCE -> LEFT SINGLE QUOTATION MARK
+    u'\u2015'   #  0xCF -> HORIZONTAL BAR
+    u'}'        #  0xD0 -> RIGHT CURLY BRACKET
+    u'J'        #  0xD1 -> LATIN CAPITAL LETTER J
+    u'K'        #  0xD2 -> LATIN CAPITAL LETTER K
+    u'L'        #  0xD3 -> LATIN CAPITAL LETTER L
+    u'M'        #  0xD4 -> LATIN CAPITAL LETTER M
+    u'N'        #  0xD5 -> LATIN CAPITAL LETTER N
+    u'O'        #  0xD6 -> LATIN CAPITAL LETTER O
+    u'P'        #  0xD7 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0xD8 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0xD9 -> LATIN CAPITAL LETTER R
+    u'\xb1'     #  0xDA -> PLUS-MINUS SIGN
+    u'\xbd'     #  0xDB -> VULGAR FRACTION ONE HALF
+    u'\x1a'     #  0xDC -> SUBSTITUTE
+    u'\u0387'   #  0xDD -> GREEK ANO TELEIA
+    u'\u2019'   #  0xDE -> RIGHT SINGLE QUOTATION MARK
+    u'\xa6'     #  0xDF -> BROKEN BAR
+    u'\\'       #  0xE0 -> REVERSE SOLIDUS
+    u'\x1a'     #  0xE1 -> SUBSTITUTE
+    u'S'        #  0xE2 -> LATIN CAPITAL LETTER S
+    u'T'        #  0xE3 -> LATIN CAPITAL LETTER T
+    u'U'        #  0xE4 -> LATIN CAPITAL LETTER U
+    u'V'        #  0xE5 -> LATIN CAPITAL LETTER V
+    u'W'        #  0xE6 -> LATIN CAPITAL LETTER W
+    u'X'        #  0xE7 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0xE8 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0xE9 -> LATIN CAPITAL LETTER Z
+    u'\xb2'     #  0xEA -> SUPERSCRIPT TWO
+    u'\xa7'     #  0xEB -> SECTION SIGN
+    u'\x1a'     #  0xEC -> SUBSTITUTE
+    u'\x1a'     #  0xED -> SUBSTITUTE
+    u'\xab'     #  0xEE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xEF -> NOT SIGN
+    u'0'        #  0xF0 -> DIGIT ZERO
+    u'1'        #  0xF1 -> DIGIT ONE
+    u'2'        #  0xF2 -> DIGIT TWO
+    u'3'        #  0xF3 -> DIGIT THREE
+    u'4'        #  0xF4 -> DIGIT FOUR
+    u'5'        #  0xF5 -> DIGIT FIVE
+    u'6'        #  0xF6 -> DIGIT SIX
+    u'7'        #  0xF7 -> DIGIT SEVEN
+    u'8'        #  0xF8 -> DIGIT EIGHT
+    u'9'        #  0xF9 -> DIGIT NINE
+    u'\xb3'     #  0xFA -> SUPERSCRIPT THREE
+    u'\xa9'     #  0xFB -> COPYRIGHT SIGN
+    u'\x1a'     #  0xFC -> SUBSTITUTE
+    u'\x1a'     #  0xFD -> SUBSTITUTE
+    u'\xbb'     #  0xFE -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\x9f'     #  0xFF -> CONTROL
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/cp932.py b/src/main/resources/PythonLibs/encodings/cp932.py
new file mode 100644
index 0000000000000000000000000000000000000000..e01f59b719057657c65f739e43fc0400722293e6
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp932.py
@@ -0,0 +1,39 @@
+#
+# cp932.py: Python Unicode Codec for CP932
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_jp, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_jp.getcodec('cp932')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp932',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/cp949.py b/src/main/resources/PythonLibs/encodings/cp949.py
new file mode 100644
index 0000000000000000000000000000000000000000..627c87125e2affe4bc75eae769f901a54e2f92fb
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp949.py
@@ -0,0 +1,39 @@
+#
+# cp949.py: Python Unicode Codec for CP949
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_kr, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_kr.getcodec('cp949')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp949',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/cp950.py b/src/main/resources/PythonLibs/encodings/cp950.py
new file mode 100644
index 0000000000000000000000000000000000000000..39eec5ed0ddef9579cf1be928acfd1a2cf37d39b
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/cp950.py
@@ -0,0 +1,39 @@
+#
+# cp950.py: Python Unicode Codec for CP950
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_tw, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_tw.getcodec('cp950')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='cp950',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/euc_jis_2004.py b/src/main/resources/PythonLibs/encodings/euc_jis_2004.py
new file mode 100644
index 0000000000000000000000000000000000000000..72b87aea68862f2fabbb7b30274e683a6654d4ae
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/euc_jis_2004.py
@@ -0,0 +1,39 @@
+#
+# euc_jis_2004.py: Python Unicode Codec for EUC_JIS_2004
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_jp, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_jp.getcodec('euc_jis_2004')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='euc_jis_2004',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/euc_jisx0213.py b/src/main/resources/PythonLibs/encodings/euc_jisx0213.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc47d04112a187d585dce4af4bd76a38e89e0f51
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/euc_jisx0213.py
@@ -0,0 +1,39 @@
+#
+# euc_jisx0213.py: Python Unicode Codec for EUC_JISX0213
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_jp, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_jp.getcodec('euc_jisx0213')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='euc_jisx0213',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/euc_jp.py b/src/main/resources/PythonLibs/encodings/euc_jp.py
new file mode 100644
index 0000000000000000000000000000000000000000..7bcbe4147f2ad49c6a0d3a9cc6eb5417cdabdf2d
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/euc_jp.py
@@ -0,0 +1,39 @@
+#
+# euc_jp.py: Python Unicode Codec for EUC_JP
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_jp, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_jp.getcodec('euc_jp')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='euc_jp',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/euc_kr.py b/src/main/resources/PythonLibs/encodings/euc_kr.py
new file mode 100644
index 0000000000000000000000000000000000000000..c1fb1260e879f0c42491be24b6a0cd0b8a365122
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/euc_kr.py
@@ -0,0 +1,39 @@
+#
+# euc_kr.py: Python Unicode Codec for EUC_KR
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_kr, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_kr.getcodec('euc_kr')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='euc_kr',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/gb18030.py b/src/main/resources/PythonLibs/encodings/gb18030.py
new file mode 100644
index 0000000000000000000000000000000000000000..34fb6c366a76147b9e2b4a62f886b2a91eb6add8
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/gb18030.py
@@ -0,0 +1,39 @@
+#
+# gb18030.py: Python Unicode Codec for GB18030
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_cn, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_cn.getcodec('gb18030')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='gb18030',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/gb2312.py b/src/main/resources/PythonLibs/encodings/gb2312.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c3b837d618ecd262007eec7d3bd786209e91c06
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/gb2312.py
@@ -0,0 +1,39 @@
+#
+# gb2312.py: Python Unicode Codec for GB2312
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_cn, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_cn.getcodec('gb2312')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='gb2312',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/gbk.py b/src/main/resources/PythonLibs/encodings/gbk.py
new file mode 100644
index 0000000000000000000000000000000000000000..1b45db89859cdf58931436a954e7eb304b5962b8
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/gbk.py
@@ -0,0 +1,39 @@
+#
+# gbk.py: Python Unicode Codec for GBK
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_cn, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_cn.getcodec('gbk')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='gbk',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/hex_codec.py b/src/main/resources/PythonLibs/encodings/hex_codec.py
new file mode 100644
index 0000000000000000000000000000000000000000..91b38d952e1f9e638e34b867ec74fa4eb2323e9f
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/hex_codec.py
@@ -0,0 +1,79 @@
+""" Python 'hex_codec' Codec - 2-digit hex content transfer encoding
+
+    Unlike most of the other codecs which target Unicode, this codec
+    will return Python string objects for both encode and decode.
+
+    Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+"""
+import codecs, binascii
+
+### Codec APIs
+
+def hex_encode(input,errors='strict'):
+
+    """ Encodes the object input and returns a tuple (output
+        object, length consumed).
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    output = binascii.b2a_hex(input)
+    return (output, len(input))
+
+def hex_decode(input,errors='strict'):
+
+    """ Decodes the object input and returns a tuple (output
+        object, length consumed).
+
+        input must be an object which provides the bf_getreadbuf
+        buffer slot. Python strings, buffer objects and memory
+        mapped files are examples of objects providing this slot.
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    output = binascii.a2b_hex(input)
+    return (output, len(input))
+
+class Codec(codecs.Codec):
+
+    def encode(self, input,errors='strict'):
+        return hex_encode(input,errors)
+    def decode(self, input,errors='strict'):
+        return hex_decode(input,errors)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        assert self.errors == 'strict'
+        return binascii.b2a_hex(input)
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        assert self.errors == 'strict'
+        return binascii.a2b_hex(input)
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='hex',
+        encode=hex_encode,
+        decode=hex_decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/hp_roman8.py b/src/main/resources/PythonLibs/encodings/hp_roman8.py
new file mode 100644
index 0000000000000000000000000000000000000000..dbaaa72d76dd0e8fdbac4b88319e861fe198f82a
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/hp_roman8.py
@@ -0,0 +1,152 @@
+""" Python Character Mapping Codec generated from 'hp_roman8.txt' with gencodec.py.
+
+    Based on data from ftp://dkuug.dk/i18n/charmaps/HP-ROMAN8 (Keld Simonsen)
+
+    Original source: LaserJet IIP Printer User's Manual HP part no
+    33471-90901, Hewlet-Packard, June 1989.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_map)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_map)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='hp-roman8',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+        0x00a1: 0x00c0, #       LATIN CAPITAL LETTER A WITH GRAVE
+        0x00a2: 0x00c2, #       LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+        0x00a3: 0x00c8, #       LATIN CAPITAL LETTER E WITH GRAVE
+        0x00a4: 0x00ca, #       LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+        0x00a5: 0x00cb, #       LATIN CAPITAL LETTER E WITH DIAERESIS
+        0x00a6: 0x00ce, #       LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+        0x00a7: 0x00cf, #       LATIN CAPITAL LETTER I WITH DIAERESIS
+        0x00a8: 0x00b4, #       ACUTE ACCENT
+        0x00a9: 0x02cb, #       MODIFIER LETTER GRAVE ACCENT (Mandarin Chinese fourth tone)
+        0x00aa: 0x02c6, #       MODIFIER LETTER CIRCUMFLEX ACCENT
+        0x00ab: 0x00a8, #       DIAERESIS
+        0x00ac: 0x02dc, #       SMALL TILDE
+        0x00ad: 0x00d9, #       LATIN CAPITAL LETTER U WITH GRAVE
+        0x00ae: 0x00db, #       LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+        0x00af: 0x20a4, #       LIRA SIGN
+        0x00b0: 0x00af, #       MACRON
+        0x00b1: 0x00dd, #       LATIN CAPITAL LETTER Y WITH ACUTE
+        0x00b2: 0x00fd, #       LATIN SMALL LETTER Y WITH ACUTE
+        0x00b3: 0x00b0, #       DEGREE SIGN
+        0x00b4: 0x00c7, #       LATIN CAPITAL LETTER C WITH CEDILLA
+        0x00b5: 0x00e7, #       LATIN SMALL LETTER C WITH CEDILLA
+        0x00b6: 0x00d1, #       LATIN CAPITAL LETTER N WITH TILDE
+        0x00b7: 0x00f1, #       LATIN SMALL LETTER N WITH TILDE
+        0x00b8: 0x00a1, #       INVERTED EXCLAMATION MARK
+        0x00b9: 0x00bf, #       INVERTED QUESTION MARK
+        0x00ba: 0x00a4, #       CURRENCY SIGN
+        0x00bb: 0x00a3, #       POUND SIGN
+        0x00bc: 0x00a5, #       YEN SIGN
+        0x00bd: 0x00a7, #       SECTION SIGN
+        0x00be: 0x0192, #       LATIN SMALL LETTER F WITH HOOK
+        0x00bf: 0x00a2, #       CENT SIGN
+        0x00c0: 0x00e2, #       LATIN SMALL LETTER A WITH CIRCUMFLEX
+        0x00c1: 0x00ea, #       LATIN SMALL LETTER E WITH CIRCUMFLEX
+        0x00c2: 0x00f4, #       LATIN SMALL LETTER O WITH CIRCUMFLEX
+        0x00c3: 0x00fb, #       LATIN SMALL LETTER U WITH CIRCUMFLEX
+        0x00c4: 0x00e1, #       LATIN SMALL LETTER A WITH ACUTE
+        0x00c5: 0x00e9, #       LATIN SMALL LETTER E WITH ACUTE
+        0x00c6: 0x00f3, #       LATIN SMALL LETTER O WITH ACUTE
+        0x00c7: 0x00fa, #       LATIN SMALL LETTER U WITH ACUTE
+        0x00c8: 0x00e0, #       LATIN SMALL LETTER A WITH GRAVE
+        0x00c9: 0x00e8, #       LATIN SMALL LETTER E WITH GRAVE
+        0x00ca: 0x00f2, #       LATIN SMALL LETTER O WITH GRAVE
+        0x00cb: 0x00f9, #       LATIN SMALL LETTER U WITH GRAVE
+        0x00cc: 0x00e4, #       LATIN SMALL LETTER A WITH DIAERESIS
+        0x00cd: 0x00eb, #       LATIN SMALL LETTER E WITH DIAERESIS
+        0x00ce: 0x00f6, #       LATIN SMALL LETTER O WITH DIAERESIS
+        0x00cf: 0x00fc, #       LATIN SMALL LETTER U WITH DIAERESIS
+        0x00d0: 0x00c5, #       LATIN CAPITAL LETTER A WITH RING ABOVE
+        0x00d1: 0x00ee, #       LATIN SMALL LETTER I WITH CIRCUMFLEX
+        0x00d2: 0x00d8, #       LATIN CAPITAL LETTER O WITH STROKE
+        0x00d3: 0x00c6, #       LATIN CAPITAL LETTER AE
+        0x00d4: 0x00e5, #       LATIN SMALL LETTER A WITH RING ABOVE
+        0x00d5: 0x00ed, #       LATIN SMALL LETTER I WITH ACUTE
+        0x00d6: 0x00f8, #       LATIN SMALL LETTER O WITH STROKE
+        0x00d7: 0x00e6, #       LATIN SMALL LETTER AE
+        0x00d8: 0x00c4, #       LATIN CAPITAL LETTER A WITH DIAERESIS
+        0x00d9: 0x00ec, #       LATIN SMALL LETTER I WITH GRAVE
+        0x00da: 0x00d6, #       LATIN CAPITAL LETTER O WITH DIAERESIS
+        0x00db: 0x00dc, #       LATIN CAPITAL LETTER U WITH DIAERESIS
+        0x00dc: 0x00c9, #       LATIN CAPITAL LETTER E WITH ACUTE
+        0x00dd: 0x00ef, #       LATIN SMALL LETTER I WITH DIAERESIS
+        0x00de: 0x00df, #       LATIN SMALL LETTER SHARP S (German)
+        0x00df: 0x00d4, #       LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+        0x00e0: 0x00c1, #       LATIN CAPITAL LETTER A WITH ACUTE
+        0x00e1: 0x00c3, #       LATIN CAPITAL LETTER A WITH TILDE
+        0x00e2: 0x00e3, #       LATIN SMALL LETTER A WITH TILDE
+        0x00e3: 0x00d0, #       LATIN CAPITAL LETTER ETH (Icelandic)
+        0x00e4: 0x00f0, #       LATIN SMALL LETTER ETH (Icelandic)
+        0x00e5: 0x00cd, #       LATIN CAPITAL LETTER I WITH ACUTE
+        0x00e6: 0x00cc, #       LATIN CAPITAL LETTER I WITH GRAVE
+        0x00e7: 0x00d3, #       LATIN CAPITAL LETTER O WITH ACUTE
+        0x00e8: 0x00d2, #       LATIN CAPITAL LETTER O WITH GRAVE
+        0x00e9: 0x00d5, #       LATIN CAPITAL LETTER O WITH TILDE
+        0x00ea: 0x00f5, #       LATIN SMALL LETTER O WITH TILDE
+        0x00eb: 0x0160, #       LATIN CAPITAL LETTER S WITH CARON
+        0x00ec: 0x0161, #       LATIN SMALL LETTER S WITH CARON
+        0x00ed: 0x00da, #       LATIN CAPITAL LETTER U WITH ACUTE
+        0x00ee: 0x0178, #       LATIN CAPITAL LETTER Y WITH DIAERESIS
+        0x00ef: 0x00ff, #       LATIN SMALL LETTER Y WITH DIAERESIS
+        0x00f0: 0x00de, #       LATIN CAPITAL LETTER THORN (Icelandic)
+        0x00f1: 0x00fe, #       LATIN SMALL LETTER THORN (Icelandic)
+        0x00f2: 0x00b7, #       MIDDLE DOT
+        0x00f3: 0x00b5, #       MICRO SIGN
+        0x00f4: 0x00b6, #       PILCROW SIGN
+        0x00f5: 0x00be, #       VULGAR FRACTION THREE QUARTERS
+        0x00f6: 0x2014, #       EM DASH
+        0x00f7: 0x00bc, #       VULGAR FRACTION ONE QUARTER
+        0x00f8: 0x00bd, #       VULGAR FRACTION ONE HALF
+        0x00f9: 0x00aa, #       FEMININE ORDINAL INDICATOR
+        0x00fa: 0x00ba, #       MASCULINE ORDINAL INDICATOR
+        0x00fb: 0x00ab, #       LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+        0x00fc: 0x25a0, #       BLACK SQUARE
+        0x00fd: 0x00bb, #       RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+        0x00fe: 0x00b1, #       PLUS-MINUS SIGN
+        0x00ff: None,
+})
+
+### Encoding Map
+
+encoding_map = codecs.make_encoding_map(decoding_map)
diff --git a/src/main/resources/PythonLibs/encodings/hz.py b/src/main/resources/PythonLibs/encodings/hz.py
new file mode 100644
index 0000000000000000000000000000000000000000..383442a3c9ac9ae5d093d972f1ff26fe758897d5
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/hz.py
@@ -0,0 +1,39 @@
+#
+# hz.py: Python Unicode Codec for HZ
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_cn, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_cn.getcodec('hz')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='hz',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/idna.py b/src/main/resources/PythonLibs/encodings/idna.py
new file mode 100644
index 0000000000000000000000000000000000000000..23c91caad119996f349f571a4d5637e3bdc3b127
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/idna.py
@@ -0,0 +1,173 @@
+import codecs
+import re
+from com.ibm.icu.text import StringPrep, StringPrepParseException
+from java.net import IDN
+
+
+# IDNA section 3.1
+dots = re.compile(u"[\u002E\u3002\uFF0E\uFF61]")
+
+
+def nameprep(label):
+    try:
+        return StringPrep.getInstance(StringPrep.RFC3491_NAMEPREP).prepare(
+            label, StringPrep.ALLOW_UNASSIGNED)
+    except StringPrepParseException, e:
+        raise UnicodeError("Invalid character")
+    
+
+def ToASCII(label):
+    return IDN.toASCII(label)
+
+
+def ToUnicode(label):
+    return IDN.toUnicode(label)
+
+
+# BELOW is the implementation shared with CPython. TODO we should merge.
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+    def encode(self,input,errors='strict'):
+
+        if errors != 'strict':
+            # IDNA is quite clear that implementations must be strict
+            raise UnicodeError("unsupported error handling "+errors)
+
+        if not input:
+            return "", 0
+
+        result = []
+        labels = dots.split(input)
+        if labels and len(labels[-1])==0:
+            trailing_dot = '.'
+            del labels[-1]
+        else:
+            trailing_dot = ''
+        for label in labels:
+            result.append(ToASCII(label))
+        # Join with U+002E
+        return ".".join(result)+trailing_dot, len(input)
+
+    def decode(self,input,errors='strict'):
+
+        if errors != 'strict':
+            raise UnicodeError("Unsupported error handling "+errors)
+
+        if not input:
+            return u"", 0
+
+        # IDNA allows decoding to operate on Unicode strings, too.
+        if isinstance(input, unicode):
+            labels = dots.split(input)
+        else:
+            # Must be ASCII string
+            input = str(input)
+            unicode(input, "ascii")
+            labels = input.split(".")
+
+        if labels and len(labels[-1]) == 0:
+            trailing_dot = u'.'
+            del labels[-1]
+        else:
+            trailing_dot = u''
+
+        result = []
+        for label in labels:
+            result.append(ToUnicode(label))
+
+        return u".".join(result)+trailing_dot, len(input)
+
+class IncrementalEncoder(codecs.BufferedIncrementalEncoder):
+    def _buffer_encode(self, input, errors, final):
+        if errors != 'strict':
+            # IDNA is quite clear that implementations must be strict
+            raise UnicodeError("unsupported error handling "+errors)
+
+        if not input:
+            return ("", 0)
+
+        labels = dots.split(input)
+        trailing_dot = u''
+        if labels:
+            if not labels[-1]:
+                trailing_dot = '.'
+                del labels[-1]
+            elif not final:
+                # Keep potentially unfinished label until the next call
+                del labels[-1]
+                if labels:
+                    trailing_dot = '.'
+
+        result = []
+        size = 0
+        for label in labels:
+            result.append(ToASCII(label))
+            if size:
+                size += 1
+            size += len(label)
+
+        # Join with U+002E
+        result = ".".join(result) + trailing_dot
+        size += len(trailing_dot)
+        return (result, size)
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    def _buffer_decode(self, input, errors, final):
+        if errors != 'strict':
+            raise UnicodeError("Unsupported error handling "+errors)
+
+        if not input:
+            return (u"", 0)
+
+        # IDNA allows decoding to operate on Unicode strings, too.
+        if isinstance(input, unicode):
+            labels = dots.split(input)
+        else:
+            # Must be ASCII string
+            input = str(input)
+            unicode(input, "ascii")
+            labels = input.split(".")
+
+        trailing_dot = u''
+        if labels:
+            if not labels[-1]:
+                trailing_dot = u'.'
+                del labels[-1]
+            elif not final:
+                # Keep potentially unfinished label until the next call
+                del labels[-1]
+                if labels:
+                    trailing_dot = u'.'
+
+        result = []
+        size = 0
+        for label in labels:
+            result.append(ToUnicode(label))
+            if size:
+                size += 1
+            size += len(label)
+
+        result = u".".join(result) + trailing_dot
+        size += len(trailing_dot)
+        return (result, size)
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='idna',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/iso2022_jp.py b/src/main/resources/PythonLibs/encodings/iso2022_jp.py
new file mode 100644
index 0000000000000000000000000000000000000000..ab0406069356e4dfd7cfcc4a981535c40c9c5574
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso2022_jp.py
@@ -0,0 +1,39 @@
+#
+# iso2022_jp.py: Python Unicode Codec for ISO2022_JP
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_iso2022, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_iso2022.getcodec('iso2022_jp')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso2022_jp',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/iso2022_jp_1.py b/src/main/resources/PythonLibs/encodings/iso2022_jp_1.py
new file mode 100644
index 0000000000000000000000000000000000000000..997044dc3787496be0ed70f2ed1b63d9ebe1b0ac
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso2022_jp_1.py
@@ -0,0 +1,39 @@
+#
+# iso2022_jp_1.py: Python Unicode Codec for ISO2022_JP_1
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_iso2022, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_iso2022.getcodec('iso2022_jp_1')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso2022_jp_1',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/iso2022_jp_2.py b/src/main/resources/PythonLibs/encodings/iso2022_jp_2.py
new file mode 100644
index 0000000000000000000000000000000000000000..9106bf762512fdd3e9deb73cba91529ab0db94ac
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso2022_jp_2.py
@@ -0,0 +1,39 @@
+#
+# iso2022_jp_2.py: Python Unicode Codec for ISO2022_JP_2
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_iso2022, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_iso2022.getcodec('iso2022_jp_2')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso2022_jp_2',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/iso2022_jp_2004.py b/src/main/resources/PythonLibs/encodings/iso2022_jp_2004.py
new file mode 100644
index 0000000000000000000000000000000000000000..40198bf098570be21f67335c42fbf9f956204725
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso2022_jp_2004.py
@@ -0,0 +1,39 @@
+#
+# iso2022_jp_2004.py: Python Unicode Codec for ISO2022_JP_2004
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_iso2022, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_iso2022.getcodec('iso2022_jp_2004')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso2022_jp_2004',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/iso2022_jp_3.py b/src/main/resources/PythonLibs/encodings/iso2022_jp_3.py
new file mode 100644
index 0000000000000000000000000000000000000000..346e08beccbbafd347371743ec89333370d3b083
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso2022_jp_3.py
@@ -0,0 +1,39 @@
+#
+# iso2022_jp_3.py: Python Unicode Codec for ISO2022_JP_3
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_iso2022, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_iso2022.getcodec('iso2022_jp_3')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso2022_jp_3',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/iso2022_jp_ext.py b/src/main/resources/PythonLibs/encodings/iso2022_jp_ext.py
new file mode 100644
index 0000000000000000000000000000000000000000..752bab9813a094e9446b084ae90957290f1324c0
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso2022_jp_ext.py
@@ -0,0 +1,39 @@
+#
+# iso2022_jp_ext.py: Python Unicode Codec for ISO2022_JP_EXT
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_iso2022, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_iso2022.getcodec('iso2022_jp_ext')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso2022_jp_ext',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/iso2022_kr.py b/src/main/resources/PythonLibs/encodings/iso2022_kr.py
new file mode 100644
index 0000000000000000000000000000000000000000..bf7018763eae38729d6c206379467f36e41910c3
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso2022_kr.py
@@ -0,0 +1,39 @@
+#
+# iso2022_kr.py: Python Unicode Codec for ISO2022_KR
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_iso2022, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_iso2022.getcodec('iso2022_kr')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso2022_kr',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_1.py b/src/main/resources/PythonLibs/encodings/iso8859_1.py
new file mode 100644
index 0000000000000000000000000000000000000000..71bc13fcbb3d5a9e2907e7b7f097d13c8425eb75
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_1.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_1 generated from 'MAPPINGS/ISO8859/8859-1.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-1',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\xa1'     #  0xA1 -> INVERTED EXCLAMATION MARK
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\xaa'     #  0xAA -> FEMININE ORDINAL INDICATOR
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\xba'     #  0xBA -> MASCULINE ORDINAL INDICATOR
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\xbf'     #  0xBF -> INVERTED QUESTION MARK
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc3'     #  0xC3 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcc'     #  0xCC -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xd0'     #  0xD0 -> LATIN CAPITAL LETTER ETH (Icelandic)
+    u'\xd1'     #  0xD1 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd2'     #  0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xdd'     #  0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xde'     #  0xDE -> LATIN CAPITAL LETTER THORN (Icelandic)
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S (German)
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0xE3 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xec'     #  0xEC -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf0'     #  0xF0 -> LATIN SMALL LETTER ETH (Icelandic)
+    u'\xf1'     #  0xF1 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf2'     #  0xF2 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xfd'     #  0xFD -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xfe'     #  0xFE -> LATIN SMALL LETTER THORN (Icelandic)
+    u'\xff'     #  0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_10.py b/src/main/resources/PythonLibs/encodings/iso8859_10.py
new file mode 100644
index 0000000000000000000000000000000000000000..757e5c5eb9a3cd45f7ef66fc335b6889f740384b
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_10.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_10 generated from 'MAPPINGS/ISO8859/8859-10.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-10',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0104'   #  0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\u0112'   #  0xA2 -> LATIN CAPITAL LETTER E WITH MACRON
+    u'\u0122'   #  0xA3 -> LATIN CAPITAL LETTER G WITH CEDILLA
+    u'\u012a'   #  0xA4 -> LATIN CAPITAL LETTER I WITH MACRON
+    u'\u0128'   #  0xA5 -> LATIN CAPITAL LETTER I WITH TILDE
+    u'\u0136'   #  0xA6 -> LATIN CAPITAL LETTER K WITH CEDILLA
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\u013b'   #  0xA8 -> LATIN CAPITAL LETTER L WITH CEDILLA
+    u'\u0110'   #  0xA9 -> LATIN CAPITAL LETTER D WITH STROKE
+    u'\u0160'   #  0xAA -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u0166'   #  0xAB -> LATIN CAPITAL LETTER T WITH STROKE
+    u'\u017d'   #  0xAC -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\u016a'   #  0xAE -> LATIN CAPITAL LETTER U WITH MACRON
+    u'\u014a'   #  0xAF -> LATIN CAPITAL LETTER ENG
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\u0105'   #  0xB1 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u0113'   #  0xB2 -> LATIN SMALL LETTER E WITH MACRON
+    u'\u0123'   #  0xB3 -> LATIN SMALL LETTER G WITH CEDILLA
+    u'\u012b'   #  0xB4 -> LATIN SMALL LETTER I WITH MACRON
+    u'\u0129'   #  0xB5 -> LATIN SMALL LETTER I WITH TILDE
+    u'\u0137'   #  0xB6 -> LATIN SMALL LETTER K WITH CEDILLA
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\u013c'   #  0xB8 -> LATIN SMALL LETTER L WITH CEDILLA
+    u'\u0111'   #  0xB9 -> LATIN SMALL LETTER D WITH STROKE
+    u'\u0161'   #  0xBA -> LATIN SMALL LETTER S WITH CARON
+    u'\u0167'   #  0xBB -> LATIN SMALL LETTER T WITH STROKE
+    u'\u017e'   #  0xBC -> LATIN SMALL LETTER Z WITH CARON
+    u'\u2015'   #  0xBD -> HORIZONTAL BAR
+    u'\u016b'   #  0xBE -> LATIN SMALL LETTER U WITH MACRON
+    u'\u014b'   #  0xBF -> LATIN SMALL LETTER ENG
+    u'\u0100'   #  0xC0 -> LATIN CAPITAL LETTER A WITH MACRON
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc3'     #  0xC3 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\u012e'   #  0xC7 -> LATIN CAPITAL LETTER I WITH OGONEK
+    u'\u010c'   #  0xC8 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\u0118'   #  0xCA -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\u0116'   #  0xCC -> LATIN CAPITAL LETTER E WITH DOT ABOVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xd0'     #  0xD0 -> LATIN CAPITAL LETTER ETH (Icelandic)
+    u'\u0145'   #  0xD1 -> LATIN CAPITAL LETTER N WITH CEDILLA
+    u'\u014c'   #  0xD2 -> LATIN CAPITAL LETTER O WITH MACRON
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\u0168'   #  0xD7 -> LATIN CAPITAL LETTER U WITH TILDE
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u0172'   #  0xD9 -> LATIN CAPITAL LETTER U WITH OGONEK
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xdd'     #  0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xde'     #  0xDE -> LATIN CAPITAL LETTER THORN (Icelandic)
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S (German)
+    u'\u0101'   #  0xE0 -> LATIN SMALL LETTER A WITH MACRON
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0xE3 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\u012f'   #  0xE7 -> LATIN SMALL LETTER I WITH OGONEK
+    u'\u010d'   #  0xE8 -> LATIN SMALL LETTER C WITH CARON
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\u0119'   #  0xEA -> LATIN SMALL LETTER E WITH OGONEK
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\u0117'   #  0xEC -> LATIN SMALL LETTER E WITH DOT ABOVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf0'     #  0xF0 -> LATIN SMALL LETTER ETH (Icelandic)
+    u'\u0146'   #  0xF1 -> LATIN SMALL LETTER N WITH CEDILLA
+    u'\u014d'   #  0xF2 -> LATIN SMALL LETTER O WITH MACRON
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\u0169'   #  0xF7 -> LATIN SMALL LETTER U WITH TILDE
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\u0173'   #  0xF9 -> LATIN SMALL LETTER U WITH OGONEK
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xfd'     #  0xFD -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xfe'     #  0xFE -> LATIN SMALL LETTER THORN (Icelandic)
+    u'\u0138'   #  0xFF -> LATIN SMALL LETTER KRA
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_11.py b/src/main/resources/PythonLibs/encodings/iso8859_11.py
new file mode 100644
index 0000000000000000000000000000000000000000..27ece8dc7b76ee71ae01ef2d7dbc8dff9ea423fb
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_11.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_11 generated from 'MAPPINGS/ISO8859/8859-11.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-11',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0e01'   #  0xA1 -> THAI CHARACTER KO KAI
+    u'\u0e02'   #  0xA2 -> THAI CHARACTER KHO KHAI
+    u'\u0e03'   #  0xA3 -> THAI CHARACTER KHO KHUAT
+    u'\u0e04'   #  0xA4 -> THAI CHARACTER KHO KHWAI
+    u'\u0e05'   #  0xA5 -> THAI CHARACTER KHO KHON
+    u'\u0e06'   #  0xA6 -> THAI CHARACTER KHO RAKHANG
+    u'\u0e07'   #  0xA7 -> THAI CHARACTER NGO NGU
+    u'\u0e08'   #  0xA8 -> THAI CHARACTER CHO CHAN
+    u'\u0e09'   #  0xA9 -> THAI CHARACTER CHO CHING
+    u'\u0e0a'   #  0xAA -> THAI CHARACTER CHO CHANG
+    u'\u0e0b'   #  0xAB -> THAI CHARACTER SO SO
+    u'\u0e0c'   #  0xAC -> THAI CHARACTER CHO CHOE
+    u'\u0e0d'   #  0xAD -> THAI CHARACTER YO YING
+    u'\u0e0e'   #  0xAE -> THAI CHARACTER DO CHADA
+    u'\u0e0f'   #  0xAF -> THAI CHARACTER TO PATAK
+    u'\u0e10'   #  0xB0 -> THAI CHARACTER THO THAN
+    u'\u0e11'   #  0xB1 -> THAI CHARACTER THO NANGMONTHO
+    u'\u0e12'   #  0xB2 -> THAI CHARACTER THO PHUTHAO
+    u'\u0e13'   #  0xB3 -> THAI CHARACTER NO NEN
+    u'\u0e14'   #  0xB4 -> THAI CHARACTER DO DEK
+    u'\u0e15'   #  0xB5 -> THAI CHARACTER TO TAO
+    u'\u0e16'   #  0xB6 -> THAI CHARACTER THO THUNG
+    u'\u0e17'   #  0xB7 -> THAI CHARACTER THO THAHAN
+    u'\u0e18'   #  0xB8 -> THAI CHARACTER THO THONG
+    u'\u0e19'   #  0xB9 -> THAI CHARACTER NO NU
+    u'\u0e1a'   #  0xBA -> THAI CHARACTER BO BAIMAI
+    u'\u0e1b'   #  0xBB -> THAI CHARACTER PO PLA
+    u'\u0e1c'   #  0xBC -> THAI CHARACTER PHO PHUNG
+    u'\u0e1d'   #  0xBD -> THAI CHARACTER FO FA
+    u'\u0e1e'   #  0xBE -> THAI CHARACTER PHO PHAN
+    u'\u0e1f'   #  0xBF -> THAI CHARACTER FO FAN
+    u'\u0e20'   #  0xC0 -> THAI CHARACTER PHO SAMPHAO
+    u'\u0e21'   #  0xC1 -> THAI CHARACTER MO MA
+    u'\u0e22'   #  0xC2 -> THAI CHARACTER YO YAK
+    u'\u0e23'   #  0xC3 -> THAI CHARACTER RO RUA
+    u'\u0e24'   #  0xC4 -> THAI CHARACTER RU
+    u'\u0e25'   #  0xC5 -> THAI CHARACTER LO LING
+    u'\u0e26'   #  0xC6 -> THAI CHARACTER LU
+    u'\u0e27'   #  0xC7 -> THAI CHARACTER WO WAEN
+    u'\u0e28'   #  0xC8 -> THAI CHARACTER SO SALA
+    u'\u0e29'   #  0xC9 -> THAI CHARACTER SO RUSI
+    u'\u0e2a'   #  0xCA -> THAI CHARACTER SO SUA
+    u'\u0e2b'   #  0xCB -> THAI CHARACTER HO HIP
+    u'\u0e2c'   #  0xCC -> THAI CHARACTER LO CHULA
+    u'\u0e2d'   #  0xCD -> THAI CHARACTER O ANG
+    u'\u0e2e'   #  0xCE -> THAI CHARACTER HO NOKHUK
+    u'\u0e2f'   #  0xCF -> THAI CHARACTER PAIYANNOI
+    u'\u0e30'   #  0xD0 -> THAI CHARACTER SARA A
+    u'\u0e31'   #  0xD1 -> THAI CHARACTER MAI HAN-AKAT
+    u'\u0e32'   #  0xD2 -> THAI CHARACTER SARA AA
+    u'\u0e33'   #  0xD3 -> THAI CHARACTER SARA AM
+    u'\u0e34'   #  0xD4 -> THAI CHARACTER SARA I
+    u'\u0e35'   #  0xD5 -> THAI CHARACTER SARA II
+    u'\u0e36'   #  0xD6 -> THAI CHARACTER SARA UE
+    u'\u0e37'   #  0xD7 -> THAI CHARACTER SARA UEE
+    u'\u0e38'   #  0xD8 -> THAI CHARACTER SARA U
+    u'\u0e39'   #  0xD9 -> THAI CHARACTER SARA UU
+    u'\u0e3a'   #  0xDA -> THAI CHARACTER PHINTHU
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\u0e3f'   #  0xDF -> THAI CURRENCY SYMBOL BAHT
+    u'\u0e40'   #  0xE0 -> THAI CHARACTER SARA E
+    u'\u0e41'   #  0xE1 -> THAI CHARACTER SARA AE
+    u'\u0e42'   #  0xE2 -> THAI CHARACTER SARA O
+    u'\u0e43'   #  0xE3 -> THAI CHARACTER SARA AI MAIMUAN
+    u'\u0e44'   #  0xE4 -> THAI CHARACTER SARA AI MAIMALAI
+    u'\u0e45'   #  0xE5 -> THAI CHARACTER LAKKHANGYAO
+    u'\u0e46'   #  0xE6 -> THAI CHARACTER MAIYAMOK
+    u'\u0e47'   #  0xE7 -> THAI CHARACTER MAITAIKHU
+    u'\u0e48'   #  0xE8 -> THAI CHARACTER MAI EK
+    u'\u0e49'   #  0xE9 -> THAI CHARACTER MAI THO
+    u'\u0e4a'   #  0xEA -> THAI CHARACTER MAI TRI
+    u'\u0e4b'   #  0xEB -> THAI CHARACTER MAI CHATTAWA
+    u'\u0e4c'   #  0xEC -> THAI CHARACTER THANTHAKHAT
+    u'\u0e4d'   #  0xED -> THAI CHARACTER NIKHAHIT
+    u'\u0e4e'   #  0xEE -> THAI CHARACTER YAMAKKAN
+    u'\u0e4f'   #  0xEF -> THAI CHARACTER FONGMAN
+    u'\u0e50'   #  0xF0 -> THAI DIGIT ZERO
+    u'\u0e51'   #  0xF1 -> THAI DIGIT ONE
+    u'\u0e52'   #  0xF2 -> THAI DIGIT TWO
+    u'\u0e53'   #  0xF3 -> THAI DIGIT THREE
+    u'\u0e54'   #  0xF4 -> THAI DIGIT FOUR
+    u'\u0e55'   #  0xF5 -> THAI DIGIT FIVE
+    u'\u0e56'   #  0xF6 -> THAI DIGIT SIX
+    u'\u0e57'   #  0xF7 -> THAI DIGIT SEVEN
+    u'\u0e58'   #  0xF8 -> THAI DIGIT EIGHT
+    u'\u0e59'   #  0xF9 -> THAI DIGIT NINE
+    u'\u0e5a'   #  0xFA -> THAI CHARACTER ANGKHANKHU
+    u'\u0e5b'   #  0xFB -> THAI CHARACTER KHOMUT
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_13.py b/src/main/resources/PythonLibs/encodings/iso8859_13.py
new file mode 100644
index 0000000000000000000000000000000000000000..71adb5c19a8851f1aa6c29d4accf1e772023bf80
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_13.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_13 generated from 'MAPPINGS/ISO8859/8859-13.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-13',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u201d'   #  0xA1 -> RIGHT DOUBLE QUOTATION MARK
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\u201e'   #  0xA5 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xd8'     #  0xA8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u0156'   #  0xAA -> LATIN CAPITAL LETTER R WITH CEDILLA
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xc6'     #  0xAF -> LATIN CAPITAL LETTER AE
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\u201c'   #  0xB4 -> LEFT DOUBLE QUOTATION MARK
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xf8'     #  0xB8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\u0157'   #  0xBA -> LATIN SMALL LETTER R WITH CEDILLA
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\xe6'     #  0xBF -> LATIN SMALL LETTER AE
+    u'\u0104'   #  0xC0 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\u012e'   #  0xC1 -> LATIN CAPITAL LETTER I WITH OGONEK
+    u'\u0100'   #  0xC2 -> LATIN CAPITAL LETTER A WITH MACRON
+    u'\u0106'   #  0xC3 -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\u0118'   #  0xC6 -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\u0112'   #  0xC7 -> LATIN CAPITAL LETTER E WITH MACRON
+    u'\u010c'   #  0xC8 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\u0179'   #  0xCA -> LATIN CAPITAL LETTER Z WITH ACUTE
+    u'\u0116'   #  0xCB -> LATIN CAPITAL LETTER E WITH DOT ABOVE
+    u'\u0122'   #  0xCC -> LATIN CAPITAL LETTER G WITH CEDILLA
+    u'\u0136'   #  0xCD -> LATIN CAPITAL LETTER K WITH CEDILLA
+    u'\u012a'   #  0xCE -> LATIN CAPITAL LETTER I WITH MACRON
+    u'\u013b'   #  0xCF -> LATIN CAPITAL LETTER L WITH CEDILLA
+    u'\u0160'   #  0xD0 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u0143'   #  0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE
+    u'\u0145'   #  0xD2 -> LATIN CAPITAL LETTER N WITH CEDILLA
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\u014c'   #  0xD4 -> LATIN CAPITAL LETTER O WITH MACRON
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\u0172'   #  0xD8 -> LATIN CAPITAL LETTER U WITH OGONEK
+    u'\u0141'   #  0xD9 -> LATIN CAPITAL LETTER L WITH STROKE
+    u'\u015a'   #  0xDA -> LATIN CAPITAL LETTER S WITH ACUTE
+    u'\u016a'   #  0xDB -> LATIN CAPITAL LETTER U WITH MACRON
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u017b'   #  0xDD -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\u017d'   #  0xDE -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S (German)
+    u'\u0105'   #  0xE0 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u012f'   #  0xE1 -> LATIN SMALL LETTER I WITH OGONEK
+    u'\u0101'   #  0xE2 -> LATIN SMALL LETTER A WITH MACRON
+    u'\u0107'   #  0xE3 -> LATIN SMALL LETTER C WITH ACUTE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\u0119'   #  0xE6 -> LATIN SMALL LETTER E WITH OGONEK
+    u'\u0113'   #  0xE7 -> LATIN SMALL LETTER E WITH MACRON
+    u'\u010d'   #  0xE8 -> LATIN SMALL LETTER C WITH CARON
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\u017a'   #  0xEA -> LATIN SMALL LETTER Z WITH ACUTE
+    u'\u0117'   #  0xEB -> LATIN SMALL LETTER E WITH DOT ABOVE
+    u'\u0123'   #  0xEC -> LATIN SMALL LETTER G WITH CEDILLA
+    u'\u0137'   #  0xED -> LATIN SMALL LETTER K WITH CEDILLA
+    u'\u012b'   #  0xEE -> LATIN SMALL LETTER I WITH MACRON
+    u'\u013c'   #  0xEF -> LATIN SMALL LETTER L WITH CEDILLA
+    u'\u0161'   #  0xF0 -> LATIN SMALL LETTER S WITH CARON
+    u'\u0144'   #  0xF1 -> LATIN SMALL LETTER N WITH ACUTE
+    u'\u0146'   #  0xF2 -> LATIN SMALL LETTER N WITH CEDILLA
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\u014d'   #  0xF4 -> LATIN SMALL LETTER O WITH MACRON
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\u0173'   #  0xF8 -> LATIN SMALL LETTER U WITH OGONEK
+    u'\u0142'   #  0xF9 -> LATIN SMALL LETTER L WITH STROKE
+    u'\u015b'   #  0xFA -> LATIN SMALL LETTER S WITH ACUTE
+    u'\u016b'   #  0xFB -> LATIN SMALL LETTER U WITH MACRON
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u017c'   #  0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\u017e'   #  0xFE -> LATIN SMALL LETTER Z WITH CARON
+    u'\u2019'   #  0xFF -> RIGHT SINGLE QUOTATION MARK
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_14.py b/src/main/resources/PythonLibs/encodings/iso8859_14.py
new file mode 100644
index 0000000000000000000000000000000000000000..56843d5fd09306231dc613dfb4f524a0eccbea88
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_14.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_14 generated from 'MAPPINGS/ISO8859/8859-14.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-14',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u1e02'   #  0xA1 -> LATIN CAPITAL LETTER B WITH DOT ABOVE
+    u'\u1e03'   #  0xA2 -> LATIN SMALL LETTER B WITH DOT ABOVE
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\u010a'   #  0xA4 -> LATIN CAPITAL LETTER C WITH DOT ABOVE
+    u'\u010b'   #  0xA5 -> LATIN SMALL LETTER C WITH DOT ABOVE
+    u'\u1e0a'   #  0xA6 -> LATIN CAPITAL LETTER D WITH DOT ABOVE
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\u1e80'   #  0xA8 -> LATIN CAPITAL LETTER W WITH GRAVE
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u1e82'   #  0xAA -> LATIN CAPITAL LETTER W WITH ACUTE
+    u'\u1e0b'   #  0xAB -> LATIN SMALL LETTER D WITH DOT ABOVE
+    u'\u1ef2'   #  0xAC -> LATIN CAPITAL LETTER Y WITH GRAVE
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\u0178'   #  0xAF -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\u1e1e'   #  0xB0 -> LATIN CAPITAL LETTER F WITH DOT ABOVE
+    u'\u1e1f'   #  0xB1 -> LATIN SMALL LETTER F WITH DOT ABOVE
+    u'\u0120'   #  0xB2 -> LATIN CAPITAL LETTER G WITH DOT ABOVE
+    u'\u0121'   #  0xB3 -> LATIN SMALL LETTER G WITH DOT ABOVE
+    u'\u1e40'   #  0xB4 -> LATIN CAPITAL LETTER M WITH DOT ABOVE
+    u'\u1e41'   #  0xB5 -> LATIN SMALL LETTER M WITH DOT ABOVE
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\u1e56'   #  0xB7 -> LATIN CAPITAL LETTER P WITH DOT ABOVE
+    u'\u1e81'   #  0xB8 -> LATIN SMALL LETTER W WITH GRAVE
+    u'\u1e57'   #  0xB9 -> LATIN SMALL LETTER P WITH DOT ABOVE
+    u'\u1e83'   #  0xBA -> LATIN SMALL LETTER W WITH ACUTE
+    u'\u1e60'   #  0xBB -> LATIN CAPITAL LETTER S WITH DOT ABOVE
+    u'\u1ef3'   #  0xBC -> LATIN SMALL LETTER Y WITH GRAVE
+    u'\u1e84'   #  0xBD -> LATIN CAPITAL LETTER W WITH DIAERESIS
+    u'\u1e85'   #  0xBE -> LATIN SMALL LETTER W WITH DIAERESIS
+    u'\u1e61'   #  0xBF -> LATIN SMALL LETTER S WITH DOT ABOVE
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc3'     #  0xC3 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcc'     #  0xCC -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\u0174'   #  0xD0 -> LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+    u'\xd1'     #  0xD1 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd2'     #  0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\u1e6a'   #  0xD7 -> LATIN CAPITAL LETTER T WITH DOT ABOVE
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xdd'     #  0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\u0176'   #  0xDE -> LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0xE3 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xec'     #  0xEC -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\u0175'   #  0xF0 -> LATIN SMALL LETTER W WITH CIRCUMFLEX
+    u'\xf1'     #  0xF1 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf2'     #  0xF2 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\u1e6b'   #  0xF7 -> LATIN SMALL LETTER T WITH DOT ABOVE
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xfd'     #  0xFD -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\u0177'   #  0xFE -> LATIN SMALL LETTER Y WITH CIRCUMFLEX
+    u'\xff'     #  0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_15.py b/src/main/resources/PythonLibs/encodings/iso8859_15.py
new file mode 100644
index 0000000000000000000000000000000000000000..13b140ca3bd225b5432f71467252e1ece31700b6
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_15.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_15 generated from 'MAPPINGS/ISO8859/8859-15.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-15',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\xa1'     #  0xA1 -> INVERTED EXCLAMATION MARK
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\u20ac'   #  0xA4 -> EURO SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\u0160'   #  0xA6 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\u0161'   #  0xA8 -> LATIN SMALL LETTER S WITH CARON
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\xaa'     #  0xAA -> FEMININE ORDINAL INDICATOR
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\u017d'   #  0xB4 -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\u017e'   #  0xB8 -> LATIN SMALL LETTER Z WITH CARON
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\xba'     #  0xBA -> MASCULINE ORDINAL INDICATOR
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u0152'   #  0xBC -> LATIN CAPITAL LIGATURE OE
+    u'\u0153'   #  0xBD -> LATIN SMALL LIGATURE OE
+    u'\u0178'   #  0xBE -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\xbf'     #  0xBF -> INVERTED QUESTION MARK
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc3'     #  0xC3 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcc'     #  0xCC -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xd0'     #  0xD0 -> LATIN CAPITAL LETTER ETH
+    u'\xd1'     #  0xD1 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd2'     #  0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xdd'     #  0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xde'     #  0xDE -> LATIN CAPITAL LETTER THORN
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0xE3 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xec'     #  0xEC -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf0'     #  0xF0 -> LATIN SMALL LETTER ETH
+    u'\xf1'     #  0xF1 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf2'     #  0xF2 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xfd'     #  0xFD -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xfe'     #  0xFE -> LATIN SMALL LETTER THORN
+    u'\xff'     #  0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_16.py b/src/main/resources/PythonLibs/encodings/iso8859_16.py
new file mode 100644
index 0000000000000000000000000000000000000000..00b9ac805556d110fb6b00bca187cf0e58309d6b
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_16.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_16 generated from 'MAPPINGS/ISO8859/8859-16.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-16',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0104'   #  0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\u0105'   #  0xA2 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u0141'   #  0xA3 -> LATIN CAPITAL LETTER L WITH STROKE
+    u'\u20ac'   #  0xA4 -> EURO SIGN
+    u'\u201e'   #  0xA5 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u0160'   #  0xA6 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\u0161'   #  0xA8 -> LATIN SMALL LETTER S WITH CARON
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u0218'   #  0xAA -> LATIN CAPITAL LETTER S WITH COMMA BELOW
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u0179'   #  0xAC -> LATIN CAPITAL LETTER Z WITH ACUTE
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\u017a'   #  0xAE -> LATIN SMALL LETTER Z WITH ACUTE
+    u'\u017b'   #  0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u010c'   #  0xB2 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\u0142'   #  0xB3 -> LATIN SMALL LETTER L WITH STROKE
+    u'\u017d'   #  0xB4 -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\u201d'   #  0xB5 -> RIGHT DOUBLE QUOTATION MARK
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\u017e'   #  0xB8 -> LATIN SMALL LETTER Z WITH CARON
+    u'\u010d'   #  0xB9 -> LATIN SMALL LETTER C WITH CARON
+    u'\u0219'   #  0xBA -> LATIN SMALL LETTER S WITH COMMA BELOW
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u0152'   #  0xBC -> LATIN CAPITAL LIGATURE OE
+    u'\u0153'   #  0xBD -> LATIN SMALL LIGATURE OE
+    u'\u0178'   #  0xBE -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\u017c'   #  0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\u0102'   #  0xC3 -> LATIN CAPITAL LETTER A WITH BREVE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\u0106'   #  0xC5 -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcc'     #  0xCC -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\u0110'   #  0xD0 -> LATIN CAPITAL LETTER D WITH STROKE
+    u'\u0143'   #  0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE
+    u'\xd2'     #  0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\u0150'   #  0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\u015a'   #  0xD7 -> LATIN CAPITAL LETTER S WITH ACUTE
+    u'\u0170'   #  0xD8 -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u0118'   #  0xDD -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\u021a'   #  0xDE -> LATIN CAPITAL LETTER T WITH COMMA BELOW
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\u0103'   #  0xE3 -> LATIN SMALL LETTER A WITH BREVE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u0107'   #  0xE5 -> LATIN SMALL LETTER C WITH ACUTE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xec'     #  0xEC -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\u0111'   #  0xF0 -> LATIN SMALL LETTER D WITH STROKE
+    u'\u0144'   #  0xF1 -> LATIN SMALL LETTER N WITH ACUTE
+    u'\xf2'     #  0xF2 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\u0151'   #  0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\u015b'   #  0xF7 -> LATIN SMALL LETTER S WITH ACUTE
+    u'\u0171'   #  0xF8 -> LATIN SMALL LETTER U WITH DOUBLE ACUTE
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u0119'   #  0xFD -> LATIN SMALL LETTER E WITH OGONEK
+    u'\u021b'   #  0xFE -> LATIN SMALL LETTER T WITH COMMA BELOW
+    u'\xff'     #  0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_2.py b/src/main/resources/PythonLibs/encodings/iso8859_2.py
new file mode 100644
index 0000000000000000000000000000000000000000..38e91d8e177595faefc7c3e7bcc0ca5604981da2
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_2.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_2 generated from 'MAPPINGS/ISO8859/8859-2.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-2',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0104'   #  0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\u02d8'   #  0xA2 -> BREVE
+    u'\u0141'   #  0xA3 -> LATIN CAPITAL LETTER L WITH STROKE
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\u013d'   #  0xA5 -> LATIN CAPITAL LETTER L WITH CARON
+    u'\u015a'   #  0xA6 -> LATIN CAPITAL LETTER S WITH ACUTE
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\u0160'   #  0xA9 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u015e'   #  0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u'\u0164'   #  0xAB -> LATIN CAPITAL LETTER T WITH CARON
+    u'\u0179'   #  0xAC -> LATIN CAPITAL LETTER Z WITH ACUTE
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\u017d'   #  0xAE -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\u017b'   #  0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\u0105'   #  0xB1 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u02db'   #  0xB2 -> OGONEK
+    u'\u0142'   #  0xB3 -> LATIN SMALL LETTER L WITH STROKE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\u013e'   #  0xB5 -> LATIN SMALL LETTER L WITH CARON
+    u'\u015b'   #  0xB6 -> LATIN SMALL LETTER S WITH ACUTE
+    u'\u02c7'   #  0xB7 -> CARON
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\u0161'   #  0xB9 -> LATIN SMALL LETTER S WITH CARON
+    u'\u015f'   #  0xBA -> LATIN SMALL LETTER S WITH CEDILLA
+    u'\u0165'   #  0xBB -> LATIN SMALL LETTER T WITH CARON
+    u'\u017a'   #  0xBC -> LATIN SMALL LETTER Z WITH ACUTE
+    u'\u02dd'   #  0xBD -> DOUBLE ACUTE ACCENT
+    u'\u017e'   #  0xBE -> LATIN SMALL LETTER Z WITH CARON
+    u'\u017c'   #  0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\u0154'   #  0xC0 -> LATIN CAPITAL LETTER R WITH ACUTE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\u0102'   #  0xC3 -> LATIN CAPITAL LETTER A WITH BREVE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\u0139'   #  0xC5 -> LATIN CAPITAL LETTER L WITH ACUTE
+    u'\u0106'   #  0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\u010c'   #  0xC8 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\u0118'   #  0xCA -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\u011a'   #  0xCC -> LATIN CAPITAL LETTER E WITH CARON
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\u010e'   #  0xCF -> LATIN CAPITAL LETTER D WITH CARON
+    u'\u0110'   #  0xD0 -> LATIN CAPITAL LETTER D WITH STROKE
+    u'\u0143'   #  0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE
+    u'\u0147'   #  0xD2 -> LATIN CAPITAL LETTER N WITH CARON
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\u0150'   #  0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\u0158'   #  0xD8 -> LATIN CAPITAL LETTER R WITH CARON
+    u'\u016e'   #  0xD9 -> LATIN CAPITAL LETTER U WITH RING ABOVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\u0170'   #  0xDB -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xdd'     #  0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\u0162'   #  0xDE -> LATIN CAPITAL LETTER T WITH CEDILLA
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\u0155'   #  0xE0 -> LATIN SMALL LETTER R WITH ACUTE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\u0103'   #  0xE3 -> LATIN SMALL LETTER A WITH BREVE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u013a'   #  0xE5 -> LATIN SMALL LETTER L WITH ACUTE
+    u'\u0107'   #  0xE6 -> LATIN SMALL LETTER C WITH ACUTE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\u010d'   #  0xE8 -> LATIN SMALL LETTER C WITH CARON
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\u0119'   #  0xEA -> LATIN SMALL LETTER E WITH OGONEK
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\u011b'   #  0xEC -> LATIN SMALL LETTER E WITH CARON
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\u010f'   #  0xEF -> LATIN SMALL LETTER D WITH CARON
+    u'\u0111'   #  0xF0 -> LATIN SMALL LETTER D WITH STROKE
+    u'\u0144'   #  0xF1 -> LATIN SMALL LETTER N WITH ACUTE
+    u'\u0148'   #  0xF2 -> LATIN SMALL LETTER N WITH CARON
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\u0151'   #  0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\u0159'   #  0xF8 -> LATIN SMALL LETTER R WITH CARON
+    u'\u016f'   #  0xF9 -> LATIN SMALL LETTER U WITH RING ABOVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\u0171'   #  0xFB -> LATIN SMALL LETTER U WITH DOUBLE ACUTE
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xfd'     #  0xFD -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\u0163'   #  0xFE -> LATIN SMALL LETTER T WITH CEDILLA
+    u'\u02d9'   #  0xFF -> DOT ABOVE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_3.py b/src/main/resources/PythonLibs/encodings/iso8859_3.py
new file mode 100644
index 0000000000000000000000000000000000000000..23daafdbb1729f548d92255274a2795fc66ffe0c
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_3.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_3 generated from 'MAPPINGS/ISO8859/8859-3.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-3',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0126'   #  0xA1 -> LATIN CAPITAL LETTER H WITH STROKE
+    u'\u02d8'   #  0xA2 -> BREVE
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\ufffe'
+    u'\u0124'   #  0xA6 -> LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\u0130'   #  0xA9 -> LATIN CAPITAL LETTER I WITH DOT ABOVE
+    u'\u015e'   #  0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u'\u011e'   #  0xAB -> LATIN CAPITAL LETTER G WITH BREVE
+    u'\u0134'   #  0xAC -> LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\ufffe'
+    u'\u017b'   #  0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\u0127'   #  0xB1 -> LATIN SMALL LETTER H WITH STROKE
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\u0125'   #  0xB6 -> LATIN SMALL LETTER H WITH CIRCUMFLEX
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\u0131'   #  0xB9 -> LATIN SMALL LETTER DOTLESS I
+    u'\u015f'   #  0xBA -> LATIN SMALL LETTER S WITH CEDILLA
+    u'\u011f'   #  0xBB -> LATIN SMALL LETTER G WITH BREVE
+    u'\u0135'   #  0xBC -> LATIN SMALL LETTER J WITH CIRCUMFLEX
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\ufffe'
+    u'\u017c'   #  0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\ufffe'
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\u010a'   #  0xC5 -> LATIN CAPITAL LETTER C WITH DOT ABOVE
+    u'\u0108'   #  0xC6 -> LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcc'     #  0xCC -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\ufffe'
+    u'\xd1'     #  0xD1 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd2'     #  0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\u0120'   #  0xD5 -> LATIN CAPITAL LETTER G WITH DOT ABOVE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\u011c'   #  0xD8 -> LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u016c'   #  0xDD -> LATIN CAPITAL LETTER U WITH BREVE
+    u'\u015c'   #  0xDE -> LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\ufffe'
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u010b'   #  0xE5 -> LATIN SMALL LETTER C WITH DOT ABOVE
+    u'\u0109'   #  0xE6 -> LATIN SMALL LETTER C WITH CIRCUMFLEX
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xec'     #  0xEC -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\ufffe'
+    u'\xf1'     #  0xF1 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf2'     #  0xF2 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\u0121'   #  0xF5 -> LATIN SMALL LETTER G WITH DOT ABOVE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\u011d'   #  0xF8 -> LATIN SMALL LETTER G WITH CIRCUMFLEX
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u016d'   #  0xFD -> LATIN SMALL LETTER U WITH BREVE
+    u'\u015d'   #  0xFE -> LATIN SMALL LETTER S WITH CIRCUMFLEX
+    u'\u02d9'   #  0xFF -> DOT ABOVE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_4.py b/src/main/resources/PythonLibs/encodings/iso8859_4.py
new file mode 100644
index 0000000000000000000000000000000000000000..c8e03b566ae91f3295f3ec42133360d5cf055769
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_4.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_4 generated from 'MAPPINGS/ISO8859/8859-4.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-4',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0104'   #  0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\u0138'   #  0xA2 -> LATIN SMALL LETTER KRA
+    u'\u0156'   #  0xA3 -> LATIN CAPITAL LETTER R WITH CEDILLA
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\u0128'   #  0xA5 -> LATIN CAPITAL LETTER I WITH TILDE
+    u'\u013b'   #  0xA6 -> LATIN CAPITAL LETTER L WITH CEDILLA
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\u0160'   #  0xA9 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u0112'   #  0xAA -> LATIN CAPITAL LETTER E WITH MACRON
+    u'\u0122'   #  0xAB -> LATIN CAPITAL LETTER G WITH CEDILLA
+    u'\u0166'   #  0xAC -> LATIN CAPITAL LETTER T WITH STROKE
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\u017d'   #  0xAE -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\u0105'   #  0xB1 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u02db'   #  0xB2 -> OGONEK
+    u'\u0157'   #  0xB3 -> LATIN SMALL LETTER R WITH CEDILLA
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\u0129'   #  0xB5 -> LATIN SMALL LETTER I WITH TILDE
+    u'\u013c'   #  0xB6 -> LATIN SMALL LETTER L WITH CEDILLA
+    u'\u02c7'   #  0xB7 -> CARON
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\u0161'   #  0xB9 -> LATIN SMALL LETTER S WITH CARON
+    u'\u0113'   #  0xBA -> LATIN SMALL LETTER E WITH MACRON
+    u'\u0123'   #  0xBB -> LATIN SMALL LETTER G WITH CEDILLA
+    u'\u0167'   #  0xBC -> LATIN SMALL LETTER T WITH STROKE
+    u'\u014a'   #  0xBD -> LATIN CAPITAL LETTER ENG
+    u'\u017e'   #  0xBE -> LATIN SMALL LETTER Z WITH CARON
+    u'\u014b'   #  0xBF -> LATIN SMALL LETTER ENG
+    u'\u0100'   #  0xC0 -> LATIN CAPITAL LETTER A WITH MACRON
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc3'     #  0xC3 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\u012e'   #  0xC7 -> LATIN CAPITAL LETTER I WITH OGONEK
+    u'\u010c'   #  0xC8 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\u0118'   #  0xCA -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\u0116'   #  0xCC -> LATIN CAPITAL LETTER E WITH DOT ABOVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\u012a'   #  0xCF -> LATIN CAPITAL LETTER I WITH MACRON
+    u'\u0110'   #  0xD0 -> LATIN CAPITAL LETTER D WITH STROKE
+    u'\u0145'   #  0xD1 -> LATIN CAPITAL LETTER N WITH CEDILLA
+    u'\u014c'   #  0xD2 -> LATIN CAPITAL LETTER O WITH MACRON
+    u'\u0136'   #  0xD3 -> LATIN CAPITAL LETTER K WITH CEDILLA
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u0172'   #  0xD9 -> LATIN CAPITAL LETTER U WITH OGONEK
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u0168'   #  0xDD -> LATIN CAPITAL LETTER U WITH TILDE
+    u'\u016a'   #  0xDE -> LATIN CAPITAL LETTER U WITH MACRON
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\u0101'   #  0xE0 -> LATIN SMALL LETTER A WITH MACRON
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0xE3 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\u012f'   #  0xE7 -> LATIN SMALL LETTER I WITH OGONEK
+    u'\u010d'   #  0xE8 -> LATIN SMALL LETTER C WITH CARON
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\u0119'   #  0xEA -> LATIN SMALL LETTER E WITH OGONEK
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\u0117'   #  0xEC -> LATIN SMALL LETTER E WITH DOT ABOVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\u012b'   #  0xEF -> LATIN SMALL LETTER I WITH MACRON
+    u'\u0111'   #  0xF0 -> LATIN SMALL LETTER D WITH STROKE
+    u'\u0146'   #  0xF1 -> LATIN SMALL LETTER N WITH CEDILLA
+    u'\u014d'   #  0xF2 -> LATIN SMALL LETTER O WITH MACRON
+    u'\u0137'   #  0xF3 -> LATIN SMALL LETTER K WITH CEDILLA
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\u0173'   #  0xF9 -> LATIN SMALL LETTER U WITH OGONEK
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u0169'   #  0xFD -> LATIN SMALL LETTER U WITH TILDE
+    u'\u016b'   #  0xFE -> LATIN SMALL LETTER U WITH MACRON
+    u'\u02d9'   #  0xFF -> DOT ABOVE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_5.py b/src/main/resources/PythonLibs/encodings/iso8859_5.py
new file mode 100644
index 0000000000000000000000000000000000000000..c01cd1caab3949d6ae4a15f6bfc7368347ad2749
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_5.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_5 generated from 'MAPPINGS/ISO8859/8859-5.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-5',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u0401'   #  0xA1 -> CYRILLIC CAPITAL LETTER IO
+    u'\u0402'   #  0xA2 -> CYRILLIC CAPITAL LETTER DJE
+    u'\u0403'   #  0xA3 -> CYRILLIC CAPITAL LETTER GJE
+    u'\u0404'   #  0xA4 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    u'\u0405'   #  0xA5 -> CYRILLIC CAPITAL LETTER DZE
+    u'\u0406'   #  0xA6 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\u0407'   #  0xA7 -> CYRILLIC CAPITAL LETTER YI
+    u'\u0408'   #  0xA8 -> CYRILLIC CAPITAL LETTER JE
+    u'\u0409'   #  0xA9 -> CYRILLIC CAPITAL LETTER LJE
+    u'\u040a'   #  0xAA -> CYRILLIC CAPITAL LETTER NJE
+    u'\u040b'   #  0xAB -> CYRILLIC CAPITAL LETTER TSHE
+    u'\u040c'   #  0xAC -> CYRILLIC CAPITAL LETTER KJE
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\u040e'   #  0xAE -> CYRILLIC CAPITAL LETTER SHORT U
+    u'\u040f'   #  0xAF -> CYRILLIC CAPITAL LETTER DZHE
+    u'\u0410'   #  0xB0 -> CYRILLIC CAPITAL LETTER A
+    u'\u0411'   #  0xB1 -> CYRILLIC CAPITAL LETTER BE
+    u'\u0412'   #  0xB2 -> CYRILLIC CAPITAL LETTER VE
+    u'\u0413'   #  0xB3 -> CYRILLIC CAPITAL LETTER GHE
+    u'\u0414'   #  0xB4 -> CYRILLIC CAPITAL LETTER DE
+    u'\u0415'   #  0xB5 -> CYRILLIC CAPITAL LETTER IE
+    u'\u0416'   #  0xB6 -> CYRILLIC CAPITAL LETTER ZHE
+    u'\u0417'   #  0xB7 -> CYRILLIC CAPITAL LETTER ZE
+    u'\u0418'   #  0xB8 -> CYRILLIC CAPITAL LETTER I
+    u'\u0419'   #  0xB9 -> CYRILLIC CAPITAL LETTER SHORT I
+    u'\u041a'   #  0xBA -> CYRILLIC CAPITAL LETTER KA
+    u'\u041b'   #  0xBB -> CYRILLIC CAPITAL LETTER EL
+    u'\u041c'   #  0xBC -> CYRILLIC CAPITAL LETTER EM
+    u'\u041d'   #  0xBD -> CYRILLIC CAPITAL LETTER EN
+    u'\u041e'   #  0xBE -> CYRILLIC CAPITAL LETTER O
+    u'\u041f'   #  0xBF -> CYRILLIC CAPITAL LETTER PE
+    u'\u0420'   #  0xC0 -> CYRILLIC CAPITAL LETTER ER
+    u'\u0421'   #  0xC1 -> CYRILLIC CAPITAL LETTER ES
+    u'\u0422'   #  0xC2 -> CYRILLIC CAPITAL LETTER TE
+    u'\u0423'   #  0xC3 -> CYRILLIC CAPITAL LETTER U
+    u'\u0424'   #  0xC4 -> CYRILLIC CAPITAL LETTER EF
+    u'\u0425'   #  0xC5 -> CYRILLIC CAPITAL LETTER HA
+    u'\u0426'   #  0xC6 -> CYRILLIC CAPITAL LETTER TSE
+    u'\u0427'   #  0xC7 -> CYRILLIC CAPITAL LETTER CHE
+    u'\u0428'   #  0xC8 -> CYRILLIC CAPITAL LETTER SHA
+    u'\u0429'   #  0xC9 -> CYRILLIC CAPITAL LETTER SHCHA
+    u'\u042a'   #  0xCA -> CYRILLIC CAPITAL LETTER HARD SIGN
+    u'\u042b'   #  0xCB -> CYRILLIC CAPITAL LETTER YERU
+    u'\u042c'   #  0xCC -> CYRILLIC CAPITAL LETTER SOFT SIGN
+    u'\u042d'   #  0xCD -> CYRILLIC CAPITAL LETTER E
+    u'\u042e'   #  0xCE -> CYRILLIC CAPITAL LETTER YU
+    u'\u042f'   #  0xCF -> CYRILLIC CAPITAL LETTER YA
+    u'\u0430'   #  0xD0 -> CYRILLIC SMALL LETTER A
+    u'\u0431'   #  0xD1 -> CYRILLIC SMALL LETTER BE
+    u'\u0432'   #  0xD2 -> CYRILLIC SMALL LETTER VE
+    u'\u0433'   #  0xD3 -> CYRILLIC SMALL LETTER GHE
+    u'\u0434'   #  0xD4 -> CYRILLIC SMALL LETTER DE
+    u'\u0435'   #  0xD5 -> CYRILLIC SMALL LETTER IE
+    u'\u0436'   #  0xD6 -> CYRILLIC SMALL LETTER ZHE
+    u'\u0437'   #  0xD7 -> CYRILLIC SMALL LETTER ZE
+    u'\u0438'   #  0xD8 -> CYRILLIC SMALL LETTER I
+    u'\u0439'   #  0xD9 -> CYRILLIC SMALL LETTER SHORT I
+    u'\u043a'   #  0xDA -> CYRILLIC SMALL LETTER KA
+    u'\u043b'   #  0xDB -> CYRILLIC SMALL LETTER EL
+    u'\u043c'   #  0xDC -> CYRILLIC SMALL LETTER EM
+    u'\u043d'   #  0xDD -> CYRILLIC SMALL LETTER EN
+    u'\u043e'   #  0xDE -> CYRILLIC SMALL LETTER O
+    u'\u043f'   #  0xDF -> CYRILLIC SMALL LETTER PE
+    u'\u0440'   #  0xE0 -> CYRILLIC SMALL LETTER ER
+    u'\u0441'   #  0xE1 -> CYRILLIC SMALL LETTER ES
+    u'\u0442'   #  0xE2 -> CYRILLIC SMALL LETTER TE
+    u'\u0443'   #  0xE3 -> CYRILLIC SMALL LETTER U
+    u'\u0444'   #  0xE4 -> CYRILLIC SMALL LETTER EF
+    u'\u0445'   #  0xE5 -> CYRILLIC SMALL LETTER HA
+    u'\u0446'   #  0xE6 -> CYRILLIC SMALL LETTER TSE
+    u'\u0447'   #  0xE7 -> CYRILLIC SMALL LETTER CHE
+    u'\u0448'   #  0xE8 -> CYRILLIC SMALL LETTER SHA
+    u'\u0449'   #  0xE9 -> CYRILLIC SMALL LETTER SHCHA
+    u'\u044a'   #  0xEA -> CYRILLIC SMALL LETTER HARD SIGN
+    u'\u044b'   #  0xEB -> CYRILLIC SMALL LETTER YERU
+    u'\u044c'   #  0xEC -> CYRILLIC SMALL LETTER SOFT SIGN
+    u'\u044d'   #  0xED -> CYRILLIC SMALL LETTER E
+    u'\u044e'   #  0xEE -> CYRILLIC SMALL LETTER YU
+    u'\u044f'   #  0xEF -> CYRILLIC SMALL LETTER YA
+    u'\u2116'   #  0xF0 -> NUMERO SIGN
+    u'\u0451'   #  0xF1 -> CYRILLIC SMALL LETTER IO
+    u'\u0452'   #  0xF2 -> CYRILLIC SMALL LETTER DJE
+    u'\u0453'   #  0xF3 -> CYRILLIC SMALL LETTER GJE
+    u'\u0454'   #  0xF4 -> CYRILLIC SMALL LETTER UKRAINIAN IE
+    u'\u0455'   #  0xF5 -> CYRILLIC SMALL LETTER DZE
+    u'\u0456'   #  0xF6 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\u0457'   #  0xF7 -> CYRILLIC SMALL LETTER YI
+    u'\u0458'   #  0xF8 -> CYRILLIC SMALL LETTER JE
+    u'\u0459'   #  0xF9 -> CYRILLIC SMALL LETTER LJE
+    u'\u045a'   #  0xFA -> CYRILLIC SMALL LETTER NJE
+    u'\u045b'   #  0xFB -> CYRILLIC SMALL LETTER TSHE
+    u'\u045c'   #  0xFC -> CYRILLIC SMALL LETTER KJE
+    u'\xa7'     #  0xFD -> SECTION SIGN
+    u'\u045e'   #  0xFE -> CYRILLIC SMALL LETTER SHORT U
+    u'\u045f'   #  0xFF -> CYRILLIC SMALL LETTER DZHE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_6.py b/src/main/resources/PythonLibs/encodings/iso8859_6.py
new file mode 100644
index 0000000000000000000000000000000000000000..16c34a3f618e9e01ea8339b310e6e35c5e932bdd
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_6.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_6 generated from 'MAPPINGS/ISO8859/8859-6.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-6',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\u060c'   #  0xAC -> ARABIC COMMA
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\u061b'   #  0xBB -> ARABIC SEMICOLON
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\u061f'   #  0xBF -> ARABIC QUESTION MARK
+    u'\ufffe'
+    u'\u0621'   #  0xC1 -> ARABIC LETTER HAMZA
+    u'\u0622'   #  0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE
+    u'\u0623'   #  0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE
+    u'\u0624'   #  0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE
+    u'\u0625'   #  0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW
+    u'\u0626'   #  0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE
+    u'\u0627'   #  0xC7 -> ARABIC LETTER ALEF
+    u'\u0628'   #  0xC8 -> ARABIC LETTER BEH
+    u'\u0629'   #  0xC9 -> ARABIC LETTER TEH MARBUTA
+    u'\u062a'   #  0xCA -> ARABIC LETTER TEH
+    u'\u062b'   #  0xCB -> ARABIC LETTER THEH
+    u'\u062c'   #  0xCC -> ARABIC LETTER JEEM
+    u'\u062d'   #  0xCD -> ARABIC LETTER HAH
+    u'\u062e'   #  0xCE -> ARABIC LETTER KHAH
+    u'\u062f'   #  0xCF -> ARABIC LETTER DAL
+    u'\u0630'   #  0xD0 -> ARABIC LETTER THAL
+    u'\u0631'   #  0xD1 -> ARABIC LETTER REH
+    u'\u0632'   #  0xD2 -> ARABIC LETTER ZAIN
+    u'\u0633'   #  0xD3 -> ARABIC LETTER SEEN
+    u'\u0634'   #  0xD4 -> ARABIC LETTER SHEEN
+    u'\u0635'   #  0xD5 -> ARABIC LETTER SAD
+    u'\u0636'   #  0xD6 -> ARABIC LETTER DAD
+    u'\u0637'   #  0xD7 -> ARABIC LETTER TAH
+    u'\u0638'   #  0xD8 -> ARABIC LETTER ZAH
+    u'\u0639'   #  0xD9 -> ARABIC LETTER AIN
+    u'\u063a'   #  0xDA -> ARABIC LETTER GHAIN
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\u0640'   #  0xE0 -> ARABIC TATWEEL
+    u'\u0641'   #  0xE1 -> ARABIC LETTER FEH
+    u'\u0642'   #  0xE2 -> ARABIC LETTER QAF
+    u'\u0643'   #  0xE3 -> ARABIC LETTER KAF
+    u'\u0644'   #  0xE4 -> ARABIC LETTER LAM
+    u'\u0645'   #  0xE5 -> ARABIC LETTER MEEM
+    u'\u0646'   #  0xE6 -> ARABIC LETTER NOON
+    u'\u0647'   #  0xE7 -> ARABIC LETTER HEH
+    u'\u0648'   #  0xE8 -> ARABIC LETTER WAW
+    u'\u0649'   #  0xE9 -> ARABIC LETTER ALEF MAKSURA
+    u'\u064a'   #  0xEA -> ARABIC LETTER YEH
+    u'\u064b'   #  0xEB -> ARABIC FATHATAN
+    u'\u064c'   #  0xEC -> ARABIC DAMMATAN
+    u'\u064d'   #  0xED -> ARABIC KASRATAN
+    u'\u064e'   #  0xEE -> ARABIC FATHA
+    u'\u064f'   #  0xEF -> ARABIC DAMMA
+    u'\u0650'   #  0xF0 -> ARABIC KASRA
+    u'\u0651'   #  0xF1 -> ARABIC SHADDA
+    u'\u0652'   #  0xF2 -> ARABIC SUKUN
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_7.py b/src/main/resources/PythonLibs/encodings/iso8859_7.py
new file mode 100644
index 0000000000000000000000000000000000000000..a560023a08b4838c20762856b35967094fefe824
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_7.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_7 generated from 'MAPPINGS/ISO8859/8859-7.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-7',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\u2018'   #  0xA1 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xA2 -> RIGHT SINGLE QUOTATION MARK
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\u20ac'   #  0xA4 -> EURO SIGN
+    u'\u20af'   #  0xA5 -> DRACHMA SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u037a'   #  0xAA -> GREEK YPOGEGRAMMENI
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\ufffe'
+    u'\u2015'   #  0xAF -> HORIZONTAL BAR
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\u0384'   #  0xB4 -> GREEK TONOS
+    u'\u0385'   #  0xB5 -> GREEK DIALYTIKA TONOS
+    u'\u0386'   #  0xB6 -> GREEK CAPITAL LETTER ALPHA WITH TONOS
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\u0388'   #  0xB8 -> GREEK CAPITAL LETTER EPSILON WITH TONOS
+    u'\u0389'   #  0xB9 -> GREEK CAPITAL LETTER ETA WITH TONOS
+    u'\u038a'   #  0xBA -> GREEK CAPITAL LETTER IOTA WITH TONOS
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u038c'   #  0xBC -> GREEK CAPITAL LETTER OMICRON WITH TONOS
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\u038e'   #  0xBE -> GREEK CAPITAL LETTER UPSILON WITH TONOS
+    u'\u038f'   #  0xBF -> GREEK CAPITAL LETTER OMEGA WITH TONOS
+    u'\u0390'   #  0xC0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+    u'\u0391'   #  0xC1 -> GREEK CAPITAL LETTER ALPHA
+    u'\u0392'   #  0xC2 -> GREEK CAPITAL LETTER BETA
+    u'\u0393'   #  0xC3 -> GREEK CAPITAL LETTER GAMMA
+    u'\u0394'   #  0xC4 -> GREEK CAPITAL LETTER DELTA
+    u'\u0395'   #  0xC5 -> GREEK CAPITAL LETTER EPSILON
+    u'\u0396'   #  0xC6 -> GREEK CAPITAL LETTER ZETA
+    u'\u0397'   #  0xC7 -> GREEK CAPITAL LETTER ETA
+    u'\u0398'   #  0xC8 -> GREEK CAPITAL LETTER THETA
+    u'\u0399'   #  0xC9 -> GREEK CAPITAL LETTER IOTA
+    u'\u039a'   #  0xCA -> GREEK CAPITAL LETTER KAPPA
+    u'\u039b'   #  0xCB -> GREEK CAPITAL LETTER LAMDA
+    u'\u039c'   #  0xCC -> GREEK CAPITAL LETTER MU
+    u'\u039d'   #  0xCD -> GREEK CAPITAL LETTER NU
+    u'\u039e'   #  0xCE -> GREEK CAPITAL LETTER XI
+    u'\u039f'   #  0xCF -> GREEK CAPITAL LETTER OMICRON
+    u'\u03a0'   #  0xD0 -> GREEK CAPITAL LETTER PI
+    u'\u03a1'   #  0xD1 -> GREEK CAPITAL LETTER RHO
+    u'\ufffe'
+    u'\u03a3'   #  0xD3 -> GREEK CAPITAL LETTER SIGMA
+    u'\u03a4'   #  0xD4 -> GREEK CAPITAL LETTER TAU
+    u'\u03a5'   #  0xD5 -> GREEK CAPITAL LETTER UPSILON
+    u'\u03a6'   #  0xD6 -> GREEK CAPITAL LETTER PHI
+    u'\u03a7'   #  0xD7 -> GREEK CAPITAL LETTER CHI
+    u'\u03a8'   #  0xD8 -> GREEK CAPITAL LETTER PSI
+    u'\u03a9'   #  0xD9 -> GREEK CAPITAL LETTER OMEGA
+    u'\u03aa'   #  0xDA -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    u'\u03ab'   #  0xDB -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    u'\u03ac'   #  0xDC -> GREEK SMALL LETTER ALPHA WITH TONOS
+    u'\u03ad'   #  0xDD -> GREEK SMALL LETTER EPSILON WITH TONOS
+    u'\u03ae'   #  0xDE -> GREEK SMALL LETTER ETA WITH TONOS
+    u'\u03af'   #  0xDF -> GREEK SMALL LETTER IOTA WITH TONOS
+    u'\u03b0'   #  0xE0 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+    u'\u03b1'   #  0xE1 -> GREEK SMALL LETTER ALPHA
+    u'\u03b2'   #  0xE2 -> GREEK SMALL LETTER BETA
+    u'\u03b3'   #  0xE3 -> GREEK SMALL LETTER GAMMA
+    u'\u03b4'   #  0xE4 -> GREEK SMALL LETTER DELTA
+    u'\u03b5'   #  0xE5 -> GREEK SMALL LETTER EPSILON
+    u'\u03b6'   #  0xE6 -> GREEK SMALL LETTER ZETA
+    u'\u03b7'   #  0xE7 -> GREEK SMALL LETTER ETA
+    u'\u03b8'   #  0xE8 -> GREEK SMALL LETTER THETA
+    u'\u03b9'   #  0xE9 -> GREEK SMALL LETTER IOTA
+    u'\u03ba'   #  0xEA -> GREEK SMALL LETTER KAPPA
+    u'\u03bb'   #  0xEB -> GREEK SMALL LETTER LAMDA
+    u'\u03bc'   #  0xEC -> GREEK SMALL LETTER MU
+    u'\u03bd'   #  0xED -> GREEK SMALL LETTER NU
+    u'\u03be'   #  0xEE -> GREEK SMALL LETTER XI
+    u'\u03bf'   #  0xEF -> GREEK SMALL LETTER OMICRON
+    u'\u03c0'   #  0xF0 -> GREEK SMALL LETTER PI
+    u'\u03c1'   #  0xF1 -> GREEK SMALL LETTER RHO
+    u'\u03c2'   #  0xF2 -> GREEK SMALL LETTER FINAL SIGMA
+    u'\u03c3'   #  0xF3 -> GREEK SMALL LETTER SIGMA
+    u'\u03c4'   #  0xF4 -> GREEK SMALL LETTER TAU
+    u'\u03c5'   #  0xF5 -> GREEK SMALL LETTER UPSILON
+    u'\u03c6'   #  0xF6 -> GREEK SMALL LETTER PHI
+    u'\u03c7'   #  0xF7 -> GREEK SMALL LETTER CHI
+    u'\u03c8'   #  0xF8 -> GREEK SMALL LETTER PSI
+    u'\u03c9'   #  0xF9 -> GREEK SMALL LETTER OMEGA
+    u'\u03ca'   #  0xFA -> GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    u'\u03cb'   #  0xFB -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    u'\u03cc'   #  0xFC -> GREEK SMALL LETTER OMICRON WITH TONOS
+    u'\u03cd'   #  0xFD -> GREEK SMALL LETTER UPSILON WITH TONOS
+    u'\u03ce'   #  0xFE -> GREEK SMALL LETTER OMEGA WITH TONOS
+    u'\ufffe'
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_8.py b/src/main/resources/PythonLibs/encodings/iso8859_8.py
new file mode 100644
index 0000000000000000000000000000000000000000..43cf2138b532012c023b859691764ec0f4a872b4
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_8.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_8 generated from 'MAPPINGS/ISO8859/8859-8.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-8',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\ufffe'
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\xd7'     #  0xAA -> MULTIPLICATION SIGN
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\xf7'     #  0xBA -> DIVISION SIGN
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\u2017'   #  0xDF -> DOUBLE LOW LINE
+    u'\u05d0'   #  0xE0 -> HEBREW LETTER ALEF
+    u'\u05d1'   #  0xE1 -> HEBREW LETTER BET
+    u'\u05d2'   #  0xE2 -> HEBREW LETTER GIMEL
+    u'\u05d3'   #  0xE3 -> HEBREW LETTER DALET
+    u'\u05d4'   #  0xE4 -> HEBREW LETTER HE
+    u'\u05d5'   #  0xE5 -> HEBREW LETTER VAV
+    u'\u05d6'   #  0xE6 -> HEBREW LETTER ZAYIN
+    u'\u05d7'   #  0xE7 -> HEBREW LETTER HET
+    u'\u05d8'   #  0xE8 -> HEBREW LETTER TET
+    u'\u05d9'   #  0xE9 -> HEBREW LETTER YOD
+    u'\u05da'   #  0xEA -> HEBREW LETTER FINAL KAF
+    u'\u05db'   #  0xEB -> HEBREW LETTER KAF
+    u'\u05dc'   #  0xEC -> HEBREW LETTER LAMED
+    u'\u05dd'   #  0xED -> HEBREW LETTER FINAL MEM
+    u'\u05de'   #  0xEE -> HEBREW LETTER MEM
+    u'\u05df'   #  0xEF -> HEBREW LETTER FINAL NUN
+    u'\u05e0'   #  0xF0 -> HEBREW LETTER NUN
+    u'\u05e1'   #  0xF1 -> HEBREW LETTER SAMEKH
+    u'\u05e2'   #  0xF2 -> HEBREW LETTER AYIN
+    u'\u05e3'   #  0xF3 -> HEBREW LETTER FINAL PE
+    u'\u05e4'   #  0xF4 -> HEBREW LETTER PE
+    u'\u05e5'   #  0xF5 -> HEBREW LETTER FINAL TSADI
+    u'\u05e6'   #  0xF6 -> HEBREW LETTER TSADI
+    u'\u05e7'   #  0xF7 -> HEBREW LETTER QOF
+    u'\u05e8'   #  0xF8 -> HEBREW LETTER RESH
+    u'\u05e9'   #  0xF9 -> HEBREW LETTER SHIN
+    u'\u05ea'   #  0xFA -> HEBREW LETTER TAV
+    u'\ufffe'
+    u'\ufffe'
+    u'\u200e'   #  0xFD -> LEFT-TO-RIGHT MARK
+    u'\u200f'   #  0xFE -> RIGHT-TO-LEFT MARK
+    u'\ufffe'
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/iso8859_9.py b/src/main/resources/PythonLibs/encodings/iso8859_9.py
new file mode 100644
index 0000000000000000000000000000000000000000..b8029382c0de6789719280d9e359d618b3b80d4d
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/iso8859_9.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec iso8859_9 generated from 'MAPPINGS/ISO8859/8859-9.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-9',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\xa0'     #  0xA0 -> NO-BREAK SPACE
+    u'\xa1'     #  0xA1 -> INVERTED EXCLAMATION MARK
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa4'     #  0xA4 -> CURRENCY SIGN
+    u'\xa5'     #  0xA5 -> YEN SIGN
+    u'\xa6'     #  0xA6 -> BROKEN BAR
+    u'\xa7'     #  0xA7 -> SECTION SIGN
+    u'\xa8'     #  0xA8 -> DIAERESIS
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\xaa'     #  0xAA -> FEMININE ORDINAL INDICATOR
+    u'\xab'     #  0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xac'     #  0xAC -> NOT SIGN
+    u'\xad'     #  0xAD -> SOFT HYPHEN
+    u'\xae'     #  0xAE -> REGISTERED SIGN
+    u'\xaf'     #  0xAF -> MACRON
+    u'\xb0'     #  0xB0 -> DEGREE SIGN
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\xb2'     #  0xB2 -> SUPERSCRIPT TWO
+    u'\xb3'     #  0xB3 -> SUPERSCRIPT THREE
+    u'\xb4'     #  0xB4 -> ACUTE ACCENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\xb6'     #  0xB6 -> PILCROW SIGN
+    u'\xb7'     #  0xB7 -> MIDDLE DOT
+    u'\xb8'     #  0xB8 -> CEDILLA
+    u'\xb9'     #  0xB9 -> SUPERSCRIPT ONE
+    u'\xba'     #  0xBA -> MASCULINE ORDINAL INDICATOR
+    u'\xbb'     #  0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbc'     #  0xBC -> VULGAR FRACTION ONE QUARTER
+    u'\xbd'     #  0xBD -> VULGAR FRACTION ONE HALF
+    u'\xbe'     #  0xBE -> VULGAR FRACTION THREE QUARTERS
+    u'\xbf'     #  0xBF -> INVERTED QUESTION MARK
+    u'\xc0'     #  0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc1'     #  0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xc2'     #  0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xc3'     #  0xC3 -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xc4'     #  0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc6'     #  0xC6 -> LATIN CAPITAL LETTER AE
+    u'\xc7'     #  0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc8'     #  0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xc9'     #  0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xca'     #  0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xcb'     #  0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xcc'     #  0xCC -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xcd'     #  0xCD -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\u011e'   #  0xD0 -> LATIN CAPITAL LETTER G WITH BREVE
+    u'\xd1'     #  0xD1 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd2'     #  0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xd3'     #  0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\xd5'     #  0xD5 -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\xd6'     #  0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xd7'     #  0xD7 -> MULTIPLICATION SIGN
+    u'\xd8'     #  0xD8 -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\xd9'     #  0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\xda'     #  0xDA -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xdc'     #  0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u0130'   #  0xDD -> LATIN CAPITAL LETTER I WITH DOT ABOVE
+    u'\u015e'   #  0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u'\xdf'     #  0xDF -> LATIN SMALL LETTER SHARP S
+    u'\xe0'     #  0xE0 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe1'     #  0xE1 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe2'     #  0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe3'     #  0xE3 -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe4'     #  0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe5'     #  0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe6'     #  0xE6 -> LATIN SMALL LETTER AE
+    u'\xe7'     #  0xE7 -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe8'     #  0xE8 -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xe9'     #  0xE9 -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xea'     #  0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0xEB -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xec'     #  0xEC -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xed'     #  0xED -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xee'     #  0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0xEF -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\u011f'   #  0xF0 -> LATIN SMALL LETTER G WITH BREVE
+    u'\xf1'     #  0xF1 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf2'     #  0xF2 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf3'     #  0xF3 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf4'     #  0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf5'     #  0xF5 -> LATIN SMALL LETTER O WITH TILDE
+    u'\xf6'     #  0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0xF7 -> DIVISION SIGN
+    u'\xf8'     #  0xF8 -> LATIN SMALL LETTER O WITH STROKE
+    u'\xf9'     #  0xF9 -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfa'     #  0xFA -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xfb'     #  0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0xFC -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u0131'   #  0xFD -> LATIN SMALL LETTER DOTLESS I
+    u'\u015f'   #  0xFE -> LATIN SMALL LETTER S WITH CEDILLA
+    u'\xff'     #  0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/johab.py b/src/main/resources/PythonLibs/encodings/johab.py
new file mode 100644
index 0000000000000000000000000000000000000000..512aeeb732b5221ba35585a97e3cc1b85d3c5b02
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/johab.py
@@ -0,0 +1,39 @@
+#
+# johab.py: Python Unicode Codec for JOHAB
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_kr, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_kr.getcodec('johab')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='johab',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/koi8_r.py b/src/main/resources/PythonLibs/encodings/koi8_r.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9eb82c0db47004e308a461947f9d3ce0b96e774
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/koi8_r.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec koi8_r generated from 'MAPPINGS/VENDORS/MISC/KOI8-R.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='koi8-r',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u2500'   #  0x80 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u2502'   #  0x81 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u250c'   #  0x82 -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2510'   #  0x83 -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x84 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2518'   #  0x85 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u251c'   #  0x86 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2524'   #  0x87 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u252c'   #  0x88 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u2534'   #  0x89 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u253c'   #  0x8A -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u2580'   #  0x8B -> UPPER HALF BLOCK
+    u'\u2584'   #  0x8C -> LOWER HALF BLOCK
+    u'\u2588'   #  0x8D -> FULL BLOCK
+    u'\u258c'   #  0x8E -> LEFT HALF BLOCK
+    u'\u2590'   #  0x8F -> RIGHT HALF BLOCK
+    u'\u2591'   #  0x90 -> LIGHT SHADE
+    u'\u2592'   #  0x91 -> MEDIUM SHADE
+    u'\u2593'   #  0x92 -> DARK SHADE
+    u'\u2320'   #  0x93 -> TOP HALF INTEGRAL
+    u'\u25a0'   #  0x94 -> BLACK SQUARE
+    u'\u2219'   #  0x95 -> BULLET OPERATOR
+    u'\u221a'   #  0x96 -> SQUARE ROOT
+    u'\u2248'   #  0x97 -> ALMOST EQUAL TO
+    u'\u2264'   #  0x98 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0x99 -> GREATER-THAN OR EQUAL TO
+    u'\xa0'     #  0x9A -> NO-BREAK SPACE
+    u'\u2321'   #  0x9B -> BOTTOM HALF INTEGRAL
+    u'\xb0'     #  0x9C -> DEGREE SIGN
+    u'\xb2'     #  0x9D -> SUPERSCRIPT TWO
+    u'\xb7'     #  0x9E -> MIDDLE DOT
+    u'\xf7'     #  0x9F -> DIVISION SIGN
+    u'\u2550'   #  0xA0 -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u2551'   #  0xA1 -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2552'   #  0xA2 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u0451'   #  0xA3 -> CYRILLIC SMALL LETTER IO
+    u'\u2553'   #  0xA4 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+    u'\u2554'   #  0xA5 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u2555'   #  0xA6 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+    u'\u2556'   #  0xA7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+    u'\u2557'   #  0xA8 -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u2558'   #  0xA9 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2559'   #  0xAA -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0xAB -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u255b'   #  0xAC -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u255c'   #  0xAD -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+    u'\u255d'   #  0xAE -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255e'   #  0xAF -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0xB0 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u2560'   #  0xB1 -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2561'   #  0xB2 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u0401'   #  0xB3 -> CYRILLIC CAPITAL LETTER IO
+    u'\u2562'   #  0xB4 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+    u'\u2563'   #  0xB5 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u2564'   #  0xB6 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+    u'\u2565'   #  0xB7 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+    u'\u2566'   #  0xB8 -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2567'   #  0xB9 -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0xBA -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2569'   #  0xBB -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u256a'   #  0xBC -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u256b'   #  0xBD -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+    u'\u256c'   #  0xBE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\xa9'     #  0xBF -> COPYRIGHT SIGN
+    u'\u044e'   #  0xC0 -> CYRILLIC SMALL LETTER YU
+    u'\u0430'   #  0xC1 -> CYRILLIC SMALL LETTER A
+    u'\u0431'   #  0xC2 -> CYRILLIC SMALL LETTER BE
+    u'\u0446'   #  0xC3 -> CYRILLIC SMALL LETTER TSE
+    u'\u0434'   #  0xC4 -> CYRILLIC SMALL LETTER DE
+    u'\u0435'   #  0xC5 -> CYRILLIC SMALL LETTER IE
+    u'\u0444'   #  0xC6 -> CYRILLIC SMALL LETTER EF
+    u'\u0433'   #  0xC7 -> CYRILLIC SMALL LETTER GHE
+    u'\u0445'   #  0xC8 -> CYRILLIC SMALL LETTER HA
+    u'\u0438'   #  0xC9 -> CYRILLIC SMALL LETTER I
+    u'\u0439'   #  0xCA -> CYRILLIC SMALL LETTER SHORT I
+    u'\u043a'   #  0xCB -> CYRILLIC SMALL LETTER KA
+    u'\u043b'   #  0xCC -> CYRILLIC SMALL LETTER EL
+    u'\u043c'   #  0xCD -> CYRILLIC SMALL LETTER EM
+    u'\u043d'   #  0xCE -> CYRILLIC SMALL LETTER EN
+    u'\u043e'   #  0xCF -> CYRILLIC SMALL LETTER O
+    u'\u043f'   #  0xD0 -> CYRILLIC SMALL LETTER PE
+    u'\u044f'   #  0xD1 -> CYRILLIC SMALL LETTER YA
+    u'\u0440'   #  0xD2 -> CYRILLIC SMALL LETTER ER
+    u'\u0441'   #  0xD3 -> CYRILLIC SMALL LETTER ES
+    u'\u0442'   #  0xD4 -> CYRILLIC SMALL LETTER TE
+    u'\u0443'   #  0xD5 -> CYRILLIC SMALL LETTER U
+    u'\u0436'   #  0xD6 -> CYRILLIC SMALL LETTER ZHE
+    u'\u0432'   #  0xD7 -> CYRILLIC SMALL LETTER VE
+    u'\u044c'   #  0xD8 -> CYRILLIC SMALL LETTER SOFT SIGN
+    u'\u044b'   #  0xD9 -> CYRILLIC SMALL LETTER YERU
+    u'\u0437'   #  0xDA -> CYRILLIC SMALL LETTER ZE
+    u'\u0448'   #  0xDB -> CYRILLIC SMALL LETTER SHA
+    u'\u044d'   #  0xDC -> CYRILLIC SMALL LETTER E
+    u'\u0449'   #  0xDD -> CYRILLIC SMALL LETTER SHCHA
+    u'\u0447'   #  0xDE -> CYRILLIC SMALL LETTER CHE
+    u'\u044a'   #  0xDF -> CYRILLIC SMALL LETTER HARD SIGN
+    u'\u042e'   #  0xE0 -> CYRILLIC CAPITAL LETTER YU
+    u'\u0410'   #  0xE1 -> CYRILLIC CAPITAL LETTER A
+    u'\u0411'   #  0xE2 -> CYRILLIC CAPITAL LETTER BE
+    u'\u0426'   #  0xE3 -> CYRILLIC CAPITAL LETTER TSE
+    u'\u0414'   #  0xE4 -> CYRILLIC CAPITAL LETTER DE
+    u'\u0415'   #  0xE5 -> CYRILLIC CAPITAL LETTER IE
+    u'\u0424'   #  0xE6 -> CYRILLIC CAPITAL LETTER EF
+    u'\u0413'   #  0xE7 -> CYRILLIC CAPITAL LETTER GHE
+    u'\u0425'   #  0xE8 -> CYRILLIC CAPITAL LETTER HA
+    u'\u0418'   #  0xE9 -> CYRILLIC CAPITAL LETTER I
+    u'\u0419'   #  0xEA -> CYRILLIC CAPITAL LETTER SHORT I
+    u'\u041a'   #  0xEB -> CYRILLIC CAPITAL LETTER KA
+    u'\u041b'   #  0xEC -> CYRILLIC CAPITAL LETTER EL
+    u'\u041c'   #  0xED -> CYRILLIC CAPITAL LETTER EM
+    u'\u041d'   #  0xEE -> CYRILLIC CAPITAL LETTER EN
+    u'\u041e'   #  0xEF -> CYRILLIC CAPITAL LETTER O
+    u'\u041f'   #  0xF0 -> CYRILLIC CAPITAL LETTER PE
+    u'\u042f'   #  0xF1 -> CYRILLIC CAPITAL LETTER YA
+    u'\u0420'   #  0xF2 -> CYRILLIC CAPITAL LETTER ER
+    u'\u0421'   #  0xF3 -> CYRILLIC CAPITAL LETTER ES
+    u'\u0422'   #  0xF4 -> CYRILLIC CAPITAL LETTER TE
+    u'\u0423'   #  0xF5 -> CYRILLIC CAPITAL LETTER U
+    u'\u0416'   #  0xF6 -> CYRILLIC CAPITAL LETTER ZHE
+    u'\u0412'   #  0xF7 -> CYRILLIC CAPITAL LETTER VE
+    u'\u042c'   #  0xF8 -> CYRILLIC CAPITAL LETTER SOFT SIGN
+    u'\u042b'   #  0xF9 -> CYRILLIC CAPITAL LETTER YERU
+    u'\u0417'   #  0xFA -> CYRILLIC CAPITAL LETTER ZE
+    u'\u0428'   #  0xFB -> CYRILLIC CAPITAL LETTER SHA
+    u'\u042d'   #  0xFC -> CYRILLIC CAPITAL LETTER E
+    u'\u0429'   #  0xFD -> CYRILLIC CAPITAL LETTER SHCHA
+    u'\u0427'   #  0xFE -> CYRILLIC CAPITAL LETTER CHE
+    u'\u042a'   #  0xFF -> CYRILLIC CAPITAL LETTER HARD SIGN
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/koi8_u.py b/src/main/resources/PythonLibs/encodings/koi8_u.py
new file mode 100644
index 0000000000000000000000000000000000000000..a9317b12b773ecdabc5a190e55b02b93ca0df730
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/koi8_u.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec koi8_u generated from 'python-mappings/KOI8-U.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='koi8-u',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\u2500'   #  0x80 -> BOX DRAWINGS LIGHT HORIZONTAL
+    u'\u2502'   #  0x81 -> BOX DRAWINGS LIGHT VERTICAL
+    u'\u250c'   #  0x82 -> BOX DRAWINGS LIGHT DOWN AND RIGHT
+    u'\u2510'   #  0x83 -> BOX DRAWINGS LIGHT DOWN AND LEFT
+    u'\u2514'   #  0x84 -> BOX DRAWINGS LIGHT UP AND RIGHT
+    u'\u2518'   #  0x85 -> BOX DRAWINGS LIGHT UP AND LEFT
+    u'\u251c'   #  0x86 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+    u'\u2524'   #  0x87 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT
+    u'\u252c'   #  0x88 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+    u'\u2534'   #  0x89 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL
+    u'\u253c'   #  0x8A -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+    u'\u2580'   #  0x8B -> UPPER HALF BLOCK
+    u'\u2584'   #  0x8C -> LOWER HALF BLOCK
+    u'\u2588'   #  0x8D -> FULL BLOCK
+    u'\u258c'   #  0x8E -> LEFT HALF BLOCK
+    u'\u2590'   #  0x8F -> RIGHT HALF BLOCK
+    u'\u2591'   #  0x90 -> LIGHT SHADE
+    u'\u2592'   #  0x91 -> MEDIUM SHADE
+    u'\u2593'   #  0x92 -> DARK SHADE
+    u'\u2320'   #  0x93 -> TOP HALF INTEGRAL
+    u'\u25a0'   #  0x94 -> BLACK SQUARE
+    u'\u2219'   #  0x95 -> BULLET OPERATOR
+    u'\u221a'   #  0x96 -> SQUARE ROOT
+    u'\u2248'   #  0x97 -> ALMOST EQUAL TO
+    u'\u2264'   #  0x98 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0x99 -> GREATER-THAN OR EQUAL TO
+    u'\xa0'     #  0x9A -> NO-BREAK SPACE
+    u'\u2321'   #  0x9B -> BOTTOM HALF INTEGRAL
+    u'\xb0'     #  0x9C -> DEGREE SIGN
+    u'\xb2'     #  0x9D -> SUPERSCRIPT TWO
+    u'\xb7'     #  0x9E -> MIDDLE DOT
+    u'\xf7'     #  0x9F -> DIVISION SIGN
+    u'\u2550'   #  0xA0 -> BOX DRAWINGS DOUBLE HORIZONTAL
+    u'\u2551'   #  0xA1 -> BOX DRAWINGS DOUBLE VERTICAL
+    u'\u2552'   #  0xA2 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+    u'\u0451'   #  0xA3 -> CYRILLIC SMALL LETTER IO
+    u'\u0454'   #  0xA4 -> CYRILLIC SMALL LETTER UKRAINIAN IE
+    u'\u2554'   #  0xA5 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT
+    u'\u0456'   #  0xA6 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\u0457'   #  0xA7 -> CYRILLIC SMALL LETTER YI (UKRAINIAN)
+    u'\u2557'   #  0xA8 -> BOX DRAWINGS DOUBLE DOWN AND LEFT
+    u'\u2558'   #  0xA9 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+    u'\u2559'   #  0xAA -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+    u'\u255a'   #  0xAB -> BOX DRAWINGS DOUBLE UP AND RIGHT
+    u'\u255b'   #  0xAC -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+    u'\u0491'   #  0xAD -> CYRILLIC SMALL LETTER UKRAINIAN GHE WITH UPTURN
+    u'\u255d'   #  0xAE -> BOX DRAWINGS DOUBLE UP AND LEFT
+    u'\u255e'   #  0xAF -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+    u'\u255f'   #  0xB0 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+    u'\u2560'   #  0xB1 -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+    u'\u2561'   #  0xB2 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+    u'\u0401'   #  0xB3 -> CYRILLIC CAPITAL LETTER IO
+    u'\u0404'   #  0xB4 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    u'\u2563'   #  0xB5 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+    u'\u0406'   #  0xB6 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\u0407'   #  0xB7 -> CYRILLIC CAPITAL LETTER YI (UKRAINIAN)
+    u'\u2566'   #  0xB8 -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+    u'\u2567'   #  0xB9 -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+    u'\u2568'   #  0xBA -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+    u'\u2569'   #  0xBB -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+    u'\u256a'   #  0xBC -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+    u'\u0490'   #  0xBD -> CYRILLIC CAPITAL LETTER UKRAINIAN GHE WITH UPTURN
+    u'\u256c'   #  0xBE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+    u'\xa9'     #  0xBF -> COPYRIGHT SIGN
+    u'\u044e'   #  0xC0 -> CYRILLIC SMALL LETTER YU
+    u'\u0430'   #  0xC1 -> CYRILLIC SMALL LETTER A
+    u'\u0431'   #  0xC2 -> CYRILLIC SMALL LETTER BE
+    u'\u0446'   #  0xC3 -> CYRILLIC SMALL LETTER TSE
+    u'\u0434'   #  0xC4 -> CYRILLIC SMALL LETTER DE
+    u'\u0435'   #  0xC5 -> CYRILLIC SMALL LETTER IE
+    u'\u0444'   #  0xC6 -> CYRILLIC SMALL LETTER EF
+    u'\u0433'   #  0xC7 -> CYRILLIC SMALL LETTER GHE
+    u'\u0445'   #  0xC8 -> CYRILLIC SMALL LETTER HA
+    u'\u0438'   #  0xC9 -> CYRILLIC SMALL LETTER I
+    u'\u0439'   #  0xCA -> CYRILLIC SMALL LETTER SHORT I
+    u'\u043a'   #  0xCB -> CYRILLIC SMALL LETTER KA
+    u'\u043b'   #  0xCC -> CYRILLIC SMALL LETTER EL
+    u'\u043c'   #  0xCD -> CYRILLIC SMALL LETTER EM
+    u'\u043d'   #  0xCE -> CYRILLIC SMALL LETTER EN
+    u'\u043e'   #  0xCF -> CYRILLIC SMALL LETTER O
+    u'\u043f'   #  0xD0 -> CYRILLIC SMALL LETTER PE
+    u'\u044f'   #  0xD1 -> CYRILLIC SMALL LETTER YA
+    u'\u0440'   #  0xD2 -> CYRILLIC SMALL LETTER ER
+    u'\u0441'   #  0xD3 -> CYRILLIC SMALL LETTER ES
+    u'\u0442'   #  0xD4 -> CYRILLIC SMALL LETTER TE
+    u'\u0443'   #  0xD5 -> CYRILLIC SMALL LETTER U
+    u'\u0436'   #  0xD6 -> CYRILLIC SMALL LETTER ZHE
+    u'\u0432'   #  0xD7 -> CYRILLIC SMALL LETTER VE
+    u'\u044c'   #  0xD8 -> CYRILLIC SMALL LETTER SOFT SIGN
+    u'\u044b'   #  0xD9 -> CYRILLIC SMALL LETTER YERU
+    u'\u0437'   #  0xDA -> CYRILLIC SMALL LETTER ZE
+    u'\u0448'   #  0xDB -> CYRILLIC SMALL LETTER SHA
+    u'\u044d'   #  0xDC -> CYRILLIC SMALL LETTER E
+    u'\u0449'   #  0xDD -> CYRILLIC SMALL LETTER SHCHA
+    u'\u0447'   #  0xDE -> CYRILLIC SMALL LETTER CHE
+    u'\u044a'   #  0xDF -> CYRILLIC SMALL LETTER HARD SIGN
+    u'\u042e'   #  0xE0 -> CYRILLIC CAPITAL LETTER YU
+    u'\u0410'   #  0xE1 -> CYRILLIC CAPITAL LETTER A
+    u'\u0411'   #  0xE2 -> CYRILLIC CAPITAL LETTER BE
+    u'\u0426'   #  0xE3 -> CYRILLIC CAPITAL LETTER TSE
+    u'\u0414'   #  0xE4 -> CYRILLIC CAPITAL LETTER DE
+    u'\u0415'   #  0xE5 -> CYRILLIC CAPITAL LETTER IE
+    u'\u0424'   #  0xE6 -> CYRILLIC CAPITAL LETTER EF
+    u'\u0413'   #  0xE7 -> CYRILLIC CAPITAL LETTER GHE
+    u'\u0425'   #  0xE8 -> CYRILLIC CAPITAL LETTER HA
+    u'\u0418'   #  0xE9 -> CYRILLIC CAPITAL LETTER I
+    u'\u0419'   #  0xEA -> CYRILLIC CAPITAL LETTER SHORT I
+    u'\u041a'   #  0xEB -> CYRILLIC CAPITAL LETTER KA
+    u'\u041b'   #  0xEC -> CYRILLIC CAPITAL LETTER EL
+    u'\u041c'   #  0xED -> CYRILLIC CAPITAL LETTER EM
+    u'\u041d'   #  0xEE -> CYRILLIC CAPITAL LETTER EN
+    u'\u041e'   #  0xEF -> CYRILLIC CAPITAL LETTER O
+    u'\u041f'   #  0xF0 -> CYRILLIC CAPITAL LETTER PE
+    u'\u042f'   #  0xF1 -> CYRILLIC CAPITAL LETTER YA
+    u'\u0420'   #  0xF2 -> CYRILLIC CAPITAL LETTER ER
+    u'\u0421'   #  0xF3 -> CYRILLIC CAPITAL LETTER ES
+    u'\u0422'   #  0xF4 -> CYRILLIC CAPITAL LETTER TE
+    u'\u0423'   #  0xF5 -> CYRILLIC CAPITAL LETTER U
+    u'\u0416'   #  0xF6 -> CYRILLIC CAPITAL LETTER ZHE
+    u'\u0412'   #  0xF7 -> CYRILLIC CAPITAL LETTER VE
+    u'\u042c'   #  0xF8 -> CYRILLIC CAPITAL LETTER SOFT SIGN
+    u'\u042b'   #  0xF9 -> CYRILLIC CAPITAL LETTER YERU
+    u'\u0417'   #  0xFA -> CYRILLIC CAPITAL LETTER ZE
+    u'\u0428'   #  0xFB -> CYRILLIC CAPITAL LETTER SHA
+    u'\u042d'   #  0xFC -> CYRILLIC CAPITAL LETTER E
+    u'\u0429'   #  0xFD -> CYRILLIC CAPITAL LETTER SHCHA
+    u'\u0427'   #  0xFE -> CYRILLIC CAPITAL LETTER CHE
+    u'\u042a'   #  0xFF -> CYRILLIC CAPITAL LETTER HARD SIGN
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/latin_1.py b/src/main/resources/PythonLibs/encodings/latin_1.py
new file mode 100644
index 0000000000000000000000000000000000000000..370160c0cb512f25573985bce277ea2f590a420c
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/latin_1.py
@@ -0,0 +1,50 @@
+""" Python 'latin-1' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    # Note: Binding these as C functions will result in the class not
+    # converting them to methods. This is intended.
+    encode = codecs.latin_1_encode
+    decode = codecs.latin_1_decode
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.latin_1_encode(input,self.errors)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.latin_1_decode(input,self.errors)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+class StreamConverter(StreamWriter,StreamReader):
+
+    encode = codecs.latin_1_decode
+    decode = codecs.latin_1_encode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='iso8859-1',
+        encode=Codec.encode,
+        decode=Codec.decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/mac_arabic.py b/src/main/resources/PythonLibs/encodings/mac_arabic.py
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d3c5f7fe41be0b0ab8e1afbe25984789636d8
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_arabic.py
@@ -0,0 +1,698 @@
+""" Python Character Mapping Codec generated from 'VENDORS/APPLE/ARABIC.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-arabic',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+    0x0080: 0x00c4,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x0081: 0x00a0,     #  NO-BREAK SPACE, right-left
+    0x0082: 0x00c7,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x0083: 0x00c9,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x0084: 0x00d1,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x0085: 0x00d6,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x0086: 0x00dc,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x0087: 0x00e1,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x0088: 0x00e0,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x0089: 0x00e2,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x008a: 0x00e4,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x008b: 0x06ba,     #  ARABIC LETTER NOON GHUNNA
+    0x008c: 0x00ab,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left
+    0x008d: 0x00e7,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x008e: 0x00e9,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x008f: 0x00e8,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x0090: 0x00ea,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x0091: 0x00eb,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x0092: 0x00ed,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x0093: 0x2026,     #  HORIZONTAL ELLIPSIS, right-left
+    0x0094: 0x00ee,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x0095: 0x00ef,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x0096: 0x00f1,     #  LATIN SMALL LETTER N WITH TILDE
+    0x0097: 0x00f3,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x0098: 0x00bb,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left
+    0x0099: 0x00f4,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x009a: 0x00f6,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x009b: 0x00f7,     #  DIVISION SIGN, right-left
+    0x009c: 0x00fa,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x009d: 0x00f9,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x009e: 0x00fb,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x009f: 0x00fc,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x00a0: 0x0020,     #  SPACE, right-left
+    0x00a1: 0x0021,     #  EXCLAMATION MARK, right-left
+    0x00a2: 0x0022,     #  QUOTATION MARK, right-left
+    0x00a3: 0x0023,     #  NUMBER SIGN, right-left
+    0x00a4: 0x0024,     #  DOLLAR SIGN, right-left
+    0x00a5: 0x066a,     #  ARABIC PERCENT SIGN
+    0x00a6: 0x0026,     #  AMPERSAND, right-left
+    0x00a7: 0x0027,     #  APOSTROPHE, right-left
+    0x00a8: 0x0028,     #  LEFT PARENTHESIS, right-left
+    0x00a9: 0x0029,     #  RIGHT PARENTHESIS, right-left
+    0x00aa: 0x002a,     #  ASTERISK, right-left
+    0x00ab: 0x002b,     #  PLUS SIGN, right-left
+    0x00ac: 0x060c,     #  ARABIC COMMA
+    0x00ad: 0x002d,     #  HYPHEN-MINUS, right-left
+    0x00ae: 0x002e,     #  FULL STOP, right-left
+    0x00af: 0x002f,     #  SOLIDUS, right-left
+    0x00b0: 0x0660,     #  ARABIC-INDIC DIGIT ZERO, right-left (need override)
+    0x00b1: 0x0661,     #  ARABIC-INDIC DIGIT ONE, right-left (need override)
+    0x00b2: 0x0662,     #  ARABIC-INDIC DIGIT TWO, right-left (need override)
+    0x00b3: 0x0663,     #  ARABIC-INDIC DIGIT THREE, right-left (need override)
+    0x00b4: 0x0664,     #  ARABIC-INDIC DIGIT FOUR, right-left (need override)
+    0x00b5: 0x0665,     #  ARABIC-INDIC DIGIT FIVE, right-left (need override)
+    0x00b6: 0x0666,     #  ARABIC-INDIC DIGIT SIX, right-left (need override)
+    0x00b7: 0x0667,     #  ARABIC-INDIC DIGIT SEVEN, right-left (need override)
+    0x00b8: 0x0668,     #  ARABIC-INDIC DIGIT EIGHT, right-left (need override)
+    0x00b9: 0x0669,     #  ARABIC-INDIC DIGIT NINE, right-left (need override)
+    0x00ba: 0x003a,     #  COLON, right-left
+    0x00bb: 0x061b,     #  ARABIC SEMICOLON
+    0x00bc: 0x003c,     #  LESS-THAN SIGN, right-left
+    0x00bd: 0x003d,     #  EQUALS SIGN, right-left
+    0x00be: 0x003e,     #  GREATER-THAN SIGN, right-left
+    0x00bf: 0x061f,     #  ARABIC QUESTION MARK
+    0x00c0: 0x274a,     #  EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left
+    0x00c1: 0x0621,     #  ARABIC LETTER HAMZA
+    0x00c2: 0x0622,     #  ARABIC LETTER ALEF WITH MADDA ABOVE
+    0x00c3: 0x0623,     #  ARABIC LETTER ALEF WITH HAMZA ABOVE
+    0x00c4: 0x0624,     #  ARABIC LETTER WAW WITH HAMZA ABOVE
+    0x00c5: 0x0625,     #  ARABIC LETTER ALEF WITH HAMZA BELOW
+    0x00c6: 0x0626,     #  ARABIC LETTER YEH WITH HAMZA ABOVE
+    0x00c7: 0x0627,     #  ARABIC LETTER ALEF
+    0x00c8: 0x0628,     #  ARABIC LETTER BEH
+    0x00c9: 0x0629,     #  ARABIC LETTER TEH MARBUTA
+    0x00ca: 0x062a,     #  ARABIC LETTER TEH
+    0x00cb: 0x062b,     #  ARABIC LETTER THEH
+    0x00cc: 0x062c,     #  ARABIC LETTER JEEM
+    0x00cd: 0x062d,     #  ARABIC LETTER HAH
+    0x00ce: 0x062e,     #  ARABIC LETTER KHAH
+    0x00cf: 0x062f,     #  ARABIC LETTER DAL
+    0x00d0: 0x0630,     #  ARABIC LETTER THAL
+    0x00d1: 0x0631,     #  ARABIC LETTER REH
+    0x00d2: 0x0632,     #  ARABIC LETTER ZAIN
+    0x00d3: 0x0633,     #  ARABIC LETTER SEEN
+    0x00d4: 0x0634,     #  ARABIC LETTER SHEEN
+    0x00d5: 0x0635,     #  ARABIC LETTER SAD
+    0x00d6: 0x0636,     #  ARABIC LETTER DAD
+    0x00d7: 0x0637,     #  ARABIC LETTER TAH
+    0x00d8: 0x0638,     #  ARABIC LETTER ZAH
+    0x00d9: 0x0639,     #  ARABIC LETTER AIN
+    0x00da: 0x063a,     #  ARABIC LETTER GHAIN
+    0x00db: 0x005b,     #  LEFT SQUARE BRACKET, right-left
+    0x00dc: 0x005c,     #  REVERSE SOLIDUS, right-left
+    0x00dd: 0x005d,     #  RIGHT SQUARE BRACKET, right-left
+    0x00de: 0x005e,     #  CIRCUMFLEX ACCENT, right-left
+    0x00df: 0x005f,     #  LOW LINE, right-left
+    0x00e0: 0x0640,     #  ARABIC TATWEEL
+    0x00e1: 0x0641,     #  ARABIC LETTER FEH
+    0x00e2: 0x0642,     #  ARABIC LETTER QAF
+    0x00e3: 0x0643,     #  ARABIC LETTER KAF
+    0x00e4: 0x0644,     #  ARABIC LETTER LAM
+    0x00e5: 0x0645,     #  ARABIC LETTER MEEM
+    0x00e6: 0x0646,     #  ARABIC LETTER NOON
+    0x00e7: 0x0647,     #  ARABIC LETTER HEH
+    0x00e8: 0x0648,     #  ARABIC LETTER WAW
+    0x00e9: 0x0649,     #  ARABIC LETTER ALEF MAKSURA
+    0x00ea: 0x064a,     #  ARABIC LETTER YEH
+    0x00eb: 0x064b,     #  ARABIC FATHATAN
+    0x00ec: 0x064c,     #  ARABIC DAMMATAN
+    0x00ed: 0x064d,     #  ARABIC KASRATAN
+    0x00ee: 0x064e,     #  ARABIC FATHA
+    0x00ef: 0x064f,     #  ARABIC DAMMA
+    0x00f0: 0x0650,     #  ARABIC KASRA
+    0x00f1: 0x0651,     #  ARABIC SHADDA
+    0x00f2: 0x0652,     #  ARABIC SUKUN
+    0x00f3: 0x067e,     #  ARABIC LETTER PEH
+    0x00f4: 0x0679,     #  ARABIC LETTER TTEH
+    0x00f5: 0x0686,     #  ARABIC LETTER TCHEH
+    0x00f6: 0x06d5,     #  ARABIC LETTER AE
+    0x00f7: 0x06a4,     #  ARABIC LETTER VEH
+    0x00f8: 0x06af,     #  ARABIC LETTER GAF
+    0x00f9: 0x0688,     #  ARABIC LETTER DDAL
+    0x00fa: 0x0691,     #  ARABIC LETTER RREH
+    0x00fb: 0x007b,     #  LEFT CURLY BRACKET, right-left
+    0x00fc: 0x007c,     #  VERTICAL LINE, right-left
+    0x00fd: 0x007d,     #  RIGHT CURLY BRACKET, right-left
+    0x00fe: 0x0698,     #  ARABIC LETTER JEH
+    0x00ff: 0x06d2,     #  ARABIC LETTER YEH BARREE
+})
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x0000 -> CONTROL CHARACTER
+    u'\x01'     #  0x0001 -> CONTROL CHARACTER
+    u'\x02'     #  0x0002 -> CONTROL CHARACTER
+    u'\x03'     #  0x0003 -> CONTROL CHARACTER
+    u'\x04'     #  0x0004 -> CONTROL CHARACTER
+    u'\x05'     #  0x0005 -> CONTROL CHARACTER
+    u'\x06'     #  0x0006 -> CONTROL CHARACTER
+    u'\x07'     #  0x0007 -> CONTROL CHARACTER
+    u'\x08'     #  0x0008 -> CONTROL CHARACTER
+    u'\t'       #  0x0009 -> CONTROL CHARACTER
+    u'\n'       #  0x000a -> CONTROL CHARACTER
+    u'\x0b'     #  0x000b -> CONTROL CHARACTER
+    u'\x0c'     #  0x000c -> CONTROL CHARACTER
+    u'\r'       #  0x000d -> CONTROL CHARACTER
+    u'\x0e'     #  0x000e -> CONTROL CHARACTER
+    u'\x0f'     #  0x000f -> CONTROL CHARACTER
+    u'\x10'     #  0x0010 -> CONTROL CHARACTER
+    u'\x11'     #  0x0011 -> CONTROL CHARACTER
+    u'\x12'     #  0x0012 -> CONTROL CHARACTER
+    u'\x13'     #  0x0013 -> CONTROL CHARACTER
+    u'\x14'     #  0x0014 -> CONTROL CHARACTER
+    u'\x15'     #  0x0015 -> CONTROL CHARACTER
+    u'\x16'     #  0x0016 -> CONTROL CHARACTER
+    u'\x17'     #  0x0017 -> CONTROL CHARACTER
+    u'\x18'     #  0x0018 -> CONTROL CHARACTER
+    u'\x19'     #  0x0019 -> CONTROL CHARACTER
+    u'\x1a'     #  0x001a -> CONTROL CHARACTER
+    u'\x1b'     #  0x001b -> CONTROL CHARACTER
+    u'\x1c'     #  0x001c -> CONTROL CHARACTER
+    u'\x1d'     #  0x001d -> CONTROL CHARACTER
+    u'\x1e'     #  0x001e -> CONTROL CHARACTER
+    u'\x1f'     #  0x001f -> CONTROL CHARACTER
+    u' '        #  0x0020 -> SPACE, left-right
+    u'!'        #  0x0021 -> EXCLAMATION MARK, left-right
+    u'"'        #  0x0022 -> QUOTATION MARK, left-right
+    u'#'        #  0x0023 -> NUMBER SIGN, left-right
+    u'$'        #  0x0024 -> DOLLAR SIGN, left-right
+    u'%'        #  0x0025 -> PERCENT SIGN, left-right
+    u'&'        #  0x0026 -> AMPERSAND, left-right
+    u"'"        #  0x0027 -> APOSTROPHE, left-right
+    u'('        #  0x0028 -> LEFT PARENTHESIS, left-right
+    u')'        #  0x0029 -> RIGHT PARENTHESIS, left-right
+    u'*'        #  0x002a -> ASTERISK, left-right
+    u'+'        #  0x002b -> PLUS SIGN, left-right
+    u','        #  0x002c -> COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR
+    u'-'        #  0x002d -> HYPHEN-MINUS, left-right
+    u'.'        #  0x002e -> FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR
+    u'/'        #  0x002f -> SOLIDUS, left-right
+    u'0'        #  0x0030 -> DIGIT ZERO;  in Arabic-script context, displayed as 0x0660 ARABIC-INDIC DIGIT ZERO
+    u'1'        #  0x0031 -> DIGIT ONE;   in Arabic-script context, displayed as 0x0661 ARABIC-INDIC DIGIT ONE
+    u'2'        #  0x0032 -> DIGIT TWO;   in Arabic-script context, displayed as 0x0662 ARABIC-INDIC DIGIT TWO
+    u'3'        #  0x0033 -> DIGIT THREE; in Arabic-script context, displayed as 0x0663 ARABIC-INDIC DIGIT THREE
+    u'4'        #  0x0034 -> DIGIT FOUR;  in Arabic-script context, displayed as 0x0664 ARABIC-INDIC DIGIT FOUR
+    u'5'        #  0x0035 -> DIGIT FIVE;  in Arabic-script context, displayed as 0x0665 ARABIC-INDIC DIGIT FIVE
+    u'6'        #  0x0036 -> DIGIT SIX;   in Arabic-script context, displayed as 0x0666 ARABIC-INDIC DIGIT SIX
+    u'7'        #  0x0037 -> DIGIT SEVEN; in Arabic-script context, displayed as 0x0667 ARABIC-INDIC DIGIT SEVEN
+    u'8'        #  0x0038 -> DIGIT EIGHT; in Arabic-script context, displayed as 0x0668 ARABIC-INDIC DIGIT EIGHT
+    u'9'        #  0x0039 -> DIGIT NINE;  in Arabic-script context, displayed as 0x0669 ARABIC-INDIC DIGIT NINE
+    u':'        #  0x003a -> COLON, left-right
+    u';'        #  0x003b -> SEMICOLON, left-right
+    u'<'        #  0x003c -> LESS-THAN SIGN, left-right
+    u'='        #  0x003d -> EQUALS SIGN, left-right
+    u'>'        #  0x003e -> GREATER-THAN SIGN, left-right
+    u'?'        #  0x003f -> QUESTION MARK, left-right
+    u'@'        #  0x0040 -> COMMERCIAL AT
+    u'A'        #  0x0041 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x0042 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x0043 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x0044 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x0045 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x0046 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x0047 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x0048 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x0049 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x004a -> LATIN CAPITAL LETTER J
+    u'K'        #  0x004b -> LATIN CAPITAL LETTER K
+    u'L'        #  0x004c -> LATIN CAPITAL LETTER L
+    u'M'        #  0x004d -> LATIN CAPITAL LETTER M
+    u'N'        #  0x004e -> LATIN CAPITAL LETTER N
+    u'O'        #  0x004f -> LATIN CAPITAL LETTER O
+    u'P'        #  0x0050 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x0051 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x0052 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x0053 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x0054 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x0055 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x0056 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x0057 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x0058 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x0059 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x005a -> LATIN CAPITAL LETTER Z
+    u'['        #  0x005b -> LEFT SQUARE BRACKET, left-right
+    u'\\'       #  0x005c -> REVERSE SOLIDUS, left-right
+    u']'        #  0x005d -> RIGHT SQUARE BRACKET, left-right
+    u'^'        #  0x005e -> CIRCUMFLEX ACCENT, left-right
+    u'_'        #  0x005f -> LOW LINE, left-right
+    u'`'        #  0x0060 -> GRAVE ACCENT
+    u'a'        #  0x0061 -> LATIN SMALL LETTER A
+    u'b'        #  0x0062 -> LATIN SMALL LETTER B
+    u'c'        #  0x0063 -> LATIN SMALL LETTER C
+    u'd'        #  0x0064 -> LATIN SMALL LETTER D
+    u'e'        #  0x0065 -> LATIN SMALL LETTER E
+    u'f'        #  0x0066 -> LATIN SMALL LETTER F
+    u'g'        #  0x0067 -> LATIN SMALL LETTER G
+    u'h'        #  0x0068 -> LATIN SMALL LETTER H
+    u'i'        #  0x0069 -> LATIN SMALL LETTER I
+    u'j'        #  0x006a -> LATIN SMALL LETTER J
+    u'k'        #  0x006b -> LATIN SMALL LETTER K
+    u'l'        #  0x006c -> LATIN SMALL LETTER L
+    u'm'        #  0x006d -> LATIN SMALL LETTER M
+    u'n'        #  0x006e -> LATIN SMALL LETTER N
+    u'o'        #  0x006f -> LATIN SMALL LETTER O
+    u'p'        #  0x0070 -> LATIN SMALL LETTER P
+    u'q'        #  0x0071 -> LATIN SMALL LETTER Q
+    u'r'        #  0x0072 -> LATIN SMALL LETTER R
+    u's'        #  0x0073 -> LATIN SMALL LETTER S
+    u't'        #  0x0074 -> LATIN SMALL LETTER T
+    u'u'        #  0x0075 -> LATIN SMALL LETTER U
+    u'v'        #  0x0076 -> LATIN SMALL LETTER V
+    u'w'        #  0x0077 -> LATIN SMALL LETTER W
+    u'x'        #  0x0078 -> LATIN SMALL LETTER X
+    u'y'        #  0x0079 -> LATIN SMALL LETTER Y
+    u'z'        #  0x007a -> LATIN SMALL LETTER Z
+    u'{'        #  0x007b -> LEFT CURLY BRACKET, left-right
+    u'|'        #  0x007c -> VERTICAL LINE, left-right
+    u'}'        #  0x007d -> RIGHT CURLY BRACKET, left-right
+    u'~'        #  0x007e -> TILDE
+    u'\x7f'     #  0x007f -> CONTROL CHARACTER
+    u'\xc4'     #  0x0080 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xa0'     #  0x0081 -> NO-BREAK SPACE, right-left
+    u'\xc7'     #  0x0082 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc9'     #  0x0083 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xd1'     #  0x0084 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd6'     #  0x0085 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x0086 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xe1'     #  0x0087 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe0'     #  0x0088 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe2'     #  0x0089 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x008a -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u06ba'   #  0x008b -> ARABIC LETTER NOON GHUNNA
+    u'\xab'     #  0x008c -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left
+    u'\xe7'     #  0x008d -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe9'     #  0x008e -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe8'     #  0x008f -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xea'     #  0x0090 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x0091 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xed'     #  0x0092 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\u2026'   #  0x0093 -> HORIZONTAL ELLIPSIS, right-left
+    u'\xee'     #  0x0094 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x0095 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf1'     #  0x0096 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf3'     #  0x0097 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xbb'     #  0x0098 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left
+    u'\xf4'     #  0x0099 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x009a -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0x009b -> DIVISION SIGN, right-left
+    u'\xfa'     #  0x009c -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf9'     #  0x009d -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfb'     #  0x009e -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0x009f -> LATIN SMALL LETTER U WITH DIAERESIS
+    u' '        #  0x00a0 -> SPACE, right-left
+    u'!'        #  0x00a1 -> EXCLAMATION MARK, right-left
+    u'"'        #  0x00a2 -> QUOTATION MARK, right-left
+    u'#'        #  0x00a3 -> NUMBER SIGN, right-left
+    u'$'        #  0x00a4 -> DOLLAR SIGN, right-left
+    u'\u066a'   #  0x00a5 -> ARABIC PERCENT SIGN
+    u'&'        #  0x00a6 -> AMPERSAND, right-left
+    u"'"        #  0x00a7 -> APOSTROPHE, right-left
+    u'('        #  0x00a8 -> LEFT PARENTHESIS, right-left
+    u')'        #  0x00a9 -> RIGHT PARENTHESIS, right-left
+    u'*'        #  0x00aa -> ASTERISK, right-left
+    u'+'        #  0x00ab -> PLUS SIGN, right-left
+    u'\u060c'   #  0x00ac -> ARABIC COMMA
+    u'-'        #  0x00ad -> HYPHEN-MINUS, right-left
+    u'.'        #  0x00ae -> FULL STOP, right-left
+    u'/'        #  0x00af -> SOLIDUS, right-left
+    u'\u0660'   #  0x00b0 -> ARABIC-INDIC DIGIT ZERO, right-left (need override)
+    u'\u0661'   #  0x00b1 -> ARABIC-INDIC DIGIT ONE, right-left (need override)
+    u'\u0662'   #  0x00b2 -> ARABIC-INDIC DIGIT TWO, right-left (need override)
+    u'\u0663'   #  0x00b3 -> ARABIC-INDIC DIGIT THREE, right-left (need override)
+    u'\u0664'   #  0x00b4 -> ARABIC-INDIC DIGIT FOUR, right-left (need override)
+    u'\u0665'   #  0x00b5 -> ARABIC-INDIC DIGIT FIVE, right-left (need override)
+    u'\u0666'   #  0x00b6 -> ARABIC-INDIC DIGIT SIX, right-left (need override)
+    u'\u0667'   #  0x00b7 -> ARABIC-INDIC DIGIT SEVEN, right-left (need override)
+    u'\u0668'   #  0x00b8 -> ARABIC-INDIC DIGIT EIGHT, right-left (need override)
+    u'\u0669'   #  0x00b9 -> ARABIC-INDIC DIGIT NINE, right-left (need override)
+    u':'        #  0x00ba -> COLON, right-left
+    u'\u061b'   #  0x00bb -> ARABIC SEMICOLON
+    u'<'        #  0x00bc -> LESS-THAN SIGN, right-left
+    u'='        #  0x00bd -> EQUALS SIGN, right-left
+    u'>'        #  0x00be -> GREATER-THAN SIGN, right-left
+    u'\u061f'   #  0x00bf -> ARABIC QUESTION MARK
+    u'\u274a'   #  0x00c0 -> EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left
+    u'\u0621'   #  0x00c1 -> ARABIC LETTER HAMZA
+    u'\u0622'   #  0x00c2 -> ARABIC LETTER ALEF WITH MADDA ABOVE
+    u'\u0623'   #  0x00c3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE
+    u'\u0624'   #  0x00c4 -> ARABIC LETTER WAW WITH HAMZA ABOVE
+    u'\u0625'   #  0x00c5 -> ARABIC LETTER ALEF WITH HAMZA BELOW
+    u'\u0626'   #  0x00c6 -> ARABIC LETTER YEH WITH HAMZA ABOVE
+    u'\u0627'   #  0x00c7 -> ARABIC LETTER ALEF
+    u'\u0628'   #  0x00c8 -> ARABIC LETTER BEH
+    u'\u0629'   #  0x00c9 -> ARABIC LETTER TEH MARBUTA
+    u'\u062a'   #  0x00ca -> ARABIC LETTER TEH
+    u'\u062b'   #  0x00cb -> ARABIC LETTER THEH
+    u'\u062c'   #  0x00cc -> ARABIC LETTER JEEM
+    u'\u062d'   #  0x00cd -> ARABIC LETTER HAH
+    u'\u062e'   #  0x00ce -> ARABIC LETTER KHAH
+    u'\u062f'   #  0x00cf -> ARABIC LETTER DAL
+    u'\u0630'   #  0x00d0 -> ARABIC LETTER THAL
+    u'\u0631'   #  0x00d1 -> ARABIC LETTER REH
+    u'\u0632'   #  0x00d2 -> ARABIC LETTER ZAIN
+    u'\u0633'   #  0x00d3 -> ARABIC LETTER SEEN
+    u'\u0634'   #  0x00d4 -> ARABIC LETTER SHEEN
+    u'\u0635'   #  0x00d5 -> ARABIC LETTER SAD
+    u'\u0636'   #  0x00d6 -> ARABIC LETTER DAD
+    u'\u0637'   #  0x00d7 -> ARABIC LETTER TAH
+    u'\u0638'   #  0x00d8 -> ARABIC LETTER ZAH
+    u'\u0639'   #  0x00d9 -> ARABIC LETTER AIN
+    u'\u063a'   #  0x00da -> ARABIC LETTER GHAIN
+    u'['        #  0x00db -> LEFT SQUARE BRACKET, right-left
+    u'\\'       #  0x00dc -> REVERSE SOLIDUS, right-left
+    u']'        #  0x00dd -> RIGHT SQUARE BRACKET, right-left
+    u'^'        #  0x00de -> CIRCUMFLEX ACCENT, right-left
+    u'_'        #  0x00df -> LOW LINE, right-left
+    u'\u0640'   #  0x00e0 -> ARABIC TATWEEL
+    u'\u0641'   #  0x00e1 -> ARABIC LETTER FEH
+    u'\u0642'   #  0x00e2 -> ARABIC LETTER QAF
+    u'\u0643'   #  0x00e3 -> ARABIC LETTER KAF
+    u'\u0644'   #  0x00e4 -> ARABIC LETTER LAM
+    u'\u0645'   #  0x00e5 -> ARABIC LETTER MEEM
+    u'\u0646'   #  0x00e6 -> ARABIC LETTER NOON
+    u'\u0647'   #  0x00e7 -> ARABIC LETTER HEH
+    u'\u0648'   #  0x00e8 -> ARABIC LETTER WAW
+    u'\u0649'   #  0x00e9 -> ARABIC LETTER ALEF MAKSURA
+    u'\u064a'   #  0x00ea -> ARABIC LETTER YEH
+    u'\u064b'   #  0x00eb -> ARABIC FATHATAN
+    u'\u064c'   #  0x00ec -> ARABIC DAMMATAN
+    u'\u064d'   #  0x00ed -> ARABIC KASRATAN
+    u'\u064e'   #  0x00ee -> ARABIC FATHA
+    u'\u064f'   #  0x00ef -> ARABIC DAMMA
+    u'\u0650'   #  0x00f0 -> ARABIC KASRA
+    u'\u0651'   #  0x00f1 -> ARABIC SHADDA
+    u'\u0652'   #  0x00f2 -> ARABIC SUKUN
+    u'\u067e'   #  0x00f3 -> ARABIC LETTER PEH
+    u'\u0679'   #  0x00f4 -> ARABIC LETTER TTEH
+    u'\u0686'   #  0x00f5 -> ARABIC LETTER TCHEH
+    u'\u06d5'   #  0x00f6 -> ARABIC LETTER AE
+    u'\u06a4'   #  0x00f7 -> ARABIC LETTER VEH
+    u'\u06af'   #  0x00f8 -> ARABIC LETTER GAF
+    u'\u0688'   #  0x00f9 -> ARABIC LETTER DDAL
+    u'\u0691'   #  0x00fa -> ARABIC LETTER RREH
+    u'{'        #  0x00fb -> LEFT CURLY BRACKET, right-left
+    u'|'        #  0x00fc -> VERTICAL LINE, right-left
+    u'}'        #  0x00fd -> RIGHT CURLY BRACKET, right-left
+    u'\u0698'   #  0x00fe -> ARABIC LETTER JEH
+    u'\u06d2'   #  0x00ff -> ARABIC LETTER YEH BARREE
+)
+
+### Encoding Map
+
+encoding_map = {
+    0x0000: 0x0000,     #  CONTROL CHARACTER
+    0x0001: 0x0001,     #  CONTROL CHARACTER
+    0x0002: 0x0002,     #  CONTROL CHARACTER
+    0x0003: 0x0003,     #  CONTROL CHARACTER
+    0x0004: 0x0004,     #  CONTROL CHARACTER
+    0x0005: 0x0005,     #  CONTROL CHARACTER
+    0x0006: 0x0006,     #  CONTROL CHARACTER
+    0x0007: 0x0007,     #  CONTROL CHARACTER
+    0x0008: 0x0008,     #  CONTROL CHARACTER
+    0x0009: 0x0009,     #  CONTROL CHARACTER
+    0x000a: 0x000a,     #  CONTROL CHARACTER
+    0x000b: 0x000b,     #  CONTROL CHARACTER
+    0x000c: 0x000c,     #  CONTROL CHARACTER
+    0x000d: 0x000d,     #  CONTROL CHARACTER
+    0x000e: 0x000e,     #  CONTROL CHARACTER
+    0x000f: 0x000f,     #  CONTROL CHARACTER
+    0x0010: 0x0010,     #  CONTROL CHARACTER
+    0x0011: 0x0011,     #  CONTROL CHARACTER
+    0x0012: 0x0012,     #  CONTROL CHARACTER
+    0x0013: 0x0013,     #  CONTROL CHARACTER
+    0x0014: 0x0014,     #  CONTROL CHARACTER
+    0x0015: 0x0015,     #  CONTROL CHARACTER
+    0x0016: 0x0016,     #  CONTROL CHARACTER
+    0x0017: 0x0017,     #  CONTROL CHARACTER
+    0x0018: 0x0018,     #  CONTROL CHARACTER
+    0x0019: 0x0019,     #  CONTROL CHARACTER
+    0x001a: 0x001a,     #  CONTROL CHARACTER
+    0x001b: 0x001b,     #  CONTROL CHARACTER
+    0x001c: 0x001c,     #  CONTROL CHARACTER
+    0x001d: 0x001d,     #  CONTROL CHARACTER
+    0x001e: 0x001e,     #  CONTROL CHARACTER
+    0x001f: 0x001f,     #  CONTROL CHARACTER
+    0x0020: 0x0020,     #  SPACE, left-right
+    0x0020: 0x00a0,     #  SPACE, right-left
+    0x0021: 0x0021,     #  EXCLAMATION MARK, left-right
+    0x0021: 0x00a1,     #  EXCLAMATION MARK, right-left
+    0x0022: 0x0022,     #  QUOTATION MARK, left-right
+    0x0022: 0x00a2,     #  QUOTATION MARK, right-left
+    0x0023: 0x0023,     #  NUMBER SIGN, left-right
+    0x0023: 0x00a3,     #  NUMBER SIGN, right-left
+    0x0024: 0x0024,     #  DOLLAR SIGN, left-right
+    0x0024: 0x00a4,     #  DOLLAR SIGN, right-left
+    0x0025: 0x0025,     #  PERCENT SIGN, left-right
+    0x0026: 0x0026,     #  AMPERSAND, left-right
+    0x0026: 0x00a6,     #  AMPERSAND, right-left
+    0x0027: 0x0027,     #  APOSTROPHE, left-right
+    0x0027: 0x00a7,     #  APOSTROPHE, right-left
+    0x0028: 0x0028,     #  LEFT PARENTHESIS, left-right
+    0x0028: 0x00a8,     #  LEFT PARENTHESIS, right-left
+    0x0029: 0x0029,     #  RIGHT PARENTHESIS, left-right
+    0x0029: 0x00a9,     #  RIGHT PARENTHESIS, right-left
+    0x002a: 0x002a,     #  ASTERISK, left-right
+    0x002a: 0x00aa,     #  ASTERISK, right-left
+    0x002b: 0x002b,     #  PLUS SIGN, left-right
+    0x002b: 0x00ab,     #  PLUS SIGN, right-left
+    0x002c: 0x002c,     #  COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR
+    0x002d: 0x002d,     #  HYPHEN-MINUS, left-right
+    0x002d: 0x00ad,     #  HYPHEN-MINUS, right-left
+    0x002e: 0x002e,     #  FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR
+    0x002e: 0x00ae,     #  FULL STOP, right-left
+    0x002f: 0x002f,     #  SOLIDUS, left-right
+    0x002f: 0x00af,     #  SOLIDUS, right-left
+    0x0030: 0x0030,     #  DIGIT ZERO;  in Arabic-script context, displayed as 0x0660 ARABIC-INDIC DIGIT ZERO
+    0x0031: 0x0031,     #  DIGIT ONE;   in Arabic-script context, displayed as 0x0661 ARABIC-INDIC DIGIT ONE
+    0x0032: 0x0032,     #  DIGIT TWO;   in Arabic-script context, displayed as 0x0662 ARABIC-INDIC DIGIT TWO
+    0x0033: 0x0033,     #  DIGIT THREE; in Arabic-script context, displayed as 0x0663 ARABIC-INDIC DIGIT THREE
+    0x0034: 0x0034,     #  DIGIT FOUR;  in Arabic-script context, displayed as 0x0664 ARABIC-INDIC DIGIT FOUR
+    0x0035: 0x0035,     #  DIGIT FIVE;  in Arabic-script context, displayed as 0x0665 ARABIC-INDIC DIGIT FIVE
+    0x0036: 0x0036,     #  DIGIT SIX;   in Arabic-script context, displayed as 0x0666 ARABIC-INDIC DIGIT SIX
+    0x0037: 0x0037,     #  DIGIT SEVEN; in Arabic-script context, displayed as 0x0667 ARABIC-INDIC DIGIT SEVEN
+    0x0038: 0x0038,     #  DIGIT EIGHT; in Arabic-script context, displayed as 0x0668 ARABIC-INDIC DIGIT EIGHT
+    0x0039: 0x0039,     #  DIGIT NINE;  in Arabic-script context, displayed as 0x0669 ARABIC-INDIC DIGIT NINE
+    0x003a: 0x003a,     #  COLON, left-right
+    0x003a: 0x00ba,     #  COLON, right-left
+    0x003b: 0x003b,     #  SEMICOLON, left-right
+    0x003c: 0x003c,     #  LESS-THAN SIGN, left-right
+    0x003c: 0x00bc,     #  LESS-THAN SIGN, right-left
+    0x003d: 0x003d,     #  EQUALS SIGN, left-right
+    0x003d: 0x00bd,     #  EQUALS SIGN, right-left
+    0x003e: 0x003e,     #  GREATER-THAN SIGN, left-right
+    0x003e: 0x00be,     #  GREATER-THAN SIGN, right-left
+    0x003f: 0x003f,     #  QUESTION MARK, left-right
+    0x0040: 0x0040,     #  COMMERCIAL AT
+    0x0041: 0x0041,     #  LATIN CAPITAL LETTER A
+    0x0042: 0x0042,     #  LATIN CAPITAL LETTER B
+    0x0043: 0x0043,     #  LATIN CAPITAL LETTER C
+    0x0044: 0x0044,     #  LATIN CAPITAL LETTER D
+    0x0045: 0x0045,     #  LATIN CAPITAL LETTER E
+    0x0046: 0x0046,     #  LATIN CAPITAL LETTER F
+    0x0047: 0x0047,     #  LATIN CAPITAL LETTER G
+    0x0048: 0x0048,     #  LATIN CAPITAL LETTER H
+    0x0049: 0x0049,     #  LATIN CAPITAL LETTER I
+    0x004a: 0x004a,     #  LATIN CAPITAL LETTER J
+    0x004b: 0x004b,     #  LATIN CAPITAL LETTER K
+    0x004c: 0x004c,     #  LATIN CAPITAL LETTER L
+    0x004d: 0x004d,     #  LATIN CAPITAL LETTER M
+    0x004e: 0x004e,     #  LATIN CAPITAL LETTER N
+    0x004f: 0x004f,     #  LATIN CAPITAL LETTER O
+    0x0050: 0x0050,     #  LATIN CAPITAL LETTER P
+    0x0051: 0x0051,     #  LATIN CAPITAL LETTER Q
+    0x0052: 0x0052,     #  LATIN CAPITAL LETTER R
+    0x0053: 0x0053,     #  LATIN CAPITAL LETTER S
+    0x0054: 0x0054,     #  LATIN CAPITAL LETTER T
+    0x0055: 0x0055,     #  LATIN CAPITAL LETTER U
+    0x0056: 0x0056,     #  LATIN CAPITAL LETTER V
+    0x0057: 0x0057,     #  LATIN CAPITAL LETTER W
+    0x0058: 0x0058,     #  LATIN CAPITAL LETTER X
+    0x0059: 0x0059,     #  LATIN CAPITAL LETTER Y
+    0x005a: 0x005a,     #  LATIN CAPITAL LETTER Z
+    0x005b: 0x005b,     #  LEFT SQUARE BRACKET, left-right
+    0x005b: 0x00db,     #  LEFT SQUARE BRACKET, right-left
+    0x005c: 0x005c,     #  REVERSE SOLIDUS, left-right
+    0x005c: 0x00dc,     #  REVERSE SOLIDUS, right-left
+    0x005d: 0x005d,     #  RIGHT SQUARE BRACKET, left-right
+    0x005d: 0x00dd,     #  RIGHT SQUARE BRACKET, right-left
+    0x005e: 0x005e,     #  CIRCUMFLEX ACCENT, left-right
+    0x005e: 0x00de,     #  CIRCUMFLEX ACCENT, right-left
+    0x005f: 0x005f,     #  LOW LINE, left-right
+    0x005f: 0x00df,     #  LOW LINE, right-left
+    0x0060: 0x0060,     #  GRAVE ACCENT
+    0x0061: 0x0061,     #  LATIN SMALL LETTER A
+    0x0062: 0x0062,     #  LATIN SMALL LETTER B
+    0x0063: 0x0063,     #  LATIN SMALL LETTER C
+    0x0064: 0x0064,     #  LATIN SMALL LETTER D
+    0x0065: 0x0065,     #  LATIN SMALL LETTER E
+    0x0066: 0x0066,     #  LATIN SMALL LETTER F
+    0x0067: 0x0067,     #  LATIN SMALL LETTER G
+    0x0068: 0x0068,     #  LATIN SMALL LETTER H
+    0x0069: 0x0069,     #  LATIN SMALL LETTER I
+    0x006a: 0x006a,     #  LATIN SMALL LETTER J
+    0x006b: 0x006b,     #  LATIN SMALL LETTER K
+    0x006c: 0x006c,     #  LATIN SMALL LETTER L
+    0x006d: 0x006d,     #  LATIN SMALL LETTER M
+    0x006e: 0x006e,     #  LATIN SMALL LETTER N
+    0x006f: 0x006f,     #  LATIN SMALL LETTER O
+    0x0070: 0x0070,     #  LATIN SMALL LETTER P
+    0x0071: 0x0071,     #  LATIN SMALL LETTER Q
+    0x0072: 0x0072,     #  LATIN SMALL LETTER R
+    0x0073: 0x0073,     #  LATIN SMALL LETTER S
+    0x0074: 0x0074,     #  LATIN SMALL LETTER T
+    0x0075: 0x0075,     #  LATIN SMALL LETTER U
+    0x0076: 0x0076,     #  LATIN SMALL LETTER V
+    0x0077: 0x0077,     #  LATIN SMALL LETTER W
+    0x0078: 0x0078,     #  LATIN SMALL LETTER X
+    0x0079: 0x0079,     #  LATIN SMALL LETTER Y
+    0x007a: 0x007a,     #  LATIN SMALL LETTER Z
+    0x007b: 0x007b,     #  LEFT CURLY BRACKET, left-right
+    0x007b: 0x00fb,     #  LEFT CURLY BRACKET, right-left
+    0x007c: 0x007c,     #  VERTICAL LINE, left-right
+    0x007c: 0x00fc,     #  VERTICAL LINE, right-left
+    0x007d: 0x007d,     #  RIGHT CURLY BRACKET, left-right
+    0x007d: 0x00fd,     #  RIGHT CURLY BRACKET, right-left
+    0x007e: 0x007e,     #  TILDE
+    0x007f: 0x007f,     #  CONTROL CHARACTER
+    0x00a0: 0x0081,     #  NO-BREAK SPACE, right-left
+    0x00ab: 0x008c,     #  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left
+    0x00bb: 0x0098,     #  RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left
+    0x00c4: 0x0080,     #  LATIN CAPITAL LETTER A WITH DIAERESIS
+    0x00c7: 0x0082,     #  LATIN CAPITAL LETTER C WITH CEDILLA
+    0x00c9: 0x0083,     #  LATIN CAPITAL LETTER E WITH ACUTE
+    0x00d1: 0x0084,     #  LATIN CAPITAL LETTER N WITH TILDE
+    0x00d6: 0x0085,     #  LATIN CAPITAL LETTER O WITH DIAERESIS
+    0x00dc: 0x0086,     #  LATIN CAPITAL LETTER U WITH DIAERESIS
+    0x00e0: 0x0088,     #  LATIN SMALL LETTER A WITH GRAVE
+    0x00e1: 0x0087,     #  LATIN SMALL LETTER A WITH ACUTE
+    0x00e2: 0x0089,     #  LATIN SMALL LETTER A WITH CIRCUMFLEX
+    0x00e4: 0x008a,     #  LATIN SMALL LETTER A WITH DIAERESIS
+    0x00e7: 0x008d,     #  LATIN SMALL LETTER C WITH CEDILLA
+    0x00e8: 0x008f,     #  LATIN SMALL LETTER E WITH GRAVE
+    0x00e9: 0x008e,     #  LATIN SMALL LETTER E WITH ACUTE
+    0x00ea: 0x0090,     #  LATIN SMALL LETTER E WITH CIRCUMFLEX
+    0x00eb: 0x0091,     #  LATIN SMALL LETTER E WITH DIAERESIS
+    0x00ed: 0x0092,     #  LATIN SMALL LETTER I WITH ACUTE
+    0x00ee: 0x0094,     #  LATIN SMALL LETTER I WITH CIRCUMFLEX
+    0x00ef: 0x0095,     #  LATIN SMALL LETTER I WITH DIAERESIS
+    0x00f1: 0x0096,     #  LATIN SMALL LETTER N WITH TILDE
+    0x00f3: 0x0097,     #  LATIN SMALL LETTER O WITH ACUTE
+    0x00f4: 0x0099,     #  LATIN SMALL LETTER O WITH CIRCUMFLEX
+    0x00f6: 0x009a,     #  LATIN SMALL LETTER O WITH DIAERESIS
+    0x00f7: 0x009b,     #  DIVISION SIGN, right-left
+    0x00f9: 0x009d,     #  LATIN SMALL LETTER U WITH GRAVE
+    0x00fa: 0x009c,     #  LATIN SMALL LETTER U WITH ACUTE
+    0x00fb: 0x009e,     #  LATIN SMALL LETTER U WITH CIRCUMFLEX
+    0x00fc: 0x009f,     #  LATIN SMALL LETTER U WITH DIAERESIS
+    0x060c: 0x00ac,     #  ARABIC COMMA
+    0x061b: 0x00bb,     #  ARABIC SEMICOLON
+    0x061f: 0x00bf,     #  ARABIC QUESTION MARK
+    0x0621: 0x00c1,     #  ARABIC LETTER HAMZA
+    0x0622: 0x00c2,     #  ARABIC LETTER ALEF WITH MADDA ABOVE
+    0x0623: 0x00c3,     #  ARABIC LETTER ALEF WITH HAMZA ABOVE
+    0x0624: 0x00c4,     #  ARABIC LETTER WAW WITH HAMZA ABOVE
+    0x0625: 0x00c5,     #  ARABIC LETTER ALEF WITH HAMZA BELOW
+    0x0626: 0x00c6,     #  ARABIC LETTER YEH WITH HAMZA ABOVE
+    0x0627: 0x00c7,     #  ARABIC LETTER ALEF
+    0x0628: 0x00c8,     #  ARABIC LETTER BEH
+    0x0629: 0x00c9,     #  ARABIC LETTER TEH MARBUTA
+    0x062a: 0x00ca,     #  ARABIC LETTER TEH
+    0x062b: 0x00cb,     #  ARABIC LETTER THEH
+    0x062c: 0x00cc,     #  ARABIC LETTER JEEM
+    0x062d: 0x00cd,     #  ARABIC LETTER HAH
+    0x062e: 0x00ce,     #  ARABIC LETTER KHAH
+    0x062f: 0x00cf,     #  ARABIC LETTER DAL
+    0x0630: 0x00d0,     #  ARABIC LETTER THAL
+    0x0631: 0x00d1,     #  ARABIC LETTER REH
+    0x0632: 0x00d2,     #  ARABIC LETTER ZAIN
+    0x0633: 0x00d3,     #  ARABIC LETTER SEEN
+    0x0634: 0x00d4,     #  ARABIC LETTER SHEEN
+    0x0635: 0x00d5,     #  ARABIC LETTER SAD
+    0x0636: 0x00d6,     #  ARABIC LETTER DAD
+    0x0637: 0x00d7,     #  ARABIC LETTER TAH
+    0x0638: 0x00d8,     #  ARABIC LETTER ZAH
+    0x0639: 0x00d9,     #  ARABIC LETTER AIN
+    0x063a: 0x00da,     #  ARABIC LETTER GHAIN
+    0x0640: 0x00e0,     #  ARABIC TATWEEL
+    0x0641: 0x00e1,     #  ARABIC LETTER FEH
+    0x0642: 0x00e2,     #  ARABIC LETTER QAF
+    0x0643: 0x00e3,     #  ARABIC LETTER KAF
+    0x0644: 0x00e4,     #  ARABIC LETTER LAM
+    0x0645: 0x00e5,     #  ARABIC LETTER MEEM
+    0x0646: 0x00e6,     #  ARABIC LETTER NOON
+    0x0647: 0x00e7,     #  ARABIC LETTER HEH
+    0x0648: 0x00e8,     #  ARABIC LETTER WAW
+    0x0649: 0x00e9,     #  ARABIC LETTER ALEF MAKSURA
+    0x064a: 0x00ea,     #  ARABIC LETTER YEH
+    0x064b: 0x00eb,     #  ARABIC FATHATAN
+    0x064c: 0x00ec,     #  ARABIC DAMMATAN
+    0x064d: 0x00ed,     #  ARABIC KASRATAN
+    0x064e: 0x00ee,     #  ARABIC FATHA
+    0x064f: 0x00ef,     #  ARABIC DAMMA
+    0x0650: 0x00f0,     #  ARABIC KASRA
+    0x0651: 0x00f1,     #  ARABIC SHADDA
+    0x0652: 0x00f2,     #  ARABIC SUKUN
+    0x0660: 0x00b0,     #  ARABIC-INDIC DIGIT ZERO, right-left (need override)
+    0x0661: 0x00b1,     #  ARABIC-INDIC DIGIT ONE, right-left (need override)
+    0x0662: 0x00b2,     #  ARABIC-INDIC DIGIT TWO, right-left (need override)
+    0x0663: 0x00b3,     #  ARABIC-INDIC DIGIT THREE, right-left (need override)
+    0x0664: 0x00b4,     #  ARABIC-INDIC DIGIT FOUR, right-left (need override)
+    0x0665: 0x00b5,     #  ARABIC-INDIC DIGIT FIVE, right-left (need override)
+    0x0666: 0x00b6,     #  ARABIC-INDIC DIGIT SIX, right-left (need override)
+    0x0667: 0x00b7,     #  ARABIC-INDIC DIGIT SEVEN, right-left (need override)
+    0x0668: 0x00b8,     #  ARABIC-INDIC DIGIT EIGHT, right-left (need override)
+    0x0669: 0x00b9,     #  ARABIC-INDIC DIGIT NINE, right-left (need override)
+    0x066a: 0x00a5,     #  ARABIC PERCENT SIGN
+    0x0679: 0x00f4,     #  ARABIC LETTER TTEH
+    0x067e: 0x00f3,     #  ARABIC LETTER PEH
+    0x0686: 0x00f5,     #  ARABIC LETTER TCHEH
+    0x0688: 0x00f9,     #  ARABIC LETTER DDAL
+    0x0691: 0x00fa,     #  ARABIC LETTER RREH
+    0x0698: 0x00fe,     #  ARABIC LETTER JEH
+    0x06a4: 0x00f7,     #  ARABIC LETTER VEH
+    0x06af: 0x00f8,     #  ARABIC LETTER GAF
+    0x06ba: 0x008b,     #  ARABIC LETTER NOON GHUNNA
+    0x06d2: 0x00ff,     #  ARABIC LETTER YEH BARREE
+    0x06d5: 0x00f6,     #  ARABIC LETTER AE
+    0x2026: 0x0093,     #  HORIZONTAL ELLIPSIS, right-left
+    0x274a: 0x00c0,     #  EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left
+}
diff --git a/src/main/resources/PythonLibs/encodings/mac_centeuro.py b/src/main/resources/PythonLibs/encodings/mac_centeuro.py
new file mode 100644
index 0000000000000000000000000000000000000000..483c8212ace08f95502bee43c15ef4be268ad0e1
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_centeuro.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_centeuro generated from 'MAPPINGS/VENDORS/APPLE/CENTEURO.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-centeuro',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\xc4'     #  0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\u0100'   #  0x81 -> LATIN CAPITAL LETTER A WITH MACRON
+    u'\u0101'   #  0x82 -> LATIN SMALL LETTER A WITH MACRON
+    u'\xc9'     #  0x83 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\u0104'   #  0x84 -> LATIN CAPITAL LETTER A WITH OGONEK
+    u'\xd6'     #  0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xe1'     #  0x87 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\u0105'   #  0x88 -> LATIN SMALL LETTER A WITH OGONEK
+    u'\u010c'   #  0x89 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\xe4'     #  0x8A -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u010d'   #  0x8B -> LATIN SMALL LETTER C WITH CARON
+    u'\u0106'   #  0x8C -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\u0107'   #  0x8D -> LATIN SMALL LETTER C WITH ACUTE
+    u'\xe9'     #  0x8E -> LATIN SMALL LETTER E WITH ACUTE
+    u'\u0179'   #  0x8F -> LATIN CAPITAL LETTER Z WITH ACUTE
+    u'\u017a'   #  0x90 -> LATIN SMALL LETTER Z WITH ACUTE
+    u'\u010e'   #  0x91 -> LATIN CAPITAL LETTER D WITH CARON
+    u'\xed'     #  0x92 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\u010f'   #  0x93 -> LATIN SMALL LETTER D WITH CARON
+    u'\u0112'   #  0x94 -> LATIN CAPITAL LETTER E WITH MACRON
+    u'\u0113'   #  0x95 -> LATIN SMALL LETTER E WITH MACRON
+    u'\u0116'   #  0x96 -> LATIN CAPITAL LETTER E WITH DOT ABOVE
+    u'\xf3'     #  0x97 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\u0117'   #  0x98 -> LATIN SMALL LETTER E WITH DOT ABOVE
+    u'\xf4'     #  0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x9A -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf5'     #  0x9B -> LATIN SMALL LETTER O WITH TILDE
+    u'\xfa'     #  0x9C -> LATIN SMALL LETTER U WITH ACUTE
+    u'\u011a'   #  0x9D -> LATIN CAPITAL LETTER E WITH CARON
+    u'\u011b'   #  0x9E -> LATIN SMALL LETTER E WITH CARON
+    u'\xfc'     #  0x9F -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u2020'   #  0xA0 -> DAGGER
+    u'\xb0'     #  0xA1 -> DEGREE SIGN
+    u'\u0118'   #  0xA2 -> LATIN CAPITAL LETTER E WITH OGONEK
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa7'     #  0xA4 -> SECTION SIGN
+    u'\u2022'   #  0xA5 -> BULLET
+    u'\xb6'     #  0xA6 -> PILCROW SIGN
+    u'\xdf'     #  0xA7 -> LATIN SMALL LETTER SHARP S
+    u'\xae'     #  0xA8 -> REGISTERED SIGN
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u2122'   #  0xAA -> TRADE MARK SIGN
+    u'\u0119'   #  0xAB -> LATIN SMALL LETTER E WITH OGONEK
+    u'\xa8'     #  0xAC -> DIAERESIS
+    u'\u2260'   #  0xAD -> NOT EQUAL TO
+    u'\u0123'   #  0xAE -> LATIN SMALL LETTER G WITH CEDILLA
+    u'\u012e'   #  0xAF -> LATIN CAPITAL LETTER I WITH OGONEK
+    u'\u012f'   #  0xB0 -> LATIN SMALL LETTER I WITH OGONEK
+    u'\u012a'   #  0xB1 -> LATIN CAPITAL LETTER I WITH MACRON
+    u'\u2264'   #  0xB2 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0xB3 -> GREATER-THAN OR EQUAL TO
+    u'\u012b'   #  0xB4 -> LATIN SMALL LETTER I WITH MACRON
+    u'\u0136'   #  0xB5 -> LATIN CAPITAL LETTER K WITH CEDILLA
+    u'\u2202'   #  0xB6 -> PARTIAL DIFFERENTIAL
+    u'\u2211'   #  0xB7 -> N-ARY SUMMATION
+    u'\u0142'   #  0xB8 -> LATIN SMALL LETTER L WITH STROKE
+    u'\u013b'   #  0xB9 -> LATIN CAPITAL LETTER L WITH CEDILLA
+    u'\u013c'   #  0xBA -> LATIN SMALL LETTER L WITH CEDILLA
+    u'\u013d'   #  0xBB -> LATIN CAPITAL LETTER L WITH CARON
+    u'\u013e'   #  0xBC -> LATIN SMALL LETTER L WITH CARON
+    u'\u0139'   #  0xBD -> LATIN CAPITAL LETTER L WITH ACUTE
+    u'\u013a'   #  0xBE -> LATIN SMALL LETTER L WITH ACUTE
+    u'\u0145'   #  0xBF -> LATIN CAPITAL LETTER N WITH CEDILLA
+    u'\u0146'   #  0xC0 -> LATIN SMALL LETTER N WITH CEDILLA
+    u'\u0143'   #  0xC1 -> LATIN CAPITAL LETTER N WITH ACUTE
+    u'\xac'     #  0xC2 -> NOT SIGN
+    u'\u221a'   #  0xC3 -> SQUARE ROOT
+    u'\u0144'   #  0xC4 -> LATIN SMALL LETTER N WITH ACUTE
+    u'\u0147'   #  0xC5 -> LATIN CAPITAL LETTER N WITH CARON
+    u'\u2206'   #  0xC6 -> INCREMENT
+    u'\xab'     #  0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2026'   #  0xC9 -> HORIZONTAL ELLIPSIS
+    u'\xa0'     #  0xCA -> NO-BREAK SPACE
+    u'\u0148'   #  0xCB -> LATIN SMALL LETTER N WITH CARON
+    u'\u0150'   #  0xCC -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+    u'\xd5'     #  0xCD -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\u0151'   #  0xCE -> LATIN SMALL LETTER O WITH DOUBLE ACUTE
+    u'\u014c'   #  0xCF -> LATIN CAPITAL LETTER O WITH MACRON
+    u'\u2013'   #  0xD0 -> EN DASH
+    u'\u2014'   #  0xD1 -> EM DASH
+    u'\u201c'   #  0xD2 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0xD3 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2018'   #  0xD4 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xD5 -> RIGHT SINGLE QUOTATION MARK
+    u'\xf7'     #  0xD6 -> DIVISION SIGN
+    u'\u25ca'   #  0xD7 -> LOZENGE
+    u'\u014d'   #  0xD8 -> LATIN SMALL LETTER O WITH MACRON
+    u'\u0154'   #  0xD9 -> LATIN CAPITAL LETTER R WITH ACUTE
+    u'\u0155'   #  0xDA -> LATIN SMALL LETTER R WITH ACUTE
+    u'\u0158'   #  0xDB -> LATIN CAPITAL LETTER R WITH CARON
+    u'\u2039'   #  0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u203a'   #  0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\u0159'   #  0xDE -> LATIN SMALL LETTER R WITH CARON
+    u'\u0156'   #  0xDF -> LATIN CAPITAL LETTER R WITH CEDILLA
+    u'\u0157'   #  0xE0 -> LATIN SMALL LETTER R WITH CEDILLA
+    u'\u0160'   #  0xE1 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u201a'   #  0xE2 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u201e'   #  0xE3 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u0161'   #  0xE4 -> LATIN SMALL LETTER S WITH CARON
+    u'\u015a'   #  0xE5 -> LATIN CAPITAL LETTER S WITH ACUTE
+    u'\u015b'   #  0xE6 -> LATIN SMALL LETTER S WITH ACUTE
+    u'\xc1'     #  0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\u0164'   #  0xE8 -> LATIN CAPITAL LETTER T WITH CARON
+    u'\u0165'   #  0xE9 -> LATIN SMALL LETTER T WITH CARON
+    u'\xcd'     #  0xEA -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\u017d'   #  0xEB -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\u017e'   #  0xEC -> LATIN SMALL LETTER Z WITH CARON
+    u'\u016a'   #  0xED -> LATIN CAPITAL LETTER U WITH MACRON
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\u016b'   #  0xF0 -> LATIN SMALL LETTER U WITH MACRON
+    u'\u016e'   #  0xF1 -> LATIN CAPITAL LETTER U WITH RING ABOVE
+    u'\xda'     #  0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\u016f'   #  0xF3 -> LATIN SMALL LETTER U WITH RING ABOVE
+    u'\u0170'   #  0xF4 -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+    u'\u0171'   #  0xF5 -> LATIN SMALL LETTER U WITH DOUBLE ACUTE
+    u'\u0172'   #  0xF6 -> LATIN CAPITAL LETTER U WITH OGONEK
+    u'\u0173'   #  0xF7 -> LATIN SMALL LETTER U WITH OGONEK
+    u'\xdd'     #  0xF8 -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xfd'     #  0xF9 -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\u0137'   #  0xFA -> LATIN SMALL LETTER K WITH CEDILLA
+    u'\u017b'   #  0xFB -> LATIN CAPITAL LETTER Z WITH DOT ABOVE
+    u'\u0141'   #  0xFC -> LATIN CAPITAL LETTER L WITH STROKE
+    u'\u017c'   #  0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE
+    u'\u0122'   #  0xFE -> LATIN CAPITAL LETTER G WITH CEDILLA
+    u'\u02c7'   #  0xFF -> CARON
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mac_croatian.py b/src/main/resources/PythonLibs/encodings/mac_croatian.py
new file mode 100644
index 0000000000000000000000000000000000000000..f57f7b4b33fe6a6f90b5069783a523e2804908f8
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_croatian.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_croatian generated from 'MAPPINGS/VENDORS/APPLE/CROATIAN.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-croatian',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\xc4'     #  0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc7'     #  0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc9'     #  0x83 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xd1'     #  0x84 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd6'     #  0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xe1'     #  0x87 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe0'     #  0x88 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe2'     #  0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x8A -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe3'     #  0x8B -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x8C -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x8D -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe9'     #  0x8E -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe8'     #  0x8F -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xea'     #  0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x91 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xed'     #  0x92 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xec'     #  0x93 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xee'     #  0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x95 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf1'     #  0x96 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf3'     #  0x97 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf2'     #  0x98 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf4'     #  0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x9A -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf5'     #  0x9B -> LATIN SMALL LETTER O WITH TILDE
+    u'\xfa'     #  0x9C -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf9'     #  0x9D -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfb'     #  0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0x9F -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u2020'   #  0xA0 -> DAGGER
+    u'\xb0'     #  0xA1 -> DEGREE SIGN
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa7'     #  0xA4 -> SECTION SIGN
+    u'\u2022'   #  0xA5 -> BULLET
+    u'\xb6'     #  0xA6 -> PILCROW SIGN
+    u'\xdf'     #  0xA7 -> LATIN SMALL LETTER SHARP S
+    u'\xae'     #  0xA8 -> REGISTERED SIGN
+    u'\u0160'   #  0xA9 -> LATIN CAPITAL LETTER S WITH CARON
+    u'\u2122'   #  0xAA -> TRADE MARK SIGN
+    u'\xb4'     #  0xAB -> ACUTE ACCENT
+    u'\xa8'     #  0xAC -> DIAERESIS
+    u'\u2260'   #  0xAD -> NOT EQUAL TO
+    u'\u017d'   #  0xAE -> LATIN CAPITAL LETTER Z WITH CARON
+    u'\xd8'     #  0xAF -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u221e'   #  0xB0 -> INFINITY
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u2264'   #  0xB2 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0xB3 -> GREATER-THAN OR EQUAL TO
+    u'\u2206'   #  0xB4 -> INCREMENT
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\u2202'   #  0xB6 -> PARTIAL DIFFERENTIAL
+    u'\u2211'   #  0xB7 -> N-ARY SUMMATION
+    u'\u220f'   #  0xB8 -> N-ARY PRODUCT
+    u'\u0161'   #  0xB9 -> LATIN SMALL LETTER S WITH CARON
+    u'\u222b'   #  0xBA -> INTEGRAL
+    u'\xaa'     #  0xBB -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0xBC -> MASCULINE ORDINAL INDICATOR
+    u'\u03a9'   #  0xBD -> GREEK CAPITAL LETTER OMEGA
+    u'\u017e'   #  0xBE -> LATIN SMALL LETTER Z WITH CARON
+    u'\xf8'     #  0xBF -> LATIN SMALL LETTER O WITH STROKE
+    u'\xbf'     #  0xC0 -> INVERTED QUESTION MARK
+    u'\xa1'     #  0xC1 -> INVERTED EXCLAMATION MARK
+    u'\xac'     #  0xC2 -> NOT SIGN
+    u'\u221a'   #  0xC3 -> SQUARE ROOT
+    u'\u0192'   #  0xC4 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u2248'   #  0xC5 -> ALMOST EQUAL TO
+    u'\u0106'   #  0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE
+    u'\xab'     #  0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u010c'   #  0xC8 -> LATIN CAPITAL LETTER C WITH CARON
+    u'\u2026'   #  0xC9 -> HORIZONTAL ELLIPSIS
+    u'\xa0'     #  0xCA -> NO-BREAK SPACE
+    u'\xc0'     #  0xCB -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc3'     #  0xCC -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xd5'     #  0xCD -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\u0152'   #  0xCE -> LATIN CAPITAL LIGATURE OE
+    u'\u0153'   #  0xCF -> LATIN SMALL LIGATURE OE
+    u'\u0110'   #  0xD0 -> LATIN CAPITAL LETTER D WITH STROKE
+    u'\u2014'   #  0xD1 -> EM DASH
+    u'\u201c'   #  0xD2 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0xD3 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2018'   #  0xD4 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xD5 -> RIGHT SINGLE QUOTATION MARK
+    u'\xf7'     #  0xD6 -> DIVISION SIGN
+    u'\u25ca'   #  0xD7 -> LOZENGE
+    u'\uf8ff'   #  0xD8 -> Apple logo
+    u'\xa9'     #  0xD9 -> COPYRIGHT SIGN
+    u'\u2044'   #  0xDA -> FRACTION SLASH
+    u'\u20ac'   #  0xDB -> EURO SIGN
+    u'\u2039'   #  0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u203a'   #  0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\xc6'     #  0xDE -> LATIN CAPITAL LETTER AE
+    u'\xbb'     #  0xDF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2013'   #  0xE0 -> EN DASH
+    u'\xb7'     #  0xE1 -> MIDDLE DOT
+    u'\u201a'   #  0xE2 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u201e'   #  0xE3 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2030'   #  0xE4 -> PER MILLE SIGN
+    u'\xc2'     #  0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\u0107'   #  0xE6 -> LATIN SMALL LETTER C WITH ACUTE
+    u'\xc1'     #  0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\u010d'   #  0xE8 -> LATIN SMALL LETTER C WITH CARON
+    u'\xc8'     #  0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0xEA -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0xED -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\u0111'   #  0xF0 -> LATIN SMALL LETTER D WITH STROKE
+    u'\xd2'     #  0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xda'     #  0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xd9'     #  0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\u0131'   #  0xF5 -> LATIN SMALL LETTER DOTLESS I
+    u'\u02c6'   #  0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u02dc'   #  0xF7 -> SMALL TILDE
+    u'\xaf'     #  0xF8 -> MACRON
+    u'\u03c0'   #  0xF9 -> GREEK SMALL LETTER PI
+    u'\xcb'     #  0xFA -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\u02da'   #  0xFB -> RING ABOVE
+    u'\xb8'     #  0xFC -> CEDILLA
+    u'\xca'     #  0xFD -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xe6'     #  0xFE -> LATIN SMALL LETTER AE
+    u'\u02c7'   #  0xFF -> CARON
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mac_cyrillic.py b/src/main/resources/PythonLibs/encodings/mac_cyrillic.py
new file mode 100644
index 0000000000000000000000000000000000000000..63324a14b86528fd32c0002a8417252a70ffbcd7
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_cyrillic.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_cyrillic generated from 'MAPPINGS/VENDORS/APPLE/CYRILLIC.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-cyrillic',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\u0410'   #  0x80 -> CYRILLIC CAPITAL LETTER A
+    u'\u0411'   #  0x81 -> CYRILLIC CAPITAL LETTER BE
+    u'\u0412'   #  0x82 -> CYRILLIC CAPITAL LETTER VE
+    u'\u0413'   #  0x83 -> CYRILLIC CAPITAL LETTER GHE
+    u'\u0414'   #  0x84 -> CYRILLIC CAPITAL LETTER DE
+    u'\u0415'   #  0x85 -> CYRILLIC CAPITAL LETTER IE
+    u'\u0416'   #  0x86 -> CYRILLIC CAPITAL LETTER ZHE
+    u'\u0417'   #  0x87 -> CYRILLIC CAPITAL LETTER ZE
+    u'\u0418'   #  0x88 -> CYRILLIC CAPITAL LETTER I
+    u'\u0419'   #  0x89 -> CYRILLIC CAPITAL LETTER SHORT I
+    u'\u041a'   #  0x8A -> CYRILLIC CAPITAL LETTER KA
+    u'\u041b'   #  0x8B -> CYRILLIC CAPITAL LETTER EL
+    u'\u041c'   #  0x8C -> CYRILLIC CAPITAL LETTER EM
+    u'\u041d'   #  0x8D -> CYRILLIC CAPITAL LETTER EN
+    u'\u041e'   #  0x8E -> CYRILLIC CAPITAL LETTER O
+    u'\u041f'   #  0x8F -> CYRILLIC CAPITAL LETTER PE
+    u'\u0420'   #  0x90 -> CYRILLIC CAPITAL LETTER ER
+    u'\u0421'   #  0x91 -> CYRILLIC CAPITAL LETTER ES
+    u'\u0422'   #  0x92 -> CYRILLIC CAPITAL LETTER TE
+    u'\u0423'   #  0x93 -> CYRILLIC CAPITAL LETTER U
+    u'\u0424'   #  0x94 -> CYRILLIC CAPITAL LETTER EF
+    u'\u0425'   #  0x95 -> CYRILLIC CAPITAL LETTER HA
+    u'\u0426'   #  0x96 -> CYRILLIC CAPITAL LETTER TSE
+    u'\u0427'   #  0x97 -> CYRILLIC CAPITAL LETTER CHE
+    u'\u0428'   #  0x98 -> CYRILLIC CAPITAL LETTER SHA
+    u'\u0429'   #  0x99 -> CYRILLIC CAPITAL LETTER SHCHA
+    u'\u042a'   #  0x9A -> CYRILLIC CAPITAL LETTER HARD SIGN
+    u'\u042b'   #  0x9B -> CYRILLIC CAPITAL LETTER YERU
+    u'\u042c'   #  0x9C -> CYRILLIC CAPITAL LETTER SOFT SIGN
+    u'\u042d'   #  0x9D -> CYRILLIC CAPITAL LETTER E
+    u'\u042e'   #  0x9E -> CYRILLIC CAPITAL LETTER YU
+    u'\u042f'   #  0x9F -> CYRILLIC CAPITAL LETTER YA
+    u'\u2020'   #  0xA0 -> DAGGER
+    u'\xb0'     #  0xA1 -> DEGREE SIGN
+    u'\u0490'   #  0xA2 -> CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa7'     #  0xA4 -> SECTION SIGN
+    u'\u2022'   #  0xA5 -> BULLET
+    u'\xb6'     #  0xA6 -> PILCROW SIGN
+    u'\u0406'   #  0xA7 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\xae'     #  0xA8 -> REGISTERED SIGN
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u2122'   #  0xAA -> TRADE MARK SIGN
+    u'\u0402'   #  0xAB -> CYRILLIC CAPITAL LETTER DJE
+    u'\u0452'   #  0xAC -> CYRILLIC SMALL LETTER DJE
+    u'\u2260'   #  0xAD -> NOT EQUAL TO
+    u'\u0403'   #  0xAE -> CYRILLIC CAPITAL LETTER GJE
+    u'\u0453'   #  0xAF -> CYRILLIC SMALL LETTER GJE
+    u'\u221e'   #  0xB0 -> INFINITY
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u2264'   #  0xB2 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0xB3 -> GREATER-THAN OR EQUAL TO
+    u'\u0456'   #  0xB4 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\u0491'   #  0xB6 -> CYRILLIC SMALL LETTER GHE WITH UPTURN
+    u'\u0408'   #  0xB7 -> CYRILLIC CAPITAL LETTER JE
+    u'\u0404'   #  0xB8 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE
+    u'\u0454'   #  0xB9 -> CYRILLIC SMALL LETTER UKRAINIAN IE
+    u'\u0407'   #  0xBA -> CYRILLIC CAPITAL LETTER YI
+    u'\u0457'   #  0xBB -> CYRILLIC SMALL LETTER YI
+    u'\u0409'   #  0xBC -> CYRILLIC CAPITAL LETTER LJE
+    u'\u0459'   #  0xBD -> CYRILLIC SMALL LETTER LJE
+    u'\u040a'   #  0xBE -> CYRILLIC CAPITAL LETTER NJE
+    u'\u045a'   #  0xBF -> CYRILLIC SMALL LETTER NJE
+    u'\u0458'   #  0xC0 -> CYRILLIC SMALL LETTER JE
+    u'\u0405'   #  0xC1 -> CYRILLIC CAPITAL LETTER DZE
+    u'\xac'     #  0xC2 -> NOT SIGN
+    u'\u221a'   #  0xC3 -> SQUARE ROOT
+    u'\u0192'   #  0xC4 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u2248'   #  0xC5 -> ALMOST EQUAL TO
+    u'\u2206'   #  0xC6 -> INCREMENT
+    u'\xab'     #  0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2026'   #  0xC9 -> HORIZONTAL ELLIPSIS
+    u'\xa0'     #  0xCA -> NO-BREAK SPACE
+    u'\u040b'   #  0xCB -> CYRILLIC CAPITAL LETTER TSHE
+    u'\u045b'   #  0xCC -> CYRILLIC SMALL LETTER TSHE
+    u'\u040c'   #  0xCD -> CYRILLIC CAPITAL LETTER KJE
+    u'\u045c'   #  0xCE -> CYRILLIC SMALL LETTER KJE
+    u'\u0455'   #  0xCF -> CYRILLIC SMALL LETTER DZE
+    u'\u2013'   #  0xD0 -> EN DASH
+    u'\u2014'   #  0xD1 -> EM DASH
+    u'\u201c'   #  0xD2 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0xD3 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2018'   #  0xD4 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xD5 -> RIGHT SINGLE QUOTATION MARK
+    u'\xf7'     #  0xD6 -> DIVISION SIGN
+    u'\u201e'   #  0xD7 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u040e'   #  0xD8 -> CYRILLIC CAPITAL LETTER SHORT U
+    u'\u045e'   #  0xD9 -> CYRILLIC SMALL LETTER SHORT U
+    u'\u040f'   #  0xDA -> CYRILLIC CAPITAL LETTER DZHE
+    u'\u045f'   #  0xDB -> CYRILLIC SMALL LETTER DZHE
+    u'\u2116'   #  0xDC -> NUMERO SIGN
+    u'\u0401'   #  0xDD -> CYRILLIC CAPITAL LETTER IO
+    u'\u0451'   #  0xDE -> CYRILLIC SMALL LETTER IO
+    u'\u044f'   #  0xDF -> CYRILLIC SMALL LETTER YA
+    u'\u0430'   #  0xE0 -> CYRILLIC SMALL LETTER A
+    u'\u0431'   #  0xE1 -> CYRILLIC SMALL LETTER BE
+    u'\u0432'   #  0xE2 -> CYRILLIC SMALL LETTER VE
+    u'\u0433'   #  0xE3 -> CYRILLIC SMALL LETTER GHE
+    u'\u0434'   #  0xE4 -> CYRILLIC SMALL LETTER DE
+    u'\u0435'   #  0xE5 -> CYRILLIC SMALL LETTER IE
+    u'\u0436'   #  0xE6 -> CYRILLIC SMALL LETTER ZHE
+    u'\u0437'   #  0xE7 -> CYRILLIC SMALL LETTER ZE
+    u'\u0438'   #  0xE8 -> CYRILLIC SMALL LETTER I
+    u'\u0439'   #  0xE9 -> CYRILLIC SMALL LETTER SHORT I
+    u'\u043a'   #  0xEA -> CYRILLIC SMALL LETTER KA
+    u'\u043b'   #  0xEB -> CYRILLIC SMALL LETTER EL
+    u'\u043c'   #  0xEC -> CYRILLIC SMALL LETTER EM
+    u'\u043d'   #  0xED -> CYRILLIC SMALL LETTER EN
+    u'\u043e'   #  0xEE -> CYRILLIC SMALL LETTER O
+    u'\u043f'   #  0xEF -> CYRILLIC SMALL LETTER PE
+    u'\u0440'   #  0xF0 -> CYRILLIC SMALL LETTER ER
+    u'\u0441'   #  0xF1 -> CYRILLIC SMALL LETTER ES
+    u'\u0442'   #  0xF2 -> CYRILLIC SMALL LETTER TE
+    u'\u0443'   #  0xF3 -> CYRILLIC SMALL LETTER U
+    u'\u0444'   #  0xF4 -> CYRILLIC SMALL LETTER EF
+    u'\u0445'   #  0xF5 -> CYRILLIC SMALL LETTER HA
+    u'\u0446'   #  0xF6 -> CYRILLIC SMALL LETTER TSE
+    u'\u0447'   #  0xF7 -> CYRILLIC SMALL LETTER CHE
+    u'\u0448'   #  0xF8 -> CYRILLIC SMALL LETTER SHA
+    u'\u0449'   #  0xF9 -> CYRILLIC SMALL LETTER SHCHA
+    u'\u044a'   #  0xFA -> CYRILLIC SMALL LETTER HARD SIGN
+    u'\u044b'   #  0xFB -> CYRILLIC SMALL LETTER YERU
+    u'\u044c'   #  0xFC -> CYRILLIC SMALL LETTER SOFT SIGN
+    u'\u044d'   #  0xFD -> CYRILLIC SMALL LETTER E
+    u'\u044e'   #  0xFE -> CYRILLIC SMALL LETTER YU
+    u'\u20ac'   #  0xFF -> EURO SIGN
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mac_farsi.py b/src/main/resources/PythonLibs/encodings/mac_farsi.py
new file mode 100644
index 0000000000000000000000000000000000000000..9dbd76a2323324c468e8c0a7cf76a3139eeb449f
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_farsi.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_farsi generated from 'MAPPINGS/VENDORS/APPLE/FARSI.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-farsi',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE, left-right
+    u'!'        #  0x21 -> EXCLAMATION MARK, left-right
+    u'"'        #  0x22 -> QUOTATION MARK, left-right
+    u'#'        #  0x23 -> NUMBER SIGN, left-right
+    u'$'        #  0x24 -> DOLLAR SIGN, left-right
+    u'%'        #  0x25 -> PERCENT SIGN, left-right
+    u'&'        #  0x26 -> AMPERSAND, left-right
+    u"'"        #  0x27 -> APOSTROPHE, left-right
+    u'('        #  0x28 -> LEFT PARENTHESIS, left-right
+    u')'        #  0x29 -> RIGHT PARENTHESIS, left-right
+    u'*'        #  0x2A -> ASTERISK, left-right
+    u'+'        #  0x2B -> PLUS SIGN, left-right
+    u','        #  0x2C -> COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR
+    u'-'        #  0x2D -> HYPHEN-MINUS, left-right
+    u'.'        #  0x2E -> FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR
+    u'/'        #  0x2F -> SOLIDUS, left-right
+    u'0'        #  0x30 -> DIGIT ZERO;  in Arabic-script context, displayed as 0x06F0 EXTENDED ARABIC-INDIC DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE;   in Arabic-script context, displayed as 0x06F1 EXTENDED ARABIC-INDIC DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO;   in Arabic-script context, displayed as 0x06F2 EXTENDED ARABIC-INDIC DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE; in Arabic-script context, displayed as 0x06F3 EXTENDED ARABIC-INDIC DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR;  in Arabic-script context, displayed as 0x06F4 EXTENDED ARABIC-INDIC DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE;  in Arabic-script context, displayed as 0x06F5 EXTENDED ARABIC-INDIC DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX;   in Arabic-script context, displayed as 0x06F6 EXTENDED ARABIC-INDIC DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN; in Arabic-script context, displayed as 0x06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT; in Arabic-script context, displayed as 0x06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE;  in Arabic-script context, displayed as 0x06F9 EXTENDED ARABIC-INDIC DIGIT NINE
+    u':'        #  0x3A -> COLON, left-right
+    u';'        #  0x3B -> SEMICOLON, left-right
+    u'<'        #  0x3C -> LESS-THAN SIGN, left-right
+    u'='        #  0x3D -> EQUALS SIGN, left-right
+    u'>'        #  0x3E -> GREATER-THAN SIGN, left-right
+    u'?'        #  0x3F -> QUESTION MARK, left-right
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET, left-right
+    u'\\'       #  0x5C -> REVERSE SOLIDUS, left-right
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET, left-right
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT, left-right
+    u'_'        #  0x5F -> LOW LINE, left-right
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET, left-right
+    u'|'        #  0x7C -> VERTICAL LINE, left-right
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET, left-right
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\xc4'     #  0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xa0'     #  0x81 -> NO-BREAK SPACE, right-left
+    u'\xc7'     #  0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc9'     #  0x83 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xd1'     #  0x84 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd6'     #  0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xe1'     #  0x87 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe0'     #  0x88 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe2'     #  0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x8A -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u06ba'   #  0x8B -> ARABIC LETTER NOON GHUNNA
+    u'\xab'     #  0x8C -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left
+    u'\xe7'     #  0x8D -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe9'     #  0x8E -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe8'     #  0x8F -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xea'     #  0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x91 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xed'     #  0x92 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\u2026'   #  0x93 -> HORIZONTAL ELLIPSIS, right-left
+    u'\xee'     #  0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x95 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf1'     #  0x96 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf3'     #  0x97 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xbb'     #  0x98 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left
+    u'\xf4'     #  0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x9A -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf7'     #  0x9B -> DIVISION SIGN, right-left
+    u'\xfa'     #  0x9C -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf9'     #  0x9D -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfb'     #  0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0x9F -> LATIN SMALL LETTER U WITH DIAERESIS
+    u' '        #  0xA0 -> SPACE, right-left
+    u'!'        #  0xA1 -> EXCLAMATION MARK, right-left
+    u'"'        #  0xA2 -> QUOTATION MARK, right-left
+    u'#'        #  0xA3 -> NUMBER SIGN, right-left
+    u'$'        #  0xA4 -> DOLLAR SIGN, right-left
+    u'\u066a'   #  0xA5 -> ARABIC PERCENT SIGN
+    u'&'        #  0xA6 -> AMPERSAND, right-left
+    u"'"        #  0xA7 -> APOSTROPHE, right-left
+    u'('        #  0xA8 -> LEFT PARENTHESIS, right-left
+    u')'        #  0xA9 -> RIGHT PARENTHESIS, right-left
+    u'*'        #  0xAA -> ASTERISK, right-left
+    u'+'        #  0xAB -> PLUS SIGN, right-left
+    u'\u060c'   #  0xAC -> ARABIC COMMA
+    u'-'        #  0xAD -> HYPHEN-MINUS, right-left
+    u'.'        #  0xAE -> FULL STOP, right-left
+    u'/'        #  0xAF -> SOLIDUS, right-left
+    u'\u06f0'   #  0xB0 -> EXTENDED ARABIC-INDIC DIGIT ZERO, right-left (need override)
+    u'\u06f1'   #  0xB1 -> EXTENDED ARABIC-INDIC DIGIT ONE, right-left (need override)
+    u'\u06f2'   #  0xB2 -> EXTENDED ARABIC-INDIC DIGIT TWO, right-left (need override)
+    u'\u06f3'   #  0xB3 -> EXTENDED ARABIC-INDIC DIGIT THREE, right-left (need override)
+    u'\u06f4'   #  0xB4 -> EXTENDED ARABIC-INDIC DIGIT FOUR, right-left (need override)
+    u'\u06f5'   #  0xB5 -> EXTENDED ARABIC-INDIC DIGIT FIVE, right-left (need override)
+    u'\u06f6'   #  0xB6 -> EXTENDED ARABIC-INDIC DIGIT SIX, right-left (need override)
+    u'\u06f7'   #  0xB7 -> EXTENDED ARABIC-INDIC DIGIT SEVEN, right-left (need override)
+    u'\u06f8'   #  0xB8 -> EXTENDED ARABIC-INDIC DIGIT EIGHT, right-left (need override)
+    u'\u06f9'   #  0xB9 -> EXTENDED ARABIC-INDIC DIGIT NINE, right-left (need override)
+    u':'        #  0xBA -> COLON, right-left
+    u'\u061b'   #  0xBB -> ARABIC SEMICOLON
+    u'<'        #  0xBC -> LESS-THAN SIGN, right-left
+    u'='        #  0xBD -> EQUALS SIGN, right-left
+    u'>'        #  0xBE -> GREATER-THAN SIGN, right-left
+    u'\u061f'   #  0xBF -> ARABIC QUESTION MARK
+    u'\u274a'   #  0xC0 -> EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left
+    u'\u0621'   #  0xC1 -> ARABIC LETTER HAMZA
+    u'\u0622'   #  0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE
+    u'\u0623'   #  0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE
+    u'\u0624'   #  0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE
+    u'\u0625'   #  0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW
+    u'\u0626'   #  0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE
+    u'\u0627'   #  0xC7 -> ARABIC LETTER ALEF
+    u'\u0628'   #  0xC8 -> ARABIC LETTER BEH
+    u'\u0629'   #  0xC9 -> ARABIC LETTER TEH MARBUTA
+    u'\u062a'   #  0xCA -> ARABIC LETTER TEH
+    u'\u062b'   #  0xCB -> ARABIC LETTER THEH
+    u'\u062c'   #  0xCC -> ARABIC LETTER JEEM
+    u'\u062d'   #  0xCD -> ARABIC LETTER HAH
+    u'\u062e'   #  0xCE -> ARABIC LETTER KHAH
+    u'\u062f'   #  0xCF -> ARABIC LETTER DAL
+    u'\u0630'   #  0xD0 -> ARABIC LETTER THAL
+    u'\u0631'   #  0xD1 -> ARABIC LETTER REH
+    u'\u0632'   #  0xD2 -> ARABIC LETTER ZAIN
+    u'\u0633'   #  0xD3 -> ARABIC LETTER SEEN
+    u'\u0634'   #  0xD4 -> ARABIC LETTER SHEEN
+    u'\u0635'   #  0xD5 -> ARABIC LETTER SAD
+    u'\u0636'   #  0xD6 -> ARABIC LETTER DAD
+    u'\u0637'   #  0xD7 -> ARABIC LETTER TAH
+    u'\u0638'   #  0xD8 -> ARABIC LETTER ZAH
+    u'\u0639'   #  0xD9 -> ARABIC LETTER AIN
+    u'\u063a'   #  0xDA -> ARABIC LETTER GHAIN
+    u'['        #  0xDB -> LEFT SQUARE BRACKET, right-left
+    u'\\'       #  0xDC -> REVERSE SOLIDUS, right-left
+    u']'        #  0xDD -> RIGHT SQUARE BRACKET, right-left
+    u'^'        #  0xDE -> CIRCUMFLEX ACCENT, right-left
+    u'_'        #  0xDF -> LOW LINE, right-left
+    u'\u0640'   #  0xE0 -> ARABIC TATWEEL
+    u'\u0641'   #  0xE1 -> ARABIC LETTER FEH
+    u'\u0642'   #  0xE2 -> ARABIC LETTER QAF
+    u'\u0643'   #  0xE3 -> ARABIC LETTER KAF
+    u'\u0644'   #  0xE4 -> ARABIC LETTER LAM
+    u'\u0645'   #  0xE5 -> ARABIC LETTER MEEM
+    u'\u0646'   #  0xE6 -> ARABIC LETTER NOON
+    u'\u0647'   #  0xE7 -> ARABIC LETTER HEH
+    u'\u0648'   #  0xE8 -> ARABIC LETTER WAW
+    u'\u0649'   #  0xE9 -> ARABIC LETTER ALEF MAKSURA
+    u'\u064a'   #  0xEA -> ARABIC LETTER YEH
+    u'\u064b'   #  0xEB -> ARABIC FATHATAN
+    u'\u064c'   #  0xEC -> ARABIC DAMMATAN
+    u'\u064d'   #  0xED -> ARABIC KASRATAN
+    u'\u064e'   #  0xEE -> ARABIC FATHA
+    u'\u064f'   #  0xEF -> ARABIC DAMMA
+    u'\u0650'   #  0xF0 -> ARABIC KASRA
+    u'\u0651'   #  0xF1 -> ARABIC SHADDA
+    u'\u0652'   #  0xF2 -> ARABIC SUKUN
+    u'\u067e'   #  0xF3 -> ARABIC LETTER PEH
+    u'\u0679'   #  0xF4 -> ARABIC LETTER TTEH
+    u'\u0686'   #  0xF5 -> ARABIC LETTER TCHEH
+    u'\u06d5'   #  0xF6 -> ARABIC LETTER AE
+    u'\u06a4'   #  0xF7 -> ARABIC LETTER VEH
+    u'\u06af'   #  0xF8 -> ARABIC LETTER GAF
+    u'\u0688'   #  0xF9 -> ARABIC LETTER DDAL
+    u'\u0691'   #  0xFA -> ARABIC LETTER RREH
+    u'{'        #  0xFB -> LEFT CURLY BRACKET, right-left
+    u'|'        #  0xFC -> VERTICAL LINE, right-left
+    u'}'        #  0xFD -> RIGHT CURLY BRACKET, right-left
+    u'\u0698'   #  0xFE -> ARABIC LETTER JEH
+    u'\u06d2'   #  0xFF -> ARABIC LETTER YEH BARREE
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mac_greek.py b/src/main/resources/PythonLibs/encodings/mac_greek.py
new file mode 100644
index 0000000000000000000000000000000000000000..68f4fff0dba9bcc75be2afe31a9001f6bd64d132
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_greek.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_greek generated from 'MAPPINGS/VENDORS/APPLE/GREEK.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-greek',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\xc4'     #  0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xb9'     #  0x81 -> SUPERSCRIPT ONE
+    u'\xb2'     #  0x82 -> SUPERSCRIPT TWO
+    u'\xc9'     #  0x83 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xb3'     #  0x84 -> SUPERSCRIPT THREE
+    u'\xd6'     #  0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\u0385'   #  0x87 -> GREEK DIALYTIKA TONOS
+    u'\xe0'     #  0x88 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe2'     #  0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x8A -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\u0384'   #  0x8B -> GREEK TONOS
+    u'\xa8'     #  0x8C -> DIAERESIS
+    u'\xe7'     #  0x8D -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe9'     #  0x8E -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe8'     #  0x8F -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xea'     #  0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x91 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xa3'     #  0x92 -> POUND SIGN
+    u'\u2122'   #  0x93 -> TRADE MARK SIGN
+    u'\xee'     #  0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x95 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\u2022'   #  0x96 -> BULLET
+    u'\xbd'     #  0x97 -> VULGAR FRACTION ONE HALF
+    u'\u2030'   #  0x98 -> PER MILLE SIGN
+    u'\xf4'     #  0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x9A -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xa6'     #  0x9B -> BROKEN BAR
+    u'\u20ac'   #  0x9C -> EURO SIGN # before Mac OS 9.2.2, was SOFT HYPHEN
+    u'\xf9'     #  0x9D -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfb'     #  0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0x9F -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u2020'   #  0xA0 -> DAGGER
+    u'\u0393'   #  0xA1 -> GREEK CAPITAL LETTER GAMMA
+    u'\u0394'   #  0xA2 -> GREEK CAPITAL LETTER DELTA
+    u'\u0398'   #  0xA3 -> GREEK CAPITAL LETTER THETA
+    u'\u039b'   #  0xA4 -> GREEK CAPITAL LETTER LAMDA
+    u'\u039e'   #  0xA5 -> GREEK CAPITAL LETTER XI
+    u'\u03a0'   #  0xA6 -> GREEK CAPITAL LETTER PI
+    u'\xdf'     #  0xA7 -> LATIN SMALL LETTER SHARP S
+    u'\xae'     #  0xA8 -> REGISTERED SIGN
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u03a3'   #  0xAA -> GREEK CAPITAL LETTER SIGMA
+    u'\u03aa'   #  0xAB -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+    u'\xa7'     #  0xAC -> SECTION SIGN
+    u'\u2260'   #  0xAD -> NOT EQUAL TO
+    u'\xb0'     #  0xAE -> DEGREE SIGN
+    u'\xb7'     #  0xAF -> MIDDLE DOT
+    u'\u0391'   #  0xB0 -> GREEK CAPITAL LETTER ALPHA
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u2264'   #  0xB2 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0xB3 -> GREATER-THAN OR EQUAL TO
+    u'\xa5'     #  0xB4 -> YEN SIGN
+    u'\u0392'   #  0xB5 -> GREEK CAPITAL LETTER BETA
+    u'\u0395'   #  0xB6 -> GREEK CAPITAL LETTER EPSILON
+    u'\u0396'   #  0xB7 -> GREEK CAPITAL LETTER ZETA
+    u'\u0397'   #  0xB8 -> GREEK CAPITAL LETTER ETA
+    u'\u0399'   #  0xB9 -> GREEK CAPITAL LETTER IOTA
+    u'\u039a'   #  0xBA -> GREEK CAPITAL LETTER KAPPA
+    u'\u039c'   #  0xBB -> GREEK CAPITAL LETTER MU
+    u'\u03a6'   #  0xBC -> GREEK CAPITAL LETTER PHI
+    u'\u03ab'   #  0xBD -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+    u'\u03a8'   #  0xBE -> GREEK CAPITAL LETTER PSI
+    u'\u03a9'   #  0xBF -> GREEK CAPITAL LETTER OMEGA
+    u'\u03ac'   #  0xC0 -> GREEK SMALL LETTER ALPHA WITH TONOS
+    u'\u039d'   #  0xC1 -> GREEK CAPITAL LETTER NU
+    u'\xac'     #  0xC2 -> NOT SIGN
+    u'\u039f'   #  0xC3 -> GREEK CAPITAL LETTER OMICRON
+    u'\u03a1'   #  0xC4 -> GREEK CAPITAL LETTER RHO
+    u'\u2248'   #  0xC5 -> ALMOST EQUAL TO
+    u'\u03a4'   #  0xC6 -> GREEK CAPITAL LETTER TAU
+    u'\xab'     #  0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2026'   #  0xC9 -> HORIZONTAL ELLIPSIS
+    u'\xa0'     #  0xCA -> NO-BREAK SPACE
+    u'\u03a5'   #  0xCB -> GREEK CAPITAL LETTER UPSILON
+    u'\u03a7'   #  0xCC -> GREEK CAPITAL LETTER CHI
+    u'\u0386'   #  0xCD -> GREEK CAPITAL LETTER ALPHA WITH TONOS
+    u'\u0388'   #  0xCE -> GREEK CAPITAL LETTER EPSILON WITH TONOS
+    u'\u0153'   #  0xCF -> LATIN SMALL LIGATURE OE
+    u'\u2013'   #  0xD0 -> EN DASH
+    u'\u2015'   #  0xD1 -> HORIZONTAL BAR
+    u'\u201c'   #  0xD2 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0xD3 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2018'   #  0xD4 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xD5 -> RIGHT SINGLE QUOTATION MARK
+    u'\xf7'     #  0xD6 -> DIVISION SIGN
+    u'\u0389'   #  0xD7 -> GREEK CAPITAL LETTER ETA WITH TONOS
+    u'\u038a'   #  0xD8 -> GREEK CAPITAL LETTER IOTA WITH TONOS
+    u'\u038c'   #  0xD9 -> GREEK CAPITAL LETTER OMICRON WITH TONOS
+    u'\u038e'   #  0xDA -> GREEK CAPITAL LETTER UPSILON WITH TONOS
+    u'\u03ad'   #  0xDB -> GREEK SMALL LETTER EPSILON WITH TONOS
+    u'\u03ae'   #  0xDC -> GREEK SMALL LETTER ETA WITH TONOS
+    u'\u03af'   #  0xDD -> GREEK SMALL LETTER IOTA WITH TONOS
+    u'\u03cc'   #  0xDE -> GREEK SMALL LETTER OMICRON WITH TONOS
+    u'\u038f'   #  0xDF -> GREEK CAPITAL LETTER OMEGA WITH TONOS
+    u'\u03cd'   #  0xE0 -> GREEK SMALL LETTER UPSILON WITH TONOS
+    u'\u03b1'   #  0xE1 -> GREEK SMALL LETTER ALPHA
+    u'\u03b2'   #  0xE2 -> GREEK SMALL LETTER BETA
+    u'\u03c8'   #  0xE3 -> GREEK SMALL LETTER PSI
+    u'\u03b4'   #  0xE4 -> GREEK SMALL LETTER DELTA
+    u'\u03b5'   #  0xE5 -> GREEK SMALL LETTER EPSILON
+    u'\u03c6'   #  0xE6 -> GREEK SMALL LETTER PHI
+    u'\u03b3'   #  0xE7 -> GREEK SMALL LETTER GAMMA
+    u'\u03b7'   #  0xE8 -> GREEK SMALL LETTER ETA
+    u'\u03b9'   #  0xE9 -> GREEK SMALL LETTER IOTA
+    u'\u03be'   #  0xEA -> GREEK SMALL LETTER XI
+    u'\u03ba'   #  0xEB -> GREEK SMALL LETTER KAPPA
+    u'\u03bb'   #  0xEC -> GREEK SMALL LETTER LAMDA
+    u'\u03bc'   #  0xED -> GREEK SMALL LETTER MU
+    u'\u03bd'   #  0xEE -> GREEK SMALL LETTER NU
+    u'\u03bf'   #  0xEF -> GREEK SMALL LETTER OMICRON
+    u'\u03c0'   #  0xF0 -> GREEK SMALL LETTER PI
+    u'\u03ce'   #  0xF1 -> GREEK SMALL LETTER OMEGA WITH TONOS
+    u'\u03c1'   #  0xF2 -> GREEK SMALL LETTER RHO
+    u'\u03c3'   #  0xF3 -> GREEK SMALL LETTER SIGMA
+    u'\u03c4'   #  0xF4 -> GREEK SMALL LETTER TAU
+    u'\u03b8'   #  0xF5 -> GREEK SMALL LETTER THETA
+    u'\u03c9'   #  0xF6 -> GREEK SMALL LETTER OMEGA
+    u'\u03c2'   #  0xF7 -> GREEK SMALL LETTER FINAL SIGMA
+    u'\u03c7'   #  0xF8 -> GREEK SMALL LETTER CHI
+    u'\u03c5'   #  0xF9 -> GREEK SMALL LETTER UPSILON
+    u'\u03b6'   #  0xFA -> GREEK SMALL LETTER ZETA
+    u'\u03ca'   #  0xFB -> GREEK SMALL LETTER IOTA WITH DIALYTIKA
+    u'\u03cb'   #  0xFC -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+    u'\u0390'   #  0xFD -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+    u'\u03b0'   #  0xFE -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+    u'\xad'     #  0xFF -> SOFT HYPHEN # before Mac OS 9.2.2, was undefined
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mac_iceland.py b/src/main/resources/PythonLibs/encodings/mac_iceland.py
new file mode 100644
index 0000000000000000000000000000000000000000..c24add2ad0d58b6e64cee86ff7941010b45bf44d
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_iceland.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_iceland generated from 'MAPPINGS/VENDORS/APPLE/ICELAND.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-iceland',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\xc4'     #  0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc7'     #  0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc9'     #  0x83 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xd1'     #  0x84 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd6'     #  0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xe1'     #  0x87 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe0'     #  0x88 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe2'     #  0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x8A -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe3'     #  0x8B -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x8C -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x8D -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe9'     #  0x8E -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe8'     #  0x8F -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xea'     #  0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x91 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xed'     #  0x92 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xec'     #  0x93 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xee'     #  0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x95 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf1'     #  0x96 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf3'     #  0x97 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf2'     #  0x98 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf4'     #  0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x9A -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf5'     #  0x9B -> LATIN SMALL LETTER O WITH TILDE
+    u'\xfa'     #  0x9C -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf9'     #  0x9D -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfb'     #  0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0x9F -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\xdd'     #  0xA0 -> LATIN CAPITAL LETTER Y WITH ACUTE
+    u'\xb0'     #  0xA1 -> DEGREE SIGN
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa7'     #  0xA4 -> SECTION SIGN
+    u'\u2022'   #  0xA5 -> BULLET
+    u'\xb6'     #  0xA6 -> PILCROW SIGN
+    u'\xdf'     #  0xA7 -> LATIN SMALL LETTER SHARP S
+    u'\xae'     #  0xA8 -> REGISTERED SIGN
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u2122'   #  0xAA -> TRADE MARK SIGN
+    u'\xb4'     #  0xAB -> ACUTE ACCENT
+    u'\xa8'     #  0xAC -> DIAERESIS
+    u'\u2260'   #  0xAD -> NOT EQUAL TO
+    u'\xc6'     #  0xAE -> LATIN CAPITAL LETTER AE
+    u'\xd8'     #  0xAF -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u221e'   #  0xB0 -> INFINITY
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u2264'   #  0xB2 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0xB3 -> GREATER-THAN OR EQUAL TO
+    u'\xa5'     #  0xB4 -> YEN SIGN
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\u2202'   #  0xB6 -> PARTIAL DIFFERENTIAL
+    u'\u2211'   #  0xB7 -> N-ARY SUMMATION
+    u'\u220f'   #  0xB8 -> N-ARY PRODUCT
+    u'\u03c0'   #  0xB9 -> GREEK SMALL LETTER PI
+    u'\u222b'   #  0xBA -> INTEGRAL
+    u'\xaa'     #  0xBB -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0xBC -> MASCULINE ORDINAL INDICATOR
+    u'\u03a9'   #  0xBD -> GREEK CAPITAL LETTER OMEGA
+    u'\xe6'     #  0xBE -> LATIN SMALL LETTER AE
+    u'\xf8'     #  0xBF -> LATIN SMALL LETTER O WITH STROKE
+    u'\xbf'     #  0xC0 -> INVERTED QUESTION MARK
+    u'\xa1'     #  0xC1 -> INVERTED EXCLAMATION MARK
+    u'\xac'     #  0xC2 -> NOT SIGN
+    u'\u221a'   #  0xC3 -> SQUARE ROOT
+    u'\u0192'   #  0xC4 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u2248'   #  0xC5 -> ALMOST EQUAL TO
+    u'\u2206'   #  0xC6 -> INCREMENT
+    u'\xab'     #  0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2026'   #  0xC9 -> HORIZONTAL ELLIPSIS
+    u'\xa0'     #  0xCA -> NO-BREAK SPACE
+    u'\xc0'     #  0xCB -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc3'     #  0xCC -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xd5'     #  0xCD -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\u0152'   #  0xCE -> LATIN CAPITAL LIGATURE OE
+    u'\u0153'   #  0xCF -> LATIN SMALL LIGATURE OE
+    u'\u2013'   #  0xD0 -> EN DASH
+    u'\u2014'   #  0xD1 -> EM DASH
+    u'\u201c'   #  0xD2 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0xD3 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2018'   #  0xD4 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xD5 -> RIGHT SINGLE QUOTATION MARK
+    u'\xf7'     #  0xD6 -> DIVISION SIGN
+    u'\u25ca'   #  0xD7 -> LOZENGE
+    u'\xff'     #  0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\u0178'   #  0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\u2044'   #  0xDA -> FRACTION SLASH
+    u'\u20ac'   #  0xDB -> EURO SIGN
+    u'\xd0'     #  0xDC -> LATIN CAPITAL LETTER ETH
+    u'\xf0'     #  0xDD -> LATIN SMALL LETTER ETH
+    u'\xde'     #  0xDE -> LATIN CAPITAL LETTER THORN
+    u'\xfe'     #  0xDF -> LATIN SMALL LETTER THORN
+    u'\xfd'     #  0xE0 -> LATIN SMALL LETTER Y WITH ACUTE
+    u'\xb7'     #  0xE1 -> MIDDLE DOT
+    u'\u201a'   #  0xE2 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u201e'   #  0xE3 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2030'   #  0xE4 -> PER MILLE SIGN
+    u'\xc2'     #  0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xca'     #  0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xc1'     #  0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xcb'     #  0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0xEA -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0xED -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\uf8ff'   #  0xF0 -> Apple logo
+    u'\xd2'     #  0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xda'     #  0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xd9'     #  0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\u0131'   #  0xF5 -> LATIN SMALL LETTER DOTLESS I
+    u'\u02c6'   #  0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u02dc'   #  0xF7 -> SMALL TILDE
+    u'\xaf'     #  0xF8 -> MACRON
+    u'\u02d8'   #  0xF9 -> BREVE
+    u'\u02d9'   #  0xFA -> DOT ABOVE
+    u'\u02da'   #  0xFB -> RING ABOVE
+    u'\xb8'     #  0xFC -> CEDILLA
+    u'\u02dd'   #  0xFD -> DOUBLE ACUTE ACCENT
+    u'\u02db'   #  0xFE -> OGONEK
+    u'\u02c7'   #  0xFF -> CARON
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mac_latin2.py b/src/main/resources/PythonLibs/encodings/mac_latin2.py
new file mode 100644
index 0000000000000000000000000000000000000000..e322be236c3efdd66af473d753a049140b83a3bc
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_latin2.py
@@ -0,0 +1,183 @@
+""" Python Character Mapping Codec generated from 'LATIN2.TXT' with gencodec.py.
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+(c) Copyright 2000 Guido van Rossum.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_map)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_map)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-latin2',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+        0x0080: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS
+        0x0081: 0x0100, # LATIN CAPITAL LETTER A WITH MACRON
+        0x0082: 0x0101, # LATIN SMALL LETTER A WITH MACRON
+        0x0083: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE
+        0x0084: 0x0104, # LATIN CAPITAL LETTER A WITH OGONEK
+        0x0085: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS
+        0x0086: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS
+        0x0087: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE
+        0x0088: 0x0105, # LATIN SMALL LETTER A WITH OGONEK
+        0x0089: 0x010c, # LATIN CAPITAL LETTER C WITH CARON
+        0x008a: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS
+        0x008b: 0x010d, # LATIN SMALL LETTER C WITH CARON
+        0x008c: 0x0106, # LATIN CAPITAL LETTER C WITH ACUTE
+        0x008d: 0x0107, # LATIN SMALL LETTER C WITH ACUTE
+        0x008e: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE
+        0x008f: 0x0179, # LATIN CAPITAL LETTER Z WITH ACUTE
+        0x0090: 0x017a, # LATIN SMALL LETTER Z WITH ACUTE
+        0x0091: 0x010e, # LATIN CAPITAL LETTER D WITH CARON
+        0x0092: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE
+        0x0093: 0x010f, # LATIN SMALL LETTER D WITH CARON
+        0x0094: 0x0112, # LATIN CAPITAL LETTER E WITH MACRON
+        0x0095: 0x0113, # LATIN SMALL LETTER E WITH MACRON
+        0x0096: 0x0116, # LATIN CAPITAL LETTER E WITH DOT ABOVE
+        0x0097: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE
+        0x0098: 0x0117, # LATIN SMALL LETTER E WITH DOT ABOVE
+        0x0099: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX
+        0x009a: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS
+        0x009b: 0x00f5, # LATIN SMALL LETTER O WITH TILDE
+        0x009c: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE
+        0x009d: 0x011a, # LATIN CAPITAL LETTER E WITH CARON
+        0x009e: 0x011b, # LATIN SMALL LETTER E WITH CARON
+        0x009f: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS
+        0x00a0: 0x2020, # DAGGER
+        0x00a1: 0x00b0, # DEGREE SIGN
+        0x00a2: 0x0118, # LATIN CAPITAL LETTER E WITH OGONEK
+        0x00a4: 0x00a7, # SECTION SIGN
+        0x00a5: 0x2022, # BULLET
+        0x00a6: 0x00b6, # PILCROW SIGN
+        0x00a7: 0x00df, # LATIN SMALL LETTER SHARP S
+        0x00a8: 0x00ae, # REGISTERED SIGN
+        0x00aa: 0x2122, # TRADE MARK SIGN
+        0x00ab: 0x0119, # LATIN SMALL LETTER E WITH OGONEK
+        0x00ac: 0x00a8, # DIAERESIS
+        0x00ad: 0x2260, # NOT EQUAL TO
+        0x00ae: 0x0123, # LATIN SMALL LETTER G WITH CEDILLA
+        0x00af: 0x012e, # LATIN CAPITAL LETTER I WITH OGONEK
+        0x00b0: 0x012f, # LATIN SMALL LETTER I WITH OGONEK
+        0x00b1: 0x012a, # LATIN CAPITAL LETTER I WITH MACRON
+        0x00b2: 0x2264, # LESS-THAN OR EQUAL TO
+        0x00b3: 0x2265, # GREATER-THAN OR EQUAL TO
+        0x00b4: 0x012b, # LATIN SMALL LETTER I WITH MACRON
+        0x00b5: 0x0136, # LATIN CAPITAL LETTER K WITH CEDILLA
+        0x00b6: 0x2202, # PARTIAL DIFFERENTIAL
+        0x00b7: 0x2211, # N-ARY SUMMATION
+        0x00b8: 0x0142, # LATIN SMALL LETTER L WITH STROKE
+        0x00b9: 0x013b, # LATIN CAPITAL LETTER L WITH CEDILLA
+        0x00ba: 0x013c, # LATIN SMALL LETTER L WITH CEDILLA
+        0x00bb: 0x013d, # LATIN CAPITAL LETTER L WITH CARON
+        0x00bc: 0x013e, # LATIN SMALL LETTER L WITH CARON
+        0x00bd: 0x0139, # LATIN CAPITAL LETTER L WITH ACUTE
+        0x00be: 0x013a, # LATIN SMALL LETTER L WITH ACUTE
+        0x00bf: 0x0145, # LATIN CAPITAL LETTER N WITH CEDILLA
+        0x00c0: 0x0146, # LATIN SMALL LETTER N WITH CEDILLA
+        0x00c1: 0x0143, # LATIN CAPITAL LETTER N WITH ACUTE
+        0x00c2: 0x00ac, # NOT SIGN
+        0x00c3: 0x221a, # SQUARE ROOT
+        0x00c4: 0x0144, # LATIN SMALL LETTER N WITH ACUTE
+        0x00c5: 0x0147, # LATIN CAPITAL LETTER N WITH CARON
+        0x00c6: 0x2206, # INCREMENT
+        0x00c7: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+        0x00c8: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+        0x00c9: 0x2026, # HORIZONTAL ELLIPSIS
+        0x00ca: 0x00a0, # NO-BREAK SPACE
+        0x00cb: 0x0148, # LATIN SMALL LETTER N WITH CARON
+        0x00cc: 0x0150, # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+        0x00cd: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE
+        0x00ce: 0x0151, # LATIN SMALL LETTER O WITH DOUBLE ACUTE
+        0x00cf: 0x014c, # LATIN CAPITAL LETTER O WITH MACRON
+        0x00d0: 0x2013, # EN DASH
+        0x00d1: 0x2014, # EM DASH
+        0x00d2: 0x201c, # LEFT DOUBLE QUOTATION MARK
+        0x00d3: 0x201d, # RIGHT DOUBLE QUOTATION MARK
+        0x00d4: 0x2018, # LEFT SINGLE QUOTATION MARK
+        0x00d5: 0x2019, # RIGHT SINGLE QUOTATION MARK
+        0x00d6: 0x00f7, # DIVISION SIGN
+        0x00d7: 0x25ca, # LOZENGE
+        0x00d8: 0x014d, # LATIN SMALL LETTER O WITH MACRON
+        0x00d9: 0x0154, # LATIN CAPITAL LETTER R WITH ACUTE
+        0x00da: 0x0155, # LATIN SMALL LETTER R WITH ACUTE
+        0x00db: 0x0158, # LATIN CAPITAL LETTER R WITH CARON
+        0x00dc: 0x2039, # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+        0x00dd: 0x203a, # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+        0x00de: 0x0159, # LATIN SMALL LETTER R WITH CARON
+        0x00df: 0x0156, # LATIN CAPITAL LETTER R WITH CEDILLA
+        0x00e0: 0x0157, # LATIN SMALL LETTER R WITH CEDILLA
+        0x00e1: 0x0160, # LATIN CAPITAL LETTER S WITH CARON
+        0x00e2: 0x201a, # SINGLE LOW-9 QUOTATION MARK
+        0x00e3: 0x201e, # DOUBLE LOW-9 QUOTATION MARK
+        0x00e4: 0x0161, # LATIN SMALL LETTER S WITH CARON
+        0x00e5: 0x015a, # LATIN CAPITAL LETTER S WITH ACUTE
+        0x00e6: 0x015b, # LATIN SMALL LETTER S WITH ACUTE
+        0x00e7: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE
+        0x00e8: 0x0164, # LATIN CAPITAL LETTER T WITH CARON
+        0x00e9: 0x0165, # LATIN SMALL LETTER T WITH CARON
+        0x00ea: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE
+        0x00eb: 0x017d, # LATIN CAPITAL LETTER Z WITH CARON
+        0x00ec: 0x017e, # LATIN SMALL LETTER Z WITH CARON
+        0x00ed: 0x016a, # LATIN CAPITAL LETTER U WITH MACRON
+        0x00ee: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE
+        0x00ef: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+        0x00f0: 0x016b, # LATIN SMALL LETTER U WITH MACRON
+        0x00f1: 0x016e, # LATIN CAPITAL LETTER U WITH RING ABOVE
+        0x00f2: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE
+        0x00f3: 0x016f, # LATIN SMALL LETTER U WITH RING ABOVE
+        0x00f4: 0x0170, # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+        0x00f5: 0x0171, # LATIN SMALL LETTER U WITH DOUBLE ACUTE
+        0x00f6: 0x0172, # LATIN CAPITAL LETTER U WITH OGONEK
+        0x00f7: 0x0173, # LATIN SMALL LETTER U WITH OGONEK
+        0x00f8: 0x00dd, # LATIN CAPITAL LETTER Y WITH ACUTE
+        0x00f9: 0x00fd, # LATIN SMALL LETTER Y WITH ACUTE
+        0x00fa: 0x0137, # LATIN SMALL LETTER K WITH CEDILLA
+        0x00fb: 0x017b, # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+        0x00fc: 0x0141, # LATIN CAPITAL LETTER L WITH STROKE
+        0x00fd: 0x017c, # LATIN SMALL LETTER Z WITH DOT ABOVE
+        0x00fe: 0x0122, # LATIN CAPITAL LETTER G WITH CEDILLA
+        0x00ff: 0x02c7, # CARON
+})
+
+### Encoding Map
+
+encoding_map = codecs.make_encoding_map(decoding_map)
diff --git a/src/main/resources/PythonLibs/encodings/mac_roman.py b/src/main/resources/PythonLibs/encodings/mac_roman.py
new file mode 100644
index 0000000000000000000000000000000000000000..62605ec634f8e30814174b6a19b11196761faf90
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_roman.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_roman generated from 'MAPPINGS/VENDORS/APPLE/ROMAN.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-roman',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\xc4'     #  0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc7'     #  0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc9'     #  0x83 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xd1'     #  0x84 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd6'     #  0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xe1'     #  0x87 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe0'     #  0x88 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe2'     #  0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x8A -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe3'     #  0x8B -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x8C -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x8D -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe9'     #  0x8E -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe8'     #  0x8F -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xea'     #  0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x91 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xed'     #  0x92 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xec'     #  0x93 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xee'     #  0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x95 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf1'     #  0x96 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf3'     #  0x97 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf2'     #  0x98 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf4'     #  0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x9A -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf5'     #  0x9B -> LATIN SMALL LETTER O WITH TILDE
+    u'\xfa'     #  0x9C -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf9'     #  0x9D -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfb'     #  0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0x9F -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u2020'   #  0xA0 -> DAGGER
+    u'\xb0'     #  0xA1 -> DEGREE SIGN
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa7'     #  0xA4 -> SECTION SIGN
+    u'\u2022'   #  0xA5 -> BULLET
+    u'\xb6'     #  0xA6 -> PILCROW SIGN
+    u'\xdf'     #  0xA7 -> LATIN SMALL LETTER SHARP S
+    u'\xae'     #  0xA8 -> REGISTERED SIGN
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u2122'   #  0xAA -> TRADE MARK SIGN
+    u'\xb4'     #  0xAB -> ACUTE ACCENT
+    u'\xa8'     #  0xAC -> DIAERESIS
+    u'\u2260'   #  0xAD -> NOT EQUAL TO
+    u'\xc6'     #  0xAE -> LATIN CAPITAL LETTER AE
+    u'\xd8'     #  0xAF -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u221e'   #  0xB0 -> INFINITY
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u2264'   #  0xB2 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0xB3 -> GREATER-THAN OR EQUAL TO
+    u'\xa5'     #  0xB4 -> YEN SIGN
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\u2202'   #  0xB6 -> PARTIAL DIFFERENTIAL
+    u'\u2211'   #  0xB7 -> N-ARY SUMMATION
+    u'\u220f'   #  0xB8 -> N-ARY PRODUCT
+    u'\u03c0'   #  0xB9 -> GREEK SMALL LETTER PI
+    u'\u222b'   #  0xBA -> INTEGRAL
+    u'\xaa'     #  0xBB -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0xBC -> MASCULINE ORDINAL INDICATOR
+    u'\u03a9'   #  0xBD -> GREEK CAPITAL LETTER OMEGA
+    u'\xe6'     #  0xBE -> LATIN SMALL LETTER AE
+    u'\xf8'     #  0xBF -> LATIN SMALL LETTER O WITH STROKE
+    u'\xbf'     #  0xC0 -> INVERTED QUESTION MARK
+    u'\xa1'     #  0xC1 -> INVERTED EXCLAMATION MARK
+    u'\xac'     #  0xC2 -> NOT SIGN
+    u'\u221a'   #  0xC3 -> SQUARE ROOT
+    u'\u0192'   #  0xC4 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u2248'   #  0xC5 -> ALMOST EQUAL TO
+    u'\u2206'   #  0xC6 -> INCREMENT
+    u'\xab'     #  0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2026'   #  0xC9 -> HORIZONTAL ELLIPSIS
+    u'\xa0'     #  0xCA -> NO-BREAK SPACE
+    u'\xc0'     #  0xCB -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc3'     #  0xCC -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xd5'     #  0xCD -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\u0152'   #  0xCE -> LATIN CAPITAL LIGATURE OE
+    u'\u0153'   #  0xCF -> LATIN SMALL LIGATURE OE
+    u'\u2013'   #  0xD0 -> EN DASH
+    u'\u2014'   #  0xD1 -> EM DASH
+    u'\u201c'   #  0xD2 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0xD3 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2018'   #  0xD4 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xD5 -> RIGHT SINGLE QUOTATION MARK
+    u'\xf7'     #  0xD6 -> DIVISION SIGN
+    u'\u25ca'   #  0xD7 -> LOZENGE
+    u'\xff'     #  0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\u0178'   #  0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\u2044'   #  0xDA -> FRACTION SLASH
+    u'\u20ac'   #  0xDB -> EURO SIGN
+    u'\u2039'   #  0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u203a'   #  0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\ufb01'   #  0xDE -> LATIN SMALL LIGATURE FI
+    u'\ufb02'   #  0xDF -> LATIN SMALL LIGATURE FL
+    u'\u2021'   #  0xE0 -> DOUBLE DAGGER
+    u'\xb7'     #  0xE1 -> MIDDLE DOT
+    u'\u201a'   #  0xE2 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u201e'   #  0xE3 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2030'   #  0xE4 -> PER MILLE SIGN
+    u'\xc2'     #  0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xca'     #  0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xc1'     #  0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xcb'     #  0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0xEA -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0xED -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\uf8ff'   #  0xF0 -> Apple logo
+    u'\xd2'     #  0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xda'     #  0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xd9'     #  0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\u0131'   #  0xF5 -> LATIN SMALL LETTER DOTLESS I
+    u'\u02c6'   #  0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u02dc'   #  0xF7 -> SMALL TILDE
+    u'\xaf'     #  0xF8 -> MACRON
+    u'\u02d8'   #  0xF9 -> BREVE
+    u'\u02d9'   #  0xFA -> DOT ABOVE
+    u'\u02da'   #  0xFB -> RING ABOVE
+    u'\xb8'     #  0xFC -> CEDILLA
+    u'\u02dd'   #  0xFD -> DOUBLE ACUTE ACCENT
+    u'\u02db'   #  0xFE -> OGONEK
+    u'\u02c7'   #  0xFF -> CARON
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mac_romanian.py b/src/main/resources/PythonLibs/encodings/mac_romanian.py
new file mode 100644
index 0000000000000000000000000000000000000000..5bd5ae862531f060f4910ad7de4c3c5b2895be9f
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_romanian.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_romanian generated from 'MAPPINGS/VENDORS/APPLE/ROMANIAN.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-romanian',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\xc4'     #  0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc7'     #  0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc9'     #  0x83 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xd1'     #  0x84 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd6'     #  0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xe1'     #  0x87 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe0'     #  0x88 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe2'     #  0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x8A -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe3'     #  0x8B -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x8C -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x8D -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe9'     #  0x8E -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe8'     #  0x8F -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xea'     #  0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x91 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xed'     #  0x92 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xec'     #  0x93 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xee'     #  0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x95 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf1'     #  0x96 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf3'     #  0x97 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf2'     #  0x98 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf4'     #  0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x9A -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf5'     #  0x9B -> LATIN SMALL LETTER O WITH TILDE
+    u'\xfa'     #  0x9C -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf9'     #  0x9D -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfb'     #  0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0x9F -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u2020'   #  0xA0 -> DAGGER
+    u'\xb0'     #  0xA1 -> DEGREE SIGN
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa7'     #  0xA4 -> SECTION SIGN
+    u'\u2022'   #  0xA5 -> BULLET
+    u'\xb6'     #  0xA6 -> PILCROW SIGN
+    u'\xdf'     #  0xA7 -> LATIN SMALL LETTER SHARP S
+    u'\xae'     #  0xA8 -> REGISTERED SIGN
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u2122'   #  0xAA -> TRADE MARK SIGN
+    u'\xb4'     #  0xAB -> ACUTE ACCENT
+    u'\xa8'     #  0xAC -> DIAERESIS
+    u'\u2260'   #  0xAD -> NOT EQUAL TO
+    u'\u0102'   #  0xAE -> LATIN CAPITAL LETTER A WITH BREVE
+    u'\u0218'   #  0xAF -> LATIN CAPITAL LETTER S WITH COMMA BELOW # for Unicode 3.0 and later
+    u'\u221e'   #  0xB0 -> INFINITY
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u2264'   #  0xB2 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0xB3 -> GREATER-THAN OR EQUAL TO
+    u'\xa5'     #  0xB4 -> YEN SIGN
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\u2202'   #  0xB6 -> PARTIAL DIFFERENTIAL
+    u'\u2211'   #  0xB7 -> N-ARY SUMMATION
+    u'\u220f'   #  0xB8 -> N-ARY PRODUCT
+    u'\u03c0'   #  0xB9 -> GREEK SMALL LETTER PI
+    u'\u222b'   #  0xBA -> INTEGRAL
+    u'\xaa'     #  0xBB -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0xBC -> MASCULINE ORDINAL INDICATOR
+    u'\u03a9'   #  0xBD -> GREEK CAPITAL LETTER OMEGA
+    u'\u0103'   #  0xBE -> LATIN SMALL LETTER A WITH BREVE
+    u'\u0219'   #  0xBF -> LATIN SMALL LETTER S WITH COMMA BELOW # for Unicode 3.0 and later
+    u'\xbf'     #  0xC0 -> INVERTED QUESTION MARK
+    u'\xa1'     #  0xC1 -> INVERTED EXCLAMATION MARK
+    u'\xac'     #  0xC2 -> NOT SIGN
+    u'\u221a'   #  0xC3 -> SQUARE ROOT
+    u'\u0192'   #  0xC4 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u2248'   #  0xC5 -> ALMOST EQUAL TO
+    u'\u2206'   #  0xC6 -> INCREMENT
+    u'\xab'     #  0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2026'   #  0xC9 -> HORIZONTAL ELLIPSIS
+    u'\xa0'     #  0xCA -> NO-BREAK SPACE
+    u'\xc0'     #  0xCB -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc3'     #  0xCC -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xd5'     #  0xCD -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\u0152'   #  0xCE -> LATIN CAPITAL LIGATURE OE
+    u'\u0153'   #  0xCF -> LATIN SMALL LIGATURE OE
+    u'\u2013'   #  0xD0 -> EN DASH
+    u'\u2014'   #  0xD1 -> EM DASH
+    u'\u201c'   #  0xD2 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0xD3 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2018'   #  0xD4 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xD5 -> RIGHT SINGLE QUOTATION MARK
+    u'\xf7'     #  0xD6 -> DIVISION SIGN
+    u'\u25ca'   #  0xD7 -> LOZENGE
+    u'\xff'     #  0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\u0178'   #  0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\u2044'   #  0xDA -> FRACTION SLASH
+    u'\u20ac'   #  0xDB -> EURO SIGN
+    u'\u2039'   #  0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+    u'\u203a'   #  0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+    u'\u021a'   #  0xDE -> LATIN CAPITAL LETTER T WITH COMMA BELOW # for Unicode 3.0 and later
+    u'\u021b'   #  0xDF -> LATIN SMALL LETTER T WITH COMMA BELOW # for Unicode 3.0 and later
+    u'\u2021'   #  0xE0 -> DOUBLE DAGGER
+    u'\xb7'     #  0xE1 -> MIDDLE DOT
+    u'\u201a'   #  0xE2 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u201e'   #  0xE3 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2030'   #  0xE4 -> PER MILLE SIGN
+    u'\xc2'     #  0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xca'     #  0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xc1'     #  0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xcb'     #  0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0xEA -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0xED -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\uf8ff'   #  0xF0 -> Apple logo
+    u'\xd2'     #  0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xda'     #  0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xd9'     #  0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\u0131'   #  0xF5 -> LATIN SMALL LETTER DOTLESS I
+    u'\u02c6'   #  0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u02dc'   #  0xF7 -> SMALL TILDE
+    u'\xaf'     #  0xF8 -> MACRON
+    u'\u02d8'   #  0xF9 -> BREVE
+    u'\u02d9'   #  0xFA -> DOT ABOVE
+    u'\u02da'   #  0xFB -> RING ABOVE
+    u'\xb8'     #  0xFC -> CEDILLA
+    u'\u02dd'   #  0xFD -> DOUBLE ACUTE ACCENT
+    u'\u02db'   #  0xFE -> OGONEK
+    u'\u02c7'   #  0xFF -> CARON
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mac_turkish.py b/src/main/resources/PythonLibs/encodings/mac_turkish.py
new file mode 100644
index 0000000000000000000000000000000000000000..0787f4990b4b077d69a6858187ef7ba296d39a82
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mac_turkish.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec mac_turkish generated from 'MAPPINGS/VENDORS/APPLE/TURKISH.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mac-turkish',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> CONTROL CHARACTER
+    u'\x01'     #  0x01 -> CONTROL CHARACTER
+    u'\x02'     #  0x02 -> CONTROL CHARACTER
+    u'\x03'     #  0x03 -> CONTROL CHARACTER
+    u'\x04'     #  0x04 -> CONTROL CHARACTER
+    u'\x05'     #  0x05 -> CONTROL CHARACTER
+    u'\x06'     #  0x06 -> CONTROL CHARACTER
+    u'\x07'     #  0x07 -> CONTROL CHARACTER
+    u'\x08'     #  0x08 -> CONTROL CHARACTER
+    u'\t'       #  0x09 -> CONTROL CHARACTER
+    u'\n'       #  0x0A -> CONTROL CHARACTER
+    u'\x0b'     #  0x0B -> CONTROL CHARACTER
+    u'\x0c'     #  0x0C -> CONTROL CHARACTER
+    u'\r'       #  0x0D -> CONTROL CHARACTER
+    u'\x0e'     #  0x0E -> CONTROL CHARACTER
+    u'\x0f'     #  0x0F -> CONTROL CHARACTER
+    u'\x10'     #  0x10 -> CONTROL CHARACTER
+    u'\x11'     #  0x11 -> CONTROL CHARACTER
+    u'\x12'     #  0x12 -> CONTROL CHARACTER
+    u'\x13'     #  0x13 -> CONTROL CHARACTER
+    u'\x14'     #  0x14 -> CONTROL CHARACTER
+    u'\x15'     #  0x15 -> CONTROL CHARACTER
+    u'\x16'     #  0x16 -> CONTROL CHARACTER
+    u'\x17'     #  0x17 -> CONTROL CHARACTER
+    u'\x18'     #  0x18 -> CONTROL CHARACTER
+    u'\x19'     #  0x19 -> CONTROL CHARACTER
+    u'\x1a'     #  0x1A -> CONTROL CHARACTER
+    u'\x1b'     #  0x1B -> CONTROL CHARACTER
+    u'\x1c'     #  0x1C -> CONTROL CHARACTER
+    u'\x1d'     #  0x1D -> CONTROL CHARACTER
+    u'\x1e'     #  0x1E -> CONTROL CHARACTER
+    u'\x1f'     #  0x1F -> CONTROL CHARACTER
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> CONTROL CHARACTER
+    u'\xc4'     #  0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS
+    u'\xc5'     #  0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE
+    u'\xc7'     #  0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA
+    u'\xc9'     #  0x83 -> LATIN CAPITAL LETTER E WITH ACUTE
+    u'\xd1'     #  0x84 -> LATIN CAPITAL LETTER N WITH TILDE
+    u'\xd6'     #  0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS
+    u'\xdc'     #  0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS
+    u'\xe1'     #  0x87 -> LATIN SMALL LETTER A WITH ACUTE
+    u'\xe0'     #  0x88 -> LATIN SMALL LETTER A WITH GRAVE
+    u'\xe2'     #  0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX
+    u'\xe4'     #  0x8A -> LATIN SMALL LETTER A WITH DIAERESIS
+    u'\xe3'     #  0x8B -> LATIN SMALL LETTER A WITH TILDE
+    u'\xe5'     #  0x8C -> LATIN SMALL LETTER A WITH RING ABOVE
+    u'\xe7'     #  0x8D -> LATIN SMALL LETTER C WITH CEDILLA
+    u'\xe9'     #  0x8E -> LATIN SMALL LETTER E WITH ACUTE
+    u'\xe8'     #  0x8F -> LATIN SMALL LETTER E WITH GRAVE
+    u'\xea'     #  0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX
+    u'\xeb'     #  0x91 -> LATIN SMALL LETTER E WITH DIAERESIS
+    u'\xed'     #  0x92 -> LATIN SMALL LETTER I WITH ACUTE
+    u'\xec'     #  0x93 -> LATIN SMALL LETTER I WITH GRAVE
+    u'\xee'     #  0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX
+    u'\xef'     #  0x95 -> LATIN SMALL LETTER I WITH DIAERESIS
+    u'\xf1'     #  0x96 -> LATIN SMALL LETTER N WITH TILDE
+    u'\xf3'     #  0x97 -> LATIN SMALL LETTER O WITH ACUTE
+    u'\xf2'     #  0x98 -> LATIN SMALL LETTER O WITH GRAVE
+    u'\xf4'     #  0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX
+    u'\xf6'     #  0x9A -> LATIN SMALL LETTER O WITH DIAERESIS
+    u'\xf5'     #  0x9B -> LATIN SMALL LETTER O WITH TILDE
+    u'\xfa'     #  0x9C -> LATIN SMALL LETTER U WITH ACUTE
+    u'\xf9'     #  0x9D -> LATIN SMALL LETTER U WITH GRAVE
+    u'\xfb'     #  0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX
+    u'\xfc'     #  0x9F -> LATIN SMALL LETTER U WITH DIAERESIS
+    u'\u2020'   #  0xA0 -> DAGGER
+    u'\xb0'     #  0xA1 -> DEGREE SIGN
+    u'\xa2'     #  0xA2 -> CENT SIGN
+    u'\xa3'     #  0xA3 -> POUND SIGN
+    u'\xa7'     #  0xA4 -> SECTION SIGN
+    u'\u2022'   #  0xA5 -> BULLET
+    u'\xb6'     #  0xA6 -> PILCROW SIGN
+    u'\xdf'     #  0xA7 -> LATIN SMALL LETTER SHARP S
+    u'\xae'     #  0xA8 -> REGISTERED SIGN
+    u'\xa9'     #  0xA9 -> COPYRIGHT SIGN
+    u'\u2122'   #  0xAA -> TRADE MARK SIGN
+    u'\xb4'     #  0xAB -> ACUTE ACCENT
+    u'\xa8'     #  0xAC -> DIAERESIS
+    u'\u2260'   #  0xAD -> NOT EQUAL TO
+    u'\xc6'     #  0xAE -> LATIN CAPITAL LETTER AE
+    u'\xd8'     #  0xAF -> LATIN CAPITAL LETTER O WITH STROKE
+    u'\u221e'   #  0xB0 -> INFINITY
+    u'\xb1'     #  0xB1 -> PLUS-MINUS SIGN
+    u'\u2264'   #  0xB2 -> LESS-THAN OR EQUAL TO
+    u'\u2265'   #  0xB3 -> GREATER-THAN OR EQUAL TO
+    u'\xa5'     #  0xB4 -> YEN SIGN
+    u'\xb5'     #  0xB5 -> MICRO SIGN
+    u'\u2202'   #  0xB6 -> PARTIAL DIFFERENTIAL
+    u'\u2211'   #  0xB7 -> N-ARY SUMMATION
+    u'\u220f'   #  0xB8 -> N-ARY PRODUCT
+    u'\u03c0'   #  0xB9 -> GREEK SMALL LETTER PI
+    u'\u222b'   #  0xBA -> INTEGRAL
+    u'\xaa'     #  0xBB -> FEMININE ORDINAL INDICATOR
+    u'\xba'     #  0xBC -> MASCULINE ORDINAL INDICATOR
+    u'\u03a9'   #  0xBD -> GREEK CAPITAL LETTER OMEGA
+    u'\xe6'     #  0xBE -> LATIN SMALL LETTER AE
+    u'\xf8'     #  0xBF -> LATIN SMALL LETTER O WITH STROKE
+    u'\xbf'     #  0xC0 -> INVERTED QUESTION MARK
+    u'\xa1'     #  0xC1 -> INVERTED EXCLAMATION MARK
+    u'\xac'     #  0xC2 -> NOT SIGN
+    u'\u221a'   #  0xC3 -> SQUARE ROOT
+    u'\u0192'   #  0xC4 -> LATIN SMALL LETTER F WITH HOOK
+    u'\u2248'   #  0xC5 -> ALMOST EQUAL TO
+    u'\u2206'   #  0xC6 -> INCREMENT
+    u'\xab'     #  0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\xbb'     #  0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+    u'\u2026'   #  0xC9 -> HORIZONTAL ELLIPSIS
+    u'\xa0'     #  0xCA -> NO-BREAK SPACE
+    u'\xc0'     #  0xCB -> LATIN CAPITAL LETTER A WITH GRAVE
+    u'\xc3'     #  0xCC -> LATIN CAPITAL LETTER A WITH TILDE
+    u'\xd5'     #  0xCD -> LATIN CAPITAL LETTER O WITH TILDE
+    u'\u0152'   #  0xCE -> LATIN CAPITAL LIGATURE OE
+    u'\u0153'   #  0xCF -> LATIN SMALL LIGATURE OE
+    u'\u2013'   #  0xD0 -> EN DASH
+    u'\u2014'   #  0xD1 -> EM DASH
+    u'\u201c'   #  0xD2 -> LEFT DOUBLE QUOTATION MARK
+    u'\u201d'   #  0xD3 -> RIGHT DOUBLE QUOTATION MARK
+    u'\u2018'   #  0xD4 -> LEFT SINGLE QUOTATION MARK
+    u'\u2019'   #  0xD5 -> RIGHT SINGLE QUOTATION MARK
+    u'\xf7'     #  0xD6 -> DIVISION SIGN
+    u'\u25ca'   #  0xD7 -> LOZENGE
+    u'\xff'     #  0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS
+    u'\u0178'   #  0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS
+    u'\u011e'   #  0xDA -> LATIN CAPITAL LETTER G WITH BREVE
+    u'\u011f'   #  0xDB -> LATIN SMALL LETTER G WITH BREVE
+    u'\u0130'   #  0xDC -> LATIN CAPITAL LETTER I WITH DOT ABOVE
+    u'\u0131'   #  0xDD -> LATIN SMALL LETTER DOTLESS I
+    u'\u015e'   #  0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA
+    u'\u015f'   #  0xDF -> LATIN SMALL LETTER S WITH CEDILLA
+    u'\u2021'   #  0xE0 -> DOUBLE DAGGER
+    u'\xb7'     #  0xE1 -> MIDDLE DOT
+    u'\u201a'   #  0xE2 -> SINGLE LOW-9 QUOTATION MARK
+    u'\u201e'   #  0xE3 -> DOUBLE LOW-9 QUOTATION MARK
+    u'\u2030'   #  0xE4 -> PER MILLE SIGN
+    u'\xc2'     #  0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+    u'\xca'     #  0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    u'\xc1'     #  0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE
+    u'\xcb'     #  0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS
+    u'\xc8'     #  0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE
+    u'\xcd'     #  0xEA -> LATIN CAPITAL LETTER I WITH ACUTE
+    u'\xce'     #  0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+    u'\xcf'     #  0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS
+    u'\xcc'     #  0xED -> LATIN CAPITAL LETTER I WITH GRAVE
+    u'\xd3'     #  0xEE -> LATIN CAPITAL LETTER O WITH ACUTE
+    u'\xd4'     #  0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+    u'\uf8ff'   #  0xF0 -> Apple logo
+    u'\xd2'     #  0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE
+    u'\xda'     #  0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE
+    u'\xdb'     #  0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+    u'\xd9'     #  0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE
+    u'\uf8a0'   #  0xF5 -> undefined1
+    u'\u02c6'   #  0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT
+    u'\u02dc'   #  0xF7 -> SMALL TILDE
+    u'\xaf'     #  0xF8 -> MACRON
+    u'\u02d8'   #  0xF9 -> BREVE
+    u'\u02d9'   #  0xFA -> DOT ABOVE
+    u'\u02da'   #  0xFB -> RING ABOVE
+    u'\xb8'     #  0xFC -> CEDILLA
+    u'\u02dd'   #  0xFD -> DOUBLE ACUTE ACCENT
+    u'\u02db'   #  0xFE -> OGONEK
+    u'\u02c7'   #  0xFF -> CARON
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/mbcs.py b/src/main/resources/PythonLibs/encodings/mbcs.py
new file mode 100644
index 0000000000000000000000000000000000000000..baf46cbd4836bda6bb8ddccff7c282048383e0a2
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/mbcs.py
@@ -0,0 +1,47 @@
+""" Python 'mbcs' Codec for Windows
+
+
+Cloned by Mark Hammond (mhammond@skippinet.com.au) from ascii.py,
+which was written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+# Import them explicitly to cause an ImportError
+# on non-Windows systems
+from codecs import mbcs_encode, mbcs_decode
+# for IncrementalDecoder, IncrementalEncoder, ...
+import codecs
+
+### Codec APIs
+
+encode = mbcs_encode
+
+def decode(input, errors='strict'):
+    return mbcs_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return mbcs_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    _buffer_decode = mbcs_decode
+
+class StreamWriter(codecs.StreamWriter):
+    encode = mbcs_encode
+
+class StreamReader(codecs.StreamReader):
+    decode = mbcs_decode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='mbcs',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/palmos.py b/src/main/resources/PythonLibs/encodings/palmos.py
new file mode 100644
index 0000000000000000000000000000000000000000..4b77e2ba9142ebc3f8a9f4a3dc2df89e39b5c50a
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/palmos.py
@@ -0,0 +1,83 @@
+""" Python Character Mapping Codec for PalmOS 3.5.
+
+Written by Sjoerd Mullender (sjoerd@acm.org); based on iso8859_15.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_map)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_map)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='palmos',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+
+# The PalmOS character set is mostly iso-8859-1 with some differences.
+decoding_map.update({
+        0x0080: 0x20ac, #       EURO SIGN
+        0x0082: 0x201a, #       SINGLE LOW-9 QUOTATION MARK
+        0x0083: 0x0192, #       LATIN SMALL LETTER F WITH HOOK
+        0x0084: 0x201e, #       DOUBLE LOW-9 QUOTATION MARK
+        0x0085: 0x2026, #       HORIZONTAL ELLIPSIS
+        0x0086: 0x2020, #       DAGGER
+        0x0087: 0x2021, #       DOUBLE DAGGER
+        0x0088: 0x02c6, #       MODIFIER LETTER CIRCUMFLEX ACCENT
+        0x0089: 0x2030, #       PER MILLE SIGN
+        0x008a: 0x0160, #       LATIN CAPITAL LETTER S WITH CARON
+        0x008b: 0x2039, #       SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+        0x008c: 0x0152, #       LATIN CAPITAL LIGATURE OE
+        0x008d: 0x2666, #       BLACK DIAMOND SUIT
+        0x008e: 0x2663, #       BLACK CLUB SUIT
+        0x008f: 0x2665, #       BLACK HEART SUIT
+        0x0090: 0x2660, #       BLACK SPADE SUIT
+        0x0091: 0x2018, #       LEFT SINGLE QUOTATION MARK
+        0x0092: 0x2019, #       RIGHT SINGLE QUOTATION MARK
+        0x0093: 0x201c, #       LEFT DOUBLE QUOTATION MARK
+        0x0094: 0x201d, #       RIGHT DOUBLE QUOTATION MARK
+        0x0095: 0x2022, #       BULLET
+        0x0096: 0x2013, #       EN DASH
+        0x0097: 0x2014, #       EM DASH
+        0x0098: 0x02dc, #       SMALL TILDE
+        0x0099: 0x2122, #       TRADE MARK SIGN
+        0x009a: 0x0161, #       LATIN SMALL LETTER S WITH CARON
+        0x009c: 0x0153, #       LATIN SMALL LIGATURE OE
+        0x009f: 0x0178, #       LATIN CAPITAL LETTER Y WITH DIAERESIS
+})
+
+### Encoding Map
+
+encoding_map = codecs.make_encoding_map(decoding_map)
diff --git a/src/main/resources/PythonLibs/encodings/ptcp154.py b/src/main/resources/PythonLibs/encodings/ptcp154.py
new file mode 100644
index 0000000000000000000000000000000000000000..aef897538f5e3542229e661f1679d39c21912c6b
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/ptcp154.py
@@ -0,0 +1,175 @@
+""" Python Character Mapping Codec generated from 'PTCP154.txt' with gencodec.py.
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+(c) Copyright 2000 Guido van Rossum.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_map)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_map)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='ptcp154',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+        0x0080: 0x0496, #        CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
+        0x0081: 0x0492, #        CYRILLIC CAPITAL LETTER GHE WITH STROKE
+        0x0082: 0x04ee, #        CYRILLIC CAPITAL LETTER U WITH MACRON
+        0x0083: 0x0493, #        CYRILLIC SMALL LETTER GHE WITH STROKE
+        0x0084: 0x201e, #        DOUBLE LOW-9 QUOTATION MARK
+        0x0085: 0x2026, #        HORIZONTAL ELLIPSIS
+        0x0086: 0x04b6, #        CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
+        0x0087: 0x04ae, #        CYRILLIC CAPITAL LETTER STRAIGHT U
+        0x0088: 0x04b2, #        CYRILLIC CAPITAL LETTER HA WITH DESCENDER
+        0x0089: 0x04af, #        CYRILLIC SMALL LETTER STRAIGHT U
+        0x008a: 0x04a0, #        CYRILLIC CAPITAL LETTER BASHKIR KA
+        0x008b: 0x04e2, #        CYRILLIC CAPITAL LETTER I WITH MACRON
+        0x008c: 0x04a2, #        CYRILLIC CAPITAL LETTER EN WITH DESCENDER
+        0x008d: 0x049a, #        CYRILLIC CAPITAL LETTER KA WITH DESCENDER
+        0x008e: 0x04ba, #        CYRILLIC CAPITAL LETTER SHHA
+        0x008f: 0x04b8, #        CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
+        0x0090: 0x0497, #        CYRILLIC SMALL LETTER ZHE WITH DESCENDER
+        0x0091: 0x2018, #        LEFT SINGLE QUOTATION MARK
+        0x0092: 0x2019, #        RIGHT SINGLE QUOTATION MARK
+        0x0093: 0x201c, #        LEFT DOUBLE QUOTATION MARK
+        0x0094: 0x201d, #        RIGHT DOUBLE QUOTATION MARK
+        0x0095: 0x2022, #        BULLET
+        0x0096: 0x2013, #        EN DASH
+        0x0097: 0x2014, #        EM DASH
+        0x0098: 0x04b3, #        CYRILLIC SMALL LETTER HA WITH DESCENDER
+        0x0099: 0x04b7, #        CYRILLIC SMALL LETTER CHE WITH DESCENDER
+        0x009a: 0x04a1, #        CYRILLIC SMALL LETTER BASHKIR KA
+        0x009b: 0x04e3, #        CYRILLIC SMALL LETTER I WITH MACRON
+        0x009c: 0x04a3, #        CYRILLIC SMALL LETTER EN WITH DESCENDER
+        0x009d: 0x049b, #        CYRILLIC SMALL LETTER KA WITH DESCENDER
+        0x009e: 0x04bb, #        CYRILLIC SMALL LETTER SHHA
+        0x009f: 0x04b9, #        CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE
+        0x00a1: 0x040e, #        CYRILLIC CAPITAL LETTER SHORT U (Byelorussian)
+        0x00a2: 0x045e, #        CYRILLIC SMALL LETTER SHORT U (Byelorussian)
+        0x00a3: 0x0408, #        CYRILLIC CAPITAL LETTER JE
+        0x00a4: 0x04e8, #        CYRILLIC CAPITAL LETTER BARRED O
+        0x00a5: 0x0498, #        CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
+        0x00a6: 0x04b0, #        CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
+        0x00a8: 0x0401, #        CYRILLIC CAPITAL LETTER IO
+        0x00aa: 0x04d8, #        CYRILLIC CAPITAL LETTER SCHWA
+        0x00ad: 0x04ef, #        CYRILLIC SMALL LETTER U WITH MACRON
+        0x00af: 0x049c, #        CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
+        0x00b1: 0x04b1, #        CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE
+        0x00b2: 0x0406, #        CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+        0x00b3: 0x0456, #        CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+        0x00b4: 0x0499, #        CYRILLIC SMALL LETTER ZE WITH DESCENDER
+        0x00b5: 0x04e9, #        CYRILLIC SMALL LETTER BARRED O
+        0x00b8: 0x0451, #        CYRILLIC SMALL LETTER IO
+        0x00b9: 0x2116, #        NUMERO SIGN
+        0x00ba: 0x04d9, #        CYRILLIC SMALL LETTER SCHWA
+        0x00bc: 0x0458, #        CYRILLIC SMALL LETTER JE
+        0x00bd: 0x04aa, #        CYRILLIC CAPITAL LETTER ES WITH DESCENDER
+        0x00be: 0x04ab, #        CYRILLIC SMALL LETTER ES WITH DESCENDER
+        0x00bf: 0x049d, #        CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE
+        0x00c0: 0x0410, #        CYRILLIC CAPITAL LETTER A
+        0x00c1: 0x0411, #        CYRILLIC CAPITAL LETTER BE
+        0x00c2: 0x0412, #        CYRILLIC CAPITAL LETTER VE
+        0x00c3: 0x0413, #        CYRILLIC CAPITAL LETTER GHE
+        0x00c4: 0x0414, #        CYRILLIC CAPITAL LETTER DE
+        0x00c5: 0x0415, #        CYRILLIC CAPITAL LETTER IE
+        0x00c6: 0x0416, #        CYRILLIC CAPITAL LETTER ZHE
+        0x00c7: 0x0417, #        CYRILLIC CAPITAL LETTER ZE
+        0x00c8: 0x0418, #        CYRILLIC CAPITAL LETTER I
+        0x00c9: 0x0419, #        CYRILLIC CAPITAL LETTER SHORT I
+        0x00ca: 0x041a, #        CYRILLIC CAPITAL LETTER KA
+        0x00cb: 0x041b, #        CYRILLIC CAPITAL LETTER EL
+        0x00cc: 0x041c, #        CYRILLIC CAPITAL LETTER EM
+        0x00cd: 0x041d, #        CYRILLIC CAPITAL LETTER EN
+        0x00ce: 0x041e, #        CYRILLIC CAPITAL LETTER O
+        0x00cf: 0x041f, #        CYRILLIC CAPITAL LETTER PE
+        0x00d0: 0x0420, #        CYRILLIC CAPITAL LETTER ER
+        0x00d1: 0x0421, #        CYRILLIC CAPITAL LETTER ES
+        0x00d2: 0x0422, #        CYRILLIC CAPITAL LETTER TE
+        0x00d3: 0x0423, #        CYRILLIC CAPITAL LETTER U
+        0x00d4: 0x0424, #        CYRILLIC CAPITAL LETTER EF
+        0x00d5: 0x0425, #        CYRILLIC CAPITAL LETTER HA
+        0x00d6: 0x0426, #        CYRILLIC CAPITAL LETTER TSE
+        0x00d7: 0x0427, #        CYRILLIC CAPITAL LETTER CHE
+        0x00d8: 0x0428, #        CYRILLIC CAPITAL LETTER SHA
+        0x00d9: 0x0429, #        CYRILLIC CAPITAL LETTER SHCHA
+        0x00da: 0x042a, #        CYRILLIC CAPITAL LETTER HARD SIGN
+        0x00db: 0x042b, #        CYRILLIC CAPITAL LETTER YERU
+        0x00dc: 0x042c, #        CYRILLIC CAPITAL LETTER SOFT SIGN
+        0x00dd: 0x042d, #        CYRILLIC CAPITAL LETTER E
+        0x00de: 0x042e, #        CYRILLIC CAPITAL LETTER YU
+        0x00df: 0x042f, #        CYRILLIC CAPITAL LETTER YA
+        0x00e0: 0x0430, #        CYRILLIC SMALL LETTER A
+        0x00e1: 0x0431, #        CYRILLIC SMALL LETTER BE
+        0x00e2: 0x0432, #        CYRILLIC SMALL LETTER VE
+        0x00e3: 0x0433, #        CYRILLIC SMALL LETTER GHE
+        0x00e4: 0x0434, #        CYRILLIC SMALL LETTER DE
+        0x00e5: 0x0435, #        CYRILLIC SMALL LETTER IE
+        0x00e6: 0x0436, #        CYRILLIC SMALL LETTER ZHE
+        0x00e7: 0x0437, #        CYRILLIC SMALL LETTER ZE
+        0x00e8: 0x0438, #        CYRILLIC SMALL LETTER I
+        0x00e9: 0x0439, #        CYRILLIC SMALL LETTER SHORT I
+        0x00ea: 0x043a, #        CYRILLIC SMALL LETTER KA
+        0x00eb: 0x043b, #        CYRILLIC SMALL LETTER EL
+        0x00ec: 0x043c, #        CYRILLIC SMALL LETTER EM
+        0x00ed: 0x043d, #        CYRILLIC SMALL LETTER EN
+        0x00ee: 0x043e, #        CYRILLIC SMALL LETTER O
+        0x00ef: 0x043f, #        CYRILLIC SMALL LETTER PE
+        0x00f0: 0x0440, #        CYRILLIC SMALL LETTER ER
+        0x00f1: 0x0441, #        CYRILLIC SMALL LETTER ES
+        0x00f2: 0x0442, #        CYRILLIC SMALL LETTER TE
+        0x00f3: 0x0443, #        CYRILLIC SMALL LETTER U
+        0x00f4: 0x0444, #        CYRILLIC SMALL LETTER EF
+        0x00f5: 0x0445, #        CYRILLIC SMALL LETTER HA
+        0x00f6: 0x0446, #        CYRILLIC SMALL LETTER TSE
+        0x00f7: 0x0447, #        CYRILLIC SMALL LETTER CHE
+        0x00f8: 0x0448, #        CYRILLIC SMALL LETTER SHA
+        0x00f9: 0x0449, #        CYRILLIC SMALL LETTER SHCHA
+        0x00fa: 0x044a, #        CYRILLIC SMALL LETTER HARD SIGN
+        0x00fb: 0x044b, #        CYRILLIC SMALL LETTER YERU
+        0x00fc: 0x044c, #        CYRILLIC SMALL LETTER SOFT SIGN
+        0x00fd: 0x044d, #        CYRILLIC SMALL LETTER E
+        0x00fe: 0x044e, #        CYRILLIC SMALL LETTER YU
+        0x00ff: 0x044f, #        CYRILLIC SMALL LETTER YA
+})
+
+### Encoding Map
+
+encoding_map = codecs.make_encoding_map(decoding_map)
diff --git a/src/main/resources/PythonLibs/encodings/punycode.py b/src/main/resources/PythonLibs/encodings/punycode.py
new file mode 100644
index 0000000000000000000000000000000000000000..d97200fd35b11fa5a0bc68af79904e5b11751494
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/punycode.py
@@ -0,0 +1,238 @@
+# -*- coding: iso-8859-1 -*-
+""" Codec for the Punicode encoding, as specified in RFC 3492
+
+Written by Martin v. Löwis.
+"""
+
+import codecs
+
+##################### Encoding #####################################
+
+def segregate(str):
+    """3.1 Basic code point segregation"""
+    base = []
+    extended = {}
+    for c in str:
+        if ord(c) < 128:
+            base.append(c)
+        else:
+            extended[c] = 1
+    extended = extended.keys()
+    extended.sort()
+    return "".join(base).encode("ascii"),extended
+
+def selective_len(str, max):
+    """Return the length of str, considering only characters below max."""
+    res = 0
+    for c in str:
+        if ord(c) < max:
+            res += 1
+    return res
+
+def selective_find(str, char, index, pos):
+    """Return a pair (index, pos), indicating the next occurrence of
+    char in str. index is the position of the character considering
+    only ordinals up to and including char, and pos is the position in
+    the full string. index/pos is the starting position in the full
+    string."""
+
+    l = len(str)
+    while 1:
+        pos += 1
+        if pos == l:
+            return (-1, -1)
+        c = str[pos]
+        if c == char:
+            return index+1, pos
+        elif c < char:
+            index += 1
+
+def insertion_unsort(str, extended):
+    """3.2 Insertion unsort coding"""
+    oldchar = 0x80
+    result = []
+    oldindex = -1
+    for c in extended:
+        index = pos = -1
+        char = ord(c)
+        curlen = selective_len(str, char)
+        delta = (curlen+1) * (char - oldchar)
+        while 1:
+            index,pos = selective_find(str,c,index,pos)
+            if index == -1:
+                break
+            delta += index - oldindex
+            result.append(delta-1)
+            oldindex = index
+            delta = 0
+        oldchar = char
+
+    return result
+
+def T(j, bias):
+    # Punycode parameters: tmin = 1, tmax = 26, base = 36
+    res = 36 * (j + 1) - bias
+    if res < 1: return 1
+    if res > 26: return 26
+    return res
+
+digits = "abcdefghijklmnopqrstuvwxyz0123456789"
+def generate_generalized_integer(N, bias):
+    """3.3 Generalized variable-length integers"""
+    result = []
+    j = 0
+    while 1:
+        t = T(j, bias)
+        if N < t:
+            result.append(digits[N])
+            return result
+        result.append(digits[t + ((N - t) % (36 - t))])
+        N = (N - t) // (36 - t)
+        j += 1
+
+def adapt(delta, first, numchars):
+    if first:
+        delta //= 700
+    else:
+        delta //= 2
+    delta += delta // numchars
+    # ((base - tmin) * tmax) // 2 == 455
+    divisions = 0
+    while delta > 455:
+        delta = delta // 35 # base - tmin
+        divisions += 36
+    bias = divisions + (36 * delta // (delta + 38))
+    return bias
+
+
+def generate_integers(baselen, deltas):
+    """3.4 Bias adaptation"""
+    # Punycode parameters: initial bias = 72, damp = 700, skew = 38
+    result = []
+    bias = 72
+    for points, delta in enumerate(deltas):
+        s = generate_generalized_integer(delta, bias)
+        result.extend(s)
+        bias = adapt(delta, points==0, baselen+points+1)
+    return "".join(result)
+
+def punycode_encode(text):
+    base, extended = segregate(text)
+    base = base.encode("ascii")
+    deltas = insertion_unsort(text, extended)
+    extended = generate_integers(len(base), deltas)
+    if base:
+        return base + "-" + extended
+    return extended
+
+##################### Decoding #####################################
+
+def decode_generalized_number(extended, extpos, bias, errors):
+    """3.3 Generalized variable-length integers"""
+    result = 0
+    w = 1
+    j = 0
+    while 1:
+        try:
+            char = ord(extended[extpos])
+        except IndexError:
+            if errors == "strict":
+                raise UnicodeError, "incomplete punicode string"
+            return extpos + 1, None
+        extpos += 1
+        if 0x41 <= char <= 0x5A: # A-Z
+            digit = char - 0x41
+        elif 0x30 <= char <= 0x39:
+            digit = char - 22 # 0x30-26
+        elif errors == "strict":
+            raise UnicodeError("Invalid extended code point '%s'"
+                               % extended[extpos])
+        else:
+            return extpos, None
+        t = T(j, bias)
+        result += digit * w
+        if digit < t:
+            return extpos, result
+        w = w * (36 - t)
+        j += 1
+
+
+def insertion_sort(base, extended, errors):
+    """3.2 Insertion unsort coding"""
+    char = 0x80
+    pos = -1
+    bias = 72
+    extpos = 0
+    while extpos < len(extended):
+        newpos, delta = decode_generalized_number(extended, extpos,
+                                                  bias, errors)
+        if delta is None:
+            # There was an error in decoding. We can't continue because
+            # synchronization is lost.
+            return base
+        pos += delta+1
+        char += pos // (len(base) + 1)
+        if char > 0x10FFFF:
+            if errors == "strict":
+                raise UnicodeError, ("Invalid character U+%x" % char)
+            char = ord('?')
+        pos = pos % (len(base) + 1)
+        base = base[:pos] + unichr(char) + base[pos:]
+        bias = adapt(delta, (extpos == 0), len(base))
+        extpos = newpos
+    return base
+
+def punycode_decode(text, errors):
+    pos = text.rfind("-")
+    if pos == -1:
+        base = ""
+        extended = text
+    else:
+        base = text[:pos]
+        extended = text[pos+1:]
+    base = unicode(base, "ascii", errors)
+    extended = extended.upper()
+    return insertion_sort(base, extended, errors)
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        res = punycode_encode(input)
+        return res, len(input)
+
+    def decode(self,input,errors='strict'):
+        if errors not in ('strict', 'replace', 'ignore'):
+            raise UnicodeError, "Unsupported error handling "+errors
+        res = punycode_decode(input, errors)
+        return res, len(input)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return punycode_encode(input)
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        if self.errors not in ('strict', 'replace', 'ignore'):
+            raise UnicodeError, "Unsupported error handling "+self.errors
+        return punycode_decode(input, self.errors)
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='punycode',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/quopri_codec.py b/src/main/resources/PythonLibs/encodings/quopri_codec.py
new file mode 100644
index 0000000000000000000000000000000000000000..d8683fd56d325415a25116c129ab41ae45126016
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/quopri_codec.py
@@ -0,0 +1,75 @@
+"""Codec for quoted-printable encoding.
+
+Like base64 and rot13, this returns Python strings, not Unicode.
+"""
+
+import codecs, quopri
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+def quopri_encode(input, errors='strict'):
+    """Encode the input, returning a tuple (output object, length consumed).
+
+    errors defines the error handling to apply. It defaults to
+    'strict' handling which is the only currently supported
+    error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    # using str() because of cStringIO's Unicode undesired Unicode behavior.
+    f = StringIO(str(input))
+    g = StringIO()
+    quopri.encode(f, g, 1)
+    output = g.getvalue()
+    return (output, len(input))
+
+def quopri_decode(input, errors='strict'):
+    """Decode the input, returning a tuple (output object, length consumed).
+
+    errors defines the error handling to apply. It defaults to
+    'strict' handling which is the only currently supported
+    error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    f = StringIO(str(input))
+    g = StringIO()
+    quopri.decode(f, g)
+    output = g.getvalue()
+    return (output, len(input))
+
+class Codec(codecs.Codec):
+
+    def encode(self, input,errors='strict'):
+        return quopri_encode(input,errors)
+    def decode(self, input,errors='strict'):
+        return quopri_decode(input,errors)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return quopri_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return quopri_decode(input, self.errors)[0]
+
+class StreamWriter(Codec, codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+# encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='quopri',
+        encode=quopri_encode,
+        decode=quopri_decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/raw_unicode_escape.py b/src/main/resources/PythonLibs/encodings/raw_unicode_escape.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b919b40d3788a7bd7dab3a983af091deb48a235
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/raw_unicode_escape.py
@@ -0,0 +1,45 @@
+""" Python 'raw-unicode-escape' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    # Note: Binding these as C functions will result in the class not
+    # converting them to methods. This is intended.
+    encode = codecs.raw_unicode_escape_encode
+    decode = codecs.raw_unicode_escape_decode
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.raw_unicode_escape_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.raw_unicode_escape_decode(input, self.errors)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='raw-unicode-escape',
+        encode=Codec.encode,
+        decode=Codec.decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/rot_13.py b/src/main/resources/PythonLibs/encodings/rot_13.py
new file mode 100644
index 0000000000000000000000000000000000000000..52b6431cf30d5edcc7454352cce4a8f7fe2581fe
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/rot_13.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+""" Python Character Mapping Codec for ROT13.
+
+    See http://ucsub.colorado.edu/~kominek/rot13/ for details.
+
+    Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_map)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_map)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_map)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='rot-13',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
+
+### Decoding Map
+
+decoding_map = codecs.make_identity_dict(range(256))
+decoding_map.update({
+   0x0041: 0x004e,
+   0x0042: 0x004f,
+   0x0043: 0x0050,
+   0x0044: 0x0051,
+   0x0045: 0x0052,
+   0x0046: 0x0053,
+   0x0047: 0x0054,
+   0x0048: 0x0055,
+   0x0049: 0x0056,
+   0x004a: 0x0057,
+   0x004b: 0x0058,
+   0x004c: 0x0059,
+   0x004d: 0x005a,
+   0x004e: 0x0041,
+   0x004f: 0x0042,
+   0x0050: 0x0043,
+   0x0051: 0x0044,
+   0x0052: 0x0045,
+   0x0053: 0x0046,
+   0x0054: 0x0047,
+   0x0055: 0x0048,
+   0x0056: 0x0049,
+   0x0057: 0x004a,
+   0x0058: 0x004b,
+   0x0059: 0x004c,
+   0x005a: 0x004d,
+   0x0061: 0x006e,
+   0x0062: 0x006f,
+   0x0063: 0x0070,
+   0x0064: 0x0071,
+   0x0065: 0x0072,
+   0x0066: 0x0073,
+   0x0067: 0x0074,
+   0x0068: 0x0075,
+   0x0069: 0x0076,
+   0x006a: 0x0077,
+   0x006b: 0x0078,
+   0x006c: 0x0079,
+   0x006d: 0x007a,
+   0x006e: 0x0061,
+   0x006f: 0x0062,
+   0x0070: 0x0063,
+   0x0071: 0x0064,
+   0x0072: 0x0065,
+   0x0073: 0x0066,
+   0x0074: 0x0067,
+   0x0075: 0x0068,
+   0x0076: 0x0069,
+   0x0077: 0x006a,
+   0x0078: 0x006b,
+   0x0079: 0x006c,
+   0x007a: 0x006d,
+})
+
+### Encoding Map
+
+encoding_map = codecs.make_encoding_map(decoding_map)
+
+### Filter API
+
+def rot13(infile, outfile):
+    outfile.write(infile.read().encode('rot-13'))
+
+if __name__ == '__main__':
+    import sys
+    rot13(sys.stdin, sys.stdout)
diff --git a/src/main/resources/PythonLibs/encodings/shift_jis.py b/src/main/resources/PythonLibs/encodings/shift_jis.py
new file mode 100644
index 0000000000000000000000000000000000000000..83381172764dea0f76874716cda28852a5906f7f
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/shift_jis.py
@@ -0,0 +1,39 @@
+#
+# shift_jis.py: Python Unicode Codec for SHIFT_JIS
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_jp, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_jp.getcodec('shift_jis')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='shift_jis',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/shift_jis_2004.py b/src/main/resources/PythonLibs/encodings/shift_jis_2004.py
new file mode 100644
index 0000000000000000000000000000000000000000..161b1e86f9918a4df5c3290505a98d5de4566e0e
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/shift_jis_2004.py
@@ -0,0 +1,39 @@
+#
+# shift_jis_2004.py: Python Unicode Codec for SHIFT_JIS_2004
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_jp, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_jp.getcodec('shift_jis_2004')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='shift_jis_2004',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/shift_jisx0213.py b/src/main/resources/PythonLibs/encodings/shift_jisx0213.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb653f53055e679c513218b0102ffa9d1b4ca82c
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/shift_jisx0213.py
@@ -0,0 +1,39 @@
+#
+# shift_jisx0213.py: Python Unicode Codec for SHIFT_JISX0213
+#
+# Written by Hye-Shik Chang <perky@FreeBSD.org>
+#
+
+import _codecs_jp, codecs
+import _multibytecodec as mbc
+
+codec = _codecs_jp.getcodec('shift_jisx0213')
+
+class Codec(codecs.Codec):
+    encode = codec.encode
+    decode = codec.decode
+
+class IncrementalEncoder(mbc.MultibyteIncrementalEncoder,
+                         codecs.IncrementalEncoder):
+    codec = codec
+
+class IncrementalDecoder(mbc.MultibyteIncrementalDecoder,
+                         codecs.IncrementalDecoder):
+    codec = codec
+
+class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader):
+    codec = codec
+
+class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter):
+    codec = codec
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='shift_jisx0213',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/string_escape.py b/src/main/resources/PythonLibs/encodings/string_escape.py
new file mode 100644
index 0000000000000000000000000000000000000000..e329a2607de4d59fa014de61b5949db862e3112c
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/string_escape.py
@@ -0,0 +1,38 @@
+# -*- coding: iso-8859-1 -*-
+""" Python 'escape' Codec
+
+
+Written by Martin v. Löwis (martin@v.loewis.de).
+
+"""
+import codecs
+
+class Codec(codecs.Codec):
+
+    encode = codecs.escape_encode
+    decode = codecs.escape_decode
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.escape_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.escape_decode(input, self.errors)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='string-escape',
+        encode=Codec.encode,
+        decode=Codec.decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/tis_620.py b/src/main/resources/PythonLibs/encodings/tis_620.py
new file mode 100644
index 0000000000000000000000000000000000000000..b2cd22b23dcb0cf1e0c7ef6494246f05f6e7956d
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/tis_620.py
@@ -0,0 +1,307 @@
+""" Python Character Mapping Codec tis_620 generated from 'python-mappings/TIS-620.TXT' with gencodec.py.
+
+"""#"
+
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return codecs.charmap_encode(input,errors,encoding_table)
+
+    def decode(self,input,errors='strict'):
+        return codecs.charmap_decode(input,errors,decoding_table)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='tis-620',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
+
+
+### Decoding Table
+
+decoding_table = (
+    u'\x00'     #  0x00 -> NULL
+    u'\x01'     #  0x01 -> START OF HEADING
+    u'\x02'     #  0x02 -> START OF TEXT
+    u'\x03'     #  0x03 -> END OF TEXT
+    u'\x04'     #  0x04 -> END OF TRANSMISSION
+    u'\x05'     #  0x05 -> ENQUIRY
+    u'\x06'     #  0x06 -> ACKNOWLEDGE
+    u'\x07'     #  0x07 -> BELL
+    u'\x08'     #  0x08 -> BACKSPACE
+    u'\t'       #  0x09 -> HORIZONTAL TABULATION
+    u'\n'       #  0x0A -> LINE FEED
+    u'\x0b'     #  0x0B -> VERTICAL TABULATION
+    u'\x0c'     #  0x0C -> FORM FEED
+    u'\r'       #  0x0D -> CARRIAGE RETURN
+    u'\x0e'     #  0x0E -> SHIFT OUT
+    u'\x0f'     #  0x0F -> SHIFT IN
+    u'\x10'     #  0x10 -> DATA LINK ESCAPE
+    u'\x11'     #  0x11 -> DEVICE CONTROL ONE
+    u'\x12'     #  0x12 -> DEVICE CONTROL TWO
+    u'\x13'     #  0x13 -> DEVICE CONTROL THREE
+    u'\x14'     #  0x14 -> DEVICE CONTROL FOUR
+    u'\x15'     #  0x15 -> NEGATIVE ACKNOWLEDGE
+    u'\x16'     #  0x16 -> SYNCHRONOUS IDLE
+    u'\x17'     #  0x17 -> END OF TRANSMISSION BLOCK
+    u'\x18'     #  0x18 -> CANCEL
+    u'\x19'     #  0x19 -> END OF MEDIUM
+    u'\x1a'     #  0x1A -> SUBSTITUTE
+    u'\x1b'     #  0x1B -> ESCAPE
+    u'\x1c'     #  0x1C -> FILE SEPARATOR
+    u'\x1d'     #  0x1D -> GROUP SEPARATOR
+    u'\x1e'     #  0x1E -> RECORD SEPARATOR
+    u'\x1f'     #  0x1F -> UNIT SEPARATOR
+    u' '        #  0x20 -> SPACE
+    u'!'        #  0x21 -> EXCLAMATION MARK
+    u'"'        #  0x22 -> QUOTATION MARK
+    u'#'        #  0x23 -> NUMBER SIGN
+    u'$'        #  0x24 -> DOLLAR SIGN
+    u'%'        #  0x25 -> PERCENT SIGN
+    u'&'        #  0x26 -> AMPERSAND
+    u"'"        #  0x27 -> APOSTROPHE
+    u'('        #  0x28 -> LEFT PARENTHESIS
+    u')'        #  0x29 -> RIGHT PARENTHESIS
+    u'*'        #  0x2A -> ASTERISK
+    u'+'        #  0x2B -> PLUS SIGN
+    u','        #  0x2C -> COMMA
+    u'-'        #  0x2D -> HYPHEN-MINUS
+    u'.'        #  0x2E -> FULL STOP
+    u'/'        #  0x2F -> SOLIDUS
+    u'0'        #  0x30 -> DIGIT ZERO
+    u'1'        #  0x31 -> DIGIT ONE
+    u'2'        #  0x32 -> DIGIT TWO
+    u'3'        #  0x33 -> DIGIT THREE
+    u'4'        #  0x34 -> DIGIT FOUR
+    u'5'        #  0x35 -> DIGIT FIVE
+    u'6'        #  0x36 -> DIGIT SIX
+    u'7'        #  0x37 -> DIGIT SEVEN
+    u'8'        #  0x38 -> DIGIT EIGHT
+    u'9'        #  0x39 -> DIGIT NINE
+    u':'        #  0x3A -> COLON
+    u';'        #  0x3B -> SEMICOLON
+    u'<'        #  0x3C -> LESS-THAN SIGN
+    u'='        #  0x3D -> EQUALS SIGN
+    u'>'        #  0x3E -> GREATER-THAN SIGN
+    u'?'        #  0x3F -> QUESTION MARK
+    u'@'        #  0x40 -> COMMERCIAL AT
+    u'A'        #  0x41 -> LATIN CAPITAL LETTER A
+    u'B'        #  0x42 -> LATIN CAPITAL LETTER B
+    u'C'        #  0x43 -> LATIN CAPITAL LETTER C
+    u'D'        #  0x44 -> LATIN CAPITAL LETTER D
+    u'E'        #  0x45 -> LATIN CAPITAL LETTER E
+    u'F'        #  0x46 -> LATIN CAPITAL LETTER F
+    u'G'        #  0x47 -> LATIN CAPITAL LETTER G
+    u'H'        #  0x48 -> LATIN CAPITAL LETTER H
+    u'I'        #  0x49 -> LATIN CAPITAL LETTER I
+    u'J'        #  0x4A -> LATIN CAPITAL LETTER J
+    u'K'        #  0x4B -> LATIN CAPITAL LETTER K
+    u'L'        #  0x4C -> LATIN CAPITAL LETTER L
+    u'M'        #  0x4D -> LATIN CAPITAL LETTER M
+    u'N'        #  0x4E -> LATIN CAPITAL LETTER N
+    u'O'        #  0x4F -> LATIN CAPITAL LETTER O
+    u'P'        #  0x50 -> LATIN CAPITAL LETTER P
+    u'Q'        #  0x51 -> LATIN CAPITAL LETTER Q
+    u'R'        #  0x52 -> LATIN CAPITAL LETTER R
+    u'S'        #  0x53 -> LATIN CAPITAL LETTER S
+    u'T'        #  0x54 -> LATIN CAPITAL LETTER T
+    u'U'        #  0x55 -> LATIN CAPITAL LETTER U
+    u'V'        #  0x56 -> LATIN CAPITAL LETTER V
+    u'W'        #  0x57 -> LATIN CAPITAL LETTER W
+    u'X'        #  0x58 -> LATIN CAPITAL LETTER X
+    u'Y'        #  0x59 -> LATIN CAPITAL LETTER Y
+    u'Z'        #  0x5A -> LATIN CAPITAL LETTER Z
+    u'['        #  0x5B -> LEFT SQUARE BRACKET
+    u'\\'       #  0x5C -> REVERSE SOLIDUS
+    u']'        #  0x5D -> RIGHT SQUARE BRACKET
+    u'^'        #  0x5E -> CIRCUMFLEX ACCENT
+    u'_'        #  0x5F -> LOW LINE
+    u'`'        #  0x60 -> GRAVE ACCENT
+    u'a'        #  0x61 -> LATIN SMALL LETTER A
+    u'b'        #  0x62 -> LATIN SMALL LETTER B
+    u'c'        #  0x63 -> LATIN SMALL LETTER C
+    u'd'        #  0x64 -> LATIN SMALL LETTER D
+    u'e'        #  0x65 -> LATIN SMALL LETTER E
+    u'f'        #  0x66 -> LATIN SMALL LETTER F
+    u'g'        #  0x67 -> LATIN SMALL LETTER G
+    u'h'        #  0x68 -> LATIN SMALL LETTER H
+    u'i'        #  0x69 -> LATIN SMALL LETTER I
+    u'j'        #  0x6A -> LATIN SMALL LETTER J
+    u'k'        #  0x6B -> LATIN SMALL LETTER K
+    u'l'        #  0x6C -> LATIN SMALL LETTER L
+    u'm'        #  0x6D -> LATIN SMALL LETTER M
+    u'n'        #  0x6E -> LATIN SMALL LETTER N
+    u'o'        #  0x6F -> LATIN SMALL LETTER O
+    u'p'        #  0x70 -> LATIN SMALL LETTER P
+    u'q'        #  0x71 -> LATIN SMALL LETTER Q
+    u'r'        #  0x72 -> LATIN SMALL LETTER R
+    u's'        #  0x73 -> LATIN SMALL LETTER S
+    u't'        #  0x74 -> LATIN SMALL LETTER T
+    u'u'        #  0x75 -> LATIN SMALL LETTER U
+    u'v'        #  0x76 -> LATIN SMALL LETTER V
+    u'w'        #  0x77 -> LATIN SMALL LETTER W
+    u'x'        #  0x78 -> LATIN SMALL LETTER X
+    u'y'        #  0x79 -> LATIN SMALL LETTER Y
+    u'z'        #  0x7A -> LATIN SMALL LETTER Z
+    u'{'        #  0x7B -> LEFT CURLY BRACKET
+    u'|'        #  0x7C -> VERTICAL LINE
+    u'}'        #  0x7D -> RIGHT CURLY BRACKET
+    u'~'        #  0x7E -> TILDE
+    u'\x7f'     #  0x7F -> DELETE
+    u'\x80'     #  0x80 -> <control>
+    u'\x81'     #  0x81 -> <control>
+    u'\x82'     #  0x82 -> <control>
+    u'\x83'     #  0x83 -> <control>
+    u'\x84'     #  0x84 -> <control>
+    u'\x85'     #  0x85 -> <control>
+    u'\x86'     #  0x86 -> <control>
+    u'\x87'     #  0x87 -> <control>
+    u'\x88'     #  0x88 -> <control>
+    u'\x89'     #  0x89 -> <control>
+    u'\x8a'     #  0x8A -> <control>
+    u'\x8b'     #  0x8B -> <control>
+    u'\x8c'     #  0x8C -> <control>
+    u'\x8d'     #  0x8D -> <control>
+    u'\x8e'     #  0x8E -> <control>
+    u'\x8f'     #  0x8F -> <control>
+    u'\x90'     #  0x90 -> <control>
+    u'\x91'     #  0x91 -> <control>
+    u'\x92'     #  0x92 -> <control>
+    u'\x93'     #  0x93 -> <control>
+    u'\x94'     #  0x94 -> <control>
+    u'\x95'     #  0x95 -> <control>
+    u'\x96'     #  0x96 -> <control>
+    u'\x97'     #  0x97 -> <control>
+    u'\x98'     #  0x98 -> <control>
+    u'\x99'     #  0x99 -> <control>
+    u'\x9a'     #  0x9A -> <control>
+    u'\x9b'     #  0x9B -> <control>
+    u'\x9c'     #  0x9C -> <control>
+    u'\x9d'     #  0x9D -> <control>
+    u'\x9e'     #  0x9E -> <control>
+    u'\x9f'     #  0x9F -> <control>
+    u'\ufffe'
+    u'\u0e01'   #  0xA1 -> THAI CHARACTER KO KAI
+    u'\u0e02'   #  0xA2 -> THAI CHARACTER KHO KHAI
+    u'\u0e03'   #  0xA3 -> THAI CHARACTER KHO KHUAT
+    u'\u0e04'   #  0xA4 -> THAI CHARACTER KHO KHWAI
+    u'\u0e05'   #  0xA5 -> THAI CHARACTER KHO KHON
+    u'\u0e06'   #  0xA6 -> THAI CHARACTER KHO RAKHANG
+    u'\u0e07'   #  0xA7 -> THAI CHARACTER NGO NGU
+    u'\u0e08'   #  0xA8 -> THAI CHARACTER CHO CHAN
+    u'\u0e09'   #  0xA9 -> THAI CHARACTER CHO CHING
+    u'\u0e0a'   #  0xAA -> THAI CHARACTER CHO CHANG
+    u'\u0e0b'   #  0xAB -> THAI CHARACTER SO SO
+    u'\u0e0c'   #  0xAC -> THAI CHARACTER CHO CHOE
+    u'\u0e0d'   #  0xAD -> THAI CHARACTER YO YING
+    u'\u0e0e'   #  0xAE -> THAI CHARACTER DO CHADA
+    u'\u0e0f'   #  0xAF -> THAI CHARACTER TO PATAK
+    u'\u0e10'   #  0xB0 -> THAI CHARACTER THO THAN
+    u'\u0e11'   #  0xB1 -> THAI CHARACTER THO NANGMONTHO
+    u'\u0e12'   #  0xB2 -> THAI CHARACTER THO PHUTHAO
+    u'\u0e13'   #  0xB3 -> THAI CHARACTER NO NEN
+    u'\u0e14'   #  0xB4 -> THAI CHARACTER DO DEK
+    u'\u0e15'   #  0xB5 -> THAI CHARACTER TO TAO
+    u'\u0e16'   #  0xB6 -> THAI CHARACTER THO THUNG
+    u'\u0e17'   #  0xB7 -> THAI CHARACTER THO THAHAN
+    u'\u0e18'   #  0xB8 -> THAI CHARACTER THO THONG
+    u'\u0e19'   #  0xB9 -> THAI CHARACTER NO NU
+    u'\u0e1a'   #  0xBA -> THAI CHARACTER BO BAIMAI
+    u'\u0e1b'   #  0xBB -> THAI CHARACTER PO PLA
+    u'\u0e1c'   #  0xBC -> THAI CHARACTER PHO PHUNG
+    u'\u0e1d'   #  0xBD -> THAI CHARACTER FO FA
+    u'\u0e1e'   #  0xBE -> THAI CHARACTER PHO PHAN
+    u'\u0e1f'   #  0xBF -> THAI CHARACTER FO FAN
+    u'\u0e20'   #  0xC0 -> THAI CHARACTER PHO SAMPHAO
+    u'\u0e21'   #  0xC1 -> THAI CHARACTER MO MA
+    u'\u0e22'   #  0xC2 -> THAI CHARACTER YO YAK
+    u'\u0e23'   #  0xC3 -> THAI CHARACTER RO RUA
+    u'\u0e24'   #  0xC4 -> THAI CHARACTER RU
+    u'\u0e25'   #  0xC5 -> THAI CHARACTER LO LING
+    u'\u0e26'   #  0xC6 -> THAI CHARACTER LU
+    u'\u0e27'   #  0xC7 -> THAI CHARACTER WO WAEN
+    u'\u0e28'   #  0xC8 -> THAI CHARACTER SO SALA
+    u'\u0e29'   #  0xC9 -> THAI CHARACTER SO RUSI
+    u'\u0e2a'   #  0xCA -> THAI CHARACTER SO SUA
+    u'\u0e2b'   #  0xCB -> THAI CHARACTER HO HIP
+    u'\u0e2c'   #  0xCC -> THAI CHARACTER LO CHULA
+    u'\u0e2d'   #  0xCD -> THAI CHARACTER O ANG
+    u'\u0e2e'   #  0xCE -> THAI CHARACTER HO NOKHUK
+    u'\u0e2f'   #  0xCF -> THAI CHARACTER PAIYANNOI
+    u'\u0e30'   #  0xD0 -> THAI CHARACTER SARA A
+    u'\u0e31'   #  0xD1 -> THAI CHARACTER MAI HAN-AKAT
+    u'\u0e32'   #  0xD2 -> THAI CHARACTER SARA AA
+    u'\u0e33'   #  0xD3 -> THAI CHARACTER SARA AM
+    u'\u0e34'   #  0xD4 -> THAI CHARACTER SARA I
+    u'\u0e35'   #  0xD5 -> THAI CHARACTER SARA II
+    u'\u0e36'   #  0xD6 -> THAI CHARACTER SARA UE
+    u'\u0e37'   #  0xD7 -> THAI CHARACTER SARA UEE
+    u'\u0e38'   #  0xD8 -> THAI CHARACTER SARA U
+    u'\u0e39'   #  0xD9 -> THAI CHARACTER SARA UU
+    u'\u0e3a'   #  0xDA -> THAI CHARACTER PHINTHU
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\u0e3f'   #  0xDF -> THAI CURRENCY SYMBOL BAHT
+    u'\u0e40'   #  0xE0 -> THAI CHARACTER SARA E
+    u'\u0e41'   #  0xE1 -> THAI CHARACTER SARA AE
+    u'\u0e42'   #  0xE2 -> THAI CHARACTER SARA O
+    u'\u0e43'   #  0xE3 -> THAI CHARACTER SARA AI MAIMUAN
+    u'\u0e44'   #  0xE4 -> THAI CHARACTER SARA AI MAIMALAI
+    u'\u0e45'   #  0xE5 -> THAI CHARACTER LAKKHANGYAO
+    u'\u0e46'   #  0xE6 -> THAI CHARACTER MAIYAMOK
+    u'\u0e47'   #  0xE7 -> THAI CHARACTER MAITAIKHU
+    u'\u0e48'   #  0xE8 -> THAI CHARACTER MAI EK
+    u'\u0e49'   #  0xE9 -> THAI CHARACTER MAI THO
+    u'\u0e4a'   #  0xEA -> THAI CHARACTER MAI TRI
+    u'\u0e4b'   #  0xEB -> THAI CHARACTER MAI CHATTAWA
+    u'\u0e4c'   #  0xEC -> THAI CHARACTER THANTHAKHAT
+    u'\u0e4d'   #  0xED -> THAI CHARACTER NIKHAHIT
+    u'\u0e4e'   #  0xEE -> THAI CHARACTER YAMAKKAN
+    u'\u0e4f'   #  0xEF -> THAI CHARACTER FONGMAN
+    u'\u0e50'   #  0xF0 -> THAI DIGIT ZERO
+    u'\u0e51'   #  0xF1 -> THAI DIGIT ONE
+    u'\u0e52'   #  0xF2 -> THAI DIGIT TWO
+    u'\u0e53'   #  0xF3 -> THAI DIGIT THREE
+    u'\u0e54'   #  0xF4 -> THAI DIGIT FOUR
+    u'\u0e55'   #  0xF5 -> THAI DIGIT FIVE
+    u'\u0e56'   #  0xF6 -> THAI DIGIT SIX
+    u'\u0e57'   #  0xF7 -> THAI DIGIT SEVEN
+    u'\u0e58'   #  0xF8 -> THAI DIGIT EIGHT
+    u'\u0e59'   #  0xF9 -> THAI DIGIT NINE
+    u'\u0e5a'   #  0xFA -> THAI CHARACTER ANGKHANKHU
+    u'\u0e5b'   #  0xFB -> THAI CHARACTER KHOMUT
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+    u'\ufffe'
+)
+
+### Encoding table
+encoding_table=codecs.charmap_build(decoding_table)
diff --git a/src/main/resources/PythonLibs/encodings/undefined.py b/src/main/resources/PythonLibs/encodings/undefined.py
new file mode 100644
index 0000000000000000000000000000000000000000..4690288355c710bc227c0990fb37f36e23186ea1
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/undefined.py
@@ -0,0 +1,49 @@
+""" Python 'undefined' Codec
+
+    This codec will always raise a ValueError exception when being
+    used. It is intended for use by the site.py file to switch off
+    automatic string to Unicode coercion.
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        raise UnicodeError("undefined encoding")
+
+    def decode(self,input,errors='strict'):
+        raise UnicodeError("undefined encoding")
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        raise UnicodeError("undefined encoding")
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        raise UnicodeError("undefined encoding")
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='undefined',
+        encode=Codec().encode,
+        decode=Codec().decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/unicode_escape.py b/src/main/resources/PythonLibs/encodings/unicode_escape.py
new file mode 100644
index 0000000000000000000000000000000000000000..817f93265a4634c9907b591b645a09cda73dcbf2
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/unicode_escape.py
@@ -0,0 +1,45 @@
+""" Python 'unicode-escape' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    # Note: Binding these as C functions will result in the class not
+    # converting them to methods. This is intended.
+    encode = codecs.unicode_escape_encode
+    decode = codecs.unicode_escape_decode
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.unicode_escape_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.unicode_escape_decode(input, self.errors)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='unicode-escape',
+        encode=Codec.encode,
+        decode=Codec.decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/unicode_internal.py b/src/main/resources/PythonLibs/encodings/unicode_internal.py
new file mode 100644
index 0000000000000000000000000000000000000000..df3e7752d20a8e15c985742f11265b0ec7b3277b
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/unicode_internal.py
@@ -0,0 +1,45 @@
+""" Python 'unicode-internal' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+class Codec(codecs.Codec):
+
+    # Note: Binding these as C functions will result in the class not
+    # converting them to methods. This is intended.
+    encode = codecs.unicode_internal_encode
+    decode = codecs.unicode_internal_decode
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.unicode_internal_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return codecs.unicode_internal_decode(input, self.errors)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='unicode-internal',
+        encode=Codec.encode,
+        decode=Codec.decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamwriter=StreamWriter,
+        streamreader=StreamReader,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_16.py b/src/main/resources/PythonLibs/encodings/utf_16.py
new file mode 100644
index 0000000000000000000000000000000000000000..f3fadff6153bb96f8afeceef0952c7b9b7958805
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_16.py
@@ -0,0 +1,126 @@
+""" Python 'utf-16' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs, sys
+
+### Codec APIs
+
+encode = codecs.utf_16_encode
+
+def decode(input, errors='strict'):
+    return codecs.utf_16_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def __init__(self, errors='strict'):
+        codecs.IncrementalEncoder.__init__(self, errors)
+        self.encoder = None
+
+    def encode(self, input, final=False):
+        if self.encoder is None:
+            result = codecs.utf_16_encode(input, self.errors)[0]
+            if sys.byteorder == 'little':
+                self.encoder = codecs.utf_16_le_encode
+            else:
+                self.encoder = codecs.utf_16_be_encode
+            return result
+        return self.encoder(input, self.errors)[0]
+
+    def reset(self):
+        codecs.IncrementalEncoder.reset(self)
+        self.encoder = None
+
+    def getstate(self):
+        # state info we return to the caller:
+        # 0: stream is in natural order for this platform
+        # 2: endianness hasn't been determined yet
+        # (we're never writing in unnatural order)
+        return (2 if self.encoder is None else 0)
+
+    def setstate(self, state):
+        if state:
+            self.encoder = None
+        else:
+            if sys.byteorder == 'little':
+                self.encoder = codecs.utf_16_le_encode
+            else:
+                self.encoder = codecs.utf_16_be_encode
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    def __init__(self, errors='strict'):
+        codecs.BufferedIncrementalDecoder.__init__(self, errors)
+        self.decoder = None
+
+    def _buffer_decode(self, input, errors, final):
+        if self.decoder is None:
+            (output, consumed, byteorder) = \
+                codecs.utf_16_ex_decode(input, errors, 0, final)
+            if byteorder == -1:
+                self.decoder = codecs.utf_16_le_decode
+            elif byteorder == 1:
+                self.decoder = codecs.utf_16_be_decode
+            elif consumed >= 2:
+                raise UnicodeError("UTF-16 stream does not start with BOM")
+            return (output, consumed)
+        return self.decoder(input, self.errors, final)
+
+    def reset(self):
+        codecs.BufferedIncrementalDecoder.reset(self)
+        self.decoder = None
+
+class StreamWriter(codecs.StreamWriter):
+    def __init__(self, stream, errors='strict'):
+        codecs.StreamWriter.__init__(self, stream, errors)
+        self.encoder = None
+
+    def reset(self):
+        codecs.StreamWriter.reset(self)
+        self.encoder = None
+
+    def encode(self, input, errors='strict'):
+        if self.encoder is None:
+            result = codecs.utf_16_encode(input, errors)
+            if sys.byteorder == 'little':
+                self.encoder = codecs.utf_16_le_encode
+            else:
+                self.encoder = codecs.utf_16_be_encode
+            return result
+        else:
+            return self.encoder(input, errors)
+
+class StreamReader(codecs.StreamReader):
+
+    def reset(self):
+        codecs.StreamReader.reset(self)
+        try:
+            del self.decode
+        except AttributeError:
+            pass
+
+    def decode(self, input, errors='strict'):
+        (object, consumed, byteorder) = \
+            codecs.utf_16_ex_decode(input, errors, 0, False)
+        if byteorder == -1:
+            self.decode = codecs.utf_16_le_decode
+        elif byteorder == 1:
+            self.decode = codecs.utf_16_be_decode
+        elif consumed>=2:
+            raise UnicodeError,"UTF-16 stream does not start with BOM"
+        return (object, consumed)
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-16',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_16_be.py b/src/main/resources/PythonLibs/encodings/utf_16_be.py
new file mode 100644
index 0000000000000000000000000000000000000000..86b458eb9bcd96b50f128df1978a14f5d1e41835
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_16_be.py
@@ -0,0 +1,42 @@
+""" Python 'utf-16-be' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+encode = codecs.utf_16_be_encode
+
+def decode(input, errors='strict'):
+    return codecs.utf_16_be_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.utf_16_be_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    _buffer_decode = codecs.utf_16_be_decode
+
+class StreamWriter(codecs.StreamWriter):
+    encode = codecs.utf_16_be_encode
+
+class StreamReader(codecs.StreamReader):
+    decode = codecs.utf_16_be_decode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-16-be',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_16_le.py b/src/main/resources/PythonLibs/encodings/utf_16_le.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec454142eedf251e31eab481a1cbea6424273a0a
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_16_le.py
@@ -0,0 +1,42 @@
+""" Python 'utf-16-le' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+encode = codecs.utf_16_le_encode
+
+def decode(input, errors='strict'):
+    return codecs.utf_16_le_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.utf_16_le_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    _buffer_decode = codecs.utf_16_le_decode
+
+class StreamWriter(codecs.StreamWriter):
+    encode = codecs.utf_16_le_encode
+
+class StreamReader(codecs.StreamReader):
+    decode = codecs.utf_16_le_decode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-16-le',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_32.py b/src/main/resources/PythonLibs/encodings/utf_32.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c8016fe1b3fd066db5e51ad9ad5d97042016fd6
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_32.py
@@ -0,0 +1,150 @@
+"""
+Python 'utf-32' Codec
+"""
+import codecs, sys
+
+### Codec APIs
+
+encode = codecs.utf_32_encode
+
+def decode(input, errors='strict'):
+    return codecs.utf_32_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def __init__(self, errors='strict'):
+        codecs.IncrementalEncoder.__init__(self, errors)
+        self.encoder = None
+
+    def encode(self, input, final=False):
+        if self.encoder is None:
+            result = codecs.utf_32_encode(input, self.errors)[0]
+            if sys.byteorder == 'little':
+                self.encoder = codecs.utf_32_le_encode
+            else:
+                self.encoder = codecs.utf_32_be_encode
+            return result
+        return self.encoder(input, self.errors)[0]
+
+    def reset(self):
+        codecs.IncrementalEncoder.reset(self)
+        self.encoder = None
+
+    def getstate(self):
+        # state info we return to the caller:
+        # 0: stream is in natural order for this platform
+        # 2: endianness hasn't been determined yet
+        # (we're never writing in unnatural order)
+        return (2 if self.encoder is None else 0)
+
+    def setstate(self, state):
+        if state:
+            self.encoder = None
+        else:
+            if sys.byteorder == 'little':
+                self.encoder = codecs.utf_32_le_encode
+            else:
+                self.encoder = codecs.utf_32_be_encode
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    def __init__(self, errors='strict'):
+        codecs.BufferedIncrementalDecoder.__init__(self, errors)
+        self.decoder = None
+
+    def _buffer_decode(self, input, errors, final):
+        if self.decoder is None:
+            (output, consumed, byteorder) = \
+                codecs.utf_32_ex_decode(input, errors, 0, final)
+            if byteorder == -1:
+                self.decoder = codecs.utf_32_le_decode
+            elif byteorder == 1:
+                self.decoder = codecs.utf_32_be_decode
+            elif consumed >= 4:
+                raise UnicodeError("UTF-32 stream does not start with BOM")
+            return (output, consumed)
+        return self.decoder(input, self.errors, final)
+
+    def reset(self):
+        codecs.BufferedIncrementalDecoder.reset(self)
+        self.decoder = None
+
+    def getstate(self):
+        # additonal state info from the base class must be None here,
+        # as it isn't passed along to the caller
+        state = codecs.BufferedIncrementalDecoder.getstate(self)[0]
+        # additional state info we pass to the caller:
+        # 0: stream is in natural order for this platform
+        # 1: stream is in unnatural order
+        # 2: endianness hasn't been determined yet
+        if self.decoder is None:
+            return (state, 2)
+        addstate = int((sys.byteorder == "big") !=
+                       (self.decoder is codecs.utf_32_be_decode))
+        return (state, addstate)
+
+    def setstate(self, state):
+        # state[1] will be ignored by BufferedIncrementalDecoder.setstate()
+        codecs.BufferedIncrementalDecoder.setstate(self, state)
+        state = state[1]
+        if state == 0:
+            self.decoder = (codecs.utf_32_be_decode
+                            if sys.byteorder == "big"
+                            else codecs.utf_32_le_decode)
+        elif state == 1:
+            self.decoder = (codecs.utf_32_le_decode
+                            if sys.byteorder == "big"
+                            else codecs.utf_32_be_decode)
+        else:
+            self.decoder = None
+
+class StreamWriter(codecs.StreamWriter):
+    def __init__(self, stream, errors='strict'):
+        self.encoder = None
+        codecs.StreamWriter.__init__(self, stream, errors)
+
+    def reset(self):
+        codecs.StreamWriter.reset(self)
+        self.encoder = None
+
+    def encode(self, input, errors='strict'):
+        if self.encoder is None:
+            result = codecs.utf_32_encode(input, errors)
+            if sys.byteorder == 'little':
+                self.encoder = codecs.utf_32_le_encode
+            else:
+                self.encoder = codecs.utf_32_be_encode
+            return result
+        else:
+            return self.encoder(input, errors)
+
+class StreamReader(codecs.StreamReader):
+
+    def reset(self):
+        codecs.StreamReader.reset(self)
+        try:
+            del self.decode
+        except AttributeError:
+            pass
+
+    def decode(self, input, errors='strict'):
+        (object, consumed, byteorder) = \
+            codecs.utf_32_ex_decode(input, errors, 0, False)
+        if byteorder == -1:
+            self.decode = codecs.utf_32_le_decode
+        elif byteorder == 1:
+            self.decode = codecs.utf_32_be_decode
+        elif consumed>=4:
+            raise UnicodeError,"UTF-32 stream does not start with BOM"
+        return (object, consumed)
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-32',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_32_be.py b/src/main/resources/PythonLibs/encodings/utf_32_be.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe272b5fafec69e506c7cb398712d7b6dd9e6145
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_32_be.py
@@ -0,0 +1,37 @@
+"""
+Python 'utf-32-be' Codec
+"""
+import codecs
+
+### Codec APIs
+
+encode = codecs.utf_32_be_encode
+
+def decode(input, errors='strict'):
+    return codecs.utf_32_be_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.utf_32_be_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    _buffer_decode = codecs.utf_32_be_decode
+
+class StreamWriter(codecs.StreamWriter):
+    encode = codecs.utf_32_be_encode
+
+class StreamReader(codecs.StreamReader):
+    decode = codecs.utf_32_be_decode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-32-be',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_32_le.py b/src/main/resources/PythonLibs/encodings/utf_32_le.py
new file mode 100644
index 0000000000000000000000000000000000000000..9e48210928ee652b17fe797785a20267b1d12a6e
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_32_le.py
@@ -0,0 +1,37 @@
+"""
+Python 'utf-32-le' Codec
+"""
+import codecs
+
+### Codec APIs
+
+encode = codecs.utf_32_le_encode
+
+def decode(input, errors='strict'):
+    return codecs.utf_32_le_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.utf_32_le_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    _buffer_decode = codecs.utf_32_le_decode
+
+class StreamWriter(codecs.StreamWriter):
+    encode = codecs.utf_32_le_encode
+
+class StreamReader(codecs.StreamReader):
+    decode = codecs.utf_32_le_decode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-32-le',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_7.py b/src/main/resources/PythonLibs/encodings/utf_7.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e0567f2087d65e33b3152b8240bcaf703d855fb
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_7.py
@@ -0,0 +1,38 @@
+""" Python 'utf-7' Codec
+
+Written by Brian Quinlan (brian@sweetapp.com).
+"""
+import codecs
+
+### Codec APIs
+
+encode = codecs.utf_7_encode
+
+def decode(input, errors='strict'):
+    return codecs.utf_7_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.utf_7_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    _buffer_decode = codecs.utf_7_decode
+
+class StreamWriter(codecs.StreamWriter):
+    encode = codecs.utf_7_encode
+
+class StreamReader(codecs.StreamReader):
+    decode = codecs.utf_7_decode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-7',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_8.py b/src/main/resources/PythonLibs/encodings/utf_8.py
new file mode 100644
index 0000000000000000000000000000000000000000..1bf6336571547bcec3f5aa7978ff1c7f247490ce
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_8.py
@@ -0,0 +1,42 @@
+""" Python 'utf-8' Codec
+
+
+Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
+
+"""
+import codecs
+
+### Codec APIs
+
+encode = codecs.utf_8_encode
+
+def decode(input, errors='strict'):
+    return codecs.utf_8_decode(input, errors, True)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return codecs.utf_8_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    _buffer_decode = codecs.utf_8_decode
+
+class StreamWriter(codecs.StreamWriter):
+    encode = codecs.utf_8_encode
+
+class StreamReader(codecs.StreamReader):
+    decode = codecs.utf_8_decode
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-8',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/utf_8_sig.py b/src/main/resources/PythonLibs/encodings/utf_8_sig.py
new file mode 100644
index 0000000000000000000000000000000000000000..8784694f02663451bd9196c03039ea8f4a7738e4
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/utf_8_sig.py
@@ -0,0 +1,117 @@
+""" Python 'utf-8-sig' Codec
+This work similar to UTF-8 with the following changes:
+
+* On encoding/writing a UTF-8 encoded BOM will be prepended/written as the
+  first three bytes.
+
+* On decoding/reading if the first three bytes are a UTF-8 encoded BOM, these
+  bytes will be skipped.
+"""
+import codecs
+
+### Codec APIs
+
+def encode(input, errors='strict'):
+    return (codecs.BOM_UTF8 + codecs.utf_8_encode(input, errors)[0], len(input))
+
+def decode(input, errors='strict'):
+    prefix = 0
+    if input[:3] == codecs.BOM_UTF8:
+        input = input[3:]
+        prefix = 3
+    (output, consumed) = codecs.utf_8_decode(input, errors, True)
+    return (output, consumed+prefix)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def __init__(self, errors='strict'):
+        codecs.IncrementalEncoder.__init__(self, errors)
+        self.first = 1
+
+    def encode(self, input, final=False):
+        if self.first:
+            self.first = 0
+            return codecs.BOM_UTF8 + codecs.utf_8_encode(input, self.errors)[0]
+        else:
+            return codecs.utf_8_encode(input, self.errors)[0]
+
+    def reset(self):
+        codecs.IncrementalEncoder.reset(self)
+        self.first = 1
+
+    def getstate(self):
+        return self.first
+
+    def setstate(self, state):
+        self.first = state
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+    def __init__(self, errors='strict'):
+        codecs.BufferedIncrementalDecoder.__init__(self, errors)
+        self.first = True
+
+    def _buffer_decode(self, input, errors, final):
+        if self.first:
+            if len(input) < 3:
+                if codecs.BOM_UTF8.startswith(input):
+                    # not enough data to decide if this really is a BOM
+                    # => try again on the next call
+                    return (u"", 0)
+                else:
+                    self.first = None
+            else:
+                self.first = None
+                if input[:3] == codecs.BOM_UTF8:
+                    (output, consumed) = codecs.utf_8_decode(input[3:], errors, final)
+                    return (output, consumed+3)
+        return codecs.utf_8_decode(input, errors, final)
+
+    def reset(self):
+        codecs.BufferedIncrementalDecoder.reset(self)
+        self.first = True
+
+class StreamWriter(codecs.StreamWriter):
+    def reset(self):
+        codecs.StreamWriter.reset(self)
+        try:
+            del self.encode
+        except AttributeError:
+            pass
+
+    def encode(self, input, errors='strict'):
+        self.encode = codecs.utf_8_encode
+        return encode(input, errors)
+
+class StreamReader(codecs.StreamReader):
+    def reset(self):
+        codecs.StreamReader.reset(self)
+        try:
+            del self.decode
+        except AttributeError:
+            pass
+
+    def decode(self, input, errors='strict'):
+        if len(input) < 3:
+            if codecs.BOM_UTF8.startswith(input):
+                # not enough data to decide if this is a BOM
+                # => try again on the next call
+                return (u"", 0)
+        elif input[:3] == codecs.BOM_UTF8:
+            self.decode = codecs.utf_8_decode
+            (output, consumed) = codecs.utf_8_decode(input[3:],errors)
+            return (output, consumed+3)
+        # (else) no BOM present
+        self.decode = codecs.utf_8_decode
+        return codecs.utf_8_decode(input, errors)
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='utf-8-sig',
+        encode=encode,
+        decode=decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/uu_codec.py b/src/main/resources/PythonLibs/encodings/uu_codec.py
new file mode 100644
index 0000000000000000000000000000000000000000..fb03758171d1218ad023f7a092584baa28111883
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/uu_codec.py
@@ -0,0 +1,129 @@
+""" Python 'uu_codec' Codec - UU content transfer encoding
+
+    Unlike most of the other codecs which target Unicode, this codec
+    will return Python string objects for both encode and decode.
+
+    Written by Marc-Andre Lemburg (mal@lemburg.com). Some details were
+    adapted from uu.py which was written by Lance Ellinghouse and
+    modified by Jack Jansen and Fredrik Lundh.
+
+"""
+import codecs, binascii
+
+### Codec APIs
+
+def uu_encode(input,errors='strict',filename='<data>',mode=0666):
+
+    """ Encodes the object input and returns a tuple (output
+        object, length consumed).
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    from cStringIO import StringIO
+    from binascii import b2a_uu
+    # using str() because of cStringIO's Unicode undesired Unicode behavior.
+    infile = StringIO(str(input))
+    outfile = StringIO()
+    read = infile.read
+    write = outfile.write
+
+    # Encode
+    write('begin %o %s\n' % (mode & 0777, filename))
+    chunk = read(45)
+    while chunk:
+        write(b2a_uu(chunk))
+        chunk = read(45)
+    write(' \nend\n')
+
+    return (outfile.getvalue(), len(input))
+
+def uu_decode(input,errors='strict'):
+
+    """ Decodes the object input and returns a tuple (output
+        object, length consumed).
+
+        input must be an object which provides the bf_getreadbuf
+        buffer slot. Python strings, buffer objects and memory
+        mapped files are examples of objects providing this slot.
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+        Note: filename and file mode information in the input data is
+        ignored.
+
+    """
+    assert errors == 'strict'
+    from cStringIO import StringIO
+    from binascii import a2b_uu
+    infile = StringIO(str(input))
+    outfile = StringIO()
+    readline = infile.readline
+    write = outfile.write
+
+    # Find start of encoded data
+    while 1:
+        s = readline()
+        if not s:
+            raise ValueError, 'Missing "begin" line in input data'
+        if s[:5] == 'begin':
+            break
+
+    # Decode
+    while 1:
+        s = readline()
+        if not s or \
+           s == 'end\n':
+            break
+        try:
+            data = a2b_uu(s)
+        except binascii.Error, v:
+            # Workaround for broken uuencoders by /Fredrik Lundh
+            nbytes = (((ord(s[0])-32) & 63) * 4 + 5) / 3
+            data = a2b_uu(s[:nbytes])
+            #sys.stderr.write("Warning: %s\n" % str(v))
+        write(data)
+    if not s:
+        raise ValueError, 'Truncated input data'
+
+    return (outfile.getvalue(), len(input))
+
+class Codec(codecs.Codec):
+
+    def encode(self,input,errors='strict'):
+        return uu_encode(input,errors)
+
+    def decode(self,input,errors='strict'):
+        return uu_decode(input,errors)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def encode(self, input, final=False):
+        return uu_encode(input, self.errors)[0]
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def decode(self, input, final=False):
+        return uu_decode(input, self.errors)[0]
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='uu',
+        encode=uu_encode,
+        decode=uu_decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/encodings/zlib_codec.py b/src/main/resources/PythonLibs/encodings/zlib_codec.py
new file mode 100644
index 0000000000000000000000000000000000000000..3419f9f48f5efbf1be4802f562536ca235e2748e
--- /dev/null
+++ b/src/main/resources/PythonLibs/encodings/zlib_codec.py
@@ -0,0 +1,102 @@
+""" Python 'zlib_codec' Codec - zlib compression encoding
+
+    Unlike most of the other codecs which target Unicode, this codec
+    will return Python string objects for both encode and decode.
+
+    Written by Marc-Andre Lemburg (mal@lemburg.com).
+
+"""
+import codecs
+import zlib # this codec needs the optional zlib module !
+
+### Codec APIs
+
+def zlib_encode(input,errors='strict'):
+
+    """ Encodes the object input and returns a tuple (output
+        object, length consumed).
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    output = zlib.compress(input)
+    return (output, len(input))
+
+def zlib_decode(input,errors='strict'):
+
+    """ Decodes the object input and returns a tuple (output
+        object, length consumed).
+
+        input must be an object which provides the bf_getreadbuf
+        buffer slot. Python strings, buffer objects and memory
+        mapped files are examples of objects providing this slot.
+
+        errors defines the error handling to apply. It defaults to
+        'strict' handling which is the only currently supported
+        error handling for this codec.
+
+    """
+    assert errors == 'strict'
+    output = zlib.decompress(input)
+    return (output, len(input))
+
+class Codec(codecs.Codec):
+
+    def encode(self, input, errors='strict'):
+        return zlib_encode(input, errors)
+    def decode(self, input, errors='strict'):
+        return zlib_decode(input, errors)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+    def __init__(self, errors='strict'):
+        assert errors == 'strict'
+        self.errors = errors
+        self.compressobj = zlib.compressobj()
+
+    def encode(self, input, final=False):
+        if final:
+            c = self.compressobj.compress(input)
+            return c + self.compressobj.flush()
+        else:
+            return self.compressobj.compress(input)
+
+    def reset(self):
+        self.compressobj = zlib.compressobj()
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+    def __init__(self, errors='strict'):
+        assert errors == 'strict'
+        self.errors = errors
+        self.decompressobj = zlib.decompressobj()
+
+    def decode(self, input, final=False):
+        if final:
+            c = self.decompressobj.decompress(input)
+            return c + self.decompressobj.flush()
+        else:
+            return self.decompressobj.decompress(input)
+
+    def reset(self):
+        self.decompressobj = zlib.decompressobj()
+
+class StreamWriter(Codec,codecs.StreamWriter):
+    pass
+
+class StreamReader(Codec,codecs.StreamReader):
+    pass
+
+### encodings module API
+
+def getregentry():
+    return codecs.CodecInfo(
+        name='zlib',
+        encode=zlib_encode,
+        decode=zlib_decode,
+        incrementalencoder=IncrementalEncoder,
+        incrementaldecoder=IncrementalDecoder,
+        streamreader=StreamReader,
+        streamwriter=StreamWriter,
+    )
diff --git a/src/main/resources/PythonLibs/filecmp.py b/src/main/resources/PythonLibs/filecmp.py
new file mode 100644
index 0000000000000000000000000000000000000000..4728317fce9934b5ef7cbe7fb36b740c6d12bce0
--- /dev/null
+++ b/src/main/resources/PythonLibs/filecmp.py
@@ -0,0 +1,296 @@
+"""Utilities for comparing files and directories.
+
+Classes:
+    dircmp
+
+Functions:
+    cmp(f1, f2, shallow=1) -> int
+    cmpfiles(a, b, common) -> ([], [], [])
+
+"""
+
+import os
+import stat
+from itertools import ifilter, ifilterfalse, imap, izip
+
+__all__ = ["cmp","dircmp","cmpfiles"]
+
+_cache = {}
+BUFSIZE=8*1024
+
+def cmp(f1, f2, shallow=1):
+    """Compare two files.
+
+    Arguments:
+
+    f1 -- First file name
+
+    f2 -- Second file name
+
+    shallow -- Just check stat signature (do not read the files).
+               defaults to 1.
+
+    Return value:
+
+    True if the files are the same, False otherwise.
+
+    This function uses a cache for past comparisons and the results,
+    with a cache invalidation mechanism relying on stale signatures.
+
+    """
+
+    s1 = _sig(os.stat(f1))
+    s2 = _sig(os.stat(f2))
+    if s1[0] != stat.S_IFREG or s2[0] != stat.S_IFREG:
+        return False
+    if shallow and s1 == s2:
+        return True
+    if s1[1] != s2[1]:
+        return False
+
+    outcome = _cache.get((f1, f2, s1, s2))
+    if outcome is None:
+        outcome = _do_cmp(f1, f2)
+        if len(_cache) > 100:      # limit the maximum size of the cache
+            _cache.clear()
+        _cache[f1, f2, s1, s2] = outcome
+    return outcome
+
+def _sig(st):
+    return (stat.S_IFMT(st.st_mode),
+            st.st_size,
+            st.st_mtime)
+
+def _do_cmp(f1, f2):
+    bufsize = BUFSIZE
+    with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2:
+        while True:
+            b1 = fp1.read(bufsize)
+            b2 = fp2.read(bufsize)
+            if b1 != b2:
+                return False
+            if not b1:
+                return True
+
+# Directory comparison class.
+#
+class dircmp:
+    """A class that manages the comparison of 2 directories.
+
+    dircmp(a,b,ignore=None,hide=None)
+      A and B are directories.
+      IGNORE is a list of names to ignore,
+        defaults to ['RCS', 'CVS', 'tags'].
+      HIDE is a list of names to hide,
+        defaults to [os.curdir, os.pardir].
+
+    High level usage:
+      x = dircmp(dir1, dir2)
+      x.report() -> prints a report on the differences between dir1 and dir2
+       or
+      x.report_partial_closure() -> prints report on differences between dir1
+            and dir2, and reports on common immediate subdirectories.
+      x.report_full_closure() -> like report_partial_closure,
+            but fully recursive.
+
+    Attributes:
+     left_list, right_list: The files in dir1 and dir2,
+        filtered by hide and ignore.
+     common: a list of names in both dir1 and dir2.
+     left_only, right_only: names only in dir1, dir2.
+     common_dirs: subdirectories in both dir1 and dir2.
+     common_files: files in both dir1 and dir2.
+     common_funny: names in both dir1 and dir2 where the type differs between
+        dir1 and dir2, or the name is not stat-able.
+     same_files: list of identical files.
+     diff_files: list of filenames which differ.
+     funny_files: list of files which could not be compared.
+     subdirs: a dictionary of dircmp objects, keyed by names in common_dirs.
+     """
+
+    def __init__(self, a, b, ignore=None, hide=None): # Initialize
+        self.left = a
+        self.right = b
+        if hide is None:
+            self.hide = [os.curdir, os.pardir] # Names never to be shown
+        else:
+            self.hide = hide
+        if ignore is None:
+            self.ignore = ['RCS', 'CVS', 'tags'] # Names ignored in comparison
+        else:
+            self.ignore = ignore
+
+    def phase0(self): # Compare everything except common subdirectories
+        self.left_list = _filter(os.listdir(self.left),
+                                 self.hide+self.ignore)
+        self.right_list = _filter(os.listdir(self.right),
+                                  self.hide+self.ignore)
+        self.left_list.sort()
+        self.right_list.sort()
+
+    def phase1(self): # Compute common names
+        a = dict(izip(imap(os.path.normcase, self.left_list), self.left_list))
+        b = dict(izip(imap(os.path.normcase, self.right_list), self.right_list))
+        self.common = map(a.__getitem__, ifilter(b.__contains__, a))
+        self.left_only = map(a.__getitem__, ifilterfalse(b.__contains__, a))
+        self.right_only = map(b.__getitem__, ifilterfalse(a.__contains__, b))
+
+    def phase2(self): # Distinguish files, directories, funnies
+        self.common_dirs = []
+        self.common_files = []
+        self.common_funny = []
+
+        for x in self.common:
+            a_path = os.path.join(self.left, x)
+            b_path = os.path.join(self.right, x)
+
+            ok = 1
+            try:
+                a_stat = os.stat(a_path)
+            except os.error, why:
+                # print 'Can\'t stat', a_path, ':', why[1]
+                ok = 0
+            try:
+                b_stat = os.stat(b_path)
+            except os.error, why:
+                # print 'Can\'t stat', b_path, ':', why[1]
+                ok = 0
+
+            if ok:
+                a_type = stat.S_IFMT(a_stat.st_mode)
+                b_type = stat.S_IFMT(b_stat.st_mode)
+                if a_type != b_type:
+                    self.common_funny.append(x)
+                elif stat.S_ISDIR(a_type):
+                    self.common_dirs.append(x)
+                elif stat.S_ISREG(a_type):
+                    self.common_files.append(x)
+                else:
+                    self.common_funny.append(x)
+            else:
+                self.common_funny.append(x)
+
+    def phase3(self): # Find out differences between common files
+        xx = cmpfiles(self.left, self.right, self.common_files)
+        self.same_files, self.diff_files, self.funny_files = xx
+
+    def phase4(self): # Find out differences between common subdirectories
+        # A new dircmp object is created for each common subdirectory,
+        # these are stored in a dictionary indexed by filename.
+        # The hide and ignore properties are inherited from the parent
+        self.subdirs = {}
+        for x in self.common_dirs:
+            a_x = os.path.join(self.left, x)
+            b_x = os.path.join(self.right, x)
+            self.subdirs[x]  = dircmp(a_x, b_x, self.ignore, self.hide)
+
+    def phase4_closure(self): # Recursively call phase4() on subdirectories
+        self.phase4()
+        for sd in self.subdirs.itervalues():
+            sd.phase4_closure()
+
+    def report(self): # Print a report on the differences between a and b
+        # Output format is purposely lousy
+        print 'diff', self.left, self.right
+        if self.left_only:
+            self.left_only.sort()
+            print 'Only in', self.left, ':', self.left_only
+        if self.right_only:
+            self.right_only.sort()
+            print 'Only in', self.right, ':', self.right_only
+        if self.same_files:
+            self.same_files.sort()
+            print 'Identical files :', self.same_files
+        if self.diff_files:
+            self.diff_files.sort()
+            print 'Differing files :', self.diff_files
+        if self.funny_files:
+            self.funny_files.sort()
+            print 'Trouble with common files :', self.funny_files
+        if self.common_dirs:
+            self.common_dirs.sort()
+            print 'Common subdirectories :', self.common_dirs
+        if self.common_funny:
+            self.common_funny.sort()
+            print 'Common funny cases :', self.common_funny
+
+    def report_partial_closure(self): # Print reports on self and on subdirs
+        self.report()
+        for sd in self.subdirs.itervalues():
+            print
+            sd.report()
+
+    def report_full_closure(self): # Report on self and subdirs recursively
+        self.report()
+        for sd in self.subdirs.itervalues():
+            print
+            sd.report_full_closure()
+
+    methodmap = dict(subdirs=phase4,
+                     same_files=phase3, diff_files=phase3, funny_files=phase3,
+                     common_dirs = phase2, common_files=phase2, common_funny=phase2,
+                     common=phase1, left_only=phase1, right_only=phase1,
+                     left_list=phase0, right_list=phase0)
+
+    def __getattr__(self, attr):
+        if attr not in self.methodmap:
+            raise AttributeError, attr
+        self.methodmap[attr](self)
+        return getattr(self, attr)
+
+def cmpfiles(a, b, common, shallow=1):
+    """Compare common files in two directories.
+
+    a, b -- directory names
+    common -- list of file names found in both directories
+    shallow -- if true, do comparison based solely on stat() information
+
+    Returns a tuple of three lists:
+      files that compare equal
+      files that are different
+      filenames that aren't regular files.
+
+    """
+    res = ([], [], [])
+    for x in common:
+        ax = os.path.join(a, x)
+        bx = os.path.join(b, x)
+        res[_cmp(ax, bx, shallow)].append(x)
+    return res
+
+
+# Compare two files.
+# Return:
+#       0 for equal
+#       1 for different
+#       2 for funny cases (can't stat, etc.)
+#
+def _cmp(a, b, sh, abs=abs, cmp=cmp):
+    try:
+        return not abs(cmp(a, b, sh))
+    except os.error:
+        return 2
+
+
+# Return a copy with items that occur in skip removed.
+#
+def _filter(flist, skip):
+    return list(ifilterfalse(skip.__contains__, flist))
+
+
+# Demonstration and testing.
+#
+def demo():
+    import sys
+    import getopt
+    options, args = getopt.getopt(sys.argv[1:], 'r')
+    if len(args) != 2:
+        raise getopt.GetoptError('need exactly two args', None)
+    dd = dircmp(args[0], args[1])
+    if ('-r', '') in options:
+        dd.report_full_closure()
+    else:
+        dd.report()
+
+if __name__ == '__main__':
+    demo()
diff --git a/src/main/resources/PythonLibs/fileinput.py b/src/main/resources/PythonLibs/fileinput.py
new file mode 100644
index 0000000000000000000000000000000000000000..5257711d224754fb2eeb07b20a5ab22bcd2fd843
--- /dev/null
+++ b/src/main/resources/PythonLibs/fileinput.py
@@ -0,0 +1,415 @@
+"""Helper class to quickly write a loop over all standard input files.
+
+Typical use is:
+
+    import fileinput
+    for line in fileinput.input():
+        process(line)
+
+This iterates over the lines of all files listed in sys.argv[1:],
+defaulting to sys.stdin if the list is empty.  If a filename is '-' it
+is also replaced by sys.stdin.  To specify an alternative list of
+filenames, pass it as the argument to input().  A single file name is
+also allowed.
+
+Functions filename(), lineno() return the filename and cumulative line
+number of the line that has just been read; filelineno() returns its
+line number in the current file; isfirstline() returns true iff the
+line just read is the first line of its file; isstdin() returns true
+iff the line was read from sys.stdin.  Function nextfile() closes the
+current file so that the next iteration will read the first line from
+the next file (if any); lines not read from the file will not count
+towards the cumulative line count; the filename is not changed until
+after the first line of the next file has been read.  Function close()
+closes the sequence.
+
+Before any lines have been read, filename() returns None and both line
+numbers are zero; nextfile() has no effect.  After all lines have been
+read, filename() and the line number functions return the values
+pertaining to the last line read; nextfile() has no effect.
+
+All files are opened in text mode by default, you can override this by
+setting the mode parameter to input() or FileInput.__init__().
+If an I/O error occurs during opening or reading a file, the IOError
+exception is raised.
+
+If sys.stdin is used more than once, the second and further use will
+return no lines, except perhaps for interactive use, or if it has been
+explicitly reset (e.g. using sys.stdin.seek(0)).
+
+Empty files are opened and immediately closed; the only time their
+presence in the list of filenames is noticeable at all is when the
+last file opened is empty.
+
+It is possible that the last line of a file doesn't end in a newline
+character; otherwise lines are returned including the trailing
+newline.
+
+Class FileInput is the implementation; its methods filename(),
+lineno(), fileline(), isfirstline(), isstdin(), nextfile() and close()
+correspond to the functions in the module.  In addition it has a
+readline() method which returns the next input line, and a
+__getitem__() method which implements the sequence behavior.  The
+sequence must be accessed in strictly sequential order; sequence
+access and readline() cannot be mixed.
+
+Optional in-place filtering: if the keyword argument inplace=1 is
+passed to input() or to the FileInput constructor, the file is moved
+to a backup file and standard output is directed to the input file.
+This makes it possible to write a filter that rewrites its input file
+in place.  If the keyword argument backup=".<some extension>" is also
+given, it specifies the extension for the backup file, and the backup
+file remains around; by default, the extension is ".bak" and it is
+deleted when the output file is closed.  In-place filtering is
+disabled when standard input is read.  XXX The current implementation
+does not work for MS-DOS 8+3 filesystems.
+
+Performance: this module is unfortunately one of the slower ways of
+processing large numbers of input lines.  Nevertheless, a significant
+speed-up has been obtained by using readlines(bufsize) instead of
+readline().  A new keyword argument, bufsize=N, is present on the
+input() function and the FileInput() class to override the default
+buffer size.
+
+XXX Possible additions:
+
+- optional getopt argument processing
+- isatty()
+- read(), read(size), even readlines()
+
+"""
+
+import sys, os
+
+__all__ = ["input","close","nextfile","filename","lineno","filelineno",
+           "isfirstline","isstdin","FileInput"]
+
+_state = None
+
+DEFAULT_BUFSIZE = 8*1024
+
+def input(files=None, inplace=0, backup="", bufsize=0,
+          mode="r", openhook=None):
+    """input([files[, inplace[, backup[, mode[, openhook]]]]])
+
+    Create an instance of the FileInput class. The instance will be used
+    as global state for the functions of this module, and is also returned
+    to use during iteration. The parameters to this function will be passed
+    along to the constructor of the FileInput class.
+    """
+    global _state
+    if _state and _state._file:
+        raise RuntimeError, "input() already active"
+    _state = FileInput(files, inplace, backup, bufsize, mode, openhook)
+    return _state
+
+def close():
+    """Close the sequence."""
+    global _state
+    state = _state
+    _state = None
+    if state:
+        state.close()
+
+def nextfile():
+    """
+    Close the current file so that the next iteration will read the first
+    line from the next file (if any); lines not read from the file will
+    not count towards the cumulative line count. The filename is not
+    changed until after the first line of the next file has been read.
+    Before the first line has been read, this function has no effect;
+    it cannot be used to skip the first file. After the last line of the
+    last file has been read, this function has no effect.
+    """
+    if not _state:
+        raise RuntimeError, "no active input()"
+    return _state.nextfile()
+
+def filename():
+    """
+    Return the name of the file currently being read.
+    Before the first line has been read, returns None.
+    """
+    if not _state:
+        raise RuntimeError, "no active input()"
+    return _state.filename()
+
+def lineno():
+    """
+    Return the cumulative line number of the line that has just been read.
+    Before the first line has been read, returns 0. After the last line
+    of the last file has been read, returns the line number of that line.
+    """
+    if not _state:
+        raise RuntimeError, "no active input()"
+    return _state.lineno()
+
+def filelineno():
+    """
+    Return the line number in the current file. Before the first line
+    has been read, returns 0. After the last line of the last file has
+    been read, returns the line number of that line within the file.
+    """
+    if not _state:
+        raise RuntimeError, "no active input()"
+    return _state.filelineno()
+
+def fileno():
+    """
+    Return the file number of the current file. When no file is currently
+    opened, returns -1.
+    """
+    if not _state:
+        raise RuntimeError, "no active input()"
+    return _state.fileno()
+
+def isfirstline():
+    """
+    Returns true the line just read is the first line of its file,
+    otherwise returns false.
+    """
+    if not _state:
+        raise RuntimeError, "no active input()"
+    return _state.isfirstline()
+
+def isstdin():
+    """
+    Returns true if the last line was read from sys.stdin,
+    otherwise returns false.
+    """
+    if not _state:
+        raise RuntimeError, "no active input()"
+    return _state.isstdin()
+
+class FileInput:
+    """class FileInput([files[, inplace[, backup[, mode[, openhook]]]]])
+
+    Class FileInput is the implementation of the module; its methods
+    filename(), lineno(), fileline(), isfirstline(), isstdin(), fileno(),
+    nextfile() and close() correspond to the functions of the same name
+    in the module.
+    In addition it has a readline() method which returns the next
+    input line, and a __getitem__() method which implements the
+    sequence behavior. The sequence must be accessed in strictly
+    sequential order; random access and readline() cannot be mixed.
+    """
+
+    def __init__(self, files=None, inplace=0, backup="", bufsize=0,
+                 mode="r", openhook=None):
+        if isinstance(files, basestring):
+            files = (files,)
+        else:
+            if files is None:
+                files = sys.argv[1:]
+            if not files:
+                files = ('-',)
+            else:
+                files = tuple(files)
+        self._files = files
+        self._inplace = inplace
+        self._backup = backup
+        self._bufsize = bufsize or DEFAULT_BUFSIZE
+        self._savestdout = None
+        self._output = None
+        self._filename = None
+        self._lineno = 0
+        self._filelineno = 0
+        self._file = None
+        self._isstdin = False
+        self._backupfilename = None
+        self._buffer = []
+        self._bufindex = 0
+        # restrict mode argument to reading modes
+        if mode not in ('r', 'rU', 'U', 'rb'):
+            raise ValueError("FileInput opening mode must be one of "
+                             "'r', 'rU', 'U' and 'rb'")
+        self._mode = mode
+        if inplace and openhook:
+            raise ValueError("FileInput cannot use an opening hook in inplace mode")
+        elif openhook and not hasattr(openhook, '__call__'):
+            raise ValueError("FileInput openhook must be callable")
+        self._openhook = openhook
+
+    def __del__(self):
+        self.close()
+
+    def close(self):
+        self.nextfile()
+        self._files = ()
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        try:
+            line = self._buffer[self._bufindex]
+        except IndexError:
+            pass
+        else:
+            self._bufindex += 1
+            self._lineno += 1
+            self._filelineno += 1
+            return line
+        line = self.readline()
+        if not line:
+            raise StopIteration
+        return line
+
+    def __getitem__(self, i):
+        if i != self._lineno:
+            raise RuntimeError, "accessing lines out of order"
+        try:
+            return self.next()
+        except StopIteration:
+            raise IndexError, "end of input reached"
+
+    def nextfile(self):
+        savestdout = self._savestdout
+        self._savestdout = 0
+        if savestdout:
+            sys.stdout = savestdout
+
+        output = self._output
+        self._output = 0
+        if output:
+            output.close()
+
+        file = self._file
+        self._file = 0
+        if file and not self._isstdin:
+            file.close()
+
+        backupfilename = self._backupfilename
+        self._backupfilename = 0
+        if backupfilename and not self._backup:
+            try: os.unlink(backupfilename)
+            except OSError: pass
+
+        self._isstdin = False
+        self._buffer = []
+        self._bufindex = 0
+
+    def readline(self):
+        try:
+            line = self._buffer[self._bufindex]
+        except IndexError:
+            pass
+        else:
+            self._bufindex += 1
+            self._lineno += 1
+            self._filelineno += 1
+            return line
+        if not self._file:
+            if not self._files:
+                return ""
+            self._filename = self._files[0]
+            self._files = self._files[1:]
+            self._filelineno = 0
+            self._file = None
+            self._isstdin = False
+            self._backupfilename = 0
+            if self._filename == '-':
+                self._filename = '<stdin>'
+                self._file = sys.stdin
+                self._isstdin = True
+            else:
+                if self._inplace:
+                    self._backupfilename = (
+                        self._filename + (self._backup or os.extsep+"bak"))
+                    try: os.unlink(self._backupfilename)
+                    except os.error: pass
+                    # The next few lines may raise IOError
+                    os.rename(self._filename, self._backupfilename)
+                    self._file = open(self._backupfilename, self._mode)
+                    try:
+                        perm = os.fstat(self._file.fileno()).st_mode
+                    except (AttributeError, OSError):
+                        # AttributeError occurs in Jython, where there's no
+                        # os.fstat.
+                        self._output = open(self._filename, "w")
+                    else:
+                        fd = os.open(self._filename,
+                                     os.O_CREAT | os.O_WRONLY | os.O_TRUNC,
+                                     perm)
+                        self._output = os.fdopen(fd, "w")
+                        try:
+                            if hasattr(os, 'chmod'):
+                                os.chmod(self._filename, perm)
+                        except OSError:
+                            pass
+                    self._savestdout = sys.stdout
+                    sys.stdout = self._output
+                else:
+                    # This may raise IOError
+                    if self._openhook:
+                        self._file = self._openhook(self._filename, self._mode)
+                    else:
+                        self._file = open(self._filename, self._mode)
+        self._buffer = self._file.readlines(self._bufsize)
+        self._bufindex = 0
+        if not self._buffer:
+            self.nextfile()
+        # Recursive call
+        return self.readline()
+
+    def filename(self):
+        return self._filename
+
+    def lineno(self):
+        return self._lineno
+
+    def filelineno(self):
+        return self._filelineno
+
+    def fileno(self):
+        if self._file:
+            try:
+                return self._file.fileno()
+            except ValueError:
+                return -1
+        else:
+            return -1
+
+    def isfirstline(self):
+        return self._filelineno == 1
+
+    def isstdin(self):
+        return self._isstdin
+
+
+def hook_compressed(filename, mode):
+    ext = os.path.splitext(filename)[1]
+    if ext == '.gz':
+        import gzip
+        return gzip.open(filename, mode)
+    elif ext == '.bz2':
+        import bz2
+        return bz2.BZ2File(filename, mode)
+    else:
+        return open(filename, mode)
+
+
+def hook_encoded(encoding):
+    import codecs
+    def openhook(filename, mode):
+        return codecs.open(filename, mode, encoding)
+    return openhook
+
+
+def _test():
+    import getopt
+    inplace = 0
+    backup = 0
+    opts, args = getopt.getopt(sys.argv[1:], "ib:")
+    for o, a in opts:
+        if o == '-i': inplace = 1
+        if o == '-b': backup = a
+    for line in input(args, inplace=inplace, backup=backup):
+        if line[-1:] == '\n': line = line[:-1]
+        if line[-1:] == '\r': line = line[:-1]
+        print "%d: %s[%d]%s %s" % (lineno(), filename(), filelineno(),
+                                   isfirstline() and "*" or "", line)
+    print "%d: %s[%d]" % (lineno(), filename(), filelineno())
+
+if __name__ == '__main__':
+    _test()
diff --git a/src/main/resources/PythonLibs/fnmatch.py b/src/main/resources/PythonLibs/fnmatch.py
new file mode 100644
index 0000000000000000000000000000000000000000..ffe99b5762db0116b23f3008c7de54d49681a84c
--- /dev/null
+++ b/src/main/resources/PythonLibs/fnmatch.py
@@ -0,0 +1,116 @@
+"""Filename matching with shell patterns.
+
+fnmatch(FILENAME, PATTERN) matches according to the local convention.
+fnmatchcase(FILENAME, PATTERN) always takes case in account.
+
+The functions operate by translating the pattern into a regular
+expression.  They cache the compiled regular expressions for speed.
+
+The function translate(PATTERN) returns a regular expression
+corresponding to PATTERN.  (It does not compile it.)
+"""
+
+import re
+
+__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"]
+
+_cache = {}
+_MAXCACHE = 100
+
+def _purge():
+    """Clear the pattern cache"""
+    _cache.clear()
+
+def fnmatch(name, pat):
+    """Test whether FILENAME matches PATTERN.
+
+    Patterns are Unix shell style:
+
+    *       matches everything
+    ?       matches any single character
+    [seq]   matches any character in seq
+    [!seq]  matches any char not in seq
+
+    An initial period in FILENAME is not special.
+    Both FILENAME and PATTERN are first case-normalized
+    if the operating system requires it.
+    If you don't want this, use fnmatchcase(FILENAME, PATTERN).
+    """
+
+    import os
+    name = os.path.normcase(name)
+    pat = os.path.normcase(pat)
+    return fnmatchcase(name, pat)
+
+def filter(names, pat):
+    """Return the subset of the list NAMES that match PAT"""
+    import os,posixpath
+    result=[]
+    pat=os.path.normcase(pat)
+    if not pat in _cache:
+        res = translate(pat)
+        if len(_cache) >= _MAXCACHE:
+            _cache.clear()
+        _cache[pat] = re.compile(res)
+    match=_cache[pat].match
+    if os.path is posixpath:
+        # normcase on posix is NOP. Optimize it away from the loop.
+        for name in names:
+            if match(name):
+                result.append(name)
+    else:
+        for name in names:
+            if match(os.path.normcase(name)):
+                result.append(name)
+    return result
+
+def fnmatchcase(name, pat):
+    """Test whether FILENAME matches PATTERN, including case.
+
+    This is a version of fnmatch() which doesn't case-normalize
+    its arguments.
+    """
+
+    if not pat in _cache:
+        res = translate(pat)
+        if len(_cache) >= _MAXCACHE:
+            _cache.clear()
+        _cache[pat] = re.compile(res)
+    return _cache[pat].match(name) is not None
+
+def translate(pat):
+    """Translate a shell PATTERN to a regular expression.
+
+    There is no way to quote meta-characters.
+    """
+
+    i, n = 0, len(pat)
+    res = ''
+    while i < n:
+        c = pat[i]
+        i = i+1
+        if c == '*':
+            res = res + '.*'
+        elif c == '?':
+            res = res + '.'
+        elif c == '[':
+            j = i
+            if j < n and pat[j] == '!':
+                j = j+1
+            if j < n and pat[j] == ']':
+                j = j+1
+            while j < n and pat[j] != ']':
+                j = j+1
+            if j >= n:
+                res = res + '\\['
+            else:
+                stuff = pat[i:j].replace('\\','\\\\')
+                i = j+1
+                if stuff[0] == '!':
+                    stuff = '^' + stuff[1:]
+                elif stuff[0] == '^':
+                    stuff = '\\' + stuff
+                res = '%s[%s]' % (res, stuff)
+        else:
+            res = res + re.escape(c)
+    return res + '\Z(?ms)'
diff --git a/src/main/resources/PythonLibs/formatter.py b/src/main/resources/PythonLibs/formatter.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0a8fe10b22323618ca030d984ba0230c18e8593
--- /dev/null
+++ b/src/main/resources/PythonLibs/formatter.py
@@ -0,0 +1,445 @@
+"""Generic output formatting.
+
+Formatter objects transform an abstract flow of formatting events into
+specific output events on writer objects. Formatters manage several stack
+structures to allow various properties of a writer object to be changed and
+restored; writers need not be able to handle relative changes nor any sort
+of ``change back'' operation. Specific writer properties which may be
+controlled via formatter objects are horizontal alignment, font, and left
+margin indentations. A mechanism is provided which supports providing
+arbitrary, non-exclusive style settings to a writer as well. Additional
+interfaces facilitate formatting events which are not reversible, such as
+paragraph separation.
+
+Writer objects encapsulate device interfaces. Abstract devices, such as
+file formats, are supported as well as physical devices. The provided
+implementations all work with abstract devices. The interface makes
+available mechanisms for setting the properties which formatter objects
+manage and inserting data into the output.
+"""
+
+import sys
+
+
+AS_IS = None
+
+
+class NullFormatter:
+    """A formatter which does nothing.
+
+    If the writer parameter is omitted, a NullWriter instance is created.
+    No methods of the writer are called by NullFormatter instances.
+
+    Implementations should inherit from this class if implementing a writer
+    interface but don't need to inherit any implementation.
+
+    """
+
+    def __init__(self, writer=None):
+        if writer is None:
+            writer = NullWriter()
+        self.writer = writer
+    def end_paragraph(self, blankline): pass
+    def add_line_break(self): pass
+    def add_hor_rule(self, *args, **kw): pass
+    def add_label_data(self, format, counter, blankline=None): pass
+    def add_flowing_data(self, data): pass
+    def add_literal_data(self, data): pass
+    def flush_softspace(self): pass
+    def push_alignment(self, align): pass
+    def pop_alignment(self): pass
+    def push_font(self, x): pass
+    def pop_font(self): pass
+    def push_margin(self, margin): pass
+    def pop_margin(self): pass
+    def set_spacing(self, spacing): pass
+    def push_style(self, *styles): pass
+    def pop_style(self, n=1): pass
+    def assert_line_data(self, flag=1): pass
+
+
+class AbstractFormatter:
+    """The standard formatter.
+
+    This implementation has demonstrated wide applicability to many writers,
+    and may be used directly in most circumstances.  It has been used to
+    implement a full-featured World Wide Web browser.
+
+    """
+
+    #  Space handling policy:  blank spaces at the boundary between elements
+    #  are handled by the outermost context.  "Literal" data is not checked
+    #  to determine context, so spaces in literal data are handled directly
+    #  in all circumstances.
+
+    def __init__(self, writer):
+        self.writer = writer            # Output device
+        self.align = None               # Current alignment
+        self.align_stack = []           # Alignment stack
+        self.font_stack = []            # Font state
+        self.margin_stack = []          # Margin state
+        self.spacing = None             # Vertical spacing state
+        self.style_stack = []           # Other state, e.g. color
+        self.nospace = 1                # Should leading space be suppressed
+        self.softspace = 0              # Should a space be inserted
+        self.para_end = 1               # Just ended a paragraph
+        self.parskip = 0                # Skipped space between paragraphs?
+        self.hard_break = 1             # Have a hard break
+        self.have_label = 0
+
+    def end_paragraph(self, blankline):
+        if not self.hard_break:
+            self.writer.send_line_break()
+            self.have_label = 0
+        if self.parskip < blankline and not self.have_label:
+            self.writer.send_paragraph(blankline - self.parskip)
+            self.parskip = blankline
+            self.have_label = 0
+        self.hard_break = self.nospace = self.para_end = 1
+        self.softspace = 0
+
+    def add_line_break(self):
+        if not (self.hard_break or self.para_end):
+            self.writer.send_line_break()
+            self.have_label = self.parskip = 0
+        self.hard_break = self.nospace = 1
+        self.softspace = 0
+
+    def add_hor_rule(self, *args, **kw):
+        if not self.hard_break:
+            self.writer.send_line_break()
+        self.writer.send_hor_rule(*args, **kw)
+        self.hard_break = self.nospace = 1
+        self.have_label = self.para_end = self.softspace = self.parskip = 0
+
+    def add_label_data(self, format, counter, blankline = None):
+        if self.have_label or not self.hard_break:
+            self.writer.send_line_break()
+        if not self.para_end:
+            self.writer.send_paragraph((blankline and 1) or 0)
+        if isinstance(format, str):
+            self.writer.send_label_data(self.format_counter(format, counter))
+        else:
+            self.writer.send_label_data(format)
+        self.nospace = self.have_label = self.hard_break = self.para_end = 1
+        self.softspace = self.parskip = 0
+
+    def format_counter(self, format, counter):
+        label = ''
+        for c in format:
+            if c == '1':
+                label = label + ('%d' % counter)
+            elif c in 'aA':
+                if counter > 0:
+                    label = label + self.format_letter(c, counter)
+            elif c in 'iI':
+                if counter > 0:
+                    label = label + self.format_roman(c, counter)
+            else:
+                label = label + c
+        return label
+
+    def format_letter(self, case, counter):
+        label = ''
+        while counter > 0:
+            counter, x = divmod(counter-1, 26)
+            # This makes a strong assumption that lowercase letters
+            # and uppercase letters form two contiguous blocks, with
+            # letters in order!
+            s = chr(ord(case) + x)
+            label = s + label
+        return label
+
+    def format_roman(self, case, counter):
+        ones = ['i', 'x', 'c', 'm']
+        fives = ['v', 'l', 'd']
+        label, index = '', 0
+        # This will die of IndexError when counter is too big
+        while counter > 0:
+            counter, x = divmod(counter, 10)
+            if x == 9:
+                label = ones[index] + ones[index+1] + label
+            elif x == 4:
+                label = ones[index] + fives[index] + label
+            else:
+                if x >= 5:
+                    s = fives[index]
+                    x = x-5
+                else:
+                    s = ''
+                s = s + ones[index]*x
+                label = s + label
+            index = index + 1
+        if case == 'I':
+            return label.upper()
+        return label
+
+    def add_flowing_data(self, data):
+        if not data: return
+        prespace = data[:1].isspace()
+        postspace = data[-1:].isspace()
+        data = " ".join(data.split())
+        if self.nospace and not data:
+            return
+        elif prespace or self.softspace:
+            if not data:
+                if not self.nospace:
+                    self.softspace = 1
+                    self.parskip = 0
+                return
+            if not self.nospace:
+                data = ' ' + data
+        self.hard_break = self.nospace = self.para_end = \
+                          self.parskip = self.have_label = 0
+        self.softspace = postspace
+        self.writer.send_flowing_data(data)
+
+    def add_literal_data(self, data):
+        if not data: return
+        if self.softspace:
+            self.writer.send_flowing_data(" ")
+        self.hard_break = data[-1:] == '\n'
+        self.nospace = self.para_end = self.softspace = \
+                       self.parskip = self.have_label = 0
+        self.writer.send_literal_data(data)
+
+    def flush_softspace(self):
+        if self.softspace:
+            self.hard_break = self.para_end = self.parskip = \
+                              self.have_label = self.softspace = 0
+            self.nospace = 1
+            self.writer.send_flowing_data(' ')
+
+    def push_alignment(self, align):
+        if align and align != self.align:
+            self.writer.new_alignment(align)
+            self.align = align
+            self.align_stack.append(align)
+        else:
+            self.align_stack.append(self.align)
+
+    def pop_alignment(self):
+        if self.align_stack:
+            del self.align_stack[-1]
+        if self.align_stack:
+            self.align = align = self.align_stack[-1]
+            self.writer.new_alignment(align)
+        else:
+            self.align = None
+            self.writer.new_alignment(None)
+
+    def push_font(self, font):
+        size, i, b, tt = font
+        if self.softspace:
+            self.hard_break = self.para_end = self.softspace = 0
+            self.nospace = 1
+            self.writer.send_flowing_data(' ')
+        if self.font_stack:
+            csize, ci, cb, ctt = self.font_stack[-1]
+            if size is AS_IS: size = csize
+            if i is AS_IS: i = ci
+            if b is AS_IS: b = cb
+            if tt is AS_IS: tt = ctt
+        font = (size, i, b, tt)
+        self.font_stack.append(font)
+        self.writer.new_font(font)
+
+    def pop_font(self):
+        if self.font_stack:
+            del self.font_stack[-1]
+        if self.font_stack:
+            font = self.font_stack[-1]
+        else:
+            font = None
+        self.writer.new_font(font)
+
+    def push_margin(self, margin):
+        self.margin_stack.append(margin)
+        fstack = filter(None, self.margin_stack)
+        if not margin and fstack:
+            margin = fstack[-1]
+        self.writer.new_margin(margin, len(fstack))
+
+    def pop_margin(self):
+        if self.margin_stack:
+            del self.margin_stack[-1]
+        fstack = filter(None, self.margin_stack)
+        if fstack:
+            margin = fstack[-1]
+        else:
+            margin = None
+        self.writer.new_margin(margin, len(fstack))
+
+    def set_spacing(self, spacing):
+        self.spacing = spacing
+        self.writer.new_spacing(spacing)
+
+    def push_style(self, *styles):
+        if self.softspace:
+            self.hard_break = self.para_end = self.softspace = 0
+            self.nospace = 1
+            self.writer.send_flowing_data(' ')
+        for style in styles:
+            self.style_stack.append(style)
+        self.writer.new_styles(tuple(self.style_stack))
+
+    def pop_style(self, n=1):
+        del self.style_stack[-n:]
+        self.writer.new_styles(tuple(self.style_stack))
+
+    def assert_line_data(self, flag=1):
+        self.nospace = self.hard_break = not flag
+        self.para_end = self.parskip = self.have_label = 0
+
+
+class NullWriter:
+    """Minimal writer interface to use in testing & inheritance.
+
+    A writer which only provides the interface definition; no actions are
+    taken on any methods.  This should be the base class for all writers
+    which do not need to inherit any implementation methods.
+
+    """
+    def __init__(self): pass
+    def flush(self): pass
+    def new_alignment(self, align): pass
+    def new_font(self, font): pass
+    def new_margin(self, margin, level): pass
+    def new_spacing(self, spacing): pass
+    def new_styles(self, styles): pass
+    def send_paragraph(self, blankline): pass
+    def send_line_break(self): pass
+    def send_hor_rule(self, *args, **kw): pass
+    def send_label_data(self, data): pass
+    def send_flowing_data(self, data): pass
+    def send_literal_data(self, data): pass
+
+
+class AbstractWriter(NullWriter):
+    """A writer which can be used in debugging formatters, but not much else.
+
+    Each method simply announces itself by printing its name and
+    arguments on standard output.
+
+    """
+
+    def new_alignment(self, align):
+        print "new_alignment(%r)" % (align,)
+
+    def new_font(self, font):
+        print "new_font(%r)" % (font,)
+
+    def new_margin(self, margin, level):
+        print "new_margin(%r, %d)" % (margin, level)
+
+    def new_spacing(self, spacing):
+        print "new_spacing(%r)" % (spacing,)
+
+    def new_styles(self, styles):
+        print "new_styles(%r)" % (styles,)
+
+    def send_paragraph(self, blankline):
+        print "send_paragraph(%r)" % (blankline,)
+
+    def send_line_break(self):
+        print "send_line_break()"
+
+    def send_hor_rule(self, *args, **kw):
+        print "send_hor_rule()"
+
+    def send_label_data(self, data):
+        print "send_label_data(%r)" % (data,)
+
+    def send_flowing_data(self, data):
+        print "send_flowing_data(%r)" % (data,)
+
+    def send_literal_data(self, data):
+        print "send_literal_data(%r)" % (data,)
+
+
+class DumbWriter(NullWriter):
+    """Simple writer class which writes output on the file object passed in
+    as the file parameter or, if file is omitted, on standard output.  The
+    output is simply word-wrapped to the number of columns specified by
+    the maxcol parameter.  This class is suitable for reflowing a sequence
+    of paragraphs.
+
+    """
+
+    def __init__(self, file=None, maxcol=72):
+        self.file = file or sys.stdout
+        self.maxcol = maxcol
+        NullWriter.__init__(self)
+        self.reset()
+
+    def reset(self):
+        self.col = 0
+        self.atbreak = 0
+
+    def send_paragraph(self, blankline):
+        self.file.write('\n'*blankline)
+        self.col = 0
+        self.atbreak = 0
+
+    def send_line_break(self):
+        self.file.write('\n')
+        self.col = 0
+        self.atbreak = 0
+
+    def send_hor_rule(self, *args, **kw):
+        self.file.write('\n')
+        self.file.write('-'*self.maxcol)
+        self.file.write('\n')
+        self.col = 0
+        self.atbreak = 0
+
+    def send_literal_data(self, data):
+        self.file.write(data)
+        i = data.rfind('\n')
+        if i >= 0:
+            self.col = 0
+            data = data[i+1:]
+        data = data.expandtabs()
+        self.col = self.col + len(data)
+        self.atbreak = 0
+
+    def send_flowing_data(self, data):
+        if not data: return
+        atbreak = self.atbreak or data[0].isspace()
+        col = self.col
+        maxcol = self.maxcol
+        write = self.file.write
+        for word in data.split():
+            if atbreak:
+                if col + len(word) >= maxcol:
+                    write('\n')
+                    col = 0
+                else:
+                    write(' ')
+                    col = col + 1
+            write(word)
+            col = col + len(word)
+            atbreak = 1
+        self.col = col
+        self.atbreak = data[-1].isspace()
+
+
+def test(file = None):
+    w = DumbWriter()
+    f = AbstractFormatter(w)
+    if file is not None:
+        fp = open(file)
+    elif sys.argv[1:]:
+        fp = open(sys.argv[1])
+    else:
+        fp = sys.stdin
+    for line in fp:
+        if line == '\n':
+            f.end_paragraph(1)
+        else:
+            f.add_flowing_data(line)
+    f.end_paragraph(0)
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/fpformat.py b/src/main/resources/PythonLibs/fpformat.py
new file mode 100644
index 0000000000000000000000000000000000000000..71cbb25f3c8b9eb861415eca88358aeb049202ff
--- /dev/null
+++ b/src/main/resources/PythonLibs/fpformat.py
@@ -0,0 +1,145 @@
+"""General floating point formatting functions.
+
+Functions:
+fix(x, digits_behind)
+sci(x, digits_behind)
+
+Each takes a number or a string and a number of digits as arguments.
+
+Parameters:
+x:             number to be formatted; or a string resembling a number
+digits_behind: number of digits behind the decimal point
+"""
+from warnings import warnpy3k
+warnpy3k("the fpformat module has been removed in Python 3.0", stacklevel=2)
+del warnpy3k
+
+import re
+
+__all__ = ["fix","sci","NotANumber"]
+
+# Compiled regular expression to "decode" a number
+decoder = re.compile(r'^([-+]?)0*(\d*)((?:\.\d*)?)(([eE][-+]?\d+)?)$')
+# \0 the whole thing
+# \1 leading sign or empty
+# \2 digits left of decimal point
+# \3 fraction (empty or begins with point)
+# \4 exponent part (empty or begins with 'e' or 'E')
+
+try:
+    class NotANumber(ValueError):
+        pass
+except TypeError:
+    NotANumber = 'fpformat.NotANumber'
+
+def extract(s):
+    """Return (sign, intpart, fraction, expo) or raise an exception:
+    sign is '+' or '-'
+    intpart is 0 or more digits beginning with a nonzero
+    fraction is 0 or more digits
+    expo is an integer"""
+    res = decoder.match(s)
+    if res is None: raise NotANumber, s
+    sign, intpart, fraction, exppart = res.group(1,2,3,4)
+    if sign == '+': sign = ''
+    if fraction: fraction = fraction[1:]
+    if exppart: expo = int(exppart[1:])
+    else: expo = 0
+    return sign, intpart, fraction, expo
+
+def unexpo(intpart, fraction, expo):
+    """Remove the exponent by changing intpart and fraction."""
+    if expo > 0: # Move the point left
+        f = len(fraction)
+        intpart, fraction = intpart + fraction[:expo], fraction[expo:]
+        if expo > f:
+            intpart = intpart + '0'*(expo-f)
+    elif expo < 0: # Move the point right
+        i = len(intpart)
+        intpart, fraction = intpart[:expo], intpart[expo:] + fraction
+        if expo < -i:
+            fraction = '0'*(-expo-i) + fraction
+    return intpart, fraction
+
+def roundfrac(intpart, fraction, digs):
+    """Round or extend the fraction to size digs."""
+    f = len(fraction)
+    if f <= digs:
+        return intpart, fraction + '0'*(digs-f)
+    i = len(intpart)
+    if i+digs < 0:
+        return '0'*-digs, ''
+    total = intpart + fraction
+    nextdigit = total[i+digs]
+    if nextdigit >= '5': # Hard case: increment last digit, may have carry!
+        n = i + digs - 1
+        while n >= 0:
+            if total[n] != '9': break
+            n = n-1
+        else:
+            total = '0' + total
+            i = i+1
+            n = 0
+        total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1)
+        intpart, fraction = total[:i], total[i:]
+    if digs >= 0:
+        return intpart, fraction[:digs]
+    else:
+        return intpart[:digs] + '0'*-digs, ''
+
+def fix(x, digs):
+    """Format x as [-]ddd.ddd with 'digs' digits after the point
+    and at least one digit before.
+    If digs <= 0, the point is suppressed."""
+    if type(x) != type(''): x = repr(x)
+    try:
+        sign, intpart, fraction, expo = extract(x)
+    except NotANumber:
+        return x
+    intpart, fraction = unexpo(intpart, fraction, expo)
+    intpart, fraction = roundfrac(intpart, fraction, digs)
+    while intpart and intpart[0] == '0': intpart = intpart[1:]
+    if intpart == '': intpart = '0'
+    if digs > 0: return sign + intpart + '.' + fraction
+    else: return sign + intpart
+
+def sci(x, digs):
+    """Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point
+    and exactly one digit before.
+    If digs is <= 0, one digit is kept and the point is suppressed."""
+    if type(x) != type(''): x = repr(x)
+    sign, intpart, fraction, expo = extract(x)
+    if not intpart:
+        while fraction and fraction[0] == '0':
+            fraction = fraction[1:]
+            expo = expo - 1
+        if fraction:
+            intpart, fraction = fraction[0], fraction[1:]
+            expo = expo - 1
+        else:
+            intpart = '0'
+    else:
+        expo = expo + len(intpart) - 1
+        intpart, fraction = intpart[0], intpart[1:] + fraction
+    digs = max(0, digs)
+    intpart, fraction = roundfrac(intpart, fraction, digs)
+    if len(intpart) > 1:
+        intpart, fraction, expo = \
+            intpart[0], intpart[1:] + fraction[:-1], \
+            expo + len(intpart) - 1
+    s = sign + intpart
+    if digs > 0: s = s + '.' + fraction
+    e = repr(abs(expo))
+    e = '0'*(3-len(e)) + e
+    if expo < 0: e = '-' + e
+    else: e = '+' + e
+    return s + 'e' + e
+
+def test():
+    """Interactive test run."""
+    try:
+        while 1:
+            x, digs = input('Enter (x, digs): ')
+            print x, fix(x, digs), sci(x, digs)
+    except (EOFError, KeyboardInterrupt):
+        pass
diff --git a/src/main/resources/PythonLibs/fractions.py b/src/main/resources/PythonLibs/fractions.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0d86a4393684c0f96a2ddd3249b37b2b57b87e2
--- /dev/null
+++ b/src/main/resources/PythonLibs/fractions.py
@@ -0,0 +1,605 @@
+# Originally contributed by Sjoerd Mullender.
+# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>.
+
+"""Rational, infinite-precision, real numbers."""
+
+from __future__ import division
+from decimal import Decimal
+import math
+import numbers
+import operator
+import re
+
+__all__ = ['Fraction', 'gcd']
+
+Rational = numbers.Rational
+
+
+def gcd(a, b):
+    """Calculate the Greatest Common Divisor of a and b.
+
+    Unless b==0, the result will have the same sign as b (so that when
+    b is divided by it, the result comes out positive).
+    """
+    while b:
+        a, b = b, a%b
+    return a
+
+
+_RATIONAL_FORMAT = re.compile(r"""
+    \A\s*                      # optional whitespace at the start, then
+    (?P<sign>[-+]?)            # an optional sign, then
+    (?=\d|\.\d)                # lookahead for digit or .digit
+    (?P<num>\d*)               # numerator (possibly empty)
+    (?:                        # followed by
+       (?:/(?P<denom>\d+))?    # an optional denominator
+    |                          # or
+       (?:\.(?P<decimal>\d*))? # an optional fractional part
+       (?:E(?P<exp>[-+]?\d+))? # and optional exponent
+    )
+    \s*\Z                      # and optional whitespace to finish
+""", re.VERBOSE | re.IGNORECASE)
+
+
+class Fraction(Rational):
+    """This class implements rational numbers.
+
+    In the two-argument form of the constructor, Fraction(8, 6) will
+    produce a rational number equivalent to 4/3. Both arguments must
+    be Rational. The numerator defaults to 0 and the denominator
+    defaults to 1 so that Fraction(3) == 3 and Fraction() == 0.
+
+    Fractions can also be constructed from:
+
+      - numeric strings similar to those accepted by the
+        float constructor (for example, '-2.3' or '1e10')
+
+      - strings of the form '123/456'
+
+      - float and Decimal instances
+
+      - other Rational instances (including integers)
+
+    """
+
+    __slots__ = ('_numerator', '_denominator')
+
+    # We're immutable, so use __new__ not __init__
+    def __new__(cls, numerator=0, denominator=None):
+        """Constructs a Fraction.
+
+        Takes a string like '3/2' or '1.5', another Rational instance, a
+        numerator/denominator pair, or a float.
+
+        Examples
+        --------
+
+        >>> Fraction(10, -8)
+        Fraction(-5, 4)
+        >>> Fraction(Fraction(1, 7), 5)
+        Fraction(1, 35)
+        >>> Fraction(Fraction(1, 7), Fraction(2, 3))
+        Fraction(3, 14)
+        >>> Fraction('314')
+        Fraction(314, 1)
+        >>> Fraction('-35/4')
+        Fraction(-35, 4)
+        >>> Fraction('3.1415') # conversion from numeric string
+        Fraction(6283, 2000)
+        >>> Fraction('-47e-2') # string may include a decimal exponent
+        Fraction(-47, 100)
+        >>> Fraction(1.47)  # direct construction from float (exact conversion)
+        Fraction(6620291452234629, 4503599627370496)
+        >>> Fraction(2.25)
+        Fraction(9, 4)
+        >>> Fraction(Decimal('1.47'))
+        Fraction(147, 100)
+
+        """
+        self = super(Fraction, cls).__new__(cls)
+
+        if denominator is None:
+            if isinstance(numerator, Rational):
+                self._numerator = numerator.numerator
+                self._denominator = numerator.denominator
+                return self
+
+            elif isinstance(numerator, float):
+                # Exact conversion from float
+                value = Fraction.from_float(numerator)
+                self._numerator = value._numerator
+                self._denominator = value._denominator
+                return self
+
+            elif isinstance(numerator, Decimal):
+                value = Fraction.from_decimal(numerator)
+                self._numerator = value._numerator
+                self._denominator = value._denominator
+                return self
+
+            elif isinstance(numerator, basestring):
+                # Handle construction from strings.
+                m = _RATIONAL_FORMAT.match(numerator)
+                if m is None:
+                    raise ValueError('Invalid literal for Fraction: %r' %
+                                     numerator)
+                numerator = int(m.group('num') or '0')
+                denom = m.group('denom')
+                if denom:
+                    denominator = int(denom)
+                else:
+                    denominator = 1
+                    decimal = m.group('decimal')
+                    if decimal:
+                        scale = 10**len(decimal)
+                        numerator = numerator * scale + int(decimal)
+                        denominator *= scale
+                    exp = m.group('exp')
+                    if exp:
+                        exp = int(exp)
+                        if exp >= 0:
+                            numerator *= 10**exp
+                        else:
+                            denominator *= 10**-exp
+                if m.group('sign') == '-':
+                    numerator = -numerator
+
+            else:
+                raise TypeError("argument should be a string "
+                                "or a Rational instance")
+
+        elif (isinstance(numerator, Rational) and
+            isinstance(denominator, Rational)):
+            numerator, denominator = (
+                numerator.numerator * denominator.denominator,
+                denominator.numerator * numerator.denominator
+                )
+        else:
+            raise TypeError("both arguments should be "
+                            "Rational instances")
+
+        if denominator == 0:
+            raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
+        g = gcd(numerator, denominator)
+        self._numerator = numerator // g
+        self._denominator = denominator // g
+        return self
+
+    @classmethod
+    def from_float(cls, f):
+        """Converts a finite float to a rational number, exactly.
+
+        Beware that Fraction.from_float(0.3) != Fraction(3, 10).
+
+        """
+        if isinstance(f, numbers.Integral):
+            return cls(f)
+        elif not isinstance(f, float):
+            raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
+                            (cls.__name__, f, type(f).__name__))
+        if math.isnan(f) or math.isinf(f):
+            raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
+        return cls(*f.as_integer_ratio())
+
+    @classmethod
+    def from_decimal(cls, dec):
+        """Converts a finite Decimal instance to a rational number, exactly."""
+        from decimal import Decimal
+        if isinstance(dec, numbers.Integral):
+            dec = Decimal(int(dec))
+        elif not isinstance(dec, Decimal):
+            raise TypeError(
+                "%s.from_decimal() only takes Decimals, not %r (%s)" %
+                (cls.__name__, dec, type(dec).__name__))
+        if not dec.is_finite():
+            # Catches infinities and nans.
+            raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
+        sign, digits, exp = dec.as_tuple()
+        digits = int(''.join(map(str, digits)))
+        if sign:
+            digits = -digits
+        if exp >= 0:
+            return cls(digits * 10 ** exp)
+        else:
+            return cls(digits, 10 ** -exp)
+
+    def limit_denominator(self, max_denominator=1000000):
+        """Closest Fraction to self with denominator at most max_denominator.
+
+        >>> Fraction('3.141592653589793').limit_denominator(10)
+        Fraction(22, 7)
+        >>> Fraction('3.141592653589793').limit_denominator(100)
+        Fraction(311, 99)
+        >>> Fraction(4321, 8765).limit_denominator(10000)
+        Fraction(4321, 8765)
+
+        """
+        # Algorithm notes: For any real number x, define a *best upper
+        # approximation* to x to be a rational number p/q such that:
+        #
+        #   (1) p/q >= x, and
+        #   (2) if p/q > r/s >= x then s > q, for any rational r/s.
+        #
+        # Define *best lower approximation* similarly.  Then it can be
+        # proved that a rational number is a best upper or lower
+        # approximation to x if, and only if, it is a convergent or
+        # semiconvergent of the (unique shortest) continued fraction
+        # associated to x.
+        #
+        # To find a best rational approximation with denominator <= M,
+        # we find the best upper and lower approximations with
+        # denominator <= M and take whichever of these is closer to x.
+        # In the event of a tie, the bound with smaller denominator is
+        # chosen.  If both denominators are equal (which can happen
+        # only when max_denominator == 1 and self is midway between
+        # two integers) the lower bound---i.e., the floor of self, is
+        # taken.
+
+        if max_denominator < 1:
+            raise ValueError("max_denominator should be at least 1")
+        if self._denominator <= max_denominator:
+            return Fraction(self)
+
+        p0, q0, p1, q1 = 0, 1, 1, 0
+        n, d = self._numerator, self._denominator
+        while True:
+            a = n//d
+            q2 = q0+a*q1
+            if q2 > max_denominator:
+                break
+            p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
+            n, d = d, n-a*d
+
+        k = (max_denominator-q0)//q1
+        bound1 = Fraction(p0+k*p1, q0+k*q1)
+        bound2 = Fraction(p1, q1)
+        if abs(bound2 - self) <= abs(bound1-self):
+            return bound2
+        else:
+            return bound1
+
+    @property
+    def numerator(a):
+        return a._numerator
+
+    @property
+    def denominator(a):
+        return a._denominator
+
+    def __repr__(self):
+        """repr(self)"""
+        return ('Fraction(%s, %s)' % (self._numerator, self._denominator))
+
+    def __str__(self):
+        """str(self)"""
+        if self._denominator == 1:
+            return str(self._numerator)
+        else:
+            return '%s/%s' % (self._numerator, self._denominator)
+
+    def _operator_fallbacks(monomorphic_operator, fallback_operator):
+        """Generates forward and reverse operators given a purely-rational
+        operator and a function from the operator module.
+
+        Use this like:
+        __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
+
+        In general, we want to implement the arithmetic operations so
+        that mixed-mode operations either call an implementation whose
+        author knew about the types of both arguments, or convert both
+        to the nearest built in type and do the operation there. In
+        Fraction, that means that we define __add__ and __radd__ as:
+
+            def __add__(self, other):
+                # Both types have numerators/denominator attributes,
+                # so do the operation directly
+                if isinstance(other, (int, long, Fraction)):
+                    return Fraction(self.numerator * other.denominator +
+                                    other.numerator * self.denominator,
+                                    self.denominator * other.denominator)
+                # float and complex don't have those operations, but we
+                # know about those types, so special case them.
+                elif isinstance(other, float):
+                    return float(self) + other
+                elif isinstance(other, complex):
+                    return complex(self) + other
+                # Let the other type take over.
+                return NotImplemented
+
+            def __radd__(self, other):
+                # radd handles more types than add because there's
+                # nothing left to fall back to.
+                if isinstance(other, Rational):
+                    return Fraction(self.numerator * other.denominator +
+                                    other.numerator * self.denominator,
+                                    self.denominator * other.denominator)
+                elif isinstance(other, Real):
+                    return float(other) + float(self)
+                elif isinstance(other, Complex):
+                    return complex(other) + complex(self)
+                return NotImplemented
+
+
+        There are 5 different cases for a mixed-type addition on
+        Fraction. I'll refer to all of the above code that doesn't
+        refer to Fraction, float, or complex as "boilerplate". 'r'
+        will be an instance of Fraction, which is a subtype of
+        Rational (r : Fraction <: Rational), and b : B <:
+        Complex. The first three involve 'r + b':
+
+            1. If B <: Fraction, int, float, or complex, we handle
+               that specially, and all is well.
+            2. If Fraction falls back to the boilerplate code, and it
+               were to return a value from __add__, we'd miss the
+               possibility that B defines a more intelligent __radd__,
+               so the boilerplate should return NotImplemented from
+               __add__. In particular, we don't handle Rational
+               here, even though we could get an exact answer, in case
+               the other type wants to do something special.
+            3. If B <: Fraction, Python tries B.__radd__ before
+               Fraction.__add__. This is ok, because it was
+               implemented with knowledge of Fraction, so it can
+               handle those instances before delegating to Real or
+               Complex.
+
+        The next two situations describe 'b + r'. We assume that b
+        didn't know about Fraction in its implementation, and that it
+        uses similar boilerplate code:
+
+            4. If B <: Rational, then __radd_ converts both to the
+               builtin rational type (hey look, that's us) and
+               proceeds.
+            5. Otherwise, __radd__ tries to find the nearest common
+               base ABC, and fall back to its builtin type. Since this
+               class doesn't subclass a concrete type, there's no
+               implementation to fall back to, so we need to try as
+               hard as possible to return an actual value, or the user
+               will get a TypeError.
+
+        """
+        def forward(a, b):
+            if isinstance(b, (int, long, Fraction)):
+                return monomorphic_operator(a, b)
+            elif isinstance(b, float):
+                return fallback_operator(float(a), b)
+            elif isinstance(b, complex):
+                return fallback_operator(complex(a), b)
+            else:
+                return NotImplemented
+        forward.__name__ = '__' + fallback_operator.__name__ + '__'
+        forward.__doc__ = monomorphic_operator.__doc__
+
+        def reverse(b, a):
+            if isinstance(a, Rational):
+                # Includes ints.
+                return monomorphic_operator(a, b)
+            elif isinstance(a, numbers.Real):
+                return fallback_operator(float(a), float(b))
+            elif isinstance(a, numbers.Complex):
+                return fallback_operator(complex(a), complex(b))
+            else:
+                return NotImplemented
+        reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
+        reverse.__doc__ = monomorphic_operator.__doc__
+
+        return forward, reverse
+
+    def _add(a, b):
+        """a + b"""
+        return Fraction(a.numerator * b.denominator +
+                        b.numerator * a.denominator,
+                        a.denominator * b.denominator)
+
+    __add__, __radd__ = _operator_fallbacks(_add, operator.add)
+
+    def _sub(a, b):
+        """a - b"""
+        return Fraction(a.numerator * b.denominator -
+                        b.numerator * a.denominator,
+                        a.denominator * b.denominator)
+
+    __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
+
+    def _mul(a, b):
+        """a * b"""
+        return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
+
+    __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
+
+    def _div(a, b):
+        """a / b"""
+        return Fraction(a.numerator * b.denominator,
+                        a.denominator * b.numerator)
+
+    __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
+    __div__, __rdiv__ = _operator_fallbacks(_div, operator.div)
+
+    def __floordiv__(a, b):
+        """a // b"""
+        # Will be math.floor(a / b) in 3.0.
+        div = a / b
+        if isinstance(div, Rational):
+            # trunc(math.floor(div)) doesn't work if the rational is
+            # more precise than a float because the intermediate
+            # rounding may cross an integer boundary.
+            return div.numerator // div.denominator
+        else:
+            return math.floor(div)
+
+    def __rfloordiv__(b, a):
+        """a // b"""
+        # Will be math.floor(a / b) in 3.0.
+        div = a / b
+        if isinstance(div, Rational):
+            # trunc(math.floor(div)) doesn't work if the rational is
+            # more precise than a float because the intermediate
+            # rounding may cross an integer boundary.
+            return div.numerator // div.denominator
+        else:
+            return math.floor(div)
+
+    def __mod__(a, b):
+        """a % b"""
+        div = a // b
+        return a - b * div
+
+    def __rmod__(b, a):
+        """a % b"""
+        div = a // b
+        return a - b * div
+
+    def __pow__(a, b):
+        """a ** b
+
+        If b is not an integer, the result will be a float or complex
+        since roots are generally irrational. If b is an integer, the
+        result will be rational.
+
+        """
+        if isinstance(b, Rational):
+            if b.denominator == 1:
+                power = b.numerator
+                if power >= 0:
+                    return Fraction(a._numerator ** power,
+                                    a._denominator ** power)
+                else:
+                    return Fraction(a._denominator ** -power,
+                                    a._numerator ** -power)
+            else:
+                # A fractional power will generally produce an
+                # irrational number.
+                return float(a) ** float(b)
+        else:
+            return float(a) ** b
+
+    def __rpow__(b, a):
+        """a ** b"""
+        if b._denominator == 1 and b._numerator >= 0:
+            # If a is an int, keep it that way if possible.
+            return a ** b._numerator
+
+        if isinstance(a, Rational):
+            return Fraction(a.numerator, a.denominator) ** b
+
+        if b._denominator == 1:
+            return a ** b._numerator
+
+        return a ** float(b)
+
+    def __pos__(a):
+        """+a: Coerces a subclass instance to Fraction"""
+        return Fraction(a._numerator, a._denominator)
+
+    def __neg__(a):
+        """-a"""
+        return Fraction(-a._numerator, a._denominator)
+
+    def __abs__(a):
+        """abs(a)"""
+        return Fraction(abs(a._numerator), a._denominator)
+
+    def __trunc__(a):
+        """trunc(a)"""
+        if a._numerator < 0:
+            return -(-a._numerator // a._denominator)
+        else:
+            return a._numerator // a._denominator
+
+    def __hash__(self):
+        """hash(self)
+
+        Tricky because values that are exactly representable as a
+        float must have the same hash as that float.
+
+        """
+        # XXX since this method is expensive, consider caching the result
+        if self._denominator == 1:
+            # Get integers right.
+            return hash(self._numerator)
+        # Expensive check, but definitely correct.
+        if self == float(self):
+            return hash(float(self))
+        else:
+            # Use tuple's hash to avoid a high collision rate on
+            # simple fractions.
+            return hash((self._numerator, self._denominator))
+
+    def __eq__(a, b):
+        """a == b"""
+        if isinstance(b, Rational):
+            return (a._numerator == b.numerator and
+                    a._denominator == b.denominator)
+        if isinstance(b, numbers.Complex) and b.imag == 0:
+            b = b.real
+        if isinstance(b, float):
+            if math.isnan(b) or math.isinf(b):
+                # comparisons with an infinity or nan should behave in
+                # the same way for any finite a, so treat a as zero.
+                return 0.0 == b
+            else:
+                return a == a.from_float(b)
+        else:
+            # Since a doesn't know how to compare with b, let's give b
+            # a chance to compare itself with a.
+            return NotImplemented
+
+    def _richcmp(self, other, op):
+        """Helper for comparison operators, for internal use only.
+
+        Implement comparison between a Rational instance `self`, and
+        either another Rational instance or a float `other`.  If
+        `other` is not a Rational instance or a float, return
+        NotImplemented. `op` should be one of the six standard
+        comparison operators.
+
+        """
+        # convert other to a Rational instance where reasonable.
+        if isinstance(other, Rational):
+            return op(self._numerator * other.denominator,
+                      self._denominator * other.numerator)
+        # comparisons with complex should raise a TypeError, for consistency
+        # with int<->complex, float<->complex, and complex<->complex comparisons.
+        if isinstance(other, complex):
+            raise TypeError("no ordering relation is defined for complex numbers")
+        if isinstance(other, float):
+            if math.isnan(other) or math.isinf(other):
+                return op(0.0, other)
+            else:
+                return op(self, self.from_float(other))
+        else:
+            return NotImplemented
+
+    def __lt__(a, b):
+        """a < b"""
+        return a._richcmp(b, operator.lt)
+
+    def __gt__(a, b):
+        """a > b"""
+        return a._richcmp(b, operator.gt)
+
+    def __le__(a, b):
+        """a <= b"""
+        return a._richcmp(b, operator.le)
+
+    def __ge__(a, b):
+        """a >= b"""
+        return a._richcmp(b, operator.ge)
+
+    def __nonzero__(a):
+        """a != 0"""
+        return a._numerator != 0
+
+    # support for pickling, copy, and deepcopy
+
+    def __reduce__(self):
+        return (self.__class__, (str(self),))
+
+    def __copy__(self):
+        if type(self) == Fraction:
+            return self     # I'm immutable; therefore I am my own clone
+        return self.__class__(self._numerator, self._denominator)
+
+    def __deepcopy__(self, memo):
+        if type(self) == Fraction:
+            return self     # My components are also immutable
+        return self.__class__(self._numerator, self._denominator)
diff --git a/src/main/resources/PythonLibs/ftplib.py b/src/main/resources/PythonLibs/ftplib.py
new file mode 100644
index 0000000000000000000000000000000000000000..2305cf8aeb1e3e899220230ebe38b15b22a5ff4d
--- /dev/null
+++ b/src/main/resources/PythonLibs/ftplib.py
@@ -0,0 +1,1047 @@
+"""An FTP client class and some helper functions.
+
+Based on RFC 959: File Transfer Protocol (FTP), by J. Postel and J. Reynolds
+
+Example:
+
+>>> from ftplib import FTP
+>>> ftp = FTP('ftp.python.org') # connect to host, default port
+>>> ftp.login() # default, i.e.: user anonymous, passwd anonymous@
+'230 Guest login ok, access restrictions apply.'
+>>> ftp.retrlines('LIST') # list directory contents
+total 9
+drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 .
+drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 ..
+drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 bin
+drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 etc
+d-wxrwxr-x   2 ftp      wheel        1024 Sep  5 13:43 incoming
+drwxr-xr-x   2 root     wheel        1024 Nov 17  1993 lib
+drwxr-xr-x   6 1094     wheel        1024 Sep 13 19:07 pub
+drwxr-xr-x   3 root     wheel        1024 Jan  3  1994 usr
+-rw-r--r--   1 root     root          312 Aug  1  1994 welcome.msg
+'226 Transfer complete.'
+>>> ftp.quit()
+'221 Goodbye.'
+>>>
+
+A nice test that reveals some of the network dialogue would be:
+python ftplib.py -d localhost -l -p -l
+"""
+
+#
+# Changes and improvements suggested by Steve Majewski.
+# Modified by Jack to work on the mac.
+# Modified by Siebren to support docstrings and PASV.
+# Modified by Phil Schwartz to add storbinary and storlines callbacks.
+# Modified by Giampaolo Rodola' to add TLS support.
+#
+
+import os
+import sys
+
+# Import SOCKS module if it exists, else standard socket module socket
+try:
+    import SOCKS; socket = SOCKS; del SOCKS # import SOCKS as socket
+    from socket import getfqdn; socket.getfqdn = getfqdn; del getfqdn
+except ImportError:
+    import socket
+from socket import _GLOBAL_DEFAULT_TIMEOUT
+
+__all__ = ["FTP","Netrc"]
+
+# Magic number from <socket.h>
+MSG_OOB = 0x1                           # Process data out of band
+
+
+# The standard FTP server control port
+FTP_PORT = 21
+
+
+# Exception raised when an error or invalid response is received
+class Error(Exception): pass
+class error_reply(Error): pass          # unexpected [123]xx reply
+class error_temp(Error): pass           # 4xx errors
+class error_perm(Error): pass           # 5xx errors
+class error_proto(Error): pass          # response does not begin with [1-5]
+
+
+# All exceptions (hopefully) that may be raised here and that aren't
+# (always) programming errors on our side
+all_errors = (Error, IOError, EOFError)
+
+
+# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
+CRLF = '\r\n'
+
+# The class itself
+class FTP:
+
+    '''An FTP client class.
+
+    To create a connection, call the class using these arguments:
+            host, user, passwd, acct, timeout
+
+    The first four arguments are all strings, and have default value ''.
+    timeout must be numeric and defaults to None if not passed,
+    meaning that no timeout will be set on any ftp socket(s)
+    If a timeout is passed, then this is now the default timeout for all ftp
+    socket operations for this instance.
+
+    Then use self.connect() with optional host and port argument.
+
+    To download a file, use ftp.retrlines('RETR ' + filename),
+    or ftp.retrbinary() with slightly different arguments.
+    To upload a file, use ftp.storlines() or ftp.storbinary(),
+    which have an open file as argument (see their definitions
+    below for details).
+    The download/upload functions first issue appropriate TYPE
+    and PORT or PASV commands.
+'''
+
+    debugging = 0
+    host = ''
+    port = FTP_PORT
+    sock = None
+    file = None
+    welcome = None
+    passiveserver = 1
+
+    # Initialization method (called by class instantiation).
+    # Initialize host to localhost, port to standard ftp port
+    # Optional arguments are host (for connect()),
+    # and user, passwd, acct (for login())
+    def __init__(self, host='', user='', passwd='', acct='',
+                 timeout=_GLOBAL_DEFAULT_TIMEOUT):
+        self.timeout = timeout
+        if host:
+            self.connect(host)
+            if user:
+                self.login(user, passwd, acct)
+
+    def connect(self, host='', port=0, timeout=-999):
+        '''Connect to host.  Arguments are:
+         - host: hostname to connect to (string, default previous host)
+         - port: port to connect to (integer, default previous port)
+        '''
+        if host != '':
+            self.host = host
+        if port > 0:
+            self.port = port
+        if timeout != -999:
+            self.timeout = timeout
+        self.sock = socket.create_connection((self.host, self.port), self.timeout)
+        self.af = self.sock.family
+        self.file = self.sock.makefile('rb')
+        self.welcome = self.getresp()
+        return self.welcome
+
+    def getwelcome(self):
+        '''Get the welcome message from the server.
+        (this is read and squirreled away by connect())'''
+        if self.debugging:
+            print '*welcome*', self.sanitize(self.welcome)
+        return self.welcome
+
+    def set_debuglevel(self, level):
+        '''Set the debugging level.
+        The required argument level means:
+        0: no debugging output (default)
+        1: print commands and responses but not body text etc.
+        2: also print raw lines read and sent before stripping CR/LF'''
+        self.debugging = level
+    debug = set_debuglevel
+
+    def set_pasv(self, val):
+        '''Use passive or active mode for data transfers.
+        With a false argument, use the normal PORT mode,
+        With a true argument, use the PASV command.'''
+        self.passiveserver = val
+
+    # Internal: "sanitize" a string for printing
+    def sanitize(self, s):
+        if s[:5] == 'pass ' or s[:5] == 'PASS ':
+            i = len(s)
+            while i > 5 and s[i-1] in '\r\n':
+                i = i-1
+            s = s[:5] + '*'*(i-5) + s[i:]
+        return repr(s)
+
+    # Internal: send one line to the server, appending CRLF
+    def putline(self, line):
+        line = line + CRLF
+        if self.debugging > 1: print '*put*', self.sanitize(line)
+        self.sock.sendall(line)
+
+    # Internal: send one command to the server (through putline())
+    def putcmd(self, line):
+        if self.debugging: print '*cmd*', self.sanitize(line)
+        self.putline(line)
+
+    # Internal: return one line from the server, stripping CRLF.
+    # Raise EOFError if the connection is closed
+    def getline(self):
+        line = self.file.readline()
+        if self.debugging > 1:
+            print '*get*', self.sanitize(line)
+        if not line: raise EOFError
+        if line[-2:] == CRLF: line = line[:-2]
+        elif line[-1:] in CRLF: line = line[:-1]
+        return line
+
+    # Internal: get a response from the server, which may possibly
+    # consist of multiple lines.  Return a single string with no
+    # trailing CRLF.  If the response consists of multiple lines,
+    # these are separated by '\n' characters in the string
+    def getmultiline(self):
+        line = self.getline()
+        if line[3:4] == '-':
+            code = line[:3]
+            while 1:
+                nextline = self.getline()
+                line = line + ('\n' + nextline)
+                if nextline[:3] == code and \
+                        nextline[3:4] != '-':
+                    break
+        return line
+
+    # Internal: get a response from the server.
+    # Raise various errors if the response indicates an error
+    def getresp(self):
+        resp = self.getmultiline()
+        if self.debugging: print '*resp*', self.sanitize(resp)
+        self.lastresp = resp[:3]
+        c = resp[:1]
+        if c in ('1', '2', '3'):
+            return resp
+        if c == '4':
+            raise error_temp, resp
+        if c == '5':
+            raise error_perm, resp
+        raise error_proto, resp
+
+    def voidresp(self):
+        """Expect a response beginning with '2'."""
+        resp = self.getresp()
+        if resp[:1] != '2':
+            raise error_reply, resp
+        return resp
+
+    def abort(self):
+        '''Abort a file transfer.  Uses out-of-band data.
+        This does not follow the procedure from the RFC to send Telnet
+        IP and Synch; that doesn't seem to work with the servers I've
+        tried.  Instead, just send the ABOR command as OOB data.'''
+        line = 'ABOR' + CRLF
+        if self.debugging > 1: print '*put urgent*', self.sanitize(line)
+        self.sock.sendall(line, MSG_OOB)
+        resp = self.getmultiline()
+        if resp[:3] not in ('426', '225', '226'):
+            raise error_proto, resp
+
+    def sendcmd(self, cmd):
+        '''Send a command and return the response.'''
+        self.putcmd(cmd)
+        return self.getresp()
+
+    def voidcmd(self, cmd):
+        """Send a command and expect a response beginning with '2'."""
+        self.putcmd(cmd)
+        return self.voidresp()
+
+    def sendport(self, host, port):
+        '''Send a PORT command with the current host and the given
+        port number.
+        '''
+        hbytes = host.split('.')
+        pbytes = [repr(port//256), repr(port%256)]
+        bytes = hbytes + pbytes
+        cmd = 'PORT ' + ','.join(bytes)
+        return self.voidcmd(cmd)
+
+    def sendeprt(self, host, port):
+        '''Send a EPRT command with the current host and the given port number.'''
+        af = 0
+        if self.af == socket.AF_INET:
+            af = 1
+        if self.af == socket.AF_INET6:
+            af = 2
+        if af == 0:
+            raise error_proto, 'unsupported address family'
+        fields = ['', repr(af), host, repr(port), '']
+        cmd = 'EPRT ' + '|'.join(fields)
+        return self.voidcmd(cmd)
+
+    def makeport(self):
+        '''Create a new socket and send a PORT command for it.'''
+        err = None
+        sock = None
+        for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
+            af, socktype, proto, canonname, sa = res
+            try:
+                sock = socket.socket(af, socktype, proto)
+                sock.bind(sa)
+            except socket.error, err:
+                if sock:
+                    sock.close()
+                sock = None
+                continue
+            break
+        if sock is None:
+            if err is not None:
+                raise err
+            else:
+                raise socket.error("getaddrinfo returns an empty list")
+        sock.listen(1)
+        port = sock.getsockname()[1] # Get proper port
+        host = self.sock.getsockname()[0] # Get proper host
+        if self.af == socket.AF_INET:
+            resp = self.sendport(host, port)
+        else:
+            resp = self.sendeprt(host, port)
+        if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
+            sock.settimeout(self.timeout)
+        return sock
+
+    def makepasv(self):
+        if self.af == socket.AF_INET:
+            host, port = parse227(self.sendcmd('PASV'))
+        else:
+            host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
+        return host, port
+
+    def ntransfercmd(self, cmd, rest=None):
+        """Initiate a transfer over the data connection.
+
+        If the transfer is active, send a port command and the
+        transfer command, and accept the connection.  If the server is
+        passive, send a pasv command, connect to it, and start the
+        transfer command.  Either way, return the socket for the
+        connection and the expected size of the transfer.  The
+        expected size may be None if it could not be determined.
+
+        Optional `rest' argument can be a string that is sent as the
+        argument to a REST command.  This is essentially a server
+        marker used to tell the server to skip over any data up to the
+        given marker.
+        """
+        size = None
+        if self.passiveserver:
+            host, port = self.makepasv()
+            conn = socket.create_connection((host, port), self.timeout)
+            try:
+                if rest is not None:
+                    self.sendcmd("REST %s" % rest)
+                resp = self.sendcmd(cmd)
+                # Some servers apparently send a 200 reply to
+                # a LIST or STOR command, before the 150 reply
+                # (and way before the 226 reply). This seems to
+                # be in violation of the protocol (which only allows
+                # 1xx or error messages for LIST), so we just discard
+                # this response.
+                if resp[0] == '2':
+                    resp = self.getresp()
+                if resp[0] != '1':
+                    raise error_reply, resp
+            except:
+                conn.close()
+                raise
+        else:
+            sock = self.makeport()
+            try:
+                if rest is not None:
+                    self.sendcmd("REST %s" % rest)
+                resp = self.sendcmd(cmd)
+                # See above.
+                if resp[0] == '2':
+                    resp = self.getresp()
+                if resp[0] != '1':
+                    raise error_reply, resp
+                conn, sockaddr = sock.accept()
+                if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
+                    conn.settimeout(self.timeout)
+            finally:
+                sock.close()
+        if resp[:3] == '150':
+            # this is conditional in case we received a 125
+            size = parse150(resp)
+        return conn, size
+
+    def transfercmd(self, cmd, rest=None):
+        """Like ntransfercmd() but returns only the socket."""
+        return self.ntransfercmd(cmd, rest)[0]
+
+    def login(self, user = '', passwd = '', acct = ''):
+        '''Login, default anonymous.'''
+        if not user: user = 'anonymous'
+        if not passwd: passwd = ''
+        if not acct: acct = ''
+        if user == 'anonymous' and passwd in ('', '-'):
+            # If there is no anonymous ftp password specified
+            # then we'll just use anonymous@
+            # We don't send any other thing because:
+            # - We want to remain anonymous
+            # - We want to stop SPAM
+            # - We don't want to let ftp sites to discriminate by the user,
+            #   host or country.
+            passwd = passwd + 'anonymous@'
+        resp = self.sendcmd('USER ' + user)
+        if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd)
+        if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct)
+        if resp[0] != '2':
+            raise error_reply, resp
+        return resp
+
+    def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
+        """Retrieve data in binary mode.  A new port is created for you.
+
+        Args:
+          cmd: A RETR command.
+          callback: A single parameter callable to be called on each
+                    block of data read.
+          blocksize: The maximum number of bytes to read from the
+                     socket at one time.  [default: 8192]
+          rest: Passed to transfercmd().  [default: None]
+
+        Returns:
+          The response code.
+        """
+        self.voidcmd('TYPE I')
+        conn = self.transfercmd(cmd, rest)
+        while 1:
+            data = conn.recv(blocksize)
+            if not data:
+                break
+            callback(data)
+        conn.close()
+        return self.voidresp()
+
+    def retrlines(self, cmd, callback = None):
+        """Retrieve data in line mode.  A new port is created for you.
+
+        Args:
+          cmd: A RETR, LIST, NLST, or MLSD command.
+          callback: An optional single parameter callable that is called
+                    for each line with the trailing CRLF stripped.
+                    [default: print_line()]
+
+        Returns:
+          The response code.
+        """
+        if callback is None: callback = print_line
+        resp = self.sendcmd('TYPE A')
+        conn = self.transfercmd(cmd)
+        fp = conn.makefile('rb')
+        while 1:
+            line = fp.readline()
+            if self.debugging > 2: print '*retr*', repr(line)
+            if not line:
+                break
+            if line[-2:] == CRLF:
+                line = line[:-2]
+            elif line[-1:] == '\n':
+                line = line[:-1]
+            callback(line)
+        fp.close()
+        conn.close()
+        return self.voidresp()
+
+    def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
+        """Store a file in binary mode.  A new port is created for you.
+
+        Args:
+          cmd: A STOR command.
+          fp: A file-like object with a read(num_bytes) method.
+          blocksize: The maximum data size to read from fp and send over
+                     the connection at once.  [default: 8192]
+          callback: An optional single parameter callable that is called on
+                    on each block of data after it is sent.  [default: None]
+          rest: Passed to transfercmd().  [default: None]
+
+        Returns:
+          The response code.
+        """
+        self.voidcmd('TYPE I')
+        conn = self.transfercmd(cmd, rest)
+        while 1:
+            buf = fp.read(blocksize)
+            if not buf: break
+            conn.sendall(buf)
+            if callback: callback(buf)
+        conn.close()
+        return self.voidresp()
+
+    def storlines(self, cmd, fp, callback=None):
+        """Store a file in line mode.  A new port is created for you.
+
+        Args:
+          cmd: A STOR command.
+          fp: A file-like object with a readline() method.
+          callback: An optional single parameter callable that is called on
+                    on each line after it is sent.  [default: None]
+
+        Returns:
+          The response code.
+        """
+        self.voidcmd('TYPE A')
+        conn = self.transfercmd(cmd)
+        while 1:
+            buf = fp.readline()
+            if not buf: break
+            if buf[-2:] != CRLF:
+                if buf[-1] in CRLF: buf = buf[:-1]
+                buf = buf + CRLF
+            conn.sendall(buf)
+            if callback: callback(buf)
+        conn.close()
+        return self.voidresp()
+
+    def acct(self, password):
+        '''Send new account name.'''
+        cmd = 'ACCT ' + password
+        return self.voidcmd(cmd)
+
+    def nlst(self, *args):
+        '''Return a list of files in a given directory (default the current).'''
+        cmd = 'NLST'
+        for arg in args:
+            cmd = cmd + (' ' + arg)
+        files = []
+        self.retrlines(cmd, files.append)
+        return files
+
+    def dir(self, *args):
+        '''List a directory in long form.
+        By default list current directory to stdout.
+        Optional last argument is callback function; all
+        non-empty arguments before it are concatenated to the
+        LIST command.  (This *should* only be used for a pathname.)'''
+        cmd = 'LIST'
+        func = None
+        if args[-1:] and type(args[-1]) != type(''):
+            args, func = args[:-1], args[-1]
+        for arg in args:
+            if arg:
+                cmd = cmd + (' ' + arg)
+        self.retrlines(cmd, func)
+
+    def rename(self, fromname, toname):
+        '''Rename a file.'''
+        resp = self.sendcmd('RNFR ' + fromname)
+        if resp[0] != '3':
+            raise error_reply, resp
+        return self.voidcmd('RNTO ' + toname)
+
+    def delete(self, filename):
+        '''Delete a file.'''
+        resp = self.sendcmd('DELE ' + filename)
+        if resp[:3] in ('250', '200'):
+            return resp
+        else:
+            raise error_reply, resp
+
+    def cwd(self, dirname):
+        '''Change to a directory.'''
+        if dirname == '..':
+            try:
+                return self.voidcmd('CDUP')
+            except error_perm, msg:
+                if msg.args[0][:3] != '500':
+                    raise
+        elif dirname == '':
+            dirname = '.'  # does nothing, but could return error
+        cmd = 'CWD ' + dirname
+        return self.voidcmd(cmd)
+
+    def size(self, filename):
+        '''Retrieve the size of a file.'''
+        # The SIZE command is defined in RFC-3659
+        resp = self.sendcmd('SIZE ' + filename)
+        if resp[:3] == '213':
+            s = resp[3:].strip()
+            try:
+                return int(s)
+            except (OverflowError, ValueError):
+                return long(s)
+
+    def mkd(self, dirname):
+        '''Make a directory, return its full pathname.'''
+        resp = self.sendcmd('MKD ' + dirname)
+        return parse257(resp)
+
+    def rmd(self, dirname):
+        '''Remove a directory.'''
+        return self.voidcmd('RMD ' + dirname)
+
+    def pwd(self):
+        '''Return current working directory.'''
+        resp = self.sendcmd('PWD')
+        return parse257(resp)
+
+    def quit(self):
+        '''Quit, and close the connection.'''
+        resp = self.voidcmd('QUIT')
+        self.close()
+        return resp
+
+    def close(self):
+        '''Close the connection without assuming anything about it.'''
+        if self.file is not None:
+            self.file.close()
+        if self.sock is not None:
+            self.sock.close()
+        self.file = self.sock = None
+
+try:
+    import ssl
+    ssl.PROTOCOL_TLSv1
+except (ImportError, AttributeError):
+    pass
+else:
+    class FTP_TLS(FTP):
+        '''A FTP subclass which adds TLS support to FTP as described
+        in RFC-4217.
+
+        Connect as usual to port 21 implicitly securing the FTP control
+        connection before authenticating.
+
+        Securing the data connection requires user to explicitly ask
+        for it by calling prot_p() method.
+
+        Usage example:
+        >>> from ftplib import FTP_TLS
+        >>> ftps = FTP_TLS('ftp.python.org')
+        >>> ftps.login()  # login anonymously previously securing control channel
+        '230 Guest login ok, access restrictions apply.'
+        >>> ftps.prot_p()  # switch to secure data connection
+        '200 Protection level set to P'
+        >>> ftps.retrlines('LIST')  # list directory content securely
+        total 9
+        drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 .
+        drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 ..
+        drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 bin
+        drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 etc
+        d-wxrwxr-x   2 ftp      wheel        1024 Sep  5 13:43 incoming
+        drwxr-xr-x   2 root     wheel        1024 Nov 17  1993 lib
+        drwxr-xr-x   6 1094     wheel        1024 Sep 13 19:07 pub
+        drwxr-xr-x   3 root     wheel        1024 Jan  3  1994 usr
+        -rw-r--r--   1 root     root          312 Aug  1  1994 welcome.msg
+        '226 Transfer complete.'
+        >>> ftps.quit()
+        '221 Goodbye.'
+        >>>
+        '''
+        ssl_version = ssl.PROTOCOL_TLSv1
+
+        def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
+                     certfile=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
+            self.keyfile = keyfile
+            self.certfile = certfile
+            self._prot_p = False
+            FTP.__init__(self, host, user, passwd, acct, timeout)
+
+        def login(self, user='', passwd='', acct='', secure=True):
+            if secure and not isinstance(self.sock, ssl.SSLSocket):
+                self.auth()
+            return FTP.login(self, user, passwd, acct)
+
+        def auth(self):
+            '''Set up secure control connection by using TLS/SSL.'''
+            if isinstance(self.sock, ssl.SSLSocket):
+                raise ValueError("Already using TLS")
+            if self.ssl_version == ssl.PROTOCOL_TLSv1:
+                resp = self.voidcmd('AUTH TLS')
+            else:
+                resp = self.voidcmd('AUTH SSL')
+            self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile,
+                                        ssl_version=self.ssl_version)
+            self.file = self.sock.makefile(mode='rb')
+            return resp
+
+        def prot_p(self):
+            '''Set up secure data connection.'''
+            # PROT defines whether or not the data channel is to be protected.
+            # Though RFC-2228 defines four possible protection levels,
+            # RFC-4217 only recommends two, Clear and Private.
+            # Clear (PROT C) means that no security is to be used on the
+            # data-channel, Private (PROT P) means that the data-channel
+            # should be protected by TLS.
+            # PBSZ command MUST still be issued, but must have a parameter of
+            # '0' to indicate that no buffering is taking place and the data
+            # connection should not be encapsulated.
+            self.voidcmd('PBSZ 0')
+            resp = self.voidcmd('PROT P')
+            self._prot_p = True
+            return resp
+
+        def prot_c(self):
+            '''Set up clear text data connection.'''
+            resp = self.voidcmd('PROT C')
+            self._prot_p = False
+            return resp
+
+        # --- Overridden FTP methods
+
+        def ntransfercmd(self, cmd, rest=None):
+            conn, size = FTP.ntransfercmd(self, cmd, rest)
+            if self._prot_p:
+                conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
+                                       ssl_version=self.ssl_version)
+            return conn, size
+
+        def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
+            self.voidcmd('TYPE I')
+            conn = self.transfercmd(cmd, rest)
+            try:
+                while 1:
+                    data = conn.recv(blocksize)
+                    if not data:
+                        break
+                    callback(data)
+                # shutdown ssl layer
+                if isinstance(conn, ssl.SSLSocket):
+                    conn.unwrap()
+            finally:
+                conn.close()
+            return self.voidresp()
+
+        def retrlines(self, cmd, callback = None):
+            if callback is None: callback = print_line
+            resp = self.sendcmd('TYPE A')
+            conn = self.transfercmd(cmd)
+            fp = conn.makefile('rb')
+            try:
+                while 1:
+                    line = fp.readline()
+                    if self.debugging > 2: print '*retr*', repr(line)
+                    if not line:
+                        break
+                    if line[-2:] == CRLF:
+                        line = line[:-2]
+                    elif line[-1:] == '\n':
+                        line = line[:-1]
+                    callback(line)
+                # shutdown ssl layer
+                if isinstance(conn, ssl.SSLSocket):
+                    conn.unwrap()
+            finally:
+                fp.close()
+                conn.close()
+            return self.voidresp()
+
+        def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
+            self.voidcmd('TYPE I')
+            conn = self.transfercmd(cmd, rest)
+            try:
+                while 1:
+                    buf = fp.read(blocksize)
+                    if not buf: break
+                    conn.sendall(buf)
+                    if callback: callback(buf)
+                # shutdown ssl layer
+                if isinstance(conn, ssl.SSLSocket):
+                    conn.unwrap()
+            finally:
+                conn.close()
+            return self.voidresp()
+
+        def storlines(self, cmd, fp, callback=None):
+            self.voidcmd('TYPE A')
+            conn = self.transfercmd(cmd)
+            try:
+                while 1:
+                    buf = fp.readline()
+                    if not buf: break
+                    if buf[-2:] != CRLF:
+                        if buf[-1] in CRLF: buf = buf[:-1]
+                        buf = buf + CRLF
+                    conn.sendall(buf)
+                    if callback: callback(buf)
+                # shutdown ssl layer
+                if isinstance(conn, ssl.SSLSocket):
+                    conn.unwrap()
+            finally:
+                conn.close()
+            return self.voidresp()
+
+    __all__.append('FTP_TLS')
+    all_errors = (Error, IOError, EOFError, ssl.SSLError)
+
+
+_150_re = None
+
+def parse150(resp):
+    '''Parse the '150' response for a RETR request.
+    Returns the expected transfer size or None; size is not guaranteed to
+    be present in the 150 message.
+    '''
+    if resp[:3] != '150':
+        raise error_reply, resp
+    global _150_re
+    if _150_re is None:
+        import re
+        _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE)
+    m = _150_re.match(resp)
+    if not m:
+        return None
+    s = m.group(1)
+    try:
+        return int(s)
+    except (OverflowError, ValueError):
+        return long(s)
+
+
+_227_re = None
+
+def parse227(resp):
+    '''Parse the '227' response for a PASV request.
+    Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
+    Return ('host.addr.as.numbers', port#) tuple.'''
+
+    if resp[:3] != '227':
+        raise error_reply, resp
+    global _227_re
+    if _227_re is None:
+        import re
+        _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)')
+    m = _227_re.search(resp)
+    if not m:
+        raise error_proto, resp
+    numbers = m.groups()
+    host = '.'.join(numbers[:4])
+    port = (int(numbers[4]) << 8) + int(numbers[5])
+    return host, port
+
+
+def parse229(resp, peer):
+    '''Parse the '229' response for a EPSV request.
+    Raises error_proto if it does not contain '(|||port|)'
+    Return ('host.addr.as.numbers', port#) tuple.'''
+
+    if resp[:3] != '229':
+        raise error_reply, resp
+    left = resp.find('(')
+    if left < 0: raise error_proto, resp
+    right = resp.find(')', left + 1)
+    if right < 0:
+        raise error_proto, resp # should contain '(|||port|)'
+    if resp[left + 1] != resp[right - 1]:
+        raise error_proto, resp
+    parts = resp[left + 1:right].split(resp[left+1])
+    if len(parts) != 5:
+        raise error_proto, resp
+    host = peer[0]
+    port = int(parts[3])
+    return host, port
+
+
+def parse257(resp):
+    '''Parse the '257' response for a MKD or PWD request.
+    This is a response to a MKD or PWD request: a directory name.
+    Returns the directoryname in the 257 reply.'''
+
+    if resp[:3] != '257':
+        raise error_reply, resp
+    if resp[3:5] != ' "':
+        return '' # Not compliant to RFC 959, but UNIX ftpd does this
+    dirname = ''
+    i = 5
+    n = len(resp)
+    while i < n:
+        c = resp[i]
+        i = i+1
+        if c == '"':
+            if i >= n or resp[i] != '"':
+                break
+            i = i+1
+        dirname = dirname + c
+    return dirname
+
+
+def print_line(line):
+    '''Default retrlines callback to print a line.'''
+    print line
+
+
+def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
+    '''Copy file from one FTP-instance to another.'''
+    if not targetname: targetname = sourcename
+    type = 'TYPE ' + type
+    source.voidcmd(type)
+    target.voidcmd(type)
+    sourcehost, sourceport = parse227(source.sendcmd('PASV'))
+    target.sendport(sourcehost, sourceport)
+    # RFC 959: the user must "listen" [...] BEFORE sending the
+    # transfer request.
+    # So: STOR before RETR, because here the target is a "user".
+    treply = target.sendcmd('STOR ' + targetname)
+    if treply[:3] not in ('125', '150'): raise error_proto  # RFC 959
+    sreply = source.sendcmd('RETR ' + sourcename)
+    if sreply[:3] not in ('125', '150'): raise error_proto  # RFC 959
+    source.voidresp()
+    target.voidresp()
+
+
+class Netrc:
+    """Class to parse & provide access to 'netrc' format files.
+
+    See the netrc(4) man page for information on the file format.
+
+    WARNING: This class is obsolete -- use module netrc instead.
+
+    """
+    __defuser = None
+    __defpasswd = None
+    __defacct = None
+
+    def __init__(self, filename=None):
+        if filename is None:
+            if "HOME" in os.environ:
+                filename = os.path.join(os.environ["HOME"],
+                                        ".netrc")
+            else:
+                raise IOError, \
+                      "specify file to load or set $HOME"
+        self.__hosts = {}
+        self.__macros = {}
+        fp = open(filename, "r")
+        in_macro = 0
+        while 1:
+            line = fp.readline()
+            if not line: break
+            if in_macro and line.strip():
+                macro_lines.append(line)
+                continue
+            elif in_macro:
+                self.__macros[macro_name] = tuple(macro_lines)
+                in_macro = 0
+            words = line.split()
+            host = user = passwd = acct = None
+            default = 0
+            i = 0
+            while i < len(words):
+                w1 = words[i]
+                if i+1 < len(words):
+                    w2 = words[i + 1]
+                else:
+                    w2 = None
+                if w1 == 'default':
+                    default = 1
+                elif w1 == 'machine' and w2:
+                    host = w2.lower()
+                    i = i + 1
+                elif w1 == 'login' and w2:
+                    user = w2
+                    i = i + 1
+                elif w1 == 'password' and w2:
+                    passwd = w2
+                    i = i + 1
+                elif w1 == 'account' and w2:
+                    acct = w2
+                    i = i + 1
+                elif w1 == 'macdef' and w2:
+                    macro_name = w2
+                    macro_lines = []
+                    in_macro = 1
+                    break
+                i = i + 1
+            if default:
+                self.__defuser = user or self.__defuser
+                self.__defpasswd = passwd or self.__defpasswd
+                self.__defacct = acct or self.__defacct
+            if host:
+                if host in self.__hosts:
+                    ouser, opasswd, oacct = \
+                           self.__hosts[host]
+                    user = user or ouser
+                    passwd = passwd or opasswd
+                    acct = acct or oacct
+                self.__hosts[host] = user, passwd, acct
+        fp.close()
+
+    def get_hosts(self):
+        """Return a list of hosts mentioned in the .netrc file."""
+        return self.__hosts.keys()
+
+    def get_account(self, host):
+        """Returns login information for the named host.
+
+        The return value is a triple containing userid,
+        password, and the accounting field.
+
+        """
+        host = host.lower()
+        user = passwd = acct = None
+        if host in self.__hosts:
+            user, passwd, acct = self.__hosts[host]
+        user = user or self.__defuser
+        passwd = passwd or self.__defpasswd
+        acct = acct or self.__defacct
+        return user, passwd, acct
+
+    def get_macros(self):
+        """Return a list of all defined macro names."""
+        return self.__macros.keys()
+
+    def get_macro(self, macro):
+        """Return a sequence of lines which define a named macro."""
+        return self.__macros[macro]
+
+
+
+def test():
+    '''Test program.
+    Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
+
+    -d dir
+    -l list
+    -p password
+    '''
+
+    if len(sys.argv) < 2:
+        print test.__doc__
+        sys.exit(0)
+
+    debugging = 0
+    rcfile = None
+    while sys.argv[1] == '-d':
+        debugging = debugging+1
+        del sys.argv[1]
+    if sys.argv[1][:2] == '-r':
+        # get name of alternate ~/.netrc file:
+        rcfile = sys.argv[1][2:]
+        del sys.argv[1]
+    host = sys.argv[1]
+    ftp = FTP(host)
+    ftp.set_debuglevel(debugging)
+    userid = passwd = acct = ''
+    try:
+        netrc = Netrc(rcfile)
+    except IOError:
+        if rcfile is not None:
+            sys.stderr.write("Could not open account file"
+                             " -- using anonymous login.")
+    else:
+        try:
+            userid, passwd, acct = netrc.get_account(host)
+        except KeyError:
+            # no account for host
+            sys.stderr.write(
+                    "No account -- using anonymous login.")
+    ftp.login(userid, passwd, acct)
+    for file in sys.argv[2:]:
+        if file[:2] == '-l':
+            ftp.dir(file[2:])
+        elif file[:2] == '-d':
+            cmd = 'CWD'
+            if file[2:]: cmd = cmd + ' ' + file[2:]
+            resp = ftp.sendcmd(cmd)
+        elif file == '-p':
+            ftp.set_pasv(not ftp.passiveserver)
+        else:
+            ftp.retrbinary('RETR ' + file, \
+                           sys.stdout.write, 1024)
+    ftp.quit()
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/functools.py b/src/main/resources/PythonLibs/functools.py
new file mode 100644
index 0000000000000000000000000000000000000000..53680b894660774d5c460c0198221d9444d23923
--- /dev/null
+++ b/src/main/resources/PythonLibs/functools.py
@@ -0,0 +1,100 @@
+"""functools.py - Tools for working with functions and callable objects
+"""
+# Python module wrapper for _functools C module
+# to allow utilities written in Python to be added
+# to the functools module.
+# Written by Nick Coghlan <ncoghlan at gmail.com>
+#   Copyright (C) 2006 Python Software Foundation.
+# See C source code for _functools credits/copyright
+
+from _functools import partial, reduce
+
+# update_wrapper() and wraps() are tools to help write
+# wrapper functions that can handle naive introspection
+
+WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
+WRAPPER_UPDATES = ('__dict__',)
+def update_wrapper(wrapper,
+                   wrapped,
+                   assigned = WRAPPER_ASSIGNMENTS,
+                   updated = WRAPPER_UPDATES):
+    """Update a wrapper function to look like the wrapped function
+
+       wrapper is the function to be updated
+       wrapped is the original function
+       assigned is a tuple naming the attributes assigned directly
+       from the wrapped function to the wrapper function (defaults to
+       functools.WRAPPER_ASSIGNMENTS)
+       updated is a tuple naming the attributes of the wrapper that
+       are updated with the corresponding attribute from the wrapped
+       function (defaults to functools.WRAPPER_UPDATES)
+    """
+    for attr in assigned:
+        setattr(wrapper, attr, getattr(wrapped, attr))
+    for attr in updated:
+        getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
+    # Return the wrapper so this can be used as a decorator via partial()
+    return wrapper
+
+def wraps(wrapped,
+          assigned = WRAPPER_ASSIGNMENTS,
+          updated = WRAPPER_UPDATES):
+    """Decorator factory to apply update_wrapper() to a wrapper function
+
+       Returns a decorator that invokes update_wrapper() with the decorated
+       function as the wrapper argument and the arguments to wraps() as the
+       remaining arguments. Default arguments are as for update_wrapper().
+       This is a convenience function to simplify applying partial() to
+       update_wrapper().
+    """
+    return partial(update_wrapper, wrapped=wrapped,
+                   assigned=assigned, updated=updated)
+
+def total_ordering(cls):
+    """Class decorator that fills in missing ordering methods"""
+    convert = {
+        '__lt__': [('__gt__', lambda self, other: not (self < other or self == other)),
+                   ('__le__', lambda self, other: self < other or self == other),
+                   ('__ge__', lambda self, other: not self < other)],
+        '__le__': [('__ge__', lambda self, other: not self <= other or self == other),
+                   ('__lt__', lambda self, other: self <= other and not self == other),
+                   ('__gt__', lambda self, other: not self <= other)],
+        '__gt__': [('__lt__', lambda self, other: not (self > other or self == other)),
+                   ('__ge__', lambda self, other: self > other or self == other),
+                   ('__le__', lambda self, other: not self > other)],
+        '__ge__': [('__le__', lambda self, other: (not self >= other) or self == other),
+                   ('__gt__', lambda self, other: self >= other and not self == other),
+                   ('__lt__', lambda self, other: not self >= other)]
+    }
+    roots = set(dir(cls)) & set(convert)
+    if not roots:
+        raise ValueError('must define at least one ordering operation: < > <= >=')
+    root = max(roots)       # prefer __lt__ to __le__ to __gt__ to __ge__
+    for opname, opfunc in convert[root]:
+        if opname not in roots:
+            opfunc.__name__ = opname
+            opfunc.__doc__ = getattr(int, opname).__doc__
+            setattr(cls, opname, opfunc)
+    return cls
+
+def cmp_to_key(mycmp):
+    """Convert a cmp= function into a key= function"""
+    class K(object):
+        __slots__ = ['obj']
+        def __init__(self, obj, *args):
+            self.obj = obj
+        def __lt__(self, other):
+            return mycmp(self.obj, other.obj) < 0
+        def __gt__(self, other):
+            return mycmp(self.obj, other.obj) > 0
+        def __eq__(self, other):
+            return mycmp(self.obj, other.obj) == 0
+        def __le__(self, other):
+            return mycmp(self.obj, other.obj) <= 0
+        def __ge__(self, other):
+            return mycmp(self.obj, other.obj) >= 0
+        def __ne__(self, other):
+            return mycmp(self.obj, other.obj) != 0
+        def __hash__(self):
+            raise TypeError('hash not implemented')
+    return K
diff --git a/src/main/resources/PythonLibs/future_builtins.py b/src/main/resources/PythonLibs/future_builtins.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a90591f962ce6ee19c69c17b30ed077fb2fd48b
--- /dev/null
+++ b/src/main/resources/PythonLibs/future_builtins.py
@@ -0,0 +1,33 @@
+"""This module provides functions that will be builtins in Python 3.0,
+but that conflict with builtins that already exist in Python 2.x.
+
+Functions:
+
+hex(arg) -- Returns the hexadecimal representation of an integer
+oct(arg) -- Returns the octal representation of an integer
+ascii(arg) -- Same as repr(arg)
+map, filter, zip -- Same as itertools.imap, ifilter, izip
+
+The typical usage of this module is to replace existing builtins in a
+module's namespace:
+
+from future_builtins import hex, oct
+"""
+
+__all__ = ['hex', 'oct', 'ascii', 'map', 'filter', 'zip']
+
+from itertools import imap as map, ifilter as filter, izip as zip
+
+ascii = repr
+_builtin_hex = hex
+_builtin_oct = oct
+
+def hex(arg):
+    return _builtin_hex(arg).rstrip('L')
+
+def oct(arg):
+    result = _builtin_oct(arg).rstrip('L')
+    if result == '0':
+        return '0o0'
+    i = result.index('0') + 1
+    return result[:i] + 'o' + result[i:]
diff --git a/src/main/resources/PythonLibs/genericpath.py b/src/main/resources/PythonLibs/genericpath.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0bf6013e93763ab87895a561117f25cf641af72
--- /dev/null
+++ b/src/main/resources/PythonLibs/genericpath.py
@@ -0,0 +1,105 @@
+"""
+Path operations common to more than one OS
+Do not use directly.  The OS specific modules import the appropriate
+functions from this module themselves.
+"""
+import os
+import stat
+
+__all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime',
+           'getsize', 'isdir', 'isfile']
+
+
+# Does a path exist?
+# This is false for dangling symbolic links on systems that support them.
+def exists(path):
+    """Test whether a path exists.  Returns False for broken symbolic links"""
+    try:
+        os.stat(path)
+    except os.error:
+        return False
+    return True
+
+
+# This follows symbolic links, so both islink() and isdir() can be true
+# for the same path ono systems that support symlinks
+def isfile(path):
+    """Test whether a path is a regular file"""
+    try:
+        st = os.stat(path)
+    except os.error:
+        return False
+    return stat.S_ISREG(st.st_mode)
+
+
+# Is a path a directory?
+# This follows symbolic links, so both islink() and isdir()
+# can be true for the same path on systems that support symlinks
+def isdir(s):
+    """Return true if the pathname refers to an existing directory."""
+    try:
+        st = os.stat(s)
+    except os.error:
+        return False
+    return stat.S_ISDIR(st.st_mode)
+
+
+def getsize(filename):
+    """Return the size of a file, reported by os.stat()."""
+    return os.stat(filename).st_size
+
+
+def getmtime(filename):
+    """Return the last modification time of a file, reported by os.stat()."""
+    return os.stat(filename).st_mtime
+
+
+def getatime(filename):
+    """Return the last access time of a file, reported by os.stat()."""
+    return os.stat(filename).st_atime
+
+
+def getctime(filename):
+    """Return the metadata change time of a file, reported by os.stat()."""
+    return os.stat(filename).st_ctime
+
+
+# Return the longest prefix of all list elements.
+def commonprefix(m):
+    "Given a list of pathnames, returns the longest common leading component"
+    if not m: return ''
+    s1 = min(m)
+    s2 = max(m)
+    for i, c in enumerate(s1):
+        if c != s2[i]:
+            return s1[:i]
+    return s1
+
+# Split a path in root and extension.
+# The extension is everything starting at the last dot in the last
+# pathname component; the root is everything before that.
+# It is always true that root + ext == p.
+
+# Generic implementation of splitext, to be parametrized with
+# the separators
+def _splitext(p, sep, altsep, extsep):
+    """Split the extension from a pathname.
+
+    Extension is everything from the last dot to the end, ignoring
+    leading dots.  Returns "(root, ext)"; ext may be empty."""
+
+    sepIndex = p.rfind(sep)
+    if altsep:
+        altsepIndex = p.rfind(altsep)
+        sepIndex = max(sepIndex, altsepIndex)
+
+    dotIndex = p.rfind(extsep)
+    if dotIndex > sepIndex:
+        # skip all leading dots
+        filenameIndex = sepIndex + 1
+        while filenameIndex < dotIndex:
+            if p[filenameIndex] != extsep:
+                return p[:dotIndex], p[dotIndex:]
+            filenameIndex += 1
+
+    return p, ''
diff --git a/src/main/resources/PythonLibs/getopt.py b/src/main/resources/PythonLibs/getopt.py
new file mode 100644
index 0000000000000000000000000000000000000000..251d89c5cfe9ad9c11768377c86140243d9f92ee
--- /dev/null
+++ b/src/main/resources/PythonLibs/getopt.py
@@ -0,0 +1,210 @@
+"""Parser for command line options.
+
+This module helps scripts to parse the command line arguments in
+sys.argv.  It supports the same conventions as the Unix getopt()
+function (including the special meanings of arguments of the form `-'
+and `--').  Long options similar to those supported by GNU software
+may be used as well via an optional third argument.  This module
+provides two functions and an exception:
+
+getopt() -- Parse command line options
+gnu_getopt() -- Like getopt(), but allow option and non-option arguments
+to be intermixed.
+GetoptError -- exception (class) raised with 'opt' attribute, which is the
+option involved with the exception.
+"""
+
+# Long option support added by Lars Wirzenius <liw@iki.fi>.
+#
+# Gerrit Holl <gerrit@nl.linux.org> moved the string-based exceptions
+# to class-based exceptions.
+#
+# Peter Astrand <astrand@lysator.liu.se> added gnu_getopt().
+#
+# TODO for gnu_getopt():
+#
+# - GNU getopt_long_only mechanism
+# - allow the caller to specify ordering
+# - RETURN_IN_ORDER option
+# - GNU extension with '-' as first character of option string
+# - optional arguments, specified by double colons
+# - a option string with a W followed by semicolon should
+#   treat "-W foo" as "--foo"
+
+__all__ = ["GetoptError","error","getopt","gnu_getopt"]
+
+import os
+
+class GetoptError(Exception):
+    opt = ''
+    msg = ''
+    def __init__(self, msg, opt=''):
+        self.msg = msg
+        self.opt = opt
+        Exception.__init__(self, msg, opt)
+
+    def __str__(self):
+        return self.msg
+
+error = GetoptError # backward compatibility
+
+def getopt(args, shortopts, longopts = []):
+    """getopt(args, options[, long_options]) -> opts, args
+
+    Parses command line options and parameter list.  args is the
+    argument list to be parsed, without the leading reference to the
+    running program.  Typically, this means "sys.argv[1:]".  shortopts
+    is the string of option letters that the script wants to
+    recognize, with options that require an argument followed by a
+    colon (i.e., the same format that Unix getopt() uses).  If
+    specified, longopts is a list of strings with the names of the
+    long options which should be supported.  The leading '--'
+    characters should not be included in the option name.  Options
+    which require an argument should be followed by an equal sign
+    ('=').
+
+    The return value consists of two elements: the first is a list of
+    (option, value) pairs; the second is the list of program arguments
+    left after the option list was stripped (this is a trailing slice
+    of the first argument).  Each option-and-value pair returned has
+    the option as its first element, prefixed with a hyphen (e.g.,
+    '-x'), and the option argument as its second element, or an empty
+    string if the option has no argument.  The options occur in the
+    list in the same order in which they were found, thus allowing
+    multiple occurrences.  Long and short options may be mixed.
+
+    """
+
+    opts = []
+    if type(longopts) == type(""):
+        longopts = [longopts]
+    else:
+        longopts = list(longopts)
+    while args and args[0].startswith('-') and args[0] != '-':
+        if args[0] == '--':
+            args = args[1:]
+            break
+        if args[0].startswith('--'):
+            opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
+        else:
+            opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
+
+    return opts, args
+
+def gnu_getopt(args, shortopts, longopts = []):
+    """getopt(args, options[, long_options]) -> opts, args
+
+    This function works like getopt(), except that GNU style scanning
+    mode is used by default. This means that option and non-option
+    arguments may be intermixed. The getopt() function stops
+    processing options as soon as a non-option argument is
+    encountered.
+
+    If the first character of the option string is `+', or if the
+    environment variable POSIXLY_CORRECT is set, then option
+    processing stops as soon as a non-option argument is encountered.
+
+    """
+
+    opts = []
+    prog_args = []
+    if isinstance(longopts, str):
+        longopts = [longopts]
+    else:
+        longopts = list(longopts)
+
+    # Allow options after non-option arguments?
+    if shortopts.startswith('+'):
+        shortopts = shortopts[1:]
+        all_options_first = True
+    elif os.environ.get("POSIXLY_CORRECT"):
+        all_options_first = True
+    else:
+        all_options_first = False
+
+    while args:
+        if args[0] == '--':
+            prog_args += args[1:]
+            break
+
+        if args[0][:2] == '--':
+            opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
+        elif args[0][:1] == '-' and args[0] != '-':
+            opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
+        else:
+            if all_options_first:
+                prog_args += args
+                break
+            else:
+                prog_args.append(args[0])
+                args = args[1:]
+
+    return opts, prog_args
+
+def do_longs(opts, opt, longopts, args):
+    try:
+        i = opt.index('=')
+    except ValueError:
+        optarg = None
+    else:
+        opt, optarg = opt[:i], opt[i+1:]
+
+    has_arg, opt = long_has_args(opt, longopts)
+    if has_arg:
+        if optarg is None:
+            if not args:
+                raise GetoptError('option --%s requires argument' % opt, opt)
+            optarg, args = args[0], args[1:]
+    elif optarg is not None:
+        raise GetoptError('option --%s must not have an argument' % opt, opt)
+    opts.append(('--' + opt, optarg or ''))
+    return opts, args
+
+# Return:
+#   has_arg?
+#   full option name
+def long_has_args(opt, longopts):
+    possibilities = [o for o in longopts if o.startswith(opt)]
+    if not possibilities:
+        raise GetoptError('option --%s not recognized' % opt, opt)
+    # Is there an exact match?
+    if opt in possibilities:
+        return False, opt
+    elif opt + '=' in possibilities:
+        return True, opt
+    # No exact match, so better be unique.
+    if len(possibilities) > 1:
+        # XXX since possibilities contains all valid continuations, might be
+        # nice to work them into the error msg
+        raise GetoptError('option --%s not a unique prefix' % opt, opt)
+    assert len(possibilities) == 1
+    unique_match = possibilities[0]
+    has_arg = unique_match.endswith('=')
+    if has_arg:
+        unique_match = unique_match[:-1]
+    return has_arg, unique_match
+
+def do_shorts(opts, optstring, shortopts, args):
+    while optstring != '':
+        opt, optstring = optstring[0], optstring[1:]
+        if short_has_arg(opt, shortopts):
+            if optstring == '':
+                if not args:
+                    raise GetoptError('option -%s requires argument' % opt,
+                                      opt)
+                optstring, args = args[0], args[1:]
+            optarg, optstring = optstring, ''
+        else:
+            optarg = ''
+        opts.append(('-' + opt, optarg))
+    return opts, args
+
+def short_has_arg(opt, shortopts):
+    for i in range(len(shortopts)):
+        if opt == shortopts[i] != ':':
+            return shortopts.startswith(':', i+1)
+    raise GetoptError('option -%s not recognized' % opt, opt)
+
+if __name__ == '__main__':
+    import sys
+    print getopt(sys.argv[1:], "a:b", ["alpha=", "beta"])
diff --git a/src/main/resources/PythonLibs/getpass.py b/src/main/resources/PythonLibs/getpass.py
new file mode 100644
index 0000000000000000000000000000000000000000..012a233de00cda42c503afb992374a48d9c7cd3d
--- /dev/null
+++ b/src/main/resources/PythonLibs/getpass.py
@@ -0,0 +1,160 @@
+"""Utilities to get a password and/or the current user name.
+
+getpass(prompt) - prompt for a password, with echo turned off
+getuser() - get the user name from the environment or password database
+
+On Windows, the msvcrt module will be used.
+On the Mac EasyDialogs.AskPassword is used, if available.
+
+"""
+
+# From CPython 2.5.1 with a fix to _raw_input (see
+# http://bugs.python.org/issue1703 )
+
+# Authors: Piers Lauder (original)
+#          Guido van Rossum (Windows support and cleanup)
+
+import os
+import sys
+
+__all__ = ["getpass","getuser"]
+
+def jython_getpass(prompt='Password: ', stream=None):
+    """Prompt for a password, with echo turned off.
+    The prompt is written on stream, by default stdout.
+
+    Restore terminal settings at end.
+    """
+    if stream is None:
+        stream = sys.stdout
+
+    try:
+        terminal = sys._jy_interpreter.reader.terminal
+    except:
+        return default_getpass(prompt)
+
+    echoed = terminal.getEcho()
+    terminal.disableEcho()
+    try:
+        passwd = _raw_input(prompt, stream)
+    finally:
+        if echoed:
+           terminal.enableEcho()
+
+    stream.write('\n')
+    return passwd
+
+
+def unix_getpass(prompt='Password: ', stream=None):
+    """Prompt for a password, with echo turned off.
+    The prompt is written on stream, by default stdout.
+
+    Restore terminal settings at end.
+    """
+    if stream is None:
+        stream = sys.stdout
+
+    try:
+        fd = sys.stdin.fileno()
+    except:
+        return default_getpass(prompt)
+
+    old = termios.tcgetattr(fd)     # a copy to save
+    new = old[:]
+
+    new[3] = new[3] & ~termios.ECHO # 3 == 'lflags'
+    try:
+        termios.tcsetattr(fd, termios.TCSADRAIN, new)
+        passwd = _raw_input(prompt, stream)
+    finally:
+        termios.tcsetattr(fd, termios.TCSADRAIN, old)
+
+    stream.write('\n')
+    return passwd
+
+
+def win_getpass(prompt='Password: ', stream=None):
+    """Prompt for password with echo off, using Windows getch()."""
+    if sys.stdin is not sys.__stdin__:
+        return default_getpass(prompt, stream)
+    import msvcrt
+    for c in prompt:
+        msvcrt.putch(c)
+    pw = ""
+    while 1:
+        c = msvcrt.getch()
+        if c == '\r' or c == '\n':
+            break
+        if c == '\003':
+            raise KeyboardInterrupt
+        if c == '\b':
+            pw = pw[:-1]
+        else:
+            pw = pw + c
+    msvcrt.putch('\r')
+    msvcrt.putch('\n')
+    return pw
+
+
+def default_getpass(prompt='Password: ', stream=None):
+    print >>sys.stderr, "Warning: Problem with getpass. Passwords may be echoed."
+    return _raw_input(prompt, stream)
+
+
+def _raw_input(prompt="", stream=None):
+    # A raw_input() replacement that doesn't save the string in the
+    # GNU readline history.
+    if stream is None:
+        stream = sys.stdout
+    prompt = str(prompt)
+    if prompt:
+        stream.write(prompt)
+        stream.flush()
+    line = sys.stdin.readline()
+    if not line:
+        raise EOFError
+    if line[-1] == '\n':
+        line = line[:-1]
+    return line
+
+
+def getuser():
+    """Get the username from the environment or password database.
+
+    First try various environment variables, then the password
+    database.  This works on Windows as long as USERNAME is set.
+
+    """
+
+    for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
+        user = os.environ.get(name)
+        if user:
+            return user
+
+    # If this fails, the exception will "explain" why
+    import pwd
+    return pwd.getpwuid(os.getuid())[0]
+
+# Bind the name getpass to the appropriate function
+try:
+    import termios
+    # it's possible there is an incompatible termios from the
+    # McMillan Installer, make sure we have a UNIX-compatible termios
+    termios.tcgetattr, termios.tcsetattr
+except (ImportError, AttributeError):
+    try:
+        import msvcrt
+    except ImportError:
+        try:
+            from EasyDialogs import AskPassword
+        except ImportError:
+            if os.name == 'java':
+                getpass = jython_getpass
+            else:
+                getpass = default_getpass
+        else:
+            getpass = AskPassword
+    else:
+        getpass = win_getpass
+else:
+    getpass = unix_getpass
diff --git a/src/main/resources/PythonLibs/gettext.py b/src/main/resources/PythonLibs/gettext.py
new file mode 100644
index 0000000000000000000000000000000000000000..7698bdd57d2f1b9c0d6e74503b8098d523f87b5e
--- /dev/null
+++ b/src/main/resources/PythonLibs/gettext.py
@@ -0,0 +1,592 @@
+"""Internationalization and localization support.
+
+This module provides internationalization (I18N) and localization (L10N)
+support for your Python programs by providing an interface to the GNU gettext
+message catalog library.
+
+I18N refers to the operation by which a program is made aware of multiple
+languages.  L10N refers to the adaptation of your program, once
+internationalized, to the local language and cultural habits.
+
+"""
+
+# This module represents the integration of work, contributions, feedback, and
+# suggestions from the following people:
+#
+# Martin von Loewis, who wrote the initial implementation of the underlying
+# C-based libintlmodule (later renamed _gettext), along with a skeletal
+# gettext.py implementation.
+#
+# Peter Funk, who wrote fintl.py, a fairly complete wrapper around intlmodule,
+# which also included a pure-Python implementation to read .mo files if
+# intlmodule wasn't available.
+#
+# James Henstridge, who also wrote a gettext.py module, which has some
+# interesting, but currently unsupported experimental features: the notion of
+# a Catalog class and instances, and the ability to add to a catalog file via
+# a Python API.
+#
+# Barry Warsaw integrated these modules, wrote the .install() API and code,
+# and conformed all C and Python code to Python's coding standards.
+#
+# Francois Pinard and Marc-Andre Lemburg also contributed valuably to this
+# module.
+#
+# J. David Ibanez implemented plural forms. Bruno Haible fixed some bugs.
+#
+# TODO:
+# - Lazy loading of .mo files.  Currently the entire catalog is loaded into
+#   memory, but that's probably bad for large translated programs.  Instead,
+#   the lexical sort of original strings in GNU .mo files should be exploited
+#   to do binary searches and lazy initializations.  Or you might want to use
+#   the undocumented double-hash algorithm for .mo files with hash tables, but
+#   you'll need to study the GNU gettext code to do this.
+#
+# - Support Solaris .mo file formats.  Unfortunately, we've been unable to
+#   find this format documented anywhere.
+
+
+from __future__ import with_statement
+import locale, copy, os, re, struct, sys
+from errno import ENOENT
+
+
+__all__ = ['NullTranslations', 'GNUTranslations', 'Catalog',
+           'find', 'translation', 'install', 'textdomain', 'bindtextdomain',
+           'dgettext', 'dngettext', 'gettext', 'ngettext',
+           ]
+
+_default_localedir = os.path.join(sys.prefix, 'share', 'locale')
+
+
+def test(condition, true, false):
+    """
+    Implements the C expression:
+
+      condition ? true : false
+
+    Required to correctly interpret plural forms.
+    """
+    if condition:
+        return true
+    else:
+        return false
+
+
+def c2py(plural):
+    """Gets a C expression as used in PO files for plural forms and returns a
+    Python lambda function that implements an equivalent expression.
+    """
+    # Security check, allow only the "n" identifier
+    try:
+        from cStringIO import StringIO
+    except ImportError:
+        from StringIO import StringIO
+    import token, tokenize
+    tokens = tokenize.generate_tokens(StringIO(plural).readline)
+    try:
+        danger = [x for x in tokens if x[0] == token.NAME and x[1] != 'n']
+    except tokenize.TokenError:
+        raise ValueError, \
+              'plural forms expression error, maybe unbalanced parenthesis'
+    else:
+        if danger:
+            raise ValueError, 'plural forms expression could be dangerous'
+
+    # Replace some C operators by their Python equivalents
+    plural = plural.replace('&&', ' and ')
+    plural = plural.replace('||', ' or ')
+
+    expr = re.compile(r'\!([^=])')
+    plural = expr.sub(' not \\1', plural)
+
+    # Regular expression and replacement function used to transform
+    # "a?b:c" to "test(a,b,c)".
+    expr = re.compile(r'(.*?)\?(.*?):(.*)')
+    def repl(x):
+        return "test(%s, %s, %s)" % (x.group(1), x.group(2),
+                                     expr.sub(repl, x.group(3)))
+
+    # Code to transform the plural expression, taking care of parentheses
+    stack = ['']
+    for c in plural:
+        if c == '(':
+            stack.append('')
+        elif c == ')':
+            if len(stack) == 1:
+                # Actually, we never reach this code, because unbalanced
+                # parentheses get caught in the security check at the
+                # beginning.
+                raise ValueError, 'unbalanced parenthesis in plural form'
+            s = expr.sub(repl, stack.pop())
+            stack[-1] += '(%s)' % s
+        else:
+            stack[-1] += c
+    plural = expr.sub(repl, stack.pop())
+
+    return eval('lambda n: int(%s)' % plural)
+
+
+
+def _expand_lang(locale):
+    from locale import normalize
+    locale = normalize(locale)
+    COMPONENT_CODESET   = 1 << 0
+    COMPONENT_TERRITORY = 1 << 1
+    COMPONENT_MODIFIER  = 1 << 2
+    # split up the locale into its base components
+    mask = 0
+    pos = locale.find('@')
+    if pos >= 0:
+        modifier = locale[pos:]
+        locale = locale[:pos]
+        mask |= COMPONENT_MODIFIER
+    else:
+        modifier = ''
+    pos = locale.find('.')
+    if pos >= 0:
+        codeset = locale[pos:]
+        locale = locale[:pos]
+        mask |= COMPONENT_CODESET
+    else:
+        codeset = ''
+    pos = locale.find('_')
+    if pos >= 0:
+        territory = locale[pos:]
+        locale = locale[:pos]
+        mask |= COMPONENT_TERRITORY
+    else:
+        territory = ''
+    language = locale
+    ret = []
+    for i in range(mask+1):
+        if not (i & ~mask):  # if all components for this combo exist ...
+            val = language
+            if i & COMPONENT_TERRITORY: val += territory
+            if i & COMPONENT_CODESET:   val += codeset
+            if i & COMPONENT_MODIFIER:  val += modifier
+            ret.append(val)
+    ret.reverse()
+    return ret
+
+
+
+class NullTranslations:
+    def __init__(self, fp=None):
+        self._info = {}
+        self._charset = None
+        self._output_charset = None
+        self._fallback = None
+        if fp is not None:
+            self._parse(fp)
+
+    def _parse(self, fp):
+        pass
+
+    def add_fallback(self, fallback):
+        if self._fallback:
+            self._fallback.add_fallback(fallback)
+        else:
+            self._fallback = fallback
+
+    def gettext(self, message):
+        if self._fallback:
+            return self._fallback.gettext(message)
+        return message
+
+    def lgettext(self, message):
+        if self._fallback:
+            return self._fallback.lgettext(message)
+        return message
+
+    def ngettext(self, msgid1, msgid2, n):
+        if self._fallback:
+            return self._fallback.ngettext(msgid1, msgid2, n)
+        if n == 1:
+            return msgid1
+        else:
+            return msgid2
+
+    def lngettext(self, msgid1, msgid2, n):
+        if self._fallback:
+            return self._fallback.lngettext(msgid1, msgid2, n)
+        if n == 1:
+            return msgid1
+        else:
+            return msgid2
+
+    def ugettext(self, message):
+        if self._fallback:
+            return self._fallback.ugettext(message)
+        return unicode(message)
+
+    def ungettext(self, msgid1, msgid2, n):
+        if self._fallback:
+            return self._fallback.ungettext(msgid1, msgid2, n)
+        if n == 1:
+            return unicode(msgid1)
+        else:
+            return unicode(msgid2)
+
+    def info(self):
+        return self._info
+
+    def charset(self):
+        return self._charset
+
+    def output_charset(self):
+        return self._output_charset
+
+    def set_output_charset(self, charset):
+        self._output_charset = charset
+
+    def install(self, unicode=False, names=None):
+        import __builtin__
+        __builtin__.__dict__['_'] = unicode and self.ugettext or self.gettext
+        if hasattr(names, "__contains__"):
+            if "gettext" in names:
+                __builtin__.__dict__['gettext'] = __builtin__.__dict__['_']
+            if "ngettext" in names:
+                __builtin__.__dict__['ngettext'] = (unicode and self.ungettext
+                                                             or self.ngettext)
+            if "lgettext" in names:
+                __builtin__.__dict__['lgettext'] = self.lgettext
+            if "lngettext" in names:
+                __builtin__.__dict__['lngettext'] = self.lngettext
+
+
+class GNUTranslations(NullTranslations):
+    # Magic number of .mo files
+    LE_MAGIC = 0x950412deL
+    BE_MAGIC = 0xde120495L
+
+    def _parse(self, fp):
+        """Override this method to support alternative .mo formats."""
+        unpack = struct.unpack
+        filename = getattr(fp, 'name', '')
+        # Parse the .mo file header, which consists of 5 little endian 32
+        # bit words.
+        self._catalog = catalog = {}
+        self.plural = lambda n: int(n != 1) # germanic plural by default
+        buf = fp.read()
+        buflen = len(buf)
+        # Are we big endian or little endian?
+        magic = unpack('<I', buf[:4])[0]
+        if magic == self.LE_MAGIC:
+            version, msgcount, masteridx, transidx = unpack('<4I', buf[4:20])
+            ii = '<II'
+        elif magic == self.BE_MAGIC:
+            version, msgcount, masteridx, transidx = unpack('>4I', buf[4:20])
+            ii = '>II'
+        else:
+            raise IOError(0, 'Bad magic number', filename)
+        # Now put all messages from the .mo file buffer into the catalog
+        # dictionary.
+        for i in xrange(0, msgcount):
+            mlen, moff = unpack(ii, buf[masteridx:masteridx+8])
+            mend = moff + mlen
+            tlen, toff = unpack(ii, buf[transidx:transidx+8])
+            tend = toff + tlen
+            if mend < buflen and tend < buflen:
+                msg = buf[moff:mend]
+                tmsg = buf[toff:tend]
+            else:
+                raise IOError(0, 'File is corrupt', filename)
+            # See if we're looking at GNU .mo conventions for metadata
+            if mlen == 0:
+                # Catalog description
+                lastk = k = None
+                for item in tmsg.splitlines():
+                    item = item.strip()
+                    if not item:
+                        continue
+                    if ':' in item:
+                        k, v = item.split(':', 1)
+                        k = k.strip().lower()
+                        v = v.strip()
+                        self._info[k] = v
+                        lastk = k
+                    elif lastk:
+                        self._info[lastk] += '\n' + item
+                    if k == 'content-type':
+                        self._charset = v.split('charset=')[1]
+                    elif k == 'plural-forms':
+                        v = v.split(';')
+                        plural = v[1].split('plural=')[1]
+                        self.plural = c2py(plural)
+            # Note: we unconditionally convert both msgids and msgstrs to
+            # Unicode using the character encoding specified in the charset
+            # parameter of the Content-Type header.  The gettext documentation
+            # strongly encourages msgids to be us-ascii, but some appliations
+            # require alternative encodings (e.g. Zope's ZCML and ZPT).  For
+            # traditional gettext applications, the msgid conversion will
+            # cause no problems since us-ascii should always be a subset of
+            # the charset encoding.  We may want to fall back to 8-bit msgids
+            # if the Unicode conversion fails.
+            if '\x00' in msg:
+                # Plural forms
+                msgid1, msgid2 = msg.split('\x00')
+                tmsg = tmsg.split('\x00')
+                if self._charset:
+                    msgid1 = unicode(msgid1, self._charset)
+                    tmsg = [unicode(x, self._charset) for x in tmsg]
+                for i in range(len(tmsg)):
+                    catalog[(msgid1, i)] = tmsg[i]
+            else:
+                if self._charset:
+                    msg = unicode(msg, self._charset)
+                    tmsg = unicode(tmsg, self._charset)
+                catalog[msg] = tmsg
+            # advance to next entry in the seek tables
+            masteridx += 8
+            transidx += 8
+
+    def gettext(self, message):
+        missing = object()
+        tmsg = self._catalog.get(message, missing)
+        if tmsg is missing:
+            if self._fallback:
+                return self._fallback.gettext(message)
+            return message
+        # Encode the Unicode tmsg back to an 8-bit string, if possible
+        if self._output_charset:
+            return tmsg.encode(self._output_charset)
+        elif self._charset:
+            return tmsg.encode(self._charset)
+        return tmsg
+
+    def lgettext(self, message):
+        missing = object()
+        tmsg = self._catalog.get(message, missing)
+        if tmsg is missing:
+            if self._fallback:
+                return self._fallback.lgettext(message)
+            return message
+        if self._output_charset:
+            return tmsg.encode(self._output_charset)
+        return tmsg.encode(locale.getpreferredencoding())
+
+    def ngettext(self, msgid1, msgid2, n):
+        try:
+            tmsg = self._catalog[(msgid1, self.plural(n))]
+            if self._output_charset:
+                return tmsg.encode(self._output_charset)
+            elif self._charset:
+                return tmsg.encode(self._charset)
+            return tmsg
+        except KeyError:
+            if self._fallback:
+                return self._fallback.ngettext(msgid1, msgid2, n)
+            if n == 1:
+                return msgid1
+            else:
+                return msgid2
+
+    def lngettext(self, msgid1, msgid2, n):
+        try:
+            tmsg = self._catalog[(msgid1, self.plural(n))]
+            if self._output_charset:
+                return tmsg.encode(self._output_charset)
+            return tmsg.encode(locale.getpreferredencoding())
+        except KeyError:
+            if self._fallback:
+                return self._fallback.lngettext(msgid1, msgid2, n)
+            if n == 1:
+                return msgid1
+            else:
+                return msgid2
+
+    def ugettext(self, message):
+        missing = object()
+        tmsg = self._catalog.get(message, missing)
+        if tmsg is missing:
+            if self._fallback:
+                return self._fallback.ugettext(message)
+            return unicode(message)
+        return tmsg
+
+    def ungettext(self, msgid1, msgid2, n):
+        try:
+            tmsg = self._catalog[(msgid1, self.plural(n))]
+        except KeyError:
+            if self._fallback:
+                return self._fallback.ungettext(msgid1, msgid2, n)
+            if n == 1:
+                tmsg = unicode(msgid1)
+            else:
+                tmsg = unicode(msgid2)
+        return tmsg
+
+
+# Locate a .mo file using the gettext strategy
+def find(domain, localedir=None, languages=None, all=0):
+    # Get some reasonable defaults for arguments that were not supplied
+    if localedir is None:
+        localedir = _default_localedir
+    if languages is None:
+        languages = []
+        for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'):
+            val = os.environ.get(envar)
+            if val:
+                languages = val.split(':')
+                break
+        if 'C' not in languages:
+            languages.append('C')
+    # now normalize and expand the languages
+    nelangs = []
+    for lang in languages:
+        for nelang in _expand_lang(lang):
+            if nelang not in nelangs:
+                nelangs.append(nelang)
+    # select a language
+    if all:
+        result = []
+    else:
+        result = None
+    for lang in nelangs:
+        if lang == 'C':
+            break
+        mofile = os.path.join(localedir, lang, 'LC_MESSAGES', '%s.mo' % domain)
+        if os.path.exists(mofile):
+            if all:
+                result.append(mofile)
+            else:
+                return mofile
+    return result
+
+
+
+# a mapping between absolute .mo file path and Translation object
+_translations = {}
+
+def translation(domain, localedir=None, languages=None,
+                class_=None, fallback=False, codeset=None):
+    if class_ is None:
+        class_ = GNUTranslations
+    mofiles = find(domain, localedir, languages, all=1)
+    if not mofiles:
+        if fallback:
+            return NullTranslations()
+        raise IOError(ENOENT, 'No translation file found for domain', domain)
+    # Avoid opening, reading, and parsing the .mo file after it's been done
+    # once.
+    result = None
+    for mofile in mofiles:
+        key = (class_, os.path.abspath(mofile))
+        t = _translations.get(key)
+        if t is None:
+            with open(mofile, 'rb') as fp:
+                t = _translations.setdefault(key, class_(fp))
+        # Copy the translation object to allow setting fallbacks and
+        # output charset. All other instance data is shared with the
+        # cached object.
+        t = copy.copy(t)
+        if codeset:
+            t.set_output_charset(codeset)
+        if result is None:
+            result = t
+        else:
+            result.add_fallback(t)
+    return result
+
+
+def install(domain, localedir=None, unicode=False, codeset=None, names=None):
+    t = translation(domain, localedir, fallback=True, codeset=codeset)
+    t.install(unicode, names)
+
+
+
+# a mapping b/w domains and locale directories
+_localedirs = {}
+# a mapping b/w domains and codesets
+_localecodesets = {}
+# current global domain, `messages' used for compatibility w/ GNU gettext
+_current_domain = 'messages'
+
+
+def textdomain(domain=None):
+    global _current_domain
+    if domain is not None:
+        _current_domain = domain
+    return _current_domain
+
+
+def bindtextdomain(domain, localedir=None):
+    global _localedirs
+    if localedir is not None:
+        _localedirs[domain] = localedir
+    return _localedirs.get(domain, _default_localedir)
+
+
+def bind_textdomain_codeset(domain, codeset=None):
+    global _localecodesets
+    if codeset is not None:
+        _localecodesets[domain] = codeset
+    return _localecodesets.get(domain)
+
+
+def dgettext(domain, message):
+    try:
+        t = translation(domain, _localedirs.get(domain, None),
+                        codeset=_localecodesets.get(domain))
+    except IOError:
+        return message
+    return t.gettext(message)
+
+def ldgettext(domain, message):
+    try:
+        t = translation(domain, _localedirs.get(domain, None),
+                        codeset=_localecodesets.get(domain))
+    except IOError:
+        return message
+    return t.lgettext(message)
+
+def dngettext(domain, msgid1, msgid2, n):
+    try:
+        t = translation(domain, _localedirs.get(domain, None),
+                        codeset=_localecodesets.get(domain))
+    except IOError:
+        if n == 1:
+            return msgid1
+        else:
+            return msgid2
+    return t.ngettext(msgid1, msgid2, n)
+
+def ldngettext(domain, msgid1, msgid2, n):
+    try:
+        t = translation(domain, _localedirs.get(domain, None),
+                        codeset=_localecodesets.get(domain))
+    except IOError:
+        if n == 1:
+            return msgid1
+        else:
+            return msgid2
+    return t.lngettext(msgid1, msgid2, n)
+
+def gettext(message):
+    return dgettext(_current_domain, message)
+
+def lgettext(message):
+    return ldgettext(_current_domain, message)
+
+def ngettext(msgid1, msgid2, n):
+    return dngettext(_current_domain, msgid1, msgid2, n)
+
+def lngettext(msgid1, msgid2, n):
+    return ldngettext(_current_domain, msgid1, msgid2, n)
+
+# dcgettext() has been deemed unnecessary and is not implemented.
+
+# James Henstridge's Catalog constructor from GNOME gettext.  Documented usage
+# was:
+#
+#    import gettext
+#    cat = gettext.Catalog(PACKAGE, localedir=LOCALEDIR)
+#    _ = cat.gettext
+#    print _('Hello World')
+
+# The resulting catalog object currently don't support access through a
+# dictionary API, which was supported (but apparently unused) in GNOME
+# gettext.
+
+Catalog = translation
diff --git a/src/main/resources/PythonLibs/glob.py b/src/main/resources/PythonLibs/glob.py
new file mode 100644
index 0000000000000000000000000000000000000000..f34534b53c44825f010fd757aaf68cd93132cd5a
--- /dev/null
+++ b/src/main/resources/PythonLibs/glob.py
@@ -0,0 +1,95 @@
+"""Filename globbing utility."""
+
+import sys
+import os
+import re
+import fnmatch
+
+try:
+    _unicode = unicode
+except NameError:
+    # If Python is built without Unicode support, the unicode type
+    # will not exist. Fake one.
+    class _unicode(object):
+        pass
+
+__all__ = ["glob", "iglob"]
+
+def glob(pathname):
+    """Return a list of paths matching a pathname pattern.
+
+    The pattern may contain simple shell-style wildcards a la
+    fnmatch. However, unlike fnmatch, filenames starting with a
+    dot are special cases that are not matched by '*' and '?'
+    patterns.
+
+    """
+    return list(iglob(pathname))
+
+def iglob(pathname):
+    """Return an iterator which yields the paths matching a pathname pattern.
+
+    The pattern may contain simple shell-style wildcards a la
+    fnmatch. However, unlike fnmatch, filenames starting with a
+    dot are special cases that are not matched by '*' and '?'
+    patterns.
+
+    """
+    if not has_magic(pathname):
+        if os.path.lexists(pathname):
+            yield pathname
+        return
+    dirname, basename = os.path.split(pathname)
+    if not dirname:
+        for name in glob1(os.curdir, basename):
+            yield name
+        return
+    # `os.path.split()` returns the argument itself as a dirname if it is a
+    # drive or UNC path.  Prevent an infinite recursion if a drive or UNC path
+    # contains magic characters (i.e. r'\\?\C:').
+    if dirname != pathname and has_magic(dirname):
+        dirs = iglob(dirname)
+    else:
+        dirs = [dirname]
+    if has_magic(basename):
+        glob_in_dir = glob1
+    else:
+        glob_in_dir = glob0
+    for dirname in dirs:
+        for name in glob_in_dir(dirname, basename):
+            yield os.path.join(dirname, name)
+
+# These 2 helper functions non-recursively glob inside a literal directory.
+# They return a list of basenames. `glob1` accepts a pattern while `glob0`
+# takes a literal basename (so it only has to check for its existence).
+
+def glob1(dirname, pattern):
+    if not dirname:
+        dirname = os.curdir
+    if isinstance(pattern, _unicode) and not isinstance(dirname, unicode):
+        dirname = unicode(dirname, sys.getfilesystemencoding() or
+                                   sys.getdefaultencoding())
+    try:
+        names = os.listdir(dirname)
+    except os.error:
+        return []
+    if pattern[0] != '.':
+        names = filter(lambda x: x[0] != '.', names)
+    return fnmatch.filter(names, pattern)
+
+def glob0(dirname, basename):
+    if basename == '':
+        # `os.path.split()` returns an empty basename for paths ending with a
+        # directory separator.  'q*x/' should match only directories.
+        if os.path.isdir(dirname):
+            return [basename]
+    else:
+        if os.path.lexists(os.path.join(dirname, basename)):
+            return [basename]
+    return []
+
+
+magic_check = re.compile('[*?[]')
+
+def has_magic(s):
+    return magic_check.search(s) is not None
diff --git a/src/main/resources/PythonLibs/grp.py b/src/main/resources/PythonLibs/grp.py
new file mode 100644
index 0000000000000000000000000000000000000000..50f3bd005449dd82205e7fb22c36d515cd277d6b
--- /dev/null
+++ b/src/main/resources/PythonLibs/grp.py
@@ -0,0 +1,85 @@
+"""
+Access to the Unix group database.
+
+Group entries are reported as 4-tuples containing the following fields
+from the group database, in order:
+
+  name   - name of the group
+  passwd - group password (encrypted); often empty
+  gid    - numeric ID of the group
+  mem    - list of members
+
+The gid is an integer, name and password are strings.  (Note that most
+users are not explicitly listed as members of the groups they are in
+according to the password database.  Check both databases to get
+complete membership information.)
+"""
+
+__all__ = ['getgrgid', 'getgrnam', 'getgrall']
+
+from os import _name, _posix_impl
+from org.python.core.Py import newString
+
+if _name == 'nt':
+    raise ImportError, 'grp module not supported on Windows'
+
+class struct_group(tuple):
+    """
+    grp.struct_group: Results from getgr*() routines.
+
+    This object may be accessed either as a tuple of
+      (gr_name,gr_passwd,gr_gid,gr_mem)
+    or via the object attributes as named in the above tuple.
+    """
+
+    attrs = ['gr_name', 'gr_passwd', 'gr_gid', 'gr_mem']
+
+    def __new__(cls, grp):
+        grp = (newString(grp.name), newString(grp.password), int(grp.GID),
+               [newString(member) for member in grp.members])
+        return tuple.__new__(cls, grp)
+
+    def __getattr__(self, attr):
+        try:
+            return self[self.attrs.index(attr)]
+        except ValueError:
+            raise AttributeError
+
+
+def getgrgid(uid):
+    """
+    getgrgid(id) -> tuple
+    Return the group database entry for the given numeric group ID.  If
+    id is not valid, raise KeyError.
+    """
+    entry = _posix_impl.getgrgid(uid)
+    if not entry:
+        raise KeyError(uid)
+    return struct_group(entry)
+
+
+def getgrnam(name):
+    """
+    getgrnam(name) -> tuple
+    Return the group database entry for the given group name.  If
+    name is not valid, raise KeyError.
+    """
+    entry = _posix_impl.getgrnam(name)
+    if not entry:
+        raise KeyError(name)
+    return struct_group(entry)
+
+
+def getgrall():
+    """
+    getgrall() -> list of tuples
+    Return a list of all available group database entries,
+    in arbitrary order.
+    """
+    groups = []
+    while True:
+        group = _posix_impl.getgrent()
+        if not group:
+            break
+        groups.append(struct_group(group))
+    return groups
diff --git a/src/main/resources/PythonLibs/gzip.py b/src/main/resources/PythonLibs/gzip.py
new file mode 100644
index 0000000000000000000000000000000000000000..0f50c3c0a16d1909d3775950c353ecdf2a456464
--- /dev/null
+++ b/src/main/resources/PythonLibs/gzip.py
@@ -0,0 +1,520 @@
+"""Functions that read and write gzipped files.
+
+The user of the file doesn't have to worry about the compression,
+but random access is not allowed."""
+
+# based on Andrew Kuchling's minigzip.py distributed with the zlib module
+
+import struct, sys, time, os
+import zlib
+import io
+import __builtin__
+
+__all__ = ["GzipFile","open"]
+
+FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
+
+READ, WRITE = 1, 2
+
+def write32u(output, value):
+    # The L format writes the bit pattern correctly whether signed
+    # or unsigned.
+    output.write(struct.pack("<L", value))
+
+def read32(input):
+    return struct.unpack("<I", input.read(4))[0]
+
+def open(filename, mode="rb", compresslevel=9):
+    """Shorthand for GzipFile(filename, mode, compresslevel).
+
+    The filename argument is required; mode defaults to 'rb'
+    and compresslevel defaults to 9.
+
+    """
+    return GzipFile(filename, mode, compresslevel)
+
+class GzipFile(io.BufferedIOBase):
+    """The GzipFile class simulates most of the methods of a file object with
+    the exception of the readinto() and truncate() methods.
+
+    """
+
+    myfileobj = None
+    # XXX: repeated 10mb chunk reads hurt test_gzip.test_many_append's
+    # performance on Jython (maybe CPython's allocator recycles the same
+    # 10mb buffer whereas Java's doesn't)
+    #max_read_chunk = 10 * 1024 * 1024   # 10Mb
+    max_read_chunk = 256 * 1024 # 256kb
+
+    def __init__(self, filename=None, mode=None,
+                 compresslevel=9, fileobj=None, mtime=None):
+        """Constructor for the GzipFile class.
+
+        At least one of fileobj and filename must be given a
+        non-trivial value.
+
+        The new class instance is based on fileobj, which can be a regular
+        file, a StringIO object, or any other object which simulates a file.
+        It defaults to None, in which case filename is opened to provide
+        a file object.
+
+        When fileobj is not None, the filename argument is only used to be
+        included in the gzip file header, which may includes the original
+        filename of the uncompressed file.  It defaults to the filename of
+        fileobj, if discernible; otherwise, it defaults to the empty string,
+        and in this case the original filename is not included in the header.
+
+        The mode argument can be any of 'r', 'rb', 'a', 'ab', 'w', or 'wb',
+        depending on whether the file will be read or written.  The default
+        is the mode of fileobj if discernible; otherwise, the default is 'rb'.
+        Be aware that only the 'rb', 'ab', and 'wb' values should be used
+        for cross-platform portability.
+
+        The compresslevel argument is an integer from 1 to 9 controlling the
+        level of compression; 1 is fastest and produces the least compression,
+        and 9 is slowest and produces the most compression.  The default is 9.
+
+        The mtime argument is an optional numeric timestamp to be written
+        to the stream when compressing.  All gzip compressed streams
+        are required to contain a timestamp.  If omitted or None, the
+        current time is used.  This module ignores the timestamp when
+        decompressing; however, some programs, such as gunzip, make use
+        of it.  The format of the timestamp is the same as that of the
+        return value of time.time() and of the st_mtime member of the
+        object returned by os.stat().
+
+        """
+
+        # guarantee the file is opened in binary mode on platforms
+        # that care about that sort of thing
+        if mode and 'b' not in mode:
+            mode += 'b'
+        if fileobj is None:
+            fileobj = self.myfileobj = __builtin__.open(filename, mode or 'rb')
+        if filename is None:
+            if hasattr(fileobj, 'name'): filename = fileobj.name
+            else: filename = ''
+        if mode is None:
+            if hasattr(fileobj, 'mode'): mode = fileobj.mode
+            else: mode = 'rb'
+
+        if mode[0:1] == 'r':
+            self.mode = READ
+            # Set flag indicating start of a new member
+            self._new_member = True
+            # Buffer data read from gzip file. extrastart is offset in
+            # stream where buffer starts. extrasize is number of
+            # bytes remaining in buffer from current stream position.
+            self.extrabuf = ""
+            self.extrasize = 0
+            self.extrastart = 0
+            self.name = filename
+            # Starts small, scales exponentially
+            self.min_readsize = 100
+
+        elif mode[0:1] == 'w' or mode[0:1] == 'a':
+            self.mode = WRITE
+            self._init_write(filename)
+            self.compress = zlib.compressobj(compresslevel,
+                                             zlib.DEFLATED,
+                                             -zlib.MAX_WBITS,
+                                             zlib.DEF_MEM_LEVEL,
+                                             0)
+        else:
+            raise IOError, "Mode " + mode + " not supported"
+
+        self.fileobj = fileobj
+        self.offset = 0
+        self.mtime = mtime
+
+        if self.mode == WRITE:
+            self._write_gzip_header()
+
+    @property
+    def filename(self):
+        import warnings
+        warnings.warn("use the name attribute", DeprecationWarning, 2)
+        if self.mode == WRITE and self.name[-3:] != ".gz":
+            return self.name + ".gz"
+        return self.name
+
+    def __repr__(self):
+        s = repr(self.fileobj)
+        return '<gzip ' + s[1:-1] + ' ' + hex(id(self)) + '>'
+
+    def _check_closed(self):
+        """Raises a ValueError if the underlying file object has been closed.
+
+        """
+        if self.closed:
+            raise ValueError('I/O operation on closed file.')
+
+    def _init_write(self, filename):
+        self.name = filename
+        self.crc = zlib.crc32("") & 0xffffffffL
+        self.size = 0
+        self.writebuf = []
+        self.bufsize = 0
+
+    def _write_gzip_header(self):
+        self.fileobj.write('\037\213')             # magic header
+        self.fileobj.write('\010')                 # compression method
+        fname = os.path.basename(self.name)
+        if fname.endswith(".gz"):
+            fname = fname[:-3]
+        flags = 0
+        if fname:
+            flags = FNAME
+        self.fileobj.write(chr(flags))
+        mtime = self.mtime
+        if mtime is None:
+            mtime = time.time()
+        write32u(self.fileobj, long(mtime))
+        self.fileobj.write('\002')
+        self.fileobj.write('\377')
+        if fname:
+            self.fileobj.write(fname + '\000')
+
+    def _init_read(self):
+        self.crc = zlib.crc32("") & 0xffffffffL
+        self.size = 0
+
+    def _read_gzip_header(self):
+        magic = self.fileobj.read(2)
+        if magic != '\037\213':
+            raise IOError, 'Not a gzipped file'
+        method = ord( self.fileobj.read(1) )
+        if method != 8:
+            raise IOError, 'Unknown compression method'
+        flag = ord( self.fileobj.read(1) )
+        self.mtime = read32(self.fileobj)
+        # extraflag = self.fileobj.read(1)
+        # os = self.fileobj.read(1)
+        self.fileobj.read(2)
+
+        if flag & FEXTRA:
+            # Read & discard the extra field, if present
+            xlen = ord(self.fileobj.read(1))
+            xlen = xlen + 256*ord(self.fileobj.read(1))
+            self.fileobj.read(xlen)
+        if flag & FNAME:
+            # Read and discard a null-terminated string containing the filename
+            while True:
+                s = self.fileobj.read(1)
+                if not s or s=='\000':
+                    break
+        if flag & FCOMMENT:
+            # Read and discard a null-terminated string containing a comment
+            while True:
+                s = self.fileobj.read(1)
+                if not s or s=='\000':
+                    break
+        if flag & FHCRC:
+            self.fileobj.read(2)     # Read & discard the 16-bit header CRC
+
+    def write(self,data):
+        self._check_closed()
+        if self.mode != WRITE:
+            import errno
+            raise IOError(errno.EBADF, "write() on read-only GzipFile object")
+
+        if self.fileobj is None:
+            raise ValueError, "write() on closed GzipFile object"
+
+        # Convert data type if called by io.BufferedWriter.
+        if isinstance(data, memoryview):
+            data = data.tobytes()
+
+        if len(data) > 0:
+            self.size = self.size + len(data)
+            self.crc = zlib.crc32(data, self.crc) & 0xffffffffL
+            self.fileobj.write( self.compress.compress(data) )
+            self.offset += len(data)
+
+        return len(data)
+
+    def read(self, size=-1):
+        self._check_closed()
+        if self.mode != READ:
+            import errno
+            raise IOError(errno.EBADF, "read() on write-only GzipFile object")
+
+        if self.extrasize <= 0 and self.fileobj is None:
+            return ''
+
+        readsize = 1024
+        if size < 0:        # get the whole thing
+            try:
+                while True:
+                    self._read(readsize)
+                    readsize = min(self.max_read_chunk, readsize * 2)
+            except EOFError:
+                size = self.extrasize
+        else:               # just get some more of it
+            try:
+                while size > self.extrasize:
+                    self._read(readsize)
+                    readsize = min(self.max_read_chunk, readsize * 2)
+            except EOFError:
+                if size > self.extrasize:
+                    size = self.extrasize
+
+        offset = self.offset - self.extrastart
+        chunk = self.extrabuf[offset: offset + size]
+        self.extrasize = self.extrasize - size
+
+        self.offset += size
+        return chunk
+
+    def _unread(self, buf):
+        self.extrasize = len(buf) + self.extrasize
+        self.offset -= len(buf)
+
+    def _read(self, size=1024):
+        if self.fileobj is None:
+            raise EOFError, "Reached EOF"
+
+        if self._new_member:
+            # If the _new_member flag is set, we have to
+            # jump to the next member, if there is one.
+            #
+            # First, check if we're at the end of the file;
+            # if so, it's time to stop; no more members to read.
+            pos = self.fileobj.tell()   # Save current position
+            self.fileobj.seek(0, 2)     # Seek to end of file
+            if pos == self.fileobj.tell():
+                raise EOFError, "Reached EOF"
+            else:
+                self.fileobj.seek( pos ) # Return to original position
+
+            self._init_read()
+            self._read_gzip_header()
+            self.decompress = zlib.decompressobj(-zlib.MAX_WBITS)
+            self._new_member = False
+
+        # Read a chunk of data from the file
+        buf = self.fileobj.read(size)
+
+        # If the EOF has been reached, flush the decompression object
+        # and mark this object as finished.
+
+        if buf == "":
+            uncompress = self.decompress.flush()
+            self._read_eof()
+            self._add_read_data( uncompress )
+            raise EOFError, 'Reached EOF'
+
+        uncompress = self.decompress.decompress(buf)
+        self._add_read_data( uncompress )
+
+        if self.decompress.unused_data != "":
+            # Ending case: we've come to the end of a member in the file,
+            # so seek back to the start of the unused data, finish up
+            # this member, and read a new gzip header.
+            # (The number of bytes to seek back is the length of the unused
+            # data, minus 8 because _read_eof() will rewind a further 8 bytes)
+            self.fileobj.seek( -len(self.decompress.unused_data)+8, 1)
+
+            # Check the CRC and file size, and set the flag so we read
+            # a new member on the next call
+            self._read_eof()
+            self._new_member = True
+
+    def _add_read_data(self, data):
+        self.crc = zlib.crc32(data, self.crc) & 0xffffffffL
+        offset = self.offset - self.extrastart
+        self.extrabuf = self.extrabuf[offset:] + data
+        self.extrasize = self.extrasize + len(data)
+        self.extrastart = self.offset
+        self.size = self.size + len(data)
+
+    def _read_eof(self):
+        # We've read to the end of the file, so we have to rewind in order
+        # to reread the 8 bytes containing the CRC and the file size.
+        # We check the that the computed CRC and size of the
+        # uncompressed data matches the stored values.  Note that the size
+        # stored is the true file size mod 2**32.
+        self.fileobj.seek(-8, 1)
+        crc32 = read32(self.fileobj)
+        isize = read32(self.fileobj)  # may exceed 2GB
+        if crc32 != self.crc:
+            raise IOError("CRC check failed %s != %s" % (hex(crc32),
+                                                         hex(self.crc)))
+        elif isize != (self.size & 0xffffffffL):
+            raise IOError, "Incorrect length of data produced"
+
+        # Gzip files can be padded with zeroes and still have archives.
+        # Consume all zero bytes and set the file position to the first
+        # non-zero byte. See http://www.gzip.org/#faq8
+        c = "\x00"
+        while c == "\x00":
+            c = self.fileobj.read(1)
+        if c:
+            self.fileobj.seek(-1, 1)
+
+    @property
+    def closed(self):
+        return self.fileobj is None
+
+    def close(self):
+        if self.fileobj is None:
+            return
+        if self.mode == WRITE:
+            self.fileobj.write(self.compress.flush())
+            write32u(self.fileobj, self.crc)
+            # self.size may exceed 2GB, or even 4GB
+            write32u(self.fileobj, self.size & 0xffffffffL)
+            self.fileobj = None
+        elif self.mode == READ:
+            self.fileobj = None
+        if self.myfileobj:
+            self.myfileobj.close()
+            self.myfileobj = None
+
+    if not sys.platform.startswith('java'):
+        def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH):
+            self._check_closed()
+            if self.mode == WRITE:
+                # Ensure the compressor's buffer is flushed
+                self.fileobj.write(self.compress.flush(zlib_mode))
+                self.fileobj.flush()
+    else:
+        # Java lacks Z_SYNC_FLUSH; thus Jython can't flush the
+        # compressobj until EOF
+        def flush(self,zlib_mode=None):
+            self._check_closed()
+            self.fileobj.flush()
+
+    def fileno(self):
+        """Invoke the underlying file object's fileno() method.
+
+        This will raise AttributeError if the underlying file object
+        doesn't support fileno().
+        """
+        return self.fileobj.fileno()
+
+    def rewind(self):
+        '''Return the uncompressed stream file position indicator to the
+        beginning of the file'''
+        if self.mode != READ:
+            raise IOError("Can't rewind in write mode")
+        self.fileobj.seek(0)
+        self._new_member = True
+        self.extrabuf = ""
+        self.extrasize = 0
+        self.extrastart = 0
+        self.offset = 0
+
+    def readable(self):
+        return self.mode == READ
+
+    def writable(self):
+        return self.mode == WRITE
+
+    def seekable(self):
+        return True
+
+    def seek(self, offset, whence=0):
+        if whence:
+            if whence == 1:
+                offset = self.offset + offset
+            else:
+                raise ValueError('Seek from end not supported')
+        if self.mode == WRITE:
+            if offset < self.offset:
+                raise IOError('Negative seek in write mode')
+            count = offset - self.offset
+            for i in range(count // 1024):
+                self.write(1024 * '\0')
+            self.write((count % 1024) * '\0')
+        elif self.mode == READ:
+            if offset < self.offset:
+                # for negative seek, rewind and do positive seek
+                self.rewind()
+            count = offset - self.offset
+            for i in range(count // 1024):
+                self.read(1024)
+            self.read(count % 1024)
+
+        return self.offset
+
+    def readline(self, size=-1):
+        if size < 0:
+            # Shortcut common case - newline found in buffer.
+            offset = self.offset - self.extrastart
+            i = self.extrabuf.find('\n', offset) + 1
+            if i > 0:
+                self.extrasize -= i - offset
+                self.offset += i - offset
+                return self.extrabuf[offset: i]
+
+            size = sys.maxint
+            readsize = self.min_readsize
+        else:
+            readsize = size
+        bufs = []
+        while size != 0:
+            c = self.read(readsize)
+            i = c.find('\n')
+
+            # We set i=size to break out of the loop under two
+            # conditions: 1) there's no newline, and the chunk is
+            # larger than size, or 2) there is a newline, but the
+            # resulting line would be longer than 'size'.
+            if (size <= i) or (i == -1 and len(c) > size):
+                i = size - 1
+
+            if i >= 0 or c == '':
+                bufs.append(c[:i + 1])    # Add portion of last chunk
+                self._unread(c[i + 1:])   # Push back rest of chunk
+                break
+
+            # Append chunk to list, decrease 'size',
+            bufs.append(c)
+            size = size - len(c)
+            readsize = min(size, readsize * 2)
+        if readsize > self.min_readsize:
+            self.min_readsize = min(readsize, self.min_readsize * 2, 512)
+        return ''.join(bufs) # Return resulting line
+
+
+def _test():
+    # Act like gzip; with -d, act like gunzip.
+    # The input file is not deleted, however, nor are any other gzip
+    # options or features supported.
+    args = sys.argv[1:]
+    decompress = args and args[0] == "-d"
+    if decompress:
+        args = args[1:]
+    if not args:
+        args = ["-"]
+    for arg in args:
+        if decompress:
+            if arg == "-":
+                f = GzipFile(filename="", mode="rb", fileobj=sys.stdin)
+                g = sys.stdout
+            else:
+                if arg[-3:] != ".gz":
+                    print "filename doesn't end in .gz:", repr(arg)
+                    continue
+                f = open(arg, "rb")
+                g = __builtin__.open(arg[:-3], "wb")
+        else:
+            if arg == "-":
+                f = sys.stdin
+                g = GzipFile(filename="", mode="wb", fileobj=sys.stdout)
+            else:
+                f = __builtin__.open(arg, "rb")
+                g = open(arg + ".gz", "wb")
+        while True:
+            chunk = f.read(1024)
+            if not chunk:
+                break
+            g.write(chunk)
+        if g is not sys.stdout:
+            g.close()
+        if f is not sys.stdin:
+            f.close()
+
+if __name__ == '__main__':
+    _test()
diff --git a/src/main/resources/PythonLibs/hashlib.py b/src/main/resources/PythonLibs/hashlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..d20e1f95a2afc8407ad6ea7b3602163f598e0896
--- /dev/null
+++ b/src/main/resources/PythonLibs/hashlib.py
@@ -0,0 +1,146 @@
+# $Id$
+#
+#  Copyright (C) 2005   Gregory P. Smith (greg@krypto.org)
+#  Licensed to PSF under a Contributor Agreement.
+#
+
+__doc__ = """hashlib module - A common interface to many hash functions.
+
+new(name, string='') - returns a new hash object implementing the
+                       given hash function; initializing the hash
+                       using the given string data.
+
+Named constructor functions are also available, these are much faster
+than using new():
+
+md5(), sha1(), sha224(), sha256(), sha384(), and sha512()
+
+More algorithms may be available on your platform but the above are
+guaranteed to exist.
+
+NOTE: If you want the adler32 or crc32 hash functions they are available in
+the zlib module.
+
+Choose your hash function wisely.  Some have known collision weaknesses.
+sha384 and sha512 will be slow on 32 bit platforms.
+
+Hash objects have these methods:
+ - update(arg): Update the hash object with the string arg. Repeated calls
+                are equivalent to a single call with the concatenation of all
+                the arguments.
+ - digest():    Return the digest of the strings passed to the update() method
+                so far. This may contain non-ASCII characters, including
+                NUL bytes.
+ - hexdigest(): Like digest() except the digest is returned as a string of
+                double length, containing only hexadecimal digits.
+ - copy():      Return a copy (clone) of the hash object. This can be used to
+                efficiently compute the digests of strings that share a common
+                initial substring.
+
+For example, to obtain the digest of the string 'Nobody inspects the
+spammish repetition':
+
+    >>> import hashlib
+    >>> m = hashlib.md5()
+    >>> m.update("Nobody inspects")
+    >>> m.update(" the spammish repetition")
+    >>> m.digest()
+    '\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9'
+
+More condensed:
+
+    >>> hashlib.sha224("Nobody inspects the spammish repetition").hexdigest()
+    'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'
+
+"""
+
+# This tuple and __get_builtin_constructor() must be modified if a new
+# always available algorithm is added.
+__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
+
+algorithms = __always_supported
+
+__all__ = __always_supported + ('new', 'algorithms')
+
+
+def __get_builtin_constructor(name):
+    try:
+        if name in ('SHA1', 'sha1'):
+            import _sha
+            return _sha.new
+        elif name in ('MD5', 'md5'):
+            import _md5
+            return _md5.new
+        elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
+            import _sha256
+            bs = name[3:]
+            if bs == '256':
+                return _sha256.sha256
+            elif bs == '224':
+                return _sha256.sha224
+        elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
+            import _sha512
+            bs = name[3:]
+            if bs == '512':
+                return _sha512.sha512
+            elif bs == '384':
+                return _sha512.sha384
+    except ImportError:
+        pass  # no extension module, this hash is unsupported.
+
+    raise ValueError('unsupported hash type ' + name)
+
+
+def __get_openssl_constructor(name):
+    try:
+        f = getattr(_hashlib, 'openssl_' + name)
+        # Allow the C module to raise ValueError.  The function will be
+        # defined but the hash not actually available thanks to OpenSSL.
+        f()
+        # Use the C function directly (very fast)
+        return f
+    except (AttributeError, ValueError):
+        return __get_builtin_constructor(name)
+
+
+def __py_new(name, string=''):
+    """new(name, string='') - Return a new hashing object using the named algorithm;
+    optionally initialized with a string.
+    """
+    return __get_builtin_constructor(name)(string)
+
+
+def __hash_new(name, string=''):
+    """new(name, string='') - Return a new hashing object using the named algorithm;
+    optionally initialized with a string.
+    """
+    try:
+        return _hashlib.new(name, string)
+    except ValueError:
+        # If the _hashlib module (OpenSSL) doesn't support the named
+        # hash, try using our builtin implementations.
+        # This allows for SHA224/256 and SHA384/512 support even though
+        # the OpenSSL library prior to 0.9.8 doesn't provide them.
+        return __get_builtin_constructor(name)(string)
+
+
+try:
+    import _hashlib
+    new = __hash_new
+    __get_hash = __get_openssl_constructor
+except ImportError:
+    new = __py_new
+    __get_hash = __get_builtin_constructor
+
+for __func_name in __always_supported:
+    # try them all, some may not work due to the OpenSSL
+    # version not supporting that algorithm.
+    try:
+        globals()[__func_name] = __get_hash(__func_name)
+    except ValueError:
+        import logging
+        logging.exception('code for hash %s was not found.', __func_name)
+
+# Cleanup locals()
+del __always_supported, __func_name, __get_hash
+del __py_new, __hash_new, __get_openssl_constructor
diff --git a/src/main/resources/PythonLibs/heapq.py b/src/main/resources/PythonLibs/heapq.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca79db15295f49a62eda157937168a5c833dbcf5
--- /dev/null
+++ b/src/main/resources/PythonLibs/heapq.py
@@ -0,0 +1,480 @@
+# -*- coding: latin-1 -*-
+
+"""Heap queue algorithm (a.k.a. priority queue).
+
+Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for
+all k, counting elements from 0.  For the sake of comparison,
+non-existing elements are considered to be infinite.  The interesting
+property of a heap is that a[0] is always its smallest element.
+
+Usage:
+
+heap = []            # creates an empty heap
+heappush(heap, item) # pushes a new item on the heap
+item = heappop(heap) # pops the smallest item from the heap
+item = heap[0]       # smallest item on the heap without popping it
+heapify(x)           # transforms list into a heap, in-place, in linear time
+item = heapreplace(heap, item) # pops and returns smallest item, and adds
+                               # new item; the heap size is unchanged
+
+Our API differs from textbook heap algorithms as follows:
+
+- We use 0-based indexing.  This makes the relationship between the
+  index for a node and the indexes for its children slightly less
+  obvious, but is more suitable since Python uses 0-based indexing.
+
+- Our heappop() method returns the smallest item, not the largest.
+
+These two make it possible to view the heap as a regular Python list
+without surprises: heap[0] is the smallest item, and heap.sort()
+maintains the heap invariant!
+"""
+
+# Original code by Kevin O'Connor, augmented by Tim Peters and Raymond Hettinger
+
+__about__ = """Heap queues
+
+[explanation by François Pinard]
+
+Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for
+all k, counting elements from 0.  For the sake of comparison,
+non-existing elements are considered to be infinite.  The interesting
+property of a heap is that a[0] is always its smallest element.
+
+The strange invariant above is meant to be an efficient memory
+representation for a tournament.  The numbers below are `k', not a[k]:
+
+                                   0
+
+                  1                                 2
+
+          3               4                5               6
+
+      7       8       9       10      11      12      13      14
+
+    15 16   17 18   19 20   21 22   23 24   25 26   27 28   29 30
+
+
+In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'.  In
+an usual binary tournament we see in sports, each cell is the winner
+over the two cells it tops, and we can trace the winner down the tree
+to see all opponents s/he had.  However, in many computer applications
+of such tournaments, we do not need to trace the history of a winner.
+To be more memory efficient, when a winner is promoted, we try to
+replace it by something else at a lower level, and the rule becomes
+that a cell and the two cells it tops contain three different items,
+but the top cell "wins" over the two topped cells.
+
+If this heap invariant is protected at all time, index 0 is clearly
+the overall winner.  The simplest algorithmic way to remove it and
+find the "next" winner is to move some loser (let's say cell 30 in the
+diagram above) into the 0 position, and then percolate this new 0 down
+the tree, exchanging values, until the invariant is re-established.
+This is clearly logarithmic on the total number of items in the tree.
+By iterating over all items, you get an O(n ln n) sort.
+
+A nice feature of this sort is that you can efficiently insert new
+items while the sort is going on, provided that the inserted items are
+not "better" than the last 0'th element you extracted.  This is
+especially useful in simulation contexts, where the tree holds all
+incoming events, and the "win" condition means the smallest scheduled
+time.  When an event schedule other events for execution, they are
+scheduled into the future, so they can easily go into the heap.  So, a
+heap is a good structure for implementing schedulers (this is what I
+used for my MIDI sequencer :-).
+
+Various structures for implementing schedulers have been extensively
+studied, and heaps are good for this, as they are reasonably speedy,
+the speed is almost constant, and the worst case is not much different
+than the average case.  However, there are other representations which
+are more efficient overall, yet the worst cases might be terrible.
+
+Heaps are also very useful in big disk sorts.  You most probably all
+know that a big sort implies producing "runs" (which are pre-sorted
+sequences, which size is usually related to the amount of CPU memory),
+followed by a merging passes for these runs, which merging is often
+very cleverly organised[1].  It is very important that the initial
+sort produces the longest runs possible.  Tournaments are a good way
+to that.  If, using all the memory available to hold a tournament, you
+replace and percolate items that happen to fit the current run, you'll
+produce runs which are twice the size of the memory for random input,
+and much better for input fuzzily ordered.
+
+Moreover, if you output the 0'th item on disk and get an input which
+may not fit in the current tournament (because the value "wins" over
+the last output value), it cannot fit in the heap, so the size of the
+heap decreases.  The freed memory could be cleverly reused immediately
+for progressively building a second heap, which grows at exactly the
+same rate the first heap is melting.  When the first heap completely
+vanishes, you switch heaps and start a new run.  Clever and quite
+effective!
+
+In a word, heaps are useful memory structures to know.  I use them in
+a few applications, and I think it is good to keep a `heap' module
+around. :-)
+
+--------------------
+[1] The disk balancing algorithms which are current, nowadays, are
+more annoying than clever, and this is a consequence of the seeking
+capabilities of the disks.  On devices which cannot seek, like big
+tape drives, the story was quite different, and one had to be very
+clever to ensure (far in advance) that each tape movement will be the
+most effective possible (that is, will best participate at
+"progressing" the merge).  Some tapes were even able to read
+backwards, and this was also used to avoid the rewinding time.
+Believe me, real good tape sorts were quite spectacular to watch!
+From all times, sorting has always been a Great Art! :-)
+"""
+
+__all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge',
+           'nlargest', 'nsmallest', 'heappushpop']
+
+from itertools import islice, count, imap, izip, tee, chain
+from operator import itemgetter
+
+def cmp_lt(x, y):
+    # Use __lt__ if available; otherwise, try __le__.
+    # In Py3.x, only __lt__ will be called.
+    return (x < y) if hasattr(x, '__lt__') else (not y <= x)
+
+def heappush(heap, item):
+    """Push item onto heap, maintaining the heap invariant."""
+    heap.append(item)
+    _siftdown(heap, 0, len(heap)-1)
+
+def heappop(heap):
+    """Pop the smallest item off the heap, maintaining the heap invariant."""
+    lastelt = heap.pop()    # raises appropriate IndexError if heap is empty
+    if heap:
+        returnitem = heap[0]
+        heap[0] = lastelt
+        _siftup(heap, 0)
+    else:
+        returnitem = lastelt
+    return returnitem
+
+def heapreplace(heap, item):
+    """Pop and return the current smallest value, and add the new item.
+
+    This is more efficient than heappop() followed by heappush(), and can be
+    more appropriate when using a fixed-size heap.  Note that the value
+    returned may be larger than item!  That constrains reasonable uses of
+    this routine unless written as part of a conditional replacement:
+
+        if item > heap[0]:
+            item = heapreplace(heap, item)
+    """
+    returnitem = heap[0]    # raises appropriate IndexError if heap is empty
+    heap[0] = item
+    _siftup(heap, 0)
+    return returnitem
+
+def heappushpop(heap, item):
+    """Fast version of a heappush followed by a heappop."""
+    if heap and cmp_lt(heap[0], item):
+        item, heap[0] = heap[0], item
+        _siftup(heap, 0)
+    return item
+
+def heapify(x):
+    """Transform list into a heap, in-place, in O(len(x)) time."""
+    n = len(x)
+    # Transform bottom-up.  The largest index there's any point to looking at
+    # is the largest with a child index in-range, so must have 2*i + 1 < n,
+    # or i < (n-1)/2.  If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so
+    # j-1 is the largest, which is n//2 - 1.  If n is odd = 2*j+1, this is
+    # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1.
+    for i in reversed(xrange(n//2)):
+        _siftup(x, i)
+
+def _heappushpop_max(heap, item):
+    """Maxheap version of a heappush followed by a heappop."""
+    if heap and cmp_lt(item, heap[0]):
+        item, heap[0] = heap[0], item
+        _siftup_max(heap, 0)
+    return item
+
+def _heapify_max(x):
+    """Transform list into a maxheap, in-place, in O(len(x)) time."""
+    n = len(x)
+    for i in reversed(range(n//2)):
+        _siftup_max(x, i)
+
+def nlargest(n, iterable):
+    """Find the n largest elements in a dataset.
+
+    Equivalent to:  sorted(iterable, reverse=True)[:n]
+    """
+    if n < 0:
+        return []
+    it = iter(iterable)
+    result = list(islice(it, n))
+    if not result:
+        return result
+    heapify(result)
+    _heappushpop = heappushpop
+    for elem in it:
+        _heappushpop(result, elem)
+    result.sort(reverse=True)
+    return result
+
+def nsmallest(n, iterable):
+    """Find the n smallest elements in a dataset.
+
+    Equivalent to:  sorted(iterable)[:n]
+    """
+    if n < 0:
+        return []
+    it = iter(iterable)
+    result = list(islice(it, n))
+    if not result:
+        return result
+    _heapify_max(result)
+    _heappushpop = _heappushpop_max
+    for elem in it:
+        _heappushpop(result, elem)
+    result.sort()
+    return result
+
+# 'heap' is a heap at all indices >= startpos, except possibly for pos.  pos
+# is the index of a leaf with a possibly out-of-order value.  Restore the
+# heap invariant.
+def _siftdown(heap, startpos, pos):
+    newitem = heap[pos]
+    # Follow the path to the root, moving parents down until finding a place
+    # newitem fits.
+    while pos > startpos:
+        parentpos = (pos - 1) >> 1
+        parent = heap[parentpos]
+        if cmp_lt(newitem, parent):
+            heap[pos] = parent
+            pos = parentpos
+            continue
+        break
+    heap[pos] = newitem
+
+# The child indices of heap index pos are already heaps, and we want to make
+# a heap at index pos too.  We do this by bubbling the smaller child of
+# pos up (and so on with that child's children, etc) until hitting a leaf,
+# then using _siftdown to move the oddball originally at index pos into place.
+#
+# We *could* break out of the loop as soon as we find a pos where newitem <=
+# both its children, but turns out that's not a good idea, and despite that
+# many books write the algorithm that way.  During a heap pop, the last array
+# element is sifted in, and that tends to be large, so that comparing it
+# against values starting from the root usually doesn't pay (= usually doesn't
+# get us out of the loop early).  See Knuth, Volume 3, where this is
+# explained and quantified in an exercise.
+#
+# Cutting the # of comparisons is important, since these routines have no
+# way to extract "the priority" from an array element, so that intelligence
+# is likely to be hiding in custom __cmp__ methods, or in array elements
+# storing (priority, record) tuples.  Comparisons are thus potentially
+# expensive.
+#
+# On random arrays of length 1000, making this change cut the number of
+# comparisons made by heapify() a little, and those made by exhaustive
+# heappop() a lot, in accord with theory.  Here are typical results from 3
+# runs (3 just to demonstrate how small the variance is):
+#
+# Compares needed by heapify     Compares needed by 1000 heappops
+# --------------------------     --------------------------------
+# 1837 cut to 1663               14996 cut to 8680
+# 1855 cut to 1659               14966 cut to 8678
+# 1847 cut to 1660               15024 cut to 8703
+#
+# Building the heap by using heappush() 1000 times instead required
+# 2198, 2148, and 2219 compares:  heapify() is more efficient, when
+# you can use it.
+#
+# The total compares needed by list.sort() on the same lists were 8627,
+# 8627, and 8632 (this should be compared to the sum of heapify() and
+# heappop() compares):  list.sort() is (unsurprisingly!) more efficient
+# for sorting.
+
+def _siftup(heap, pos):
+    endpos = len(heap)
+    startpos = pos
+    newitem = heap[pos]
+    # Bubble up the smaller child until hitting a leaf.
+    childpos = 2*pos + 1    # leftmost child position
+    while childpos < endpos:
+        # Set childpos to index of smaller child.
+        rightpos = childpos + 1
+        if rightpos < endpos and not cmp_lt(heap[childpos], heap[rightpos]):
+            childpos = rightpos
+        # Move the smaller child up.
+        heap[pos] = heap[childpos]
+        pos = childpos
+        childpos = 2*pos + 1
+    # The leaf at pos is empty now.  Put newitem there, and bubble it up
+    # to its final resting place (by sifting its parents down).
+    heap[pos] = newitem
+    _siftdown(heap, startpos, pos)
+
+def _siftdown_max(heap, startpos, pos):
+    'Maxheap variant of _siftdown'
+    newitem = heap[pos]
+    # Follow the path to the root, moving parents down until finding a place
+    # newitem fits.
+    while pos > startpos:
+        parentpos = (pos - 1) >> 1
+        parent = heap[parentpos]
+        if cmp_lt(parent, newitem):
+            heap[pos] = parent
+            pos = parentpos
+            continue
+        break
+    heap[pos] = newitem
+
+def _siftup_max(heap, pos):
+    'Maxheap variant of _siftup'
+    endpos = len(heap)
+    startpos = pos
+    newitem = heap[pos]
+    # Bubble up the larger child until hitting a leaf.
+    childpos = 2*pos + 1    # leftmost child position
+    while childpos < endpos:
+        # Set childpos to index of larger child.
+        rightpos = childpos + 1
+        if rightpos < endpos and not cmp_lt(heap[rightpos], heap[childpos]):
+            childpos = rightpos
+        # Move the larger child up.
+        heap[pos] = heap[childpos]
+        pos = childpos
+        childpos = 2*pos + 1
+    # The leaf at pos is empty now.  Put newitem there, and bubble it up
+    # to its final resting place (by sifting its parents down).
+    heap[pos] = newitem
+    _siftdown_max(heap, startpos, pos)
+
+# If available, use C implementation
+try:
+    from _heapq import *
+except ImportError:
+    pass
+
+def merge(*iterables):
+    '''Merge multiple sorted inputs into a single sorted output.
+
+    Similar to sorted(itertools.chain(*iterables)) but returns a generator,
+    does not pull the data into memory all at once, and assumes that each of
+    the input streams is already sorted (smallest to largest).
+
+    >>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25]))
+    [0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25]
+
+    '''
+    _heappop, _heapreplace, _StopIteration = heappop, heapreplace, StopIteration
+
+    h = []
+    h_append = h.append
+    for itnum, it in enumerate(map(iter, iterables)):
+        try:
+            next = it.next
+            h_append([next(), itnum, next])
+        except _StopIteration:
+            pass
+    heapify(h)
+
+    while 1:
+        try:
+            while 1:
+                v, itnum, next = s = h[0]   # raises IndexError when h is empty
+                yield v
+                s[0] = next()               # raises StopIteration when exhausted
+                _heapreplace(h, s)          # restore heap condition
+        except _StopIteration:
+            _heappop(h)                     # remove empty iterator
+        except IndexError:
+            return
+
+# Extend the implementations of nsmallest and nlargest to use a key= argument
+_nsmallest = nsmallest
+def nsmallest(n, iterable, key=None):
+    """Find the n smallest elements in a dataset.
+
+    Equivalent to:  sorted(iterable, key=key)[:n]
+    """
+    # Short-cut for n==1 is to use min() when len(iterable)>0
+    if n == 1:
+        it = iter(iterable)
+        head = list(islice(it, 1))
+        if not head:
+            return []
+        if key is None:
+            return [min(chain(head, it))]
+        return [min(chain(head, it), key=key)]
+
+    # When n>=size, it's faster to use sorted()
+    try:
+        size = len(iterable)
+    except (TypeError, AttributeError):
+        pass
+    else:
+        if n >= size:
+            return sorted(iterable, key=key)[:n]
+
+    # When key is none, use simpler decoration
+    if key is None:
+        it = izip(iterable, count())                        # decorate
+        result = _nsmallest(n, it)
+        return map(itemgetter(0), result)                   # undecorate
+
+    # General case, slowest method
+    in1, in2 = tee(iterable)
+    it = izip(imap(key, in1), count(), in2)                 # decorate
+    result = _nsmallest(n, it)
+    return map(itemgetter(2), result)                       # undecorate
+
+_nlargest = nlargest
+def nlargest(n, iterable, key=None):
+    """Find the n largest elements in a dataset.
+
+    Equivalent to:  sorted(iterable, key=key, reverse=True)[:n]
+    """
+
+    # Short-cut for n==1 is to use max() when len(iterable)>0
+    if n == 1:
+        it = iter(iterable)
+        head = list(islice(it, 1))
+        if not head:
+            return []
+        if key is None:
+            return [max(chain(head, it))]
+        return [max(chain(head, it), key=key)]
+
+    # When n>=size, it's faster to use sorted()
+    try:
+        size = len(iterable)
+    except (TypeError, AttributeError):
+        pass
+    else:
+        if n >= size:
+            return sorted(iterable, key=key, reverse=True)[:n]
+
+    # When key is none, use simpler decoration
+    if key is None:
+        it = izip(iterable, count(0,-1))                    # decorate
+        result = _nlargest(n, it)
+        return map(itemgetter(0), result)                   # undecorate
+
+    # General case, slowest method
+    in1, in2 = tee(iterable)
+    it = izip(imap(key, in1), count(0,-1), in2)             # decorate
+    result = _nlargest(n, it)
+    return map(itemgetter(2), result)                       # undecorate
+
+if __name__ == "__main__":
+    # Simple sanity test
+    heap = []
+    data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
+    for item in data:
+        heappush(heap, item)
+    sort = []
+    while heap:
+        sort.append(heappop(heap))
+    print sort
+
+    import doctest
+    doctest.testmod()
diff --git a/src/main/resources/PythonLibs/hmac.py b/src/main/resources/PythonLibs/hmac.py
new file mode 100644
index 0000000000000000000000000000000000000000..538810630cf3ad5a471082e74f0a1e7d990b10c1
--- /dev/null
+++ b/src/main/resources/PythonLibs/hmac.py
@@ -0,0 +1,133 @@
+"""HMAC (Keyed-Hashing for Message Authentication) Python module.
+
+Implements the HMAC algorithm as described by RFC 2104.
+"""
+
+import warnings as _warnings
+
+trans_5C = "".join ([chr (x ^ 0x5C) for x in xrange(256)])
+trans_36 = "".join ([chr (x ^ 0x36) for x in xrange(256)])
+
+# The size of the digests returned by HMAC depends on the underlying
+# hashing module used.  Use digest_size from the instance of HMAC instead.
+digest_size = None
+
+# A unique object passed by HMAC.copy() to the HMAC constructor, in order
+# that the latter return very quickly.  HMAC("") in contrast is quite
+# expensive.
+_secret_backdoor_key = []
+
+class HMAC:
+    """RFC 2104 HMAC class.  Also complies with RFC 4231.
+
+    This supports the API for Cryptographic Hash Functions (PEP 247).
+    """
+    blocksize = 64  # 512-bit HMAC; can be changed in subclasses.
+
+    def __init__(self, key, msg = None, digestmod = None):
+        """Create a new HMAC object.
+
+        key:       key for the keyed hash object.
+        msg:       Initial input for the hash, if provided.
+        digestmod: A module supporting PEP 247.  *OR*
+                   A hashlib constructor returning a new hash object.
+                   Defaults to hashlib.md5.
+        """
+
+        if key is _secret_backdoor_key: # cheap
+            return
+
+        if digestmod is None:
+            import hashlib
+            digestmod = hashlib.md5
+
+        if hasattr(digestmod, '__call__'):
+            self.digest_cons = digestmod
+        else:
+            self.digest_cons = lambda d='': digestmod.new(d)
+
+        self.outer = self.digest_cons()
+        self.inner = self.digest_cons()
+        self.digest_size = self.inner.digest_size
+
+        if hasattr(self.inner, 'block_size'):
+            blocksize = self.inner.block_size
+            if blocksize < 16:
+                # Very low blocksize, most likely a legacy value like
+                # Lib/sha.py and Lib/md5.py have.
+                _warnings.warn('block_size of %d seems too small; using our '
+                               'default of %d.' % (blocksize, self.blocksize),
+                               RuntimeWarning, 2)
+                blocksize = self.blocksize
+        else:
+            _warnings.warn('No block_size attribute on given digest object; '
+                           'Assuming %d.' % (self.blocksize),
+                           RuntimeWarning, 2)
+            blocksize = self.blocksize
+
+        if len(key) > blocksize:
+            key = self.digest_cons(key).digest()
+
+        key = key + chr(0) * (blocksize - len(key))
+        self.outer.update(key.translate(trans_5C))
+        self.inner.update(key.translate(trans_36))
+        if msg is not None:
+            self.update(msg)
+
+##    def clear(self):
+##        raise NotImplementedError, "clear() method not available in HMAC."
+
+    def update(self, msg):
+        """Update this hashing object with the string msg.
+        """
+        self.inner.update(msg)
+
+    def copy(self):
+        """Return a separate copy of this hashing object.
+
+        An update to this copy won't affect the original object.
+        """
+        other = self.__class__(_secret_backdoor_key)
+        other.digest_cons = self.digest_cons
+        other.digest_size = self.digest_size
+        other.inner = self.inner.copy()
+        other.outer = self.outer.copy()
+        return other
+
+    def _current(self):
+        """Return a hash object for the current state.
+
+        To be used only internally with digest() and hexdigest().
+        """
+        h = self.outer.copy()
+        h.update(self.inner.digest())
+        return h
+
+    def digest(self):
+        """Return the hash value of this hashing object.
+
+        This returns a string containing 8-bit data.  The object is
+        not altered in any way by this function; you can continue
+        updating the object after calling this function.
+        """
+        h = self._current()
+        return h.digest()
+
+    def hexdigest(self):
+        """Like digest(), but returns a string of hexadecimal digits instead.
+        """
+        h = self._current()
+        return h.hexdigest()
+
+def new(key, msg = None, digestmod = None):
+    """Create a new hashing object and return it.
+
+    key: The starting key for the hash.
+    msg: if available, will immediately be hashed into the object's starting
+    state.
+
+    You can now feed arbitrary strings into the object using its update()
+    method, and can ask for the hash value at any time by calling its digest()
+    method.
+    """
+    return HMAC(key, msg, digestmod)
diff --git a/src/main/resources/PythonLibs/htmlentitydefs.py b/src/main/resources/PythonLibs/htmlentitydefs.py
new file mode 100644
index 0000000000000000000000000000000000000000..3dd14a79fab855c089b94d6d03902dfb61847c75
--- /dev/null
+++ b/src/main/resources/PythonLibs/htmlentitydefs.py
@@ -0,0 +1,273 @@
+"""HTML character entity references."""
+
+# maps the HTML entity name to the Unicode codepoint
+name2codepoint = {
+    'AElig':    0x00c6, # latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1
+    'Aacute':   0x00c1, # latin capital letter A with acute, U+00C1 ISOlat1
+    'Acirc':    0x00c2, # latin capital letter A with circumflex, U+00C2 ISOlat1
+    'Agrave':   0x00c0, # latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1
+    'Alpha':    0x0391, # greek capital letter alpha, U+0391
+    'Aring':    0x00c5, # latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1
+    'Atilde':   0x00c3, # latin capital letter A with tilde, U+00C3 ISOlat1
+    'Auml':     0x00c4, # latin capital letter A with diaeresis, U+00C4 ISOlat1
+    'Beta':     0x0392, # greek capital letter beta, U+0392
+    'Ccedil':   0x00c7, # latin capital letter C with cedilla, U+00C7 ISOlat1
+    'Chi':      0x03a7, # greek capital letter chi, U+03A7
+    'Dagger':   0x2021, # double dagger, U+2021 ISOpub
+    'Delta':    0x0394, # greek capital letter delta, U+0394 ISOgrk3
+    'ETH':      0x00d0, # latin capital letter ETH, U+00D0 ISOlat1
+    'Eacute':   0x00c9, # latin capital letter E with acute, U+00C9 ISOlat1
+    'Ecirc':    0x00ca, # latin capital letter E with circumflex, U+00CA ISOlat1
+    'Egrave':   0x00c8, # latin capital letter E with grave, U+00C8 ISOlat1
+    'Epsilon':  0x0395, # greek capital letter epsilon, U+0395
+    'Eta':      0x0397, # greek capital letter eta, U+0397
+    'Euml':     0x00cb, # latin capital letter E with diaeresis, U+00CB ISOlat1
+    'Gamma':    0x0393, # greek capital letter gamma, U+0393 ISOgrk3
+    'Iacute':   0x00cd, # latin capital letter I with acute, U+00CD ISOlat1
+    'Icirc':    0x00ce, # latin capital letter I with circumflex, U+00CE ISOlat1
+    'Igrave':   0x00cc, # latin capital letter I with grave, U+00CC ISOlat1
+    'Iota':     0x0399, # greek capital letter iota, U+0399
+    'Iuml':     0x00cf, # latin capital letter I with diaeresis, U+00CF ISOlat1
+    'Kappa':    0x039a, # greek capital letter kappa, U+039A
+    'Lambda':   0x039b, # greek capital letter lambda, U+039B ISOgrk3
+    'Mu':       0x039c, # greek capital letter mu, U+039C
+    'Ntilde':   0x00d1, # latin capital letter N with tilde, U+00D1 ISOlat1
+    'Nu':       0x039d, # greek capital letter nu, U+039D
+    'OElig':    0x0152, # latin capital ligature OE, U+0152 ISOlat2
+    'Oacute':   0x00d3, # latin capital letter O with acute, U+00D3 ISOlat1
+    'Ocirc':    0x00d4, # latin capital letter O with circumflex, U+00D4 ISOlat1
+    'Ograve':   0x00d2, # latin capital letter O with grave, U+00D2 ISOlat1
+    'Omega':    0x03a9, # greek capital letter omega, U+03A9 ISOgrk3
+    'Omicron':  0x039f, # greek capital letter omicron, U+039F
+    'Oslash':   0x00d8, # latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1
+    'Otilde':   0x00d5, # latin capital letter O with tilde, U+00D5 ISOlat1
+    'Ouml':     0x00d6, # latin capital letter O with diaeresis, U+00D6 ISOlat1
+    'Phi':      0x03a6, # greek capital letter phi, U+03A6 ISOgrk3
+    'Pi':       0x03a0, # greek capital letter pi, U+03A0 ISOgrk3
+    'Prime':    0x2033, # double prime = seconds = inches, U+2033 ISOtech
+    'Psi':      0x03a8, # greek capital letter psi, U+03A8 ISOgrk3
+    'Rho':      0x03a1, # greek capital letter rho, U+03A1
+    'Scaron':   0x0160, # latin capital letter S with caron, U+0160 ISOlat2
+    'Sigma':    0x03a3, # greek capital letter sigma, U+03A3 ISOgrk3
+    'THORN':    0x00de, # latin capital letter THORN, U+00DE ISOlat1
+    'Tau':      0x03a4, # greek capital letter tau, U+03A4
+    'Theta':    0x0398, # greek capital letter theta, U+0398 ISOgrk3
+    'Uacute':   0x00da, # latin capital letter U with acute, U+00DA ISOlat1
+    'Ucirc':    0x00db, # latin capital letter U with circumflex, U+00DB ISOlat1
+    'Ugrave':   0x00d9, # latin capital letter U with grave, U+00D9 ISOlat1
+    'Upsilon':  0x03a5, # greek capital letter upsilon, U+03A5 ISOgrk3
+    'Uuml':     0x00dc, # latin capital letter U with diaeresis, U+00DC ISOlat1
+    'Xi':       0x039e, # greek capital letter xi, U+039E ISOgrk3
+    'Yacute':   0x00dd, # latin capital letter Y with acute, U+00DD ISOlat1
+    'Yuml':     0x0178, # latin capital letter Y with diaeresis, U+0178 ISOlat2
+    'Zeta':     0x0396, # greek capital letter zeta, U+0396
+    'aacute':   0x00e1, # latin small letter a with acute, U+00E1 ISOlat1
+    'acirc':    0x00e2, # latin small letter a with circumflex, U+00E2 ISOlat1
+    'acute':    0x00b4, # acute accent = spacing acute, U+00B4 ISOdia
+    'aelig':    0x00e6, # latin small letter ae = latin small ligature ae, U+00E6 ISOlat1
+    'agrave':   0x00e0, # latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1
+    'alefsym':  0x2135, # alef symbol = first transfinite cardinal, U+2135 NEW
+    'alpha':    0x03b1, # greek small letter alpha, U+03B1 ISOgrk3
+    'amp':      0x0026, # ampersand, U+0026 ISOnum
+    'and':      0x2227, # logical and = wedge, U+2227 ISOtech
+    'ang':      0x2220, # angle, U+2220 ISOamso
+    'aring':    0x00e5, # latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1
+    'asymp':    0x2248, # almost equal to = asymptotic to, U+2248 ISOamsr
+    'atilde':   0x00e3, # latin small letter a with tilde, U+00E3 ISOlat1
+    'auml':     0x00e4, # latin small letter a with diaeresis, U+00E4 ISOlat1
+    'bdquo':    0x201e, # double low-9 quotation mark, U+201E NEW
+    'beta':     0x03b2, # greek small letter beta, U+03B2 ISOgrk3
+    'brvbar':   0x00a6, # broken bar = broken vertical bar, U+00A6 ISOnum
+    'bull':     0x2022, # bullet = black small circle, U+2022 ISOpub
+    'cap':      0x2229, # intersection = cap, U+2229 ISOtech
+    'ccedil':   0x00e7, # latin small letter c with cedilla, U+00E7 ISOlat1
+    'cedil':    0x00b8, # cedilla = spacing cedilla, U+00B8 ISOdia
+    'cent':     0x00a2, # cent sign, U+00A2 ISOnum
+    'chi':      0x03c7, # greek small letter chi, U+03C7 ISOgrk3
+    'circ':     0x02c6, # modifier letter circumflex accent, U+02C6 ISOpub
+    'clubs':    0x2663, # black club suit = shamrock, U+2663 ISOpub
+    'cong':     0x2245, # approximately equal to, U+2245 ISOtech
+    'copy':     0x00a9, # copyright sign, U+00A9 ISOnum
+    'crarr':    0x21b5, # downwards arrow with corner leftwards = carriage return, U+21B5 NEW
+    'cup':      0x222a, # union = cup, U+222A ISOtech
+    'curren':   0x00a4, # currency sign, U+00A4 ISOnum
+    'dArr':     0x21d3, # downwards double arrow, U+21D3 ISOamsa
+    'dagger':   0x2020, # dagger, U+2020 ISOpub
+    'darr':     0x2193, # downwards arrow, U+2193 ISOnum
+    'deg':      0x00b0, # degree sign, U+00B0 ISOnum
+    'delta':    0x03b4, # greek small letter delta, U+03B4 ISOgrk3
+    'diams':    0x2666, # black diamond suit, U+2666 ISOpub
+    'divide':   0x00f7, # division sign, U+00F7 ISOnum
+    'eacute':   0x00e9, # latin small letter e with acute, U+00E9 ISOlat1
+    'ecirc':    0x00ea, # latin small letter e with circumflex, U+00EA ISOlat1
+    'egrave':   0x00e8, # latin small letter e with grave, U+00E8 ISOlat1
+    'empty':    0x2205, # empty set = null set = diameter, U+2205 ISOamso
+    'emsp':     0x2003, # em space, U+2003 ISOpub
+    'ensp':     0x2002, # en space, U+2002 ISOpub
+    'epsilon':  0x03b5, # greek small letter epsilon, U+03B5 ISOgrk3
+    'equiv':    0x2261, # identical to, U+2261 ISOtech
+    'eta':      0x03b7, # greek small letter eta, U+03B7 ISOgrk3
+    'eth':      0x00f0, # latin small letter eth, U+00F0 ISOlat1
+    'euml':     0x00eb, # latin small letter e with diaeresis, U+00EB ISOlat1
+    'euro':     0x20ac, # euro sign, U+20AC NEW
+    'exist':    0x2203, # there exists, U+2203 ISOtech
+    'fnof':     0x0192, # latin small f with hook = function = florin, U+0192 ISOtech
+    'forall':   0x2200, # for all, U+2200 ISOtech
+    'frac12':   0x00bd, # vulgar fraction one half = fraction one half, U+00BD ISOnum
+    'frac14':   0x00bc, # vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum
+    'frac34':   0x00be, # vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum
+    'frasl':    0x2044, # fraction slash, U+2044 NEW
+    'gamma':    0x03b3, # greek small letter gamma, U+03B3 ISOgrk3
+    'ge':       0x2265, # greater-than or equal to, U+2265 ISOtech
+    'gt':       0x003e, # greater-than sign, U+003E ISOnum
+    'hArr':     0x21d4, # left right double arrow, U+21D4 ISOamsa
+    'harr':     0x2194, # left right arrow, U+2194 ISOamsa
+    'hearts':   0x2665, # black heart suit = valentine, U+2665 ISOpub
+    'hellip':   0x2026, # horizontal ellipsis = three dot leader, U+2026 ISOpub
+    'iacute':   0x00ed, # latin small letter i with acute, U+00ED ISOlat1
+    'icirc':    0x00ee, # latin small letter i with circumflex, U+00EE ISOlat1
+    'iexcl':    0x00a1, # inverted exclamation mark, U+00A1 ISOnum
+    'igrave':   0x00ec, # latin small letter i with grave, U+00EC ISOlat1
+    'image':    0x2111, # blackletter capital I = imaginary part, U+2111 ISOamso
+    'infin':    0x221e, # infinity, U+221E ISOtech
+    'int':      0x222b, # integral, U+222B ISOtech
+    'iota':     0x03b9, # greek small letter iota, U+03B9 ISOgrk3
+    'iquest':   0x00bf, # inverted question mark = turned question mark, U+00BF ISOnum
+    'isin':     0x2208, # element of, U+2208 ISOtech
+    'iuml':     0x00ef, # latin small letter i with diaeresis, U+00EF ISOlat1
+    'kappa':    0x03ba, # greek small letter kappa, U+03BA ISOgrk3
+    'lArr':     0x21d0, # leftwards double arrow, U+21D0 ISOtech
+    'lambda':   0x03bb, # greek small letter lambda, U+03BB ISOgrk3
+    'lang':     0x2329, # left-pointing angle bracket = bra, U+2329 ISOtech
+    'laquo':    0x00ab, # left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum
+    'larr':     0x2190, # leftwards arrow, U+2190 ISOnum
+    'lceil':    0x2308, # left ceiling = apl upstile, U+2308 ISOamsc
+    'ldquo':    0x201c, # left double quotation mark, U+201C ISOnum
+    'le':       0x2264, # less-than or equal to, U+2264 ISOtech
+    'lfloor':   0x230a, # left floor = apl downstile, U+230A ISOamsc
+    'lowast':   0x2217, # asterisk operator, U+2217 ISOtech
+    'loz':      0x25ca, # lozenge, U+25CA ISOpub
+    'lrm':      0x200e, # left-to-right mark, U+200E NEW RFC 2070
+    'lsaquo':   0x2039, # single left-pointing angle quotation mark, U+2039 ISO proposed
+    'lsquo':    0x2018, # left single quotation mark, U+2018 ISOnum
+    'lt':       0x003c, # less-than sign, U+003C ISOnum
+    'macr':     0x00af, # macron = spacing macron = overline = APL overbar, U+00AF ISOdia
+    'mdash':    0x2014, # em dash, U+2014 ISOpub
+    'micro':    0x00b5, # micro sign, U+00B5 ISOnum
+    'middot':   0x00b7, # middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum
+    'minus':    0x2212, # minus sign, U+2212 ISOtech
+    'mu':       0x03bc, # greek small letter mu, U+03BC ISOgrk3
+    'nabla':    0x2207, # nabla = backward difference, U+2207 ISOtech
+    'nbsp':     0x00a0, # no-break space = non-breaking space, U+00A0 ISOnum
+    'ndash':    0x2013, # en dash, U+2013 ISOpub
+    'ne':       0x2260, # not equal to, U+2260 ISOtech
+    'ni':       0x220b, # contains as member, U+220B ISOtech
+    'not':      0x00ac, # not sign, U+00AC ISOnum
+    'notin':    0x2209, # not an element of, U+2209 ISOtech
+    'nsub':     0x2284, # not a subset of, U+2284 ISOamsn
+    'ntilde':   0x00f1, # latin small letter n with tilde, U+00F1 ISOlat1
+    'nu':       0x03bd, # greek small letter nu, U+03BD ISOgrk3
+    'oacute':   0x00f3, # latin small letter o with acute, U+00F3 ISOlat1
+    'ocirc':    0x00f4, # latin small letter o with circumflex, U+00F4 ISOlat1
+    'oelig':    0x0153, # latin small ligature oe, U+0153 ISOlat2
+    'ograve':   0x00f2, # latin small letter o with grave, U+00F2 ISOlat1
+    'oline':    0x203e, # overline = spacing overscore, U+203E NEW
+    'omega':    0x03c9, # greek small letter omega, U+03C9 ISOgrk3
+    'omicron':  0x03bf, # greek small letter omicron, U+03BF NEW
+    'oplus':    0x2295, # circled plus = direct sum, U+2295 ISOamsb
+    'or':       0x2228, # logical or = vee, U+2228 ISOtech
+    'ordf':     0x00aa, # feminine ordinal indicator, U+00AA ISOnum
+    'ordm':     0x00ba, # masculine ordinal indicator, U+00BA ISOnum
+    'oslash':   0x00f8, # latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1
+    'otilde':   0x00f5, # latin small letter o with tilde, U+00F5 ISOlat1
+    'otimes':   0x2297, # circled times = vector product, U+2297 ISOamsb
+    'ouml':     0x00f6, # latin small letter o with diaeresis, U+00F6 ISOlat1
+    'para':     0x00b6, # pilcrow sign = paragraph sign, U+00B6 ISOnum
+    'part':     0x2202, # partial differential, U+2202 ISOtech
+    'permil':   0x2030, # per mille sign, U+2030 ISOtech
+    'perp':     0x22a5, # up tack = orthogonal to = perpendicular, U+22A5 ISOtech
+    'phi':      0x03c6, # greek small letter phi, U+03C6 ISOgrk3
+    'pi':       0x03c0, # greek small letter pi, U+03C0 ISOgrk3
+    'piv':      0x03d6, # greek pi symbol, U+03D6 ISOgrk3
+    'plusmn':   0x00b1, # plus-minus sign = plus-or-minus sign, U+00B1 ISOnum
+    'pound':    0x00a3, # pound sign, U+00A3 ISOnum
+    'prime':    0x2032, # prime = minutes = feet, U+2032 ISOtech
+    'prod':     0x220f, # n-ary product = product sign, U+220F ISOamsb
+    'prop':     0x221d, # proportional to, U+221D ISOtech
+    'psi':      0x03c8, # greek small letter psi, U+03C8 ISOgrk3
+    'quot':     0x0022, # quotation mark = APL quote, U+0022 ISOnum
+    'rArr':     0x21d2, # rightwards double arrow, U+21D2 ISOtech
+    'radic':    0x221a, # square root = radical sign, U+221A ISOtech
+    'rang':     0x232a, # right-pointing angle bracket = ket, U+232A ISOtech
+    'raquo':    0x00bb, # right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum
+    'rarr':     0x2192, # rightwards arrow, U+2192 ISOnum
+    'rceil':    0x2309, # right ceiling, U+2309 ISOamsc
+    'rdquo':    0x201d, # right double quotation mark, U+201D ISOnum
+    'real':     0x211c, # blackletter capital R = real part symbol, U+211C ISOamso
+    'reg':      0x00ae, # registered sign = registered trade mark sign, U+00AE ISOnum
+    'rfloor':   0x230b, # right floor, U+230B ISOamsc
+    'rho':      0x03c1, # greek small letter rho, U+03C1 ISOgrk3
+    'rlm':      0x200f, # right-to-left mark, U+200F NEW RFC 2070
+    'rsaquo':   0x203a, # single right-pointing angle quotation mark, U+203A ISO proposed
+    'rsquo':    0x2019, # right single quotation mark, U+2019 ISOnum
+    'sbquo':    0x201a, # single low-9 quotation mark, U+201A NEW
+    'scaron':   0x0161, # latin small letter s with caron, U+0161 ISOlat2
+    'sdot':     0x22c5, # dot operator, U+22C5 ISOamsb
+    'sect':     0x00a7, # section sign, U+00A7 ISOnum
+    'shy':      0x00ad, # soft hyphen = discretionary hyphen, U+00AD ISOnum
+    'sigma':    0x03c3, # greek small letter sigma, U+03C3 ISOgrk3
+    'sigmaf':   0x03c2, # greek small letter final sigma, U+03C2 ISOgrk3
+    'sim':      0x223c, # tilde operator = varies with = similar to, U+223C ISOtech
+    'spades':   0x2660, # black spade suit, U+2660 ISOpub
+    'sub':      0x2282, # subset of, U+2282 ISOtech
+    'sube':     0x2286, # subset of or equal to, U+2286 ISOtech
+    'sum':      0x2211, # n-ary sumation, U+2211 ISOamsb
+    'sup':      0x2283, # superset of, U+2283 ISOtech
+    'sup1':     0x00b9, # superscript one = superscript digit one, U+00B9 ISOnum
+    'sup2':     0x00b2, # superscript two = superscript digit two = squared, U+00B2 ISOnum
+    'sup3':     0x00b3, # superscript three = superscript digit three = cubed, U+00B3 ISOnum
+    'supe':     0x2287, # superset of or equal to, U+2287 ISOtech
+    'szlig':    0x00df, # latin small letter sharp s = ess-zed, U+00DF ISOlat1
+    'tau':      0x03c4, # greek small letter tau, U+03C4 ISOgrk3
+    'there4':   0x2234, # therefore, U+2234 ISOtech
+    'theta':    0x03b8, # greek small letter theta, U+03B8 ISOgrk3
+    'thetasym': 0x03d1, # greek small letter theta symbol, U+03D1 NEW
+    'thinsp':   0x2009, # thin space, U+2009 ISOpub
+    'thorn':    0x00fe, # latin small letter thorn with, U+00FE ISOlat1
+    'tilde':    0x02dc, # small tilde, U+02DC ISOdia
+    'times':    0x00d7, # multiplication sign, U+00D7 ISOnum
+    'trade':    0x2122, # trade mark sign, U+2122 ISOnum
+    'uArr':     0x21d1, # upwards double arrow, U+21D1 ISOamsa
+    'uacute':   0x00fa, # latin small letter u with acute, U+00FA ISOlat1
+    'uarr':     0x2191, # upwards arrow, U+2191 ISOnum
+    'ucirc':    0x00fb, # latin small letter u with circumflex, U+00FB ISOlat1
+    'ugrave':   0x00f9, # latin small letter u with grave, U+00F9 ISOlat1
+    'uml':      0x00a8, # diaeresis = spacing diaeresis, U+00A8 ISOdia
+    'upsih':    0x03d2, # greek upsilon with hook symbol, U+03D2 NEW
+    'upsilon':  0x03c5, # greek small letter upsilon, U+03C5 ISOgrk3
+    'uuml':     0x00fc, # latin small letter u with diaeresis, U+00FC ISOlat1
+    'weierp':   0x2118, # script capital P = power set = Weierstrass p, U+2118 ISOamso
+    'xi':       0x03be, # greek small letter xi, U+03BE ISOgrk3
+    'yacute':   0x00fd, # latin small letter y with acute, U+00FD ISOlat1
+    'yen':      0x00a5, # yen sign = yuan sign, U+00A5 ISOnum
+    'yuml':     0x00ff, # latin small letter y with diaeresis, U+00FF ISOlat1
+    'zeta':     0x03b6, # greek small letter zeta, U+03B6 ISOgrk3
+    'zwj':      0x200d, # zero width joiner, U+200D NEW RFC 2070
+    'zwnj':     0x200c, # zero width non-joiner, U+200C NEW RFC 2070
+}
+
+# maps the Unicode codepoint to the HTML entity name
+codepoint2name = {}
+
+# maps the HTML entity name to the character
+# (or a character reference if the character is outside the Latin-1 range)
+entitydefs = {}
+
+for (name, codepoint) in name2codepoint.iteritems():
+    codepoint2name[codepoint] = name
+    if codepoint <= 0xff:
+        entitydefs[name] = chr(codepoint)
+    else:
+        entitydefs[name] = '&#%d;' % codepoint
+
+del name, codepoint
diff --git a/src/main/resources/PythonLibs/htmllib.py b/src/main/resources/PythonLibs/htmllib.py
new file mode 100644
index 0000000000000000000000000000000000000000..44647dbf026c054c563a78dee19020927cfd5d88
--- /dev/null
+++ b/src/main/resources/PythonLibs/htmllib.py
@@ -0,0 +1,491 @@
+"""HTML 2.0 parser.
+
+See the HTML 2.0 specification:
+http://www.w3.org/hypertext/WWW/MarkUp/html-spec/html-spec_toc.html
+"""
+
+from warnings import warnpy3k
+warnpy3k("the htmllib module has been removed in Python 3.0",
+         stacklevel=2)
+del warnpy3k
+
+import sgmllib
+
+from formatter import AS_IS
+
+__all__ = ["HTMLParser", "HTMLParseError"]
+
+
+class HTMLParseError(sgmllib.SGMLParseError):
+    """Error raised when an HTML document can't be parsed."""
+
+
+class HTMLParser(sgmllib.SGMLParser):
+    """This is the basic HTML parser class.
+
+    It supports all entity names required by the XHTML 1.0 Recommendation.
+    It also defines handlers for all HTML 2.0 and many HTML 3.0 and 3.2
+    elements.
+
+    """
+
+    from htmlentitydefs import entitydefs
+
+    def __init__(self, formatter, verbose=0):
+        """Creates an instance of the HTMLParser class.
+
+        The formatter parameter is the formatter instance associated with
+        the parser.
+
+        """
+        sgmllib.SGMLParser.__init__(self, verbose)
+        self.formatter = formatter
+
+    def error(self, message):
+        raise HTMLParseError(message)
+
+    def reset(self):
+        sgmllib.SGMLParser.reset(self)
+        self.savedata = None
+        self.isindex = 0
+        self.title = None
+        self.base = None
+        self.anchor = None
+        self.anchorlist = []
+        self.nofill = 0
+        self.list_stack = []
+
+    # ------ Methods used internally; some may be overridden
+
+    # --- Formatter interface, taking care of 'savedata' mode;
+    # shouldn't need to be overridden
+
+    def handle_data(self, data):
+        if self.savedata is not None:
+            self.savedata = self.savedata + data
+        else:
+            if self.nofill:
+                self.formatter.add_literal_data(data)
+            else:
+                self.formatter.add_flowing_data(data)
+
+    # --- Hooks to save data; shouldn't need to be overridden
+
+    def save_bgn(self):
+        """Begins saving character data in a buffer instead of sending it
+        to the formatter object.
+
+        Retrieve the stored data via the save_end() method.  Use of the
+        save_bgn() / save_end() pair may not be nested.
+
+        """
+        self.savedata = ''
+
+    def save_end(self):
+        """Ends buffering character data and returns all data saved since
+        the preceding call to the save_bgn() method.
+
+        If the nofill flag is false, whitespace is collapsed to single
+        spaces.  A call to this method without a preceding call to the
+        save_bgn() method will raise a TypeError exception.
+
+        """
+        data = self.savedata
+        self.savedata = None
+        if not self.nofill:
+            data = ' '.join(data.split())
+        return data
+
+    # --- Hooks for anchors; should probably be overridden
+
+    def anchor_bgn(self, href, name, type):
+        """This method is called at the start of an anchor region.
+
+        The arguments correspond to the attributes of the <A> tag with
+        the same names.  The default implementation maintains a list of
+        hyperlinks (defined by the HREF attribute for <A> tags) within
+        the document.  The list of hyperlinks is available as the data
+        attribute anchorlist.
+
+        """
+        self.anchor = href
+        if self.anchor:
+            self.anchorlist.append(href)
+
+    def anchor_end(self):
+        """This method is called at the end of an anchor region.
+
+        The default implementation adds a textual footnote marker using an
+        index into the list of hyperlinks created by the anchor_bgn()method.
+
+        """
+        if self.anchor:
+            self.handle_data("[%d]" % len(self.anchorlist))
+            self.anchor = None
+
+    # --- Hook for images; should probably be overridden
+
+    def handle_image(self, src, alt, *args):
+        """This method is called to handle images.
+
+        The default implementation simply passes the alt value to the
+        handle_data() method.
+
+        """
+        self.handle_data(alt)
+
+    # --------- Top level elememts
+
+    def start_html(self, attrs): pass
+    def end_html(self): pass
+
+    def start_head(self, attrs): pass
+    def end_head(self): pass
+
+    def start_body(self, attrs): pass
+    def end_body(self): pass
+
+    # ------ Head elements
+
+    def start_title(self, attrs):
+        self.save_bgn()
+
+    def end_title(self):
+        self.title = self.save_end()
+
+    def do_base(self, attrs):
+        for a, v in attrs:
+            if a == 'href':
+                self.base = v
+
+    def do_isindex(self, attrs):
+        self.isindex = 1
+
+    def do_link(self, attrs):
+        pass
+
+    def do_meta(self, attrs):
+        pass
+
+    def do_nextid(self, attrs): # Deprecated
+        pass
+
+    # ------ Body elements
+
+    # --- Headings
+
+    def start_h1(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.formatter.push_font(('h1', 0, 1, 0))
+
+    def end_h1(self):
+        self.formatter.end_paragraph(1)
+        self.formatter.pop_font()
+
+    def start_h2(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.formatter.push_font(('h2', 0, 1, 0))
+
+    def end_h2(self):
+        self.formatter.end_paragraph(1)
+        self.formatter.pop_font()
+
+    def start_h3(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.formatter.push_font(('h3', 0, 1, 0))
+
+    def end_h3(self):
+        self.formatter.end_paragraph(1)
+        self.formatter.pop_font()
+
+    def start_h4(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.formatter.push_font(('h4', 0, 1, 0))
+
+    def end_h4(self):
+        self.formatter.end_paragraph(1)
+        self.formatter.pop_font()
+
+    def start_h5(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.formatter.push_font(('h5', 0, 1, 0))
+
+    def end_h5(self):
+        self.formatter.end_paragraph(1)
+        self.formatter.pop_font()
+
+    def start_h6(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.formatter.push_font(('h6', 0, 1, 0))
+
+    def end_h6(self):
+        self.formatter.end_paragraph(1)
+        self.formatter.pop_font()
+
+    # --- Block Structuring Elements
+
+    def do_p(self, attrs):
+        self.formatter.end_paragraph(1)
+
+    def start_pre(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.formatter.push_font((AS_IS, AS_IS, AS_IS, 1))
+        self.nofill = self.nofill + 1
+
+    def end_pre(self):
+        self.formatter.end_paragraph(1)
+        self.formatter.pop_font()
+        self.nofill = max(0, self.nofill - 1)
+
+    def start_xmp(self, attrs):
+        self.start_pre(attrs)
+        self.setliteral('xmp') # Tell SGML parser
+
+    def end_xmp(self):
+        self.end_pre()
+
+    def start_listing(self, attrs):
+        self.start_pre(attrs)
+        self.setliteral('listing') # Tell SGML parser
+
+    def end_listing(self):
+        self.end_pre()
+
+    def start_address(self, attrs):
+        self.formatter.end_paragraph(0)
+        self.formatter.push_font((AS_IS, 1, AS_IS, AS_IS))
+
+    def end_address(self):
+        self.formatter.end_paragraph(0)
+        self.formatter.pop_font()
+
+    def start_blockquote(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.formatter.push_margin('blockquote')
+
+    def end_blockquote(self):
+        self.formatter.end_paragraph(1)
+        self.formatter.pop_margin()
+
+    # --- List Elements
+
+    def start_ul(self, attrs):
+        self.formatter.end_paragraph(not self.list_stack)
+        self.formatter.push_margin('ul')
+        self.list_stack.append(['ul', '*', 0])
+
+    def end_ul(self):
+        if self.list_stack: del self.list_stack[-1]
+        self.formatter.end_paragraph(not self.list_stack)
+        self.formatter.pop_margin()
+
+    def do_li(self, attrs):
+        self.formatter.end_paragraph(0)
+        if self.list_stack:
+            [dummy, label, counter] = top = self.list_stack[-1]
+            top[2] = counter = counter+1
+        else:
+            label, counter = '*', 0
+        self.formatter.add_label_data(label, counter)
+
+    def start_ol(self, attrs):
+        self.formatter.end_paragraph(not self.list_stack)
+        self.formatter.push_margin('ol')
+        label = '1.'
+        for a, v in attrs:
+            if a == 'type':
+                if len(v) == 1: v = v + '.'
+                label = v
+        self.list_stack.append(['ol', label, 0])
+
+    def end_ol(self):
+        if self.list_stack: del self.list_stack[-1]
+        self.formatter.end_paragraph(not self.list_stack)
+        self.formatter.pop_margin()
+
+    def start_menu(self, attrs):
+        self.start_ul(attrs)
+
+    def end_menu(self):
+        self.end_ul()
+
+    def start_dir(self, attrs):
+        self.start_ul(attrs)
+
+    def end_dir(self):
+        self.end_ul()
+
+    def start_dl(self, attrs):
+        self.formatter.end_paragraph(1)
+        self.list_stack.append(['dl', '', 0])
+
+    def end_dl(self):
+        self.ddpop(1)
+        if self.list_stack: del self.list_stack[-1]
+
+    def do_dt(self, attrs):
+        self.ddpop()
+
+    def do_dd(self, attrs):
+        self.ddpop()
+        self.formatter.push_margin('dd')
+        self.list_stack.append(['dd', '', 0])
+
+    def ddpop(self, bl=0):
+        self.formatter.end_paragraph(bl)
+        if self.list_stack:
+            if self.list_stack[-1][0] == 'dd':
+                del self.list_stack[-1]
+                self.formatter.pop_margin()
+
+    # --- Phrase Markup
+
+    # Idiomatic Elements
+
+    def start_cite(self, attrs): self.start_i(attrs)
+    def end_cite(self): self.end_i()
+
+    def start_code(self, attrs): self.start_tt(attrs)
+    def end_code(self): self.end_tt()
+
+    def start_em(self, attrs): self.start_i(attrs)
+    def end_em(self): self.end_i()
+
+    def start_kbd(self, attrs): self.start_tt(attrs)
+    def end_kbd(self): self.end_tt()
+
+    def start_samp(self, attrs): self.start_tt(attrs)
+    def end_samp(self): self.end_tt()
+
+    def start_strong(self, attrs): self.start_b(attrs)
+    def end_strong(self): self.end_b()
+
+    def start_var(self, attrs): self.start_i(attrs)
+    def end_var(self): self.end_i()
+
+    # Typographic Elements
+
+    def start_i(self, attrs):
+        self.formatter.push_font((AS_IS, 1, AS_IS, AS_IS))
+    def end_i(self):
+        self.formatter.pop_font()
+
+    def start_b(self, attrs):
+        self.formatter.push_font((AS_IS, AS_IS, 1, AS_IS))
+    def end_b(self):
+        self.formatter.pop_font()
+
+    def start_tt(self, attrs):
+        self.formatter.push_font((AS_IS, AS_IS, AS_IS, 1))
+    def end_tt(self):
+        self.formatter.pop_font()
+
+    def start_a(self, attrs):
+        href = ''
+        name = ''
+        type = ''
+        for attrname, value in attrs:
+            value = value.strip()
+            if attrname == 'href':
+                href = value
+            if attrname == 'name':
+                name = value
+            if attrname == 'type':
+                type = value.lower()
+        self.anchor_bgn(href, name, type)
+
+    def end_a(self):
+        self.anchor_end()
+
+    # --- Line Break
+
+    def do_br(self, attrs):
+        self.formatter.add_line_break()
+
+    # --- Horizontal Rule
+
+    def do_hr(self, attrs):
+        self.formatter.add_hor_rule()
+
+    # --- Image
+
+    def do_img(self, attrs):
+        align = ''
+        alt = '(image)'
+        ismap = ''
+        src = ''
+        width = 0
+        height = 0
+        for attrname, value in attrs:
+            if attrname == 'align':
+                align = value
+            if attrname == 'alt':
+                alt = value
+            if attrname == 'ismap':
+                ismap = value
+            if attrname == 'src':
+                src = value
+            if attrname == 'width':
+                try: width = int(value)
+                except ValueError: pass
+            if attrname == 'height':
+                try: height = int(value)
+                except ValueError: pass
+        self.handle_image(src, alt, ismap, align, width, height)
+
+    # --- Really Old Unofficial Deprecated Stuff
+
+    def do_plaintext(self, attrs):
+        self.start_pre(attrs)
+        self.setnomoretags() # Tell SGML parser
+
+    # --- Unhandled tags
+
+    def unknown_starttag(self, tag, attrs):
+        pass
+
+    def unknown_endtag(self, tag):
+        pass
+
+
+def test(args = None):
+    import sys, formatter
+
+    if not args:
+        args = sys.argv[1:]
+
+    silent = args and args[0] == '-s'
+    if silent:
+        del args[0]
+
+    if args:
+        file = args[0]
+    else:
+        file = 'test.html'
+
+    if file == '-':
+        f = sys.stdin
+    else:
+        try:
+            f = open(file, 'r')
+        except IOError, msg:
+            print file, ":", msg
+            sys.exit(1)
+
+    data = f.read()
+
+    if f is not sys.stdin:
+        f.close()
+
+    if silent:
+        f = formatter.NullFormatter()
+    else:
+        f = formatter.AbstractFormatter(formatter.DumbWriter())
+
+    p = HTMLParser(f)
+    p.feed(data)
+    p.close()
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/httplib.py b/src/main/resources/PythonLibs/httplib.py
new file mode 100644
index 0000000000000000000000000000000000000000..5c919d2b2fafb81b98b1b26a43e91538fda4ebc9
--- /dev/null
+++ b/src/main/resources/PythonLibs/httplib.py
@@ -0,0 +1,1342 @@
+r"""HTTP/1.1 client library
+
+<intro stuff goes here>
+<other stuff, too>
+
+HTTPConnection goes through a number of "states", which define when a client
+may legally make another request or fetch the response for a particular
+request. This diagram details these state transitions:
+
+    (null)
+      |
+      | HTTPConnection()
+      v
+    Idle
+      |
+      | putrequest()
+      v
+    Request-started
+      |
+      | ( putheader() )*  endheaders()
+      v
+    Request-sent
+      |
+      | response = getresponse()
+      v
+    Unread-response   [Response-headers-read]
+      |\____________________
+      |                     |
+      | response.read()     | putrequest()
+      v                     v
+    Idle                  Req-started-unread-response
+                     ______/|
+                   /        |
+   response.read() |        | ( putheader() )*  endheaders()
+                   v        v
+       Request-started    Req-sent-unread-response
+                            |
+                            | response.read()
+                            v
+                          Request-sent
+
+This diagram presents the following rules:
+  -- a second request may not be started until {response-headers-read}
+  -- a response [object] cannot be retrieved until {request-sent}
+  -- there is no differentiation between an unread response body and a
+     partially read response body
+
+Note: this enforcement is applied by the HTTPConnection class. The
+      HTTPResponse class does not enforce this state machine, which
+      implies sophisticated clients may accelerate the request/response
+      pipeline. Caution should be taken, though: accelerating the states
+      beyond the above pattern may imply knowledge of the server's
+      connection-close behavior for certain requests. For example, it
+      is impossible to tell whether the server will close the connection
+      UNTIL the response headers have been read; this means that further
+      requests cannot be placed into the pipeline until it is known that
+      the server will NOT be closing the connection.
+
+Logical State                  __state            __response
+-------------                  -------            ----------
+Idle                           _CS_IDLE           None
+Request-started                _CS_REQ_STARTED    None
+Request-sent                   _CS_REQ_SENT       None
+Unread-response                _CS_IDLE           <response_class>
+Req-started-unread-response    _CS_REQ_STARTED    <response_class>
+Req-sent-unread-response       _CS_REQ_SENT       <response_class>
+"""
+
+from array import array
+import os
+import socket
+from sys import py3kwarning
+from urlparse import urlsplit
+import warnings
+with warnings.catch_warnings():
+    if py3kwarning:
+        warnings.filterwarnings("ignore", ".*mimetools has been removed",
+                                DeprecationWarning)
+    import mimetools
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+__all__ = ["HTTP", "HTTPResponse", "HTTPConnection",
+           "HTTPException", "NotConnected", "UnknownProtocol",
+           "UnknownTransferEncoding", "UnimplementedFileMode",
+           "IncompleteRead", "InvalidURL", "ImproperConnectionState",
+           "CannotSendRequest", "CannotSendHeader", "ResponseNotReady",
+           "BadStatusLine", "error", "responses"]
+
+HTTP_PORT = 80
+HTTPS_PORT = 443
+
+_UNKNOWN = 'UNKNOWN'
+
+# connection states
+_CS_IDLE = 'Idle'
+_CS_REQ_STARTED = 'Request-started'
+_CS_REQ_SENT = 'Request-sent'
+
+# status codes
+# informational
+CONTINUE = 100
+SWITCHING_PROTOCOLS = 101
+PROCESSING = 102
+
+# successful
+OK = 200
+CREATED = 201
+ACCEPTED = 202
+NON_AUTHORITATIVE_INFORMATION = 203
+NO_CONTENT = 204
+RESET_CONTENT = 205
+PARTIAL_CONTENT = 206
+MULTI_STATUS = 207
+IM_USED = 226
+
+# redirection
+MULTIPLE_CHOICES = 300
+MOVED_PERMANENTLY = 301
+FOUND = 302
+SEE_OTHER = 303
+NOT_MODIFIED = 304
+USE_PROXY = 305
+TEMPORARY_REDIRECT = 307
+
+# client error
+BAD_REQUEST = 400
+UNAUTHORIZED = 401
+PAYMENT_REQUIRED = 402
+FORBIDDEN = 403
+NOT_FOUND = 404
+METHOD_NOT_ALLOWED = 405
+NOT_ACCEPTABLE = 406
+PROXY_AUTHENTICATION_REQUIRED = 407
+REQUEST_TIMEOUT = 408
+CONFLICT = 409
+GONE = 410
+LENGTH_REQUIRED = 411
+PRECONDITION_FAILED = 412
+REQUEST_ENTITY_TOO_LARGE = 413
+REQUEST_URI_TOO_LONG = 414
+UNSUPPORTED_MEDIA_TYPE = 415
+REQUESTED_RANGE_NOT_SATISFIABLE = 416
+EXPECTATION_FAILED = 417
+UNPROCESSABLE_ENTITY = 422
+LOCKED = 423
+FAILED_DEPENDENCY = 424
+UPGRADE_REQUIRED = 426
+
+# server error
+INTERNAL_SERVER_ERROR = 500
+NOT_IMPLEMENTED = 501
+BAD_GATEWAY = 502
+SERVICE_UNAVAILABLE = 503
+GATEWAY_TIMEOUT = 504
+HTTP_VERSION_NOT_SUPPORTED = 505
+INSUFFICIENT_STORAGE = 507
+NOT_EXTENDED = 510
+
+# Mapping status codes to official W3C names
+responses = {
+    100: 'Continue',
+    101: 'Switching Protocols',
+
+    200: 'OK',
+    201: 'Created',
+    202: 'Accepted',
+    203: 'Non-Authoritative Information',
+    204: 'No Content',
+    205: 'Reset Content',
+    206: 'Partial Content',
+
+    300: 'Multiple Choices',
+    301: 'Moved Permanently',
+    302: 'Found',
+    303: 'See Other',
+    304: 'Not Modified',
+    305: 'Use Proxy',
+    306: '(Unused)',
+    307: 'Temporary Redirect',
+
+    400: 'Bad Request',
+    401: 'Unauthorized',
+    402: 'Payment Required',
+    403: 'Forbidden',
+    404: 'Not Found',
+    405: 'Method Not Allowed',
+    406: 'Not Acceptable',
+    407: 'Proxy Authentication Required',
+    408: 'Request Timeout',
+    409: 'Conflict',
+    410: 'Gone',
+    411: 'Length Required',
+    412: 'Precondition Failed',
+    413: 'Request Entity Too Large',
+    414: 'Request-URI Too Long',
+    415: 'Unsupported Media Type',
+    416: 'Requested Range Not Satisfiable',
+    417: 'Expectation Failed',
+
+    500: 'Internal Server Error',
+    501: 'Not Implemented',
+    502: 'Bad Gateway',
+    503: 'Service Unavailable',
+    504: 'Gateway Timeout',
+    505: 'HTTP Version Not Supported',
+}
+
+# maximal amount of data to read at one time in _safe_read
+MAXAMOUNT = 1048576
+
+# maximal line length when calling readline().
+_MAXLINE = 65536
+
+class HTTPMessage(mimetools.Message):
+
+    def addheader(self, key, value):
+        """Add header for field key handling repeats."""
+        prev = self.dict.get(key)
+        if prev is None:
+            self.dict[key] = value
+        else:
+            combined = ", ".join((prev, value))
+            self.dict[key] = combined
+
+    def addcontinue(self, key, more):
+        """Add more field data from a continuation line."""
+        prev = self.dict[key]
+        self.dict[key] = prev + "\n " + more
+
+    def readheaders(self):
+        """Read header lines.
+
+        Read header lines up to the entirely blank line that terminates them.
+        The (normally blank) line that ends the headers is skipped, but not
+        included in the returned list.  If a non-header line ends the headers,
+        (which is an error), an attempt is made to backspace over it; it is
+        never included in the returned list.
+
+        The variable self.status is set to the empty string if all went well,
+        otherwise it is an error message.  The variable self.headers is a
+        completely uninterpreted list of lines contained in the header (so
+        printing them will reproduce the header exactly as it appears in the
+        file).
+
+        If multiple header fields with the same name occur, they are combined
+        according to the rules in RFC 2616 sec 4.2:
+
+        Appending each subsequent field-value to the first, each separated
+        by a comma. The order in which header fields with the same field-name
+        are received is significant to the interpretation of the combined
+        field value.
+        """
+        # XXX The implementation overrides the readheaders() method of
+        # rfc822.Message.  The base class design isn't amenable to
+        # customized behavior here so the method here is a copy of the
+        # base class code with a few small changes.
+
+        self.dict = {}
+        self.unixfrom = ''
+        self.headers = hlist = []
+        self.status = ''
+        headerseen = ""
+        firstline = 1
+        startofline = unread = tell = None
+        if hasattr(self.fp, 'unread'):
+            unread = self.fp.unread
+        elif self.seekable:
+            tell = self.fp.tell
+        while True:
+            if tell:
+                try:
+                    startofline = tell()
+                except IOError:
+                    startofline = tell = None
+                    self.seekable = 0
+            line = self.fp.readline(_MAXLINE + 1)
+            if len(line) > _MAXLINE:
+                raise LineTooLong("header line")
+            if not line:
+                self.status = 'EOF in headers'
+                break
+            # Skip unix From name time lines
+            if firstline and line.startswith('From '):
+                self.unixfrom = self.unixfrom + line
+                continue
+            firstline = 0
+            if headerseen and line[0] in ' \t':
+                # XXX Not sure if continuation lines are handled properly
+                # for http and/or for repeating headers
+                # It's a continuation line.
+                hlist.append(line)
+                self.addcontinue(headerseen, line.strip())
+                continue
+            elif self.iscomment(line):
+                # It's a comment.  Ignore it.
+                continue
+            elif self.islast(line):
+                # Note! No pushback here!  The delimiter line gets eaten.
+                break
+            headerseen = self.isheader(line)
+            if headerseen:
+                # It's a legal header line, save it.
+                hlist.append(line)
+                self.addheader(headerseen, line[len(headerseen)+1:].strip())
+                continue
+            else:
+                # It's not a header line; throw it back and stop here.
+                if not self.dict:
+                    self.status = 'No headers'
+                else:
+                    self.status = 'Non-header line where header expected'
+                # Try to undo the read.
+                if unread:
+                    unread(line)
+                elif tell:
+                    self.fp.seek(startofline)
+                else:
+                    self.status = self.status + '; bad seek'
+                break
+
+class HTTPResponse:
+
+    # strict: If true, raise BadStatusLine if the status line can't be
+    # parsed as a valid HTTP/1.0 or 1.1 status line.  By default it is
+    # false because it prevents clients from talking to HTTP/0.9
+    # servers.  Note that a response with a sufficiently corrupted
+    # status line will look like an HTTP/0.9 response.
+
+    # See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details.
+
+    def __init__(self, sock, debuglevel=0, strict=0, method=None, buffering=False):
+        if buffering:
+            # The caller won't be using any sock.recv() calls, so buffering
+            # is fine and recommended for performance.
+            self.fp = sock.makefile('rb')
+        else:
+            # The buffer size is specified as zero, because the headers of
+            # the response are read with readline().  If the reads were
+            # buffered the readline() calls could consume some of the
+            # response, which make be read via a recv() on the underlying
+            # socket.
+            self.fp = sock.makefile('rb', 0)
+        self.debuglevel = debuglevel
+        self.strict = strict
+        self._method = method
+
+        self.msg = None
+
+        # from the Status-Line of the response
+        self.version = _UNKNOWN # HTTP-Version
+        self.status = _UNKNOWN  # Status-Code
+        self.reason = _UNKNOWN  # Reason-Phrase
+
+        self.chunked = _UNKNOWN         # is "chunked" being used?
+        self.chunk_left = _UNKNOWN      # bytes left to read in current chunk
+        self.length = _UNKNOWN          # number of bytes left in response
+        self.will_close = _UNKNOWN      # conn will close at end of response
+
+    def _read_status(self):
+        # Initialize with Simple-Response defaults
+        line = self.fp.readline(_MAXLINE + 1)
+        if len(line) > _MAXLINE:
+            raise LineTooLong("header line")
+        if self.debuglevel > 0:
+            print "reply:", repr(line)
+        if not line:
+            # Presumably, the server closed the connection before
+            # sending a valid response.
+            raise BadStatusLine(line)
+        try:
+            [version, status, reason] = line.split(None, 2)
+        except ValueError:
+            try:
+                [version, status] = line.split(None, 1)
+                reason = ""
+            except ValueError:
+                # empty version will cause next test to fail and status
+                # will be treated as 0.9 response.
+                version = ""
+        if not version.startswith('HTTP/'):
+            if self.strict:
+                self.close()
+                raise BadStatusLine(line)
+            else:
+                # assume it's a Simple-Response from an 0.9 server
+                self.fp = LineAndFileWrapper(line, self.fp)
+                return "HTTP/0.9", 200, ""
+
+        # The status code is a three-digit number
+        try:
+            status = int(status)
+            if status < 100 or status > 999:
+                raise BadStatusLine(line)
+        except ValueError:
+            raise BadStatusLine(line)
+        return version, status, reason
+
+    def begin(self):
+        if self.msg is not None:
+            # we've already started reading the response
+            return
+
+        # read until we get a non-100 response
+        while True:
+            version, status, reason = self._read_status()
+            if status != CONTINUE:
+                break
+            # skip the header from the 100 response
+            while True:
+                skip = self.fp.readline(_MAXLINE + 1)
+                if len(skip) > _MAXLINE:
+                    raise LineTooLong("header line")
+                skip = skip.strip()
+                if not skip:
+                    break
+                if self.debuglevel > 0:
+                    print "header:", skip
+
+        self.status = status
+        self.reason = reason.strip()
+        if version == 'HTTP/1.0':
+            self.version = 10
+        elif version.startswith('HTTP/1.'):
+            self.version = 11   # use HTTP/1.1 code for HTTP/1.x where x>=1
+        elif version == 'HTTP/0.9':
+            self.version = 9
+        else:
+            raise UnknownProtocol(version)
+
+        if self.version == 9:
+            self.length = None
+            self.chunked = 0
+            self.will_close = 1
+            self.msg = HTTPMessage(StringIO())
+            return
+
+        self.msg = HTTPMessage(self.fp, 0)
+        if self.debuglevel > 0:
+            for hdr in self.msg.headers:
+                print "header:", hdr,
+
+        # don't let the msg keep an fp
+        self.msg.fp = None
+
+        # are we using the chunked-style of transfer encoding?
+        tr_enc = self.msg.getheader('transfer-encoding')
+        if tr_enc and tr_enc.lower() == "chunked":
+            self.chunked = 1
+            self.chunk_left = None
+        else:
+            self.chunked = 0
+
+        # will the connection close at the end of the response?
+        self.will_close = self._check_close()
+
+        # do we have a Content-Length?
+        # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
+        length = self.msg.getheader('content-length')
+        if length and not self.chunked:
+            try:
+                self.length = int(length)
+            except ValueError:
+                self.length = None
+            else:
+                if self.length < 0:  # ignore nonsensical negative lengths
+                    self.length = None
+        else:
+            self.length = None
+
+        # does the body have a fixed length? (of zero)
+        if (status == NO_CONTENT or status == NOT_MODIFIED or
+            100 <= status < 200 or      # 1xx codes
+            self._method == 'HEAD'):
+            self.length = 0
+
+        # if the connection remains open, and we aren't using chunked, and
+        # a content-length was not provided, then assume that the connection
+        # WILL close.
+        if not self.will_close and \
+           not self.chunked and \
+           self.length is None:
+            self.will_close = 1
+
+    def _check_close(self):
+        conn = self.msg.getheader('connection')
+        if self.version == 11:
+            # An HTTP/1.1 proxy is assumed to stay open unless
+            # explicitly closed.
+            conn = self.msg.getheader('connection')
+            if conn and "close" in conn.lower():
+                return True
+            return False
+
+        # Some HTTP/1.0 implementations have support for persistent
+        # connections, using rules different than HTTP/1.1.
+
+        # For older HTTP, Keep-Alive indicates persistent connection.
+        if self.msg.getheader('keep-alive'):
+            return False
+
+        # At least Akamai returns a "Connection: Keep-Alive" header,
+        # which was supposed to be sent by the client.
+        if conn and "keep-alive" in conn.lower():
+            return False
+
+        # Proxy-Connection is a netscape hack.
+        pconn = self.msg.getheader('proxy-connection')
+        if pconn and "keep-alive" in pconn.lower():
+            return False
+
+        # otherwise, assume it will close
+        return True
+
+    def close(self):
+        if self.fp:
+            self.fp.close()
+            self.fp = None
+
+    def isclosed(self):
+        # NOTE: it is possible that we will not ever call self.close(). This
+        #       case occurs when will_close is TRUE, length is None, and we
+        #       read up to the last byte, but NOT past it.
+        #
+        # IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be
+        #          called, meaning self.isclosed() is meaningful.
+        return self.fp is None
+
+    # XXX It would be nice to have readline and __iter__ for this, too.
+
+    def read(self, amt=None):
+        if self.fp is None:
+            return ''
+
+        if self._method == 'HEAD':
+            self.close()
+            return ''
+
+        if self.chunked:
+            return self._read_chunked(amt)
+
+        if amt is None:
+            # unbounded read
+            if self.length is None:
+                s = self.fp.read()
+            else:
+                try:
+                    s = self._safe_read(self.length)
+                except IncompleteRead:
+                    self.close()
+                    raise
+                self.length = 0
+            self.close()        # we read everything
+            return s
+
+        if self.length is not None:
+            if amt > self.length:
+                # clip the read to the "end of response"
+                amt = self.length
+
+        # we do not use _safe_read() here because this may be a .will_close
+        # connection, and the user is reading more bytes than will be provided
+        # (for example, reading in 1k chunks)
+        s = self.fp.read(amt)
+        if not s:
+            # Ideally, we would raise IncompleteRead if the content-length
+            # wasn't satisfied, but it might break compatibility.
+            self.close()
+        if self.length is not None:
+            self.length -= len(s)
+            if not self.length:
+                self.close()
+
+        return s
+
+    def _read_chunked(self, amt):
+        assert self.chunked != _UNKNOWN
+        chunk_left = self.chunk_left
+        value = []
+        while True:
+            if chunk_left is None:
+                line = self.fp.readline(_MAXLINE + 1)
+                if len(line) > _MAXLINE:
+                    raise LineTooLong("chunk size")
+                i = line.find(';')
+                if i >= 0:
+                    line = line[:i] # strip chunk-extensions
+                try:
+                    chunk_left = int(line, 16)
+                except ValueError:
+                    # close the connection as protocol synchronisation is
+                    # probably lost
+                    self.close()
+                    raise IncompleteRead(''.join(value))
+                if chunk_left == 0:
+                    break
+            if amt is None:
+                value.append(self._safe_read(chunk_left))
+            elif amt < chunk_left:
+                value.append(self._safe_read(amt))
+                self.chunk_left = chunk_left - amt
+                return ''.join(value)
+            elif amt == chunk_left:
+                value.append(self._safe_read(amt))
+                self._safe_read(2)  # toss the CRLF at the end of the chunk
+                self.chunk_left = None
+                return ''.join(value)
+            else:
+                value.append(self._safe_read(chunk_left))
+                amt -= chunk_left
+
+            # we read the whole chunk, get another
+            self._safe_read(2)      # toss the CRLF at the end of the chunk
+            chunk_left = None
+
+        # read and discard trailer up to the CRLF terminator
+        ### note: we shouldn't have any trailers!
+        while True:
+            line = self.fp.readline(_MAXLINE + 1)
+            if len(line) > _MAXLINE:
+                raise LineTooLong("trailer line")
+            if not line:
+                # a vanishingly small number of sites EOF without
+                # sending the trailer
+                break
+            if line == '\r\n':
+                break
+
+        # we read everything; close the "file"
+        self.close()
+
+        return ''.join(value)
+
+    def _safe_read(self, amt):
+        """Read the number of bytes requested, compensating for partial reads.
+
+        Normally, we have a blocking socket, but a read() can be interrupted
+        by a signal (resulting in a partial read).
+
+        Note that we cannot distinguish between EOF and an interrupt when zero
+        bytes have been read. IncompleteRead() will be raised in this
+        situation.
+
+        This function should be used when <amt> bytes "should" be present for
+        reading. If the bytes are truly not available (due to EOF), then the
+        IncompleteRead exception can be used to detect the problem.
+        """
+        # NOTE(gps): As of svn r74426 socket._fileobject.read(x) will never
+        # return less than x bytes unless EOF is encountered.  It now handles
+        # signal interruptions (socket.error EINTR) internally.  This code
+        # never caught that exception anyways.  It seems largely pointless.
+        # self.fp.read(amt) will work fine.
+        s = []
+        while amt > 0:
+            chunk = self.fp.read(min(amt, MAXAMOUNT))
+            if not chunk:
+                raise IncompleteRead(''.join(s), amt)
+            s.append(chunk)
+            amt -= len(chunk)
+        return ''.join(s)
+
+    def fileno(self):
+        return self.fp.fileno()
+
+    def getheader(self, name, default=None):
+        if self.msg is None:
+            raise ResponseNotReady()
+        return self.msg.getheader(name, default)
+
+    def getheaders(self):
+        """Return list of (header, value) tuples."""
+        if self.msg is None:
+            raise ResponseNotReady()
+        return self.msg.items()
+
+
+class HTTPConnection:
+
+    _http_vsn = 11
+    _http_vsn_str = 'HTTP/1.1'
+
+    response_class = HTTPResponse
+    default_port = HTTP_PORT
+    auto_open = 1
+    debuglevel = 0
+    strict = 0
+
+    def __init__(self, host, port=None, strict=None,
+                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_address=None):
+        self.timeout = timeout
+        self.source_address = source_address
+        self.sock = None
+        self._buffer = []
+        self.__response = None
+        self.__state = _CS_IDLE
+        self._method = None
+        self._tunnel_host = None
+        self._tunnel_port = None
+        self._tunnel_headers = {}
+
+        self._set_hostport(host, port)
+        if strict is not None:
+            self.strict = strict
+
+    def set_tunnel(self, host, port=None, headers=None):
+        """ Sets up the host and the port for the HTTP CONNECT Tunnelling.
+
+        The headers argument should be a mapping of extra HTTP headers
+        to send with the CONNECT request.
+        """
+        self._tunnel_host = host
+        self._tunnel_port = port
+        if headers:
+            self._tunnel_headers = headers
+        else:
+            self._tunnel_headers.clear()
+
+    def _set_hostport(self, host, port):
+        if port is None:
+            i = host.rfind(':')
+            j = host.rfind(']')         # ipv6 addresses have [...]
+            if i > j:
+                try:
+                    port = int(host[i+1:])
+                except ValueError:
+                    if host[i+1:] == "":  # http://foo.com:/ == http://foo.com/
+                        port = self.default_port
+                    else:
+                        raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
+                host = host[:i]
+            else:
+                port = self.default_port
+            if host and host[0] == '[' and host[-1] == ']':
+                host = host[1:-1]
+        self.host = host
+        self.port = port
+
+    def set_debuglevel(self, level):
+        self.debuglevel = level
+
+    def _tunnel(self):
+        self._set_hostport(self._tunnel_host, self._tunnel_port)
+        self.send("CONNECT %s:%d HTTP/1.0\r\n" % (self.host, self.port))
+        for header, value in self._tunnel_headers.iteritems():
+            self.send("%s: %s\r\n" % (header, value))
+        self.send("\r\n")
+        response = self.response_class(self.sock, strict = self.strict,
+                                       method = self._method)
+        (version, code, message) = response._read_status()
+
+        if code != 200:
+            self.close()
+            raise socket.error("Tunnel connection failed: %d %s" % (code,
+                                                                    message.strip()))
+        while True:
+            line = response.fp.readline(_MAXLINE + 1)
+            if len(line) > _MAXLINE:
+                raise LineTooLong("header line")
+            if not line:
+                # for sites which EOF without sending trailer
+                break
+            if line == '\r\n':
+                break
+
+
+    def connect(self):
+        """Connect to the host and port specified in __init__."""
+        self.sock = socket.create_connection((self.host,self.port),
+                                             self.timeout, self.source_address)
+
+        if self._tunnel_host:
+            self._tunnel()
+
+    def close(self):
+        """Close the connection to the HTTP server."""
+        if self.sock:
+            self.sock.close()   # close it manually... there may be other refs
+            self.sock = None
+        if self.__response:
+            self.__response.close()
+            self.__response = None
+        self.__state = _CS_IDLE
+
+    def send(self, data):
+        """Send `data' to the server."""
+        if self.sock is None:
+            if self.auto_open:
+                self.connect()
+            else:
+                raise NotConnected()
+
+        if self.debuglevel > 0:
+            print "send:", repr(data)
+        blocksize = 8192
+        if hasattr(data,'read') and not isinstance(data, array):
+            if self.debuglevel > 0: print "sendIng a read()able"
+            datablock = data.read(blocksize)
+            while datablock:
+                self.sock.sendall(datablock)
+                datablock = data.read(blocksize)
+        else:
+            self.sock.sendall(data)
+
+    def _output(self, s):
+        """Add a line of output to the current request buffer.
+
+        Assumes that the line does *not* end with \\r\\n.
+        """
+        self._buffer.append(s)
+
+    def _send_output(self, message_body=None):
+        """Send the currently buffered request and clear the buffer.
+
+        Appends an extra \\r\\n to the buffer.
+        A message_body may be specified, to be appended to the request.
+        """
+        self._buffer.extend(("", ""))
+        msg = "\r\n".join(self._buffer)
+        del self._buffer[:]
+        # If msg and message_body are sent in a single send() call,
+        # it will avoid performance problems caused by the interaction
+        # between delayed ack and the Nagle algorithm.
+        if isinstance(message_body, str):
+            msg += message_body
+            message_body = None
+        self.send(msg)
+        if message_body is not None:
+            #message_body was not a string (i.e. it is a file) and
+            #we must run the risk of Nagle
+            self.send(message_body)
+
+    def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0):
+        """Send a request to the server.
+
+        `method' specifies an HTTP request method, e.g. 'GET'.
+        `url' specifies the object being requested, e.g. '/index.html'.
+        `skip_host' if True does not add automatically a 'Host:' header
+        `skip_accept_encoding' if True does not add automatically an
+           'Accept-Encoding:' header
+        """
+
+        # if a prior response has been completed, then forget about it.
+        if self.__response and self.__response.isclosed():
+            self.__response = None
+
+
+        # in certain cases, we cannot issue another request on this connection.
+        # this occurs when:
+        #   1) we are in the process of sending a request.   (_CS_REQ_STARTED)
+        #   2) a response to a previous request has signalled that it is going
+        #      to close the connection upon completion.
+        #   3) the headers for the previous response have not been read, thus
+        #      we cannot determine whether point (2) is true.   (_CS_REQ_SENT)
+        #
+        # if there is no prior response, then we can request at will.
+        #
+        # if point (2) is true, then we will have passed the socket to the
+        # response (effectively meaning, "there is no prior response"), and
+        # will open a new one when a new request is made.
+        #
+        # Note: if a prior response exists, then we *can* start a new request.
+        #       We are not allowed to begin fetching the response to this new
+        #       request, however, until that prior response is complete.
+        #
+        if self.__state == _CS_IDLE:
+            self.__state = _CS_REQ_STARTED
+        else:
+            raise CannotSendRequest()
+
+        # Save the method we use, we need it later in the response phase
+        self._method = method
+        if not url:
+            url = '/'
+        hdr = '%s %s %s' % (method, url, self._http_vsn_str)
+
+        self._output(hdr)
+
+        if self._http_vsn == 11:
+            # Issue some standard headers for better HTTP/1.1 compliance
+
+            if not skip_host:
+                # this header is issued *only* for HTTP/1.1
+                # connections. more specifically, this means it is
+                # only issued when the client uses the new
+                # HTTPConnection() class. backwards-compat clients
+                # will be using HTTP/1.0 and those clients may be
+                # issuing this header themselves. we should NOT issue
+                # it twice; some web servers (such as Apache) barf
+                # when they see two Host: headers
+
+                # If we need a non-standard port,include it in the
+                # header.  If the request is going through a proxy,
+                # but the host of the actual URL, not the host of the
+                # proxy.
+
+                netloc = ''
+                if url.startswith('http'):
+                    nil, netloc, nil, nil, nil = urlsplit(url)
+
+                if netloc:
+                    try:
+                        netloc_enc = netloc.encode("ascii")
+                    except UnicodeEncodeError:
+                        netloc_enc = netloc.encode("idna")
+                    self.putheader('Host', netloc_enc)
+                else:
+                    try:
+                        host_enc = self.host.encode("ascii")
+                    except UnicodeEncodeError:
+                        host_enc = self.host.encode("idna")
+                    # Wrap the IPv6 Host Header with [] (RFC 2732)
+                    if host_enc.find(':') >= 0:
+                        host_enc = "[" + host_enc + "]"
+                    if self.port == self.default_port:
+                        self.putheader('Host', host_enc)
+                    else:
+                        self.putheader('Host', "%s:%s" % (host_enc, self.port))
+
+            # note: we are assuming that clients will not attempt to set these
+            #       headers since *this* library must deal with the
+            #       consequences. this also means that when the supporting
+            #       libraries are updated to recognize other forms, then this
+            #       code should be changed (removed or updated).
+
+            # we only want a Content-Encoding of "identity" since we don't
+            # support encodings such as x-gzip or x-deflate.
+            if not skip_accept_encoding:
+                self.putheader('Accept-Encoding', 'identity')
+
+            # we can accept "chunked" Transfer-Encodings, but no others
+            # NOTE: no TE header implies *only* "chunked"
+            #self.putheader('TE', 'chunked')
+
+            # if TE is supplied in the header, then it must appear in a
+            # Connection header.
+            #self.putheader('Connection', 'TE')
+
+        else:
+            # For HTTP/1.0, the server will assume "not chunked"
+            pass
+
+    def putheader(self, header, *values):
+        """Send a request header line to the server.
+
+        For example: h.putheader('Accept', 'text/html')
+        """
+        if self.__state != _CS_REQ_STARTED:
+            raise CannotSendHeader()
+
+        hdr = '%s: %s' % (header, '\r\n\t'.join([str(v) for v in values]))
+        self._output(hdr)
+
+    def endheaders(self, message_body=None):
+        """Indicate that the last header line has been sent to the server.
+
+        This method sends the request to the server.  The optional
+        message_body argument can be used to pass a message body
+        associated with the request.  The message body will be sent in
+        the same packet as the message headers if it is string, otherwise it is
+        sent as a separate packet.
+        """
+        if self.__state == _CS_REQ_STARTED:
+            self.__state = _CS_REQ_SENT
+        else:
+            raise CannotSendHeader()
+        self._send_output(message_body)
+
+    def request(self, method, url, body=None, headers={}):
+        """Send a complete request to the server."""
+        self._send_request(method, url, body, headers)
+
+    def _set_content_length(self, body):
+        # Set the content-length based on the body.
+        thelen = None
+        try:
+            thelen = str(len(body))
+        except TypeError, te:
+            # If this is a file-like object, try to
+            # fstat its file descriptor
+            try:
+                thelen = str(os.fstat(body.fileno()).st_size)
+            except (AttributeError, OSError):
+                # Don't send a length if this failed
+                if self.debuglevel > 0: print "Cannot stat!!"
+
+        if thelen is not None:
+            self.putheader('Content-Length', thelen)
+
+    def _send_request(self, method, url, body, headers):
+        # Honor explicitly requested Host: and Accept-Encoding: headers.
+        header_names = dict.fromkeys([k.lower() for k in headers])
+        skips = {}
+        if 'host' in header_names:
+            skips['skip_host'] = 1
+        if 'accept-encoding' in header_names:
+            skips['skip_accept_encoding'] = 1
+
+        self.putrequest(method, url, **skips)
+
+        if body is not None and 'content-length' not in header_names:
+            self._set_content_length(body)
+        for hdr, value in headers.iteritems():
+            self.putheader(hdr, value)
+        self.endheaders(body)
+
+    def getresponse(self, buffering=False):
+        "Get the response from the server."
+
+        # if a prior response has been completed, then forget about it.
+        if self.__response and self.__response.isclosed():
+            self.__response = None
+
+        #
+        # if a prior response exists, then it must be completed (otherwise, we
+        # cannot read this response's header to determine the connection-close
+        # behavior)
+        #
+        # note: if a prior response existed, but was connection-close, then the
+        # socket and response were made independent of this HTTPConnection
+        # object since a new request requires that we open a whole new
+        # connection
+        #
+        # this means the prior response had one of two states:
+        #   1) will_close: this connection was reset and the prior socket and
+        #                  response operate independently
+        #   2) persistent: the response was retained and we await its
+        #                  isclosed() status to become true.
+        #
+        if self.__state != _CS_REQ_SENT or self.__response:
+            raise ResponseNotReady()
+
+        args = (self.sock,)
+        kwds = {"strict":self.strict, "method":self._method}
+        if self.debuglevel > 0:
+            args += (self.debuglevel,)
+        if buffering:
+            #only add this keyword if non-default, for compatibility with
+            #other response_classes.
+            kwds["buffering"] = True;
+        response = self.response_class(*args, **kwds)
+
+        response.begin()
+        assert response.will_close != _UNKNOWN
+        self.__state = _CS_IDLE
+
+        if response.will_close:
+            # this effectively passes the connection to the response
+            self.close()
+        else:
+            # remember this, so we can tell when it is complete
+            self.__response = response
+
+        return response
+
+
+class HTTP:
+    "Compatibility class with httplib.py from 1.5."
+
+    _http_vsn = 10
+    _http_vsn_str = 'HTTP/1.0'
+
+    debuglevel = 0
+
+    _connection_class = HTTPConnection
+
+    def __init__(self, host='', port=None, strict=None):
+        "Provide a default host, since the superclass requires one."
+
+        # some joker passed 0 explicitly, meaning default port
+        if port == 0:
+            port = None
+
+        # Note that we may pass an empty string as the host; this will raise
+        # an error when we attempt to connect. Presumably, the client code
+        # will call connect before then, with a proper host.
+        self._setup(self._connection_class(host, port, strict))
+
+    def _setup(self, conn):
+        self._conn = conn
+
+        # set up delegation to flesh out interface
+        self.send = conn.send
+        self.putrequest = conn.putrequest
+        self.putheader = conn.putheader
+        self.endheaders = conn.endheaders
+        self.set_debuglevel = conn.set_debuglevel
+
+        conn._http_vsn = self._http_vsn
+        conn._http_vsn_str = self._http_vsn_str
+
+        self.file = None
+
+    def connect(self, host=None, port=None):
+        "Accept arguments to set the host/port, since the superclass doesn't."
+
+        if host is not None:
+            self._conn._set_hostport(host, port)
+        self._conn.connect()
+
+    def getfile(self):
+        "Provide a getfile, since the superclass' does not use this concept."
+        return self.file
+
+    def getreply(self, buffering=False):
+        """Compat definition since superclass does not define it.
+
+        Returns a tuple consisting of:
+        - server status code (e.g. '200' if all goes well)
+        - server "reason" corresponding to status code
+        - any RFC822 headers in the response from the server
+        """
+        try:
+            if not buffering:
+                response = self._conn.getresponse()
+            else:
+                #only add this keyword if non-default for compatibility
+                #with other connection classes
+                response = self._conn.getresponse(buffering)
+        except BadStatusLine, e:
+            ### hmm. if getresponse() ever closes the socket on a bad request,
+            ### then we are going to have problems with self.sock
+
+            ### should we keep this behavior? do people use it?
+            # keep the socket open (as a file), and return it
+            self.file = self._conn.sock.makefile('rb', 0)
+
+            # close our socket -- we want to restart after any protocol error
+            self.close()
+
+            self.headers = None
+            return -1, e.line, None
+
+        self.headers = response.msg
+        self.file = response.fp
+        return response.status, response.reason, response.msg
+
+    def close(self):
+        self._conn.close()
+
+        # note that self.file == response.fp, which gets closed by the
+        # superclass. just clear the object ref here.
+        ### hmm. messy. if status==-1, then self.file is owned by us.
+        ### well... we aren't explicitly closing, but losing this ref will
+        ### do it
+        self.file = None
+
+try:
+    import ssl
+except ImportError:
+    pass
+else:
+    class HTTPSConnection(HTTPConnection):
+        "This class allows communication via SSL."
+
+        default_port = HTTPS_PORT
+
+        def __init__(self, host, port=None, key_file=None, cert_file=None,
+                     strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
+                     source_address=None):
+            HTTPConnection.__init__(self, host, port, strict, timeout,
+                                    source_address)
+            self.key_file = key_file
+            self.cert_file = cert_file
+
+        def connect(self):
+            "Connect to a host on a given (SSL) port."
+
+            sock = socket.create_connection((self.host, self.port),
+                                            self.timeout, self.source_address)
+            if self._tunnel_host:
+                self.sock = sock
+                self._tunnel()
+            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
+
+    __all__.append("HTTPSConnection")
+
+    class HTTPS(HTTP):
+        """Compatibility with 1.5 httplib interface
+
+        Python 1.5.2 did not have an HTTPS class, but it defined an
+        interface for sending http requests that is also useful for
+        https.
+        """
+
+        _connection_class = HTTPSConnection
+
+        def __init__(self, host='', port=None, key_file=None, cert_file=None,
+                     strict=None):
+            # provide a default host, pass the X509 cert info
+
+            # urf. compensate for bad input.
+            if port == 0:
+                port = None
+            self._setup(self._connection_class(host, port, key_file,
+                                               cert_file, strict))
+
+            # we never actually use these for anything, but we keep them
+            # here for compatibility with post-1.5.2 CVS.
+            self.key_file = key_file
+            self.cert_file = cert_file
+
+
+    def FakeSocket (sock, sslobj):
+        warnings.warn("FakeSocket is deprecated, and won't be in 3.x.  " +
+                      "Use the result of ssl.wrap_socket() directly instead.",
+                      DeprecationWarning, stacklevel=2)
+        return sslobj
+
+
+class HTTPException(Exception):
+    # Subclasses that define an __init__ must call Exception.__init__
+    # or define self.args.  Otherwise, str() will fail.
+    pass
+
+class NotConnected(HTTPException):
+    pass
+
+class InvalidURL(HTTPException):
+    pass
+
+class UnknownProtocol(HTTPException):
+    def __init__(self, version):
+        self.args = version,
+        self.version = version
+
+class UnknownTransferEncoding(HTTPException):
+    pass
+
+class UnimplementedFileMode(HTTPException):
+    pass
+
+class IncompleteRead(HTTPException):
+    def __init__(self, partial, expected=None):
+        self.args = partial,
+        self.partial = partial
+        self.expected = expected
+    def __repr__(self):
+        if self.expected is not None:
+            e = ', %i more expected' % self.expected
+        else:
+            e = ''
+        return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e)
+    def __str__(self):
+        return repr(self)
+
+class ImproperConnectionState(HTTPException):
+    pass
+
+class CannotSendRequest(ImproperConnectionState):
+    pass
+
+class CannotSendHeader(ImproperConnectionState):
+    pass
+
+class ResponseNotReady(ImproperConnectionState):
+    pass
+
+class BadStatusLine(HTTPException):
+    def __init__(self, line):
+        if not line:
+            line = repr(line)
+        self.args = line,
+        self.line = line
+
+class LineTooLong(HTTPException):
+    def __init__(self, line_type):
+        HTTPException.__init__(self, "got more than %d bytes when reading %s"
+                                     % (_MAXLINE, line_type))
+
+# for backwards compatibility
+error = HTTPException
+
+class LineAndFileWrapper:
+    """A limited file-like object for HTTP/0.9 responses."""
+
+    # The status-line parsing code calls readline(), which normally
+    # get the HTTP status line.  For a 0.9 response, however, this is
+    # actually the first line of the body!  Clients need to get a
+    # readable file object that contains that line.
+
+    def __init__(self, line, file):
+        self._line = line
+        self._file = file
+        self._line_consumed = 0
+        self._line_offset = 0
+        self._line_left = len(line)
+
+    def __getattr__(self, attr):
+        return getattr(self._file, attr)
+
+    def _done(self):
+        # called when the last byte is read from the line.  After the
+        # call, all read methods are delegated to the underlying file
+        # object.
+        self._line_consumed = 1
+        self.read = self._file.read
+        self.readline = self._file.readline
+        self.readlines = self._file.readlines
+
+    def read(self, amt=None):
+        if self._line_consumed:
+            return self._file.read(amt)
+        assert self._line_left
+        if amt is None or amt > self._line_left:
+            s = self._line[self._line_offset:]
+            self._done()
+            if amt is None:
+                return s + self._file.read()
+            else:
+                return s + self._file.read(amt - len(s))
+        else:
+            assert amt <= self._line_left
+            i = self._line_offset
+            j = i + amt
+            s = self._line[i:j]
+            self._line_offset = j
+            self._line_left -= amt
+            if self._line_left == 0:
+                self._done()
+            return s
+
+    def readline(self):
+        if self._line_consumed:
+            return self._file.readline()
+        assert self._line_left
+        s = self._line[self._line_offset:]
+        self._done()
+        return s
+
+    def readlines(self, size=None):
+        if self._line_consumed:
+            return self._file.readlines(size)
+        assert self._line_left
+        L = [self._line[self._line_offset:]]
+        self._done()
+        if size is None:
+            return L + self._file.readlines()
+        else:
+            return L + self._file.readlines(size)
diff --git a/src/main/resources/PythonLibs/ihooks.py b/src/main/resources/PythonLibs/ihooks.py
new file mode 100644
index 0000000000000000000000000000000000000000..8761dac7cd05d0caace06cc1fbd115e046b20819
--- /dev/null
+++ b/src/main/resources/PythonLibs/ihooks.py
@@ -0,0 +1,554 @@
+"""Import hook support.
+
+Consistent use of this module will make it possible to change the
+different mechanisms involved in loading modules independently.
+
+While the built-in module imp exports interfaces to the built-in
+module searching and loading algorithm, and it is possible to replace
+the built-in function __import__ in order to change the semantics of
+the import statement, until now it has been difficult to combine the
+effect of different __import__ hacks, like loading modules from URLs
+by rimport.py, or restricted execution by rexec.py.
+
+This module defines three new concepts:
+
+1) A "file system hooks" class provides an interface to a filesystem.
+
+One hooks class is defined (Hooks), which uses the interface provided
+by standard modules os and os.path.  It should be used as the base
+class for other hooks classes.
+
+2) A "module loader" class provides an interface to search for a
+module in a search path and to load it.  It defines a method which
+searches for a module in a single directory; by overriding this method
+one can redefine the details of the search.  If the directory is None,
+built-in and frozen modules are searched instead.
+
+Two module loader class are defined, both implementing the search
+strategy used by the built-in __import__ function: ModuleLoader uses
+the imp module's find_module interface, while HookableModuleLoader
+uses a file system hooks class to interact with the file system.  Both
+use the imp module's load_* interfaces to actually load the module.
+
+3) A "module importer" class provides an interface to import a
+module, as well as interfaces to reload and unload a module.  It also
+provides interfaces to install and uninstall itself instead of the
+default __import__ and reload (and unload) functions.
+
+One module importer class is defined (ModuleImporter), which uses a
+module loader instance passed in (by default HookableModuleLoader is
+instantiated).
+
+The classes defined here should be used as base classes for extended
+functionality along those lines.
+
+If a module importer class supports dotted names, its import_module()
+must return a different value depending on whether it is called on
+behalf of a "from ... import ..." statement or not.  (This is caused
+by the way the __import__ hook is used by the Python interpreter.)  It
+would also do wise to install a different version of reload().
+
+"""
+from warnings import warnpy3k, warn
+warnpy3k("the ihooks module has been removed in Python 3.0", stacklevel=2)
+del warnpy3k
+
+import __builtin__
+import imp
+import os
+import sys
+
+__all__ = ["BasicModuleLoader","Hooks","ModuleLoader","FancyModuleLoader",
+           "BasicModuleImporter","ModuleImporter","install","uninstall"]
+
+VERBOSE = 0
+
+
+from imp import C_EXTENSION, PY_SOURCE, PY_COMPILED
+from imp import C_BUILTIN, PY_FROZEN, PKG_DIRECTORY
+BUILTIN_MODULE = C_BUILTIN
+FROZEN_MODULE = PY_FROZEN
+
+
+class _Verbose:
+
+    def __init__(self, verbose = VERBOSE):
+        self.verbose = verbose
+
+    def get_verbose(self):
+        return self.verbose
+
+    def set_verbose(self, verbose):
+        self.verbose = verbose
+
+    # XXX The following is an experimental interface
+
+    def note(self, *args):
+        if self.verbose:
+            self.message(*args)
+
+    def message(self, format, *args):
+        if args:
+            print format%args
+        else:
+            print format
+
+
+class BasicModuleLoader(_Verbose):
+
+    """Basic module loader.
+
+    This provides the same functionality as built-in import.  It
+    doesn't deal with checking sys.modules -- all it provides is
+    find_module() and a load_module(), as well as find_module_in_dir()
+    which searches just one directory, and can be overridden by a
+    derived class to change the module search algorithm when the basic
+    dependency on sys.path is unchanged.
+
+    The interface is a little more convenient than imp's:
+    find_module(name, [path]) returns None or 'stuff', and
+    load_module(name, stuff) loads the module.
+
+    """
+
+    def find_module(self, name, path = None):
+        if path is None:
+            path = [None] + self.default_path()
+        for dir in path:
+            stuff = self.find_module_in_dir(name, dir)
+            if stuff: return stuff
+        return None
+
+    def default_path(self):
+        return sys.path
+
+    def find_module_in_dir(self, name, dir):
+        if dir is None:
+            return self.find_builtin_module(name)
+        else:
+            try:
+                return imp.find_module(name, [dir])
+            except ImportError:
+                return None
+
+    def find_builtin_module(self, name):
+        # XXX frozen packages?
+        if imp.is_builtin(name):
+            return None, '', ('', '', BUILTIN_MODULE)
+        if imp.is_frozen(name):
+            return None, '', ('', '', FROZEN_MODULE)
+        return None
+
+    def load_module(self, name, stuff):
+        file, filename, info = stuff
+        try:
+            return imp.load_module(name, file, filename, info)
+        finally:
+            if file: file.close()
+
+
+class Hooks(_Verbose):
+
+    """Hooks into the filesystem and interpreter.
+
+    By deriving a subclass you can redefine your filesystem interface,
+    e.g. to merge it with the URL space.
+
+    This base class behaves just like the native filesystem.
+
+    """
+
+    # imp interface
+    def get_suffixes(self): return imp.get_suffixes()
+    def new_module(self, name): return imp.new_module(name)
+    def is_builtin(self, name): return imp.is_builtin(name)
+    def init_builtin(self, name): return imp.init_builtin(name)
+    def is_frozen(self, name): return imp.is_frozen(name)
+    def init_frozen(self, name): return imp.init_frozen(name)
+    def get_frozen_object(self, name): return imp.get_frozen_object(name)
+    def load_source(self, name, filename, file=None):
+        return imp.load_source(name, filename, file)
+    def load_compiled(self, name, filename, file=None):
+        return imp.load_compiled(name, filename, file)
+    def load_dynamic(self, name, filename, file=None):
+        return imp.load_dynamic(name, filename, file)
+    def load_package(self, name, filename, file=None):
+        return imp.load_module(name, file, filename, ("", "", PKG_DIRECTORY))
+
+    def add_module(self, name):
+        d = self.modules_dict()
+        if name in d: return d[name]
+        d[name] = m = self.new_module(name)
+        return m
+
+    # sys interface
+    def modules_dict(self): return sys.modules
+    def default_path(self): return sys.path
+
+    def path_split(self, x): return os.path.split(x)
+    def path_join(self, x, y): return os.path.join(x, y)
+    def path_isabs(self, x): return os.path.isabs(x)
+    # etc.
+
+    def path_exists(self, x): return os.path.exists(x)
+    def path_isdir(self, x): return os.path.isdir(x)
+    def path_isfile(self, x): return os.path.isfile(x)
+    def path_islink(self, x): return os.path.islink(x)
+    # etc.
+
+    def openfile(self, *x): return open(*x)
+    openfile_error = IOError
+    def listdir(self, x): return os.listdir(x)
+    listdir_error = os.error
+    # etc.
+
+
+class ModuleLoader(BasicModuleLoader):
+
+    """Default module loader; uses file system hooks.
+
+    By defining suitable hooks, you might be able to load modules from
+    other sources than the file system, e.g. from compressed or
+    encrypted files, tar files or (if you're brave!) URLs.
+
+    """
+
+    def __init__(self, hooks = None, verbose = VERBOSE):
+        BasicModuleLoader.__init__(self, verbose)
+        self.hooks = hooks or Hooks(verbose)
+
+    def default_path(self):
+        return self.hooks.default_path()
+
+    def modules_dict(self):
+        return self.hooks.modules_dict()
+
+    def get_hooks(self):
+        return self.hooks
+
+    def set_hooks(self, hooks):
+        self.hooks = hooks
+
+    def find_builtin_module(self, name):
+        # XXX frozen packages?
+        if self.hooks.is_builtin(name):
+            return None, '', ('', '', BUILTIN_MODULE)
+        if self.hooks.is_frozen(name):
+            return None, '', ('', '', FROZEN_MODULE)
+        return None
+
+    def find_module_in_dir(self, name, dir, allow_packages=1):
+        if dir is None:
+            return self.find_builtin_module(name)
+        if allow_packages:
+            fullname = self.hooks.path_join(dir, name)
+            if self.hooks.path_isdir(fullname):
+                stuff = self.find_module_in_dir("__init__", fullname, 0)
+                if stuff:
+                    file = stuff[0]
+                    if file: file.close()
+                    return None, fullname, ('', '', PKG_DIRECTORY)
+        for info in self.hooks.get_suffixes():
+            suff, mode, type = info
+            fullname = self.hooks.path_join(dir, name+suff)
+            try:
+                fp = self.hooks.openfile(fullname, mode)
+                return fp, fullname, info
+            except self.hooks.openfile_error:
+                pass
+        return None
+
+    def load_module(self, name, stuff):
+        file, filename, info = stuff
+        (suff, mode, type) = info
+        try:
+            if type == BUILTIN_MODULE:
+                return self.hooks.init_builtin(name)
+            if type == FROZEN_MODULE:
+                return self.hooks.init_frozen(name)
+            if type == C_EXTENSION:
+                m = self.hooks.load_dynamic(name, filename, file)
+            elif type == PY_SOURCE:
+                m = self.hooks.load_source(name, filename, file)
+            elif type == PY_COMPILED:
+                m = self.hooks.load_compiled(name, filename, file)
+            elif type == PKG_DIRECTORY:
+                m = self.hooks.load_package(name, filename, file)
+            else:
+                raise ImportError, "Unrecognized module type (%r) for %s" % \
+                      (type, name)
+        finally:
+            if file: file.close()
+        m.__file__ = filename
+        return m
+
+
+class FancyModuleLoader(ModuleLoader):
+
+    """Fancy module loader -- parses and execs the code itself."""
+
+    def load_module(self, name, stuff):
+        file, filename, (suff, mode, type) = stuff
+        realfilename = filename
+        path = None
+
+        if type == PKG_DIRECTORY:
+            initstuff = self.find_module_in_dir("__init__", filename, 0)
+            if not initstuff:
+                raise ImportError, "No __init__ module in package %s" % name
+            initfile, initfilename, initinfo = initstuff
+            initsuff, initmode, inittype = initinfo
+            if inittype not in (PY_COMPILED, PY_SOURCE):
+                if initfile: initfile.close()
+                raise ImportError, \
+                    "Bad type (%r) for __init__ module in package %s" % (
+                    inittype, name)
+            path = [filename]
+            file = initfile
+            realfilename = initfilename
+            type = inittype
+
+        if type == FROZEN_MODULE:
+            code = self.hooks.get_frozen_object(name)
+        elif type == PY_COMPILED:
+            import marshal
+            file.seek(8)
+            code = marshal.load(file)
+        elif type == PY_SOURCE:
+            data = file.read()
+            code = compile(data, realfilename, 'exec')
+        else:
+            return ModuleLoader.load_module(self, name, stuff)
+
+        m = self.hooks.add_module(name)
+        if path:
+            m.__path__ = path
+        m.__file__ = filename
+        try:
+            exec code in m.__dict__
+        except:
+            d = self.hooks.modules_dict()
+            if name in d:
+                del d[name]
+            raise
+        return m
+
+
+class BasicModuleImporter(_Verbose):
+
+    """Basic module importer; uses module loader.
+
+    This provides basic import facilities but no package imports.
+
+    """
+
+    def __init__(self, loader = None, verbose = VERBOSE):
+        _Verbose.__init__(self, verbose)
+        self.loader = loader or ModuleLoader(None, verbose)
+        self.modules = self.loader.modules_dict()
+
+    def get_loader(self):
+        return self.loader
+
+    def set_loader(self, loader):
+        self.loader = loader
+
+    def get_hooks(self):
+        return self.loader.get_hooks()
+
+    def set_hooks(self, hooks):
+        return self.loader.set_hooks(hooks)
+
+    def import_module(self, name, globals={}, locals={}, fromlist=[]):
+        name = str(name)
+        if name in self.modules:
+            return self.modules[name] # Fast path
+        stuff = self.loader.find_module(name)
+        if not stuff:
+            raise ImportError, "No module named %s" % name
+        return self.loader.load_module(name, stuff)
+
+    def reload(self, module, path = None):
+        name = str(module.__name__)
+        stuff = self.loader.find_module(name, path)
+        if not stuff:
+            raise ImportError, "Module %s not found for reload" % name
+        return self.loader.load_module(name, stuff)
+
+    def unload(self, module):
+        del self.modules[str(module.__name__)]
+        # XXX Should this try to clear the module's namespace?
+
+    def install(self):
+        self.save_import_module = __builtin__.__import__
+        self.save_reload = __builtin__.reload
+        if not hasattr(__builtin__, 'unload'):
+            __builtin__.unload = None
+        self.save_unload = __builtin__.unload
+        __builtin__.__import__ = self.import_module
+        __builtin__.reload = self.reload
+        __builtin__.unload = self.unload
+
+    def uninstall(self):
+        __builtin__.__import__ = self.save_import_module
+        __builtin__.reload = self.save_reload
+        __builtin__.unload = self.save_unload
+        if not __builtin__.unload:
+            del __builtin__.unload
+
+
+class ModuleImporter(BasicModuleImporter):
+
+    """A module importer that supports packages."""
+
+    def import_module(self, name, globals=None, locals=None, fromlist=None,
+                      level=-1):
+        parent = self.determine_parent(globals, level)
+        q, tail = self.find_head_package(parent, str(name))
+        m = self.load_tail(q, tail)
+        if not fromlist:
+            return q
+        if hasattr(m, "__path__"):
+            self.ensure_fromlist(m, fromlist)
+        return m
+
+    def determine_parent(self, globals, level=-1):
+        if not globals or not level:
+            return None
+        pkgname = globals.get('__package__')
+        if pkgname is not None:
+            if not pkgname and level > 0:
+                raise ValueError, 'Attempted relative import in non-package'
+        else:
+            # __package__ not set, figure it out and set it
+            modname = globals.get('__name__')
+            if modname is None:
+                return None
+            if "__path__" in globals:
+                # __path__ is set so modname is already the package name
+                pkgname = modname
+            else:
+                # normal module, work out package name if any
+                if '.' not in modname:
+                    if level > 0:
+                        raise ValueError, ('Attempted relative import in '
+                                           'non-package')
+                    globals['__package__'] = None
+                    return None
+                pkgname = modname.rpartition('.')[0]
+            globals['__package__'] = pkgname
+        if level > 0:
+            dot = len(pkgname)
+            for x in range(level, 1, -1):
+                try:
+                    dot = pkgname.rindex('.', 0, dot)
+                except ValueError:
+                    raise ValueError('attempted relative import beyond '
+                                     'top-level package')
+            pkgname = pkgname[:dot]
+        try:
+            return sys.modules[pkgname]
+        except KeyError:
+            if level < 1:
+                warn("Parent module '%s' not found while handling "
+                     "absolute import" % pkgname, RuntimeWarning, 1)
+                return None
+            else:
+                raise SystemError, ("Parent module '%s' not loaded, cannot "
+                                    "perform relative import" % pkgname)
+
+    def find_head_package(self, parent, name):
+        if '.' in name:
+            i = name.find('.')
+            head = name[:i]
+            tail = name[i+1:]
+        else:
+            head = name
+            tail = ""
+        if parent:
+            qname = "%s.%s" % (parent.__name__, head)
+        else:
+            qname = head
+        q = self.import_it(head, qname, parent)
+        if q: return q, tail
+        if parent:
+            qname = head
+            parent = None
+            q = self.import_it(head, qname, parent)
+            if q: return q, tail
+        raise ImportError, "No module named '%s'" % qname
+
+    def load_tail(self, q, tail):
+        m = q
+        while tail:
+            i = tail.find('.')
+            if i < 0: i = len(tail)
+            head, tail = tail[:i], tail[i+1:]
+            mname = "%s.%s" % (m.__name__, head)
+            m = self.import_it(head, mname, m)
+            if not m:
+                raise ImportError, "No module named '%s'" % mname
+        return m
+
+    def ensure_fromlist(self, m, fromlist, recursive=0):
+        for sub in fromlist:
+            if sub == "*":
+                if not recursive:
+                    try:
+                        all = m.__all__
+                    except AttributeError:
+                        pass
+                    else:
+                        self.ensure_fromlist(m, all, 1)
+                continue
+            if sub != "*" and not hasattr(m, sub):
+                subname = "%s.%s" % (m.__name__, sub)
+                submod = self.import_it(sub, subname, m)
+                if not submod:
+                    raise ImportError, "No module named '%s'" % subname
+
+    def import_it(self, partname, fqname, parent, force_load=0):
+        if not partname:
+            # completely empty module name should only happen in
+            # 'from . import' or __import__("")
+            return parent
+        if not force_load:
+            try:
+                return self.modules[fqname]
+            except KeyError:
+                pass
+        try:
+            path = parent and parent.__path__
+        except AttributeError:
+            return None
+        partname = str(partname)
+        stuff = self.loader.find_module(partname, path)
+        if not stuff:
+            return None
+        fqname = str(fqname)
+        m = self.loader.load_module(fqname, stuff)
+        if parent:
+            setattr(parent, partname, m)
+        return m
+
+    def reload(self, module):
+        name = str(module.__name__)
+        if '.' not in name:
+            return self.import_it(name, name, None, force_load=1)
+        i = name.rfind('.')
+        pname = name[:i]
+        parent = self.modules[pname]
+        return self.import_it(name[i+1:], name, parent, force_load=1)
+
+
+default_importer = None
+current_importer = None
+
+def install(importer = None):
+    global current_importer
+    current_importer = importer or default_importer or ModuleImporter()
+    current_importer.install()
+
+def uninstall():
+    global current_importer
+    current_importer.uninstall()
diff --git a/src/main/resources/PythonLibs/imaplib.py b/src/main/resources/PythonLibs/imaplib.py
new file mode 100644
index 0000000000000000000000000000000000000000..c576927a8b0e4c92dd4ca9aad88baff4b3e1de19
--- /dev/null
+++ b/src/main/resources/PythonLibs/imaplib.py
@@ -0,0 +1,1518 @@
+"""IMAP4 client.
+
+Based on RFC 2060.
+
+Public class:           IMAP4
+Public variable:        Debug
+Public functions:       Internaldate2tuple
+                        Int2AP
+                        ParseFlags
+                        Time2Internaldate
+"""
+
+# Author: Piers Lauder <piers@cs.su.oz.au> December 1997.
+#
+# Authentication code contributed by Donn Cave <donn@u.washington.edu> June 1998.
+# String method conversion by ESR, February 2001.
+# GET/SETACL contributed by Anthony Baxter <anthony@interlink.com.au> April 2001.
+# IMAP4_SSL contributed by Tino Lange <Tino.Lange@isg.de> March 2002.
+# GET/SETQUOTA contributed by Andreas Zeidler <az@kreativkombinat.de> June 2002.
+# PROXYAUTH contributed by Rick Holbert <holbert.13@osu.edu> November 2002.
+# GET/SETANNOTATION contributed by Tomas Lindroos <skitta@abo.fi> June 2005.
+
+__version__ = "2.58"
+
+import binascii, errno, random, re, socket, subprocess, sys, time
+
+__all__ = ["IMAP4", "IMAP4_stream", "Internaldate2tuple",
+           "Int2AP", "ParseFlags", "Time2Internaldate"]
+
+#       Globals
+
+CRLF = '\r\n'
+Debug = 0
+IMAP4_PORT = 143
+IMAP4_SSL_PORT = 993
+AllowedVersions = ('IMAP4REV1', 'IMAP4')        # Most recent first
+
+#       Commands
+
+Commands = {
+        # name            valid states
+        'APPEND':       ('AUTH', 'SELECTED'),
+        'AUTHENTICATE': ('NONAUTH',),
+        'CAPABILITY':   ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'),
+        'CHECK':        ('SELECTED',),
+        'CLOSE':        ('SELECTED',),
+        'COPY':         ('SELECTED',),
+        'CREATE':       ('AUTH', 'SELECTED'),
+        'DELETE':       ('AUTH', 'SELECTED'),
+        'DELETEACL':    ('AUTH', 'SELECTED'),
+        'EXAMINE':      ('AUTH', 'SELECTED'),
+        'EXPUNGE':      ('SELECTED',),
+        'FETCH':        ('SELECTED',),
+        'GETACL':       ('AUTH', 'SELECTED'),
+        'GETANNOTATION':('AUTH', 'SELECTED'),
+        'GETQUOTA':     ('AUTH', 'SELECTED'),
+        'GETQUOTAROOT': ('AUTH', 'SELECTED'),
+        'MYRIGHTS':     ('AUTH', 'SELECTED'),
+        'LIST':         ('AUTH', 'SELECTED'),
+        'LOGIN':        ('NONAUTH',),
+        'LOGOUT':       ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'),
+        'LSUB':         ('AUTH', 'SELECTED'),
+        'NAMESPACE':    ('AUTH', 'SELECTED'),
+        'NOOP':         ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'),
+        'PARTIAL':      ('SELECTED',),                                  # NB: obsolete
+        'PROXYAUTH':    ('AUTH',),
+        'RENAME':       ('AUTH', 'SELECTED'),
+        'SEARCH':       ('SELECTED',),
+        'SELECT':       ('AUTH', 'SELECTED'),
+        'SETACL':       ('AUTH', 'SELECTED'),
+        'SETANNOTATION':('AUTH', 'SELECTED'),
+        'SETQUOTA':     ('AUTH', 'SELECTED'),
+        'SORT':         ('SELECTED',),
+        'STATUS':       ('AUTH', 'SELECTED'),
+        'STORE':        ('SELECTED',),
+        'SUBSCRIBE':    ('AUTH', 'SELECTED'),
+        'THREAD':       ('SELECTED',),
+        'UID':          ('SELECTED',),
+        'UNSUBSCRIBE':  ('AUTH', 'SELECTED'),
+        }
+
+#       Patterns to match server responses
+
+Continuation = re.compile(r'\+( (?P<data>.*))?')
+Flags = re.compile(r'.*FLAGS \((?P<flags>[^\)]*)\)')
+InternalDate = re.compile(r'.*INTERNALDATE "'
+        r'(?P<day>[ 0123][0-9])-(?P<mon>[A-Z][a-z][a-z])-(?P<year>[0-9][0-9][0-9][0-9])'
+        r' (?P<hour>[0-9][0-9]):(?P<min>[0-9][0-9]):(?P<sec>[0-9][0-9])'
+        r' (?P<zonen>[-+])(?P<zoneh>[0-9][0-9])(?P<zonem>[0-9][0-9])'
+        r'"')
+Literal = re.compile(r'.*{(?P<size>\d+)}$')
+MapCRLF = re.compile(r'\r\n|\r|\n')
+Response_code = re.compile(r'\[(?P<type>[A-Z-]+)( (?P<data>[^\]]*))?\]')
+Untagged_response = re.compile(r'\* (?P<type>[A-Z-]+)( (?P<data>.*))?')
+Untagged_status = re.compile(r'\* (?P<data>\d+) (?P<type>[A-Z-]+)( (?P<data2>.*))?')
+
+
+
+class IMAP4:
+
+    """IMAP4 client class.
+
+    Instantiate with: IMAP4([host[, port]])
+
+            host - host's name (default: localhost);
+            port - port number (default: standard IMAP4 port).
+
+    All IMAP4rev1 commands are supported by methods of the same
+    name (in lower-case).
+
+    All arguments to commands are converted to strings, except for
+    AUTHENTICATE, and the last argument to APPEND which is passed as
+    an IMAP4 literal.  If necessary (the string contains any
+    non-printing characters or white-space and isn't enclosed with
+    either parentheses or double quotes) each string is quoted.
+    However, the 'password' argument to the LOGIN command is always
+    quoted.  If you want to avoid having an argument string quoted
+    (eg: the 'flags' argument to STORE) then enclose the string in
+    parentheses (eg: "(\Deleted)").
+
+    Each command returns a tuple: (type, [data, ...]) where 'type'
+    is usually 'OK' or 'NO', and 'data' is either the text from the
+    tagged response, or untagged results from command. Each 'data'
+    is either a string, or a tuple. If a tuple, then the first part
+    is the header of the response, and the second part contains
+    the data (ie: 'literal' value).
+
+    Errors raise the exception class <instance>.error("<reason>").
+    IMAP4 server errors raise <instance>.abort("<reason>"),
+    which is a sub-class of 'error'. Mailbox status changes
+    from READ-WRITE to READ-ONLY raise the exception class
+    <instance>.readonly("<reason>"), which is a sub-class of 'abort'.
+
+    "error" exceptions imply a program error.
+    "abort" exceptions imply the connection should be reset, and
+            the command re-tried.
+    "readonly" exceptions imply the command should be re-tried.
+
+    Note: to use this module, you must read the RFCs pertaining to the
+    IMAP4 protocol, as the semantics of the arguments to each IMAP4
+    command are left to the invoker, not to mention the results. Also,
+    most IMAP servers implement a sub-set of the commands available here.
+    """
+
+    class error(Exception): pass    # Logical errors - debug required
+    class abort(error): pass        # Service errors - close and retry
+    class readonly(abort): pass     # Mailbox status changed to READ-ONLY
+
+    mustquote = re.compile(r"[^\w!#$%&'*+,.:;<=>?^`|~-]")
+
+    def __init__(self, host = '', port = IMAP4_PORT):
+        self.debug = Debug
+        self.state = 'LOGOUT'
+        self.literal = None             # A literal argument to a command
+        self.tagged_commands = {}       # Tagged commands awaiting response
+        self.untagged_responses = {}    # {typ: [data, ...], ...}
+        self.continuation_response = '' # Last continuation response
+        self.is_readonly = False        # READ-ONLY desired state
+        self.tagnum = 0
+
+        # Open socket to server.
+
+        self.open(host, port)
+
+        # Create unique tag for this session,
+        # and compile tagged response matcher.
+
+        self.tagpre = Int2AP(random.randint(4096, 65535))
+        self.tagre = re.compile(r'(?P<tag>'
+                        + self.tagpre
+                        + r'\d+) (?P<type>[A-Z]+) (?P<data>.*)')
+
+        # Get server welcome message,
+        # request and store CAPABILITY response.
+
+        if __debug__:
+            self._cmd_log_len = 10
+            self._cmd_log_idx = 0
+            self._cmd_log = {}           # Last `_cmd_log_len' interactions
+            if self.debug >= 1:
+                self._mesg('imaplib version %s' % __version__)
+                self._mesg('new IMAP4 connection, tag=%s' % self.tagpre)
+
+        self.welcome = self._get_response()
+        if 'PREAUTH' in self.untagged_responses:
+            self.state = 'AUTH'
+        elif 'OK' in self.untagged_responses:
+            self.state = 'NONAUTH'
+        else:
+            raise self.error(self.welcome)
+
+        typ, dat = self.capability()
+        if dat == [None]:
+            raise self.error('no CAPABILITY response from server')
+        self.capabilities = tuple(dat[-1].upper().split())
+
+        if __debug__:
+            if self.debug >= 3:
+                self._mesg('CAPABILITIES: %r' % (self.capabilities,))
+
+        for version in AllowedVersions:
+            if not version in self.capabilities:
+                continue
+            self.PROTOCOL_VERSION = version
+            return
+
+        raise self.error('server not IMAP4 compliant')
+
+
+    def __getattr__(self, attr):
+        #       Allow UPPERCASE variants of IMAP4 command methods.
+        if attr in Commands:
+            return getattr(self, attr.lower())
+        raise AttributeError("Unknown IMAP4 command: '%s'" % attr)
+
+
+
+    #       Overridable methods
+
+
+    def open(self, host = '', port = IMAP4_PORT):
+        """Setup connection to remote server on "host:port"
+            (default: localhost:standard IMAP4 port).
+        This connection will be used by the routines:
+            read, readline, send, shutdown.
+        """
+        self.host = host
+        self.port = port
+        self.sock = socket.create_connection((host, port))
+        self.file = self.sock.makefile('rb')
+
+
+    def read(self, size):
+        """Read 'size' bytes from remote."""
+        return self.file.read(size)
+
+
+    def readline(self):
+        """Read line from remote."""
+        return self.file.readline()
+
+
+    def send(self, data):
+        """Send data to remote."""
+        self.sock.sendall(data)
+
+
+    def shutdown(self):
+        """Close I/O established in "open"."""
+        self.file.close()
+        try:
+            self.sock.shutdown(socket.SHUT_RDWR)
+        except socket.error as e:
+            # The server might already have closed the connection
+            if e.errno != errno.ENOTCONN:
+                raise
+        finally:
+            self.sock.close()
+
+
+    def socket(self):
+        """Return socket instance used to connect to IMAP4 server.
+
+        socket = <instance>.socket()
+        """
+        return self.sock
+
+
+
+    #       Utility methods
+
+
+    def recent(self):
+        """Return most recent 'RECENT' responses if any exist,
+        else prompt server for an update using the 'NOOP' command.
+
+        (typ, [data]) = <instance>.recent()
+
+        'data' is None if no new messages,
+        else list of RECENT responses, most recent last.
+        """
+        name = 'RECENT'
+        typ, dat = self._untagged_response('OK', [None], name)
+        if dat[-1]:
+            return typ, dat
+        typ, dat = self.noop()  # Prod server for response
+        return self._untagged_response(typ, dat, name)
+
+
+    def response(self, code):
+        """Return data for response 'code' if received, or None.
+
+        Old value for response 'code' is cleared.
+
+        (code, [data]) = <instance>.response(code)
+        """
+        return self._untagged_response(code, [None], code.upper())
+
+
+
+    #       IMAP4 commands
+
+
+    def append(self, mailbox, flags, date_time, message):
+        """Append message to named mailbox.
+
+        (typ, [data]) = <instance>.append(mailbox, flags, date_time, message)
+
+                All args except `message' can be None.
+        """
+        name = 'APPEND'
+        if not mailbox:
+            mailbox = 'INBOX'
+        if flags:
+            if (flags[0],flags[-1]) != ('(',')'):
+                flags = '(%s)' % flags
+        else:
+            flags = None
+        if date_time:
+            date_time = Time2Internaldate(date_time)
+        else:
+            date_time = None
+        self.literal = MapCRLF.sub(CRLF, message)
+        return self._simple_command(name, mailbox, flags, date_time)
+
+
+    def authenticate(self, mechanism, authobject):
+        """Authenticate command - requires response processing.
+
+        'mechanism' specifies which authentication mechanism is to
+        be used - it must appear in <instance>.capabilities in the
+        form AUTH=<mechanism>.
+
+        'authobject' must be a callable object:
+
+                data = authobject(response)
+
+        It will be called to process server continuation responses.
+        It should return data that will be encoded and sent to server.
+        It should return None if the client abort response '*' should
+        be sent instead.
+        """
+        mech = mechanism.upper()
+        # XXX: shouldn't this code be removed, not commented out?
+        #cap = 'AUTH=%s' % mech
+        #if not cap in self.capabilities:       # Let the server decide!
+        #    raise self.error("Server doesn't allow %s authentication." % mech)
+        self.literal = _Authenticator(authobject).process
+        typ, dat = self._simple_command('AUTHENTICATE', mech)
+        if typ != 'OK':
+            raise self.error(dat[-1])
+        self.state = 'AUTH'
+        return typ, dat
+
+
+    def capability(self):
+        """(typ, [data]) = <instance>.capability()
+        Fetch capabilities list from server."""
+
+        name = 'CAPABILITY'
+        typ, dat = self._simple_command(name)
+        return self._untagged_response(typ, dat, name)
+
+
+    def check(self):
+        """Checkpoint mailbox on server.
+
+        (typ, [data]) = <instance>.check()
+        """
+        return self._simple_command('CHECK')
+
+
+    def close(self):
+        """Close currently selected mailbox.
+
+        Deleted messages are removed from writable mailbox.
+        This is the recommended command before 'LOGOUT'.
+
+        (typ, [data]) = <instance>.close()
+        """
+        try:
+            typ, dat = self._simple_command('CLOSE')
+        finally:
+            self.state = 'AUTH'
+        return typ, dat
+
+
+    def copy(self, message_set, new_mailbox):
+        """Copy 'message_set' messages onto end of 'new_mailbox'.
+
+        (typ, [data]) = <instance>.copy(message_set, new_mailbox)
+        """
+        return self._simple_command('COPY', message_set, new_mailbox)
+
+
+    def create(self, mailbox):
+        """Create new mailbox.
+
+        (typ, [data]) = <instance>.create(mailbox)
+        """
+        return self._simple_command('CREATE', mailbox)
+
+
+    def delete(self, mailbox):
+        """Delete old mailbox.
+
+        (typ, [data]) = <instance>.delete(mailbox)
+        """
+        return self._simple_command('DELETE', mailbox)
+
+    def deleteacl(self, mailbox, who):
+        """Delete the ACLs (remove any rights) set for who on mailbox.
+
+        (typ, [data]) = <instance>.deleteacl(mailbox, who)
+        """
+        return self._simple_command('DELETEACL', mailbox, who)
+
+    def expunge(self):
+        """Permanently remove deleted items from selected mailbox.
+
+        Generates 'EXPUNGE' response for each deleted message.
+
+        (typ, [data]) = <instance>.expunge()
+
+        'data' is list of 'EXPUNGE'd message numbers in order received.
+        """
+        name = 'EXPUNGE'
+        typ, dat = self._simple_command(name)
+        return self._untagged_response(typ, dat, name)
+
+
+    def fetch(self, message_set, message_parts):
+        """Fetch (parts of) messages.
+
+        (typ, [data, ...]) = <instance>.fetch(message_set, message_parts)
+
+        'message_parts' should be a string of selected parts
+        enclosed in parentheses, eg: "(UID BODY[TEXT])".
+
+        'data' are tuples of message part envelope and data.
+        """
+        name = 'FETCH'
+        typ, dat = self._simple_command(name, message_set, message_parts)
+        return self._untagged_response(typ, dat, name)
+
+
+    def getacl(self, mailbox):
+        """Get the ACLs for a mailbox.
+
+        (typ, [data]) = <instance>.getacl(mailbox)
+        """
+        typ, dat = self._simple_command('GETACL', mailbox)
+        return self._untagged_response(typ, dat, 'ACL')
+
+
+    def getannotation(self, mailbox, entry, attribute):
+        """(typ, [data]) = <instance>.getannotation(mailbox, entry, attribute)
+        Retrieve ANNOTATIONs."""
+
+        typ, dat = self._simple_command('GETANNOTATION', mailbox, entry, attribute)
+        return self._untagged_response(typ, dat, 'ANNOTATION')
+
+
+    def getquota(self, root):
+        """Get the quota root's resource usage and limits.
+
+        Part of the IMAP4 QUOTA extension defined in rfc2087.
+
+        (typ, [data]) = <instance>.getquota(root)
+        """
+        typ, dat = self._simple_command('GETQUOTA', root)
+        return self._untagged_response(typ, dat, 'QUOTA')
+
+
+    def getquotaroot(self, mailbox):
+        """Get the list of quota roots for the named mailbox.
+
+        (typ, [[QUOTAROOT responses...], [QUOTA responses]]) = <instance>.getquotaroot(mailbox)
+        """
+        typ, dat = self._simple_command('GETQUOTAROOT', mailbox)
+        typ, quota = self._untagged_response(typ, dat, 'QUOTA')
+        typ, quotaroot = self._untagged_response(typ, dat, 'QUOTAROOT')
+        return typ, [quotaroot, quota]
+
+
+    def list(self, directory='""', pattern='*'):
+        """List mailbox names in directory matching pattern.
+
+        (typ, [data]) = <instance>.list(directory='""', pattern='*')
+
+        'data' is list of LIST responses.
+        """
+        name = 'LIST'
+        typ, dat = self._simple_command(name, directory, pattern)
+        return self._untagged_response(typ, dat, name)
+
+
+    def login(self, user, password):
+        """Identify client using plaintext password.
+
+        (typ, [data]) = <instance>.login(user, password)
+
+        NB: 'password' will be quoted.
+        """
+        typ, dat = self._simple_command('LOGIN', user, self._quote(password))
+        if typ != 'OK':
+            raise self.error(dat[-1])
+        self.state = 'AUTH'
+        return typ, dat
+
+
+    def login_cram_md5(self, user, password):
+        """ Force use of CRAM-MD5 authentication.
+
+        (typ, [data]) = <instance>.login_cram_md5(user, password)
+        """
+        self.user, self.password = user, password
+        return self.authenticate('CRAM-MD5', self._CRAM_MD5_AUTH)
+
+
+    def _CRAM_MD5_AUTH(self, challenge):
+        """ Authobject to use with CRAM-MD5 authentication. """
+        import hmac
+        return self.user + " " + hmac.HMAC(self.password, challenge).hexdigest()
+
+
+    def logout(self):
+        """Shutdown connection to server.
+
+        (typ, [data]) = <instance>.logout()
+
+        Returns server 'BYE' response.
+        """
+        self.state = 'LOGOUT'
+        try: typ, dat = self._simple_command('LOGOUT')
+        except: typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]]
+        self.shutdown()
+        if 'BYE' in self.untagged_responses:
+            return 'BYE', self.untagged_responses['BYE']
+        return typ, dat
+
+
+    def lsub(self, directory='""', pattern='*'):
+        """List 'subscribed' mailbox names in directory matching pattern.
+
+        (typ, [data, ...]) = <instance>.lsub(directory='""', pattern='*')
+
+        'data' are tuples of message part envelope and data.
+        """
+        name = 'LSUB'
+        typ, dat = self._simple_command(name, directory, pattern)
+        return self._untagged_response(typ, dat, name)
+
+    def myrights(self, mailbox):
+        """Show my ACLs for a mailbox (i.e. the rights that I have on mailbox).
+
+        (typ, [data]) = <instance>.myrights(mailbox)
+        """
+        typ,dat = self._simple_command('MYRIGHTS', mailbox)
+        return self._untagged_response(typ, dat, 'MYRIGHTS')
+
+    def namespace(self):
+        """ Returns IMAP namespaces ala rfc2342
+
+        (typ, [data, ...]) = <instance>.namespace()
+        """
+        name = 'NAMESPACE'
+        typ, dat = self._simple_command(name)
+        return self._untagged_response(typ, dat, name)
+
+
+    def noop(self):
+        """Send NOOP command.
+
+        (typ, [data]) = <instance>.noop()
+        """
+        if __debug__:
+            if self.debug >= 3:
+                self._dump_ur(self.untagged_responses)
+        return self._simple_command('NOOP')
+
+
+    def partial(self, message_num, message_part, start, length):
+        """Fetch truncated part of a message.
+
+        (typ, [data, ...]) = <instance>.partial(message_num, message_part, start, length)
+
+        'data' is tuple of message part envelope and data.
+        """
+        name = 'PARTIAL'
+        typ, dat = self._simple_command(name, message_num, message_part, start, length)
+        return self._untagged_response(typ, dat, 'FETCH')
+
+
+    def proxyauth(self, user):
+        """Assume authentication as "user".
+
+        Allows an authorised administrator to proxy into any user's
+        mailbox.
+
+        (typ, [data]) = <instance>.proxyauth(user)
+        """
+
+        name = 'PROXYAUTH'
+        return self._simple_command('PROXYAUTH', user)
+
+
+    def rename(self, oldmailbox, newmailbox):
+        """Rename old mailbox name to new.
+
+        (typ, [data]) = <instance>.rename(oldmailbox, newmailbox)
+        """
+        return self._simple_command('RENAME', oldmailbox, newmailbox)
+
+
+    def search(self, charset, *criteria):
+        """Search mailbox for matching messages.
+
+        (typ, [data]) = <instance>.search(charset, criterion, ...)
+
+        'data' is space separated list of matching message numbers.
+        """
+        name = 'SEARCH'
+        if charset:
+            typ, dat = self._simple_command(name, 'CHARSET', charset, *criteria)
+        else:
+            typ, dat = self._simple_command(name, *criteria)
+        return self._untagged_response(typ, dat, name)
+
+
+    def select(self, mailbox='INBOX', readonly=False):
+        """Select a mailbox.
+
+        Flush all untagged responses.
+
+        (typ, [data]) = <instance>.select(mailbox='INBOX', readonly=False)
+
+        'data' is count of messages in mailbox ('EXISTS' response).
+
+        Mandated responses are ('FLAGS', 'EXISTS', 'RECENT', 'UIDVALIDITY'), so
+        other responses should be obtained via <instance>.response('FLAGS') etc.
+        """
+        self.untagged_responses = {}    # Flush old responses.
+        self.is_readonly = readonly
+        if readonly:
+            name = 'EXAMINE'
+        else:
+            name = 'SELECT'
+        typ, dat = self._simple_command(name, mailbox)
+        if typ != 'OK':
+            self.state = 'AUTH'     # Might have been 'SELECTED'
+            return typ, dat
+        self.state = 'SELECTED'
+        if 'READ-ONLY' in self.untagged_responses \
+                and not readonly:
+            if __debug__:
+                if self.debug >= 1:
+                    self._dump_ur(self.untagged_responses)
+            raise self.readonly('%s is not writable' % mailbox)
+        return typ, self.untagged_responses.get('EXISTS', [None])
+
+
+    def setacl(self, mailbox, who, what):
+        """Set a mailbox acl.
+
+        (typ, [data]) = <instance>.setacl(mailbox, who, what)
+        """
+        return self._simple_command('SETACL', mailbox, who, what)
+
+
+    def setannotation(self, *args):
+        """(typ, [data]) = <instance>.setannotation(mailbox[, entry, attribute]+)
+        Set ANNOTATIONs."""
+
+        typ, dat = self._simple_command('SETANNOTATION', *args)
+        return self._untagged_response(typ, dat, 'ANNOTATION')
+
+
+    def setquota(self, root, limits):
+        """Set the quota root's resource limits.
+
+        (typ, [data]) = <instance>.setquota(root, limits)
+        """
+        typ, dat = self._simple_command('SETQUOTA', root, limits)
+        return self._untagged_response(typ, dat, 'QUOTA')
+
+
+    def sort(self, sort_criteria, charset, *search_criteria):
+        """IMAP4rev1 extension SORT command.
+
+        (typ, [data]) = <instance>.sort(sort_criteria, charset, search_criteria, ...)
+        """
+        name = 'SORT'
+        #if not name in self.capabilities:      # Let the server decide!
+        #       raise self.error('unimplemented extension command: %s' % name)
+        if (sort_criteria[0],sort_criteria[-1]) != ('(',')'):
+            sort_criteria = '(%s)' % sort_criteria
+        typ, dat = self._simple_command(name, sort_criteria, charset, *search_criteria)
+        return self._untagged_response(typ, dat, name)
+
+
+    def status(self, mailbox, names):
+        """Request named status conditions for mailbox.
+
+        (typ, [data]) = <instance>.status(mailbox, names)
+        """
+        name = 'STATUS'
+        #if self.PROTOCOL_VERSION == 'IMAP4':   # Let the server decide!
+        #    raise self.error('%s unimplemented in IMAP4 (obtain IMAP4rev1 server, or re-code)' % name)
+        typ, dat = self._simple_command(name, mailbox, names)
+        return self._untagged_response(typ, dat, name)
+
+
+    def store(self, message_set, command, flags):
+        """Alters flag dispositions for messages in mailbox.
+
+        (typ, [data]) = <instance>.store(message_set, command, flags)
+        """
+        if (flags[0],flags[-1]) != ('(',')'):
+            flags = '(%s)' % flags  # Avoid quoting the flags
+        typ, dat = self._simple_command('STORE', message_set, command, flags)
+        return self._untagged_response(typ, dat, 'FETCH')
+
+
+    def subscribe(self, mailbox):
+        """Subscribe to new mailbox.
+
+        (typ, [data]) = <instance>.subscribe(mailbox)
+        """
+        return self._simple_command('SUBSCRIBE', mailbox)
+
+
+    def thread(self, threading_algorithm, charset, *search_criteria):
+        """IMAPrev1 extension THREAD command.
+
+        (type, [data]) = <instance>.thread(threading_algorithm, charset, search_criteria, ...)
+        """
+        name = 'THREAD'
+        typ, dat = self._simple_command(name, threading_algorithm, charset, *search_criteria)
+        return self._untagged_response(typ, dat, name)
+
+
+    def uid(self, command, *args):
+        """Execute "command arg ..." with messages identified by UID,
+                rather than message number.
+
+        (typ, [data]) = <instance>.uid(command, arg1, arg2, ...)
+
+        Returns response appropriate to 'command'.
+        """
+        command = command.upper()
+        if not command in Commands:
+            raise self.error("Unknown IMAP4 UID command: %s" % command)
+        if self.state not in Commands[command]:
+            raise self.error("command %s illegal in state %s, "
+                             "only allowed in states %s" %
+                             (command, self.state,
+                              ', '.join(Commands[command])))
+        name = 'UID'
+        typ, dat = self._simple_command(name, command, *args)
+        if command in ('SEARCH', 'SORT', 'THREAD'):
+            name = command
+        else:
+            name = 'FETCH'
+        return self._untagged_response(typ, dat, name)
+
+
+    def unsubscribe(self, mailbox):
+        """Unsubscribe from old mailbox.
+
+        (typ, [data]) = <instance>.unsubscribe(mailbox)
+        """
+        return self._simple_command('UNSUBSCRIBE', mailbox)
+
+
+    def xatom(self, name, *args):
+        """Allow simple extension commands
+                notified by server in CAPABILITY response.
+
+        Assumes command is legal in current state.
+
+        (typ, [data]) = <instance>.xatom(name, arg, ...)
+
+        Returns response appropriate to extension command `name'.
+        """
+        name = name.upper()
+        #if not name in self.capabilities:      # Let the server decide!
+        #    raise self.error('unknown extension command: %s' % name)
+        if not name in Commands:
+            Commands[name] = (self.state,)
+        return self._simple_command(name, *args)
+
+
+
+    #       Private methods
+
+
+    def _append_untagged(self, typ, dat):
+
+        if dat is None: dat = ''
+        ur = self.untagged_responses
+        if __debug__:
+            if self.debug >= 5:
+                self._mesg('untagged_responses[%s] %s += ["%s"]' %
+                        (typ, len(ur.get(typ,'')), dat))
+        if typ in ur:
+            ur[typ].append(dat)
+        else:
+            ur[typ] = [dat]
+
+
+    def _check_bye(self):
+        bye = self.untagged_responses.get('BYE')
+        if bye:
+            raise self.abort(bye[-1])
+
+
+    def _command(self, name, *args):
+
+        if self.state not in Commands[name]:
+            self.literal = None
+            raise self.error("command %s illegal in state %s, "
+                             "only allowed in states %s" %
+                             (name, self.state,
+                              ', '.join(Commands[name])))
+
+        for typ in ('OK', 'NO', 'BAD'):
+            if typ in self.untagged_responses:
+                del self.untagged_responses[typ]
+
+        if 'READ-ONLY' in self.untagged_responses \
+        and not self.is_readonly:
+            raise self.readonly('mailbox status changed to READ-ONLY')
+
+        tag = self._new_tag()
+        data = '%s %s' % (tag, name)
+        for arg in args:
+            if arg is None: continue
+            data = '%s %s' % (data, self._checkquote(arg))
+
+        literal = self.literal
+        if literal is not None:
+            self.literal = None
+            if type(literal) is type(self._command):
+                literator = literal
+            else:
+                literator = None
+                data = '%s {%s}' % (data, len(literal))
+
+        if __debug__:
+            if self.debug >= 4:
+                self._mesg('> %s' % data)
+            else:
+                self._log('> %s' % data)
+
+        try:
+            self.send('%s%s' % (data, CRLF))
+        except (socket.error, OSError), val:
+            raise self.abort('socket error: %s' % val)
+
+        if literal is None:
+            return tag
+
+        while 1:
+            # Wait for continuation response
+
+            while self._get_response():
+                if self.tagged_commands[tag]:   # BAD/NO?
+                    return tag
+
+            # Send literal
+
+            if literator:
+                literal = literator(self.continuation_response)
+
+            if __debug__:
+                if self.debug >= 4:
+                    self._mesg('write literal size %s' % len(literal))
+
+            try:
+                self.send(literal)
+                self.send(CRLF)
+            except (socket.error, OSError), val:
+                raise self.abort('socket error: %s' % val)
+
+            if not literator:
+                break
+
+        return tag
+
+
+    def _command_complete(self, name, tag):
+        # BYE is expected after LOGOUT
+        if name != 'LOGOUT':
+            self._check_bye()
+        try:
+            typ, data = self._get_tagged_response(tag)
+        except self.abort, val:
+            raise self.abort('command: %s => %s' % (name, val))
+        except self.error, val:
+            raise self.error('command: %s => %s' % (name, val))
+        if name != 'LOGOUT':
+            self._check_bye()
+        if typ == 'BAD':
+            raise self.error('%s command error: %s %s' % (name, typ, data))
+        return typ, data
+
+
+    def _get_response(self):
+
+        # Read response and store.
+        #
+        # Returns None for continuation responses,
+        # otherwise first response line received.
+
+        resp = self._get_line()
+
+        # Command completion response?
+
+        if self._match(self.tagre, resp):
+            tag = self.mo.group('tag')
+            if not tag in self.tagged_commands:
+                raise self.abort('unexpected tagged response: %s' % resp)
+
+            typ = self.mo.group('type')
+            dat = self.mo.group('data')
+            self.tagged_commands[tag] = (typ, [dat])
+        else:
+            dat2 = None
+
+            # '*' (untagged) responses?
+
+            if not self._match(Untagged_response, resp):
+                if self._match(Untagged_status, resp):
+                    dat2 = self.mo.group('data2')
+
+            if self.mo is None:
+                # Only other possibility is '+' (continuation) response...
+
+                if self._match(Continuation, resp):
+                    self.continuation_response = self.mo.group('data')
+                    return None     # NB: indicates continuation
+
+                raise self.abort("unexpected response: '%s'" % resp)
+
+            typ = self.mo.group('type')
+            dat = self.mo.group('data')
+            if dat is None: dat = ''        # Null untagged response
+            if dat2: dat = dat + ' ' + dat2
+
+            # Is there a literal to come?
+
+            while self._match(Literal, dat):
+
+                # Read literal direct from connection.
+
+                size = int(self.mo.group('size'))
+                if __debug__:
+                    if self.debug >= 4:
+                        self._mesg('read literal size %s' % size)
+                data = self.read(size)
+
+                # Store response with literal as tuple
+
+                self._append_untagged(typ, (dat, data))
+
+                # Read trailer - possibly containing another literal
+
+                dat = self._get_line()
+
+            self._append_untagged(typ, dat)
+
+        # Bracketed response information?
+
+        if typ in ('OK', 'NO', 'BAD') and self._match(Response_code, dat):
+            self._append_untagged(self.mo.group('type'), self.mo.group('data'))
+
+        if __debug__:
+            if self.debug >= 1 and typ in ('NO', 'BAD', 'BYE'):
+                self._mesg('%s response: %s' % (typ, dat))
+
+        return resp
+
+
+    def _get_tagged_response(self, tag):
+
+        while 1:
+            result = self.tagged_commands[tag]
+            if result is not None:
+                del self.tagged_commands[tag]
+                return result
+
+            # Some have reported "unexpected response" exceptions.
+            # Note that ignoring them here causes loops.
+            # Instead, send me details of the unexpected response and
+            # I'll update the code in `_get_response()'.
+
+            try:
+                self._get_response()
+            except self.abort, val:
+                if __debug__:
+                    if self.debug >= 1:
+                        self.print_log()
+                raise
+
+
+    def _get_line(self):
+
+        line = self.readline()
+        if not line:
+            raise self.abort('socket error: EOF')
+
+        # Protocol mandates all lines terminated by CRLF
+        if not line.endswith('\r\n'):
+            raise self.abort('socket error: unterminated line')
+
+        line = line[:-2]
+        if __debug__:
+            if self.debug >= 4:
+                self._mesg('< %s' % line)
+            else:
+                self._log('< %s' % line)
+        return line
+
+
+    def _match(self, cre, s):
+
+        # Run compiled regular expression match method on 's'.
+        # Save result, return success.
+
+        self.mo = cre.match(s)
+        if __debug__:
+            if self.mo is not None and self.debug >= 5:
+                self._mesg("\tmatched r'%s' => %r" % (cre.pattern, self.mo.groups()))
+        return self.mo is not None
+
+
+    def _new_tag(self):
+
+        tag = '%s%s' % (self.tagpre, self.tagnum)
+        self.tagnum = self.tagnum + 1
+        self.tagged_commands[tag] = None
+        return tag
+
+
+    def _checkquote(self, arg):
+
+        # Must quote command args if non-alphanumeric chars present,
+        # and not already quoted.
+
+        if type(arg) is not type(''):
+            return arg
+        if len(arg) >= 2 and (arg[0],arg[-1]) in (('(',')'),('"','"')):
+            return arg
+        if arg and self.mustquote.search(arg) is None:
+            return arg
+        return self._quote(arg)
+
+
+    def _quote(self, arg):
+
+        arg = arg.replace('\\', '\\\\')
+        arg = arg.replace('"', '\\"')
+
+        return '"%s"' % arg
+
+
+    def _simple_command(self, name, *args):
+
+        return self._command_complete(name, self._command(name, *args))
+
+
+    def _untagged_response(self, typ, dat, name):
+
+        if typ == 'NO':
+            return typ, dat
+        if not name in self.untagged_responses:
+            return typ, [None]
+        data = self.untagged_responses.pop(name)
+        if __debug__:
+            if self.debug >= 5:
+                self._mesg('untagged_responses[%s] => %s' % (name, data))
+        return typ, data
+
+
+    if __debug__:
+
+        def _mesg(self, s, secs=None):
+            if secs is None:
+                secs = time.time()
+            tm = time.strftime('%M:%S', time.localtime(secs))
+            sys.stderr.write('  %s.%02d %s\n' % (tm, (secs*100)%100, s))
+            sys.stderr.flush()
+
+        def _dump_ur(self, dict):
+            # Dump untagged responses (in `dict').
+            l = dict.items()
+            if not l: return
+            t = '\n\t\t'
+            l = map(lambda x:'%s: "%s"' % (x[0], x[1][0] and '" "'.join(x[1]) or ''), l)
+            self._mesg('untagged responses dump:%s%s' % (t, t.join(l)))
+
+        def _log(self, line):
+            # Keep log of last `_cmd_log_len' interactions for debugging.
+            self._cmd_log[self._cmd_log_idx] = (line, time.time())
+            self._cmd_log_idx += 1
+            if self._cmd_log_idx >= self._cmd_log_len:
+                self._cmd_log_idx = 0
+
+        def print_log(self):
+            self._mesg('last %d IMAP4 interactions:' % len(self._cmd_log))
+            i, n = self._cmd_log_idx, self._cmd_log_len
+            while n:
+                try:
+                    self._mesg(*self._cmd_log[i])
+                except:
+                    pass
+                i += 1
+                if i >= self._cmd_log_len:
+                    i = 0
+                n -= 1
+
+
+
+try:
+    import ssl
+except ImportError:
+    pass
+else:
+    class IMAP4_SSL(IMAP4):
+
+        """IMAP4 client class over SSL connection
+
+        Instantiate with: IMAP4_SSL([host[, port[, keyfile[, certfile]]]])
+
+                host - host's name (default: localhost);
+                port - port number (default: standard IMAP4 SSL port).
+                keyfile - PEM formatted file that contains your private key (default: None);
+                certfile - PEM formatted certificate chain file (default: None);
+
+        for more documentation see the docstring of the parent class IMAP4.
+        """
+
+
+        def __init__(self, host = '', port = IMAP4_SSL_PORT, keyfile = None, certfile = None):
+            self.keyfile = keyfile
+            self.certfile = certfile
+            IMAP4.__init__(self, host, port)
+
+
+        def open(self, host = '', port = IMAP4_SSL_PORT):
+            """Setup connection to remote server on "host:port".
+                (default: localhost:standard IMAP4 SSL port).
+            This connection will be used by the routines:
+                read, readline, send, shutdown.
+            """
+            self.host = host
+            self.port = port
+            self.sock = socket.create_connection((host, port))
+            self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile)
+            self.file = self.sslobj.makefile('rb')
+
+
+        def read(self, size):
+            """Read 'size' bytes from remote."""
+            return self.file.read(size)
+
+
+        def readline(self):
+            """Read line from remote."""
+            return self.file.readline()
+
+
+        def send(self, data):
+            """Send data to remote."""
+            bytes = len(data)
+            while bytes > 0:
+                sent = self.sslobj.write(data)
+                if sent == bytes:
+                    break    # avoid copy
+                data = data[sent:]
+                bytes = bytes - sent
+
+
+        def shutdown(self):
+            """Close I/O established in "open"."""
+            self.file.close()
+            self.sock.close()
+
+
+        def socket(self):
+            """Return socket instance used to connect to IMAP4 server.
+
+            socket = <instance>.socket()
+            """
+            return self.sock
+
+
+        def ssl(self):
+            """Return SSLObject instance used to communicate with the IMAP4 server.
+
+            ssl = ssl.wrap_socket(<instance>.socket)
+            """
+            return self.sslobj
+
+    __all__.append("IMAP4_SSL")
+
+
+class IMAP4_stream(IMAP4):
+
+    """IMAP4 client class over a stream
+
+    Instantiate with: IMAP4_stream(command)
+
+            where "command" is a string that can be passed to subprocess.Popen()
+
+    for more documentation see the docstring of the parent class IMAP4.
+    """
+
+
+    def __init__(self, command):
+        self.command = command
+        IMAP4.__init__(self)
+
+
+    def open(self, host = None, port = None):
+        """Setup a stream connection.
+        This connection will be used by the routines:
+            read, readline, send, shutdown.
+        """
+        self.host = None        # For compatibility with parent class
+        self.port = None
+        self.sock = None
+        self.file = None
+        self.process = subprocess.Popen(self.command,
+            stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+            shell=True, close_fds=True)
+        self.writefile = self.process.stdin
+        self.readfile = self.process.stdout
+
+
+    def read(self, size):
+        """Read 'size' bytes from remote."""
+        return self.readfile.read(size)
+
+
+    def readline(self):
+        """Read line from remote."""
+        return self.readfile.readline()
+
+
+    def send(self, data):
+        """Send data to remote."""
+        self.writefile.write(data)
+        self.writefile.flush()
+
+
+    def shutdown(self):
+        """Close I/O established in "open"."""
+        self.readfile.close()
+        self.writefile.close()
+        self.process.wait()
+
+
+
+class _Authenticator:
+
+    """Private class to provide en/decoding
+            for base64-based authentication conversation.
+    """
+
+    def __init__(self, mechinst):
+        self.mech = mechinst    # Callable object to provide/process data
+
+    def process(self, data):
+        ret = self.mech(self.decode(data))
+        if ret is None:
+            return '*'      # Abort conversation
+        return self.encode(ret)
+
+    def encode(self, inp):
+        #
+        #  Invoke binascii.b2a_base64 iteratively with
+        #  short even length buffers, strip the trailing
+        #  line feed from the result and append.  "Even"
+        #  means a number that factors to both 6 and 8,
+        #  so when it gets to the end of the 8-bit input
+        #  there's no partial 6-bit output.
+        #
+        oup = ''
+        while inp:
+            if len(inp) > 48:
+                t = inp[:48]
+                inp = inp[48:]
+            else:
+                t = inp
+                inp = ''
+            e = binascii.b2a_base64(t)
+            if e:
+                oup = oup + e[:-1]
+        return oup
+
+    def decode(self, inp):
+        if not inp:
+            return ''
+        return binascii.a2b_base64(inp)
+
+
+
+Mon2num = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
+        'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
+
+def Internaldate2tuple(resp):
+    """Parse an IMAP4 INTERNALDATE string.
+
+    Return corresponding local time.  The return value is a
+    time.struct_time instance or None if the string has wrong format.
+    """
+
+    mo = InternalDate.match(resp)
+    if not mo:
+        return None
+
+    mon = Mon2num[mo.group('mon')]
+    zonen = mo.group('zonen')
+
+    day = int(mo.group('day'))
+    year = int(mo.group('year'))
+    hour = int(mo.group('hour'))
+    min = int(mo.group('min'))
+    sec = int(mo.group('sec'))
+    zoneh = int(mo.group('zoneh'))
+    zonem = int(mo.group('zonem'))
+
+    # INTERNALDATE timezone must be subtracted to get UT
+
+    zone = (zoneh*60 + zonem)*60
+    if zonen == '-':
+        zone = -zone
+
+    tt = (year, mon, day, hour, min, sec, -1, -1, -1)
+
+    utc = time.mktime(tt)
+
+    # Following is necessary because the time module has no 'mkgmtime'.
+    # 'mktime' assumes arg in local timezone, so adds timezone/altzone.
+
+    lt = time.localtime(utc)
+    if time.daylight and lt[-1]:
+        zone = zone + time.altzone
+    else:
+        zone = zone + time.timezone
+
+    return time.localtime(utc - zone)
+
+
+
+def Int2AP(num):
+
+    """Convert integer to A-P string representation."""
+
+    val = ''; AP = 'ABCDEFGHIJKLMNOP'
+    num = int(abs(num))
+    while num:
+        num, mod = divmod(num, 16)
+        val = AP[mod] + val
+    return val
+
+
+
+def ParseFlags(resp):
+
+    """Convert IMAP4 flags response to python tuple."""
+
+    mo = Flags.match(resp)
+    if not mo:
+        return ()
+
+    return tuple(mo.group('flags').split())
+
+
+def Time2Internaldate(date_time):
+
+    """Convert date_time to IMAP4 INTERNALDATE representation.
+
+    Return string in form: '"DD-Mmm-YYYY HH:MM:SS +HHMM"'.  The
+    date_time argument can be a number (int or float) representing
+    seconds since epoch (as returned by time.time()), a 9-tuple
+    representing local time (as returned by time.localtime()), or a
+    double-quoted string.  In the last case, it is assumed to already
+    be in the correct format.
+    """
+
+    if isinstance(date_time, (int, float)):
+        tt = time.localtime(date_time)
+    elif isinstance(date_time, (tuple, time.struct_time)):
+        tt = date_time
+    elif isinstance(date_time, str) and (date_time[0],date_time[-1]) == ('"','"'):
+        return date_time        # Assume in correct format
+    else:
+        raise ValueError("date_time not of a known type")
+
+    dt = time.strftime("%d-%b-%Y %H:%M:%S", tt)
+    if dt[0] == '0':
+        dt = ' ' + dt[1:]
+    if time.daylight and tt[-1]:
+        zone = -time.altzone
+    else:
+        zone = -time.timezone
+    return '"' + dt + " %+03d%02d" % divmod(zone//60, 60) + '"'
+
+
+
+if __name__ == '__main__':
+
+    # To test: invoke either as 'python imaplib.py [IMAP4_server_hostname]'
+    # or 'python imaplib.py -s "rsh IMAP4_server_hostname exec /etc/rimapd"'
+    # to test the IMAP4_stream class
+
+    import getopt, getpass
+
+    try:
+        optlist, args = getopt.getopt(sys.argv[1:], 'd:s:')
+    except getopt.error, val:
+        optlist, args = (), ()
+
+    stream_command = None
+    for opt,val in optlist:
+        if opt == '-d':
+            Debug = int(val)
+        elif opt == '-s':
+            stream_command = val
+            if not args: args = (stream_command,)
+
+    if not args: args = ('',)
+
+    host = args[0]
+
+    USER = getpass.getuser()
+    PASSWD = getpass.getpass("IMAP password for %s on %s: " % (USER, host or "localhost"))
+
+    test_mesg = 'From: %(user)s@localhost%(lf)sSubject: IMAP4 test%(lf)s%(lf)sdata...%(lf)s' % {'user':USER, 'lf':'\n'}
+    test_seq1 = (
+    ('login', (USER, PASSWD)),
+    ('create', ('/tmp/xxx 1',)),
+    ('rename', ('/tmp/xxx 1', '/tmp/yyy')),
+    ('CREATE', ('/tmp/yyz 2',)),
+    ('append', ('/tmp/yyz 2', None, None, test_mesg)),
+    ('list', ('/tmp', 'yy*')),
+    ('select', ('/tmp/yyz 2',)),
+    ('search', (None, 'SUBJECT', 'test')),
+    ('fetch', ('1', '(FLAGS INTERNALDATE RFC822)')),
+    ('store', ('1', 'FLAGS', '(\Deleted)')),
+    ('namespace', ()),
+    ('expunge', ()),
+    ('recent', ()),
+    ('close', ()),
+    )
+
+    test_seq2 = (
+    ('select', ()),
+    ('response',('UIDVALIDITY',)),
+    ('uid', ('SEARCH', 'ALL')),
+    ('response', ('EXISTS',)),
+    ('append', (None, None, None, test_mesg)),
+    ('recent', ()),
+    ('logout', ()),
+    )
+
+    def run(cmd, args):
+        M._mesg('%s %s' % (cmd, args))
+        typ, dat = getattr(M, cmd)(*args)
+        M._mesg('%s => %s %s' % (cmd, typ, dat))
+        if typ == 'NO': raise dat[0]
+        return dat
+
+    try:
+        if stream_command:
+            M = IMAP4_stream(stream_command)
+        else:
+            M = IMAP4(host)
+        if M.state == 'AUTH':
+            test_seq1 = test_seq1[1:]   # Login not needed
+        M._mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION)
+        M._mesg('CAPABILITIES = %r' % (M.capabilities,))
+
+        for cmd,args in test_seq1:
+            run(cmd, args)
+
+        for ml in run('list', ('/tmp/', 'yy%')):
+            mo = re.match(r'.*"([^"]+)"$', ml)
+            if mo: path = mo.group(1)
+            else: path = ml.split()[-1]
+            run('delete', (path,))
+
+        for cmd,args in test_seq2:
+            dat = run(cmd, args)
+
+            if (cmd,args) != ('uid', ('SEARCH', 'ALL')):
+                continue
+
+            uid = dat[-1].split()
+            if not uid: continue
+            run('uid', ('FETCH', '%s' % uid[-1],
+                    '(FLAGS INTERNALDATE RFC822.SIZE RFC822.HEADER RFC822.TEXT)'))
+
+        print '\nAll tests OK.'
+
+    except:
+        print '\nTests failed.'
+
+        if not Debug:
+            print '''
+If you would like to see debugging output,
+try: %s -d5
+''' % sys.argv[0]
+
+        raise
diff --git a/src/main/resources/PythonLibs/imghdr.py b/src/main/resources/PythonLibs/imghdr.py
new file mode 100644
index 0000000000000000000000000000000000000000..1683024cb72923d6a02bf50230ad9860aa69875c
--- /dev/null
+++ b/src/main/resources/PythonLibs/imghdr.py
@@ -0,0 +1,161 @@
+"""Recognize image file formats based on their first few bytes."""
+
+__all__ = ["what"]
+
+#-------------------------#
+# Recognize image headers #
+#-------------------------#
+
+def what(file, h=None):
+    if h is None:
+        if isinstance(file, basestring):
+            f = open(file, 'rb')
+            h = f.read(32)
+        else:
+            location = file.tell()
+            h = file.read(32)
+            file.seek(location)
+            f = None
+    else:
+        f = None
+    try:
+        for tf in tests:
+            res = tf(h, f)
+            if res:
+                return res
+    finally:
+        if f: f.close()
+    return None
+
+
+#---------------------------------#
+# Subroutines per image file type #
+#---------------------------------#
+
+tests = []
+
+def test_jpeg(h, f):
+    """JPEG data in JFIF format"""
+    if h[6:10] == 'JFIF':
+        return 'jpeg'
+
+tests.append(test_jpeg)
+
+def test_exif(h, f):
+    """JPEG data in Exif format"""
+    if h[6:10] == 'Exif':
+        return 'jpeg'
+
+tests.append(test_exif)
+
+def test_png(h, f):
+    if h[:8] == "\211PNG\r\n\032\n":
+        return 'png'
+
+tests.append(test_png)
+
+def test_gif(h, f):
+    """GIF ('87 and '89 variants)"""
+    if h[:6] in ('GIF87a', 'GIF89a'):
+        return 'gif'
+
+tests.append(test_gif)
+
+def test_tiff(h, f):
+    """TIFF (can be in Motorola or Intel byte order)"""
+    if h[:2] in ('MM', 'II'):
+        return 'tiff'
+
+tests.append(test_tiff)
+
+def test_rgb(h, f):
+    """SGI image library"""
+    if h[:2] == '\001\332':
+        return 'rgb'
+
+tests.append(test_rgb)
+
+def test_pbm(h, f):
+    """PBM (portable bitmap)"""
+    if len(h) >= 3 and \
+        h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r':
+        return 'pbm'
+
+tests.append(test_pbm)
+
+def test_pgm(h, f):
+    """PGM (portable graymap)"""
+    if len(h) >= 3 and \
+        h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r':
+        return 'pgm'
+
+tests.append(test_pgm)
+
+def test_ppm(h, f):
+    """PPM (portable pixmap)"""
+    if len(h) >= 3 and \
+        h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r':
+        return 'ppm'
+
+tests.append(test_ppm)
+
+def test_rast(h, f):
+    """Sun raster file"""
+    if h[:4] == '\x59\xA6\x6A\x95':
+        return 'rast'
+
+tests.append(test_rast)
+
+def test_xbm(h, f):
+    """X bitmap (X10 or X11)"""
+    s = '#define '
+    if h[:len(s)] == s:
+        return 'xbm'
+
+tests.append(test_xbm)
+
+def test_bmp(h, f):
+    if h[:2] == 'BM':
+        return 'bmp'
+
+tests.append(test_bmp)
+
+#--------------------#
+# Small test program #
+#--------------------#
+
+def test():
+    import sys
+    recursive = 0
+    if sys.argv[1:] and sys.argv[1] == '-r':
+        del sys.argv[1:2]
+        recursive = 1
+    try:
+        if sys.argv[1:]:
+            testall(sys.argv[1:], recursive, 1)
+        else:
+            testall(['.'], recursive, 1)
+    except KeyboardInterrupt:
+        sys.stderr.write('\n[Interrupted]\n')
+        sys.exit(1)
+
+def testall(list, recursive, toplevel):
+    import sys
+    import os
+    for filename in list:
+        if os.path.isdir(filename):
+            print filename + '/:',
+            if recursive or toplevel:
+                print 'recursing down:'
+                import glob
+                names = glob.glob(os.path.join(filename, '*'))
+                testall(names, recursive, 0)
+            else:
+                print '*** directory (use -r) ***'
+        else:
+            print filename + ':',
+            sys.stdout.flush()
+            try:
+                print what(filename)
+            except IOError:
+                print '*** not found ***'
diff --git a/src/main/resources/PythonLibs/importlib/__init__.py b/src/main/resources/PythonLibs/importlib/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..ad31a1ac4776f5b830eb3d5e02dbcd7470e5ece9
--- /dev/null
+++ b/src/main/resources/PythonLibs/importlib/__init__.py
@@ -0,0 +1,38 @@
+"""Backport of importlib.import_module from 3.x."""
+# While not critical (and in no way guaranteed!), it would be nice to keep this
+# code compatible with Python 2.3.
+import sys
+
+def _resolve_name(name, package, level):
+    """Return the absolute name of the module to be imported."""
+    if not hasattr(package, 'rindex'):
+        raise ValueError("'package' not set to a string")
+    dot = len(package)
+    for x in xrange(level, 1, -1):
+        try:
+            dot = package.rindex('.', 0, dot)
+        except ValueError:
+            raise ValueError("attempted relative import beyond top-level "
+                              "package")
+    return "%s.%s" % (package[:dot], name)
+
+
+def import_module(name, package=None):
+    """Import a module.
+
+    The 'package' argument is required when performing a relative import. It
+    specifies the package to use as the anchor point from which to resolve the
+    relative import to an absolute import.
+
+    """
+    if name.startswith('.'):
+        if not package:
+            raise TypeError("relative imports require the 'package' argument")
+        level = 0
+        for character in name:
+            if character != '.':
+                break
+            level += 1
+        name = _resolve_name(name[level:], package, level)
+    __import__(name)
+    return sys.modules[name]
diff --git a/src/main/resources/PythonLibs/inspect.py b/src/main/resources/PythonLibs/inspect.py
new file mode 100644
index 0000000000000000000000000000000000000000..b737a34929b356f28fdbd2a6beb28b6c489a4406
--- /dev/null
+++ b/src/main/resources/PythonLibs/inspect.py
@@ -0,0 +1,967 @@
+# -*- coding: iso-8859-1 -*-
+"""Get useful information from live Python objects.
+
+This module encapsulates the interface provided by the internal special
+attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion.
+It also provides some help for examining source code and class layout.
+
+Here are some of the useful functions provided by this module:
+
+    ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
+        isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
+        isroutine() - check object types
+    getmembers() - get members of an object that satisfy a given condition
+
+    getfile(), getsourcefile(), getsource() - find an object's source code
+    getdoc(), getcomments() - get documentation on an object
+    getmodule() - determine the module that an object came from
+    getclasstree() - arrange classes so as to represent their hierarchy
+
+    getargspec(), getargvalues() - get info about function arguments
+    formatargspec(), formatargvalues() - format an argument spec
+    getouterframes(), getinnerframes() - get info about frames
+    currentframe() - get the current stack frame
+    stack(), trace() - get info about frames on the stack or in a traceback
+"""
+
+# This module is in the public domain.  No warranties.
+
+__author__ = 'Ka-Ping Yee <ping@lfw.org>'
+__date__ = '1 Jan 2001'
+
+import sys
+import os
+import types
+import string
+import re
+import dis
+import imp
+import tokenize
+import linecache
+from operator import attrgetter
+from collections import namedtuple
+_jython = sys.platform.startswith('java')
+if _jython:
+    _ReflectedFunctionType = type(os.listdir)
+
+# These constants are from Include/code.h.
+CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 0x1, 0x2, 0x4, 0x8
+CO_NESTED, CO_GENERATOR, CO_NOFREE = 0x10, 0x20, 0x40
+# See Include/object.h
+TPFLAGS_IS_ABSTRACT = 1 << 20
+
+# ----------------------------------------------------------- type-checking
+def ismodule(object):
+    """Return true if the object is a module.
+
+    Module objects provide these attributes:
+        __doc__         documentation string
+        __file__        filename (missing for built-in modules)"""
+    return isinstance(object, types.ModuleType)
+
+def isclass(object):
+    """Return true if the object is a class.
+
+    Class objects provide these attributes:
+        __doc__         documentation string
+        __module__      name of module in which this class was defined"""
+    return isinstance(object, types.ClassType) or hasattr(object, '__bases__')
+
+def ismethod(object):
+    """Return true if the object is an instance method.
+
+    Instance method objects provide these attributes:
+        __doc__         documentation string
+        __name__        name with which this method was defined
+        im_class        class object in which this method belongs
+        im_func         function object containing implementation of method
+        im_self         instance to which this method is bound, or None"""
+    return isinstance(object, types.MethodType)
+
+def ismethoddescriptor(object):
+    """Return true if the object is a method descriptor.
+
+    But not if ismethod() or isclass() or isfunction() are true.
+
+    This is new in Python 2.2, and, for example, is true of int.__add__.
+    An object passing this test has a __get__ attribute but not a __set__
+    attribute, but beyond that the set of attributes varies.  __name__ is
+    usually sensible, and __doc__ often is.
+
+    Methods implemented via descriptors that also pass one of the other
+    tests return false from the ismethoddescriptor() test, simply because
+    the other tests promise more -- you can, e.g., count on having the
+    im_func attribute (etc) when an object passes ismethod()."""
+    return (hasattr(object, "__get__")
+            and not hasattr(object, "__set__") # else it's a data descriptor
+            and not ismethod(object)           # mutual exclusion
+            and not isfunction(object)
+            and not isclass(object))
+
+def isdatadescriptor(object):
+    """Return true if the object is a data descriptor.
+
+    Data descriptors have both a __get__ and a __set__ attribute.  Examples are
+    properties (defined in Python) and getsets and members (defined in C).
+    Typically, data descriptors will also have __name__ and __doc__ attributes
+    (properties, getsets, and members have both of these attributes), but this
+    is not guaranteed."""
+    return (hasattr(object, "__set__") and hasattr(object, "__get__"))
+
+if hasattr(types, 'MemberDescriptorType'):
+    # CPython and equivalent
+    def ismemberdescriptor(object):
+        """Return true if the object is a member descriptor.
+
+        Member descriptors are specialized descriptors defined in extension
+        modules."""
+        return isinstance(object, types.MemberDescriptorType)
+else:
+    # Other implementations
+    def ismemberdescriptor(object):
+        """Return true if the object is a member descriptor.
+
+        Member descriptors are specialized descriptors defined in extension
+        modules."""
+        return False
+
+if hasattr(types, 'GetSetDescriptorType'):
+    # CPython and equivalent
+    def isgetsetdescriptor(object):
+        """Return true if the object is a getset descriptor.
+
+        getset descriptors are specialized descriptors defined in extension
+        modules."""
+        return isinstance(object, types.GetSetDescriptorType)
+else:
+    # Other implementations
+    def isgetsetdescriptor(object):
+        """Return true if the object is a getset descriptor.
+
+        getset descriptors are specialized descriptors defined in extension
+        modules."""
+        return False
+
+def isfunction(object):
+    """Return true if the object is a user-defined function.
+
+    Function objects provide these attributes:
+        __doc__         documentation string
+        __name__        name with which this function was defined
+        func_code       code object containing compiled function bytecode
+        func_defaults   tuple of any default values for arguments
+        func_doc        (same as __doc__)
+        func_globals    global namespace in which this function was defined
+        func_name       (same as __name__)"""
+    return isinstance(object, types.FunctionType)
+
+def isgeneratorfunction(object):
+    """Return true if the object is a user-defined generator function.
+
+    Generator function objects provides same attributes as functions.
+
+    See isfunction.__doc__ for attributes listing."""
+    return bool((isfunction(object) or ismethod(object)) and
+                object.func_code.co_flags & CO_GENERATOR)
+
+def isgenerator(object):
+    """Return true if the object is a generator.
+
+    Generator objects provide these attributes:
+        __iter__        defined to support interation over container
+        close           raises a new GeneratorExit exception inside the
+                        generator to terminate the iteration
+        gi_code         code object
+        gi_frame        frame object or possibly None once the generator has
+                        been exhausted
+        gi_running      set to 1 when generator is executing, 0 otherwise
+        next            return the next item from the container
+        send            resumes the generator and "sends" a value that becomes
+                        the result of the current yield-expression
+        throw           used to raise an exception inside the generator"""
+    return isinstance(object, types.GeneratorType)
+
+def istraceback(object):
+    """Return true if the object is a traceback.
+
+    Traceback objects provide these attributes:
+        tb_frame        frame object at this level
+        tb_lasti        index of last attempted instruction in bytecode
+        tb_lineno       current line number in Python source code
+        tb_next         next inner traceback object (called by this level)"""
+    return isinstance(object, types.TracebackType)
+
+def isframe(object):
+    """Return true if the object is a frame object.
+
+    Frame objects provide these attributes:
+        f_back          next outer frame object (this frame's caller)
+        f_builtins      built-in namespace seen by this frame
+        f_code          code object being executed in this frame
+        f_exc_traceback traceback if raised in this frame, or None
+        f_exc_type      exception type if raised in this frame, or None
+        f_exc_value     exception value if raised in this frame, or None
+        f_globals       global namespace seen by this frame
+        f_lasti         index of last attempted instruction in bytecode
+        f_lineno        current line number in Python source code
+        f_locals        local namespace seen by this frame
+        f_restricted    0 or 1 if frame is in restricted execution mode
+        f_trace         tracing function for this frame, or None"""
+    return isinstance(object, types.FrameType)
+
+def iscode(object):
+    """Return true if the object is a code object.
+
+    Code objects provide these attributes:
+        co_argcount     number of arguments (not including * or ** args)
+        co_code         string of raw compiled bytecode
+        co_consts       tuple of constants used in the bytecode
+        co_filename     name of file in which this code object was created
+        co_firstlineno  number of first line in Python source code
+        co_flags        bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
+        co_lnotab       encoded mapping of line numbers to bytecode indices
+        co_name         name with which this code object was defined
+        co_names        tuple of names of local variables
+        co_nlocals      number of local variables
+        co_stacksize    virtual machine stack space required
+        co_varnames     tuple of names of arguments and local variables"""
+    return isinstance(object, types.CodeType)
+
+def isbuiltin(object):
+    """Return true if the object is a built-in function or method.
+
+    Built-in functions and methods provide these attributes:
+        __doc__         documentation string
+        __name__        original name of this function or method
+        __self__        instance to which a method is bound, or None"""
+    return isinstance(object, types.BuiltinFunctionType)
+
+def isroutine(object):
+    """Return true if the object is any kind of function or method."""
+    return (isbuiltin(object)
+            or isfunction(object)
+            or ismethod(object)
+            or ismethoddescriptor(object)
+            or (_jython and isinstance(object, _ReflectedFunctionType)))
+
+def isabstract(object):
+    """Return true if the object is an abstract base class (ABC)."""
+    return isinstance(object, type) and object.__flags__ & TPFLAGS_IS_ABSTRACT
+
+def getmembers(object, predicate=None):
+    """Return all members of an object as (name, value) pairs sorted by name.
+    Optionally, only return members that satisfy a given predicate."""
+    results = []
+    for key in dir(object):
+        value = getattr(object, key)
+        if not predicate or predicate(value):
+            results.append((key, value))
+    results.sort()
+    return results
+
+Attribute = namedtuple('Attribute', 'name kind defining_class object')
+
+def classify_class_attrs(cls):
+    """Return list of attribute-descriptor tuples.
+
+    For each name in dir(cls), the return list contains a 4-tuple
+    with these elements:
+
+        0. The name (a string).
+
+        1. The kind of attribute this is, one of these strings:
+               'class method'    created via classmethod()
+               'static method'   created via staticmethod()
+               'property'        created via property()
+               'method'          any other flavor of method
+               'data'            not a method
+
+        2. The class which defined this attribute (a class).
+
+        3. The object as obtained directly from the defining class's
+           __dict__, not via getattr.  This is especially important for
+           data attributes:  C.data is just a data object, but
+           C.__dict__['data'] may be a data descriptor with additional
+           info, like a __doc__ string.
+    """
+
+    mro = getmro(cls)
+    names = dir(cls)
+    result = []
+    for name in names:
+        # Get the object associated with the name.
+        # Getting an obj from the __dict__ sometimes reveals more than
+        # using getattr.  Static and class methods are dramatic examples.
+        if name in cls.__dict__:
+            obj = cls.__dict__[name]
+        else:
+            obj = getattr(cls, name)
+
+        # Figure out where it was defined.
+        homecls = getattr(obj, "__objclass__", None)
+        if homecls is None:
+            # search the dicts.
+            for base in mro:
+                if name in base.__dict__:
+                    homecls = base
+                    break
+
+        # Get the object again, in order to get it from the defining
+        # __dict__ instead of via getattr (if possible).
+        if homecls is not None and name in homecls.__dict__:
+            obj = homecls.__dict__[name]
+
+        # Also get the object via getattr.
+        obj_via_getattr = getattr(cls, name)
+
+        # Classify the object.
+        if isinstance(obj, staticmethod):
+            kind = "static method"
+        elif isinstance(obj, classmethod):
+            kind = "class method"
+        elif isinstance(obj, property):
+            kind = "property"
+        elif (ismethod(obj_via_getattr) or
+              ismethoddescriptor(obj_via_getattr)):
+            kind = "method"
+        else:
+            kind = "data"
+
+        result.append(Attribute(name, kind, homecls, obj))
+
+    return result
+
+# ----------------------------------------------------------- class helpers
+def _searchbases(cls, accum):
+    # Simulate the "classic class" search order.
+    if cls in accum:
+        return
+    accum.append(cls)
+    for base in cls.__bases__:
+        _searchbases(base, accum)
+
+def getmro(cls):
+    "Return tuple of base classes (including cls) in method resolution order."
+    if hasattr(cls, "__mro__"):
+        return cls.__mro__
+    else:
+        result = []
+        _searchbases(cls, result)
+        return tuple(result)
+
+# -------------------------------------------------- source code extraction
+def indentsize(line):
+    """Return the indent size, in spaces, at the start of a line of text."""
+    expline = string.expandtabs(line)
+    return len(expline) - len(string.lstrip(expline))
+
+def getdoc(object):
+    """Get the documentation string for an object.
+
+    All tabs are expanded to spaces.  To clean up docstrings that are
+    indented to line up with blocks of code, any whitespace than can be
+    uniformly removed from the second line onwards is removed."""
+    try:
+        doc = object.__doc__
+    except AttributeError:
+        return None
+    if not isinstance(doc, types.StringTypes):
+        return None
+    return cleandoc(doc)
+
+def cleandoc(doc):
+    """Clean up indentation from docstrings.
+
+    Any whitespace that can be uniformly removed from the second line
+    onwards is removed."""
+    try:
+        lines = string.split(string.expandtabs(doc), '\n')
+    except UnicodeError:
+        return None
+    else:
+        # Find minimum indentation of any non-blank lines after first line.
+        margin = sys.maxint
+        for line in lines[1:]:
+            content = len(string.lstrip(line))
+            if content:
+                indent = len(line) - content
+                margin = min(margin, indent)
+        # Remove indentation.
+        if lines:
+            lines[0] = lines[0].lstrip()
+        if margin < sys.maxint:
+            for i in range(1, len(lines)): lines[i] = lines[i][margin:]
+        # Remove any trailing or leading blank lines.
+        while lines and not lines[-1]:
+            lines.pop()
+        while lines and not lines[0]:
+            lines.pop(0)
+        return string.join(lines, '\n')
+
+def getfile(object):
+    """Work out which source or compiled file an object was defined in."""
+    if ismodule(object):
+        if hasattr(object, '__file__'):
+            return object.__file__
+        raise TypeError('arg is a built-in module')
+    if isclass(object):
+        object = sys.modules.get(object.__module__)
+        if hasattr(object, '__file__'):
+            return object.__file__
+        raise TypeError('arg is a built-in class')
+    if ismethod(object):
+        object = object.im_func
+    if isfunction(object):
+        object = object.func_code
+    if istraceback(object):
+        object = object.tb_frame
+    if isframe(object):
+        object = object.f_code
+    if iscode(object):
+        return object.co_filename
+    raise TypeError('arg is not a module, class, method, '
+                    'function, traceback, frame, or code object')
+
+ModuleInfo = namedtuple('ModuleInfo', 'name suffix mode module_type')
+
+def getmoduleinfo(path):
+    """Get the module name, suffix, mode, and module type for a given file."""
+    filename = os.path.basename(path)
+    suffixes = map(lambda info:
+                   (-len(info[0]), info[0], info[1], info[2]),
+                    imp.get_suffixes())
+    suffixes.sort() # try longest suffixes first, in case they overlap
+    for neglen, suffix, mode, mtype in suffixes:
+        if filename[neglen:] == suffix:
+            return ModuleInfo(filename[:neglen], suffix, mode, mtype)
+
+def getmodulename(path):
+    """Return the module name for a given file, or None."""
+    info = getmoduleinfo(path)
+    if info: return info[0]
+
+def getsourcefile(object):
+    """Return the Python source file an object was defined in, if it exists."""
+    filename = getfile(object)
+    if string.lower(filename[-4:]) in ('.pyc', '.pyo'):
+        filename = filename[:-4] + '.py'
+    elif filename.endswith('$py.class'):
+        filename = filename[:-9] + '.py'
+    for suffix, mode, kind in imp.get_suffixes():
+        if 'b' in mode and string.lower(filename[-len(suffix):]) == suffix:
+            # Looks like a binary file.  We want to only return a text file.
+            return None
+    if os.path.exists(filename):
+        return filename
+    # only return a non-existent filename if the module has a PEP 302 loader
+    if hasattr(getmodule(object, filename), '__loader__'):
+        return filename
+
+def getabsfile(object, _filename=None):
+    """Return an absolute path to the source or compiled file for an object.
+
+    The idea is for each object to have a unique origin, so this routine
+    normalizes the result as much as possible."""
+    if _filename is None:
+        _filename = getsourcefile(object) or getfile(object)
+    return os.path.normcase(os.path.abspath(_filename))
+
+modulesbyfile = {}
+_filesbymodname = {}
+
+def getmodule(object, _filename=None):
+    """Return the module an object was defined in, or None if not found."""
+    if ismodule(object):
+        return object
+    if hasattr(object, '__module__'):
+        return sys.modules.get(object.__module__)
+    # Try the filename to modulename cache
+    if _filename is not None and _filename in modulesbyfile:
+        return sys.modules.get(modulesbyfile[_filename])
+    # Try the cache again with the absolute file name
+    try:
+        file = getabsfile(object, _filename)
+    except TypeError:
+        return None
+    if file in modulesbyfile:
+        return sys.modules.get(modulesbyfile[file])
+    # Update the filename to module name cache and check yet again
+    # Copy sys.modules in order to cope with changes while iterating
+    for modname, module in sys.modules.items():
+        if ismodule(module) and hasattr(module, '__file__'):
+            f = module.__file__
+            if f == _filesbymodname.get(modname, None):
+                # Have already mapped this module, so skip it
+                continue
+            _filesbymodname[modname] = f
+            f = getabsfile(module)
+            # Always map to the name the module knows itself by
+            modulesbyfile[f] = modulesbyfile[
+                os.path.realpath(f)] = module.__name__
+    if file in modulesbyfile:
+        return sys.modules.get(modulesbyfile[file])
+    # Check the main module
+    main = sys.modules['__main__']
+    if not hasattr(object, '__name__'):
+        return None
+    if hasattr(main, object.__name__):
+        mainobject = getattr(main, object.__name__)
+        if mainobject is object:
+            return main
+    # Check builtins
+    builtin = sys.modules['__builtin__']
+    if hasattr(builtin, object.__name__):
+        builtinobject = getattr(builtin, object.__name__)
+        if builtinobject is object:
+            return builtin
+
+def findsource(object):
+    """Return the entire source file and starting line number for an object.
+
+    The argument may be a module, class, method, function, traceback, frame,
+    or code object.  The source code is returned as a list of all the lines
+    in the file and the line number indexes a line in that list.  An IOError
+    is raised if the source code cannot be retrieved."""
+    file = getsourcefile(object) or getfile(object)
+    module = getmodule(object, file)
+    if module:
+        lines = linecache.getlines(file, module.__dict__)
+    else:
+        lines = linecache.getlines(file)
+    if not lines:
+        raise IOError('could not get source code')
+
+    if ismodule(object):
+        return lines, 0
+
+    if isclass(object):
+        name = object.__name__
+        pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
+        # make some effort to find the best matching class definition:
+        # use the one with the least indentation, which is the one
+        # that's most probably not inside a function definition.
+        candidates = []
+        for i in range(len(lines)):
+            match = pat.match(lines[i])
+            if match:
+                # if it's at toplevel, it's already the best one
+                if lines[i][0] == 'c':
+                    return lines, i
+                # else add whitespace to candidate list
+                candidates.append((match.group(1), i))
+        if candidates:
+            # this will sort by whitespace, and by line number,
+            # less whitespace first
+            candidates.sort()
+            return lines, candidates[0][1]
+        else:
+            raise IOError('could not find class definition')
+
+    if ismethod(object):
+        object = object.im_func
+    if isfunction(object):
+        object = object.func_code
+    if istraceback(object):
+        object = object.tb_frame
+    if isframe(object):
+        object = object.f_code
+    if iscode(object):
+        if not hasattr(object, 'co_firstlineno'):
+            raise IOError('could not find function definition')
+        lnum = object.co_firstlineno - 1
+        pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
+        while lnum > 0:
+            if pat.match(lines[lnum]): break
+            lnum = lnum - 1
+        return lines, lnum
+    raise IOError('could not find code object')
+
+def getcomments(object):
+    """Get lines of comments immediately preceding an object's source code.
+
+    Returns None when source can't be found.
+    """
+    try:
+        lines, lnum = findsource(object)
+    except (IOError, TypeError):
+        return None
+
+    if ismodule(object):
+        # Look for a comment block at the top of the file.
+        start = 0
+        if lines and lines[0][:2] == '#!': start = 1
+        while start < len(lines) and string.strip(lines[start]) in ('', '#'):
+            start = start + 1
+        if start < len(lines) and lines[start][:1] == '#':
+            comments = []
+            end = start
+            while end < len(lines) and lines[end][:1] == '#':
+                comments.append(string.expandtabs(lines[end]))
+                end = end + 1
+            return string.join(comments, '')
+
+    # Look for a preceding block of comments at the same indentation.
+    elif lnum > 0:
+        indent = indentsize(lines[lnum])
+        end = lnum - 1
+        if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \
+            indentsize(lines[end]) == indent:
+            comments = [string.lstrip(string.expandtabs(lines[end]))]
+            if end > 0:
+                end = end - 1
+                comment = string.lstrip(string.expandtabs(lines[end]))
+                while comment[:1] == '#' and indentsize(lines[end]) == indent:
+                    comments[:0] = [comment]
+                    end = end - 1
+                    if end < 0: break
+                    comment = string.lstrip(string.expandtabs(lines[end]))
+            while comments and string.strip(comments[0]) == '#':
+                comments[:1] = []
+            while comments and string.strip(comments[-1]) == '#':
+                comments[-1:] = []
+            return string.join(comments, '')
+
+class EndOfBlock(Exception): pass
+
+class BlockFinder:
+    """Provide a tokeneater() method to detect the end of a code block."""
+    def __init__(self):
+        self.indent = 0
+        self.islambda = False
+        self.started = False
+        self.passline = False
+        self.last = 1
+
+    def tokeneater(self, type, token, srow_scol, erow_ecol, line):
+        srow, scol = srow_scol
+        erow, ecol = erow_ecol
+        if not self.started:
+            # look for the first "def", "class" or "lambda"
+            if token in ("def", "class", "lambda"):
+                if token == "lambda":
+                    self.islambda = True
+                self.started = True
+            self.passline = True    # skip to the end of the line
+        elif type == tokenize.NEWLINE:
+            self.passline = False   # stop skipping when a NEWLINE is seen
+            self.last = srow
+            if self.islambda:       # lambdas always end at the first NEWLINE
+                raise EndOfBlock
+        elif self.passline:
+            pass
+        elif type == tokenize.INDENT:
+            self.indent = self.indent + 1
+            self.passline = True
+        elif type == tokenize.DEDENT:
+            self.indent = self.indent - 1
+            # the end of matching indent/dedent pairs end a block
+            # (note that this only works for "def"/"class" blocks,
+            #  not e.g. for "if: else:" or "try: finally:" blocks)
+            if self.indent <= 0:
+                raise EndOfBlock
+        elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL):
+            # any other token on the same indentation level end the previous
+            # block as well, except the pseudo-tokens COMMENT and NL.
+            raise EndOfBlock
+
+def getblock(lines):
+    """Extract the block of code at the top of the given list of lines."""
+    blockfinder = BlockFinder()
+    try:
+        tokenize.tokenize(iter(lines).next, blockfinder.tokeneater)
+    except (EndOfBlock, IndentationError):
+        pass
+    return lines[:blockfinder.last]
+
+def getsourcelines(object):
+    """Return a list of source lines and starting line number for an object.
+
+    The argument may be a module, class, method, function, traceback, frame,
+    or code object.  The source code is returned as a list of the lines
+    corresponding to the object and the line number indicates where in the
+    original source file the first line of code was found.  An IOError is
+    raised if the source code cannot be retrieved."""
+    lines, lnum = findsource(object)
+
+    if ismodule(object): return lines, 0
+    else: return getblock(lines[lnum:]), lnum + 1
+
+def getsource(object):
+    """Return the text of the source code for an object.
+
+    The argument may be a module, class, method, function, traceback, frame,
+    or code object.  The source code is returned as a single string.  An
+    IOError is raised if the source code cannot be retrieved."""
+    lines, lnum = getsourcelines(object)
+    return string.join(lines, '')
+
+# --------------------------------------------------- class tree extraction
+def walktree(classes, children, parent):
+    """Recursive helper function for getclasstree()."""
+    results = []
+    classes.sort(key=attrgetter('__module__', '__name__'))
+    for c in classes:
+        results.append((c, c.__bases__))
+        if c in children:
+            results.append(walktree(children[c], children, c))
+    return results
+
+def getclasstree(classes, unique=0):
+    """Arrange the given list of classes into a hierarchy of nested lists.
+
+    Where a nested list appears, it contains classes derived from the class
+    whose entry immediately precedes the list.  Each entry is a 2-tuple
+    containing a class and a tuple of its base classes.  If the 'unique'
+    argument is true, exactly one entry appears in the returned structure
+    for each class in the given list.  Otherwise, classes using multiple
+    inheritance and their descendants will appear multiple times."""
+    children = {}
+    roots = []
+    for c in classes:
+        if c.__bases__:
+            for parent in c.__bases__:
+                if not parent in children:
+                    children[parent] = []
+                children[parent].append(c)
+                if unique and parent in classes: break
+        elif c not in roots:
+            roots.append(c)
+    for parent in children:
+        if parent not in classes:
+            roots.append(parent)
+    return walktree(roots, children, None)
+
+# ------------------------------------------------ argument list extraction
+Arguments = namedtuple('Arguments', 'args varargs keywords')
+
+def getargs(co):
+    """Get information about the arguments accepted by a code object.
+
+    Three things are returned: (args, varargs, varkw), where 'args' is
+    a list of argument names (possibly containing nested lists), and
+    'varargs' and 'varkw' are the names of the * and ** arguments or None."""
+
+    if not iscode(co):
+        raise TypeError('arg is not a code object')
+
+    if not _jython:
+         # Jython doesn't have co_code
+        code = co.co_code
+
+    nargs = co.co_argcount
+    names = co.co_varnames
+    args = list(names[:nargs])
+    step = 0
+
+    # The following acrobatics are for anonymous (tuple) arguments.
+    for i in range(nargs):
+        if args[i][:1] in ('', '.'):
+            stack, remain, count = [], [], []
+            while step < len(code):
+                op = ord(code[step])
+                step = step + 1
+                if op >= dis.HAVE_ARGUMENT:
+                    opname = dis.opname[op]
+                    value = ord(code[step]) + ord(code[step+1])*256
+                    step = step + 2
+                    if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
+                        remain.append(value)
+                        count.append(value)
+                    elif opname == 'STORE_FAST':
+                        stack.append(names[value])
+
+                        # Special case for sublists of length 1: def foo((bar))
+                        # doesn't generate the UNPACK_TUPLE bytecode, so if
+                        # `remain` is empty here, we have such a sublist.
+                        if not remain:
+                            stack[0] = [stack[0]]
+                            break
+                        else:
+                            remain[-1] = remain[-1] - 1
+                            while remain[-1] == 0:
+                                remain.pop()
+                                size = count.pop()
+                                stack[-size:] = [stack[-size:]]
+                                if not remain: break
+                                remain[-1] = remain[-1] - 1
+                            if not remain: break
+            args[i] = stack[0]
+
+    varargs = None
+    if co.co_flags & CO_VARARGS:
+        varargs = co.co_varnames[nargs]
+        nargs = nargs + 1
+    varkw = None
+    if co.co_flags & CO_VARKEYWORDS:
+        varkw = co.co_varnames[nargs]
+    return Arguments(args, varargs, varkw)
+
+ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
+
+def getargspec(func):
+    """Get the names and default values of a function's arguments.
+
+    A tuple of four things is returned: (args, varargs, varkw, defaults).
+    'args' is a list of the argument names (it may contain nested lists).
+    'varargs' and 'varkw' are the names of the * and ** arguments or None.
+    'defaults' is an n-tuple of the default values of the last n arguments.
+    """
+
+    if ismethod(func):
+        func = func.im_func
+    if not isfunction(func):
+        raise TypeError('arg is not a Python function')
+    args, varargs, varkw = getargs(func.func_code)
+    return ArgSpec(args, varargs, varkw, func.func_defaults)
+
+ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals')
+
+def getargvalues(frame):
+    """Get information about arguments passed into a particular frame.
+
+    A tuple of four things is returned: (args, varargs, varkw, locals).
+    'args' is a list of the argument names (it may contain nested lists).
+    'varargs' and 'varkw' are the names of the * and ** arguments or None.
+    'locals' is the locals dictionary of the given frame."""
+    args, varargs, varkw = getargs(frame.f_code)
+    return ArgInfo(args, varargs, varkw, frame.f_locals)
+
+def joinseq(seq):
+    if len(seq) == 1:
+        return '(' + seq[0] + ',)'
+    else:
+        return '(' + string.join(seq, ', ') + ')'
+
+def strseq(object, convert, join=joinseq):
+    """Recursively walk a sequence, stringifying each element."""
+    if type(object) in (list, tuple):
+        return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object))
+    else:
+        return convert(object)
+
+def formatargspec(args, varargs=None, varkw=None, defaults=None,
+                  formatarg=str,
+                  formatvarargs=lambda name: '*' + name,
+                  formatvarkw=lambda name: '**' + name,
+                  formatvalue=lambda value: '=' + repr(value),
+                  join=joinseq):
+    """Format an argument spec from the 4 values returned by getargspec.
+
+    The first four arguments are (args, varargs, varkw, defaults).  The
+    other four arguments are the corresponding optional formatting functions
+    that are called to turn names and values into strings.  The ninth
+    argument is an optional function to format the sequence of arguments."""
+    specs = []
+    if defaults:
+        firstdefault = len(args) - len(defaults)
+    for i in range(len(args)):
+        spec = strseq(args[i], formatarg, join)
+        if defaults and i >= firstdefault:
+            spec = spec + formatvalue(defaults[i - firstdefault])
+        specs.append(spec)
+    if varargs is not None:
+        specs.append(formatvarargs(varargs))
+    if varkw is not None:
+        specs.append(formatvarkw(varkw))
+    return '(' + string.join(specs, ', ') + ')'
+
+def formatargvalues(args, varargs, varkw, locals,
+                    formatarg=str,
+                    formatvarargs=lambda name: '*' + name,
+                    formatvarkw=lambda name: '**' + name,
+                    formatvalue=lambda value: '=' + repr(value),
+                    join=joinseq):
+    """Format an argument spec from the 4 values returned by getargvalues.
+
+    The first four arguments are (args, varargs, varkw, locals).  The
+    next four arguments are the corresponding optional formatting functions
+    that are called to turn names and values into strings.  The ninth
+    argument is an optional function to format the sequence of arguments."""
+    def convert(name, locals=locals,
+                formatarg=formatarg, formatvalue=formatvalue):
+        return formatarg(name) + formatvalue(locals[name])
+    specs = []
+    for i in range(len(args)):
+        specs.append(strseq(args[i], convert, join))
+    if varargs:
+        specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
+    if varkw:
+        specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
+    return '(' + string.join(specs, ', ') + ')'
+
+# -------------------------------------------------- stack frame extraction
+
+Traceback = namedtuple('Traceback', 'filename lineno function code_context index')
+
+def getframeinfo(frame, context=1):
+    """Get information about a frame or traceback object.
+
+    A tuple of five things is returned: the filename, the line number of
+    the current line, the function name, a list of lines of context from
+    the source code, and the index of the current line within that list.
+    The optional second argument specifies the number of lines of context
+    to return, which are centered around the current line."""
+    if istraceback(frame):
+        lineno = frame.tb_lineno
+        frame = frame.tb_frame
+    else:
+        lineno = frame.f_lineno
+    if not isframe(frame):
+        raise TypeError('arg is not a frame or traceback object')
+
+    filename = getsourcefile(frame) or getfile(frame)
+    if context > 0:
+        start = lineno - 1 - context//2
+        try:
+            lines, lnum = findsource(frame)
+        except IOError:
+            lines = index = None
+        else:
+            start = max(start, 1)
+            start = max(0, min(start, len(lines) - context))
+            lines = lines[start:start+context]
+            index = lineno - 1 - start
+    else:
+        lines = index = None
+
+    return Traceback(filename, lineno, frame.f_code.co_name, lines, index)
+
+def getlineno(frame):
+    """Get the line number from a frame object, allowing for optimization."""
+    # FrameType.f_lineno is now a descriptor that grovels co_lnotab
+    return frame.f_lineno
+
+def getouterframes(frame, context=1):
+    """Get a list of records for a frame and all higher (calling) frames.
+
+    Each record contains a frame object, filename, line number, function
+    name, a list of lines of context, and index within the context."""
+    framelist = []
+    while frame:
+        framelist.append((frame,) + getframeinfo(frame, context))
+        frame = frame.f_back
+    return framelist
+
+def getinnerframes(tb, context=1):
+    """Get a list of records for a traceback's frame and all lower frames.
+
+    Each record contains a frame object, filename, line number, function
+    name, a list of lines of context, and index within the context."""
+    framelist = []
+    while tb:
+        framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
+        tb = tb.tb_next
+    return framelist
+
+if hasattr(sys, '_getframe'):
+    currentframe = sys._getframe
+else:
+    currentframe = lambda _=None: None
+
+def stack(context=1):
+    """Return a list of records for the stack above the caller's frame."""
+    return getouterframes(sys._getframe(1), context)
+
+def trace(context=1):
+    """Return a list of records for the stack below the current exception."""
+    return getinnerframes(sys.exc_info()[2], context)
diff --git a/src/main/resources/PythonLibs/io.py b/src/main/resources/PythonLibs/io.py
new file mode 100644
index 0000000000000000000000000000000000000000..4102ad62d568900ff6360f5f3de3c75e8dbec9e9
--- /dev/null
+++ b/src/main/resources/PythonLibs/io.py
@@ -0,0 +1,107 @@
+# XXX Temporary addition to Jython while we use _jyio.py in place of _io.
+# This module will stand in place of the lib-python io.py. The idea is
+# gradually to switch, in _jyio, between Python implementation there and
+# Java implementations imported from _io as classes in Java. In the end,
+# we delete this and _jyio.py, and go back to using lib-python's io.py
+
+"""The io module provides the Python interfaces to stream handling. The
+builtin open function is defined in this module.
+
+At the top of the I/O hierarchy is the abstract base class IOBase. It
+defines the basic interface to a stream. Note, however, that there is no
+separation between reading and writing to streams; implementations are
+allowed to throw an IOError if they do not support a given operation.
+
+Extending IOBase is RawIOBase which deals simply with the reading and
+writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide
+an interface to OS files.
+
+BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its
+subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer
+streams that are readable, writable, and both respectively.
+BufferedRandom provides a buffered interface to random access
+streams. BytesIO is a simple stream of in-memory bytes.
+
+Another IOBase subclass, TextIOBase, deals with the encoding and decoding
+of streams into text. TextIOWrapper, which extends it, is a buffered text
+interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO
+is a in-memory stream for text.
+
+Argument names are not part of the specification, and only the arguments
+of open() are intended to be used as keyword arguments.
+
+data:
+
+DEFAULT_BUFFER_SIZE
+
+   An int containing the default buffer size used by the module's buffered
+   I/O classes. open() uses the file's blksize (as obtained by os.stat) if
+   possible.
+"""
+# New I/O library conforming to PEP 3116.
+
+# XXX edge cases when switching between reading/writing
+# XXX need to support 1 meaning line-buffered
+# XXX whenever an argument is None, use the default value
+# XXX read/write ops should check readable/writable
+# XXX buffered readinto should work with arbitrary buffer objects
+# XXX use incremental encoder for text output, at least for UTF-16 and UTF-8-SIG
+# XXX check writable, readable and seekable in appropriate places
+
+
+__author__ = ("Guido van Rossum <guido@python.org>, "
+              "Mike Verdone <mike.verdone@gmail.com>, "
+              "Mark Russell <mark.russell@zen.co.uk>, "
+              "Antoine Pitrou <solipsis@pitrou.net>, "
+              "Amaury Forgeot d'Arc <amauryfa@gmail.com>, "
+              "Benjamin Peterson <benjamin@python.org>")
+
+__all__ = ["BlockingIOError", "open", "IOBase", "RawIOBase", "FileIO",
+           "BytesIO", "StringIO", "BufferedIOBase",
+           "BufferedReader", "BufferedWriter", "BufferedRWPair",
+           "BufferedRandom", "TextIOBase", "TextIOWrapper",
+           "UnsupportedOperation", "SEEK_SET", "SEEK_CUR", "SEEK_END"]
+
+
+import abc
+
+# For the time being, import everything via _jyio instead of from _io directly
+import _jyio
+from _jyio import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation,
+                 open,
+                 FileIO,
+                 BytesIO, StringIO, BufferedReader,
+                 BufferedWriter, BufferedRWPair, BufferedRandom,
+                 IncrementalNewlineDecoder, TextIOWrapper)
+
+OpenWrapper = _jyio.open # for compatibility with _pyio
+
+# for seek()
+SEEK_SET = 0
+SEEK_CUR = 1
+SEEK_END = 2
+
+# Declaring ABCs in C is tricky so we do it here.
+# Method descriptions and default implementations are inherited from the C
+# version however.
+class IOBase(_jyio._IOBase):
+    __metaclass__ = abc.ABCMeta
+
+class RawIOBase(_jyio._RawIOBase, IOBase):
+    pass
+
+class BufferedIOBase(_jyio._BufferedIOBase, IOBase):
+    pass
+
+class TextIOBase(_jyio._TextIOBase, IOBase):
+    pass
+
+RawIOBase.register(FileIO)
+
+for klass in (BytesIO, BufferedReader, BufferedWriter, BufferedRandom,
+              BufferedRWPair):
+    BufferedIOBase.register(klass)
+
+for klass in (StringIO, TextIOWrapper):
+    TextIOBase.register(klass)
+del klass
diff --git a/src/main/resources/PythonLibs/isql.py b/src/main/resources/PythonLibs/isql.py
new file mode 100644
index 0000000000000000000000000000000000000000..b6cd8de8ee48906f566f48849bb3eb746889b166
--- /dev/null
+++ b/src/main/resources/PythonLibs/isql.py
@@ -0,0 +1,235 @@
+import dbexts, cmd, sys, os
+
+if sys.platform.startswith("java"):
+    import java.lang.String
+
+"""
+Isql works in conjunction with dbexts to provide an interactive environment
+for database work.
+"""
+
+class IsqlExit(Exception): pass
+
+class Prompt:
+    """
+    This class fixes a problem with the cmd.Cmd class since it uses an ivar 'prompt'
+    as opposed to a method 'prompt()'.  To get around this, this class is plugged in
+    as a 'prompt' attribute and when invoked the '__str__' method is called which
+    figures out the appropriate prompt to display.  I still think, even though this
+    is clever, the attribute version of 'prompt' is poor design.
+    """
+    def __init__(self, isql):
+        self.isql = isql
+    def __str__(self):
+        prompt = "%s> " % (self.isql.db.dbname)
+        if len(self.isql.sqlbuffer) > 0:
+            prompt = "... "
+        return prompt
+    if sys.platform.startswith("java"):
+        def __tojava__(self, cls):
+            if cls == java.lang.String:
+                return self.__str__()
+            return False
+
+class IsqlCmd(cmd.Cmd):
+
+    def __init__(self, db=None, delimiter=";", comment=('#', '--')):
+        cmd.Cmd.__init__(self, completekey=None)
+        if db is None or type(db) == type(""):
+            self.db = dbexts.dbexts(db)
+        else:
+            self.db = db
+        self.kw = {}
+        self.sqlbuffer = []
+        self.comment = comment
+        self.delimiter = delimiter
+        self.prompt = Prompt(self)
+
+    def parseline(self, line):
+        command, arg, line = cmd.Cmd.parseline(self, line)
+        if command and command <> "EOF":
+            command = command.lower()
+        return command, arg, line
+
+    def do_which(self, arg):
+        """\nPrints the current db connection parameters.\n"""
+        print self.db
+        return False
+
+    def do_EOF(self, arg):
+        return False
+
+    def do_p(self, arg):
+        """\nExecute a python expression.\n"""
+        try:
+            exec arg.strip() in globals()
+        except:
+            print sys.exc_info()[1]
+        return False
+
+    def do_column(self, arg):
+        """\nInstructions for column display.\n"""
+        return False
+
+    def do_use(self, arg):
+        """\nUse a new database connection.\n"""
+        # this allows custom dbexts
+        self.db = self.db.__class__(arg.strip())
+        return False
+
+    def do_table(self, arg):
+        """\nPrints table meta-data.  If no table name, prints all tables.\n"""
+        if len(arg.strip()):
+            self.db.table(arg, **self.kw)
+        else:
+            self.db.table(None, **self.kw)
+        return False
+
+    def do_proc(self, arg):
+        """\nPrints store procedure meta-data.\n"""
+        if len(arg.strip()):
+            self.db.proc(arg, **self.kw)
+        else:
+            self.db.proc(None, **self.kw)
+        return False
+
+    def do_schema(self, arg):
+        """\nPrints schema information.\n"""
+        print
+        self.db.schema(arg)
+        print
+        return False
+
+    def do_delimiter(self, arg):
+        """\nChange the delimiter.\n"""
+        delimiter = arg.strip()
+        if len(delimiter) > 0:
+            self.delimiter = delimiter
+
+    def do_o(self, arg):
+        """\nSet the output.\n"""
+        if not arg:
+            fp = self.db.out
+            try:
+                if fp:
+                    fp.close()
+            finally:
+                self.db.out = None
+        else:
+            fp = open(arg, "w")
+            self.db.out = fp
+
+    def do_q(self, arg):
+        """\nQuit.\n"""
+        try:
+            if self.db.out:
+                self.db.out.close()
+        finally:
+            return True
+
+    def do_set(self, arg):
+        """\nSet a parameter. Some examples:\n set owner = 'informix'\n set types = ['VIEW', 'TABLE']\nThe right hand side is evaluated using `eval()`\n"""
+        if len(arg.strip()) == 0:
+            items = self.kw.items()
+            if len(items):
+                print
+                # format the results but don't include how many rows affected
+                for a in dbexts.console(items, ("key", "value"))[:-1]:
+                    print a
+                print
+            return False
+        d = filter(lambda x: len(x) > 0, map(lambda x: x.strip(), arg.split("=")))
+        if len(d) == 1:
+            if self.kw.has_key(d[0]):
+                del self.kw[d[0]]
+        else:
+            self.kw[d[0]] = eval(d[1])
+
+    def do_i(self, arg):
+        fp = open(arg)
+        try:
+            print
+            for line in fp.readlines():
+                line = self.precmd(line)
+                stop = self.onecmd(line)
+                stop = self.postcmd(stop, line)
+        finally:
+            fp.close()
+        return False
+
+    def default(self, arg):
+        try:
+            token = arg.strip()
+            if not token:
+                return False
+            comment = [token.startswith(x) for x in self.comment]
+            if reduce(lambda x,y: x or y, comment):
+                return False
+            if token[0] == '\\':
+                token = token[1:]
+            # is it possible the line contains the delimiter
+            if len(token) >= len(self.delimiter):
+                # does the line end with the delimiter
+                if token[-1 * len(self.delimiter):] == self.delimiter:
+                    # now add all up to the delimiter
+                    self.sqlbuffer.append(token[:-1 * len(self.delimiter)])
+                    if self.sqlbuffer:
+                        q = " ".join(self.sqlbuffer)
+                        print q
+                        self.db.isql(q, **self.kw)
+                        self.sqlbuffer = []
+                        if self.db.updatecount:
+                            print
+                            if self.db.updatecount == 1:
+                                print "1 row affected"
+                            else:
+                                print "%d rows affected" % (self.db.updatecount)
+                            print
+                        return False
+            if token:
+                self.sqlbuffer.append(token)
+        except:
+            self.sqlbuffer = []
+            print
+            print sys.exc_info()[1]
+            print
+        return False
+
+    def emptyline(self):
+        return False
+
+    def postloop(self):
+        raise IsqlExit()
+
+    def cmdloop(self, intro=None):
+        while 1:
+            try:
+                cmd.Cmd.cmdloop(self, intro)
+            except IsqlExit, e:
+                break
+            except Exception, e:
+                print
+                print e
+                print
+            intro = None
+
+if __name__ == '__main__':
+    import getopt
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "b:", [])
+    except getopt.error, msg:
+        print
+        print msg
+        print "Try `%s --help` for more information." % (sys.argv[0])
+        sys.exit(0)
+
+    dbname = None
+    for opt, arg in opts:
+        if opt == '-b':
+            dbname = arg
+
+    intro = "\nisql - interactive sql (%s)\n" % (__version__)
+
+    isql = IsqlCmd(dbname)
+    isql.cmdloop()
diff --git a/src/main/resources/PythonLibs/javapath.py b/src/main/resources/PythonLibs/javapath.py
new file mode 100644
index 0000000000000000000000000000000000000000..e11bfbb2b4e049d786b25841521f3452d4b708df
--- /dev/null
+++ b/src/main/resources/PythonLibs/javapath.py
@@ -0,0 +1,363 @@
+"""Common pathname manipulations, JDK version.
+
+Instead of importing this module directly, import os and refer to this
+module as os.path.
+
+"""
+
+# Incompletely implemented:
+# ismount -- How?
+# normcase -- How?
+
+# Missing:
+# sameopenfile -- Java doesn't have fstat nor file descriptors?
+# samestat -- How?
+
+import stat
+import sys
+from java.io import File
+import java.io.IOException
+from java.lang import System
+import os
+
+from org.python.core.Py import newString as asPyString
+import warnings
+warnings.warn('The javapath module is deprecated. Use the os.path module.',
+              DeprecationWarning, 2)
+
+
+def _tostr(s, method):
+    if isinstance(s, basestring):
+        return s
+    raise TypeError, "%s() argument must be a str or unicode object, not %s" % (
+                method, _type_name(s))
+
+def _type_name(obj):
+    TPFLAGS_HEAPTYPE = 1 << 9
+    type_name = ''
+    obj_type = type(obj)
+    is_heap = obj_type.__flags__ & TPFLAGS_HEAPTYPE == TPFLAGS_HEAPTYPE
+    if not is_heap and obj_type.__module__ != '__builtin__':
+        type_name = '%s.' % obj_type.__module__
+    type_name += obj_type.__name__
+    return type_name
+
+def dirname(path):
+    """Return the directory component of a pathname"""
+    path = _tostr(path, "dirname")
+    result = asPyString(File(path).getParent())
+    if not result:
+        if isabs(path):
+            result = path # Must be root
+        else:
+            result = ""
+    return result
+
+def basename(path):
+    """Return the final component of a pathname"""
+    path = _tostr(path, "basename")
+    return asPyString(File(path).getName())
+
+def split(path):
+    """Split a pathname.
+
+    Return tuple "(head, tail)" where "tail" is everything after the
+    final slash.  Either part may be empty.
+
+    """
+    path = _tostr(path, "split")
+    return (dirname(path), basename(path))
+
+def splitext(path):
+    """Split the extension from a pathname.
+
+    Extension is everything from the last dot to the end.  Return
+    "(root, ext)", either part may be empty.
+
+    """
+    i = 0
+    n = -1
+    for c in path:
+        if c == '.': n = i
+        i = i+1
+    if n < 0:
+        return (path, "")
+    else:
+        return (path[:n], path[n:])
+
+def splitdrive(path):
+    """Split a pathname into drive and path specifiers.
+
+    Returns a 2-tuple "(drive,path)"; either part may be empty.
+    """
+    # Algorithm based on CPython's ntpath.splitdrive and ntpath.isabs.
+    if path[1:2] == ':' and path[0].lower() in 'abcdefghijklmnopqrstuvwxyz' \
+            and (path[2:] == '' or path[2] in '/\\'):
+        return path[:2], path[2:]
+    return '', path
+
+def exists(path):
+    """Test whether a path exists.
+
+    Returns false for broken symbolic links.
+
+    """
+    path = _tostr(path, "exists")
+    return File(sys.getPath(path)).exists()
+
+def isabs(path):
+    """Test whether a path is absolute"""
+    path = _tostr(path, "isabs")
+    return File(path).isAbsolute()
+
+def isfile(path):
+    """Test whether a path is a regular file"""
+    path = _tostr(path, "isfile")
+    return File(sys.getPath(path)).isFile()
+
+def isdir(path):
+    """Test whether a path is a directory"""
+    path = _tostr(path, "isdir")
+    return File(sys.getPath(path)).isDirectory()
+
+def join(path, *args):
+    """Join two or more pathname components, inserting os.sep as needed"""
+    path = _tostr(path, "join")
+    f = File(path)
+    for a in args:
+        a = _tostr(a, "join")
+        g = File(a)
+        if g.isAbsolute() or len(f.getPath()) == 0:
+            f = g
+        else:
+            if a == "":
+                a = os.sep
+            f = File(f, a)
+    return asPyString(f.getPath())
+
+def normcase(path):
+    """Normalize case of pathname.
+
+    XXX Not done right under JDK.
+
+    """
+    path = _tostr(path, "normcase")
+    return asPyString(File(path).getPath())
+
+def commonprefix(m):
+    "Given a list of pathnames, return the longest common leading component"
+    if not m: return ''
+    prefix = m[0]
+    for item in m:
+        for i in range(len(prefix)):
+            if prefix[:i+1] <> item[:i+1]:
+                prefix = prefix[:i]
+                if i == 0: return ''
+                break
+    return prefix
+
+def islink(path):
+    """Test whether a path is a symbolic link"""
+    try:
+        st = os.lstat(path)
+    except (os.error, AttributeError):
+        return False
+    return stat.S_ISLNK(st.st_mode)
+
+def samefile(path, path2):
+    """Test whether two pathnames reference the same actual file"""
+    path = _tostr(path, "samefile")
+    path2 = _tostr(path2, "samefile")
+    return _realpath(path) == _realpath(path2)
+
+def ismount(path):
+    """Test whether a path is a mount point.
+
+    XXX This incorrectly always returns false under JDK.
+
+    """
+    return 0
+
+def walk(top, func, arg):
+    """Walk a directory tree.
+
+    walk(top,func,args) calls func(arg, d, files) for each directory
+    "d" in the tree rooted at "top" (including "top" itself).  "files"
+    is a list of all the files and subdirs in directory "d".
+
+    """
+    try:
+        names = os.listdir(top)
+    except os.error:
+        return
+    func(arg, top, names)
+    for name in names:
+        name = join(top, name)
+        if isdir(name) and not islink(name):
+            walk(name, func, arg)
+
+def expanduser(path):
+    if path[:1] == "~":
+        c = path[1:2]
+        if not c:
+            return gethome()
+        if c == os.sep:
+            return asPyString(File(gethome(), path[2:]).getPath())
+    return path
+
+def getuser():
+    return System.getProperty("user.name")
+
+def gethome():
+    return System.getProperty("user.home")
+
+
+# normpath() from Python 1.5.2, with Java appropriate generalizations
+
+# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
+# It should be understood that this may change the meaning of the path
+# if it contains symbolic links!
+def normpath(path):
+    """Normalize path, eliminating double slashes, etc."""
+    sep = os.sep
+    if sep == '\\':
+        path = path.replace("/", sep)
+    curdir = os.curdir
+    pardir = os.pardir
+    import string
+    # Treat initial slashes specially
+    slashes = ''
+    while path[:1] == sep:
+        slashes = slashes + sep
+        path = path[1:]
+    comps = string.splitfields(path, sep)
+    i = 0
+    while i < len(comps):
+        if comps[i] == curdir:
+            del comps[i]
+            while i < len(comps) and comps[i] == '':
+                del comps[i]
+        elif comps[i] == pardir and i > 0 and comps[i-1] not in ('', pardir):
+            del comps[i-1:i+1]
+            i = i-1
+        elif comps[i] == '' and i > 0 and comps[i-1] <> '':
+            del comps[i]
+        else:
+            i = i+1
+    # If the path is now empty, substitute '.'
+    if not comps and not slashes:
+        comps.append(curdir)
+    return slashes + string.joinfields(comps, sep)
+
+def abspath(path):
+    """Return an absolute path normalized but symbolic links not eliminated"""
+    path = _tostr(path, "abspath")
+    return _abspath(path)
+
+def _abspath(path):
+    # Must use normpath separately because getAbsolutePath doesn't normalize
+    # and getCanonicalPath would eliminate symlinks.
+    return normpath(asPyString(File(sys.getPath(path)).getAbsolutePath()))
+
+def realpath(path):
+    """Return an absolute path normalized and symbolic links eliminated"""
+    path = _tostr(path, "realpath")
+    return _realpath(path)
+
+def _realpath(path):
+    try:
+        return asPyString(File(sys.getPath(path)).getCanonicalPath())
+    except java.io.IOException:
+        return _abspath(path)
+
+def getsize(path):
+    path = _tostr(path, "getsize")
+    f = File(sys.getPath(path))
+    size = f.length()
+    # Sadly, if the returned length is zero, we don't really know if the file
+    # is zero sized or does not exist.
+    if size == 0 and not f.exists():
+        raise OSError(0, 'No such file or directory', path)
+    return size
+
+def getmtime(path):
+    path = _tostr(path, "getmtime")
+    f = File(sys.getPath(path))
+    if not f.exists():
+        raise OSError(0, 'No such file or directory', path)
+    return f.lastModified() / 1000.0
+
+def getatime(path):
+    # We can't detect access time so we return modification time. This
+    # matches the behaviour in os.stat().
+    path = _tostr(path, "getatime")
+    f = File(sys.getPath(path))
+    if not f.exists():
+        raise OSError(0, 'No such file or directory', path)
+    return f.lastModified() / 1000.0
+
+
+# expandvars is stolen from CPython-2.1.1's Lib/ntpath.py:
+
+# Expand paths containing shell variable substitutions.
+# The following rules apply:
+#       - no expansion within single quotes
+#       - no escape character, except for '$$' which is translated into '$'
+#       - ${varname} is accepted.
+#       - varnames can be made out of letters, digits and the character '_'
+# XXX With COMMAND.COM you can use any characters in a variable name,
+# XXX except '^|<>='.
+
+def expandvars(path):
+    """Expand shell variables of form $var and ${var}.
+
+    Unknown variables are left unchanged."""
+    if '$' not in path:
+        return path
+    import string
+    varchars = string.letters + string.digits + '_-'
+    res = ''
+    index = 0
+    pathlen = len(path)
+    while index < pathlen:
+        c = path[index]
+        if c == '\'':   # no expansion within single quotes
+            path = path[index + 1:]
+            pathlen = len(path)
+            try:
+                index = path.index('\'')
+                res = res + '\'' + path[:index + 1]
+            except ValueError:
+                res = res + path
+                index = pathlen - 1
+        elif c == '$':  # variable or '$$'
+            if path[index + 1:index + 2] == '$':
+                res = res + c
+                index = index + 1
+            elif path[index + 1:index + 2] == '{':
+                path = path[index+2:]
+                pathlen = len(path)
+                try:
+                    index = path.index('}')
+                    var = path[:index]
+                    if os.environ.has_key(var):
+                        res = res + os.environ[var]
+                except ValueError:
+                    res = res + path
+                    index = pathlen - 1
+            else:
+                var = ''
+                index = index + 1
+                c = path[index:index + 1]
+                while c != '' and c in varchars:
+                    var = var + c
+                    index = index + 1
+                    c = path[index:index + 1]
+                if os.environ.has_key(var):
+                    res = res + os.environ[var]
+                if c != '':
+                    res = res + c
+        else:
+            res = res + c
+        index = index + 1
+    return res
diff --git a/src/main/resources/PythonLibs/javashell.py b/src/main/resources/PythonLibs/javashell.py
new file mode 100644
index 0000000000000000000000000000000000000000..261e433fa13be44d2e1083e5559e7730854b4a73
--- /dev/null
+++ b/src/main/resources/PythonLibs/javashell.py
@@ -0,0 +1,93 @@
+"""
+Implement subshell functionality for Jython.
+
+This is mostly to provide the environ object for the os module,
+and subshell execution functionality for os.system and popen* functions.
+
+javashell attempts to determine a suitable command shell for the host
+operating system, and uses that shell to determine environment variables
+and to provide subshell execution functionality.
+"""
+from java.lang import System, Runtime
+from java.io import File
+from java.io import IOException
+from java.io import InputStreamReader
+from java.io import BufferedReader
+from UserDict import UserDict
+import jarray
+import os
+import string
+import subprocess
+import sys
+import types
+import warnings
+warnings.warn('The javashell module is deprecated. Use the subprocess module.',
+              DeprecationWarning, 2)
+
+__all__ = ["shellexecute"]
+
+def __warn( *args ):
+    print " ".join( [str( arg ) for arg in args ])
+
+class _ShellEnv:
+    """Provide environment derived by spawning a subshell and parsing its
+    environment.  Also supports subshell execution functions and provides
+    empty environment support for platforms with unknown shell functionality.
+    """
+    def __init__( self, cmd=None, getEnv=None, keyTransform=None ):
+        """Construct _ShellEnv instance.
+        cmd: list of exec() arguments required to run a command in
+            subshell, or None
+        getEnv: shell command to list environment variables, or None.
+            deprecated
+        keyTransform: normalization function for environment keys,
+          such as 'string.upper', or None. deprecated.
+        """
+        self.cmd = cmd
+        self.environment = os.environ
+
+    def execute( self, cmd ):
+        """Execute cmd in a shell, and return the java.lang.Process instance.
+        Accepts either a string command to be executed in a shell,
+        or a sequence of [executable, args...].
+        """
+        shellCmd = self._formatCmd( cmd )
+
+        env = self._formatEnvironment( self.environment )
+        try:
+            p = Runtime.getRuntime().exec( shellCmd, env, File(os.getcwd()) )
+            return p
+        except IOException, ex:
+            raise OSError(
+                0,
+                "Failed to execute command (%s): %s" % ( shellCmd, ex )
+                )
+
+    ########## utility methods
+    def _formatCmd( self, cmd ):
+        """Format a command for execution in a shell."""
+        if self.cmd is None:
+            msgFmt = "Unable to execute commands in subshell because shell" \
+                     " functionality not implemented for OS %s"  \
+                     " Failed command=%s"
+            raise OSError( 0, msgFmt % ( os._name, cmd ))
+
+        if isinstance(cmd, basestring):
+            shellCmd = self.cmd + [cmd]
+        else:
+            shellCmd = cmd
+
+        return shellCmd
+
+    def _formatEnvironment( self, env ):
+        """Format enviroment in lines suitable for Runtime.exec"""
+        lines = []
+        for keyValue in env.items():
+            lines.append( "%s=%s" % keyValue )
+        return lines
+
+def _getOsType():
+    return os._name
+
+_shellEnv = _ShellEnv(subprocess._shell_command)
+shellexecute = _shellEnv.execute
diff --git a/src/main/resources/PythonLibs/json/__init__.py b/src/main/resources/PythonLibs/json/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be85da022b2e88ddc21eb7cec57b69775300a4c
--- /dev/null
+++ b/src/main/resources/PythonLibs/json/__init__.py
@@ -0,0 +1,351 @@
+r"""JSON (JavaScript Object Notation) <http://json.org> is a subset of
+JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
+interchange format.
+
+:mod:`json` exposes an API familiar to users of the standard library
+:mod:`marshal` and :mod:`pickle` modules. It is the externally maintained
+version of the :mod:`json` library contained in Python 2.6, but maintains
+compatibility with Python 2.4 and Python 2.5 and (currently) has
+significant performance advantages, even without using the optional C
+extension for speedups.
+
+Encoding basic Python object hierarchies::
+
+    >>> import json
+    >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
+    '["foo", {"bar": ["baz", null, 1.0, 2]}]'
+    >>> print json.dumps("\"foo\bar")
+    "\"foo\bar"
+    >>> print json.dumps(u'\u1234')
+    "\u1234"
+    >>> print json.dumps('\\')
+    "\\"
+    >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
+    {"a": 0, "b": 0, "c": 0}
+    >>> from StringIO import StringIO
+    >>> io = StringIO()
+    >>> json.dump(['streaming API'], io)
+    >>> io.getvalue()
+    '["streaming API"]'
+
+Compact encoding::
+
+    >>> import json
+    >>> json.dumps([1,2,3,{'4': 5, '6': 7}], sort_keys=True, separators=(',',':'))
+    '[1,2,3,{"4":5,"6":7}]'
+
+Pretty printing::
+
+    >>> import json
+    >>> print json.dumps({'4': 5, '6': 7}, sort_keys=True,
+    ...                  indent=4, separators=(',', ': '))
+    {
+        "4": 5,
+        "6": 7
+    }
+
+Decoding JSON::
+
+    >>> import json
+    >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
+    >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj
+    True
+    >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar'
+    True
+    >>> from StringIO import StringIO
+    >>> io = StringIO('["streaming API"]')
+    >>> json.load(io)[0] == 'streaming API'
+    True
+
+Specializing JSON object decoding::
+
+    >>> import json
+    >>> def as_complex(dct):
+    ...     if '__complex__' in dct:
+    ...         return complex(dct['real'], dct['imag'])
+    ...     return dct
+    ...
+    >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
+    ...     object_hook=as_complex)
+    (1+2j)
+    >>> from decimal import Decimal
+    >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1')
+    True
+
+Specializing JSON object encoding::
+
+    >>> import json
+    >>> def encode_complex(obj):
+    ...     if isinstance(obj, complex):
+    ...         return [obj.real, obj.imag]
+    ...     raise TypeError(repr(o) + " is not JSON serializable")
+    ...
+    >>> json.dumps(2 + 1j, default=encode_complex)
+    '[2.0, 1.0]'
+    >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j)
+    '[2.0, 1.0]'
+    >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j))
+    '[2.0, 1.0]'
+
+
+Using json.tool from the shell to validate and pretty-print::
+
+    $ echo '{"json":"obj"}' | python -m json.tool
+    {
+        "json": "obj"
+    }
+    $ echo '{ 1.2:3.4}' | python -m json.tool
+    Expecting property name enclosed in double quotes: line 1 column 3 (char 2)
+"""
+__version__ = '2.0.9'
+__all__ = [
+    'dump', 'dumps', 'load', 'loads',
+    'JSONDecoder', 'JSONEncoder',
+]
+
+__author__ = 'Bob Ippolito <bob@redivi.com>'
+
+from .decoder import JSONDecoder
+from .encoder import JSONEncoder
+
+_default_encoder = JSONEncoder(
+    skipkeys=False,
+    ensure_ascii=True,
+    check_circular=True,
+    allow_nan=True,
+    indent=None,
+    separators=None,
+    encoding='utf-8',
+    default=None,
+)
+
+def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
+        allow_nan=True, cls=None, indent=None, separators=None,
+        encoding='utf-8', default=None, sort_keys=False, **kw):
+    """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
+    ``.write()``-supporting file-like object).
+
+    If ``skipkeys`` is true then ``dict`` keys that are not basic types
+    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
+    will be skipped instead of raising a ``TypeError``.
+
+    If ``ensure_ascii`` is true (the default), all non-ASCII characters in the
+    output are escaped with ``\uXXXX`` sequences, and the result is a ``str``
+    instance consisting of ASCII characters only.  If ``ensure_ascii`` is
+    ``False``, some chunks written to ``fp`` may be ``unicode`` instances.
+    This usually happens because the input contains unicode strings or the
+    ``encoding`` parameter is used. Unless ``fp.write()`` explicitly
+    understands ``unicode`` (as in ``codecs.getwriter``) this is likely to
+    cause an error.
+
+    If ``check_circular`` is false, then the circular reference check
+    for container types will be skipped and a circular reference will
+    result in an ``OverflowError`` (or worse).
+
+    If ``allow_nan`` is false, then it will be a ``ValueError`` to
+    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
+    in strict compliance of the JSON specification, instead of using the
+    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
+
+    If ``indent`` is a non-negative integer, then JSON array elements and
+    object members will be pretty-printed with that indent level. An indent
+    level of 0 will only insert newlines. ``None`` is the most compact
+    representation.  Since the default item separator is ``', '``,  the
+    output might include trailing whitespace when ``indent`` is specified.
+    You can use ``separators=(',', ': ')`` to avoid this.
+
+    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
+    then it will be used instead of the default ``(', ', ': ')`` separators.
+    ``(',', ':')`` is the most compact JSON representation.
+
+    ``encoding`` is the character encoding for str instances, default is UTF-8.
+
+    ``default(obj)`` is a function that should return a serializable version
+    of obj or raise TypeError. The default simply raises TypeError.
+
+    If *sort_keys* is ``True`` (default: ``False``), then the output of
+    dictionaries will be sorted by key.
+
+    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
+    ``.default()`` method to serialize additional types), specify it with
+    the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.
+
+    """
+    # cached encoder
+    if (not skipkeys and ensure_ascii and
+        check_circular and allow_nan and
+        cls is None and indent is None and separators is None and
+        encoding == 'utf-8' and default is None and not sort_keys and not kw):
+        iterable = _default_encoder.iterencode(obj)
+    else:
+        if cls is None:
+            cls = JSONEncoder
+        iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
+            check_circular=check_circular, allow_nan=allow_nan, indent=indent,
+            separators=separators, encoding=encoding,
+            default=default, sort_keys=sort_keys, **kw).iterencode(obj)
+    # could accelerate with writelines in some versions of Python, at
+    # a debuggability cost
+    for chunk in iterable:
+        fp.write(chunk)
+
+
+def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
+        allow_nan=True, cls=None, indent=None, separators=None,
+        encoding='utf-8', default=None, sort_keys=False, **kw):
+    """Serialize ``obj`` to a JSON formatted ``str``.
+
+    If ``skipkeys`` is false then ``dict`` keys that are not basic types
+    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
+    will be skipped instead of raising a ``TypeError``.
+
+    If ``ensure_ascii`` is false, all non-ASCII characters are not escaped, and
+    the return value may be a ``unicode`` instance. See ``dump`` for details.
+
+    If ``check_circular`` is false, then the circular reference check
+    for container types will be skipped and a circular reference will
+    result in an ``OverflowError`` (or worse).
+
+    If ``allow_nan`` is false, then it will be a ``ValueError`` to
+    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
+    strict compliance of the JSON specification, instead of using the
+    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
+
+    If ``indent`` is a non-negative integer, then JSON array elements and
+    object members will be pretty-printed with that indent level. An indent
+    level of 0 will only insert newlines. ``None`` is the most compact
+    representation.  Since the default item separator is ``', '``,  the
+    output might include trailing whitespace when ``indent`` is specified.
+    You can use ``separators=(',', ': ')`` to avoid this.
+
+    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
+    then it will be used instead of the default ``(', ', ': ')`` separators.
+    ``(',', ':')`` is the most compact JSON representation.
+
+    ``encoding`` is the character encoding for str instances, default is UTF-8.
+
+    ``default(obj)`` is a function that should return a serializable version
+    of obj or raise TypeError. The default simply raises TypeError.
+
+    If *sort_keys* is ``True`` (default: ``False``), then the output of
+    dictionaries will be sorted by key.
+
+    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
+    ``.default()`` method to serialize additional types), specify it with
+    the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.
+
+    """
+    # cached encoder
+    if (not skipkeys and ensure_ascii and
+        check_circular and allow_nan and
+        cls is None and indent is None and separators is None and
+        encoding == 'utf-8' and default is None and not sort_keys and not kw):
+        return _default_encoder.encode(obj)
+    if cls is None:
+        cls = JSONEncoder
+    return cls(
+        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
+        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
+        separators=separators, encoding=encoding, default=default,
+        sort_keys=sort_keys, **kw).encode(obj)
+
+
+_default_decoder = JSONDecoder(encoding=None, object_hook=None,
+                               object_pairs_hook=None)
+
+
+def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
+        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
+    """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
+    a JSON document) to a Python object.
+
+    If the contents of ``fp`` is encoded with an ASCII based encoding other
+    than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
+    be specified. Encodings that are not ASCII based (such as UCS-2) are
+    not allowed, and should be wrapped with
+    ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
+    object and passed to ``loads()``
+
+    ``object_hook`` is an optional function that will be called with the
+    result of any object literal decode (a ``dict``). The return value of
+    ``object_hook`` will be used instead of the ``dict``. This feature
+    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
+
+    ``object_pairs_hook`` is an optional function that will be called with the
+    result of any object literal decoded with an ordered list of pairs.  The
+    return value of ``object_pairs_hook`` will be used instead of the ``dict``.
+    This feature can be used to implement custom decoders that rely on the
+    order that the key and value pairs are decoded (for example,
+    collections.OrderedDict will remember the order of insertion). If
+    ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority.
+
+    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
+    kwarg; otherwise ``JSONDecoder`` is used.
+
+    """
+    return loads(fp.read(),
+        encoding=encoding, cls=cls, object_hook=object_hook,
+        parse_float=parse_float, parse_int=parse_int,
+        parse_constant=parse_constant, object_pairs_hook=object_pairs_hook,
+        **kw)
+
+
+def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
+        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
+    """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
+    document) to a Python object.
+
+    If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
+    other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
+    must be specified. Encodings that are not ASCII based (such as UCS-2)
+    are not allowed and should be decoded to ``unicode`` first.
+
+    ``object_hook`` is an optional function that will be called with the
+    result of any object literal decode (a ``dict``). The return value of
+    ``object_hook`` will be used instead of the ``dict``. This feature
+    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
+
+    ``object_pairs_hook`` is an optional function that will be called with the
+    result of any object literal decoded with an ordered list of pairs.  The
+    return value of ``object_pairs_hook`` will be used instead of the ``dict``.
+    This feature can be used to implement custom decoders that rely on the
+    order that the key and value pairs are decoded (for example,
+    collections.OrderedDict will remember the order of insertion). If
+    ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority.
+
+    ``parse_float``, if specified, will be called with the string
+    of every JSON float to be decoded. By default this is equivalent to
+    float(num_str). This can be used to use another datatype or parser
+    for JSON floats (e.g. decimal.Decimal).
+
+    ``parse_int``, if specified, will be called with the string
+    of every JSON int to be decoded. By default this is equivalent to
+    int(num_str). This can be used to use another datatype or parser
+    for JSON integers (e.g. float).
+
+    ``parse_constant``, if specified, will be called with one of the
+    following strings: -Infinity, Infinity, NaN, null, true, false.
+    This can be used to raise an exception if invalid JSON numbers
+    are encountered.
+
+    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
+    kwarg; otherwise ``JSONDecoder`` is used.
+
+    """
+    if (cls is None and encoding is None and object_hook is None and
+            parse_int is None and parse_float is None and
+            parse_constant is None and object_pairs_hook is None and not kw):
+        return _default_decoder.decode(s)
+    if cls is None:
+        cls = JSONDecoder
+    if object_hook is not None:
+        kw['object_hook'] = object_hook
+    if object_pairs_hook is not None:
+        kw['object_pairs_hook'] = object_pairs_hook
+    if parse_float is not None:
+        kw['parse_float'] = parse_float
+    if parse_int is not None:
+        kw['parse_int'] = parse_int
+    if parse_constant is not None:
+        kw['parse_constant'] = parse_constant
+    return cls(encoding=encoding, **kw).decode(s)
diff --git a/src/main/resources/PythonLibs/json/decoder.py b/src/main/resources/PythonLibs/json/decoder.py
new file mode 100644
index 0000000000000000000000000000000000000000..dc8916c9264f8189167d0a8c9923f0c51ea50c43
--- /dev/null
+++ b/src/main/resources/PythonLibs/json/decoder.py
@@ -0,0 +1,384 @@
+"""Implementation of JSONDecoder
+"""
+import re
+import sys
+import struct
+
+from json import scanner
+try:
+    from _json import scanstring as c_scanstring
+except ImportError:
+    c_scanstring = None
+
+__all__ = ['JSONDecoder']
+
+FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
+
+def _floatconstants():
+    _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
+    if sys.byteorder != 'big':
+        _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
+    nan, inf = struct.unpack('dd', _BYTES)
+    return nan, inf, -inf
+
+NaN, PosInf, NegInf = _floatconstants()
+
+
+def linecol(doc, pos):
+    lineno = doc.count('\n', 0, pos) + 1
+    if lineno == 1:
+        colno = pos + 1
+    else:
+        colno = pos - doc.rindex('\n', 0, pos)
+    return lineno, colno
+
+
+def errmsg(msg, doc, pos, end=None):
+    # Note that this function is called from _json
+    lineno, colno = linecol(doc, pos)
+    if end is None:
+        fmt = '{0}: line {1} column {2} (char {3})'
+        return fmt.format(msg, lineno, colno, pos)
+        #fmt = '%s: line %d column %d (char %d)'
+        #return fmt % (msg, lineno, colno, pos)
+    endlineno, endcolno = linecol(doc, end)
+    fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})'
+    return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end)
+    #fmt = '%s: line %d column %d - line %d column %d (char %d - %d)'
+    #return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end)
+
+
+_CONSTANTS = {
+    '-Infinity': NegInf,
+    'Infinity': PosInf,
+    'NaN': NaN,
+}
+
+STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
+BACKSLASH = {
+    '"': u'"', '\\': u'\\', '/': u'/',
+    'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
+}
+
+DEFAULT_ENCODING = "utf-8"
+
+def py_scanstring(s, end, encoding=None, strict=True,
+        _b=BACKSLASH, _m=STRINGCHUNK.match):
+    """Scan the string s for a JSON string. End is the index of the
+    character in s after the quote that started the JSON string.
+    Unescapes all valid JSON string escape sequences and raises ValueError
+    on attempt to decode an invalid string. If strict is False then literal
+    control characters are allowed in the string.
+
+    Returns a tuple of the decoded string and the index of the character in s
+    after the end quote."""
+    if encoding is None:
+        encoding = DEFAULT_ENCODING
+    chunks = []
+    _append = chunks.append
+    begin = end - 1
+    while 1:
+        chunk = _m(s, end)
+        if chunk is None:
+            raise ValueError(
+                errmsg("Unterminated string starting at", s, begin))
+        end = chunk.end()
+        content, terminator = chunk.groups()
+        # Content is contains zero or more unescaped string characters
+        if content:
+            if not isinstance(content, unicode):
+                content = unicode(content, encoding)
+            _append(content)
+        # Terminator is the end of string, a literal control character,
+        # or a backslash denoting that an escape sequence follows
+        if terminator == '"':
+            break
+        elif terminator != '\\':
+            if strict:
+                #msg = "Invalid control character %r at" % (terminator,)
+                msg = "Invalid control character {0!r} at".format(terminator)
+                raise ValueError(errmsg(msg, s, end))
+            else:
+                _append(terminator)
+                continue
+        try:
+            esc = s[end]
+        except IndexError:
+            raise ValueError(
+                errmsg("Unterminated string starting at", s, begin))
+        # If not a unicode escape sequence, must be in the lookup table
+        if esc != 'u':
+            try:
+                char = _b[esc]
+            except KeyError:
+                msg = "Invalid \\escape: " + repr(esc)
+                raise ValueError(errmsg(msg, s, end))
+            end += 1
+        else:
+            # Unicode escape sequence
+            esc = s[end + 1:end + 5]
+            next_end = end + 5
+            if len(esc) != 4:
+                msg = "Invalid \\uXXXX escape"
+                raise ValueError(errmsg(msg, s, end))
+            uni = int(esc, 16)
+            # Check for surrogate pair on UCS-4 systems
+            if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535:
+                msg = "Invalid \\uXXXX\\uXXXX surrogate pair"
+                if not s[end + 5:end + 7] == '\\u':
+                    raise ValueError(errmsg(msg, s, end))
+                esc2 = s[end + 7:end + 11]
+                if len(esc2) != 4:
+                    raise ValueError(errmsg(msg, s, end))
+                uni2 = int(esc2, 16)
+                uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
+                next_end += 6
+            char = unichr(uni)
+            end = next_end
+        # Append the unescaped character
+        _append(char)
+    return u''.join(chunks), end
+
+
+# Use speedup if available
+scanstring = c_scanstring or py_scanstring
+
+WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)
+WHITESPACE_STR = ' \t\n\r'
+
+def JSONObject(s_and_end, encoding, strict, scan_once, object_hook,
+               object_pairs_hook, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
+    s, end = s_and_end
+    pairs = []
+    pairs_append = pairs.append
+    # Use a slice to prevent IndexError from being raised, the following
+    # check will raise a more specific ValueError if the string is empty
+    nextchar = s[end:end + 1]
+    # Normally we expect nextchar == '"'
+    if nextchar != '"':
+        if nextchar in _ws:
+            end = _w(s, end).end()
+            nextchar = s[end:end + 1]
+        # Trivial empty object
+        if nextchar == '}':
+            if object_pairs_hook is not None:
+                result = object_pairs_hook(pairs)
+                return result, end
+            pairs = {}
+            if object_hook is not None:
+                pairs = object_hook(pairs)
+            return pairs, end + 1
+        elif nextchar != '"':
+            raise ValueError(errmsg(
+                "Expecting property name enclosed in double quotes", s, end))
+    end += 1
+    while True:
+        key, end = scanstring(s, end, encoding, strict)
+
+        # To skip some function call overhead we optimize the fast paths where
+        # the JSON key separator is ": " or just ":".
+        if s[end:end + 1] != ':':
+            end = _w(s, end).end()
+            if s[end:end + 1] != ':':
+                raise ValueError(errmsg("Expecting ':' delimiter", s, end))
+        end += 1
+
+        try:
+            if s[end] in _ws:
+                end += 1
+                if s[end] in _ws:
+                    end = _w(s, end + 1).end()
+        except IndexError:
+            pass
+
+        try:
+            value, end = scan_once(s, end)
+        except StopIteration:
+            raise ValueError(errmsg("Expecting object", s, end))
+        pairs_append((key, value))
+
+        try:
+            nextchar = s[end]
+            if nextchar in _ws:
+                end = _w(s, end + 1).end()
+                nextchar = s[end]
+        except IndexError:
+            nextchar = ''
+        end += 1
+
+        if nextchar == '}':
+            break
+        elif nextchar != ',':
+            raise ValueError(errmsg("Expecting ',' delimiter", s, end - 1))
+
+        try:
+            nextchar = s[end]
+            if nextchar in _ws:
+                end += 1
+                nextchar = s[end]
+                if nextchar in _ws:
+                    end = _w(s, end + 1).end()
+                    nextchar = s[end]
+        except IndexError:
+            nextchar = ''
+
+        end += 1
+        if nextchar != '"':
+            raise ValueError(errmsg(
+                "Expecting property name enclosed in double quotes", s, end - 1))
+    if object_pairs_hook is not None:
+        result = object_pairs_hook(pairs)
+        return result, end
+    pairs = dict(pairs)
+    if object_hook is not None:
+        pairs = object_hook(pairs)
+    return pairs, end
+
+def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
+    s, end = s_and_end
+    values = []
+    nextchar = s[end:end + 1]
+    if nextchar in _ws:
+        end = _w(s, end + 1).end()
+        nextchar = s[end:end + 1]
+    # Look-ahead for trivial empty array
+    if nextchar == ']':
+        return values, end + 1
+    _append = values.append
+    while True:
+        try:
+            value, end = scan_once(s, end)
+        except StopIteration:
+            raise ValueError(errmsg("Expecting object", s, end))
+        _append(value)
+        nextchar = s[end:end + 1]
+        if nextchar in _ws:
+            end = _w(s, end + 1).end()
+            nextchar = s[end:end + 1]
+        end += 1
+        if nextchar == ']':
+            break
+        elif nextchar != ',':
+            raise ValueError(errmsg("Expecting ',' delimiter", s, end))
+        try:
+            if s[end] in _ws:
+                end += 1
+                if s[end] in _ws:
+                    end = _w(s, end + 1).end()
+        except IndexError:
+            pass
+
+    return values, end
+
+class JSONDecoder(object):
+    """Simple JSON <http://json.org> decoder
+
+    Performs the following translations in decoding by default:
+
+    +---------------+-------------------+
+    | JSON          | Python            |
+    +===============+===================+
+    | object        | dict              |
+    +---------------+-------------------+
+    | array         | list              |
+    +---------------+-------------------+
+    | string        | unicode           |
+    +---------------+-------------------+
+    | number (int)  | int, long         |
+    +---------------+-------------------+
+    | number (real) | float             |
+    +---------------+-------------------+
+    | true          | True              |
+    +---------------+-------------------+
+    | false         | False             |
+    +---------------+-------------------+
+    | null          | None              |
+    +---------------+-------------------+
+
+    It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
+    their corresponding ``float`` values, which is outside the JSON spec.
+
+    """
+
+    def __init__(self, encoding=None, object_hook=None, parse_float=None,
+            parse_int=None, parse_constant=None, strict=True,
+            object_pairs_hook=None):
+        """``encoding`` determines the encoding used to interpret any ``str``
+        objects decoded by this instance (utf-8 by default).  It has no
+        effect when decoding ``unicode`` objects.
+
+        Note that currently only encodings that are a superset of ASCII work,
+        strings of other encodings should be passed in as ``unicode``.
+
+        ``object_hook``, if specified, will be called with the result
+        of every JSON object decoded and its return value will be used in
+        place of the given ``dict``.  This can be used to provide custom
+        deserializations (e.g. to support JSON-RPC class hinting).
+
+        ``object_pairs_hook``, if specified will be called with the result of
+        every JSON object decoded with an ordered list of pairs.  The return
+        value of ``object_pairs_hook`` will be used instead of the ``dict``.
+        This feature can be used to implement custom decoders that rely on the
+        order that the key and value pairs are decoded (for example,
+        collections.OrderedDict will remember the order of insertion). If
+        ``object_hook`` is also defined, the ``object_pairs_hook`` takes
+        priority.
+
+        ``parse_float``, if specified, will be called with the string
+        of every JSON float to be decoded. By default this is equivalent to
+        float(num_str). This can be used to use another datatype or parser
+        for JSON floats (e.g. decimal.Decimal).
+
+        ``parse_int``, if specified, will be called with the string
+        of every JSON int to be decoded. By default this is equivalent to
+        int(num_str). This can be used to use another datatype or parser
+        for JSON integers (e.g. float).
+
+        ``parse_constant``, if specified, will be called with one of the
+        following strings: -Infinity, Infinity, NaN.
+        This can be used to raise an exception if invalid JSON numbers
+        are encountered.
+
+        If ``strict`` is false (true is the default), then control
+        characters will be allowed inside strings.  Control characters in
+        this context are those with character codes in the 0-31 range,
+        including ``'\\t'`` (tab), ``'\\n'``, ``'\\r'`` and ``'\\0'``.
+
+        """
+        self.encoding = encoding
+        self.object_hook = object_hook
+        self.object_pairs_hook = object_pairs_hook
+        self.parse_float = parse_float or float
+        self.parse_int = parse_int or int
+        self.parse_constant = parse_constant or _CONSTANTS.__getitem__
+        self.strict = strict
+        self.parse_object = JSONObject
+        self.parse_array = JSONArray
+        self.parse_string = scanstring
+        self.scan_once = scanner.make_scanner(self)
+
+    def decode(self, s, _w=WHITESPACE.match):
+        """Return the Python representation of ``s`` (a ``str`` or ``unicode``
+        instance containing a JSON document)
+
+        """
+        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
+        end = _w(s, end).end()
+        if end != len(s):
+            raise ValueError(errmsg("Extra data", s, end, len(s)))
+        return obj
+
+    def raw_decode(self, s, idx=0):
+        """Decode a JSON document from ``s`` (a ``str`` or ``unicode``
+        beginning with a JSON document) and return a 2-tuple of the Python
+        representation and the index in ``s`` where the document ended.
+
+        This can be used to decode a JSON document from a string that may
+        have extraneous data at the end.
+
+        """
+        try:
+            obj, end = self.scan_once(s, idx)
+        except StopIteration:
+            raise ValueError("No JSON object could be decoded")
+        return obj, end
diff --git a/src/main/resources/PythonLibs/json/encoder.py b/src/main/resources/PythonLibs/json/encoder.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d1aaa8eedfd6173beea57ac09a0fa9dcda34593
--- /dev/null
+++ b/src/main/resources/PythonLibs/json/encoder.py
@@ -0,0 +1,447 @@
+"""Implementation of JSONEncoder
+"""
+import re
+
+try:
+    from _json import encode_basestring_ascii as c_encode_basestring_ascii
+except ImportError:
+    c_encode_basestring_ascii = None
+try:
+    from _json import make_encoder as c_make_encoder
+except ImportError:
+    c_make_encoder = None
+
+ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
+ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
+HAS_UTF8 = re.compile(r'[\x80-\xff]')
+ESCAPE_DCT = {
+    '\\': '\\\\',
+    '"': '\\"',
+    '\b': '\\b',
+    '\f': '\\f',
+    '\n': '\\n',
+    '\r': '\\r',
+    '\t': '\\t',
+}
+for i in range(0x20):
+    ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
+    #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
+
+INFINITY = float('inf')
+FLOAT_REPR = repr
+
+def encode_basestring(s):
+    """Return a JSON representation of a Python string
+
+    """
+    def replace(match):
+        return ESCAPE_DCT[match.group(0)]
+    return '"' + ESCAPE.sub(replace, s) + '"'
+
+
+def py_encode_basestring_ascii(s):
+    """Return an ASCII-only JSON representation of a Python string
+
+    """
+    if isinstance(s, str) and HAS_UTF8.search(s) is not None:
+        s = s.decode('utf-8')
+    def replace(match):
+        s = match.group(0)
+        try:
+            return ESCAPE_DCT[s]
+        except KeyError:
+            n = ord(s)
+            if n < 0x10000:
+                return '\\u{0:04x}'.format(n)
+                #return '\\u%04x' % (n,)
+            else:
+                # surrogate pair
+                n -= 0x10000
+                s1 = 0xd800 | ((n >> 10) & 0x3ff)
+                s2 = 0xdc00 | (n & 0x3ff)
+                return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
+                #return '\\u%04x\\u%04x' % (s1, s2)
+    return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
+
+
+encode_basestring_ascii = (
+    c_encode_basestring_ascii or py_encode_basestring_ascii)
+
+class JSONEncoder(object):
+    """Extensible JSON <http://json.org> encoder for Python data structures.
+
+    Supports the following objects and types by default:
+
+    +-------------------+---------------+
+    | Python            | JSON          |
+    +===================+===============+
+    | dict              | object        |
+    +-------------------+---------------+
+    | list, tuple       | array         |
+    +-------------------+---------------+
+    | str, unicode      | string        |
+    +-------------------+---------------+
+    | int, long, float  | number        |
+    +-------------------+---------------+
+    | True              | true          |
+    +-------------------+---------------+
+    | False             | false         |
+    +-------------------+---------------+
+    | None              | null          |
+    +-------------------+---------------+
+
+    To extend this to recognize other objects, subclass and implement a
+    ``.default()`` method with another method that returns a serializable
+    object for ``o`` if possible, otherwise it should call the superclass
+    implementation (to raise ``TypeError``).
+
+    """
+    item_separator = ', '
+    key_separator = ': '
+    def __init__(self, skipkeys=False, ensure_ascii=True,
+            check_circular=True, allow_nan=True, sort_keys=False,
+            indent=None, separators=None, encoding='utf-8', default=None):
+        """Constructor for JSONEncoder, with sensible defaults.
+
+        If skipkeys is false, then it is a TypeError to attempt
+        encoding of keys that are not str, int, long, float or None.  If
+        skipkeys is True, such items are simply skipped.
+
+        If *ensure_ascii* is true (the default), all non-ASCII
+        characters in the output are escaped with \uXXXX sequences,
+        and the results are str instances consisting of ASCII
+        characters only.  If ensure_ascii is False, a result may be a
+        unicode instance.  This usually happens if the input contains
+        unicode strings or the *encoding* parameter is used.
+
+        If check_circular is true, then lists, dicts, and custom encoded
+        objects will be checked for circular references during encoding to
+        prevent an infinite recursion (which would cause an OverflowError).
+        Otherwise, no such check takes place.
+
+        If allow_nan is true, then NaN, Infinity, and -Infinity will be
+        encoded as such.  This behavior is not JSON specification compliant,
+        but is consistent with most JavaScript based encoders and decoders.
+        Otherwise, it will be a ValueError to encode such floats.
+
+        If sort_keys is true, then the output of dictionaries will be
+        sorted by key; this is useful for regression tests to ensure
+        that JSON serializations can be compared on a day-to-day basis.
+
+        If indent is a non-negative integer, then JSON array
+        elements and object members will be pretty-printed with that
+        indent level.  An indent level of 0 will only insert newlines.
+        None is the most compact representation.  Since the default
+        item separator is ', ',  the output might include trailing
+        whitespace when indent is specified.  You can use
+        separators=(',', ': ') to avoid this.
+
+        If specified, separators should be a (item_separator, key_separator)
+        tuple.  The default is (', ', ': ').  To get the most compact JSON
+        representation you should specify (',', ':') to eliminate whitespace.
+
+        If specified, default is a function that gets called for objects
+        that can't otherwise be serialized.  It should return a JSON encodable
+        version of the object or raise a ``TypeError``.
+
+        If encoding is not None, then all input strings will be
+        transformed into unicode using that encoding prior to JSON-encoding.
+        The default is UTF-8.
+
+        """
+
+        self.skipkeys = skipkeys
+        self.ensure_ascii = ensure_ascii
+        self.check_circular = check_circular
+        self.allow_nan = allow_nan
+        self.sort_keys = sort_keys
+        self.indent = indent
+        if separators is not None:
+            self.item_separator, self.key_separator = separators
+        if default is not None:
+            self.default = default
+        self.encoding = encoding
+
+    def default(self, o):
+        """Implement this method in a subclass such that it returns
+        a serializable object for ``o``, or calls the base implementation
+        (to raise a ``TypeError``).
+
+        For example, to support arbitrary iterators, you could
+        implement default like this::
+
+            def default(self, o):
+                try:
+                    iterable = iter(o)
+                except TypeError:
+                    pass
+                else:
+                    return list(iterable)
+                return JSONEncoder.default(self, o)
+
+        """
+        raise TypeError(repr(o) + " is not JSON serializable")
+
+    def encode(self, o):
+        """Return a JSON string representation of a Python data structure.
+
+        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
+        '{"foo": ["bar", "baz"]}'
+
+        """
+        # This is for extremely simple cases and benchmarks.
+        if isinstance(o, basestring):
+            if isinstance(o, str):
+                _encoding = self.encoding
+                if (_encoding is not None
+                        and not (_encoding == 'utf-8')):
+                    o = o.decode(_encoding)
+            if self.ensure_ascii:
+                return encode_basestring_ascii(o)
+            else:
+                return encode_basestring(o)
+        # This doesn't pass the iterator directly to ''.join() because the
+        # exceptions aren't as detailed.  The list call should be roughly
+        # equivalent to the PySequence_Fast that ''.join() would do.
+        chunks = self.iterencode(o, _one_shot=True)
+        if not isinstance(chunks, (list, tuple)):
+            chunks = list(chunks)
+        return ''.join(chunks)
+
+    def iterencode(self, o, _one_shot=False):
+        """Encode the given object and yield each string
+        representation as available.
+
+        For example::
+
+            for chunk in JSONEncoder().iterencode(bigobject):
+                mysocket.write(chunk)
+
+        """
+        if self.check_circular:
+            markers = {}
+        else:
+            markers = None
+        if self.ensure_ascii:
+            _encoder = encode_basestring_ascii
+        else:
+            _encoder = encode_basestring
+        if self.encoding != 'utf-8':
+            def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
+                if isinstance(o, str):
+                    o = o.decode(_encoding)
+                return _orig_encoder(o)
+
+        def floatstr(o, allow_nan=self.allow_nan,
+                _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY):
+            # Check for specials.  Note that this type of test is processor
+            # and/or platform-specific, so do tests which don't depend on the
+            # internals.
+
+            if o != o:
+                text = 'NaN'
+            elif o == _inf:
+                text = 'Infinity'
+            elif o == _neginf:
+                text = '-Infinity'
+            else:
+                return _repr(o)
+
+            if not allow_nan:
+                raise ValueError(
+                    "Out of range float values are not JSON compliant: " +
+                    repr(o))
+
+            return text
+
+
+        if (_one_shot and c_make_encoder is not None
+                and self.indent is None and not self.sort_keys):
+            _iterencode = c_make_encoder(
+                markers, self.default, _encoder, self.indent,
+                self.key_separator, self.item_separator, self.sort_keys,
+                self.skipkeys, self.allow_nan)
+        else:
+            _iterencode = _make_iterencode(
+                markers, self.default, _encoder, self.indent, floatstr,
+                self.key_separator, self.item_separator, self.sort_keys,
+                self.skipkeys, _one_shot)
+        return _iterencode(o, 0)
+
+def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
+        _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
+        ## HACK: hand-optimized bytecode; turn globals into locals
+        ValueError=ValueError,
+        basestring=basestring,
+        dict=dict,
+        float=float,
+        id=id,
+        int=int,
+        isinstance=isinstance,
+        list=list,
+        long=long,
+        str=str,
+        tuple=tuple,
+    ):
+
+    def _iterencode_list(lst, _current_indent_level):
+        if not lst:
+            yield '[]'
+            return
+        if markers is not None:
+            markerid = id(lst)
+            if markerid in markers:
+                raise ValueError("Circular reference detected")
+            markers[markerid] = lst
+        buf = '['
+        if _indent is not None:
+            _current_indent_level += 1
+            newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
+            separator = _item_separator + newline_indent
+            buf += newline_indent
+        else:
+            newline_indent = None
+            separator = _item_separator
+        first = True
+        for value in lst:
+            if first:
+                first = False
+            else:
+                buf = separator
+            if isinstance(value, basestring):
+                yield buf + _encoder(value)
+            elif value is None:
+                yield buf + 'null'
+            elif value is True:
+                yield buf + 'true'
+            elif value is False:
+                yield buf + 'false'
+            elif isinstance(value, (int, long)):
+                yield buf + str(value)
+            elif isinstance(value, float):
+                yield buf + _floatstr(value)
+            else:
+                yield buf
+                if isinstance(value, (list, tuple)):
+                    chunks = _iterencode_list(value, _current_indent_level)
+                elif isinstance(value, dict):
+                    chunks = _iterencode_dict(value, _current_indent_level)
+                else:
+                    chunks = _iterencode(value, _current_indent_level)
+                for chunk in chunks:
+                    yield chunk
+        if newline_indent is not None:
+            _current_indent_level -= 1
+            yield '\n' + (' ' * (_indent * _current_indent_level))
+        yield ']'
+        if markers is not None:
+            del markers[markerid]
+
+    def _iterencode_dict(dct, _current_indent_level):
+        if not dct:
+            yield '{}'
+            return
+        if markers is not None:
+            markerid = id(dct)
+            if markerid in markers:
+                raise ValueError("Circular reference detected")
+            markers[markerid] = dct
+        yield '{'
+        if _indent is not None:
+            _current_indent_level += 1
+            newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
+            item_separator = _item_separator + newline_indent
+            yield newline_indent
+        else:
+            newline_indent = None
+            item_separator = _item_separator
+        first = True
+        if _sort_keys:
+            items = sorted(dct.items(), key=lambda kv: kv[0])
+        else:
+            items = dct.iteritems()
+        for key, value in items:
+            if isinstance(key, basestring):
+                pass
+            # JavaScript is weakly typed for these, so it makes sense to
+            # also allow them.  Many encoders seem to do something like this.
+            elif isinstance(key, float):
+                key = _floatstr(key)
+            elif key is True:
+                key = 'true'
+            elif key is False:
+                key = 'false'
+            elif key is None:
+                key = 'null'
+            elif isinstance(key, (int, long)):
+                key = str(key)
+            elif _skipkeys:
+                continue
+            else:
+                raise TypeError("key " + repr(key) + " is not a string")
+            if first:
+                first = False
+            else:
+                yield item_separator
+            yield _encoder(key)
+            yield _key_separator
+            if isinstance(value, basestring):
+                yield _encoder(value)
+            elif value is None:
+                yield 'null'
+            elif value is True:
+                yield 'true'
+            elif value is False:
+                yield 'false'
+            elif isinstance(value, (int, long)):
+                yield str(value)
+            elif isinstance(value, float):
+                yield _floatstr(value)
+            else:
+                if isinstance(value, (list, tuple)):
+                    chunks = _iterencode_list(value, _current_indent_level)
+                elif isinstance(value, dict):
+                    chunks = _iterencode_dict(value, _current_indent_level)
+                else:
+                    chunks = _iterencode(value, _current_indent_level)
+                for chunk in chunks:
+                    yield chunk
+        if newline_indent is not None:
+            _current_indent_level -= 1
+            yield '\n' + (' ' * (_indent * _current_indent_level))
+        yield '}'
+        if markers is not None:
+            del markers[markerid]
+
+    def _iterencode(o, _current_indent_level):
+        if isinstance(o, basestring):
+            yield _encoder(o)
+        elif o is None:
+            yield 'null'
+        elif o is True:
+            yield 'true'
+        elif o is False:
+            yield 'false'
+        elif isinstance(o, (int, long)):
+            yield str(o)
+        elif isinstance(o, float):
+            yield _floatstr(o)
+        elif isinstance(o, (list, tuple)):
+            for chunk in _iterencode_list(o, _current_indent_level):
+                yield chunk
+        elif isinstance(o, dict):
+            for chunk in _iterencode_dict(o, _current_indent_level):
+                yield chunk
+        else:
+            if markers is not None:
+                markerid = id(o)
+                if markerid in markers:
+                    raise ValueError("Circular reference detected")
+                markers[markerid] = o
+            o = _default(o)
+            for chunk in _iterencode(o, _current_indent_level):
+                yield chunk
+            if markers is not None:
+                del markers[markerid]
+
+    return _iterencode
diff --git a/src/main/resources/PythonLibs/json/scanner.py b/src/main/resources/PythonLibs/json/scanner.py
new file mode 100644
index 0000000000000000000000000000000000000000..74e6805155d85399fd5a6a67d5b35765270f63db
--- /dev/null
+++ b/src/main/resources/PythonLibs/json/scanner.py
@@ -0,0 +1,67 @@
+"""JSON token scanner
+"""
+import re
+try:
+    from _json import make_scanner as c_make_scanner
+except ImportError:
+    c_make_scanner = None
+
+__all__ = ['make_scanner']
+
+NUMBER_RE = re.compile(
+    r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?',
+    (re.VERBOSE | re.MULTILINE | re.DOTALL))
+
+def py_make_scanner(context):
+    parse_object = context.parse_object
+    parse_array = context.parse_array
+    parse_string = context.parse_string
+    match_number = NUMBER_RE.match
+    encoding = context.encoding
+    strict = context.strict
+    parse_float = context.parse_float
+    parse_int = context.parse_int
+    parse_constant = context.parse_constant
+    object_hook = context.object_hook
+    object_pairs_hook = context.object_pairs_hook
+
+    def _scan_once(string, idx):
+        try:
+            nextchar = string[idx]
+        except IndexError:
+            raise StopIteration
+
+        if nextchar == '"':
+            return parse_string(string, idx + 1, encoding, strict)
+        elif nextchar == '{':
+            return parse_object((string, idx + 1), encoding, strict,
+                _scan_once, object_hook, object_pairs_hook)
+        elif nextchar == '[':
+            return parse_array((string, idx + 1), _scan_once)
+        elif nextchar == 'n' and string[idx:idx + 4] == 'null':
+            return None, idx + 4
+        elif nextchar == 't' and string[idx:idx + 4] == 'true':
+            return True, idx + 4
+        elif nextchar == 'f' and string[idx:idx + 5] == 'false':
+            return False, idx + 5
+
+        m = match_number(string, idx)
+        if m is not None:
+            integer, frac, exp = m.groups()
+            if frac or exp:
+                res = parse_float(integer + (frac or '') + (exp or ''))
+            else:
+                res = parse_int(integer)
+            return res, m.end()
+        elif nextchar == 'N' and string[idx:idx + 3] == 'NaN':
+            return parse_constant('NaN'), idx + 3
+        elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity':
+            return parse_constant('Infinity'), idx + 8
+        elif nextchar == '-' and string[idx:idx + 9] == '-Infinity':
+            return parse_constant('-Infinity'), idx + 9
+        else:
+            raise StopIteration
+
+    return _scan_once
+
+make_scanner = c_make_scanner or py_make_scanner
diff --git a/src/main/resources/PythonLibs/json/tool.py b/src/main/resources/PythonLibs/json/tool.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc5d74923df2abef7a6c94e2d34eba7c13fecded
--- /dev/null
+++ b/src/main/resources/PythonLibs/json/tool.py
@@ -0,0 +1,40 @@
+r"""Command-line tool to validate and pretty-print JSON
+
+Usage::
+
+    $ echo '{"json":"obj"}' | python -m json.tool
+    {
+        "json": "obj"
+    }
+    $ echo '{ 1.2:3.4}' | python -m json.tool
+    Expecting property name enclosed in double quotes: line 1 column 3 (char 2)
+
+"""
+import sys
+import json
+
+def main():
+    if len(sys.argv) == 1:
+        infile = sys.stdin
+        outfile = sys.stdout
+    elif len(sys.argv) == 2:
+        infile = open(sys.argv[1], 'rb')
+        outfile = sys.stdout
+    elif len(sys.argv) == 3:
+        infile = open(sys.argv[1], 'rb')
+        outfile = open(sys.argv[2], 'wb')
+    else:
+        raise SystemExit(sys.argv[0] + " [infile [outfile]]")
+    with infile:
+        try:
+            obj = json.load(infile)
+        except ValueError, e:
+            raise SystemExit(e)
+    with outfile:
+        json.dump(obj, outfile, sort_keys=True,
+                  indent=4, separators=(',', ': '))
+        outfile.write('\n')
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/main/resources/PythonLibs/keyword.py b/src/main/resources/PythonLibs/keyword.py
new file mode 100644
index 0000000000000000000000000000000000000000..69794bda8c879a098a2adaef5e4bcee32f8683c8
--- /dev/null
+++ b/src/main/resources/PythonLibs/keyword.py
@@ -0,0 +1,93 @@
+#! /usr/bin/env python
+
+"""Keywords (from "graminit.c")
+
+This file is automatically generated; please don't muck it up!
+
+To update the symbols in this file, 'cd' to the top directory of
+the python source tree after building the interpreter and run:
+
+    ./python Lib/keyword.py
+"""
+
+__all__ = ["iskeyword", "kwlist"]
+
+kwlist = [
+#--start keywords--
+        'and',
+        'as',
+        'assert',
+        'break',
+        'class',
+        'continue',
+        'def',
+        'del',
+        'elif',
+        'else',
+        'except',
+        'exec',
+        'finally',
+        'for',
+        'from',
+        'global',
+        'if',
+        'import',
+        'in',
+        'is',
+        'lambda',
+        'not',
+        'or',
+        'pass',
+        'print',
+        'raise',
+        'return',
+        'try',
+        'while',
+        'with',
+        'yield',
+#--end keywords--
+        ]
+
+iskeyword = frozenset(kwlist).__contains__
+
+def main():
+    import sys, re
+
+    args = sys.argv[1:]
+    iptfile = args and args[0] or "Python/graminit.c"
+    if len(args) > 1: optfile = args[1]
+    else: optfile = "Lib/keyword.py"
+
+    # scan the source file for keywords
+    fp = open(iptfile)
+    strprog = re.compile('"([^"]+)"')
+    lines = []
+    for line in fp:
+        if '{1, "' in line:
+            match = strprog.search(line)
+            if match:
+                lines.append("        '" + match.group(1) + "',\n")
+    fp.close()
+    lines.sort()
+
+    # load the output skeleton from the target
+    fp = open(optfile)
+    format = fp.readlines()
+    fp.close()
+
+    # insert the lines of keywords
+    try:
+        start = format.index("#--start keywords--\n") + 1
+        end = format.index("#--end keywords--\n")
+        format[start:end] = lines
+    except ValueError:
+        sys.stderr.write("target does not contain format markers\n")
+        sys.exit(1)
+
+    # write the output file
+    fp = open(optfile, 'w')
+    fp.write(''.join(format))
+    fp.close()
+
+if __name__ == "__main__":
+    main()
diff --git a/src/main/resources/PythonLibs/linecache.py b/src/main/resources/PythonLibs/linecache.py
new file mode 100644
index 0000000000000000000000000000000000000000..811f27fe3657c776fc5795d469f24cb21615492f
--- /dev/null
+++ b/src/main/resources/PythonLibs/linecache.py
@@ -0,0 +1,135 @@
+"""Cache lines from files.
+
+This is intended to read lines from modules imported -- hence if a filename
+is not found, it will look down the module search path for a file by
+that name.
+"""
+
+import sys
+import os
+
+__all__ = ["getline", "clearcache", "checkcache"]
+
+def getline(filename, lineno, module_globals=None):
+    lines = getlines(filename, module_globals)
+    if 1 <= lineno <= len(lines):
+        return lines[lineno-1]
+    else:
+        return ''
+
+
+# The cache
+
+cache = {} # The cache
+
+
+def clearcache():
+    """Clear the cache entirely."""
+
+    global cache
+    cache = {}
+
+
+def getlines(filename, module_globals=None):
+    """Get the lines for a file from the cache.
+    Update the cache if it doesn't contain an entry for this file already."""
+
+    if filename in cache:
+        return cache[filename][2]
+    else:
+        return updatecache(filename, module_globals)
+
+
+def checkcache(filename=None):
+    """Discard cache entries that are out of date.
+    (This is not checked upon each call!)"""
+
+    if filename is None:
+        filenames = cache.keys()
+    else:
+        if filename in cache:
+            filenames = [filename]
+        else:
+            return
+
+    for filename in filenames:
+        size, mtime, lines, fullname = cache[filename]
+        if mtime is None:
+            continue   # no-op for files loaded via a __loader__
+        try:
+            stat = os.stat(fullname)
+        except os.error:
+            del cache[filename]
+            continue
+        if size != stat.st_size or mtime != stat.st_mtime:
+            del cache[filename]
+
+
+def updatecache(filename, module_globals=None):
+    """Update a cache entry and return its list of lines.
+    If something's wrong, print a message, discard the cache entry,
+    and return an empty list."""
+
+    if filename in cache:
+        del cache[filename]
+    if not filename or (filename.startswith('<') and filename.endswith('>')):
+        return []
+
+    fullname = filename
+    try:
+        stat = os.stat(fullname)
+    except OSError:
+        basename = filename
+
+        # Try for a __loader__, if available
+        if module_globals and '__loader__' in module_globals:
+            name = module_globals.get('__name__')
+            loader = module_globals['__loader__']
+            get_source = getattr(loader, 'get_source', None)
+
+            if name and get_source:
+                try:
+                    data = get_source(name)
+                except (ImportError, IOError):
+                    pass
+                else:
+                    if data is None:
+                        # No luck, the PEP302 loader cannot find the source
+                        # for this module.
+                        return []
+                    cache[filename] = (
+                        len(data), None,
+                        [line+'\n' for line in data.splitlines()], fullname
+                    )
+                    return cache[filename][2]
+
+        # Try looking through the module search path, which is only useful
+        # when handling a relative filename.
+        if os.path.isabs(filename):
+            return []
+
+        for dirname in sys.path:
+            # When using imputil, sys.path may contain things other than
+            # strings; ignore them when it happens.
+            try:
+                fullname = os.path.join(dirname, basename)
+            except (TypeError, AttributeError):
+                # Not sufficiently string-like to do anything useful with.
+                continue
+            try:
+                stat = os.stat(fullname)
+                break
+            except os.error:
+                pass
+        else:
+            return []
+    try:
+        with open(fullname, 'rU') as fp:
+            lines = fp.readlines()
+    except IOError:
+        return []
+    if lines and not lines[-1].endswith('\n'):
+        lines[-1] += '\n'
+    size, mtime = stat.st_size, stat.st_mtime
+    cache[filename] = size, mtime, lines, fullname
+    return lines
diff --git a/src/main/resources/PythonLibs/locale.py b/src/main/resources/PythonLibs/locale.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ddfdb782c0d0945413ddbfebe2fd34975a896ec
--- /dev/null
+++ b/src/main/resources/PythonLibs/locale.py
@@ -0,0 +1,1882 @@
+""" Locale support.
+
+    The module provides low-level access to the C lib's locale APIs
+    and adds high level number formatting APIs as well as a locale
+    aliasing engine to complement these.
+
+    The aliasing engine includes support for many commonly used locale
+    names and maps them to values suitable for passing to the C lib's
+    setlocale() function. It also includes default encodings for all
+    supported locale names.
+
+"""
+
+import sys
+import encodings
+import encodings.aliases
+import re
+import operator
+import functools
+
+try:
+    _unicode = unicode
+except NameError:
+    # If Python is built without Unicode support, the unicode type
+    # will not exist. Fake one.
+    class _unicode(object):
+        pass
+
+# Try importing the _locale module.
+#
+# If this fails, fall back on a basic 'C' locale emulation.
+
+# Yuck:  LC_MESSAGES is non-standard:  can't tell whether it exists before
+# trying the import.  So __all__ is also fiddled at the end of the file.
+__all__ = ["getlocale", "getdefaultlocale", "getpreferredencoding", "Error",
+           "setlocale", "resetlocale", "localeconv", "strcoll", "strxfrm",
+           "str", "atof", "atoi", "format", "format_string", "currency",
+           "normalize", "LC_CTYPE", "LC_COLLATE", "LC_TIME", "LC_MONETARY",
+           "LC_NUMERIC", "LC_ALL", "CHAR_MAX"]
+
+try:
+
+    from _locale import *
+
+except ImportError:
+
+    # Locale emulation
+
+    CHAR_MAX = 127
+    LC_ALL = 6
+    LC_COLLATE = 3
+    LC_CTYPE = 0
+    LC_MESSAGES = 5
+    LC_MONETARY = 4
+    LC_NUMERIC = 1
+    LC_TIME = 2
+    Error = ValueError
+
+    def localeconv():
+        """ localeconv() -> dict.
+            Returns numeric and monetary locale-specific parameters.
+        """
+        # 'C' locale default values
+        return {'grouping': [127],
+                'currency_symbol': '',
+                'n_sign_posn': 127,
+                'p_cs_precedes': 127,
+                'n_cs_precedes': 127,
+                'mon_grouping': [],
+                'n_sep_by_space': 127,
+                'decimal_point': '.',
+                'negative_sign': '',
+                'positive_sign': '',
+                'p_sep_by_space': 127,
+                'int_curr_symbol': '',
+                'p_sign_posn': 127,
+                'thousands_sep': '',
+                'mon_thousands_sep': '',
+                'frac_digits': 127,
+                'mon_decimal_point': '',
+                'int_frac_digits': 127}
+
+    def setlocale(category, value=None):
+        """ setlocale(integer,string=None) -> string.
+            Activates/queries locale processing.
+        """
+        if value not in (None, '', 'C'):
+            raise Error, '_locale emulation only supports "C" locale'
+        return 'C'
+
+    def strcoll(a,b):
+        """ strcoll(string,string) -> int.
+            Compares two strings according to the locale.
+        """
+        return cmp(a,b)
+
+    def strxfrm(s):
+        """ strxfrm(string) -> string.
+            Returns a string that behaves for cmp locale-aware.
+        """
+        return s
+
+
+_localeconv = localeconv
+
+# With this dict, you can override some items of localeconv's return value.
+# This is useful for testing purposes.
+_override_localeconv = {}
+
+@functools.wraps(_localeconv)
+def localeconv():
+    d = _localeconv()
+    if _override_localeconv:
+        d.update(_override_localeconv)
+    return d
+
+
+### Number formatting APIs
+
+# Author: Martin von Loewis
+# improved by Georg Brandl
+
+# Iterate over grouping intervals
+def _grouping_intervals(grouping):
+    last_interval = None
+    for interval in grouping:
+        # if grouping is -1, we are done
+        if interval == CHAR_MAX:
+            return
+        # 0: re-use last group ad infinitum
+        if interval == 0:
+            if last_interval is None:
+                raise ValueError("invalid grouping")
+            while True:
+                yield last_interval
+        yield interval
+        last_interval = interval
+
+#perform the grouping from right to left
+def _group(s, monetary=False):
+    conv = localeconv()
+    thousands_sep = conv[monetary and 'mon_thousands_sep' or 'thousands_sep']
+    grouping = conv[monetary and 'mon_grouping' or 'grouping']
+    if not grouping:
+        return (s, 0)
+    if s[-1] == ' ':
+        stripped = s.rstrip()
+        right_spaces = s[len(stripped):]
+        s = stripped
+    else:
+        right_spaces = ''
+    left_spaces = ''
+    groups = []
+    for interval in _grouping_intervals(grouping):
+        if not s or s[-1] not in "0123456789":
+            # only non-digit characters remain (sign, spaces)
+            left_spaces = s
+            s = ''
+            break
+        groups.append(s[-interval:])
+        s = s[:-interval]
+    if s:
+        groups.append(s)
+    groups.reverse()
+    return (
+        left_spaces + thousands_sep.join(groups) + right_spaces,
+        len(thousands_sep) * (len(groups) - 1)
+    )
+
+# Strip a given amount of excess padding from the given string
+def _strip_padding(s, amount):
+    lpos = 0
+    while amount and s[lpos] == ' ':
+        lpos += 1
+        amount -= 1
+    rpos = len(s) - 1
+    while amount and s[rpos] == ' ':
+        rpos -= 1
+        amount -= 1
+    return s[lpos:rpos+1]
+
+_percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?'
+                         r'(?P<modifiers>[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]')
+
+def format(percent, value, grouping=False, monetary=False, *additional):
+    """Returns the locale-aware substitution of a %? specifier
+    (percent).
+
+    additional is for format strings which contain one or more
+    '*' modifiers."""
+    # this is only for one-percent-specifier strings and this should be checked
+    match = _percent_re.match(percent)
+    if not match or len(match.group())!= len(percent):
+        raise ValueError(("format() must be given exactly one %%char "
+                         "format specifier, %s not valid") % repr(percent))
+    return _format(percent, value, grouping, monetary, *additional)
+
+def _format(percent, value, grouping=False, monetary=False, *additional):
+    if additional:
+        formatted = percent % ((value,) + additional)
+    else:
+        formatted = percent % value
+    # floats and decimal ints need special action!
+    if percent[-1] in 'eEfFgG':
+        seps = 0
+        parts = formatted.split('.')
+        if grouping:
+            parts[0], seps = _group(parts[0], monetary=monetary)
+        decimal_point = localeconv()[monetary and 'mon_decimal_point'
+                                              or 'decimal_point']
+        formatted = decimal_point.join(parts)
+        if seps:
+            formatted = _strip_padding(formatted, seps)
+    elif percent[-1] in 'diu':
+        seps = 0
+        if grouping:
+            formatted, seps = _group(formatted, monetary=monetary)
+        if seps:
+            formatted = _strip_padding(formatted, seps)
+    return formatted
+
+def format_string(f, val, grouping=False):
+    """Formats a string in the same way that the % formatting would use,
+    but takes the current locale into account.
+    Grouping is applied if the third parameter is true."""
+    percents = list(_percent_re.finditer(f))
+    new_f = _percent_re.sub('%s', f)
+
+    if operator.isMappingType(val):
+        new_val = []
+        for perc in percents:
+            if perc.group()[-1]=='%':
+                new_val.append('%')
+            else:
+                new_val.append(format(perc.group(), val, grouping))
+    else:
+        if not isinstance(val, tuple):
+            val = (val,)
+        new_val = []
+        i = 0
+        for perc in percents:
+            if perc.group()[-1]=='%':
+                new_val.append('%')
+            else:
+                starcount = perc.group('modifiers').count('*')
+                new_val.append(_format(perc.group(),
+                                      val[i],
+                                      grouping,
+                                      False,
+                                      *val[i+1:i+1+starcount]))
+                i += (1 + starcount)
+    val = tuple(new_val)
+
+    return new_f % val
+
+def currency(val, symbol=True, grouping=False, international=False):
+    """Formats val according to the currency settings
+    in the current locale."""
+    conv = localeconv()
+
+    # check for illegal values
+    digits = conv[international and 'int_frac_digits' or 'frac_digits']
+    if digits == 127:
+        raise ValueError("Currency formatting is not possible using "
+                         "the 'C' locale.")
+
+    s = format('%%.%if' % digits, abs(val), grouping, monetary=True)
+    # '<' and '>' are markers if the sign must be inserted between symbol and value
+    s = '<' + s + '>'
+
+    if symbol:
+        smb = conv[international and 'int_curr_symbol' or 'currency_symbol']
+        precedes = conv[val<0 and 'n_cs_precedes' or 'p_cs_precedes']
+        separated = conv[val<0 and 'n_sep_by_space' or 'p_sep_by_space']
+
+        if precedes:
+            s = smb + (separated and ' ' or '') + s
+        else:
+            s = s + (separated and ' ' or '') + smb
+
+    sign_pos = conv[val<0 and 'n_sign_posn' or 'p_sign_posn']
+    sign = conv[val<0 and 'negative_sign' or 'positive_sign']
+
+    if sign_pos == 0:
+        s = '(' + s + ')'
+    elif sign_pos == 1:
+        s = sign + s
+    elif sign_pos == 2:
+        s = s + sign
+    elif sign_pos == 3:
+        s = s.replace('<', sign)
+    elif sign_pos == 4:
+        s = s.replace('>', sign)
+    else:
+        # the default if nothing specified;
+        # this should be the most fitting sign position
+        s = sign + s
+
+    return s.replace('<', '').replace('>', '')
+
+def str(val):
+    """Convert float to integer, taking the locale into account."""
+    return format("%.12g", val)
+
+def atof(string, func=float):
+    "Parses a string as a float according to the locale settings."
+    #First, get rid of the grouping
+    ts = localeconv()['thousands_sep']
+    if ts:
+        string = string.replace(ts, '')
+    #next, replace the decimal point with a dot
+    dd = localeconv()['decimal_point']
+    if dd:
+        string = string.replace(dd, '.')
+    #finally, parse the string
+    return func(string)
+
+def atoi(str):
+    "Converts a string to an integer according to the locale settings."
+    return atof(str, int)
+
+def _test():
+    setlocale(LC_ALL, "")
+    #do grouping
+    s1 = format("%d", 123456789,1)
+    print s1, "is", atoi(s1)
+    #standard formatting
+    s1 = str(3.14)
+    print s1, "is", atof(s1)
+
+### Locale name aliasing engine
+
+# Author: Marc-Andre Lemburg, mal@lemburg.com
+# Various tweaks by Fredrik Lundh <fredrik@pythonware.com>
+
+# store away the low-level version of setlocale (it's
+# overridden below)
+_setlocale = setlocale
+
+# Avoid relying on the locale-dependent .lower() method
+# (see issue #1813).
+_ascii_lower_map = ''.join(
+    chr(x + 32 if x >= ord('A') and x <= ord('Z') else x)
+    for x in range(256)
+)
+
+def normalize(localename):
+
+    """ Returns a normalized locale code for the given locale
+        name.
+
+        The returned locale code is formatted for use with
+        setlocale().
+
+        If normalization fails, the original name is returned
+        unchanged.
+
+        If the given encoding is not known, the function defaults to
+        the default encoding for the locale code just like setlocale()
+        does.
+
+    """
+    # Normalize the locale name and extract the encoding
+    if isinstance(localename, _unicode):
+        localename = localename.encode('ascii')
+    fullname = localename.translate(_ascii_lower_map)
+    if ':' in fullname:
+        # ':' is sometimes used as encoding delimiter.
+        fullname = fullname.replace(':', '.')
+    if '.' in fullname:
+        langname, encoding = fullname.split('.')[:2]
+        fullname = langname + '.' + encoding
+    else:
+        langname = fullname
+        encoding = ''
+
+    # First lookup: fullname (possibly with encoding)
+    norm_encoding = encoding.replace('-', '')
+    norm_encoding = norm_encoding.replace('_', '')
+    lookup_name = langname + '.' + encoding
+    code = locale_alias.get(lookup_name, None)
+    if code is not None:
+        return code
+    #print 'first lookup failed'
+
+    # Second try: langname (without encoding)
+    code = locale_alias.get(langname, None)
+    if code is not None:
+        #print 'langname lookup succeeded'
+        if '.' in code:
+            langname, defenc = code.split('.')
+        else:
+            langname = code
+            defenc = ''
+        if encoding:
+            # Convert the encoding to a C lib compatible encoding string
+            norm_encoding = encodings.normalize_encoding(encoding)
+            #print 'norm encoding: %r' % norm_encoding
+            norm_encoding = encodings.aliases.aliases.get(norm_encoding,
+                                                          norm_encoding)
+            #print 'aliased encoding: %r' % norm_encoding
+            encoding = locale_encoding_alias.get(norm_encoding,
+                                                 norm_encoding)
+        else:
+            encoding = defenc
+        #print 'found encoding %r' % encoding
+        if encoding:
+            return langname + '.' + encoding
+        else:
+            return langname
+
+    else:
+        return localename
+
+def _parse_localename(localename):
+
+    """ Parses the locale code for localename and returns the
+        result as tuple (language code, encoding).
+
+        The localename is normalized and passed through the locale
+        alias engine. A ValueError is raised in case the locale name
+        cannot be parsed.
+
+        The language code corresponds to RFC 1766.  code and encoding
+        can be None in case the values cannot be determined or are
+        unknown to this implementation.
+
+    """
+    code = normalize(localename)
+    if '@' in code:
+        # Deal with locale modifiers
+        code, modifier = code.split('@')
+        if modifier == 'euro' and '.' not in code:
+            # Assume Latin-9 for @euro locales. This is bogus,
+            # since some systems may use other encodings for these
+            # locales. Also, we ignore other modifiers.
+            return code, 'iso-8859-15'
+
+    if '.' in code:
+        return tuple(code.split('.')[:2])
+    elif code == 'C':
+        return None, None
+    raise ValueError, 'unknown locale: %s' % localename
+
+def _build_localename(localetuple):
+
+    """ Builds a locale code from the given tuple (language code,
+        encoding).
+
+        No aliasing or normalizing takes place.
+
+    """
+    language, encoding = localetuple
+    if language is None:
+        language = 'C'
+    if encoding is None:
+        return language
+    else:
+        return language + '.' + encoding
+
+def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')):
+
+    """ Tries to determine the default locale settings and returns
+        them as tuple (language code, encoding).
+
+        According to POSIX, a program which has not called
+        setlocale(LC_ALL, "") runs using the portable 'C' locale.
+        Calling setlocale(LC_ALL, "") lets it use the default locale as
+        defined by the LANG variable. Since we don't want to interfere
+        with the current locale setting we thus emulate the behavior
+        in the way described above.
+
+        To maintain compatibility with other platforms, not only the
+        LANG variable is tested, but a list of variables given as
+        envvars parameter. The first found to be defined will be
+        used. envvars defaults to the search path used in GNU gettext;
+        it must always contain the variable name 'LANG'.
+
+        Except for the code 'C', the language code corresponds to RFC
+        1766.  code and encoding can be None in case the values cannot
+        be determined.
+
+    """
+
+    try:
+        # check if it's supported by the _locale module
+        import _locale
+        code, encoding = _locale._getdefaultlocale()
+    except (ImportError, AttributeError):
+        pass
+    else:
+        # make sure the code/encoding values are valid
+        if sys.platform == "win32" and code and code[:2] == "0x":
+            # map windows language identifier to language name
+            code = windows_locale.get(int(code, 0))
+        # ...add other platform-specific processing here, if
+        # necessary...
+        return code, encoding
+
+    # fall back on POSIX behaviour
+    import os
+    lookup = os.environ.get
+    for variable in envvars:
+        localename = lookup(variable,None)
+        if localename:
+            if variable == 'LANGUAGE':
+                localename = localename.split(':')[0]
+            break
+    else:
+        localename = 'C'
+    return _parse_localename(localename)
+
+
+def getlocale(category=LC_CTYPE):
+
+    """ Returns the current setting for the given locale category as
+        tuple (language code, encoding).
+
+        category may be one of the LC_* value except LC_ALL. It
+        defaults to LC_CTYPE.
+
+        Except for the code 'C', the language code corresponds to RFC
+        1766.  code and encoding can be None in case the values cannot
+        be determined.
+
+    """
+    localename = _setlocale(category)
+    if category == LC_ALL and ';' in localename:
+        raise TypeError, 'category LC_ALL is not supported'
+    return _parse_localename(localename)
+
+def setlocale(category, locale=None):
+
+    """ Set the locale for the given category.  The locale can be
+        a string, an iterable of two strings (language code and encoding),
+        or None.
+
+        Iterables are converted to strings using the locale aliasing
+        engine.  Locale strings are passed directly to the C lib.
+
+        category may be given as one of the LC_* values.
+
+    """
+    if locale and type(locale) is not type(""):
+        # convert to string
+        locale = normalize(_build_localename(locale))
+    return _setlocale(category, locale)
+
+def resetlocale(category=LC_ALL):
+
+    """ Sets the locale for category to the default setting.
+
+        The default setting is determined by calling
+        getdefaultlocale(). category defaults to LC_ALL.
+
+    """
+    _setlocale(category, _build_localename(getdefaultlocale()))
+
+if sys.platform.startswith("win"):
+    # On Win32, this will return the ANSI code page
+    def getpreferredencoding(do_setlocale = True):
+        """Return the charset that the user is likely using."""
+        import _locale
+        return _locale._getdefaultlocale()[1]
+else:
+    # On Unix, if CODESET is available, use that.
+    try:
+        CODESET
+    except NameError:
+        # Fall back to parsing environment variables :-(
+        def getpreferredencoding(do_setlocale = True):
+            """Return the charset that the user is likely using,
+            by looking at environment variables."""
+            return getdefaultlocale()[1]
+    else:
+        def getpreferredencoding(do_setlocale = True):
+            """Return the charset that the user is likely using,
+            according to the system configuration."""
+            if do_setlocale:
+                oldloc = setlocale(LC_CTYPE)
+                try:
+                    setlocale(LC_CTYPE, "")
+                except Error:
+                    pass
+                result = nl_langinfo(CODESET)
+                setlocale(LC_CTYPE, oldloc)
+                return result
+            else:
+                return nl_langinfo(CODESET)
+
+
+### Database
+#
+# The following data was extracted from the locale.alias file which
+# comes with X11 and then hand edited removing the explicit encoding
+# definitions and adding some more aliases. The file is usually
+# available as /usr/lib/X11/locale/locale.alias.
+#
+
+#
+# The local_encoding_alias table maps lowercase encoding alias names
+# to C locale encoding names (case-sensitive). Note that normalize()
+# first looks up the encoding in the encodings.aliases dictionary and
+# then applies this mapping to find the correct C lib name for the
+# encoding.
+#
+locale_encoding_alias = {
+
+    # Mappings for non-standard encoding names used in locale names
+    '437':                          'C',
+    'c':                            'C',
+    'en':                           'ISO8859-1',
+    'jis':                          'JIS7',
+    'jis7':                         'JIS7',
+    'ajec':                         'eucJP',
+
+    # Mappings from Python codec names to C lib encoding names
+    'ascii':                        'ISO8859-1',
+    'latin_1':                      'ISO8859-1',
+    'iso8859_1':                    'ISO8859-1',
+    'iso8859_10':                   'ISO8859-10',
+    'iso8859_11':                   'ISO8859-11',
+    'iso8859_13':                   'ISO8859-13',
+    'iso8859_14':                   'ISO8859-14',
+    'iso8859_15':                   'ISO8859-15',
+    'iso8859_16':                   'ISO8859-16',
+    'iso8859_2':                    'ISO8859-2',
+    'iso8859_3':                    'ISO8859-3',
+    'iso8859_4':                    'ISO8859-4',
+    'iso8859_5':                    'ISO8859-5',
+    'iso8859_6':                    'ISO8859-6',
+    'iso8859_7':                    'ISO8859-7',
+    'iso8859_8':                    'ISO8859-8',
+    'iso8859_9':                    'ISO8859-9',
+    'iso2022_jp':                   'JIS7',
+    'shift_jis':                    'SJIS',
+    'tactis':                       'TACTIS',
+    'euc_jp':                       'eucJP',
+    'euc_kr':                       'eucKR',
+    'utf_8':                        'UTF-8',
+    'koi8_r':                       'KOI8-R',
+    'koi8_u':                       'KOI8-U',
+    # XXX This list is still incomplete. If you know more
+    # mappings, please file a bug report. Thanks.
+}
+
+#
+# The locale_alias table maps lowercase alias names to C locale names
+# (case-sensitive). Encodings are always separated from the locale
+# name using a dot ('.'); they should only be given in case the
+# language name is needed to interpret the given encoding alias
+# correctly (CJK codes often have this need).
+#
+# Note that the normalize() function which uses this tables
+# removes '_' and '-' characters from the encoding part of the
+# locale name before doing the lookup. This saves a lot of
+# space in the table.
+#
+# MAL 2004-12-10:
+# Updated alias mapping to most recent locale.alias file
+# from X.org distribution using makelocalealias.py.
+#
+# These are the differences compared to the old mapping (Python 2.4
+# and older):
+#
+#    updated 'bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251'
+#    updated 'bg_bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251'
+#    updated 'bulgarian' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251'
+#    updated 'cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2'
+#    updated 'cz_cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2'
+#    updated 'czech' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2'
+#    updated 'dutch' -> 'nl_BE.ISO8859-1' to 'nl_NL.ISO8859-1'
+#    updated 'et' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15'
+#    updated 'et_ee' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15'
+#    updated 'fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15'
+#    updated 'fi_fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15'
+#    updated 'iw' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8'
+#    updated 'iw_il' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8'
+#    updated 'japanese' -> 'ja_JP.SJIS' to 'ja_JP.eucJP'
+#    updated 'lt' -> 'lt_LT.ISO8859-4' to 'lt_LT.ISO8859-13'
+#    updated 'lv' -> 'lv_LV.ISO8859-4' to 'lv_LV.ISO8859-13'
+#    updated 'sl' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2'
+#    updated 'slovene' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2'
+#    updated 'th_th' -> 'th_TH.TACTIS' to 'th_TH.ISO8859-11'
+#    updated 'zh_cn' -> 'zh_CN.eucCN' to 'zh_CN.gb2312'
+#    updated 'zh_cn.big5' -> 'zh_TW.eucTW' to 'zh_TW.big5'
+#    updated 'zh_tw' -> 'zh_TW.eucTW' to 'zh_TW.big5'
+#
+# MAL 2008-05-30:
+# Updated alias mapping to most recent locale.alias file
+# from X.org distribution using makelocalealias.py.
+#
+# These are the differences compared to the old mapping (Python 2.5
+# and older):
+#
+#    updated 'cs_cs.iso88592' -> 'cs_CZ.ISO8859-2' to 'cs_CS.ISO8859-2'
+#    updated 'serbocroatian' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2'
+#    updated 'sh' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2'
+#    updated 'sh_hr.iso88592' -> 'sh_HR.ISO8859-2' to 'hr_HR.ISO8859-2'
+#    updated 'sh_sp' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2'
+#    updated 'sh_yu' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2'
+#    updated 'sp' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5'
+#    updated 'sp_yu' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5'
+#    updated 'sr' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'
+#    updated 'sr@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'
+#    updated 'sr_sp' -> 'sr_SP.ISO8859-2' to 'sr_CS.ISO8859-2'
+#    updated 'sr_yu' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'
+#    updated 'sr_yu.cp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251'
+#    updated 'sr_yu.iso88592' -> 'sr_YU.ISO8859-2' to 'sr_CS.ISO8859-2'
+#    updated 'sr_yu.iso88595' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'
+#    updated 'sr_yu.iso88595@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'
+#    updated 'sr_yu.microsoftcp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251'
+#    updated 'sr_yu.utf8@cyrillic' -> 'sr_YU.UTF-8' to 'sr_CS.UTF-8'
+#    updated 'sr_yu@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'
+#
+# AP 2010-04-12:
+# Updated alias mapping to most recent locale.alias file
+# from X.org distribution using makelocalealias.py.
+#
+# These are the differences compared to the old mapping (Python 2.6.5
+# and older):
+#
+#    updated 'ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8'
+#    updated 'ru_ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8'
+#    updated 'serbocroatian' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'
+#    updated 'sh' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'
+#    updated 'sh_yu' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'
+#    updated 'sr' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8'
+#    updated 'sr@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8'
+#    updated 'sr@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'
+#    updated 'sr_cs.utf8@latn' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8@latin'
+#    updated 'sr_cs@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'
+#    updated 'sr_yu' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8@latin'
+#    updated 'sr_yu.utf8@cyrillic' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8'
+#    updated 'sr_yu@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8'
+#
+
+locale_alias = {
+    'a3':                                   'a3_AZ.KOI8-C',
+    'a3_az':                                'a3_AZ.KOI8-C',
+    'a3_az.koi8c':                          'a3_AZ.KOI8-C',
+    'af':                                   'af_ZA.ISO8859-1',
+    'af_za':                                'af_ZA.ISO8859-1',
+    'af_za.iso88591':                       'af_ZA.ISO8859-1',
+    'am':                                   'am_ET.UTF-8',
+    'am_et':                                'am_ET.UTF-8',
+    'american':                             'en_US.ISO8859-1',
+    'american.iso88591':                    'en_US.ISO8859-1',
+    'ar':                                   'ar_AA.ISO8859-6',
+    'ar_aa':                                'ar_AA.ISO8859-6',
+    'ar_aa.iso88596':                       'ar_AA.ISO8859-6',
+    'ar_ae':                                'ar_AE.ISO8859-6',
+    'ar_ae.iso88596':                       'ar_AE.ISO8859-6',
+    'ar_bh':                                'ar_BH.ISO8859-6',
+    'ar_bh.iso88596':                       'ar_BH.ISO8859-6',
+    'ar_dz':                                'ar_DZ.ISO8859-6',
+    'ar_dz.iso88596':                       'ar_DZ.ISO8859-6',
+    'ar_eg':                                'ar_EG.ISO8859-6',
+    'ar_eg.iso88596':                       'ar_EG.ISO8859-6',
+    'ar_iq':                                'ar_IQ.ISO8859-6',
+    'ar_iq.iso88596':                       'ar_IQ.ISO8859-6',
+    'ar_jo':                                'ar_JO.ISO8859-6',
+    'ar_jo.iso88596':                       'ar_JO.ISO8859-6',
+    'ar_kw':                                'ar_KW.ISO8859-6',
+    'ar_kw.iso88596':                       'ar_KW.ISO8859-6',
+    'ar_lb':                                'ar_LB.ISO8859-6',
+    'ar_lb.iso88596':                       'ar_LB.ISO8859-6',
+    'ar_ly':                                'ar_LY.ISO8859-6',
+    'ar_ly.iso88596':                       'ar_LY.ISO8859-6',
+    'ar_ma':                                'ar_MA.ISO8859-6',
+    'ar_ma.iso88596':                       'ar_MA.ISO8859-6',
+    'ar_om':                                'ar_OM.ISO8859-6',
+    'ar_om.iso88596':                       'ar_OM.ISO8859-6',
+    'ar_qa':                                'ar_QA.ISO8859-6',
+    'ar_qa.iso88596':                       'ar_QA.ISO8859-6',
+    'ar_sa':                                'ar_SA.ISO8859-6',
+    'ar_sa.iso88596':                       'ar_SA.ISO8859-6',
+    'ar_sd':                                'ar_SD.ISO8859-6',
+    'ar_sd.iso88596':                       'ar_SD.ISO8859-6',
+    'ar_sy':                                'ar_SY.ISO8859-6',
+    'ar_sy.iso88596':                       'ar_SY.ISO8859-6',
+    'ar_tn':                                'ar_TN.ISO8859-6',
+    'ar_tn.iso88596':                       'ar_TN.ISO8859-6',
+    'ar_ye':                                'ar_YE.ISO8859-6',
+    'ar_ye.iso88596':                       'ar_YE.ISO8859-6',
+    'arabic':                               'ar_AA.ISO8859-6',
+    'arabic.iso88596':                      'ar_AA.ISO8859-6',
+    'as':                                   'as_IN.UTF-8',
+    'az':                                   'az_AZ.ISO8859-9E',
+    'az_az':                                'az_AZ.ISO8859-9E',
+    'az_az.iso88599e':                      'az_AZ.ISO8859-9E',
+    'be':                                   'be_BY.CP1251',
+    'be@latin':                             'be_BY.UTF-8@latin',
+    'be_by':                                'be_BY.CP1251',
+    'be_by.cp1251':                         'be_BY.CP1251',
+    'be_by.microsoftcp1251':                'be_BY.CP1251',
+    'be_by.utf8@latin':                     'be_BY.UTF-8@latin',
+    'be_by@latin':                          'be_BY.UTF-8@latin',
+    'bg':                                   'bg_BG.CP1251',
+    'bg_bg':                                'bg_BG.CP1251',
+    'bg_bg.cp1251':                         'bg_BG.CP1251',
+    'bg_bg.iso88595':                       'bg_BG.ISO8859-5',
+    'bg_bg.koi8r':                          'bg_BG.KOI8-R',
+    'bg_bg.microsoftcp1251':                'bg_BG.CP1251',
+    'bn_in':                                'bn_IN.UTF-8',
+    'bokmal':                               'nb_NO.ISO8859-1',
+    'bokm\xe5l':                            'nb_NO.ISO8859-1',
+    'br':                                   'br_FR.ISO8859-1',
+    'br_fr':                                'br_FR.ISO8859-1',
+    'br_fr.iso88591':                       'br_FR.ISO8859-1',
+    'br_fr.iso885914':                      'br_FR.ISO8859-14',
+    'br_fr.iso885915':                      'br_FR.ISO8859-15',
+    'br_fr.iso885915@euro':                 'br_FR.ISO8859-15',
+    'br_fr.utf8@euro':                      'br_FR.UTF-8',
+    'br_fr@euro':                           'br_FR.ISO8859-15',
+    'bs':                                   'bs_BA.ISO8859-2',
+    'bs_ba':                                'bs_BA.ISO8859-2',
+    'bs_ba.iso88592':                       'bs_BA.ISO8859-2',
+    'bulgarian':                            'bg_BG.CP1251',
+    'c':                                    'C',
+    'c-french':                             'fr_CA.ISO8859-1',
+    'c-french.iso88591':                    'fr_CA.ISO8859-1',
+    'c.en':                                 'C',
+    'c.iso88591':                           'en_US.ISO8859-1',
+    'c_c':                                  'C',
+    'c_c.c':                                'C',
+    'ca':                                   'ca_ES.ISO8859-1',
+    'ca_ad':                                'ca_AD.ISO8859-1',
+    'ca_ad.iso88591':                       'ca_AD.ISO8859-1',
+    'ca_ad.iso885915':                      'ca_AD.ISO8859-15',
+    'ca_ad.iso885915@euro':                 'ca_AD.ISO8859-15',
+    'ca_ad.utf8@euro':                      'ca_AD.UTF-8',
+    'ca_ad@euro':                           'ca_AD.ISO8859-15',
+    'ca_es':                                'ca_ES.ISO8859-1',
+    'ca_es.iso88591':                       'ca_ES.ISO8859-1',
+    'ca_es.iso885915':                      'ca_ES.ISO8859-15',
+    'ca_es.iso885915@euro':                 'ca_ES.ISO8859-15',
+    'ca_es.utf8@euro':                      'ca_ES.UTF-8',
+    'ca_es@euro':                           'ca_ES.ISO8859-15',
+    'ca_fr':                                'ca_FR.ISO8859-1',
+    'ca_fr.iso88591':                       'ca_FR.ISO8859-1',
+    'ca_fr.iso885915':                      'ca_FR.ISO8859-15',
+    'ca_fr.iso885915@euro':                 'ca_FR.ISO8859-15',
+    'ca_fr.utf8@euro':                      'ca_FR.UTF-8',
+    'ca_fr@euro':                           'ca_FR.ISO8859-15',
+    'ca_it':                                'ca_IT.ISO8859-1',
+    'ca_it.iso88591':                       'ca_IT.ISO8859-1',
+    'ca_it.iso885915':                      'ca_IT.ISO8859-15',
+    'ca_it.iso885915@euro':                 'ca_IT.ISO8859-15',
+    'ca_it.utf8@euro':                      'ca_IT.UTF-8',
+    'ca_it@euro':                           'ca_IT.ISO8859-15',
+    'catalan':                              'ca_ES.ISO8859-1',
+    'cextend':                              'en_US.ISO8859-1',
+    'cextend.en':                           'en_US.ISO8859-1',
+    'chinese-s':                            'zh_CN.eucCN',
+    'chinese-t':                            'zh_TW.eucTW',
+    'croatian':                             'hr_HR.ISO8859-2',
+    'cs':                                   'cs_CZ.ISO8859-2',
+    'cs_cs':                                'cs_CZ.ISO8859-2',
+    'cs_cs.iso88592':                       'cs_CS.ISO8859-2',
+    'cs_cz':                                'cs_CZ.ISO8859-2',
+    'cs_cz.iso88592':                       'cs_CZ.ISO8859-2',
+    'cy':                                   'cy_GB.ISO8859-1',
+    'cy_gb':                                'cy_GB.ISO8859-1',
+    'cy_gb.iso88591':                       'cy_GB.ISO8859-1',
+    'cy_gb.iso885914':                      'cy_GB.ISO8859-14',
+    'cy_gb.iso885915':                      'cy_GB.ISO8859-15',
+    'cy_gb@euro':                           'cy_GB.ISO8859-15',
+    'cz':                                   'cs_CZ.ISO8859-2',
+    'cz_cz':                                'cs_CZ.ISO8859-2',
+    'czech':                                'cs_CZ.ISO8859-2',
+    'da':                                   'da_DK.ISO8859-1',
+    'da.iso885915':                         'da_DK.ISO8859-15',
+    'da_dk':                                'da_DK.ISO8859-1',
+    'da_dk.88591':                          'da_DK.ISO8859-1',
+    'da_dk.885915':                         'da_DK.ISO8859-15',
+    'da_dk.iso88591':                       'da_DK.ISO8859-1',
+    'da_dk.iso885915':                      'da_DK.ISO8859-15',
+    'da_dk@euro':                           'da_DK.ISO8859-15',
+    'danish':                               'da_DK.ISO8859-1',
+    'danish.iso88591':                      'da_DK.ISO8859-1',
+    'dansk':                                'da_DK.ISO8859-1',
+    'de':                                   'de_DE.ISO8859-1',
+    'de.iso885915':                         'de_DE.ISO8859-15',
+    'de_at':                                'de_AT.ISO8859-1',
+    'de_at.iso88591':                       'de_AT.ISO8859-1',
+    'de_at.iso885915':                      'de_AT.ISO8859-15',
+    'de_at.iso885915@euro':                 'de_AT.ISO8859-15',
+    'de_at.utf8@euro':                      'de_AT.UTF-8',
+    'de_at@euro':                           'de_AT.ISO8859-15',
+    'de_be':                                'de_BE.ISO8859-1',
+    'de_be.iso88591':                       'de_BE.ISO8859-1',
+    'de_be.iso885915':                      'de_BE.ISO8859-15',
+    'de_be.iso885915@euro':                 'de_BE.ISO8859-15',
+    'de_be.utf8@euro':                      'de_BE.UTF-8',
+    'de_be@euro':                           'de_BE.ISO8859-15',
+    'de_ch':                                'de_CH.ISO8859-1',
+    'de_ch.iso88591':                       'de_CH.ISO8859-1',
+    'de_ch.iso885915':                      'de_CH.ISO8859-15',
+    'de_ch@euro':                           'de_CH.ISO8859-15',
+    'de_de':                                'de_DE.ISO8859-1',
+    'de_de.88591':                          'de_DE.ISO8859-1',
+    'de_de.885915':                         'de_DE.ISO8859-15',
+    'de_de.885915@euro':                    'de_DE.ISO8859-15',
+    'de_de.iso88591':                       'de_DE.ISO8859-1',
+    'de_de.iso885915':                      'de_DE.ISO8859-15',
+    'de_de.iso885915@euro':                 'de_DE.ISO8859-15',
+    'de_de.utf8@euro':                      'de_DE.UTF-8',
+    'de_de@euro':                           'de_DE.ISO8859-15',
+    'de_lu':                                'de_LU.ISO8859-1',
+    'de_lu.iso88591':                       'de_LU.ISO8859-1',
+    'de_lu.iso885915':                      'de_LU.ISO8859-15',
+    'de_lu.iso885915@euro':                 'de_LU.ISO8859-15',
+    'de_lu.utf8@euro':                      'de_LU.UTF-8',
+    'de_lu@euro':                           'de_LU.ISO8859-15',
+    'deutsch':                              'de_DE.ISO8859-1',
+    'dutch':                                'nl_NL.ISO8859-1',
+    'dutch.iso88591':                       'nl_BE.ISO8859-1',
+    'ee':                                   'ee_EE.ISO8859-4',
+    'ee_ee':                                'ee_EE.ISO8859-4',
+    'ee_ee.iso88594':                       'ee_EE.ISO8859-4',
+    'eesti':                                'et_EE.ISO8859-1',
+    'el':                                   'el_GR.ISO8859-7',
+    'el_gr':                                'el_GR.ISO8859-7',
+    'el_gr.iso88597':                       'el_GR.ISO8859-7',
+    'el_gr@euro':                           'el_GR.ISO8859-15',
+    'en':                                   'en_US.ISO8859-1',
+    'en.iso88591':                          'en_US.ISO8859-1',
+    'en_au':                                'en_AU.ISO8859-1',
+    'en_au.iso88591':                       'en_AU.ISO8859-1',
+    'en_be':                                'en_BE.ISO8859-1',
+    'en_be@euro':                           'en_BE.ISO8859-15',
+    'en_bw':                                'en_BW.ISO8859-1',
+    'en_bw.iso88591':                       'en_BW.ISO8859-1',
+    'en_ca':                                'en_CA.ISO8859-1',
+    'en_ca.iso88591':                       'en_CA.ISO8859-1',
+    'en_gb':                                'en_GB.ISO8859-1',
+    'en_gb.88591':                          'en_GB.ISO8859-1',
+    'en_gb.iso88591':                       'en_GB.ISO8859-1',
+    'en_gb.iso885915':                      'en_GB.ISO8859-15',
+    'en_gb@euro':                           'en_GB.ISO8859-15',
+    'en_hk':                                'en_HK.ISO8859-1',
+    'en_hk.iso88591':                       'en_HK.ISO8859-1',
+    'en_ie':                                'en_IE.ISO8859-1',
+    'en_ie.iso88591':                       'en_IE.ISO8859-1',
+    'en_ie.iso885915':                      'en_IE.ISO8859-15',
+    'en_ie.iso885915@euro':                 'en_IE.ISO8859-15',
+    'en_ie.utf8@euro':                      'en_IE.UTF-8',
+    'en_ie@euro':                           'en_IE.ISO8859-15',
+    'en_in':                                'en_IN.ISO8859-1',
+    'en_nz':                                'en_NZ.ISO8859-1',
+    'en_nz.iso88591':                       'en_NZ.ISO8859-1',
+    'en_ph':                                'en_PH.ISO8859-1',
+    'en_ph.iso88591':                       'en_PH.ISO8859-1',
+    'en_sg':                                'en_SG.ISO8859-1',
+    'en_sg.iso88591':                       'en_SG.ISO8859-1',
+    'en_uk':                                'en_GB.ISO8859-1',
+    'en_us':                                'en_US.ISO8859-1',
+    'en_us.88591':                          'en_US.ISO8859-1',
+    'en_us.885915':                         'en_US.ISO8859-15',
+    'en_us.iso88591':                       'en_US.ISO8859-1',
+    'en_us.iso885915':                      'en_US.ISO8859-15',
+    'en_us.iso885915@euro':                 'en_US.ISO8859-15',
+    'en_us@euro':                           'en_US.ISO8859-15',
+    'en_us@euro@euro':                      'en_US.ISO8859-15',
+    'en_za':                                'en_ZA.ISO8859-1',
+    'en_za.88591':                          'en_ZA.ISO8859-1',
+    'en_za.iso88591':                       'en_ZA.ISO8859-1',
+    'en_za.iso885915':                      'en_ZA.ISO8859-15',
+    'en_za@euro':                           'en_ZA.ISO8859-15',
+    'en_zw':                                'en_ZW.ISO8859-1',
+    'en_zw.iso88591':                       'en_ZW.ISO8859-1',
+    'eng_gb':                               'en_GB.ISO8859-1',
+    'eng_gb.8859':                          'en_GB.ISO8859-1',
+    'english':                              'en_EN.ISO8859-1',
+    'english.iso88591':                     'en_EN.ISO8859-1',
+    'english_uk':                           'en_GB.ISO8859-1',
+    'english_uk.8859':                      'en_GB.ISO8859-1',
+    'english_united-states':                'en_US.ISO8859-1',
+    'english_united-states.437':            'C',
+    'english_us':                           'en_US.ISO8859-1',
+    'english_us.8859':                      'en_US.ISO8859-1',
+    'english_us.ascii':                     'en_US.ISO8859-1',
+    'eo':                                   'eo_XX.ISO8859-3',
+    'eo_eo':                                'eo_EO.ISO8859-3',
+    'eo_eo.iso88593':                       'eo_EO.ISO8859-3',
+    'eo_xx':                                'eo_XX.ISO8859-3',
+    'eo_xx.iso88593':                       'eo_XX.ISO8859-3',
+    'es':                                   'es_ES.ISO8859-1',
+    'es_ar':                                'es_AR.ISO8859-1',
+    'es_ar.iso88591':                       'es_AR.ISO8859-1',
+    'es_bo':                                'es_BO.ISO8859-1',
+    'es_bo.iso88591':                       'es_BO.ISO8859-1',
+    'es_cl':                                'es_CL.ISO8859-1',
+    'es_cl.iso88591':                       'es_CL.ISO8859-1',
+    'es_co':                                'es_CO.ISO8859-1',
+    'es_co.iso88591':                       'es_CO.ISO8859-1',
+    'es_cr':                                'es_CR.ISO8859-1',
+    'es_cr.iso88591':                       'es_CR.ISO8859-1',
+    'es_do':                                'es_DO.ISO8859-1',
+    'es_do.iso88591':                       'es_DO.ISO8859-1',
+    'es_ec':                                'es_EC.ISO8859-1',
+    'es_ec.iso88591':                       'es_EC.ISO8859-1',
+    'es_es':                                'es_ES.ISO8859-1',
+    'es_es.88591':                          'es_ES.ISO8859-1',
+    'es_es.iso88591':                       'es_ES.ISO8859-1',
+    'es_es.iso885915':                      'es_ES.ISO8859-15',
+    'es_es.iso885915@euro':                 'es_ES.ISO8859-15',
+    'es_es.utf8@euro':                      'es_ES.UTF-8',
+    'es_es@euro':                           'es_ES.ISO8859-15',
+    'es_gt':                                'es_GT.ISO8859-1',
+    'es_gt.iso88591':                       'es_GT.ISO8859-1',
+    'es_hn':                                'es_HN.ISO8859-1',
+    'es_hn.iso88591':                       'es_HN.ISO8859-1',
+    'es_mx':                                'es_MX.ISO8859-1',
+    'es_mx.iso88591':                       'es_MX.ISO8859-1',
+    'es_ni':                                'es_NI.ISO8859-1',
+    'es_ni.iso88591':                       'es_NI.ISO8859-1',
+    'es_pa':                                'es_PA.ISO8859-1',
+    'es_pa.iso88591':                       'es_PA.ISO8859-1',
+    'es_pa.iso885915':                      'es_PA.ISO8859-15',
+    'es_pa@euro':                           'es_PA.ISO8859-15',
+    'es_pe':                                'es_PE.ISO8859-1',
+    'es_pe.iso88591':                       'es_PE.ISO8859-1',
+    'es_pe.iso885915':                      'es_PE.ISO8859-15',
+    'es_pe@euro':                           'es_PE.ISO8859-15',
+    'es_pr':                                'es_PR.ISO8859-1',
+    'es_pr.iso88591':                       'es_PR.ISO8859-1',
+    'es_py':                                'es_PY.ISO8859-1',
+    'es_py.iso88591':                       'es_PY.ISO8859-1',
+    'es_py.iso885915':                      'es_PY.ISO8859-15',
+    'es_py@euro':                           'es_PY.ISO8859-15',
+    'es_sv':                                'es_SV.ISO8859-1',
+    'es_sv.iso88591':                       'es_SV.ISO8859-1',
+    'es_sv.iso885915':                      'es_SV.ISO8859-15',
+    'es_sv@euro':                           'es_SV.ISO8859-15',
+    'es_us':                                'es_US.ISO8859-1',
+    'es_us.iso88591':                       'es_US.ISO8859-1',
+    'es_uy':                                'es_UY.ISO8859-1',
+    'es_uy.iso88591':                       'es_UY.ISO8859-1',
+    'es_uy.iso885915':                      'es_UY.ISO8859-15',
+    'es_uy@euro':                           'es_UY.ISO8859-15',
+    'es_ve':                                'es_VE.ISO8859-1',
+    'es_ve.iso88591':                       'es_VE.ISO8859-1',
+    'es_ve.iso885915':                      'es_VE.ISO8859-15',
+    'es_ve@euro':                           'es_VE.ISO8859-15',
+    'estonian':                             'et_EE.ISO8859-1',
+    'et':                                   'et_EE.ISO8859-15',
+    'et_ee':                                'et_EE.ISO8859-15',
+    'et_ee.iso88591':                       'et_EE.ISO8859-1',
+    'et_ee.iso885913':                      'et_EE.ISO8859-13',
+    'et_ee.iso885915':                      'et_EE.ISO8859-15',
+    'et_ee.iso88594':                       'et_EE.ISO8859-4',
+    'et_ee@euro':                           'et_EE.ISO8859-15',
+    'eu':                                   'eu_ES.ISO8859-1',
+    'eu_es':                                'eu_ES.ISO8859-1',
+    'eu_es.iso88591':                       'eu_ES.ISO8859-1',
+    'eu_es.iso885915':                      'eu_ES.ISO8859-15',
+    'eu_es.iso885915@euro':                 'eu_ES.ISO8859-15',
+    'eu_es.utf8@euro':                      'eu_ES.UTF-8',
+    'eu_es@euro':                           'eu_ES.ISO8859-15',
+    'fa':                                   'fa_IR.UTF-8',
+    'fa_ir':                                'fa_IR.UTF-8',
+    'fa_ir.isiri3342':                      'fa_IR.ISIRI-3342',
+    'fi':                                   'fi_FI.ISO8859-15',
+    'fi.iso885915':                         'fi_FI.ISO8859-15',
+    'fi_fi':                                'fi_FI.ISO8859-15',
+    'fi_fi.88591':                          'fi_FI.ISO8859-1',
+    'fi_fi.iso88591':                       'fi_FI.ISO8859-1',
+    'fi_fi.iso885915':                      'fi_FI.ISO8859-15',
+    'fi_fi.iso885915@euro':                 'fi_FI.ISO8859-15',
+    'fi_fi.utf8@euro':                      'fi_FI.UTF-8',
+    'fi_fi@euro':                           'fi_FI.ISO8859-15',
+    'finnish':                              'fi_FI.ISO8859-1',
+    'finnish.iso88591':                     'fi_FI.ISO8859-1',
+    'fo':                                   'fo_FO.ISO8859-1',
+    'fo_fo':                                'fo_FO.ISO8859-1',
+    'fo_fo.iso88591':                       'fo_FO.ISO8859-1',
+    'fo_fo.iso885915':                      'fo_FO.ISO8859-15',
+    'fo_fo@euro':                           'fo_FO.ISO8859-15',
+    'fr':                                   'fr_FR.ISO8859-1',
+    'fr.iso885915':                         'fr_FR.ISO8859-15',
+    'fr_be':                                'fr_BE.ISO8859-1',
+    'fr_be.88591':                          'fr_BE.ISO8859-1',
+    'fr_be.iso88591':                       'fr_BE.ISO8859-1',
+    'fr_be.iso885915':                      'fr_BE.ISO8859-15',
+    'fr_be.iso885915@euro':                 'fr_BE.ISO8859-15',
+    'fr_be.utf8@euro':                      'fr_BE.UTF-8',
+    'fr_be@euro':                           'fr_BE.ISO8859-15',
+    'fr_ca':                                'fr_CA.ISO8859-1',
+    'fr_ca.88591':                          'fr_CA.ISO8859-1',
+    'fr_ca.iso88591':                       'fr_CA.ISO8859-1',
+    'fr_ca.iso885915':                      'fr_CA.ISO8859-15',
+    'fr_ca@euro':                           'fr_CA.ISO8859-15',
+    'fr_ch':                                'fr_CH.ISO8859-1',
+    'fr_ch.88591':                          'fr_CH.ISO8859-1',
+    'fr_ch.iso88591':                       'fr_CH.ISO8859-1',
+    'fr_ch.iso885915':                      'fr_CH.ISO8859-15',
+    'fr_ch@euro':                           'fr_CH.ISO8859-15',
+    'fr_fr':                                'fr_FR.ISO8859-1',
+    'fr_fr.88591':                          'fr_FR.ISO8859-1',
+    'fr_fr.iso88591':                       'fr_FR.ISO8859-1',
+    'fr_fr.iso885915':                      'fr_FR.ISO8859-15',
+    'fr_fr.iso885915@euro':                 'fr_FR.ISO8859-15',
+    'fr_fr.utf8@euro':                      'fr_FR.UTF-8',
+    'fr_fr@euro':                           'fr_FR.ISO8859-15',
+    'fr_lu':                                'fr_LU.ISO8859-1',
+    'fr_lu.88591':                          'fr_LU.ISO8859-1',
+    'fr_lu.iso88591':                       'fr_LU.ISO8859-1',
+    'fr_lu.iso885915':                      'fr_LU.ISO8859-15',
+    'fr_lu.iso885915@euro':                 'fr_LU.ISO8859-15',
+    'fr_lu.utf8@euro':                      'fr_LU.UTF-8',
+    'fr_lu@euro':                           'fr_LU.ISO8859-15',
+    'fran\xe7ais':                          'fr_FR.ISO8859-1',
+    'fre_fr':                               'fr_FR.ISO8859-1',
+    'fre_fr.8859':                          'fr_FR.ISO8859-1',
+    'french':                               'fr_FR.ISO8859-1',
+    'french.iso88591':                      'fr_CH.ISO8859-1',
+    'french_france':                        'fr_FR.ISO8859-1',
+    'french_france.8859':                   'fr_FR.ISO8859-1',
+    'ga':                                   'ga_IE.ISO8859-1',
+    'ga_ie':                                'ga_IE.ISO8859-1',
+    'ga_ie.iso88591':                       'ga_IE.ISO8859-1',
+    'ga_ie.iso885914':                      'ga_IE.ISO8859-14',
+    'ga_ie.iso885915':                      'ga_IE.ISO8859-15',
+    'ga_ie.iso885915@euro':                 'ga_IE.ISO8859-15',
+    'ga_ie.utf8@euro':                      'ga_IE.UTF-8',
+    'ga_ie@euro':                           'ga_IE.ISO8859-15',
+    'galego':                               'gl_ES.ISO8859-1',
+    'galician':                             'gl_ES.ISO8859-1',
+    'gd':                                   'gd_GB.ISO8859-1',
+    'gd_gb':                                'gd_GB.ISO8859-1',
+    'gd_gb.iso88591':                       'gd_GB.ISO8859-1',
+    'gd_gb.iso885914':                      'gd_GB.ISO8859-14',
+    'gd_gb.iso885915':                      'gd_GB.ISO8859-15',
+    'gd_gb@euro':                           'gd_GB.ISO8859-15',
+    'ger_de':                               'de_DE.ISO8859-1',
+    'ger_de.8859':                          'de_DE.ISO8859-1',
+    'german':                               'de_DE.ISO8859-1',
+    'german.iso88591':                      'de_CH.ISO8859-1',
+    'german_germany':                       'de_DE.ISO8859-1',
+    'german_germany.8859':                  'de_DE.ISO8859-1',
+    'gl':                                   'gl_ES.ISO8859-1',
+    'gl_es':                                'gl_ES.ISO8859-1',
+    'gl_es.iso88591':                       'gl_ES.ISO8859-1',
+    'gl_es.iso885915':                      'gl_ES.ISO8859-15',
+    'gl_es.iso885915@euro':                 'gl_ES.ISO8859-15',
+    'gl_es.utf8@euro':                      'gl_ES.UTF-8',
+    'gl_es@euro':                           'gl_ES.ISO8859-15',
+    'greek':                                'el_GR.ISO8859-7',
+    'greek.iso88597':                       'el_GR.ISO8859-7',
+    'gu_in':                                'gu_IN.UTF-8',
+    'gv':                                   'gv_GB.ISO8859-1',
+    'gv_gb':                                'gv_GB.ISO8859-1',
+    'gv_gb.iso88591':                       'gv_GB.ISO8859-1',
+    'gv_gb.iso885914':                      'gv_GB.ISO8859-14',
+    'gv_gb.iso885915':                      'gv_GB.ISO8859-15',
+    'gv_gb@euro':                           'gv_GB.ISO8859-15',
+    'he':                                   'he_IL.ISO8859-8',
+    'he_il':                                'he_IL.ISO8859-8',
+    'he_il.cp1255':                         'he_IL.CP1255',
+    'he_il.iso88598':                       'he_IL.ISO8859-8',
+    'he_il.microsoftcp1255':                'he_IL.CP1255',
+    'hebrew':                               'iw_IL.ISO8859-8',
+    'hebrew.iso88598':                      'iw_IL.ISO8859-8',
+    'hi':                                   'hi_IN.ISCII-DEV',
+    'hi_in':                                'hi_IN.ISCII-DEV',
+    'hi_in.isciidev':                       'hi_IN.ISCII-DEV',
+    'hne':                                  'hne_IN.UTF-8',
+    'hr':                                   'hr_HR.ISO8859-2',
+    'hr_hr':                                'hr_HR.ISO8859-2',
+    'hr_hr.iso88592':                       'hr_HR.ISO8859-2',
+    'hrvatski':                             'hr_HR.ISO8859-2',
+    'hu':                                   'hu_HU.ISO8859-2',
+    'hu_hu':                                'hu_HU.ISO8859-2',
+    'hu_hu.iso88592':                       'hu_HU.ISO8859-2',
+    'hungarian':                            'hu_HU.ISO8859-2',
+    'icelandic':                            'is_IS.ISO8859-1',
+    'icelandic.iso88591':                   'is_IS.ISO8859-1',
+    'id':                                   'id_ID.ISO8859-1',
+    'id_id':                                'id_ID.ISO8859-1',
+    'in':                                   'id_ID.ISO8859-1',
+    'in_id':                                'id_ID.ISO8859-1',
+    'is':                                   'is_IS.ISO8859-1',
+    'is_is':                                'is_IS.ISO8859-1',
+    'is_is.iso88591':                       'is_IS.ISO8859-1',
+    'is_is.iso885915':                      'is_IS.ISO8859-15',
+    'is_is@euro':                           'is_IS.ISO8859-15',
+    'iso-8859-1':                           'en_US.ISO8859-1',
+    'iso-8859-15':                          'en_US.ISO8859-15',
+    'iso8859-1':                            'en_US.ISO8859-1',
+    'iso8859-15':                           'en_US.ISO8859-15',
+    'iso_8859_1':                           'en_US.ISO8859-1',
+    'iso_8859_15':                          'en_US.ISO8859-15',
+    'it':                                   'it_IT.ISO8859-1',
+    'it.iso885915':                         'it_IT.ISO8859-15',
+    'it_ch':                                'it_CH.ISO8859-1',
+    'it_ch.iso88591':                       'it_CH.ISO8859-1',
+    'it_ch.iso885915':                      'it_CH.ISO8859-15',
+    'it_ch@euro':                           'it_CH.ISO8859-15',
+    'it_it':                                'it_IT.ISO8859-1',
+    'it_it.88591':                          'it_IT.ISO8859-1',
+    'it_it.iso88591':                       'it_IT.ISO8859-1',
+    'it_it.iso885915':                      'it_IT.ISO8859-15',
+    'it_it.iso885915@euro':                 'it_IT.ISO8859-15',
+    'it_it.utf8@euro':                      'it_IT.UTF-8',
+    'it_it@euro':                           'it_IT.ISO8859-15',
+    'italian':                              'it_IT.ISO8859-1',
+    'italian.iso88591':                     'it_IT.ISO8859-1',
+    'iu':                                   'iu_CA.NUNACOM-8',
+    'iu_ca':                                'iu_CA.NUNACOM-8',
+    'iu_ca.nunacom8':                       'iu_CA.NUNACOM-8',
+    'iw':                                   'he_IL.ISO8859-8',
+    'iw_il':                                'he_IL.ISO8859-8',
+    'iw_il.iso88598':                       'he_IL.ISO8859-8',
+    'ja':                                   'ja_JP.eucJP',
+    'ja.jis':                               'ja_JP.JIS7',
+    'ja.sjis':                              'ja_JP.SJIS',
+    'ja_jp':                                'ja_JP.eucJP',
+    'ja_jp.ajec':                           'ja_JP.eucJP',
+    'ja_jp.euc':                            'ja_JP.eucJP',
+    'ja_jp.eucjp':                          'ja_JP.eucJP',
+    'ja_jp.iso-2022-jp':                    'ja_JP.JIS7',
+    'ja_jp.iso2022jp':                      'ja_JP.JIS7',
+    'ja_jp.jis':                            'ja_JP.JIS7',
+    'ja_jp.jis7':                           'ja_JP.JIS7',
+    'ja_jp.mscode':                         'ja_JP.SJIS',
+    'ja_jp.pck':                            'ja_JP.SJIS',
+    'ja_jp.sjis':                           'ja_JP.SJIS',
+    'ja_jp.ujis':                           'ja_JP.eucJP',
+    'japan':                                'ja_JP.eucJP',
+    'japanese':                             'ja_JP.eucJP',
+    'japanese-euc':                         'ja_JP.eucJP',
+    'japanese.euc':                         'ja_JP.eucJP',
+    'japanese.sjis':                        'ja_JP.SJIS',
+    'jp_jp':                                'ja_JP.eucJP',
+    'ka':                                   'ka_GE.GEORGIAN-ACADEMY',
+    'ka_ge':                                'ka_GE.GEORGIAN-ACADEMY',
+    'ka_ge.georgianacademy':                'ka_GE.GEORGIAN-ACADEMY',
+    'ka_ge.georgianps':                     'ka_GE.GEORGIAN-PS',
+    'ka_ge.georgianrs':                     'ka_GE.GEORGIAN-ACADEMY',
+    'kl':                                   'kl_GL.ISO8859-1',
+    'kl_gl':                                'kl_GL.ISO8859-1',
+    'kl_gl.iso88591':                       'kl_GL.ISO8859-1',
+    'kl_gl.iso885915':                      'kl_GL.ISO8859-15',
+    'kl_gl@euro':                           'kl_GL.ISO8859-15',
+    'km_kh':                                'km_KH.UTF-8',
+    'kn':                                   'kn_IN.UTF-8',
+    'kn_in':                                'kn_IN.UTF-8',
+    'ko':                                   'ko_KR.eucKR',
+    'ko_kr':                                'ko_KR.eucKR',
+    'ko_kr.euc':                            'ko_KR.eucKR',
+    'ko_kr.euckr':                          'ko_KR.eucKR',
+    'korean':                               'ko_KR.eucKR',
+    'korean.euc':                           'ko_KR.eucKR',
+    'ks':                                   'ks_IN.UTF-8',
+    'ks_in@devanagari':                     'ks_IN@devanagari.UTF-8',
+    'kw':                                   'kw_GB.ISO8859-1',
+    'kw_gb':                                'kw_GB.ISO8859-1',
+    'kw_gb.iso88591':                       'kw_GB.ISO8859-1',
+    'kw_gb.iso885914':                      'kw_GB.ISO8859-14',
+    'kw_gb.iso885915':                      'kw_GB.ISO8859-15',
+    'kw_gb@euro':                           'kw_GB.ISO8859-15',
+    'ky':                                   'ky_KG.UTF-8',
+    'ky_kg':                                'ky_KG.UTF-8',
+    'lithuanian':                           'lt_LT.ISO8859-13',
+    'lo':                                   'lo_LA.MULELAO-1',
+    'lo_la':                                'lo_LA.MULELAO-1',
+    'lo_la.cp1133':                         'lo_LA.IBM-CP1133',
+    'lo_la.ibmcp1133':                      'lo_LA.IBM-CP1133',
+    'lo_la.mulelao1':                       'lo_LA.MULELAO-1',
+    'lt':                                   'lt_LT.ISO8859-13',
+    'lt_lt':                                'lt_LT.ISO8859-13',
+    'lt_lt.iso885913':                      'lt_LT.ISO8859-13',
+    'lt_lt.iso88594':                       'lt_LT.ISO8859-4',
+    'lv':                                   'lv_LV.ISO8859-13',
+    'lv_lv':                                'lv_LV.ISO8859-13',
+    'lv_lv.iso885913':                      'lv_LV.ISO8859-13',
+    'lv_lv.iso88594':                       'lv_LV.ISO8859-4',
+    'mai':                                  'mai_IN.UTF-8',
+    'mi':                                   'mi_NZ.ISO8859-1',
+    'mi_nz':                                'mi_NZ.ISO8859-1',
+    'mi_nz.iso88591':                       'mi_NZ.ISO8859-1',
+    'mk':                                   'mk_MK.ISO8859-5',
+    'mk_mk':                                'mk_MK.ISO8859-5',
+    'mk_mk.cp1251':                         'mk_MK.CP1251',
+    'mk_mk.iso88595':                       'mk_MK.ISO8859-5',
+    'mk_mk.microsoftcp1251':                'mk_MK.CP1251',
+    'ml':                                   'ml_IN.UTF-8',
+    'mr':                                   'mr_IN.UTF-8',
+    'mr_in':                                'mr_IN.UTF-8',
+    'ms':                                   'ms_MY.ISO8859-1',
+    'ms_my':                                'ms_MY.ISO8859-1',
+    'ms_my.iso88591':                       'ms_MY.ISO8859-1',
+    'mt':                                   'mt_MT.ISO8859-3',
+    'mt_mt':                                'mt_MT.ISO8859-3',
+    'mt_mt.iso88593':                       'mt_MT.ISO8859-3',
+    'nb':                                   'nb_NO.ISO8859-1',
+    'nb_no':                                'nb_NO.ISO8859-1',
+    'nb_no.88591':                          'nb_NO.ISO8859-1',
+    'nb_no.iso88591':                       'nb_NO.ISO8859-1',
+    'nb_no.iso885915':                      'nb_NO.ISO8859-15',
+    'nb_no@euro':                           'nb_NO.ISO8859-15',
+    'nl':                                   'nl_NL.ISO8859-1',
+    'nl.iso885915':                         'nl_NL.ISO8859-15',
+    'nl_be':                                'nl_BE.ISO8859-1',
+    'nl_be.88591':                          'nl_BE.ISO8859-1',
+    'nl_be.iso88591':                       'nl_BE.ISO8859-1',
+    'nl_be.iso885915':                      'nl_BE.ISO8859-15',
+    'nl_be.iso885915@euro':                 'nl_BE.ISO8859-15',
+    'nl_be.utf8@euro':                      'nl_BE.UTF-8',
+    'nl_be@euro':                           'nl_BE.ISO8859-15',
+    'nl_nl':                                'nl_NL.ISO8859-1',
+    'nl_nl.88591':                          'nl_NL.ISO8859-1',
+    'nl_nl.iso88591':                       'nl_NL.ISO8859-1',
+    'nl_nl.iso885915':                      'nl_NL.ISO8859-15',
+    'nl_nl.iso885915@euro':                 'nl_NL.ISO8859-15',
+    'nl_nl.utf8@euro':                      'nl_NL.UTF-8',
+    'nl_nl@euro':                           'nl_NL.ISO8859-15',
+    'nn':                                   'nn_NO.ISO8859-1',
+    'nn_no':                                'nn_NO.ISO8859-1',
+    'nn_no.88591':                          'nn_NO.ISO8859-1',
+    'nn_no.iso88591':                       'nn_NO.ISO8859-1',
+    'nn_no.iso885915':                      'nn_NO.ISO8859-15',
+    'nn_no@euro':                           'nn_NO.ISO8859-15',
+    'no':                                   'no_NO.ISO8859-1',
+    'no@nynorsk':                           'ny_NO.ISO8859-1',
+    'no_no':                                'no_NO.ISO8859-1',
+    'no_no.88591':                          'no_NO.ISO8859-1',
+    'no_no.iso88591':                       'no_NO.ISO8859-1',
+    'no_no.iso885915':                      'no_NO.ISO8859-15',
+    'no_no.iso88591@bokmal':                'no_NO.ISO8859-1',
+    'no_no.iso88591@nynorsk':               'no_NO.ISO8859-1',
+    'no_no@euro':                           'no_NO.ISO8859-15',
+    'norwegian':                            'no_NO.ISO8859-1',
+    'norwegian.iso88591':                   'no_NO.ISO8859-1',
+    'nr':                                   'nr_ZA.ISO8859-1',
+    'nr_za':                                'nr_ZA.ISO8859-1',
+    'nr_za.iso88591':                       'nr_ZA.ISO8859-1',
+    'nso':                                  'nso_ZA.ISO8859-15',
+    'nso_za':                               'nso_ZA.ISO8859-15',
+    'nso_za.iso885915':                     'nso_ZA.ISO8859-15',
+    'ny':                                   'ny_NO.ISO8859-1',
+    'ny_no':                                'ny_NO.ISO8859-1',
+    'ny_no.88591':                          'ny_NO.ISO8859-1',
+    'ny_no.iso88591':                       'ny_NO.ISO8859-1',
+    'ny_no.iso885915':                      'ny_NO.ISO8859-15',
+    'ny_no@euro':                           'ny_NO.ISO8859-15',
+    'nynorsk':                              'nn_NO.ISO8859-1',
+    'oc':                                   'oc_FR.ISO8859-1',
+    'oc_fr':                                'oc_FR.ISO8859-1',
+    'oc_fr.iso88591':                       'oc_FR.ISO8859-1',
+    'oc_fr.iso885915':                      'oc_FR.ISO8859-15',
+    'oc_fr@euro':                           'oc_FR.ISO8859-15',
+    'or':                                   'or_IN.UTF-8',
+    'pa':                                   'pa_IN.UTF-8',
+    'pa_in':                                'pa_IN.UTF-8',
+    'pd':                                   'pd_US.ISO8859-1',
+    'pd_de':                                'pd_DE.ISO8859-1',
+    'pd_de.iso88591':                       'pd_DE.ISO8859-1',
+    'pd_de.iso885915':                      'pd_DE.ISO8859-15',
+    'pd_de@euro':                           'pd_DE.ISO8859-15',
+    'pd_us':                                'pd_US.ISO8859-1',
+    'pd_us.iso88591':                       'pd_US.ISO8859-1',
+    'pd_us.iso885915':                      'pd_US.ISO8859-15',
+    'pd_us@euro':                           'pd_US.ISO8859-15',
+    'ph':                                   'ph_PH.ISO8859-1',
+    'ph_ph':                                'ph_PH.ISO8859-1',
+    'ph_ph.iso88591':                       'ph_PH.ISO8859-1',
+    'pl':                                   'pl_PL.ISO8859-2',
+    'pl_pl':                                'pl_PL.ISO8859-2',
+    'pl_pl.iso88592':                       'pl_PL.ISO8859-2',
+    'polish':                               'pl_PL.ISO8859-2',
+    'portuguese':                           'pt_PT.ISO8859-1',
+    'portuguese.iso88591':                  'pt_PT.ISO8859-1',
+    'portuguese_brazil':                    'pt_BR.ISO8859-1',
+    'portuguese_brazil.8859':               'pt_BR.ISO8859-1',
+    'posix':                                'C',
+    'posix-utf2':                           'C',
+    'pp':                                   'pp_AN.ISO8859-1',
+    'pp_an':                                'pp_AN.ISO8859-1',
+    'pp_an.iso88591':                       'pp_AN.ISO8859-1',
+    'pt':                                   'pt_PT.ISO8859-1',
+    'pt.iso885915':                         'pt_PT.ISO8859-15',
+    'pt_br':                                'pt_BR.ISO8859-1',
+    'pt_br.88591':                          'pt_BR.ISO8859-1',
+    'pt_br.iso88591':                       'pt_BR.ISO8859-1',
+    'pt_br.iso885915':                      'pt_BR.ISO8859-15',
+    'pt_br@euro':                           'pt_BR.ISO8859-15',
+    'pt_pt':                                'pt_PT.ISO8859-1',
+    'pt_pt.88591':                          'pt_PT.ISO8859-1',
+    'pt_pt.iso88591':                       'pt_PT.ISO8859-1',
+    'pt_pt.iso885915':                      'pt_PT.ISO8859-15',
+    'pt_pt.iso885915@euro':                 'pt_PT.ISO8859-15',
+    'pt_pt.utf8@euro':                      'pt_PT.UTF-8',
+    'pt_pt@euro':                           'pt_PT.ISO8859-15',
+    'ro':                                   'ro_RO.ISO8859-2',
+    'ro_ro':                                'ro_RO.ISO8859-2',
+    'ro_ro.iso88592':                       'ro_RO.ISO8859-2',
+    'romanian':                             'ro_RO.ISO8859-2',
+    'ru':                                   'ru_RU.UTF-8',
+    'ru.koi8r':                             'ru_RU.KOI8-R',
+    'ru_ru':                                'ru_RU.UTF-8',
+    'ru_ru.cp1251':                         'ru_RU.CP1251',
+    'ru_ru.iso88595':                       'ru_RU.ISO8859-5',
+    'ru_ru.koi8r':                          'ru_RU.KOI8-R',
+    'ru_ru.microsoftcp1251':                'ru_RU.CP1251',
+    'ru_ua':                                'ru_UA.KOI8-U',
+    'ru_ua.cp1251':                         'ru_UA.CP1251',
+    'ru_ua.koi8u':                          'ru_UA.KOI8-U',
+    'ru_ua.microsoftcp1251':                'ru_UA.CP1251',
+    'rumanian':                             'ro_RO.ISO8859-2',
+    'russian':                              'ru_RU.ISO8859-5',
+    'rw':                                   'rw_RW.ISO8859-1',
+    'rw_rw':                                'rw_RW.ISO8859-1',
+    'rw_rw.iso88591':                       'rw_RW.ISO8859-1',
+    'sd':                                   'sd_IN@devanagari.UTF-8',
+    'se_no':                                'se_NO.UTF-8',
+    'serbocroatian':                        'sr_RS.UTF-8@latin',
+    'sh':                                   'sr_RS.UTF-8@latin',
+    'sh_ba.iso88592@bosnia':                'sr_CS.ISO8859-2',
+    'sh_hr':                                'sh_HR.ISO8859-2',
+    'sh_hr.iso88592':                       'hr_HR.ISO8859-2',
+    'sh_sp':                                'sr_CS.ISO8859-2',
+    'sh_yu':                                'sr_RS.UTF-8@latin',
+    'si':                                   'si_LK.UTF-8',
+    'si_lk':                                'si_LK.UTF-8',
+    'sinhala':                              'si_LK.UTF-8',
+    'sk':                                   'sk_SK.ISO8859-2',
+    'sk_sk':                                'sk_SK.ISO8859-2',
+    'sk_sk.iso88592':                       'sk_SK.ISO8859-2',
+    'sl':                                   'sl_SI.ISO8859-2',
+    'sl_cs':                                'sl_CS.ISO8859-2',
+    'sl_si':                                'sl_SI.ISO8859-2',
+    'sl_si.iso88592':                       'sl_SI.ISO8859-2',
+    'slovak':                               'sk_SK.ISO8859-2',
+    'slovene':                              'sl_SI.ISO8859-2',
+    'slovenian':                            'sl_SI.ISO8859-2',
+    'sp':                                   'sr_CS.ISO8859-5',
+    'sp_yu':                                'sr_CS.ISO8859-5',
+    'spanish':                              'es_ES.ISO8859-1',
+    'spanish.iso88591':                     'es_ES.ISO8859-1',
+    'spanish_spain':                        'es_ES.ISO8859-1',
+    'spanish_spain.8859':                   'es_ES.ISO8859-1',
+    'sq':                                   'sq_AL.ISO8859-2',
+    'sq_al':                                'sq_AL.ISO8859-2',
+    'sq_al.iso88592':                       'sq_AL.ISO8859-2',
+    'sr':                                   'sr_RS.UTF-8',
+    'sr@cyrillic':                          'sr_RS.UTF-8',
+    'sr@latin':                             'sr_RS.UTF-8@latin',
+    'sr@latn':                              'sr_RS.UTF-8@latin',
+    'sr_cs':                                'sr_RS.UTF-8',
+    'sr_cs.iso88592':                       'sr_CS.ISO8859-2',
+    'sr_cs.iso88592@latn':                  'sr_CS.ISO8859-2',
+    'sr_cs.iso88595':                       'sr_CS.ISO8859-5',
+    'sr_cs.utf8@latn':                      'sr_RS.UTF-8@latin',
+    'sr_cs@latn':                           'sr_RS.UTF-8@latin',
+    'sr_me':                                'sr_ME.UTF-8',
+    'sr_rs':                                'sr_RS.UTF-8',
+    'sr_rs.utf8@latn':                      'sr_RS.UTF-8@latin',
+    'sr_rs@latin':                          'sr_RS.UTF-8@latin',
+    'sr_rs@latn':                           'sr_RS.UTF-8@latin',
+    'sr_sp':                                'sr_CS.ISO8859-2',
+    'sr_yu':                                'sr_RS.UTF-8@latin',
+    'sr_yu.cp1251@cyrillic':                'sr_CS.CP1251',
+    'sr_yu.iso88592':                       'sr_CS.ISO8859-2',
+    'sr_yu.iso88595':                       'sr_CS.ISO8859-5',
+    'sr_yu.iso88595@cyrillic':              'sr_CS.ISO8859-5',
+    'sr_yu.microsoftcp1251@cyrillic':       'sr_CS.CP1251',
+    'sr_yu.utf8@cyrillic':                  'sr_RS.UTF-8',
+    'sr_yu@cyrillic':                       'sr_RS.UTF-8',
+    'ss':                                   'ss_ZA.ISO8859-1',
+    'ss_za':                                'ss_ZA.ISO8859-1',
+    'ss_za.iso88591':                       'ss_ZA.ISO8859-1',
+    'st':                                   'st_ZA.ISO8859-1',
+    'st_za':                                'st_ZA.ISO8859-1',
+    'st_za.iso88591':                       'st_ZA.ISO8859-1',
+    'sv':                                   'sv_SE.ISO8859-1',
+    'sv.iso885915':                         'sv_SE.ISO8859-15',
+    'sv_fi':                                'sv_FI.ISO8859-1',
+    'sv_fi.iso88591':                       'sv_FI.ISO8859-1',
+    'sv_fi.iso885915':                      'sv_FI.ISO8859-15',
+    'sv_fi.iso885915@euro':                 'sv_FI.ISO8859-15',
+    'sv_fi.utf8@euro':                      'sv_FI.UTF-8',
+    'sv_fi@euro':                           'sv_FI.ISO8859-15',
+    'sv_se':                                'sv_SE.ISO8859-1',
+    'sv_se.88591':                          'sv_SE.ISO8859-1',
+    'sv_se.iso88591':                       'sv_SE.ISO8859-1',
+    'sv_se.iso885915':                      'sv_SE.ISO8859-15',
+    'sv_se@euro':                           'sv_SE.ISO8859-15',
+    'swedish':                              'sv_SE.ISO8859-1',
+    'swedish.iso88591':                     'sv_SE.ISO8859-1',
+    'ta':                                   'ta_IN.TSCII-0',
+    'ta_in':                                'ta_IN.TSCII-0',
+    'ta_in.tscii':                          'ta_IN.TSCII-0',
+    'ta_in.tscii0':                         'ta_IN.TSCII-0',
+    'te':                                   'te_IN.UTF-8',
+    'tg':                                   'tg_TJ.KOI8-C',
+    'tg_tj':                                'tg_TJ.KOI8-C',
+    'tg_tj.koi8c':                          'tg_TJ.KOI8-C',
+    'th':                                   'th_TH.ISO8859-11',
+    'th_th':                                'th_TH.ISO8859-11',
+    'th_th.iso885911':                      'th_TH.ISO8859-11',
+    'th_th.tactis':                         'th_TH.TIS620',
+    'th_th.tis620':                         'th_TH.TIS620',
+    'thai':                                 'th_TH.ISO8859-11',
+    'tl':                                   'tl_PH.ISO8859-1',
+    'tl_ph':                                'tl_PH.ISO8859-1',
+    'tl_ph.iso88591':                       'tl_PH.ISO8859-1',
+    'tn':                                   'tn_ZA.ISO8859-15',
+    'tn_za':                                'tn_ZA.ISO8859-15',
+    'tn_za.iso885915':                      'tn_ZA.ISO8859-15',
+    'tr':                                   'tr_TR.ISO8859-9',
+    'tr_tr':                                'tr_TR.ISO8859-9',
+    'tr_tr.iso88599':                       'tr_TR.ISO8859-9',
+    'ts':                                   'ts_ZA.ISO8859-1',
+    'ts_za':                                'ts_ZA.ISO8859-1',
+    'ts_za.iso88591':                       'ts_ZA.ISO8859-1',
+    'tt':                                   'tt_RU.TATAR-CYR',
+    'tt_ru':                                'tt_RU.TATAR-CYR',
+    'tt_ru.koi8c':                          'tt_RU.KOI8-C',
+    'tt_ru.tatarcyr':                       'tt_RU.TATAR-CYR',
+    'turkish':                              'tr_TR.ISO8859-9',
+    'turkish.iso88599':                     'tr_TR.ISO8859-9',
+    'uk':                                   'uk_UA.KOI8-U',
+    'uk_ua':                                'uk_UA.KOI8-U',
+    'uk_ua.cp1251':                         'uk_UA.CP1251',
+    'uk_ua.iso88595':                       'uk_UA.ISO8859-5',
+    'uk_ua.koi8u':                          'uk_UA.KOI8-U',
+    'uk_ua.microsoftcp1251':                'uk_UA.CP1251',
+    'univ':                                 'en_US.utf',
+    'universal':                            'en_US.utf',
+    'universal.utf8@ucs4':                  'en_US.UTF-8',
+    'ur':                                   'ur_PK.CP1256',
+    'ur_pk':                                'ur_PK.CP1256',
+    'ur_pk.cp1256':                         'ur_PK.CP1256',
+    'ur_pk.microsoftcp1256':                'ur_PK.CP1256',
+    'uz':                                   'uz_UZ.UTF-8',
+    'uz_uz':                                'uz_UZ.UTF-8',
+    'uz_uz.iso88591':                       'uz_UZ.ISO8859-1',
+    'uz_uz.utf8@cyrillic':                  'uz_UZ.UTF-8',
+    'uz_uz@cyrillic':                       'uz_UZ.UTF-8',
+    've':                                   've_ZA.UTF-8',
+    've_za':                                've_ZA.UTF-8',
+    'vi':                                   'vi_VN.TCVN',
+    'vi_vn':                                'vi_VN.TCVN',
+    'vi_vn.tcvn':                           'vi_VN.TCVN',
+    'vi_vn.tcvn5712':                       'vi_VN.TCVN',
+    'vi_vn.viscii':                         'vi_VN.VISCII',
+    'vi_vn.viscii111':                      'vi_VN.VISCII',
+    'wa':                                   'wa_BE.ISO8859-1',
+    'wa_be':                                'wa_BE.ISO8859-1',
+    'wa_be.iso88591':                       'wa_BE.ISO8859-1',
+    'wa_be.iso885915':                      'wa_BE.ISO8859-15',
+    'wa_be.iso885915@euro':                 'wa_BE.ISO8859-15',
+    'wa_be@euro':                           'wa_BE.ISO8859-15',
+    'xh':                                   'xh_ZA.ISO8859-1',
+    'xh_za':                                'xh_ZA.ISO8859-1',
+    'xh_za.iso88591':                       'xh_ZA.ISO8859-1',
+    'yi':                                   'yi_US.CP1255',
+    'yi_us':                                'yi_US.CP1255',
+    'yi_us.cp1255':                         'yi_US.CP1255',
+    'yi_us.microsoftcp1255':                'yi_US.CP1255',
+    'zh':                                   'zh_CN.eucCN',
+    'zh_cn':                                'zh_CN.gb2312',
+    'zh_cn.big5':                           'zh_TW.big5',
+    'zh_cn.euc':                            'zh_CN.eucCN',
+    'zh_cn.gb18030':                        'zh_CN.gb18030',
+    'zh_cn.gb2312':                         'zh_CN.gb2312',
+    'zh_cn.gbk':                            'zh_CN.gbk',
+    'zh_hk':                                'zh_HK.big5hkscs',
+    'zh_hk.big5':                           'zh_HK.big5',
+    'zh_hk.big5hk':                         'zh_HK.big5hkscs',
+    'zh_hk.big5hkscs':                      'zh_HK.big5hkscs',
+    'zh_tw':                                'zh_TW.big5',
+    'zh_tw.big5':                           'zh_TW.big5',
+    'zh_tw.euc':                            'zh_TW.eucTW',
+    'zh_tw.euctw':                          'zh_TW.eucTW',
+    'zu':                                   'zu_ZA.ISO8859-1',
+    'zu_za':                                'zu_ZA.ISO8859-1',
+    'zu_za.iso88591':                       'zu_ZA.ISO8859-1',
+}
+
+#
+# This maps Windows language identifiers to locale strings.
+#
+# This list has been updated from
+# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_238z.asp
+# to include every locale up to Windows Vista.
+#
+# NOTE: this mapping is incomplete.  If your language is missing, please
+# submit a bug report to the Python bug tracker at http://bugs.python.org/
+# Make sure you include the missing language identifier and the suggested
+# locale code.
+#
+
+windows_locale = {
+    0x0436: "af_ZA", # Afrikaans
+    0x041c: "sq_AL", # Albanian
+    0x0484: "gsw_FR",# Alsatian - France
+    0x045e: "am_ET", # Amharic - Ethiopia
+    0x0401: "ar_SA", # Arabic - Saudi Arabia
+    0x0801: "ar_IQ", # Arabic - Iraq
+    0x0c01: "ar_EG", # Arabic - Egypt
+    0x1001: "ar_LY", # Arabic - Libya
+    0x1401: "ar_DZ", # Arabic - Algeria
+    0x1801: "ar_MA", # Arabic - Morocco
+    0x1c01: "ar_TN", # Arabic - Tunisia
+    0x2001: "ar_OM", # Arabic - Oman
+    0x2401: "ar_YE", # Arabic - Yemen
+    0x2801: "ar_SY", # Arabic - Syria
+    0x2c01: "ar_JO", # Arabic - Jordan
+    0x3001: "ar_LB", # Arabic - Lebanon
+    0x3401: "ar_KW", # Arabic - Kuwait
+    0x3801: "ar_AE", # Arabic - United Arab Emirates
+    0x3c01: "ar_BH", # Arabic - Bahrain
+    0x4001: "ar_QA", # Arabic - Qatar
+    0x042b: "hy_AM", # Armenian
+    0x044d: "as_IN", # Assamese - India
+    0x042c: "az_AZ", # Azeri - Latin
+    0x082c: "az_AZ", # Azeri - Cyrillic
+    0x046d: "ba_RU", # Bashkir
+    0x042d: "eu_ES", # Basque - Russia
+    0x0423: "be_BY", # Belarusian
+    0x0445: "bn_IN", # Begali
+    0x201a: "bs_BA", # Bosnian - Cyrillic
+    0x141a: "bs_BA", # Bosnian - Latin
+    0x047e: "br_FR", # Breton - France
+    0x0402: "bg_BG", # Bulgarian
+#    0x0455: "my_MM", # Burmese - Not supported
+    0x0403: "ca_ES", # Catalan
+    0x0004: "zh_CHS",# Chinese - Simplified
+    0x0404: "zh_TW", # Chinese - Taiwan
+    0x0804: "zh_CN", # Chinese - PRC
+    0x0c04: "zh_HK", # Chinese - Hong Kong S.A.R.
+    0x1004: "zh_SG", # Chinese - Singapore
+    0x1404: "zh_MO", # Chinese - Macao S.A.R.
+    0x7c04: "zh_CHT",# Chinese - Traditional
+    0x0483: "co_FR", # Corsican - France
+    0x041a: "hr_HR", # Croatian
+    0x101a: "hr_BA", # Croatian - Bosnia
+    0x0405: "cs_CZ", # Czech
+    0x0406: "da_DK", # Danish
+    0x048c: "gbz_AF",# Dari - Afghanistan
+    0x0465: "div_MV",# Divehi - Maldives
+    0x0413: "nl_NL", # Dutch - The Netherlands
+    0x0813: "nl_BE", # Dutch - Belgium
+    0x0409: "en_US", # English - United States
+    0x0809: "en_GB", # English - United Kingdom
+    0x0c09: "en_AU", # English - Australia
+    0x1009: "en_CA", # English - Canada
+    0x1409: "en_NZ", # English - New Zealand
+    0x1809: "en_IE", # English - Ireland
+    0x1c09: "en_ZA", # English - South Africa
+    0x2009: "en_JA", # English - Jamaica
+    0x2409: "en_CB", # English - Carribbean
+    0x2809: "en_BZ", # English - Belize
+    0x2c09: "en_TT", # English - Trinidad
+    0x3009: "en_ZW", # English - Zimbabwe
+    0x3409: "en_PH", # English - Philippines
+    0x4009: "en_IN", # English - India
+    0x4409: "en_MY", # English - Malaysia
+    0x4809: "en_IN", # English - Singapore
+    0x0425: "et_EE", # Estonian
+    0x0438: "fo_FO", # Faroese
+    0x0464: "fil_PH",# Filipino
+    0x040b: "fi_FI", # Finnish
+    0x040c: "fr_FR", # French - France
+    0x080c: "fr_BE", # French - Belgium
+    0x0c0c: "fr_CA", # French - Canada
+    0x100c: "fr_CH", # French - Switzerland
+    0x140c: "fr_LU", # French - Luxembourg
+    0x180c: "fr_MC", # French - Monaco
+    0x0462: "fy_NL", # Frisian - Netherlands
+    0x0456: "gl_ES", # Galician
+    0x0437: "ka_GE", # Georgian
+    0x0407: "de_DE", # German - Germany
+    0x0807: "de_CH", # German - Switzerland
+    0x0c07: "de_AT", # German - Austria
+    0x1007: "de_LU", # German - Luxembourg
+    0x1407: "de_LI", # German - Liechtenstein
+    0x0408: "el_GR", # Greek
+    0x046f: "kl_GL", # Greenlandic - Greenland
+    0x0447: "gu_IN", # Gujarati
+    0x0468: "ha_NG", # Hausa - Latin
+    0x040d: "he_IL", # Hebrew
+    0x0439: "hi_IN", # Hindi
+    0x040e: "hu_HU", # Hungarian
+    0x040f: "is_IS", # Icelandic
+    0x0421: "id_ID", # Indonesian
+    0x045d: "iu_CA", # Inuktitut - Syllabics
+    0x085d: "iu_CA", # Inuktitut - Latin
+    0x083c: "ga_IE", # Irish - Ireland
+    0x0410: "it_IT", # Italian - Italy
+    0x0810: "it_CH", # Italian - Switzerland
+    0x0411: "ja_JP", # Japanese
+    0x044b: "kn_IN", # Kannada - India
+    0x043f: "kk_KZ", # Kazakh
+    0x0453: "kh_KH", # Khmer - Cambodia
+    0x0486: "qut_GT",# K'iche - Guatemala
+    0x0487: "rw_RW", # Kinyarwanda - Rwanda
+    0x0457: "kok_IN",# Konkani
+    0x0412: "ko_KR", # Korean
+    0x0440: "ky_KG", # Kyrgyz
+    0x0454: "lo_LA", # Lao - Lao PDR
+    0x0426: "lv_LV", # Latvian
+    0x0427: "lt_LT", # Lithuanian
+    0x082e: "dsb_DE",# Lower Sorbian - Germany
+    0x046e: "lb_LU", # Luxembourgish
+    0x042f: "mk_MK", # FYROM Macedonian
+    0x043e: "ms_MY", # Malay - Malaysia
+    0x083e: "ms_BN", # Malay - Brunei Darussalam
+    0x044c: "ml_IN", # Malayalam - India
+    0x043a: "mt_MT", # Maltese
+    0x0481: "mi_NZ", # Maori
+    0x047a: "arn_CL",# Mapudungun
+    0x044e: "mr_IN", # Marathi
+    0x047c: "moh_CA",# Mohawk - Canada
+    0x0450: "mn_MN", # Mongolian - Cyrillic
+    0x0850: "mn_CN", # Mongolian - PRC
+    0x0461: "ne_NP", # Nepali
+    0x0414: "nb_NO", # Norwegian - Bokmal
+    0x0814: "nn_NO", # Norwegian - Nynorsk
+    0x0482: "oc_FR", # Occitan - France
+    0x0448: "or_IN", # Oriya - India
+    0x0463: "ps_AF", # Pashto - Afghanistan
+    0x0429: "fa_IR", # Persian
+    0x0415: "pl_PL", # Polish
+    0x0416: "pt_BR", # Portuguese - Brazil
+    0x0816: "pt_PT", # Portuguese - Portugal
+    0x0446: "pa_IN", # Punjabi
+    0x046b: "quz_BO",# Quechua (Bolivia)
+    0x086b: "quz_EC",# Quechua (Ecuador)
+    0x0c6b: "quz_PE",# Quechua (Peru)
+    0x0418: "ro_RO", # Romanian - Romania
+    0x0417: "rm_CH", # Romansh
+    0x0419: "ru_RU", # Russian
+    0x243b: "smn_FI",# Sami Finland
+    0x103b: "smj_NO",# Sami Norway
+    0x143b: "smj_SE",# Sami Sweden
+    0x043b: "se_NO", # Sami Northern Norway
+    0x083b: "se_SE", # Sami Northern Sweden
+    0x0c3b: "se_FI", # Sami Northern Finland
+    0x203b: "sms_FI",# Sami Skolt
+    0x183b: "sma_NO",# Sami Southern Norway
+    0x1c3b: "sma_SE",# Sami Southern Sweden
+    0x044f: "sa_IN", # Sanskrit
+    0x0c1a: "sr_SP", # Serbian - Cyrillic
+    0x1c1a: "sr_BA", # Serbian - Bosnia Cyrillic
+    0x081a: "sr_SP", # Serbian - Latin
+    0x181a: "sr_BA", # Serbian - Bosnia Latin
+    0x045b: "si_LK", # Sinhala - Sri Lanka
+    0x046c: "ns_ZA", # Northern Sotho
+    0x0432: "tn_ZA", # Setswana - Southern Africa
+    0x041b: "sk_SK", # Slovak
+    0x0424: "sl_SI", # Slovenian
+    0x040a: "es_ES", # Spanish - Spain
+    0x080a: "es_MX", # Spanish - Mexico
+    0x0c0a: "es_ES", # Spanish - Spain (Modern)
+    0x100a: "es_GT", # Spanish - Guatemala
+    0x140a: "es_CR", # Spanish - Costa Rica
+    0x180a: "es_PA", # Spanish - Panama
+    0x1c0a: "es_DO", # Spanish - Dominican Republic
+    0x200a: "es_VE", # Spanish - Venezuela
+    0x240a: "es_CO", # Spanish - Colombia
+    0x280a: "es_PE", # Spanish - Peru
+    0x2c0a: "es_AR", # Spanish - Argentina
+    0x300a: "es_EC", # Spanish - Ecuador
+    0x340a: "es_CL", # Spanish - Chile
+    0x380a: "es_UR", # Spanish - Uruguay
+    0x3c0a: "es_PY", # Spanish - Paraguay
+    0x400a: "es_BO", # Spanish - Bolivia
+    0x440a: "es_SV", # Spanish - El Salvador
+    0x480a: "es_HN", # Spanish - Honduras
+    0x4c0a: "es_NI", # Spanish - Nicaragua
+    0x500a: "es_PR", # Spanish - Puerto Rico
+    0x540a: "es_US", # Spanish - United States
+#    0x0430: "", # Sutu - Not supported
+    0x0441: "sw_KE", # Swahili
+    0x041d: "sv_SE", # Swedish - Sweden
+    0x081d: "sv_FI", # Swedish - Finland
+    0x045a: "syr_SY",# Syriac
+    0x0428: "tg_TJ", # Tajik - Cyrillic
+    0x085f: "tmz_DZ",# Tamazight - Latin
+    0x0449: "ta_IN", # Tamil
+    0x0444: "tt_RU", # Tatar
+    0x044a: "te_IN", # Telugu
+    0x041e: "th_TH", # Thai
+    0x0851: "bo_BT", # Tibetan - Bhutan
+    0x0451: "bo_CN", # Tibetan - PRC
+    0x041f: "tr_TR", # Turkish
+    0x0442: "tk_TM", # Turkmen - Cyrillic
+    0x0480: "ug_CN", # Uighur - Arabic
+    0x0422: "uk_UA", # Ukrainian
+    0x042e: "wen_DE",# Upper Sorbian - Germany
+    0x0420: "ur_PK", # Urdu
+    0x0820: "ur_IN", # Urdu - India
+    0x0443: "uz_UZ", # Uzbek - Latin
+    0x0843: "uz_UZ", # Uzbek - Cyrillic
+    0x042a: "vi_VN", # Vietnamese
+    0x0452: "cy_GB", # Welsh
+    0x0488: "wo_SN", # Wolof - Senegal
+    0x0434: "xh_ZA", # Xhosa - South Africa
+    0x0485: "sah_RU",# Yakut - Cyrillic
+    0x0478: "ii_CN", # Yi - PRC
+    0x046a: "yo_NG", # Yoruba - Nigeria
+    0x0435: "zu_ZA", # Zulu
+}
+
+def _print_locale():
+
+    """ Test function.
+    """
+    categories = {}
+    def _init_categories(categories=categories):
+        for k,v in globals().items():
+            if k[:3] == 'LC_':
+                categories[k] = v
+    _init_categories()
+    del categories['LC_ALL']
+
+    print 'Locale defaults as determined by getdefaultlocale():'
+    print '-'*72
+    lang, enc = getdefaultlocale()
+    print 'Language: ', lang or '(undefined)'
+    print 'Encoding: ', enc or '(undefined)'
+    print
+
+    print 'Locale settings on startup:'
+    print '-'*72
+    for name,category in categories.items():
+        print name, '...'
+        lang, enc = getlocale(category)
+        print '   Language: ', lang or '(undefined)'
+        print '   Encoding: ', enc or '(undefined)'
+        print
+
+    print
+    print 'Locale settings after calling resetlocale():'
+    print '-'*72
+    resetlocale()
+    for name,category in categories.items():
+        print name, '...'
+        lang, enc = getlocale(category)
+        print '   Language: ', lang or '(undefined)'
+        print '   Encoding: ', enc or '(undefined)'
+        print
+
+    try:
+        setlocale(LC_ALL, "")
+    except:
+        print 'NOTE:'
+        print 'setlocale(LC_ALL, "") does not support the default locale'
+        print 'given in the OS environment variables.'
+    else:
+        print
+        print 'Locale settings after calling setlocale(LC_ALL, ""):'
+        print '-'*72
+        for name,category in categories.items():
+            print name, '...'
+            lang, enc = getlocale(category)
+            print '   Language: ', lang or '(undefined)'
+            print '   Encoding: ', enc or '(undefined)'
+            print
+
+###
+
+try:
+    LC_MESSAGES
+except NameError:
+    pass
+else:
+    __all__.append("LC_MESSAGES")
+
+if __name__=='__main__':
+    print 'Locale aliasing:'
+    print
+    _print_locale()
+    print
+    print 'Number formatting:'
+    print
+    _test()
diff --git a/src/main/resources/PythonLibs/logging/__init__.py b/src/main/resources/PythonLibs/logging/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..1a622a3d074778eba4a8e105f165161975834e3c
--- /dev/null
+++ b/src/main/resources/PythonLibs/logging/__init__.py
@@ -0,0 +1,1726 @@
+# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of Vinay Sajip
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+Logging package for Python. Based on PEP 282 and comments thereto in
+comp.lang.python.
+
+Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved.
+
+To use, simply 'import logging' and log away!
+"""
+
+import sys, os, time, cStringIO, traceback, warnings, weakref
+
+__all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
+           'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
+           'LogRecord', 'Logger', 'LoggerAdapter', 'NOTSET', 'NullHandler',
+           'StreamHandler', 'WARN', 'WARNING', 'addLevelName', 'basicConfig',
+           'captureWarnings', 'critical', 'debug', 'disable', 'error',
+           'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
+           'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning']
+
+try:
+    import codecs
+except ImportError:
+    codecs = None
+
+try:
+    import thread
+    import threading
+except ImportError:
+    thread = None
+
+__author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
+__status__  = "production"
+__version__ = "0.5.1.2"
+__date__    = "07 February 2010"
+
+#---------------------------------------------------------------------------
+#   Miscellaneous module data
+#---------------------------------------------------------------------------
+try:
+    unicode
+    _unicode = True
+except NameError:
+    _unicode = False
+
+#
+# _srcfile is used when walking the stack to check when we've got the first
+# caller stack frame.
+#
+if hasattr(sys, 'frozen'): #support for py2exe
+    _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:])
+elif __file__[-4:].lower() in ['.pyc', '.pyo']:
+    _srcfile = __file__[:-4] + '.py'
+else:
+    _srcfile = __file__
+_srcfile = os.path.normcase(_srcfile)
+
+# next bit filched from 1.5.2's inspect.py
+def currentframe():
+    """Return the frame object for the caller's stack frame."""
+    try:
+        raise Exception
+    except:
+        return sys.exc_info()[2].tb_frame.f_back
+
+if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3)
+# done filching
+
+# _srcfile is only used in conjunction with sys._getframe().
+# To provide compatibility with older versions of Python, set _srcfile
+# to None if _getframe() is not available; this value will prevent
+# findCaller() from being called.
+#if not hasattr(sys, "_getframe"):
+#    _srcfile = None
+
+#
+#_startTime is used as the base when calculating the relative time of events
+#
+_startTime = time.time()
+
+#
+#raiseExceptions is used to see if exceptions during handling should be
+#propagated
+#
+raiseExceptions = 1
+
+#
+# If you don't want threading information in the log, set this to zero
+#
+logThreads = 1
+
+#
+# If you don't want multiprocessing information in the log, set this to zero
+#
+logMultiprocessing = 1
+
+#
+# If you don't want process information in the log, set this to zero
+#
+logProcesses = 1
+
+#---------------------------------------------------------------------------
+#   Level related stuff
+#---------------------------------------------------------------------------
+#
+# Default levels and level names, these can be replaced with any positive set
+# of values having corresponding names. There is a pseudo-level, NOTSET, which
+# is only really there as a lower limit for user-defined levels. Handlers and
+# loggers are initialized with NOTSET so that they will log all messages, even
+# at user-defined levels.
+#
+
+CRITICAL = 50
+FATAL = CRITICAL
+ERROR = 40
+WARNING = 30
+WARN = WARNING
+INFO = 20
+DEBUG = 10
+NOTSET = 0
+
+_levelNames = {
+    CRITICAL : 'CRITICAL',
+    ERROR : 'ERROR',
+    WARNING : 'WARNING',
+    INFO : 'INFO',
+    DEBUG : 'DEBUG',
+    NOTSET : 'NOTSET',
+    'CRITICAL' : CRITICAL,
+    'ERROR' : ERROR,
+    'WARN' : WARNING,
+    'WARNING' : WARNING,
+    'INFO' : INFO,
+    'DEBUG' : DEBUG,
+    'NOTSET' : NOTSET,
+}
+
+def getLevelName(level):
+    """
+    Return the textual representation of logging level 'level'.
+
+    If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
+    INFO, DEBUG) then you get the corresponding string. If you have
+    associated levels with names using addLevelName then the name you have
+    associated with 'level' is returned.
+
+    If a numeric value corresponding to one of the defined levels is passed
+    in, the corresponding string representation is returned.
+
+    Otherwise, the string "Level %s" % level is returned.
+    """
+    return _levelNames.get(level, ("Level %s" % level))
+
+def addLevelName(level, levelName):
+    """
+    Associate 'levelName' with 'level'.
+
+    This is used when converting levels to text during message formatting.
+    """
+    _acquireLock()
+    try:    #unlikely to cause an exception, but you never know...
+        _levelNames[level] = levelName
+        _levelNames[levelName] = level
+    finally:
+        _releaseLock()
+
+def _checkLevel(level):
+    if isinstance(level, (int, long)):
+        rv = level
+    elif str(level) == level:
+        if level not in _levelNames:
+            raise ValueError("Unknown level: %r" % level)
+        rv = _levelNames[level]
+    else:
+        raise TypeError("Level not an integer or a valid string: %r" % level)
+    return rv
+
+#---------------------------------------------------------------------------
+#   Thread-related stuff
+#---------------------------------------------------------------------------
+
+#
+#_lock is used to serialize access to shared data structures in this module.
+#This needs to be an RLock because fileConfig() creates and configures
+#Handlers, and so might arbitrary user threads. Since Handler code updates the
+#shared dictionary _handlers, it needs to acquire the lock. But if configuring,
+#the lock would already have been acquired - so we need an RLock.
+#The same argument applies to Loggers and Manager.loggerDict.
+#
+if thread:
+    _lock = threading.RLock()
+else:
+    _lock = None
+
+def _acquireLock():
+    """
+    Acquire the module-level lock for serializing access to shared data.
+
+    This should be released with _releaseLock().
+    """
+    if _lock:
+        _lock.acquire()
+
+def _releaseLock():
+    """
+    Release the module-level lock acquired by calling _acquireLock().
+    """
+    if _lock:
+        _lock.release()
+
+#---------------------------------------------------------------------------
+#   The logging record
+#---------------------------------------------------------------------------
+
+class LogRecord(object):
+    """
+    A LogRecord instance represents an event being logged.
+
+    LogRecord instances are created every time something is logged. They
+    contain all the information pertinent to the event being logged. The
+    main information passed in is in msg and args, which are combined
+    using str(msg) % args to create the message field of the record. The
+    record also includes information such as when the record was created,
+    the source line where the logging call was made, and any exception
+    information to be logged.
+    """
+    def __init__(self, name, level, pathname, lineno,
+                 msg, args, exc_info, func=None):
+        """
+        Initialize a logging record with interesting information.
+        """
+        ct = time.time()
+        self.name = name
+        self.msg = msg
+        #
+        # The following statement allows passing of a dictionary as a sole
+        # argument, so that you can do something like
+        #  logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
+        # Suggested by Stefan Behnel.
+        # Note that without the test for args[0], we get a problem because
+        # during formatting, we test to see if the arg is present using
+        # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
+        # and if the passed arg fails 'if self.args:' then no formatting
+        # is done. For example, logger.warn('Value is %d', 0) would log
+        # 'Value is %d' instead of 'Value is 0'.
+        # For the use case of passing a dictionary, this should not be a
+        # problem.
+        if args and len(args) == 1 and isinstance(args[0], dict) and args[0]:
+            args = args[0]
+        self.args = args
+        self.levelname = getLevelName(level)
+        self.levelno = level
+        self.pathname = pathname
+        try:
+            self.filename = os.path.basename(pathname)
+            self.module = os.path.splitext(self.filename)[0]
+        except (TypeError, ValueError, AttributeError):
+            self.filename = pathname
+            self.module = "Unknown module"
+        self.exc_info = exc_info
+        self.exc_text = None      # used to cache the traceback text
+        self.lineno = lineno
+        self.funcName = func
+        self.created = ct
+        self.msecs = (ct - long(ct)) * 1000
+        self.relativeCreated = (self.created - _startTime) * 1000
+        if logThreads and thread:
+            self.thread = thread.get_ident()
+            self.threadName = threading.current_thread().name
+        else:
+            self.thread = None
+            self.threadName = None
+        if not logMultiprocessing:
+            self.processName = None
+        else:
+            self.processName = 'MainProcess'
+            mp = sys.modules.get('multiprocessing')
+            if mp is not None:
+                # Errors may occur if multiprocessing has not finished loading
+                # yet - e.g. if a custom import hook causes third-party code
+                # to run when multiprocessing calls import. See issue 8200
+                # for an example
+                try:
+                    self.processName = mp.current_process().name
+                except StandardError:
+                    pass
+        if logProcesses and hasattr(os, 'getpid'):
+            self.process = os.getpid()
+        else:
+            self.process = None
+
+    def __str__(self):
+        return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
+            self.pathname, self.lineno, self.msg)
+
+    def getMessage(self):
+        """
+        Return the message for this LogRecord.
+
+        Return the message for this LogRecord after merging any user-supplied
+        arguments with the message.
+        """
+        if not _unicode: #if no unicode support...
+            msg = str(self.msg)
+        else:
+            msg = self.msg
+            if not isinstance(msg, basestring):
+                try:
+                    msg = str(self.msg)
+                except UnicodeError:
+                    msg = self.msg      #Defer encoding till later
+        if self.args:
+            msg = msg % self.args
+        return msg
+
+def makeLogRecord(dict):
+    """
+    Make a LogRecord whose attributes are defined by the specified dictionary,
+    This function is useful for converting a logging event received over
+    a socket connection (which is sent as a dictionary) into a LogRecord
+    instance.
+    """
+    rv = LogRecord(None, None, "", 0, "", (), None, None)
+    rv.__dict__.update(dict)
+    return rv
+
+#---------------------------------------------------------------------------
+#   Formatter classes and functions
+#---------------------------------------------------------------------------
+
+class Formatter(object):
+    """
+    Formatter instances are used to convert a LogRecord to text.
+
+    Formatters need to know how a LogRecord is constructed. They are
+    responsible for converting a LogRecord to (usually) a string which can
+    be interpreted by either a human or an external system. The base Formatter
+    allows a formatting string to be specified. If none is supplied, the
+    default value of "%s(message)\\n" is used.
+
+    The Formatter can be initialized with a format string which makes use of
+    knowledge of the LogRecord attributes - e.g. the default value mentioned
+    above makes use of the fact that the user's message and arguments are pre-
+    formatted into a LogRecord's message attribute. Currently, the useful
+    attributes in a LogRecord are described by:
+
+    %(name)s            Name of the logger (logging channel)
+    %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
+                        WARNING, ERROR, CRITICAL)
+    %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
+                        "WARNING", "ERROR", "CRITICAL")
+    %(pathname)s        Full pathname of the source file where the logging
+                        call was issued (if available)
+    %(filename)s        Filename portion of pathname
+    %(module)s          Module (name portion of filename)
+    %(lineno)d          Source line number where the logging call was issued
+                        (if available)
+    %(funcName)s        Function name
+    %(created)f         Time when the LogRecord was created (time.time()
+                        return value)
+    %(asctime)s         Textual time when the LogRecord was created
+    %(msecs)d           Millisecond portion of the creation time
+    %(relativeCreated)d Time in milliseconds when the LogRecord was created,
+                        relative to the time the logging module was loaded
+                        (typically at application startup time)
+    %(thread)d          Thread ID (if available)
+    %(threadName)s      Thread name (if available)
+    %(process)d         Process ID (if available)
+    %(message)s         The result of record.getMessage(), computed just as
+                        the record is emitted
+    """
+
+    converter = time.localtime
+
+    def __init__(self, fmt=None, datefmt=None):
+        """
+        Initialize the formatter with specified format strings.
+
+        Initialize the formatter either with the specified format string, or a
+        default as described above. Allow for specialized date formatting with
+        the optional datefmt argument (if omitted, you get the ISO8601 format).
+        """
+        if fmt:
+            self._fmt = fmt
+        else:
+            self._fmt = "%(message)s"
+        self.datefmt = datefmt
+
+    def formatTime(self, record, datefmt=None):
+        """
+        Return the creation time of the specified LogRecord as formatted text.
+
+        This method should be called from format() by a formatter which
+        wants to make use of a formatted time. This method can be overridden
+        in formatters to provide for any specific requirement, but the
+        basic behaviour is as follows: if datefmt (a string) is specified,
+        it is used with time.strftime() to format the creation time of the
+        record. Otherwise, the ISO8601 format is used. The resulting
+        string is returned. This function uses a user-configurable function
+        to convert the creation time to a tuple. By default, time.localtime()
+        is used; to change this for a particular formatter instance, set the
+        'converter' attribute to a function with the same signature as
+        time.localtime() or time.gmtime(). To change it for all formatters,
+        for example if you want all logging times to be shown in GMT,
+        set the 'converter' attribute in the Formatter class.
+        """
+        ct = self.converter(record.created)
+        if datefmt:
+            s = time.strftime(datefmt, ct)
+        else:
+            t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
+            s = "%s,%03d" % (t, record.msecs)
+        return s
+
+    def formatException(self, ei):
+        """
+        Format and return the specified exception information as a string.
+
+        This default implementation just uses
+        traceback.print_exception()
+        """
+        sio = cStringIO.StringIO()
+        traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
+        s = sio.getvalue()
+        sio.close()
+        if s[-1:] == "\n":
+            s = s[:-1]
+        return s
+
+    def usesTime(self):
+        """
+        Check if the format uses the creation time of the record.
+        """
+        return self._fmt.find("%(asctime)") >= 0
+
+    def format(self, record):
+        """
+        Format the specified record as text.
+
+        The record's attribute dictionary is used as the operand to a
+        string formatting operation which yields the returned string.
+        Before formatting the dictionary, a couple of preparatory steps
+        are carried out. The message attribute of the record is computed
+        using LogRecord.getMessage(). If the formatting string uses the
+        time (as determined by a call to usesTime(), formatTime() is
+        called to format the event time. If there is exception information,
+        it is formatted using formatException() and appended to the message.
+        """
+        record.message = record.getMessage()
+        if self.usesTime():
+            record.asctime = self.formatTime(record, self.datefmt)
+        s = self._fmt % record.__dict__
+        if record.exc_info:
+            # Cache the traceback text to avoid converting it multiple times
+            # (it's constant anyway)
+            if not record.exc_text:
+                record.exc_text = self.formatException(record.exc_info)
+        if record.exc_text:
+            if s[-1:] != "\n":
+                s = s + "\n"
+            try:
+                s = s + record.exc_text
+            except UnicodeError:
+                # Sometimes filenames have non-ASCII chars, which can lead
+                # to errors when s is Unicode and record.exc_text is str
+                # See issue 8924.
+                # We also use replace for when there are multiple
+                # encodings, e.g. UTF-8 for the filesystem and latin-1
+                # for a script. See issue 13232.
+                s = s + record.exc_text.decode(sys.getfilesystemencoding(),
+                                               'replace')
+        return s
+
+#
+#   The default formatter to use when no other is specified
+#
+_defaultFormatter = Formatter()
+
+class BufferingFormatter(object):
+    """
+    A formatter suitable for formatting a number of records.
+    """
+    def __init__(self, linefmt=None):
+        """
+        Optionally specify a formatter which will be used to format each
+        individual record.
+        """
+        if linefmt:
+            self.linefmt = linefmt
+        else:
+            self.linefmt = _defaultFormatter
+
+    def formatHeader(self, records):
+        """
+        Return the header string for the specified records.
+        """
+        return ""
+
+    def formatFooter(self, records):
+        """
+        Return the footer string for the specified records.
+        """
+        return ""
+
+    def format(self, records):
+        """
+        Format the specified records and return the result as a string.
+        """
+        rv = ""
+        if len(records) > 0:
+            rv = rv + self.formatHeader(records)
+            for record in records:
+                rv = rv + self.linefmt.format(record)
+            rv = rv + self.formatFooter(records)
+        return rv
+
+#---------------------------------------------------------------------------
+#   Filter classes and functions
+#---------------------------------------------------------------------------
+
+class Filter(object):
+    """
+    Filter instances are used to perform arbitrary filtering of LogRecords.
+
+    Loggers and Handlers can optionally use Filter instances to filter
+    records as desired. The base filter class only allows events which are
+    below a certain point in the logger hierarchy. For example, a filter
+    initialized with "A.B" will allow events logged by loggers "A.B",
+    "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
+    initialized with the empty string, all events are passed.
+    """
+    def __init__(self, name=''):
+        """
+        Initialize a filter.
+
+        Initialize with the name of the logger which, together with its
+        children, will have its events allowed through the filter. If no
+        name is specified, allow every event.
+        """
+        self.name = name
+        self.nlen = len(name)
+
+    def filter(self, record):
+        """
+        Determine if the specified record is to be logged.
+
+        Is the specified record to be logged? Returns 0 for no, nonzero for
+        yes. If deemed appropriate, the record may be modified in-place.
+        """
+        if self.nlen == 0:
+            return 1
+        elif self.name == record.name:
+            return 1
+        elif record.name.find(self.name, 0, self.nlen) != 0:
+            return 0
+        return (record.name[self.nlen] == ".")
+
+class Filterer(object):
+    """
+    A base class for loggers and handlers which allows them to share
+    common code.
+    """
+    def __init__(self):
+        """
+        Initialize the list of filters to be an empty list.
+        """
+        self.filters = []
+
+    def addFilter(self, filter):
+        """
+        Add the specified filter to this handler.
+        """
+        if not (filter in self.filters):
+            self.filters.append(filter)
+
+    def removeFilter(self, filter):
+        """
+        Remove the specified filter from this handler.
+        """
+        if filter in self.filters:
+            self.filters.remove(filter)
+
+    def filter(self, record):
+        """
+        Determine if a record is loggable by consulting all the filters.
+
+        The default is to allow the record to be logged; any filter can veto
+        this and the record is then dropped. Returns a zero value if a record
+        is to be dropped, else non-zero.
+        """
+        rv = 1
+        for f in self.filters:
+            if not f.filter(record):
+                rv = 0
+                break
+        return rv
+
+#---------------------------------------------------------------------------
+#   Handler classes and functions
+#---------------------------------------------------------------------------
+
+_handlers = weakref.WeakValueDictionary()  #map of handler names to handlers
+_handlerList = [] # added to allow handlers to be removed in reverse of order initialized
+
+def _removeHandlerRef(wr):
+    """
+    Remove a handler reference from the internal cleanup list.
+    """
+    # This function can be called during module teardown, when globals are
+    # set to None. If _acquireLock is None, assume this is the case and do
+    # nothing.
+    if (_acquireLock is not None and _handlerList is not None and
+        _releaseLock is not None):
+        _acquireLock()
+        try:
+            if wr in _handlerList:
+                _handlerList.remove(wr)
+        finally:
+            _releaseLock()
+
+def _addHandlerRef(handler):
+    """
+    Add a handler to the internal cleanup list using a weak reference.
+    """
+    _acquireLock()
+    try:
+        _handlerList.append(weakref.ref(handler, _removeHandlerRef))
+    finally:
+        _releaseLock()
+
+class Handler(Filterer):
+    """
+    Handler instances dispatch logging events to specific destinations.
+
+    The base handler class. Acts as a placeholder which defines the Handler
+    interface. Handlers can optionally use Formatter instances to format
+    records as desired. By default, no formatter is specified; in this case,
+    the 'raw' message as determined by record.message is logged.
+    """
+    def __init__(self, level=NOTSET):
+        """
+        Initializes the instance - basically setting the formatter to None
+        and the filter list to empty.
+        """
+        Filterer.__init__(self)
+        self._name = None
+        self.level = _checkLevel(level)
+        self.formatter = None
+        # Add the handler to the global _handlerList (for cleanup on shutdown)
+        _addHandlerRef(self)
+        self.createLock()
+
+    def get_name(self):
+        return self._name
+
+    def set_name(self, name):
+        _acquireLock()
+        try:
+            if self._name in _handlers:
+                del _handlers[self._name]
+            self._name = name
+            if name:
+                _handlers[name] = self
+        finally:
+            _releaseLock()
+
+    name = property(get_name, set_name)
+
+    def createLock(self):
+        """
+        Acquire a thread lock for serializing access to the underlying I/O.
+        """
+        if thread:
+            self.lock = threading.RLock()
+        else:
+            self.lock = None
+
+    def acquire(self):
+        """
+        Acquire the I/O thread lock.
+        """
+        if self.lock:
+            self.lock.acquire()
+
+    def release(self):
+        """
+        Release the I/O thread lock.
+        """
+        if self.lock:
+            self.lock.release()
+
+    def setLevel(self, level):
+        """
+        Set the logging level of this handler.
+        """
+        self.level = _checkLevel(level)
+
+    def format(self, record):
+        """
+        Format the specified record.
+
+        If a formatter is set, use it. Otherwise, use the default formatter
+        for the module.
+        """
+        if self.formatter:
+            fmt = self.formatter
+        else:
+            fmt = _defaultFormatter
+        return fmt.format(record)
+
+    def emit(self, record):
+        """
+        Do whatever it takes to actually log the specified logging record.
+
+        This version is intended to be implemented by subclasses and so
+        raises a NotImplementedError.
+        """
+        raise NotImplementedError('emit must be implemented '
+                                  'by Handler subclasses')
+
+    def handle(self, record):
+        """
+        Conditionally emit the specified logging record.
+
+        Emission depends on filters which may have been added to the handler.
+        Wrap the actual emission of the record with acquisition/release of
+        the I/O thread lock. Returns whether the filter passed the record for
+        emission.
+        """
+        rv = self.filter(record)
+        if rv:
+            self.acquire()
+            try:
+                self.emit(record)
+            finally:
+                self.release()
+        return rv
+
+    def setFormatter(self, fmt):
+        """
+        Set the formatter for this handler.
+        """
+        self.formatter = fmt
+
+    def flush(self):
+        """
+        Ensure all logging output has been flushed.
+
+        This version does nothing and is intended to be implemented by
+        subclasses.
+        """
+        pass
+
+    def close(self):
+        """
+        Tidy up any resources used by the handler.
+
+        This version removes the handler from an internal map of handlers,
+        _handlers, which is used for handler lookup by name. Subclasses
+        should ensure that this gets called from overridden close()
+        methods.
+        """
+        #get the module data lock, as we're updating a shared structure.
+        _acquireLock()
+        try:    #unlikely to raise an exception, but you never know...
+            if self._name and self._name in _handlers:
+                del _handlers[self._name]
+        finally:
+            _releaseLock()
+
+    def handleError(self, record):
+        """
+        Handle errors which occur during an emit() call.
+
+        This method should be called from handlers when an exception is
+        encountered during an emit() call. If raiseExceptions is false,
+        exceptions get silently ignored. This is what is mostly wanted
+        for a logging system - most users will not care about errors in
+        the logging system, they are more interested in application errors.
+        You could, however, replace this with a custom handler if you wish.
+        The record which was being processed is passed in to this method.
+        """
+        if raiseExceptions and sys.stderr:  # see issue 13807
+            ei = sys.exc_info()
+            try:
+                traceback.print_exception(ei[0], ei[1], ei[2],
+                                          None, sys.stderr)
+                sys.stderr.write('Logged from file %s, line %s\n' % (
+                                 record.filename, record.lineno))
+            except IOError:
+                pass    # see issue 5971
+            finally:
+                del ei
+
+class StreamHandler(Handler):
+    """
+    A handler class which writes logging records, appropriately formatted,
+    to a stream. Note that this class does not close the stream, as
+    sys.stdout or sys.stderr may be used.
+    """
+
+    def __init__(self, stream=None):
+        """
+        Initialize the handler.
+
+        If stream is not specified, sys.stderr is used.
+        """
+        Handler.__init__(self)
+        if stream is None:
+            stream = sys.stderr
+        self.stream = stream
+
+    def flush(self):
+        """
+        Flushes the stream.
+        """
+        self.acquire()
+        try:
+            if self.stream and hasattr(self.stream, "flush"):
+                self.stream.flush()
+        finally:
+            self.release()
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        If a formatter is specified, it is used to format the record.
+        The record is then written to the stream with a trailing newline.  If
+        exception information is present, it is formatted using
+        traceback.print_exception and appended to the stream.  If the stream
+        has an 'encoding' attribute, it is used to determine how to do the
+        output to the stream.
+        """
+        try:
+            msg = self.format(record)
+            stream = self.stream
+            fs = "%s\n"
+            if not _unicode: #if no unicode support...
+                stream.write(fs % msg)
+            else:
+                try:
+                    if (isinstance(msg, unicode) and
+                        getattr(stream, 'encoding', None)):
+                        ufs = fs.decode(stream.encoding)
+                        try:
+                            stream.write(ufs % msg)
+                        except UnicodeEncodeError:
+                            #Printing to terminals sometimes fails. For example,
+                            #with an encoding of 'cp1251', the above write will
+                            #work if written to a stream opened or wrapped by
+                            #the codecs module, but fail when writing to a
+                            #terminal even when the codepage is set to cp1251.
+                            #An extra encoding step seems to be needed.
+                            stream.write((ufs % msg).encode(stream.encoding))
+                    else:
+                        stream.write(fs % msg)
+                except UnicodeError:
+                    stream.write(fs % msg.encode("UTF-8"))
+            self.flush()
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            self.handleError(record)
+
+class FileHandler(StreamHandler):
+    """
+    A handler class which writes formatted logging records to disk files.
+    """
+    def __init__(self, filename, mode='a', encoding=None, delay=0):
+        """
+        Open the specified file and use it as the stream for logging.
+        """
+        #keep the absolute path, otherwise derived classes which use this
+        #may come a cropper when the current directory changes
+        if codecs is None:
+            encoding = None
+        self.baseFilename = os.path.abspath(filename)
+        self.mode = mode
+        self.encoding = encoding
+        if delay:
+            #We don't open the stream, but we still need to call the
+            #Handler constructor to set level, formatter, lock etc.
+            Handler.__init__(self)
+            self.stream = None
+        else:
+            StreamHandler.__init__(self, self._open())
+
+    def close(self):
+        """
+        Closes the stream.
+        """
+        self.acquire()
+        try:
+            if self.stream:
+                self.flush()
+                if hasattr(self.stream, "close"):
+                    self.stream.close()
+                StreamHandler.close(self)
+                self.stream = None
+        finally:
+            self.release()
+
+    def _open(self):
+        """
+        Open the current base file with the (original) mode and encoding.
+        Return the resulting stream.
+        """
+        if self.encoding is None:
+            stream = open(self.baseFilename, self.mode)
+        else:
+            stream = codecs.open(self.baseFilename, self.mode, self.encoding)
+        return stream
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        If the stream was not opened because 'delay' was specified in the
+        constructor, open it before calling the superclass's emit.
+        """
+        if self.stream is None:
+            self.stream = self._open()
+        StreamHandler.emit(self, record)
+
+#---------------------------------------------------------------------------
+#   Manager classes and functions
+#---------------------------------------------------------------------------
+
+class PlaceHolder(object):
+    """
+    PlaceHolder instances are used in the Manager logger hierarchy to take
+    the place of nodes for which no loggers have been defined. This class is
+    intended for internal use only and not as part of the public API.
+    """
+    def __init__(self, alogger):
+        """
+        Initialize with the specified logger being a child of this placeholder.
+        """
+        #self.loggers = [alogger]
+        self.loggerMap = { alogger : None }
+
+    def append(self, alogger):
+        """
+        Add the specified logger as a child of this placeholder.
+        """
+        #if alogger not in self.loggers:
+        if alogger not in self.loggerMap:
+            #self.loggers.append(alogger)
+            self.loggerMap[alogger] = None
+
+#
+#   Determine which class to use when instantiating loggers.
+#
+_loggerClass = None
+
+def setLoggerClass(klass):
+    """
+    Set the class to be used when instantiating a logger. The class should
+    define __init__() such that only a name argument is required, and the
+    __init__() should call Logger.__init__()
+    """
+    if klass != Logger:
+        if not issubclass(klass, Logger):
+            raise TypeError("logger not derived from logging.Logger: "
+                            + klass.__name__)
+    global _loggerClass
+    _loggerClass = klass
+
+def getLoggerClass():
+    """
+    Return the class to be used when instantiating a logger.
+    """
+
+    return _loggerClass
+
+class Manager(object):
+    """
+    There is [under normal circumstances] just one Manager instance, which
+    holds the hierarchy of loggers.
+    """
+    def __init__(self, rootnode):
+        """
+        Initialize the manager with the root node of the logger hierarchy.
+        """
+        self.root = rootnode
+        self.disable = 0
+        self.emittedNoHandlerWarning = 0
+        self.loggerDict = {}
+        self.loggerClass = None
+
+    def getLogger(self, name):
+        """
+        Get a logger with the specified name (channel name), creating it
+        if it doesn't yet exist. This name is a dot-separated hierarchical
+        name, such as "a", "a.b", "a.b.c" or similar.
+
+        If a PlaceHolder existed for the specified name [i.e. the logger
+        didn't exist but a child of it did], replace it with the created
+        logger and fix up the parent/child references which pointed to the
+        placeholder to now point to the logger.
+        """
+        rv = None
+        if not isinstance(name, basestring):
+            raise TypeError('A logger name must be string or Unicode')
+        if isinstance(name, unicode):
+            name = name.encode('utf-8')
+        _acquireLock()
+        try:
+            if name in self.loggerDict:
+                rv = self.loggerDict[name]
+                if isinstance(rv, PlaceHolder):
+                    ph = rv
+                    rv = (self.loggerClass or _loggerClass)(name)
+                    rv.manager = self
+                    self.loggerDict[name] = rv
+                    self._fixupChildren(ph, rv)
+                    self._fixupParents(rv)
+            else:
+                rv = (self.loggerClass or _loggerClass)(name)
+                rv.manager = self
+                self.loggerDict[name] = rv
+                self._fixupParents(rv)
+        finally:
+            _releaseLock()
+        return rv
+
+    def setLoggerClass(self, klass):
+        """
+        Set the class to be used when instantiating a logger with this Manager.
+        """
+        if klass != Logger:
+            if not issubclass(klass, Logger):
+                raise TypeError("logger not derived from logging.Logger: "
+                                + klass.__name__)
+        self.loggerClass = klass
+
+    def _fixupParents(self, alogger):
+        """
+        Ensure that there are either loggers or placeholders all the way
+        from the specified logger to the root of the logger hierarchy.
+        """
+        name = alogger.name
+        i = name.rfind(".")
+        rv = None
+        while (i > 0) and not rv:
+            substr = name[:i]
+            if substr not in self.loggerDict:
+                self.loggerDict[substr] = PlaceHolder(alogger)
+            else:
+                obj = self.loggerDict[substr]
+                if isinstance(obj, Logger):
+                    rv = obj
+                else:
+                    assert isinstance(obj, PlaceHolder)
+                    obj.append(alogger)
+            i = name.rfind(".", 0, i - 1)
+        if not rv:
+            rv = self.root
+        alogger.parent = rv
+
+    def _fixupChildren(self, ph, alogger):
+        """
+        Ensure that children of the placeholder ph are connected to the
+        specified logger.
+        """
+        name = alogger.name
+        namelen = len(name)
+        for c in ph.loggerMap.keys():
+            #The if means ... if not c.parent.name.startswith(nm)
+            if c.parent.name[:namelen] != name:
+                alogger.parent = c.parent
+                c.parent = alogger
+
+#---------------------------------------------------------------------------
+#   Logger classes and functions
+#---------------------------------------------------------------------------
+
+class Logger(Filterer):
+    """
+    Instances of the Logger class represent a single logging channel. A
+    "logging channel" indicates an area of an application. Exactly how an
+    "area" is defined is up to the application developer. Since an
+    application can have any number of areas, logging channels are identified
+    by a unique string. Application areas can be nested (e.g. an area
+    of "input processing" might include sub-areas "read CSV files", "read
+    XLS files" and "read Gnumeric files"). To cater for this natural nesting,
+    channel names are organized into a namespace hierarchy where levels are
+    separated by periods, much like the Java or Python package namespace. So
+    in the instance given above, channel names might be "input" for the upper
+    level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
+    There is no arbitrary limit to the depth of nesting.
+    """
+    def __init__(self, name, level=NOTSET):
+        """
+        Initialize the logger with a name and an optional level.
+        """
+        Filterer.__init__(self)
+        self.name = name
+        self.level = _checkLevel(level)
+        self.parent = None
+        self.propagate = 1
+        self.handlers = []
+        self.disabled = 0
+
+    def setLevel(self, level):
+        """
+        Set the logging level of this logger.
+        """
+        self.level = _checkLevel(level)
+
+    def debug(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'DEBUG'.
+
+        To pass exception information, use the keyword argument exc_info with
+        a true value, e.g.
+
+        logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
+        """
+        if self.isEnabledFor(DEBUG):
+            self._log(DEBUG, msg, args, **kwargs)
+
+    def info(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'INFO'.
+
+        To pass exception information, use the keyword argument exc_info with
+        a true value, e.g.
+
+        logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
+        """
+        if self.isEnabledFor(INFO):
+            self._log(INFO, msg, args, **kwargs)
+
+    def warning(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'WARNING'.
+
+        To pass exception information, use the keyword argument exc_info with
+        a true value, e.g.
+
+        logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
+        """
+        if self.isEnabledFor(WARNING):
+            self._log(WARNING, msg, args, **kwargs)
+
+    warn = warning
+
+    def error(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'ERROR'.
+
+        To pass exception information, use the keyword argument exc_info with
+        a true value, e.g.
+
+        logger.error("Houston, we have a %s", "major problem", exc_info=1)
+        """
+        if self.isEnabledFor(ERROR):
+            self._log(ERROR, msg, args, **kwargs)
+
+    def exception(self, msg, *args, **kwargs):
+        """
+        Convenience method for logging an ERROR with exception information.
+        """
+        kwargs['exc_info'] = 1
+        self.error(msg, *args, **kwargs)
+
+    def critical(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'CRITICAL'.
+
+        To pass exception information, use the keyword argument exc_info with
+        a true value, e.g.
+
+        logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
+        """
+        if self.isEnabledFor(CRITICAL):
+            self._log(CRITICAL, msg, args, **kwargs)
+
+    fatal = critical
+
+    def log(self, level, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with the integer severity 'level'.
+
+        To pass exception information, use the keyword argument exc_info with
+        a true value, e.g.
+
+        logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
+        """
+        if not isinstance(level, int):
+            if raiseExceptions:
+                raise TypeError("level must be an integer")
+            else:
+                return
+        if self.isEnabledFor(level):
+            self._log(level, msg, args, **kwargs)
+
+    def findCaller(self):
+        """
+        Find the stack frame of the caller so that we can note the source
+        file name, line number and function name.
+        """
+        f = currentframe()
+        #On some versions of IronPython, currentframe() returns None if
+        #IronPython isn't run with -X:Frames.
+        if f is not None:
+            f = f.f_back
+        rv = "(unknown file)", 0, "(unknown function)"
+        while hasattr(f, "f_code"):
+            co = f.f_code
+            filename = os.path.normcase(co.co_filename)
+            if filename == _srcfile:
+                f = f.f_back
+                continue
+            rv = (co.co_filename, f.f_lineno, co.co_name)
+            break
+        return rv
+
+    def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
+        """
+        A factory method which can be overridden in subclasses to create
+        specialized LogRecords.
+        """
+        rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
+        if extra is not None:
+            for key in extra:
+                if (key in ["message", "asctime"]) or (key in rv.__dict__):
+                    raise KeyError("Attempt to overwrite %r in LogRecord" % key)
+                rv.__dict__[key] = extra[key]
+        return rv
+
+    def _log(self, level, msg, args, exc_info=None, extra=None):
+        """
+        Low-level logging routine which creates a LogRecord and then calls
+        all the handlers of this logger to handle the record.
+        """
+        if _srcfile:
+            #IronPython doesn't track Python frames, so findCaller raises an
+            #exception on some versions of IronPython. We trap it here so that
+            #IronPython can use logging.
+            try:
+                fn, lno, func = self.findCaller()
+            except ValueError:
+                fn, lno, func = "(unknown file)", 0, "(unknown function)"
+        else:
+            fn, lno, func = "(unknown file)", 0, "(unknown function)"
+        if exc_info:
+            if not isinstance(exc_info, tuple):
+                exc_info = sys.exc_info()
+        record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
+        self.handle(record)
+
+    def handle(self, record):
+        """
+        Call the handlers for the specified record.
+
+        This method is used for unpickled records received from a socket, as
+        well as those created locally. Logger-level filtering is applied.
+        """
+        if (not self.disabled) and self.filter(record):
+            self.callHandlers(record)
+
+    def addHandler(self, hdlr):
+        """
+        Add the specified handler to this logger.
+        """
+        _acquireLock()
+        try:
+            if not (hdlr in self.handlers):
+                self.handlers.append(hdlr)
+        finally:
+            _releaseLock()
+
+    def removeHandler(self, hdlr):
+        """
+        Remove the specified handler from this logger.
+        """
+        _acquireLock()
+        try:
+            if hdlr in self.handlers:
+                self.handlers.remove(hdlr)
+        finally:
+            _releaseLock()
+
+    def callHandlers(self, record):
+        """
+        Pass a record to all relevant handlers.
+
+        Loop through all handlers for this logger and its parents in the
+        logger hierarchy. If no handler was found, output a one-off error
+        message to sys.stderr. Stop searching up the hierarchy whenever a
+        logger with the "propagate" attribute set to zero is found - that
+        will be the last logger whose handlers are called.
+        """
+        c = self
+        found = 0
+        while c:
+            for hdlr in c.handlers:
+                found = found + 1
+                if record.levelno >= hdlr.level:
+                    hdlr.handle(record)
+            if not c.propagate:
+                c = None    #break out
+            else:
+                c = c.parent
+        if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
+            sys.stderr.write("No handlers could be found for logger"
+                             " \"%s\"\n" % self.name)
+            self.manager.emittedNoHandlerWarning = 1
+
+    def getEffectiveLevel(self):
+        """
+        Get the effective level for this logger.
+
+        Loop through this logger and its parents in the logger hierarchy,
+        looking for a non-zero logging level. Return the first one found.
+        """
+        logger = self
+        while logger:
+            if logger.level:
+                return logger.level
+            logger = logger.parent
+        return NOTSET
+
+    def isEnabledFor(self, level):
+        """
+        Is this logger enabled for level 'level'?
+        """
+        if self.manager.disable >= level:
+            return 0
+        return level >= self.getEffectiveLevel()
+
+    def getChild(self, suffix):
+        """
+        Get a logger which is a descendant to this one.
+
+        This is a convenience method, such that
+
+        logging.getLogger('abc').getChild('def.ghi')
+
+        is the same as
+
+        logging.getLogger('abc.def.ghi')
+
+        It's useful, for example, when the parent logger is named using
+        __name__ rather than a literal string.
+        """
+        if self.root is not self:
+            suffix = '.'.join((self.name, suffix))
+        return self.manager.getLogger(suffix)
+
+class RootLogger(Logger):
+    """
+    A root logger is not that different to any other logger, except that
+    it must have a logging level and there is only one instance of it in
+    the hierarchy.
+    """
+    def __init__(self, level):
+        """
+        Initialize the logger with the name "root".
+        """
+        Logger.__init__(self, "root", level)
+
+_loggerClass = Logger
+
+class LoggerAdapter(object):
+    """
+    An adapter for loggers which makes it easier to specify contextual
+    information in logging output.
+    """
+
+    def __init__(self, logger, extra):
+        """
+        Initialize the adapter with a logger and a dict-like object which
+        provides contextual information. This constructor signature allows
+        easy stacking of LoggerAdapters, if so desired.
+
+        You can effectively pass keyword arguments as shown in the
+        following example:
+
+        adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
+        """
+        self.logger = logger
+        self.extra = extra
+
+    def process(self, msg, kwargs):
+        """
+        Process the logging message and keyword arguments passed in to
+        a logging call to insert contextual information. You can either
+        manipulate the message itself, the keyword args or both. Return
+        the message and kwargs modified (or not) to suit your needs.
+
+        Normally, you'll only need to override this one method in a
+        LoggerAdapter subclass for your specific needs.
+        """
+        kwargs["extra"] = self.extra
+        return msg, kwargs
+
+    def debug(self, msg, *args, **kwargs):
+        """
+        Delegate a debug call to the underlying logger, after adding
+        contextual information from this adapter instance.
+        """
+        msg, kwargs = self.process(msg, kwargs)
+        self.logger.debug(msg, *args, **kwargs)
+
+    def info(self, msg, *args, **kwargs):
+        """
+        Delegate an info call to the underlying logger, after adding
+        contextual information from this adapter instance.
+        """
+        msg, kwargs = self.process(msg, kwargs)
+        self.logger.info(msg, *args, **kwargs)
+
+    def warning(self, msg, *args, **kwargs):
+        """
+        Delegate a warning call to the underlying logger, after adding
+        contextual information from this adapter instance.
+        """
+        msg, kwargs = self.process(msg, kwargs)
+        self.logger.warning(msg, *args, **kwargs)
+
+    def error(self, msg, *args, **kwargs):
+        """
+        Delegate an error call to the underlying logger, after adding
+        contextual information from this adapter instance.
+        """
+        msg, kwargs = self.process(msg, kwargs)
+        self.logger.error(msg, *args, **kwargs)
+
+    def exception(self, msg, *args, **kwargs):
+        """
+        Delegate an exception call to the underlying logger, after adding
+        contextual information from this adapter instance.
+        """
+        msg, kwargs = self.process(msg, kwargs)
+        kwargs["exc_info"] = 1
+        self.logger.error(msg, *args, **kwargs)
+
+    def critical(self, msg, *args, **kwargs):
+        """
+        Delegate a critical call to the underlying logger, after adding
+        contextual information from this adapter instance.
+        """
+        msg, kwargs = self.process(msg, kwargs)
+        self.logger.critical(msg, *args, **kwargs)
+
+    def log(self, level, msg, *args, **kwargs):
+        """
+        Delegate a log call to the underlying logger, after adding
+        contextual information from this adapter instance.
+        """
+        msg, kwargs = self.process(msg, kwargs)
+        self.logger.log(level, msg, *args, **kwargs)
+
+    def isEnabledFor(self, level):
+        """
+        See if the underlying logger is enabled for the specified level.
+        """
+        return self.logger.isEnabledFor(level)
+
+root = RootLogger(WARNING)
+Logger.root = root
+Logger.manager = Manager(Logger.root)
+
+#---------------------------------------------------------------------------
+# Configuration classes and functions
+#---------------------------------------------------------------------------
+
+BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
+
+def basicConfig(**kwargs):
+    """
+    Do basic configuration for the logging system.
+
+    This function does nothing if the root logger already has handlers
+    configured. It is a convenience method intended for use by simple scripts
+    to do one-shot configuration of the logging package.
+
+    The default behaviour is to create a StreamHandler which writes to
+    sys.stderr, set a formatter using the BASIC_FORMAT format string, and
+    add the handler to the root logger.
+
+    A number of optional keyword arguments may be specified, which can alter
+    the default behaviour.
+
+    filename  Specifies that a FileHandler be created, using the specified
+              filename, rather than a StreamHandler.
+    filemode  Specifies the mode to open the file, if filename is specified
+              (if filemode is unspecified, it defaults to 'a').
+    format    Use the specified format string for the handler.
+    datefmt   Use the specified date/time format.
+    level     Set the root logger level to the specified level.
+    stream    Use the specified stream to initialize the StreamHandler. Note
+              that this argument is incompatible with 'filename' - if both
+              are present, 'stream' is ignored.
+
+    Note that you could specify a stream created using open(filename, mode)
+    rather than passing the filename and mode in. However, it should be
+    remembered that StreamHandler does not close its stream (since it may be
+    using sys.stdout or sys.stderr), whereas FileHandler closes its stream
+    when the handler is closed.
+    """
+    # Add thread safety in case someone mistakenly calls
+    # basicConfig() from multiple threads
+    _acquireLock()
+    try:
+        if len(root.handlers) == 0:
+            filename = kwargs.get("filename")
+            if filename:
+                mode = kwargs.get("filemode", 'a')
+                hdlr = FileHandler(filename, mode)
+            else:
+                stream = kwargs.get("stream")
+                hdlr = StreamHandler(stream)
+            fs = kwargs.get("format", BASIC_FORMAT)
+            dfs = kwargs.get("datefmt", None)
+            fmt = Formatter(fs, dfs)
+            hdlr.setFormatter(fmt)
+            root.addHandler(hdlr)
+            level = kwargs.get("level")
+            if level is not None:
+                root.setLevel(level)
+    finally:
+        _releaseLock()
+
+#---------------------------------------------------------------------------
+# Utility functions at module level.
+# Basically delegate everything to the root logger.
+#---------------------------------------------------------------------------
+
+def getLogger(name=None):
+    """
+    Return a logger with the specified name, creating it if necessary.
+
+    If no name is specified, return the root logger.
+    """
+    if name:
+        return Logger.manager.getLogger(name)
+    else:
+        return root
+
+#def getRootLogger():
+#    """
+#    Return the root logger.
+#
+#    Note that getLogger('') now does the same thing, so this function is
+#    deprecated and may disappear in the future.
+#    """
+#    return root
+
+def critical(msg, *args, **kwargs):
+    """
+    Log a message with severity 'CRITICAL' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    root.critical(msg, *args, **kwargs)
+
+fatal = critical
+
+def error(msg, *args, **kwargs):
+    """
+    Log a message with severity 'ERROR' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    root.error(msg, *args, **kwargs)
+
+def exception(msg, *args, **kwargs):
+    """
+    Log a message with severity 'ERROR' on the root logger,
+    with exception information.
+    """
+    kwargs['exc_info'] = 1
+    error(msg, *args, **kwargs)
+
+def warning(msg, *args, **kwargs):
+    """
+    Log a message with severity 'WARNING' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    root.warning(msg, *args, **kwargs)
+
+warn = warning
+
+def info(msg, *args, **kwargs):
+    """
+    Log a message with severity 'INFO' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    root.info(msg, *args, **kwargs)
+
+def debug(msg, *args, **kwargs):
+    """
+    Log a message with severity 'DEBUG' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    root.debug(msg, *args, **kwargs)
+
+def log(level, msg, *args, **kwargs):
+    """
+    Log 'msg % args' with the integer severity 'level' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    root.log(level, msg, *args, **kwargs)
+
+def disable(level):
+    """
+    Disable all logging calls of severity 'level' and below.
+    """
+    root.manager.disable = level
+
+def shutdown(handlerList=_handlerList):
+    """
+    Perform any cleanup actions in the logging system (e.g. flushing
+    buffers).
+
+    Should be called at application exit.
+    """
+    for wr in reversed(handlerList[:]):
+        #errors might occur, for example, if files are locked
+        #we just ignore them if raiseExceptions is not set
+        try:
+            h = wr()
+            if h:
+                try:
+                    h.acquire()
+                    h.flush()
+                    h.close()
+                except (IOError, ValueError):
+                    # Ignore errors which might be caused
+                    # because handlers have been closed but
+                    # references to them are still around at
+                    # application exit.
+                    pass
+                finally:
+                    h.release()
+        except:
+            if raiseExceptions:
+                raise
+            #else, swallow
+
+#Let's try and shutdown automatically on application exit...
+import atexit
+atexit.register(shutdown)
+
+# Null handler
+
+class NullHandler(Handler):
+    """
+    This handler does nothing. It's intended to be used to avoid the
+    "No handlers could be found for logger XXX" one-off warning. This is
+    important for library code, which may contain code to log events. If a user
+    of the library does not configure logging, the one-off warning might be
+    produced; to avoid this, the library developer simply needs to instantiate
+    a NullHandler and add it to the top-level logger of the library module or
+    package.
+    """
+    def handle(self, record):
+        pass
+
+    def emit(self, record):
+        pass
+
+    def createLock(self):
+        self.lock = None
+
+# Warnings integration
+
+_warnings_showwarning = None
+
+def _showwarning(message, category, filename, lineno, file=None, line=None):
+    """
+    Implementation of showwarnings which redirects to logging, which will first
+    check to see if the file parameter is None. If a file is specified, it will
+    delegate to the original warnings implementation of showwarning. Otherwise,
+    it will call warnings.formatwarning and will log the resulting string to a
+    warnings logger named "py.warnings" with level logging.WARNING.
+    """
+    if file is not None:
+        if _warnings_showwarning is not None:
+            _warnings_showwarning(message, category, filename, lineno, file, line)
+    else:
+        s = warnings.formatwarning(message, category, filename, lineno, line)
+        logger = getLogger("py.warnings")
+        if not logger.handlers:
+            logger.addHandler(NullHandler())
+        logger.warning("%s", s)
+
+def captureWarnings(capture):
+    """
+    If capture is true, redirect all warnings to the logging package.
+    If capture is False, ensure that warnings are not redirected to logging
+    but to their original destinations.
+    """
+    global _warnings_showwarning
+    if capture:
+        if _warnings_showwarning is None:
+            _warnings_showwarning = warnings.showwarning
+            warnings.showwarning = _showwarning
+    else:
+        if _warnings_showwarning is not None:
+            warnings.showwarning = _warnings_showwarning
+            _warnings_showwarning = None
diff --git a/src/main/resources/PythonLibs/logging/config.py b/src/main/resources/PythonLibs/logging/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..6840590709f3dc536219a7e9b4e9a37a16ff63db
--- /dev/null
+++ b/src/main/resources/PythonLibs/logging/config.py
@@ -0,0 +1,909 @@
+# Copyright 2001-2010 by Vinay Sajip. All Rights Reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of Vinay Sajip
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+Configuration functions for the logging package for Python. The core package
+is based on PEP 282 and comments thereto in comp.lang.python, and influenced
+by Apache's log4j system.
+
+Copyright (C) 2001-2010 Vinay Sajip. All Rights Reserved.
+
+To use, simply 'import logging' and log away!
+"""
+
+import sys, logging, logging.handlers, socket, struct, os, traceback, re
+import types, cStringIO
+
+try:
+    import thread
+    import threading
+except ImportError:
+    thread = None
+
+from SocketServer import ThreadingTCPServer, StreamRequestHandler
+
+
+DEFAULT_LOGGING_CONFIG_PORT = 9030
+
+if sys.platform == "win32":
+    RESET_ERROR = 10054   #WSAECONNRESET
+else:
+    RESET_ERROR = 104     #ECONNRESET
+
+#
+#   The following code implements a socket listener for on-the-fly
+#   reconfiguration of logging.
+#
+#   _listener holds the server object doing the listening
+_listener = None
+
+def fileConfig(fname, defaults=None, disable_existing_loggers=True):
+    """
+    Read the logging configuration from a ConfigParser-format file.
+
+    This can be called several times from an application, allowing an end user
+    the ability to select from various pre-canned configurations (if the
+    developer provides a mechanism to present the choices and load the chosen
+    configuration).
+    """
+    import ConfigParser
+
+    cp = ConfigParser.ConfigParser(defaults)
+    if hasattr(fname, 'readline'):
+        cp.readfp(fname)
+    else:
+        cp.read(fname)
+
+    formatters = _create_formatters(cp)
+
+    # critical section
+    logging._acquireLock()
+    try:
+        logging._handlers.clear()
+        del logging._handlerList[:]
+        # Handlers add themselves to logging._handlers
+        handlers = _install_handlers(cp, formatters)
+        _install_loggers(cp, handlers, disable_existing_loggers)
+    finally:
+        logging._releaseLock()
+
+
+def _resolve(name):
+    """Resolve a dotted name to a global object."""
+    name = name.split('.')
+    used = name.pop(0)
+    found = __import__(used)
+    for n in name:
+        used = used + '.' + n
+        try:
+            found = getattr(found, n)
+        except AttributeError:
+            __import__(used)
+            found = getattr(found, n)
+    return found
+
+def _strip_spaces(alist):
+    return map(lambda x: x.strip(), alist)
+
+def _encoded(s):
+    return s if isinstance(s, str) else s.encode('utf-8')
+
+def _create_formatters(cp):
+    """Create and return formatters"""
+    flist = cp.get("formatters", "keys")
+    if not len(flist):
+        return {}
+    flist = flist.split(",")
+    flist = _strip_spaces(flist)
+    formatters = {}
+    for form in flist:
+        sectname = "formatter_%s" % form
+        opts = cp.options(sectname)
+        if "format" in opts:
+            fs = cp.get(sectname, "format", 1)
+        else:
+            fs = None
+        if "datefmt" in opts:
+            dfs = cp.get(sectname, "datefmt", 1)
+        else:
+            dfs = None
+        c = logging.Formatter
+        if "class" in opts:
+            class_name = cp.get(sectname, "class")
+            if class_name:
+                c = _resolve(class_name)
+        f = c(fs, dfs)
+        formatters[form] = f
+    return formatters
+
+
+def _install_handlers(cp, formatters):
+    """Install and return handlers"""
+    hlist = cp.get("handlers", "keys")
+    if not len(hlist):
+        return {}
+    hlist = hlist.split(",")
+    hlist = _strip_spaces(hlist)
+    handlers = {}
+    fixups = [] #for inter-handler references
+    for hand in hlist:
+        sectname = "handler_%s" % hand
+        klass = cp.get(sectname, "class")
+        opts = cp.options(sectname)
+        if "formatter" in opts:
+            fmt = cp.get(sectname, "formatter")
+        else:
+            fmt = ""
+        try:
+            klass = eval(klass, vars(logging))
+        except (AttributeError, NameError):
+            klass = _resolve(klass)
+        args = cp.get(sectname, "args")
+        args = eval(args, vars(logging))
+        h = klass(*args)
+        if "level" in opts:
+            level = cp.get(sectname, "level")
+            h.setLevel(logging._levelNames[level])
+        if len(fmt):
+            h.setFormatter(formatters[fmt])
+        if issubclass(klass, logging.handlers.MemoryHandler):
+            if "target" in opts:
+                target = cp.get(sectname,"target")
+            else:
+                target = ""
+            if len(target): #the target handler may not be loaded yet, so keep for later...
+                fixups.append((h, target))
+        handlers[hand] = h
+    #now all handlers are loaded, fixup inter-handler references...
+    for h, t in fixups:
+        h.setTarget(handlers[t])
+    return handlers
+
+
+def _install_loggers(cp, handlers, disable_existing_loggers):
+    """Create and install loggers"""
+
+    # configure the root first
+    llist = cp.get("loggers", "keys")
+    llist = llist.split(",")
+    llist = list(map(lambda x: x.strip(), llist))
+    llist.remove("root")
+    sectname = "logger_root"
+    root = logging.root
+    log = root
+    opts = cp.options(sectname)
+    if "level" in opts:
+        level = cp.get(sectname, "level")
+        log.setLevel(logging._levelNames[level])
+    for h in root.handlers[:]:
+        root.removeHandler(h)
+    hlist = cp.get(sectname, "handlers")
+    if len(hlist):
+        hlist = hlist.split(",")
+        hlist = _strip_spaces(hlist)
+        for hand in hlist:
+            log.addHandler(handlers[hand])
+
+    #and now the others...
+    #we don't want to lose the existing loggers,
+    #since other threads may have pointers to them.
+    #existing is set to contain all existing loggers,
+    #and as we go through the new configuration we
+    #remove any which are configured. At the end,
+    #what's left in existing is the set of loggers
+    #which were in the previous configuration but
+    #which are not in the new configuration.
+    existing = list(root.manager.loggerDict.keys())
+    #The list needs to be sorted so that we can
+    #avoid disabling child loggers of explicitly
+    #named loggers. With a sorted list it is easier
+    #to find the child loggers.
+    existing.sort()
+    #We'll keep the list of existing loggers
+    #which are children of named loggers here...
+    child_loggers = []
+    #now set up the new ones...
+    for log in llist:
+        sectname = "logger_%s" % log
+        qn = cp.get(sectname, "qualname")
+        opts = cp.options(sectname)
+        if "propagate" in opts:
+            propagate = cp.getint(sectname, "propagate")
+        else:
+            propagate = 1
+        logger = logging.getLogger(qn)
+        if qn in existing:
+            i = existing.index(qn) + 1 # start with the entry after qn
+            prefixed = qn + "."
+            pflen = len(prefixed)
+            num_existing = len(existing)
+            while i < num_existing:
+                if existing[i][:pflen] == prefixed:
+                    child_loggers.append(existing[i])
+                i += 1
+            existing.remove(qn)
+        if "level" in opts:
+            level = cp.get(sectname, "level")
+            logger.setLevel(logging._levelNames[level])
+        for h in logger.handlers[:]:
+            logger.removeHandler(h)
+        logger.propagate = propagate
+        logger.disabled = 0
+        hlist = cp.get(sectname, "handlers")
+        if len(hlist):
+            hlist = hlist.split(",")
+            hlist = _strip_spaces(hlist)
+            for hand in hlist:
+                logger.addHandler(handlers[hand])
+
+    #Disable any old loggers. There's no point deleting
+    #them as other threads may continue to hold references
+    #and by disabling them, you stop them doing any logging.
+    #However, don't disable children of named loggers, as that's
+    #probably not what was intended by the user.
+    for log in existing:
+        logger = root.manager.loggerDict[log]
+        if log in child_loggers:
+            logger.level = logging.NOTSET
+            logger.handlers = []
+            logger.propagate = 1
+        elif disable_existing_loggers:
+            logger.disabled = 1
+
+
+
+IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I)
+
+
+def valid_ident(s):
+    m = IDENTIFIER.match(s)
+    if not m:
+        raise ValueError('Not a valid Python identifier: %r' % s)
+    return True
+
+
+# The ConvertingXXX classes are wrappers around standard Python containers,
+# and they serve to convert any suitable values in the container. The
+# conversion converts base dicts, lists and tuples to their wrapped
+# equivalents, whereas strings which match a conversion format are converted
+# appropriately.
+#
+# Each wrapper should have a configurator attribute holding the actual
+# configurator to use for conversion.
+
+class ConvertingDict(dict):
+    """A converting dictionary wrapper."""
+
+    def __getitem__(self, key):
+        value = dict.__getitem__(self, key)
+        result = self.configurator.convert(value)
+        #If the converted value is different, save for next time
+        if value is not result:
+            self[key] = result
+            if type(result) in (ConvertingDict, ConvertingList,
+                                ConvertingTuple):
+                result.parent = self
+                result.key = key
+        return result
+
+    def get(self, key, default=None):
+        value = dict.get(self, key, default)
+        result = self.configurator.convert(value)
+        #If the converted value is different, save for next time
+        if value is not result:
+            self[key] = result
+            if type(result) in (ConvertingDict, ConvertingList,
+                                ConvertingTuple):
+                result.parent = self
+                result.key = key
+        return result
+
+    def pop(self, key, default=None):
+        value = dict.pop(self, key, default)
+        result = self.configurator.convert(value)
+        if value is not result:
+            if type(result) in (ConvertingDict, ConvertingList,
+                                ConvertingTuple):
+                result.parent = self
+                result.key = key
+        return result
+
+class ConvertingList(list):
+    """A converting list wrapper."""
+    def __getitem__(self, key):
+        value = list.__getitem__(self, key)
+        result = self.configurator.convert(value)
+        #If the converted value is different, save for next time
+        if value is not result:
+            self[key] = result
+            if type(result) in (ConvertingDict, ConvertingList,
+                                ConvertingTuple):
+                result.parent = self
+                result.key = key
+        return result
+
+    def pop(self, idx=-1):
+        value = list.pop(self, idx)
+        result = self.configurator.convert(value)
+        if value is not result:
+            if type(result) in (ConvertingDict, ConvertingList,
+                                ConvertingTuple):
+                result.parent = self
+        return result
+
+class ConvertingTuple(tuple):
+    """A converting tuple wrapper."""
+    def __getitem__(self, key):
+        value = tuple.__getitem__(self, key)
+        result = self.configurator.convert(value)
+        if value is not result:
+            if type(result) in (ConvertingDict, ConvertingList,
+                                ConvertingTuple):
+                result.parent = self
+                result.key = key
+        return result
+
+class BaseConfigurator(object):
+    """
+    The configurator base class which defines some useful defaults.
+    """
+
+    CONVERT_PATTERN = re.compile(r'^(?P<prefix>[a-z]+)://(?P<suffix>.*)$')
+
+    WORD_PATTERN = re.compile(r'^\s*(\w+)\s*')
+    DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*')
+    INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*')
+    DIGIT_PATTERN = re.compile(r'^\d+$')
+
+    value_converters = {
+        'ext' : 'ext_convert',
+        'cfg' : 'cfg_convert',
+    }
+
+    # We might want to use a different one, e.g. importlib
+    importer = __import__
+
+    def __init__(self, config):
+        self.config = ConvertingDict(config)
+        self.config.configurator = self
+
+    def resolve(self, s):
+        """
+        Resolve strings to objects using standard import and attribute
+        syntax.
+        """
+        name = s.split('.')
+        used = name.pop(0)
+        try:
+            found = self.importer(used)
+            for frag in name:
+                used += '.' + frag
+                try:
+                    found = getattr(found, frag)
+                except AttributeError:
+                    self.importer(used)
+                    found = getattr(found, frag)
+            return found
+        except ImportError:
+            e, tb = sys.exc_info()[1:]
+            v = ValueError('Cannot resolve %r: %s' % (s, e))
+            v.__cause__, v.__traceback__ = e, tb
+            raise v
+
+    def ext_convert(self, value):
+        """Default converter for the ext:// protocol."""
+        return self.resolve(value)
+
+    def cfg_convert(self, value):
+        """Default converter for the cfg:// protocol."""
+        rest = value
+        m = self.WORD_PATTERN.match(rest)
+        if m is None:
+            raise ValueError("Unable to convert %r" % value)
+        else:
+            rest = rest[m.end():]
+            d = self.config[m.groups()[0]]
+            #print d, rest
+            while rest:
+                m = self.DOT_PATTERN.match(rest)
+                if m:
+                    d = d[m.groups()[0]]
+                else:
+                    m = self.INDEX_PATTERN.match(rest)
+                    if m:
+                        idx = m.groups()[0]
+                        if not self.DIGIT_PATTERN.match(idx):
+                            d = d[idx]
+                        else:
+                            try:
+                                n = int(idx) # try as number first (most likely)
+                                d = d[n]
+                            except TypeError:
+                                d = d[idx]
+                if m:
+                    rest = rest[m.end():]
+                else:
+                    raise ValueError('Unable to convert '
+                                     '%r at %r' % (value, rest))
+        #rest should be empty
+        return d
+
+    def convert(self, value):
+        """
+        Convert values to an appropriate type. dicts, lists and tuples are
+        replaced by their converting alternatives. Strings are checked to
+        see if they have a conversion format and are converted if they do.
+        """
+        if not isinstance(value, ConvertingDict) and isinstance(value, dict):
+            value = ConvertingDict(value)
+            value.configurator = self
+        elif not isinstance(value, ConvertingList) and isinstance(value, list):
+            value = ConvertingList(value)
+            value.configurator = self
+        elif not isinstance(value, ConvertingTuple) and\
+                 isinstance(value, tuple):
+            value = ConvertingTuple(value)
+            value.configurator = self
+        elif isinstance(value, basestring): # str for py3k
+            m = self.CONVERT_PATTERN.match(value)
+            if m:
+                d = m.groupdict()
+                prefix = d['prefix']
+                converter = self.value_converters.get(prefix, None)
+                if converter:
+                    suffix = d['suffix']
+                    converter = getattr(self, converter)
+                    value = converter(suffix)
+        return value
+
+    def configure_custom(self, config):
+        """Configure an object with a user-supplied factory."""
+        c = config.pop('()')
+        if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType:
+            c = self.resolve(c)
+        props = config.pop('.', None)
+        # Check for valid identifiers
+        kwargs = dict([(k, config[k]) for k in config if valid_ident(k)])
+        result = c(**kwargs)
+        if props:
+            for name, value in props.items():
+                setattr(result, name, value)
+        return result
+
+    def as_tuple(self, value):
+        """Utility function which converts lists to tuples."""
+        if isinstance(value, list):
+            value = tuple(value)
+        return value
+
+class DictConfigurator(BaseConfigurator):
+    """
+    Configure logging using a dictionary-like object to describe the
+    configuration.
+    """
+
+    def configure(self):
+        """Do the configuration."""
+
+        config = self.config
+        if 'version' not in config:
+            raise ValueError("dictionary doesn't specify a version")
+        if config['version'] != 1:
+            raise ValueError("Unsupported version: %s" % config['version'])
+        incremental = config.pop('incremental', False)
+        EMPTY_DICT = {}
+        logging._acquireLock()
+        try:
+            if incremental:
+                handlers = config.get('handlers', EMPTY_DICT)
+                for name in handlers:
+                    if name not in logging._handlers:
+                        raise ValueError('No handler found with '
+                                         'name %r'  % name)
+                    else:
+                        try:
+                            handler = logging._handlers[name]
+                            handler_config = handlers[name]
+                            level = handler_config.get('level', None)
+                            if level:
+                                handler.setLevel(logging._checkLevel(level))
+                        except StandardError, e:
+                            raise ValueError('Unable to configure handler '
+                                             '%r: %s' % (name, e))
+                loggers = config.get('loggers', EMPTY_DICT)
+                for name in loggers:
+                    try:
+                        self.configure_logger(name, loggers[name], True)
+                    except StandardError, e:
+                        raise ValueError('Unable to configure logger '
+                                         '%r: %s' % (name, e))
+                root = config.get('root', None)
+                if root:
+                    try:
+                        self.configure_root(root, True)
+                    except StandardError, e:
+                        raise ValueError('Unable to configure root '
+                                         'logger: %s' % e)
+            else:
+                disable_existing = config.pop('disable_existing_loggers', True)
+
+                logging._handlers.clear()
+                del logging._handlerList[:]
+
+                # Do formatters first - they don't refer to anything else
+                formatters = config.get('formatters', EMPTY_DICT)
+                for name in formatters:
+                    try:
+                        formatters[name] = self.configure_formatter(
+                                                            formatters[name])
+                    except StandardError, e:
+                        raise ValueError('Unable to configure '
+                                         'formatter %r: %s' % (name, e))
+                # Next, do filters - they don't refer to anything else, either
+                filters = config.get('filters', EMPTY_DICT)
+                for name in filters:
+                    try:
+                        filters[name] = self.configure_filter(filters[name])
+                    except StandardError, e:
+                        raise ValueError('Unable to configure '
+                                         'filter %r: %s' % (name, e))
+
+                # Next, do handlers - they refer to formatters and filters
+                # As handlers can refer to other handlers, sort the keys
+                # to allow a deterministic order of configuration
+                handlers = config.get('handlers', EMPTY_DICT)
+                for name in sorted(handlers):
+                    try:
+                        handler = self.configure_handler(handlers[name])
+                        handler.name = name
+                        handlers[name] = handler
+                    except StandardError, e:
+                        raise ValueError('Unable to configure handler '
+                                         '%r: %s' % (name, e))
+                # Next, do loggers - they refer to handlers and filters
+
+                #we don't want to lose the existing loggers,
+                #since other threads may have pointers to them.
+                #existing is set to contain all existing loggers,
+                #and as we go through the new configuration we
+                #remove any which are configured. At the end,
+                #what's left in existing is the set of loggers
+                #which were in the previous configuration but
+                #which are not in the new configuration.
+                root = logging.root
+                existing = root.manager.loggerDict.keys()
+                #The list needs to be sorted so that we can
+                #avoid disabling child loggers of explicitly
+                #named loggers. With a sorted list it is easier
+                #to find the child loggers.
+                existing.sort()
+                #We'll keep the list of existing loggers
+                #which are children of named loggers here...
+                child_loggers = []
+                #now set up the new ones...
+                loggers = config.get('loggers', EMPTY_DICT)
+                for name in loggers:
+                    name = _encoded(name)
+                    if name in existing:
+                        i = existing.index(name)
+                        prefixed = name + "."
+                        pflen = len(prefixed)
+                        num_existing = len(existing)
+                        i = i + 1 # look at the entry after name
+                        while (i < num_existing) and\
+                              (existing[i][:pflen] == prefixed):
+                            child_loggers.append(existing[i])
+                            i = i + 1
+                        existing.remove(name)
+                    try:
+                        self.configure_logger(name, loggers[name])
+                    except StandardError, e:
+                        raise ValueError('Unable to configure logger '
+                                         '%r: %s' % (name, e))
+
+                #Disable any old loggers. There's no point deleting
+                #them as other threads may continue to hold references
+                #and by disabling them, you stop them doing any logging.
+                #However, don't disable children of named loggers, as that's
+                #probably not what was intended by the user.
+                for log in existing:
+                    logger = root.manager.loggerDict[log]
+                    if log in child_loggers:
+                        logger.level = logging.NOTSET
+                        logger.handlers = []
+                        logger.propagate = True
+                    elif disable_existing:
+                        logger.disabled = True
+
+                # And finally, do the root logger
+                root = config.get('root', None)
+                if root:
+                    try:
+                        self.configure_root(root)
+                    except StandardError, e:
+                        raise ValueError('Unable to configure root '
+                                         'logger: %s' % e)
+        finally:
+            logging._releaseLock()
+
+    def configure_formatter(self, config):
+        """Configure a formatter from a dictionary."""
+        if '()' in config:
+            factory = config['()'] # for use in exception handler
+            try:
+                result = self.configure_custom(config)
+            except TypeError, te:
+                if "'format'" not in str(te):
+                    raise
+                #Name of parameter changed from fmt to format.
+                #Retry with old name.
+                #This is so that code can be used with older Python versions
+                #(e.g. by Django)
+                config['fmt'] = config.pop('format')
+                config['()'] = factory
+                result = self.configure_custom(config)
+        else:
+            fmt = config.get('format', None)
+            dfmt = config.get('datefmt', None)
+            result = logging.Formatter(fmt, dfmt)
+        return result
+
+    def configure_filter(self, config):
+        """Configure a filter from a dictionary."""
+        if '()' in config:
+            result = self.configure_custom(config)
+        else:
+            name = config.get('name', '')
+            result = logging.Filter(name)
+        return result
+
+    def add_filters(self, filterer, filters):
+        """Add filters to a filterer from a list of names."""
+        for f in filters:
+            try:
+                filterer.addFilter(self.config['filters'][f])
+            except StandardError, e:
+                raise ValueError('Unable to add filter %r: %s' % (f, e))
+
+    def configure_handler(self, config):
+        """Configure a handler from a dictionary."""
+        formatter = config.pop('formatter', None)
+        if formatter:
+            try:
+                formatter = self.config['formatters'][formatter]
+            except StandardError, e:
+                raise ValueError('Unable to set formatter '
+                                 '%r: %s' % (formatter, e))
+        level = config.pop('level', None)
+        filters = config.pop('filters', None)
+        if '()' in config:
+            c = config.pop('()')
+            if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType:
+                c = self.resolve(c)
+            factory = c
+        else:
+            klass = self.resolve(config.pop('class'))
+            #Special case for handler which refers to another handler
+            if issubclass(klass, logging.handlers.MemoryHandler) and\
+                'target' in config:
+                try:
+                    config['target'] = self.config['handlers'][config['target']]
+                except StandardError, e:
+                    raise ValueError('Unable to set target handler '
+                                     '%r: %s' % (config['target'], e))
+            elif issubclass(klass, logging.handlers.SMTPHandler) and\
+                'mailhost' in config:
+                config['mailhost'] = self.as_tuple(config['mailhost'])
+            elif issubclass(klass, logging.handlers.SysLogHandler) and\
+                'address' in config:
+                config['address'] = self.as_tuple(config['address'])
+            factory = klass
+        kwargs = dict([(k, config[k]) for k in config if valid_ident(k)])
+        try:
+            result = factory(**kwargs)
+        except TypeError, te:
+            if "'stream'" not in str(te):
+                raise
+            #The argument name changed from strm to stream
+            #Retry with old name.
+            #This is so that code can be used with older Python versions
+            #(e.g. by Django)
+            kwargs['strm'] = kwargs.pop('stream')
+            result = factory(**kwargs)
+        if formatter:
+            result.setFormatter(formatter)
+        if level is not None:
+            result.setLevel(logging._checkLevel(level))
+        if filters:
+            self.add_filters(result, filters)
+        return result
+
+    def add_handlers(self, logger, handlers):
+        """Add handlers to a logger from a list of names."""
+        for h in handlers:
+            try:
+                logger.addHandler(self.config['handlers'][h])
+            except StandardError, e:
+                raise ValueError('Unable to add handler %r: %s' % (h, e))
+
+    def common_logger_config(self, logger, config, incremental=False):
+        """
+        Perform configuration which is common to root and non-root loggers.
+        """
+        level = config.get('level', None)
+        if level is not None:
+            logger.setLevel(logging._checkLevel(level))
+        if not incremental:
+            #Remove any existing handlers
+            for h in logger.handlers[:]:
+                logger.removeHandler(h)
+            handlers = config.get('handlers', None)
+            if handlers:
+                self.add_handlers(logger, handlers)
+            filters = config.get('filters', None)
+            if filters:
+                self.add_filters(logger, filters)
+
+    def configure_logger(self, name, config, incremental=False):
+        """Configure a non-root logger from a dictionary."""
+        logger = logging.getLogger(name)
+        self.common_logger_config(logger, config, incremental)
+        propagate = config.get('propagate', None)
+        if propagate is not None:
+            logger.propagate = propagate
+
+    def configure_root(self, config, incremental=False):
+        """Configure a root logger from a dictionary."""
+        root = logging.getLogger()
+        self.common_logger_config(root, config, incremental)
+
+dictConfigClass = DictConfigurator
+
+def dictConfig(config):
+    """Configure logging using a dictionary."""
+    dictConfigClass(config).configure()
+
+
+def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
+    """
+    Start up a socket server on the specified port, and listen for new
+    configurations.
+
+    These will be sent as a file suitable for processing by fileConfig().
+    Returns a Thread object on which you can call start() to start the server,
+    and which you can join() when appropriate. To stop the server, call
+    stopListening().
+    """
+    if not thread:
+        raise NotImplementedError("listen() needs threading to work")
+
+    class ConfigStreamHandler(StreamRequestHandler):
+        """
+        Handler for a logging configuration request.
+
+        It expects a completely new logging configuration and uses fileConfig
+        to install it.
+        """
+        def handle(self):
+            """
+            Handle a request.
+
+            Each request is expected to be a 4-byte length, packed using
+            struct.pack(">L", n), followed by the config file.
+            Uses fileConfig() to do the grunt work.
+            """
+            import tempfile
+            try:
+                conn = self.connection
+                chunk = conn.recv(4)
+                if len(chunk) == 4:
+                    slen = struct.unpack(">L", chunk)[0]
+                    chunk = self.connection.recv(slen)
+                    while len(chunk) < slen:
+                        chunk = chunk + conn.recv(slen - len(chunk))
+                    try:
+                        import json
+                        d =json.loads(chunk)
+                        assert isinstance(d, dict)
+                        dictConfig(d)
+                    except:
+                        #Apply new configuration.
+
+                        file = cStringIO.StringIO(chunk)
+                        try:
+                            fileConfig(file)
+                        except (KeyboardInterrupt, SystemExit):
+                            raise
+                        except:
+                            traceback.print_exc()
+                    if self.server.ready:
+                        self.server.ready.set()
+            except socket.error, e:
+                if not isinstance(e.args, tuple):
+                    raise
+                else:
+                    errcode = e.args[0]
+                    if errcode != RESET_ERROR:
+                        raise
+
+    class ConfigSocketReceiver(ThreadingTCPServer):
+        """
+        A simple TCP socket-based logging config receiver.
+        """
+
+        allow_reuse_address = 1
+
+        def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
+                     handler=None, ready=None):
+            ThreadingTCPServer.__init__(self, (host, port), handler)
+            logging._acquireLock()
+            self.abort = 0
+            logging._releaseLock()
+            self.timeout = 1
+            self.ready = ready
+
+        def serve_until_stopped(self):
+            if sys.platform.startswith('java'):
+                from select import cpython_compatible_select as select
+            else:
+                from select import select
+            abort = 0
+            while not abort:
+                rd, wr, ex = select([self.socket.fileno()],
+                                     [], [],
+                                     self.timeout)
+                if rd:
+                    self.handle_request()
+                logging._acquireLock()
+                abort = self.abort
+                logging._releaseLock()
+            self.socket.close()
+
+    class Server(threading.Thread):
+
+        def __init__(self, rcvr, hdlr, port):
+            super(Server, self).__init__()
+            self.rcvr = rcvr
+            self.hdlr = hdlr
+            self.port = port
+            self.ready = threading.Event()
+
+        def run(self):
+            server = self.rcvr(port=self.port, handler=self.hdlr,
+                               ready=self.ready)
+            if self.port == 0:
+                self.port = server.server_address[1]
+            self.ready.set()
+            global _listener
+            logging._acquireLock()
+            _listener = server
+            logging._releaseLock()
+            server.serve_until_stopped()
+
+    return Server(ConfigSocketReceiver, ConfigStreamHandler, port)
+
+def stopListening():
+    """
+    Stop the listening server which was created with a call to listen().
+    """
+    global _listener
+    logging._acquireLock()
+    try:
+        if _listener:
+            _listener.abort = 1
+            _listener = None
+    finally:
+        logging._releaseLock()
diff --git a/src/main/resources/PythonLibs/logging/handlers.py b/src/main/resources/PythonLibs/logging/handlers.py
new file mode 100644
index 0000000000000000000000000000000000000000..26dfe4a1d18520c46d86e4d54c84d07e4ba6b83f
--- /dev/null
+++ b/src/main/resources/PythonLibs/logging/handlers.py
@@ -0,0 +1,1198 @@
+# Copyright 2001-2012 by Vinay Sajip. All Rights Reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of Vinay Sajip
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+Additional handlers for the logging package for Python. The core package is
+based on PEP 282 and comments thereto in comp.lang.python.
+
+Copyright (C) 2001-2012 Vinay Sajip. All Rights Reserved.
+
+To use, simply 'import logging.handlers' and log away!
+"""
+
+import errno, logging, socket, os, cPickle, struct, time, re
+from stat import ST_DEV, ST_INO, ST_MTIME
+
+try:
+    import codecs
+except ImportError:
+    codecs = None
+try:
+    unicode
+    _unicode = True
+except NameError:
+    _unicode = False
+
+#
+# Some constants...
+#
+
+DEFAULT_TCP_LOGGING_PORT    = 9020
+DEFAULT_UDP_LOGGING_PORT    = 9021
+DEFAULT_HTTP_LOGGING_PORT   = 9022
+DEFAULT_SOAP_LOGGING_PORT   = 9023
+SYSLOG_UDP_PORT             = 514
+SYSLOG_TCP_PORT             = 514
+
+_MIDNIGHT = 24 * 60 * 60  # number of seconds in a day
+
+class BaseRotatingHandler(logging.FileHandler):
+    """
+    Base class for handlers that rotate log files at a certain point.
+    Not meant to be instantiated directly.  Instead, use RotatingFileHandler
+    or TimedRotatingFileHandler.
+    """
+    def __init__(self, filename, mode, encoding=None, delay=0):
+        """
+        Use the specified filename for streamed logging
+        """
+        if codecs is None:
+            encoding = None
+        logging.FileHandler.__init__(self, filename, mode, encoding, delay)
+        self.mode = mode
+        self.encoding = encoding
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        Output the record to the file, catering for rollover as described
+        in doRollover().
+        """
+        try:
+            if self.shouldRollover(record):
+                self.doRollover()
+            logging.FileHandler.emit(self, record)
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            self.handleError(record)
+
+class RotatingFileHandler(BaseRotatingHandler):
+    """
+    Handler for logging to a set of files, which switches from one file
+    to the next when the current file reaches a certain size.
+    """
+    def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0):
+        """
+        Open the specified file and use it as the stream for logging.
+
+        By default, the file grows indefinitely. You can specify particular
+        values of maxBytes and backupCount to allow the file to rollover at
+        a predetermined size.
+
+        Rollover occurs whenever the current log file is nearly maxBytes in
+        length. If backupCount is >= 1, the system will successively create
+        new files with the same pathname as the base file, but with extensions
+        ".1", ".2" etc. appended to it. For example, with a backupCount of 5
+        and a base file name of "app.log", you would get "app.log",
+        "app.log.1", "app.log.2", ... through to "app.log.5". The file being
+        written to is always "app.log" - when it gets filled up, it is closed
+        and renamed to "app.log.1", and if files "app.log.1", "app.log.2" etc.
+        exist, then they are renamed to "app.log.2", "app.log.3" etc.
+        respectively.
+
+        If maxBytes is zero, rollover never occurs.
+        """
+        # If rotation/rollover is wanted, it doesn't make sense to use another
+        # mode. If for example 'w' were specified, then if there were multiple
+        # runs of the calling application, the logs from previous runs would be
+        # lost if the 'w' is respected, because the log file would be truncated
+        # on each run.
+        if maxBytes > 0:
+            mode = 'a'
+        BaseRotatingHandler.__init__(self, filename, mode, encoding, delay)
+        self.maxBytes = maxBytes
+        self.backupCount = backupCount
+
+    def doRollover(self):
+        """
+        Do a rollover, as described in __init__().
+        """
+        if self.stream:
+            self.stream.close()
+            self.stream = None
+        if self.backupCount > 0:
+            for i in range(self.backupCount - 1, 0, -1):
+                sfn = "%s.%d" % (self.baseFilename, i)
+                dfn = "%s.%d" % (self.baseFilename, i + 1)
+                if os.path.exists(sfn):
+                    #print "%s -> %s" % (sfn, dfn)
+                    if os.path.exists(dfn):
+                        os.remove(dfn)
+                    os.rename(sfn, dfn)
+            dfn = self.baseFilename + ".1"
+            if os.path.exists(dfn):
+                os.remove(dfn)
+            os.rename(self.baseFilename, dfn)
+            #print "%s -> %s" % (self.baseFilename, dfn)
+        self.stream = self._open()
+
+    def shouldRollover(self, record):
+        """
+        Determine if rollover should occur.
+
+        Basically, see if the supplied record would cause the file to exceed
+        the size limit we have.
+        """
+        if self.stream is None:                 # delay was set...
+            self.stream = self._open()
+        if self.maxBytes > 0:                   # are we rolling over?
+            msg = "%s\n" % self.format(record)
+            self.stream.seek(0, 2)  #due to non-posix-compliant Windows feature
+            if self.stream.tell() + len(msg) >= self.maxBytes:
+                return 1
+        return 0
+
+class TimedRotatingFileHandler(BaseRotatingHandler):
+    """
+    Handler for logging to a file, rotating the log file at certain timed
+    intervals.
+
+    If backupCount is > 0, when rollover is done, no more than backupCount
+    files are kept - the oldest ones are deleted.
+    """
+    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False):
+        BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay)
+        self.when = when.upper()
+        self.backupCount = backupCount
+        self.utc = utc
+        # Calculate the real rollover interval, which is just the number of
+        # seconds between rollovers.  Also set the filename suffix used when
+        # a rollover occurs.  Current 'when' events supported:
+        # S - Seconds
+        # M - Minutes
+        # H - Hours
+        # D - Days
+        # midnight - roll over at midnight
+        # W{0-6} - roll over on a certain day; 0 - Monday
+        #
+        # Case of the 'when' specifier is not important; lower or upper case
+        # will work.
+        if self.when == 'S':
+            self.interval = 1 # one second
+            self.suffix = "%Y-%m-%d_%H-%M-%S"
+            self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$"
+        elif self.when == 'M':
+            self.interval = 60 # one minute
+            self.suffix = "%Y-%m-%d_%H-%M"
+            self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}$"
+        elif self.when == 'H':
+            self.interval = 60 * 60 # one hour
+            self.suffix = "%Y-%m-%d_%H"
+            self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}$"
+        elif self.when == 'D' or self.when == 'MIDNIGHT':
+            self.interval = 60 * 60 * 24 # one day
+            self.suffix = "%Y-%m-%d"
+            self.extMatch = r"^\d{4}-\d{2}-\d{2}$"
+        elif self.when.startswith('W'):
+            self.interval = 60 * 60 * 24 * 7 # one week
+            if len(self.when) != 2:
+                raise ValueError("You must specify a day for weekly rollover from 0 to 6 (0 is Monday): %s" % self.when)
+            if self.when[1] < '0' or self.when[1] > '6':
+                raise ValueError("Invalid day specified for weekly rollover: %s" % self.when)
+            self.dayOfWeek = int(self.when[1])
+            self.suffix = "%Y-%m-%d"
+            self.extMatch = r"^\d{4}-\d{2}-\d{2}$"
+        else:
+            raise ValueError("Invalid rollover interval specified: %s" % self.when)
+
+        self.extMatch = re.compile(self.extMatch)
+        self.interval = self.interval * interval # multiply by units requested
+        if os.path.exists(filename):
+            t = os.stat(filename)[ST_MTIME]
+        else:
+            t = int(time.time())
+        self.rolloverAt = self.computeRollover(t)
+
+    def computeRollover(self, currentTime):
+        """
+        Work out the rollover time based on the specified time.
+        """
+        result = currentTime + self.interval
+        # If we are rolling over at midnight or weekly, then the interval is already known.
+        # What we need to figure out is WHEN the next interval is.  In other words,
+        # if you are rolling over at midnight, then your base interval is 1 day,
+        # but you want to start that one day clock at midnight, not now.  So, we
+        # have to fudge the rolloverAt value in order to trigger the first rollover
+        # at the right time.  After that, the regular interval will take care of
+        # the rest.  Note that this code doesn't care about leap seconds. :)
+        if self.when == 'MIDNIGHT' or self.when.startswith('W'):
+            # This could be done with less code, but I wanted it to be clear
+            if self.utc:
+                t = time.gmtime(currentTime)
+            else:
+                t = time.localtime(currentTime)
+            currentHour = t[3]
+            currentMinute = t[4]
+            currentSecond = t[5]
+            # r is the number of seconds left between now and midnight
+            r = _MIDNIGHT - ((currentHour * 60 + currentMinute) * 60 +
+                    currentSecond)
+            result = currentTime + r
+            # If we are rolling over on a certain day, add in the number of days until
+            # the next rollover, but offset by 1 since we just calculated the time
+            # until the next day starts.  There are three cases:
+            # Case 1) The day to rollover is today; in this case, do nothing
+            # Case 2) The day to rollover is further in the interval (i.e., today is
+            #         day 2 (Wednesday) and rollover is on day 6 (Sunday).  Days to
+            #         next rollover is simply 6 - 2 - 1, or 3.
+            # Case 3) The day to rollover is behind us in the interval (i.e., today
+            #         is day 5 (Saturday) and rollover is on day 3 (Thursday).
+            #         Days to rollover is 6 - 5 + 3, or 4.  In this case, it's the
+            #         number of days left in the current week (1) plus the number
+            #         of days in the next week until the rollover day (3).
+            # The calculations described in 2) and 3) above need to have a day added.
+            # This is because the above time calculation takes us to midnight on this
+            # day, i.e. the start of the next day.
+            if self.when.startswith('W'):
+                day = t[6] # 0 is Monday
+                if day != self.dayOfWeek:
+                    if day < self.dayOfWeek:
+                        daysToWait = self.dayOfWeek - day
+                    else:
+                        daysToWait = 6 - day + self.dayOfWeek + 1
+                    newRolloverAt = result + (daysToWait * (60 * 60 * 24))
+                    if not self.utc:
+                        dstNow = t[-1]
+                        dstAtRollover = time.localtime(newRolloverAt)[-1]
+                        if dstNow != dstAtRollover:
+                            if not dstNow:  # DST kicks in before next rollover, so we need to deduct an hour
+                                addend = -3600
+                            else:           # DST bows out before next rollover, so we need to add an hour
+                                addend = 3600
+                            newRolloverAt += addend
+                    result = newRolloverAt
+        return result
+
+    def shouldRollover(self, record):
+        """
+        Determine if rollover should occur.
+
+        record is not used, as we are just comparing times, but it is needed so
+        the method signatures are the same
+        """
+        t = int(time.time())
+        if t >= self.rolloverAt:
+            return 1
+        #print "No need to rollover: %d, %d" % (t, self.rolloverAt)
+        return 0
+
+    def getFilesToDelete(self):
+        """
+        Determine the files to delete when rolling over.
+
+        More specific than the earlier method, which just used glob.glob().
+        """
+        dirName, baseName = os.path.split(self.baseFilename)
+        fileNames = os.listdir(dirName)
+        result = []
+        prefix = baseName + "."
+        plen = len(prefix)
+        for fileName in fileNames:
+            if fileName[:plen] == prefix:
+                suffix = fileName[plen:]
+                if self.extMatch.match(suffix):
+                    result.append(os.path.join(dirName, fileName))
+        result.sort()
+        if len(result) < self.backupCount:
+            result = []
+        else:
+            result = result[:len(result) - self.backupCount]
+        return result
+
+    def doRollover(self):
+        """
+        do a rollover; in this case, a date/time stamp is appended to the filename
+        when the rollover happens.  However, you want the file to be named for the
+        start of the interval, not the current time.  If there is a backup count,
+        then we have to get a list of matching filenames, sort them and remove
+        the one with the oldest suffix.
+        """
+        if self.stream:
+            self.stream.close()
+            self.stream = None
+        # get the time that this sequence started at and make it a TimeTuple
+        currentTime = int(time.time())
+        dstNow = time.localtime(currentTime)[-1]
+        t = self.rolloverAt - self.interval
+        if self.utc:
+            timeTuple = time.gmtime(t)
+        else:
+            timeTuple = time.localtime(t)
+            dstThen = timeTuple[-1]
+            if dstNow != dstThen:
+                if dstNow:
+                    addend = 3600
+                else:
+                    addend = -3600
+                timeTuple = time.localtime(t + addend)
+        dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple)
+        if os.path.exists(dfn):
+            os.remove(dfn)
+        os.rename(self.baseFilename, dfn)
+        if self.backupCount > 0:
+            # find the oldest log file and delete it
+            #s = glob.glob(self.baseFilename + ".20*")
+            #if len(s) > self.backupCount:
+            #    s.sort()
+            #    os.remove(s[0])
+            for s in self.getFilesToDelete():
+                os.remove(s)
+        #print "%s -> %s" % (self.baseFilename, dfn)
+        self.stream = self._open()
+        newRolloverAt = self.computeRollover(currentTime)
+        while newRolloverAt <= currentTime:
+            newRolloverAt = newRolloverAt + self.interval
+        #If DST changes and midnight or weekly rollover, adjust for this.
+        if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc:
+            dstAtRollover = time.localtime(newRolloverAt)[-1]
+            if dstNow != dstAtRollover:
+                if not dstNow:  # DST kicks in before next rollover, so we need to deduct an hour
+                    addend = -3600
+                else:           # DST bows out before next rollover, so we need to add an hour
+                    addend = 3600
+                newRolloverAt += addend
+        self.rolloverAt = newRolloverAt
+
+class WatchedFileHandler(logging.FileHandler):
+    """
+    A handler for logging to a file, which watches the file
+    to see if it has changed while in use. This can happen because of
+    usage of programs such as newsyslog and logrotate which perform
+    log file rotation. This handler, intended for use under Unix,
+    watches the file to see if it has changed since the last emit.
+    (A file has changed if its device or inode have changed.)
+    If it has changed, the old file stream is closed, and the file
+    opened to get a new stream.
+
+    This handler is not appropriate for use under Windows, because
+    under Windows open files cannot be moved or renamed - logging
+    opens the files with exclusive locks - and so there is no need
+    for such a handler. Furthermore, ST_INO is not supported under
+    Windows; stat always returns zero for this value.
+
+    This handler is based on a suggestion and patch by Chad J.
+    Schroeder.
+    """
+    def __init__(self, filename, mode='a', encoding=None, delay=0):
+        logging.FileHandler.__init__(self, filename, mode, encoding, delay)
+        self.dev, self.ino = -1, -1
+        self._statstream()
+
+    def _statstream(self):
+        if self.stream:
+            sres = os.fstat(self.stream.fileno())
+            self.dev, self.ino = sres[ST_DEV], sres[ST_INO]
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        First check if the underlying file has changed, and if it
+        has, close the old stream and reopen the file to get the
+        current stream.
+        """
+        # Reduce the chance of race conditions by stat'ing by path only
+        # once and then fstat'ing our new fd if we opened a new log stream.
+        # See issue #14632: Thanks to John Mulligan for the problem report
+        # and patch.
+        try:
+            # stat the file by path, checking for existence
+            sres = os.stat(self.baseFilename)
+        except OSError as err:
+            if err.errno == errno.ENOENT:
+                sres = None
+            else:
+                raise
+        # compare file system stat with that of our stream file handle
+        if not sres or sres[ST_DEV] != self.dev or sres[ST_INO] != self.ino:
+            if self.stream is not None:
+                # we have an open file handle, clean it up
+                self.stream.flush()
+                self.stream.close()
+                # open a new file handle and get new stat info from that fd
+                self.stream = self._open()
+                self._statstream()
+        logging.FileHandler.emit(self, record)
+
+class SocketHandler(logging.Handler):
+    """
+    A handler class which writes logging records, in pickle format, to
+    a streaming socket. The socket is kept open across logging calls.
+    If the peer resets it, an attempt is made to reconnect on the next call.
+    The pickle which is sent is that of the LogRecord's attribute dictionary
+    (__dict__), so that the receiver does not need to have the logging module
+    installed in order to process the logging event.
+
+    To unpickle the record at the receiving end into a LogRecord, use the
+    makeLogRecord function.
+    """
+
+    def __init__(self, host, port):
+        """
+        Initializes the handler with a specific host address and port.
+
+        The attribute 'closeOnError' is set to 1 - which means that if
+        a socket error occurs, the socket is silently closed and then
+        reopened on the next logging call.
+        """
+        logging.Handler.__init__(self)
+        self.host = host
+        self.port = port
+        self.sock = None
+        self.closeOnError = 0
+        self.retryTime = None
+        #
+        # Exponential backoff parameters.
+        #
+        self.retryStart = 1.0
+        self.retryMax = 30.0
+        self.retryFactor = 2.0
+
+    def makeSocket(self, timeout=1):
+        """
+        A factory method which allows subclasses to define the precise
+        type of socket they want.
+        """
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        if hasattr(s, 'settimeout'):
+            s.settimeout(timeout)
+        s.connect((self.host, self.port))
+        return s
+
+    def createSocket(self):
+        """
+        Try to create a socket, using an exponential backoff with
+        a max retry time. Thanks to Robert Olson for the original patch
+        (SF #815911) which has been slightly refactored.
+        """
+        now = time.time()
+        # Either retryTime is None, in which case this
+        # is the first time back after a disconnect, or
+        # we've waited long enough.
+        if self.retryTime is None:
+            attempt = 1
+        else:
+            attempt = (now >= self.retryTime)
+        if attempt:
+            try:
+                self.sock = self.makeSocket()
+                self.retryTime = None # next time, no delay before trying
+            except socket.error:
+                #Creation failed, so set the retry time and return.
+                if self.retryTime is None:
+                    self.retryPeriod = self.retryStart
+                else:
+                    self.retryPeriod = self.retryPeriod * self.retryFactor
+                    if self.retryPeriod > self.retryMax:
+                        self.retryPeriod = self.retryMax
+                self.retryTime = now + self.retryPeriod
+
+    def send(self, s):
+        """
+        Send a pickled string to the socket.
+
+        This function allows for partial sends which can happen when the
+        network is busy.
+        """
+        if self.sock is None:
+            self.createSocket()
+        #self.sock can be None either because we haven't reached the retry
+        #time yet, or because we have reached the retry time and retried,
+        #but are still unable to connect.
+        if self.sock:
+            try:
+                if hasattr(self.sock, "sendall"):
+                    self.sock.sendall(s)
+                else:
+                    sentsofar = 0
+                    left = len(s)
+                    while left > 0:
+                        sent = self.sock.send(s[sentsofar:])
+                        sentsofar = sentsofar + sent
+                        left = left - sent
+            except socket.error:
+                self.sock.close()
+                self.sock = None  # so we can call createSocket next time
+
+    def makePickle(self, record):
+        """
+        Pickles the record in binary format with a length prefix, and
+        returns it ready for transmission across the socket.
+        """
+        ei = record.exc_info
+        if ei:
+            # just to get traceback text into record.exc_text ...
+            dummy = self.format(record)
+            record.exc_info = None  # to avoid Unpickleable error
+        # See issue #14436: If msg or args are objects, they may not be
+        # available on the receiving end. So we convert the msg % args
+        # to a string, save it as msg and zap the args.
+        d = dict(record.__dict__)
+        d['msg'] = record.getMessage()
+        d['args'] = None
+        s = cPickle.dumps(d, 1)
+        if ei:
+            record.exc_info = ei  # for next handler
+        slen = struct.pack(">L", len(s))
+        return slen + s
+
+    def handleError(self, record):
+        """
+        Handle an error during logging.
+
+        An error has occurred during logging. Most likely cause -
+        connection lost. Close the socket so that we can retry on the
+        next event.
+        """
+        if self.closeOnError and self.sock:
+            self.sock.close()
+            self.sock = None        #try to reconnect next time
+        else:
+            logging.Handler.handleError(self, record)
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        Pickles the record and writes it to the socket in binary format.
+        If there is an error with the socket, silently drop the packet.
+        If there was a problem with the socket, re-establishes the
+        socket.
+        """
+        try:
+            s = self.makePickle(record)
+            self.send(s)
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            self.handleError(record)
+
+    def close(self):
+        """
+        Closes the socket.
+        """
+        self.acquire()
+        try:
+            if self.sock:
+                self.sock.close()
+                self.sock = None
+        finally:
+            self.release()
+        logging.Handler.close(self)
+
+class DatagramHandler(SocketHandler):
+    """
+    A handler class which writes logging records, in pickle format, to
+    a datagram socket.  The pickle which is sent is that of the LogRecord's
+    attribute dictionary (__dict__), so that the receiver does not need to
+    have the logging module installed in order to process the logging event.
+
+    To unpickle the record at the receiving end into a LogRecord, use the
+    makeLogRecord function.
+
+    """
+    def __init__(self, host, port):
+        """
+        Initializes the handler with a specific host address and port.
+        """
+        SocketHandler.__init__(self, host, port)
+        self.closeOnError = 0
+
+    def makeSocket(self):
+        """
+        The factory method of SocketHandler is here overridden to create
+        a UDP socket (SOCK_DGRAM).
+        """
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        return s
+
+    def send(self, s):
+        """
+        Send a pickled string to a socket.
+
+        This function no longer allows for partial sends which can happen
+        when the network is busy - UDP does not guarantee delivery and
+        can deliver packets out of sequence.
+        """
+        if self.sock is None:
+            self.createSocket()
+        self.sock.sendto(s, (self.host, self.port))
+
+class SysLogHandler(logging.Handler):
+    """
+    A handler class which sends formatted logging records to a syslog
+    server. Based on Sam Rushing's syslog module:
+    http://www.nightmare.com/squirl/python-ext/misc/syslog.py
+    Contributed by Nicolas Untz (after which minor refactoring changes
+    have been made).
+    """
+
+    # from <linux/sys/syslog.h>:
+    # ======================================================================
+    # priorities/facilities are encoded into a single 32-bit quantity, where
+    # the bottom 3 bits are the priority (0-7) and the top 28 bits are the
+    # facility (0-big number). Both the priorities and the facilities map
+    # roughly one-to-one to strings in the syslogd(8) source code.  This
+    # mapping is included in this file.
+    #
+    # priorities (these are ordered)
+
+    LOG_EMERG     = 0       #  system is unusable
+    LOG_ALERT     = 1       #  action must be taken immediately
+    LOG_CRIT      = 2       #  critical conditions
+    LOG_ERR       = 3       #  error conditions
+    LOG_WARNING   = 4       #  warning conditions
+    LOG_NOTICE    = 5       #  normal but significant condition
+    LOG_INFO      = 6       #  informational
+    LOG_DEBUG     = 7       #  debug-level messages
+
+    #  facility codes
+    LOG_KERN      = 0       #  kernel messages
+    LOG_USER      = 1       #  random user-level messages
+    LOG_MAIL      = 2       #  mail system
+    LOG_DAEMON    = 3       #  system daemons
+    LOG_AUTH      = 4       #  security/authorization messages
+    LOG_SYSLOG    = 5       #  messages generated internally by syslogd
+    LOG_LPR       = 6       #  line printer subsystem
+    LOG_NEWS      = 7       #  network news subsystem
+    LOG_UUCP      = 8       #  UUCP subsystem
+    LOG_CRON      = 9       #  clock daemon
+    LOG_AUTHPRIV  = 10      #  security/authorization messages (private)
+    LOG_FTP       = 11      #  FTP daemon
+
+    #  other codes through 15 reserved for system use
+    LOG_LOCAL0    = 16      #  reserved for local use
+    LOG_LOCAL1    = 17      #  reserved for local use
+    LOG_LOCAL2    = 18      #  reserved for local use
+    LOG_LOCAL3    = 19      #  reserved for local use
+    LOG_LOCAL4    = 20      #  reserved for local use
+    LOG_LOCAL5    = 21      #  reserved for local use
+    LOG_LOCAL6    = 22      #  reserved for local use
+    LOG_LOCAL7    = 23      #  reserved for local use
+
+    priority_names = {
+        "alert":    LOG_ALERT,
+        "crit":     LOG_CRIT,
+        "critical": LOG_CRIT,
+        "debug":    LOG_DEBUG,
+        "emerg":    LOG_EMERG,
+        "err":      LOG_ERR,
+        "error":    LOG_ERR,        #  DEPRECATED
+        "info":     LOG_INFO,
+        "notice":   LOG_NOTICE,
+        "panic":    LOG_EMERG,      #  DEPRECATED
+        "warn":     LOG_WARNING,    #  DEPRECATED
+        "warning":  LOG_WARNING,
+        }
+
+    facility_names = {
+        "auth":     LOG_AUTH,
+        "authpriv": LOG_AUTHPRIV,
+        "cron":     LOG_CRON,
+        "daemon":   LOG_DAEMON,
+        "ftp":      LOG_FTP,
+        "kern":     LOG_KERN,
+        "lpr":      LOG_LPR,
+        "mail":     LOG_MAIL,
+        "news":     LOG_NEWS,
+        "security": LOG_AUTH,       #  DEPRECATED
+        "syslog":   LOG_SYSLOG,
+        "user":     LOG_USER,
+        "uucp":     LOG_UUCP,
+        "local0":   LOG_LOCAL0,
+        "local1":   LOG_LOCAL1,
+        "local2":   LOG_LOCAL2,
+        "local3":   LOG_LOCAL3,
+        "local4":   LOG_LOCAL4,
+        "local5":   LOG_LOCAL5,
+        "local6":   LOG_LOCAL6,
+        "local7":   LOG_LOCAL7,
+        }
+
+    #The map below appears to be trivially lowercasing the key. However,
+    #there's more to it than meets the eye - in some locales, lowercasing
+    #gives unexpected results. See SF #1524081: in the Turkish locale,
+    #"INFO".lower() != "info"
+    priority_map = {
+        "DEBUG" : "debug",
+        "INFO" : "info",
+        "WARNING" : "warning",
+        "ERROR" : "error",
+        "CRITICAL" : "critical"
+    }
+
+    def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
+                 facility=LOG_USER, socktype=socket.SOCK_DGRAM):
+        """
+        Initialize a handler.
+
+        If address is specified as a string, a UNIX socket is used. To log to a
+        local syslogd, "SysLogHandler(address="/dev/log")" can be used.
+        If facility is not specified, LOG_USER is used.
+        """
+        logging.Handler.__init__(self)
+
+        self.address = address
+        self.facility = facility
+        self.socktype = socktype
+
+        if isinstance(address, basestring):
+            self.unixsocket = 1
+            self._connect_unixsocket(address)
+        else:
+            self.unixsocket = 0
+            self.socket = socket.socket(socket.AF_INET, socktype)
+            if socktype == socket.SOCK_STREAM:
+                self.socket.connect(address)
+        self.formatter = None
+
+    def _connect_unixsocket(self, address):
+        self.socket = socket.socket(socket.AF_UNIX, self.socktype)
+        try:
+            self.socket.connect(address)
+        except socket.error:
+            self.socket.close()
+            raise
+
+    # curious: when talking to the unix-domain '/dev/log' socket, a
+    #   zero-terminator seems to be required.  this string is placed
+    #   into a class variable so that it can be overridden if
+    #   necessary.
+    log_format_string = '<%d>%s\000'
+
+    def encodePriority(self, facility, priority):
+        """
+        Encode the facility and priority. You can pass in strings or
+        integers - if strings are passed, the facility_names and
+        priority_names mapping dictionaries are used to convert them to
+        integers.
+        """
+        if isinstance(facility, basestring):
+            facility = self.facility_names[facility]
+        if isinstance(priority, basestring):
+            priority = self.priority_names[priority]
+        return (facility << 3) | priority
+
+    def close (self):
+        """
+        Closes the socket.
+        """
+        self.acquire()
+        try:
+            if self.unixsocket:
+                self.socket.close()
+        finally:
+            self.release()
+        logging.Handler.close(self)
+
+    def mapPriority(self, levelName):
+        """
+        Map a logging level name to a key in the priority_names map.
+        This is useful in two scenarios: when custom levels are being
+        used, and in the case where you can't do a straightforward
+        mapping by lowercasing the logging level name because of locale-
+        specific issues (see SF #1524081).
+        """
+        return self.priority_map.get(levelName, "warning")
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        The record is formatted, and then sent to the syslog server. If
+        exception information is present, it is NOT sent to the server.
+        """
+        msg = self.format(record) + '\000'
+        """
+        We need to convert record level to lowercase, maybe this will
+        change in the future.
+        """
+        prio = '<%d>' % self.encodePriority(self.facility,
+                                            self.mapPriority(record.levelname))
+        # Message is a string. Convert to bytes as required by RFC 5424
+        if type(msg) is unicode:
+            msg = msg.encode('utf-8')
+        msg = prio + msg
+        try:
+            if self.unixsocket:
+                try:
+                    self.socket.send(msg)
+                except socket.error:
+                    self._connect_unixsocket(self.address)
+                    self.socket.send(msg)
+            elif self.socktype == socket.SOCK_DGRAM:
+                self.socket.sendto(msg, self.address)
+            else:
+                self.socket.sendall(msg)
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            self.handleError(record)
+
+class SMTPHandler(logging.Handler):
+    """
+    A handler class which sends an SMTP email for each logging event.
+    """
+    def __init__(self, mailhost, fromaddr, toaddrs, subject,
+                 credentials=None, secure=None):
+        """
+        Initialize the handler.
+
+        Initialize the instance with the from and to addresses and subject
+        line of the email. To specify a non-standard SMTP port, use the
+        (host, port) tuple format for the mailhost argument. To specify
+        authentication credentials, supply a (username, password) tuple
+        for the credentials argument. To specify the use of a secure
+        protocol (TLS), pass in a tuple for the secure argument. This will
+        only be used when authentication credentials are supplied. The tuple
+        will be either an empty tuple, or a single-value tuple with the name
+        of a keyfile, or a 2-value tuple with the names of the keyfile and
+        certificate file. (This tuple is passed to the `starttls` method).
+        """
+        logging.Handler.__init__(self)
+        if isinstance(mailhost, tuple):
+            self.mailhost, self.mailport = mailhost
+        else:
+            self.mailhost, self.mailport = mailhost, None
+        if isinstance(credentials, tuple):
+            self.username, self.password = credentials
+        else:
+            self.username = None
+        self.fromaddr = fromaddr
+        if isinstance(toaddrs, basestring):
+            toaddrs = [toaddrs]
+        self.toaddrs = toaddrs
+        self.subject = subject
+        self.secure = secure
+        self._timeout = 5.0
+
+    def getSubject(self, record):
+        """
+        Determine the subject for the email.
+
+        If you want to specify a subject line which is record-dependent,
+        override this method.
+        """
+        return self.subject
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        Format the record and send it to the specified addressees.
+        """
+        try:
+            import smtplib
+            from email.utils import formatdate
+            port = self.mailport
+            if not port:
+                port = smtplib.SMTP_PORT
+            smtp = smtplib.SMTP(self.mailhost, port, timeout=self._timeout)
+            msg = self.format(record)
+            msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % (
+                            self.fromaddr,
+                            ",".join(self.toaddrs),
+                            self.getSubject(record),
+                            formatdate(), msg)
+            if self.username:
+                if self.secure is not None:
+                    smtp.ehlo()
+                    smtp.starttls(*self.secure)
+                    smtp.ehlo()
+                smtp.login(self.username, self.password)
+            smtp.sendmail(self.fromaddr, self.toaddrs, msg)
+            smtp.quit()
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            self.handleError(record)
+
+class NTEventLogHandler(logging.Handler):
+    """
+    A handler class which sends events to the NT Event Log. Adds a
+    registry entry for the specified application name. If no dllname is
+    provided, win32service.pyd (which contains some basic message
+    placeholders) is used. Note that use of these placeholders will make
+    your event logs big, as the entire message source is held in the log.
+    If you want slimmer logs, you have to pass in the name of your own DLL
+    which contains the message definitions you want to use in the event log.
+    """
+    def __init__(self, appname, dllname=None, logtype="Application"):
+        logging.Handler.__init__(self)
+        try:
+            import win32evtlogutil, win32evtlog
+            self.appname = appname
+            self._welu = win32evtlogutil
+            if not dllname:
+                dllname = os.path.split(self._welu.__file__)
+                dllname = os.path.split(dllname[0])
+                dllname = os.path.join(dllname[0], r'win32service.pyd')
+            self.dllname = dllname
+            self.logtype = logtype
+            self._welu.AddSourceToRegistry(appname, dllname, logtype)
+            self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE
+            self.typemap = {
+                logging.DEBUG   : win32evtlog.EVENTLOG_INFORMATION_TYPE,
+                logging.INFO    : win32evtlog.EVENTLOG_INFORMATION_TYPE,
+                logging.WARNING : win32evtlog.EVENTLOG_WARNING_TYPE,
+                logging.ERROR   : win32evtlog.EVENTLOG_ERROR_TYPE,
+                logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE,
+         }
+        except ImportError:
+            print("The Python Win32 extensions for NT (service, event "\
+                        "logging) appear not to be available.")
+            self._welu = None
+
+    def getMessageID(self, record):
+        """
+        Return the message ID for the event record. If you are using your
+        own messages, you could do this by having the msg passed to the
+        logger being an ID rather than a formatting string. Then, in here,
+        you could use a dictionary lookup to get the message ID. This
+        version returns 1, which is the base message ID in win32service.pyd.
+        """
+        return 1
+
+    def getEventCategory(self, record):
+        """
+        Return the event category for the record.
+
+        Override this if you want to specify your own categories. This version
+        returns 0.
+        """
+        return 0
+
+    def getEventType(self, record):
+        """
+        Return the event type for the record.
+
+        Override this if you want to specify your own types. This version does
+        a mapping using the handler's typemap attribute, which is set up in
+        __init__() to a dictionary which contains mappings for DEBUG, INFO,
+        WARNING, ERROR and CRITICAL. If you are using your own levels you will
+        either need to override this method or place a suitable dictionary in
+        the handler's typemap attribute.
+        """
+        return self.typemap.get(record.levelno, self.deftype)
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        Determine the message ID, event category and event type. Then
+        log the message in the NT event log.
+        """
+        if self._welu:
+            try:
+                id = self.getMessageID(record)
+                cat = self.getEventCategory(record)
+                type = self.getEventType(record)
+                msg = self.format(record)
+                self._welu.ReportEvent(self.appname, id, cat, type, [msg])
+            except (KeyboardInterrupt, SystemExit):
+                raise
+            except:
+                self.handleError(record)
+
+    def close(self):
+        """
+        Clean up this handler.
+
+        You can remove the application name from the registry as a
+        source of event log entries. However, if you do this, you will
+        not be able to see the events as you intended in the Event Log
+        Viewer - it needs to be able to access the registry to get the
+        DLL name.
+        """
+        #self._welu.RemoveSourceFromRegistry(self.appname, self.logtype)
+        logging.Handler.close(self)
+
+class HTTPHandler(logging.Handler):
+    """
+    A class which sends records to a Web server, using either GET or
+    POST semantics.
+    """
+    def __init__(self, host, url, method="GET"):
+        """
+        Initialize the instance with the host, the request URL, and the method
+        ("GET" or "POST")
+        """
+        logging.Handler.__init__(self)
+        method = method.upper()
+        if method not in ["GET", "POST"]:
+            raise ValueError("method must be GET or POST")
+        self.host = host
+        self.url = url
+        self.method = method
+
+    def mapLogRecord(self, record):
+        """
+        Default implementation of mapping the log record into a dict
+        that is sent as the CGI data. Overwrite in your class.
+        Contributed by Franz  Glasner.
+        """
+        return record.__dict__
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        Send the record to the Web server as a percent-encoded dictionary
+        """
+        try:
+            import httplib, urllib
+            host = self.host
+            h = httplib.HTTP(host)
+            url = self.url
+            data = urllib.urlencode(self.mapLogRecord(record))
+            if self.method == "GET":
+                if (url.find('?') >= 0):
+                    sep = '&'
+                else:
+                    sep = '?'
+                url = url + "%c%s" % (sep, data)
+            h.putrequest(self.method, url)
+            # support multiple hosts on one IP address...
+            # need to strip optional :port from host, if present
+            i = host.find(":")
+            if i >= 0:
+                host = host[:i]
+            h.putheader("Host", host)
+            if self.method == "POST":
+                h.putheader("Content-type",
+                            "application/x-www-form-urlencoded")
+                h.putheader("Content-length", str(len(data)))
+            h.endheaders(data if self.method == "POST" else None)
+            h.getreply()    #can't do anything with the result
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:
+            self.handleError(record)
+
+class BufferingHandler(logging.Handler):
+    """
+  A handler class which buffers logging records in memory. Whenever each
+  record is added to the buffer, a check is made to see if the buffer should
+  be flushed. If it should, then flush() is expected to do what's needed.
+    """
+    def __init__(self, capacity):
+        """
+        Initialize the handler with the buffer size.
+        """
+        logging.Handler.__init__(self)
+        self.capacity = capacity
+        self.buffer = []
+
+    def shouldFlush(self, record):
+        """
+        Should the handler flush its buffer?
+
+        Returns true if the buffer is up to capacity. This method can be
+        overridden to implement custom flushing strategies.
+        """
+        return (len(self.buffer) >= self.capacity)
+
+    def emit(self, record):
+        """
+        Emit a record.
+
+        Append the record. If shouldFlush() tells us to, call flush() to process
+        the buffer.
+        """
+        self.buffer.append(record)
+        if self.shouldFlush(record):
+            self.flush()
+
+    def flush(self):
+        """
+        Override to implement custom flushing behaviour.
+
+        This version just zaps the buffer to empty.
+        """
+        self.acquire()
+        try:
+            self.buffer = []
+        finally:
+            self.release()
+
+    def close(self):
+        """
+        Close the handler.
+
+        This version just flushes and chains to the parent class' close().
+        """
+        self.flush()
+        logging.Handler.close(self)
+
+class MemoryHandler(BufferingHandler):
+    """
+    A handler class which buffers logging records in memory, periodically
+    flushing them to a target handler. Flushing occurs whenever the buffer
+    is full, or when an event of a certain severity or greater is seen.
+    """
+    def __init__(self, capacity, flushLevel=logging.ERROR, target=None):
+        """
+        Initialize the handler with the buffer size, the level at which
+        flushing should occur and an optional target.
+
+        Note that without a target being set either here or via setTarget(),
+        a MemoryHandler is no use to anyone!
+        """
+        BufferingHandler.__init__(self, capacity)
+        self.flushLevel = flushLevel
+        self.target = target
+
+    def shouldFlush(self, record):
+        """
+        Check for buffer full or a record at the flushLevel or higher.
+        """
+        return (len(self.buffer) >= self.capacity) or \
+                (record.levelno >= self.flushLevel)
+
+    def setTarget(self, target):
+        """
+        Set the target handler for this handler.
+        """
+        self.target = target
+
+    def flush(self):
+        """
+        For a MemoryHandler, flushing means just sending the buffered
+        records to the target, if there is one. Override if you want
+        different behaviour.
+        """
+        self.acquire()
+        try:
+            if self.target:
+                for record in self.buffer:
+                    self.target.handle(record)
+                self.buffer = []
+        finally:
+            self.release()
+
+    def close(self):
+        """
+        Flush, set the target to None and lose the buffer.
+        """
+        self.flush()
+        self.acquire()
+        try:
+            self.target = None
+            BufferingHandler.close(self)
+        finally:
+            self.release()
diff --git a/src/main/resources/PythonLibs/macpath.py b/src/main/resources/PythonLibs/macpath.py
new file mode 100644
index 0000000000000000000000000000000000000000..cd4cb8581af67e6e7d1bef020f71fb9bc750b470
--- /dev/null
+++ b/src/main/resources/PythonLibs/macpath.py
@@ -0,0 +1,215 @@
+"""Pathname and path-related operations for the Macintosh."""
+
+import os
+import warnings
+from stat import *
+import genericpath
+from genericpath import *
+
+__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
+           "basename","dirname","commonprefix","getsize","getmtime",
+           "getatime","getctime", "islink","exists","lexists","isdir","isfile",
+           "walk","expanduser","expandvars","normpath","abspath",
+           "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
+           "devnull","realpath","supports_unicode_filenames"]
+
+# strings representing various path-related bits and pieces
+curdir = ':'
+pardir = '::'
+extsep = '.'
+sep = ':'
+pathsep = '\n'
+defpath = ':'
+altsep = None
+devnull = 'Dev:Null'
+
+# Normalize the case of a pathname.  Dummy in Posix, but <s>.lower() here.
+
+def normcase(path):
+    return path.lower()
+
+
+def isabs(s):
+    """Return true if a path is absolute.
+    On the Mac, relative paths begin with a colon,
+    but as a special case, paths with no colons at all are also relative.
+    Anything else is absolute (the string up to the first colon is the
+    volume name)."""
+
+    return ':' in s and s[0] != ':'
+
+
+def join(s, *p):
+    path = s
+    for t in p:
+        if (not s) or isabs(t):
+            path = t
+            continue
+        if t[:1] == ':':
+            t = t[1:]
+        if ':' not in path:
+            path = ':' + path
+        if path[-1:] != ':':
+            path = path + ':'
+        path = path + t
+    return path
+
+
+def split(s):
+    """Split a pathname into two parts: the directory leading up to the final
+    bit, and the basename (the filename, without colons, in that directory).
+    The result (s, t) is such that join(s, t) yields the original argument."""
+
+    if ':' not in s: return '', s
+    colon = 0
+    for i in range(len(s)):
+        if s[i] == ':': colon = i + 1
+    path, file = s[:colon-1], s[colon:]
+    if path and not ':' in path:
+        path = path + ':'
+    return path, file
+
+
+def splitext(p):
+    return genericpath._splitext(p, sep, altsep, extsep)
+splitext.__doc__ = genericpath._splitext.__doc__
+
+def splitdrive(p):
+    """Split a pathname into a drive specification and the rest of the
+    path.  Useful on DOS/Windows/NT; on the Mac, the drive is always
+    empty (don't use the volume name -- it doesn't have the same
+    syntactic and semantic oddities as DOS drive letters, such as there
+    being a separate current directory per drive)."""
+
+    return '', p
+
+
+# Short interfaces to split()
+
+def dirname(s): return split(s)[0]
+def basename(s): return split(s)[1]
+
+def ismount(s):
+    if not isabs(s):
+        return False
+    components = split(s)
+    return len(components) == 2 and components[1] == ''
+
+def islink(s):
+    """Return true if the pathname refers to a symbolic link."""
+
+    try:
+        import Carbon.File
+        return Carbon.File.ResolveAliasFile(s, 0)[2]
+    except:
+        return False
+
+# Is `stat`/`lstat` a meaningful difference on the Mac?  This is safe in any
+# case.
+
+def lexists(path):
+    """Test whether a path exists.  Returns True for broken symbolic links"""
+
+    try:
+        st = os.lstat(path)
+    except os.error:
+        return False
+    return True
+
+def expandvars(path):
+    """Dummy to retain interface-compatibility with other operating systems."""
+    return path
+
+
+def expanduser(path):
+    """Dummy to retain interface-compatibility with other operating systems."""
+    return path
+
+class norm_error(Exception):
+    """Path cannot be normalized"""
+
+def normpath(s):
+    """Normalize a pathname.  Will return the same result for
+    equivalent paths."""
+
+    if ":" not in s:
+        return ":"+s
+
+    comps = s.split(":")
+    i = 1
+    while i < len(comps)-1:
+        if comps[i] == "" and comps[i-1] != "":
+            if i > 1:
+                del comps[i-1:i+1]
+                i = i - 1
+            else:
+                # best way to handle this is to raise an exception
+                raise norm_error, 'Cannot use :: immediately after volume name'
+        else:
+            i = i + 1
+
+    s = ":".join(comps)
+
+    # remove trailing ":" except for ":" and "Volume:"
+    if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
+        s = s[:-1]
+    return s
+
+
+def walk(top, func, arg):
+    """Directory tree walk with callback function.
+
+    For each directory in the directory tree rooted at top (including top
+    itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
+    dirname is the name of the directory, and fnames a list of the names of
+    the files and subdirectories in dirname (excluding '.' and '..').  func
+    may modify the fnames list in-place (e.g. via del or slice assignment),
+    and walk will only recurse into the subdirectories whose names remain in
+    fnames; this can be used to implement a filter, or to impose a specific
+    order of visiting.  No semantics are defined for, or required of, arg,
+    beyond that arg is always passed to func.  It can be used, e.g., to pass
+    a filename pattern, or a mutable object designed to accumulate
+    statistics.  Passing None for arg is common."""
+    warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.",
+                      stacklevel=2)
+    try:
+        names = os.listdir(top)
+    except os.error:
+        return
+    func(arg, top, names)
+    for name in names:
+        name = join(top, name)
+        if isdir(name) and not islink(name):
+            walk(name, func, arg)
+
+
+def abspath(path):
+    """Return an absolute path."""
+    if not isabs(path):
+        if isinstance(path, unicode):
+            cwd = os.getcwdu()
+        else:
+            cwd = os.getcwd()
+        path = join(cwd, path)
+    return normpath(path)
+
+# realpath is a no-op on systems without islink support
+def realpath(path):
+    path = abspath(path)
+    try:
+        import Carbon.File
+    except ImportError:
+        return path
+    if not path:
+        return path
+    components = path.split(':')
+    path = components[0] + ':'
+    for c in components[1:]:
+        path = join(path, c)
+        try:
+            path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
+        except Carbon.File.Error:
+            pass
+    return path
+
+supports_unicode_filenames = True
diff --git a/src/main/resources/PythonLibs/macurl2path.py b/src/main/resources/PythonLibs/macurl2path.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c5ae64572e26ab59f299ce83b16ca42827b44a2
--- /dev/null
+++ b/src/main/resources/PythonLibs/macurl2path.py
@@ -0,0 +1,97 @@
+"""Macintosh-specific module for conversion between pathnames and URLs.
+
+Do not import directly; use urllib instead."""
+
+import urllib
+import os
+
+__all__ = ["url2pathname","pathname2url"]
+
+def url2pathname(pathname):
+    """OS-specific conversion from a relative URL of the 'file' scheme
+    to a file system path; not recommended for general use."""
+    #
+    # XXXX The .. handling should be fixed...
+    #
+    tp = urllib.splittype(pathname)[0]
+    if tp and tp != 'file':
+        raise RuntimeError, 'Cannot convert non-local URL to pathname'
+    # Turn starting /// into /, an empty hostname means current host
+    if pathname[:3] == '///':
+        pathname = pathname[2:]
+    elif pathname[:2] == '//':
+        raise RuntimeError, 'Cannot convert non-local URL to pathname'
+    components = pathname.split('/')
+    # Remove . and embedded ..
+    i = 0
+    while i < len(components):
+        if components[i] == '.':
+            del components[i]
+        elif components[i] == '..' and i > 0 and \
+                                  components[i-1] not in ('', '..'):
+            del components[i-1:i+1]
+            i = i-1
+        elif components[i] == '' and i > 0 and components[i-1] != '':
+            del components[i]
+        else:
+            i = i+1
+    if not components[0]:
+        # Absolute unix path, don't start with colon
+        rv = ':'.join(components[1:])
+    else:
+        # relative unix path, start with colon. First replace
+        # leading .. by empty strings (giving ::file)
+        i = 0
+        while i < len(components) and components[i] == '..':
+            components[i] = ''
+            i = i + 1
+        rv = ':' + ':'.join(components)
+    # and finally unquote slashes and other funny characters
+    return urllib.unquote(rv)
+
+def pathname2url(pathname):
+    """OS-specific conversion from a file system path to a relative URL
+    of the 'file' scheme; not recommended for general use."""
+    if '/' in pathname:
+        raise RuntimeError, "Cannot convert pathname containing slashes"
+    components = pathname.split(':')
+    # Remove empty first and/or last component
+    if components[0] == '':
+        del components[0]
+    if components[-1] == '':
+        del components[-1]
+    # Replace empty string ('::') by .. (will result in '/../' later)
+    for i in range(len(components)):
+        if components[i] == '':
+            components[i] = '..'
+    # Truncate names longer than 31 bytes
+    components = map(_pncomp2url, components)
+
+    if os.path.isabs(pathname):
+        return '/' + '/'.join(components)
+    else:
+        return '/'.join(components)
+
+def _pncomp2url(component):
+    component = urllib.quote(component[:31], safe='')  # We want to quote slashes
+    return component
+
+def test():
+    for url in ["index.html",
+                "bar/index.html",
+                "/foo/bar/index.html",
+                "/foo/bar/",
+                "/"]:
+        print '%r -> %r' % (url, url2pathname(url))
+    for path in ["drive:",
+                 "drive:dir:",
+                 "drive:dir:file",
+                 "drive:file",
+                 "file",
+                 ":file",
+                 ":dir:",
+                 ":dir:file"]:
+        print '%r -> %r' % (path, pathname2url(path))
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/mailbox.py b/src/main/resources/PythonLibs/mailbox.py
new file mode 100644
index 0000000000000000000000000000000000000000..530d3c5a66ef729f430308bc025d6c7474bb7997
--- /dev/null
+++ b/src/main/resources/PythonLibs/mailbox.py
@@ -0,0 +1,2230 @@
+#! /usr/bin/env python
+
+"""Read/write support for Maildir, mbox, MH, Babyl, and MMDF mailboxes."""
+
+# Notes for authors of new mailbox subclasses:
+#
+# Remember to fsync() changes to disk before closing a modified file
+# or returning from a flush() method.  See functions _sync_flush() and
+# _sync_close().
+
+import sys
+import os
+import time
+import calendar
+import socket
+import errno
+import copy
+import email
+import email.message
+import email.generator
+import StringIO
+try:
+    if sys.platform == 'os2emx':
+        # OS/2 EMX fcntl() not adequate
+        raise ImportError
+    import fcntl
+except ImportError:
+    fcntl = None
+
+import warnings
+with warnings.catch_warnings():
+    if sys.py3kwarning:
+        warnings.filterwarnings("ignore", ".*rfc822 has been removed",
+                                DeprecationWarning)
+    import rfc822
+
+__all__ = [ 'Mailbox', 'Maildir', 'mbox', 'MH', 'Babyl', 'MMDF',
+            'Message', 'MaildirMessage', 'mboxMessage', 'MHMessage',
+            'BabylMessage', 'MMDFMessage', 'UnixMailbox',
+            'PortableUnixMailbox', 'MmdfMailbox', 'MHMailbox', 'BabylMailbox' ]
+
+class Mailbox:
+    """A group of messages in a particular place."""
+
+    def __init__(self, path, factory=None, create=True):
+        """Initialize a Mailbox instance."""
+        self._path = os.path.abspath(os.path.expanduser(path))
+        self._factory = factory
+
+    def add(self, message):
+        """Add message and return assigned key."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def remove(self, key):
+        """Remove the keyed message; raise KeyError if it doesn't exist."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def __delitem__(self, key):
+        self.remove(key)
+
+    def discard(self, key):
+        """If the keyed message exists, remove it."""
+        try:
+            self.remove(key)
+        except KeyError:
+            pass
+
+    def __setitem__(self, key, message):
+        """Replace the keyed message; raise KeyError if it doesn't exist."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def get(self, key, default=None):
+        """Return the keyed message, or default if it doesn't exist."""
+        try:
+            return self.__getitem__(key)
+        except KeyError:
+            return default
+
+    def __getitem__(self, key):
+        """Return the keyed message; raise KeyError if it doesn't exist."""
+        if not self._factory:
+            return self.get_message(key)
+        else:
+            return self._factory(self.get_file(key))
+
+    def get_message(self, key):
+        """Return a Message representation or raise a KeyError."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def get_string(self, key):
+        """Return a string representation or raise a KeyError."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def get_file(self, key):
+        """Return a file-like representation or raise a KeyError."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def iterkeys(self):
+        """Return an iterator over keys."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def keys(self):
+        """Return a list of keys."""
+        return list(self.iterkeys())
+
+    def itervalues(self):
+        """Return an iterator over all messages."""
+        for key in self.iterkeys():
+            try:
+                value = self[key]
+            except KeyError:
+                continue
+            yield value
+
+    def __iter__(self):
+        return self.itervalues()
+
+    def values(self):
+        """Return a list of messages. Memory intensive."""
+        return list(self.itervalues())
+
+    def iteritems(self):
+        """Return an iterator over (key, message) tuples."""
+        for key in self.iterkeys():
+            try:
+                value = self[key]
+            except KeyError:
+                continue
+            yield (key, value)
+
+    def items(self):
+        """Return a list of (key, message) tuples. Memory intensive."""
+        return list(self.iteritems())
+
+    def has_key(self, key):
+        """Return True if the keyed message exists, False otherwise."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def __contains__(self, key):
+        return self.has_key(key)
+
+    def __len__(self):
+        """Return a count of messages in the mailbox."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def clear(self):
+        """Delete all messages."""
+        for key in self.iterkeys():
+            self.discard(key)
+
+    def pop(self, key, default=None):
+        """Delete the keyed message and return it, or default."""
+        try:
+            result = self[key]
+        except KeyError:
+            return default
+        self.discard(key)
+        return result
+
+    def popitem(self):
+        """Delete an arbitrary (key, message) pair and return it."""
+        for key in self.iterkeys():
+            return (key, self.pop(key))     # This is only run once.
+        else:
+            raise KeyError('No messages in mailbox')
+
+    def update(self, arg=None):
+        """Change the messages that correspond to certain keys."""
+        if hasattr(arg, 'iteritems'):
+            source = arg.iteritems()
+        elif hasattr(arg, 'items'):
+            source = arg.items()
+        else:
+            source = arg
+        bad_key = False
+        for key, message in source:
+            try:
+                self[key] = message
+            except KeyError:
+                bad_key = True
+        if bad_key:
+            raise KeyError('No message with key(s)')
+
+    def flush(self):
+        """Write any pending changes to the disk."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def lock(self):
+        """Lock the mailbox."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def unlock(self):
+        """Unlock the mailbox if it is locked."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    def close(self):
+        """Flush and close the mailbox."""
+        raise NotImplementedError('Method must be implemented by subclass')
+
+    # Whether each message must end in a newline
+    _append_newline = False
+
+    def _dump_message(self, message, target, mangle_from_=False):
+        # Most files are opened in binary mode to allow predictable seeking.
+        # To get native line endings on disk, the user-friendly \n line endings
+        # used in strings and by email.Message are translated here.
+        """Dump message contents to target file."""
+        if isinstance(message, email.message.Message):
+            buffer = StringIO.StringIO()
+            gen = email.generator.Generator(buffer, mangle_from_, 0)
+            gen.flatten(message)
+            buffer.seek(0)
+            data = buffer.read().replace('\n', os.linesep)
+            target.write(data)
+            if self._append_newline and not data.endswith(os.linesep):
+                # Make sure the message ends with a newline
+                target.write(os.linesep)
+        elif isinstance(message, str):
+            if mangle_from_:
+                message = message.replace('\nFrom ', '\n>From ')
+            message = message.replace('\n', os.linesep)
+            target.write(message)
+            if self._append_newline and not message.endswith(os.linesep):
+                # Make sure the message ends with a newline
+                target.write(os.linesep)
+        elif hasattr(message, 'read'):
+            lastline = None
+            while True:
+                line = message.readline()
+                if line == '':
+                    break
+                if mangle_from_ and line.startswith('From '):
+                    line = '>From ' + line[5:]
+                line = line.replace('\n', os.linesep)
+                target.write(line)
+                lastline = line
+            if self._append_newline and lastline and not lastline.endswith(os.linesep):
+                # Make sure the message ends with a newline
+                target.write(os.linesep)
+        else:
+            raise TypeError('Invalid message type: %s' % type(message))
+
+
+class Maildir(Mailbox):
+    """A qmail-style Maildir mailbox."""
+
+    colon = ':'
+
+    def __init__(self, dirname, factory=rfc822.Message, create=True):
+        """Initialize a Maildir instance."""
+        Mailbox.__init__(self, dirname, factory, create)
+        self._paths = {
+            'tmp': os.path.join(self._path, 'tmp'),
+            'new': os.path.join(self._path, 'new'),
+            'cur': os.path.join(self._path, 'cur'),
+            }
+        if not os.path.exists(self._path):
+            if create:
+                os.mkdir(self._path, 0700)
+                for path in self._paths.values():
+                    os.mkdir(path, 0o700)
+            else:
+                raise NoSuchMailboxError(self._path)
+        self._toc = {}
+        self._toc_mtimes = {'cur': 0, 'new': 0}
+        self._last_read = 0         # Records last time we read cur/new
+        self._skewfactor = 0.1      # Adjust if os/fs clocks are skewing
+
+    def add(self, message):
+        """Add message and return assigned key."""
+        tmp_file = self._create_tmp()
+        try:
+            self._dump_message(message, tmp_file)
+        except BaseException:
+            tmp_file.close()
+            os.remove(tmp_file.name)
+            raise
+        _sync_close(tmp_file)
+        if isinstance(message, MaildirMessage):
+            subdir = message.get_subdir()
+            suffix = self.colon + message.get_info()
+            if suffix == self.colon:
+                suffix = ''
+        else:
+            subdir = 'new'
+            suffix = ''
+        uniq = os.path.basename(tmp_file.name).split(self.colon)[0]
+        dest = os.path.join(self._path, subdir, uniq + suffix)
+        try:
+            if hasattr(os, 'link'):
+                os.link(tmp_file.name, dest)
+                os.remove(tmp_file.name)
+            else:
+                os.rename(tmp_file.name, dest)
+        except OSError, e:
+            os.remove(tmp_file.name)
+            if e.errno == errno.EEXIST:
+                raise ExternalClashError('Name clash with existing message: %s'
+                                         % dest)
+            else:
+                raise
+        if isinstance(message, MaildirMessage):
+            os.utime(dest, (os.path.getatime(dest), message.get_date()))
+        return uniq
+
+    def remove(self, key):
+        """Remove the keyed message; raise KeyError if it doesn't exist."""
+        os.remove(os.path.join(self._path, self._lookup(key)))
+
+    def discard(self, key):
+        """If the keyed message exists, remove it."""
+        # This overrides an inapplicable implementation in the superclass.
+        try:
+            self.remove(key)
+        except KeyError:
+            pass
+        except OSError, e:
+            if e.errno != errno.ENOENT:
+                raise
+
+    def __setitem__(self, key, message):
+        """Replace the keyed message; raise KeyError if it doesn't exist."""
+        old_subpath = self._lookup(key)
+        temp_key = self.add(message)
+        temp_subpath = self._lookup(temp_key)
+        if isinstance(message, MaildirMessage):
+            # temp's subdir and suffix were specified by message.
+            dominant_subpath = temp_subpath
+        else:
+            # temp's subdir and suffix were defaults from add().
+            dominant_subpath = old_subpath
+        subdir = os.path.dirname(dominant_subpath)
+        if self.colon in dominant_subpath:
+            suffix = self.colon + dominant_subpath.split(self.colon)[-1]
+        else:
+            suffix = ''
+        self.discard(key)
+        new_path = os.path.join(self._path, subdir, key + suffix)
+        os.rename(os.path.join(self._path, temp_subpath), new_path)
+        if isinstance(message, MaildirMessage):
+            os.utime(new_path, (os.path.getatime(new_path),
+                                message.get_date()))
+
+    def get_message(self, key):
+        """Return a Message representation or raise a KeyError."""
+        subpath = self._lookup(key)
+        f = open(os.path.join(self._path, subpath), 'r')
+        try:
+            if self._factory:
+                msg = self._factory(f)
+            else:
+                msg = MaildirMessage(f)
+        finally:
+            f.close()
+        subdir, name = os.path.split(subpath)
+        msg.set_subdir(subdir)
+        if self.colon in name:
+            msg.set_info(name.split(self.colon)[-1])
+        msg.set_date(os.path.getmtime(os.path.join(self._path, subpath)))
+        return msg
+
+    def get_string(self, key):
+        """Return a string representation or raise a KeyError."""
+        f = open(os.path.join(self._path, self._lookup(key)), 'r')
+        try:
+            return f.read()
+        finally:
+            f.close()
+
+    def get_file(self, key):
+        """Return a file-like representation or raise a KeyError."""
+        f = open(os.path.join(self._path, self._lookup(key)), 'rb')
+        return _ProxyFile(f)
+
+    def iterkeys(self):
+        """Return an iterator over keys."""
+        self._refresh()
+        for key in self._toc:
+            try:
+                self._lookup(key)
+            except KeyError:
+                continue
+            yield key
+
+    def has_key(self, key):
+        """Return True if the keyed message exists, False otherwise."""
+        self._refresh()
+        return key in self._toc
+
+    def __len__(self):
+        """Return a count of messages in the mailbox."""
+        self._refresh()
+        return len(self._toc)
+
+    def flush(self):
+        """Write any pending changes to disk."""
+        # Maildir changes are always written immediately, so there's nothing
+        # to do.
+        pass
+
+    def lock(self):
+        """Lock the mailbox."""
+        return
+
+    def unlock(self):
+        """Unlock the mailbox if it is locked."""
+        return
+
+    def close(self):
+        """Flush and close the mailbox."""
+        return
+
+    def list_folders(self):
+        """Return a list of folder names."""
+        result = []
+        for entry in os.listdir(self._path):
+            if len(entry) > 1 and entry[0] == '.' and \
+               os.path.isdir(os.path.join(self._path, entry)):
+                result.append(entry[1:])
+        return result
+
+    def get_folder(self, folder):
+        """Return a Maildir instance for the named folder."""
+        return Maildir(os.path.join(self._path, '.' + folder),
+                       factory=self._factory,
+                       create=False)
+
+    def add_folder(self, folder):
+        """Create a folder and return a Maildir instance representing it."""
+        path = os.path.join(self._path, '.' + folder)
+        result = Maildir(path, factory=self._factory)
+        maildirfolder_path = os.path.join(path, 'maildirfolder')
+        if not os.path.exists(maildirfolder_path):
+            os.close(os.open(maildirfolder_path, os.O_CREAT | os.O_WRONLY,
+                0666))
+        return result
+
+    def remove_folder(self, folder):
+        """Delete the named folder, which must be empty."""
+        path = os.path.join(self._path, '.' + folder)
+        for entry in os.listdir(os.path.join(path, 'new')) + \
+                     os.listdir(os.path.join(path, 'cur')):
+            if len(entry) < 1 or entry[0] != '.':
+                raise NotEmptyError('Folder contains message(s): %s' % folder)
+        for entry in os.listdir(path):
+            if entry != 'new' and entry != 'cur' and entry != 'tmp' and \
+               os.path.isdir(os.path.join(path, entry)):
+                raise NotEmptyError("Folder contains subdirectory '%s': %s" %
+                                    (folder, entry))
+        for root, dirs, files in os.walk(path, topdown=False):
+            for entry in files:
+                os.remove(os.path.join(root, entry))
+            for entry in dirs:
+                os.rmdir(os.path.join(root, entry))
+        os.rmdir(path)
+
+    def clean(self):
+        """Delete old files in "tmp"."""
+        now = time.time()
+        for entry in os.listdir(os.path.join(self._path, 'tmp')):
+            path = os.path.join(self._path, 'tmp', entry)
+            if now - os.path.getatime(path) > 129600:   # 60 * 60 * 36
+                os.remove(path)
+
+    _count = 1  # This is used to generate unique file names.
+
+    def _create_tmp(self):
+        """Create a file in the tmp subdirectory and open and return it."""
+        now = time.time()
+        hostname = socket.gethostname()
+        if '/' in hostname:
+            hostname = hostname.replace('/', r'\057')
+        if ':' in hostname:
+            hostname = hostname.replace(':', r'\072')
+        uniq = "%s.M%sP%sQ%s.%s" % (int(now), int(now % 1 * 1e6), os.getpid(),
+                                    Maildir._count, hostname)
+        path = os.path.join(self._path, 'tmp', uniq)
+        try:
+            os.stat(path)
+        except OSError, e:
+            if e.errno == errno.ENOENT:
+                Maildir._count += 1
+                try:
+                    return _create_carefully(path)
+                except OSError, e:
+                    if e.errno != errno.EEXIST:
+                        raise
+            else:
+                raise
+
+        # Fall through to here if stat succeeded or open raised EEXIST.
+        raise ExternalClashError('Name clash prevented file creation: %s' %
+                                 path)
+
+    def _refresh(self):
+        """Update table of contents mapping."""
+        # If it has been less than two seconds since the last _refresh() call,
+        # we have to unconditionally re-read the mailbox just in case it has
+        # been modified, because os.path.mtime() has a 2 sec resolution in the
+        # most common worst case (FAT) and a 1 sec resolution typically.  This
+        # results in a few unnecessary re-reads when _refresh() is called
+        # multiple times in that interval, but once the clock ticks over, we
+        # will only re-read as needed.  Because the filesystem might be being
+        # served by an independent system with its own clock, we record and
+        # compare with the mtimes from the filesystem.  Because the other
+        # system's clock might be skewing relative to our clock, we add an
+        # extra delta to our wait.  The default is one tenth second, but is an
+        # instance variable and so can be adjusted if dealing with a
+        # particularly skewed or irregular system.
+        if time.time() - self._last_read > 2 + self._skewfactor:
+            refresh = False
+            for subdir in self._toc_mtimes:
+                mtime = os.path.getmtime(self._paths[subdir])
+                if mtime > self._toc_mtimes[subdir]:
+                    refresh = True
+                self._toc_mtimes[subdir] = mtime
+            if not refresh:
+                return
+        # Refresh toc
+        self._toc = {}
+        for subdir in self._toc_mtimes:
+            path = self._paths[subdir]
+            for entry in os.listdir(path):
+                p = os.path.join(path, entry)
+                if os.path.isdir(p):
+                    continue
+                uniq = entry.split(self.colon)[0]
+                self._toc[uniq] = os.path.join(subdir, entry)
+        self._last_read = time.time()
+
+    def _lookup(self, key):
+        """Use TOC to return subpath for given key, or raise a KeyError."""
+        try:
+            if os.path.exists(os.path.join(self._path, self._toc[key])):
+                return self._toc[key]
+        except KeyError:
+            pass
+        self._refresh()
+        try:
+            return self._toc[key]
+        except KeyError:
+            raise KeyError('No message with key: %s' % key)
+
+    # This method is for backward compatibility only.
+    def next(self):
+        """Return the next message in a one-time iteration."""
+        if not hasattr(self, '_onetime_keys'):
+            self._onetime_keys = self.iterkeys()
+        while True:
+            try:
+                return self[self._onetime_keys.next()]
+            except StopIteration:
+                return None
+            except KeyError:
+                continue
+
+
+class _singlefileMailbox(Mailbox):
+    """A single-file mailbox."""
+
+    def __init__(self, path, factory=None, create=True):
+        """Initialize a single-file mailbox."""
+        Mailbox.__init__(self, path, factory, create)
+        try:
+            f = open(self._path, 'rb+')
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                if create:
+                    f = open(self._path, 'wb+')
+                else:
+                    raise NoSuchMailboxError(self._path)
+            elif e.errno in (errno.EACCES, errno.EROFS):
+                f = open(self._path, 'rb')
+            else:
+                raise
+        self._file = f
+        self._toc = None
+        self._next_key = 0
+        self._pending = False       # No changes require rewriting the file.
+        self._pending_sync = False  # No need to sync the file
+        self._locked = False
+        self._file_length = None    # Used to record mailbox size
+
+    def add(self, message):
+        """Add message and return assigned key."""
+        self._lookup()
+        self._toc[self._next_key] = self._append_message(message)
+        self._next_key += 1
+        # _append_message appends the message to the mailbox file. We
+        # don't need a full rewrite + rename, sync is enough.
+        self._pending_sync = True
+        return self._next_key - 1
+
+    def remove(self, key):
+        """Remove the keyed message; raise KeyError if it doesn't exist."""
+        self._lookup(key)
+        del self._toc[key]
+        self._pending = True
+
+    def __setitem__(self, key, message):
+        """Replace the keyed message; raise KeyError if it doesn't exist."""
+        self._lookup(key)
+        self._toc[key] = self._append_message(message)
+        self._pending = True
+
+    def iterkeys(self):
+        """Return an iterator over keys."""
+        self._lookup()
+        for key in self._toc.keys():
+            yield key
+
+    def has_key(self, key):
+        """Return True if the keyed message exists, False otherwise."""
+        self._lookup()
+        return key in self._toc
+
+    def __len__(self):
+        """Return a count of messages in the mailbox."""
+        self._lookup()
+        return len(self._toc)
+
+    def lock(self):
+        """Lock the mailbox."""
+        if not self._locked:
+            _lock_file(self._file)
+            self._locked = True
+
+    def unlock(self):
+        """Unlock the mailbox if it is locked."""
+        if self._locked:
+            _unlock_file(self._file)
+            self._locked = False
+
+    def flush(self):
+        """Write any pending changes to disk."""
+        if not self._pending:
+            if self._pending_sync:
+                # Messages have only been added, so syncing the file
+                # is enough.
+                _sync_flush(self._file)
+                self._pending_sync = False
+            return
+
+        # In order to be writing anything out at all, self._toc must
+        # already have been generated (and presumably has been modified
+        # by adding or deleting an item).
+        assert self._toc is not None
+
+        # Check length of self._file; if it's changed, some other process
+        # has modified the mailbox since we scanned it.
+        self._file.seek(0, 2)
+        cur_len = self._file.tell()
+        if cur_len != self._file_length:
+            raise ExternalClashError('Size of mailbox file changed '
+                                     '(expected %i, found %i)' %
+                                     (self._file_length, cur_len))
+
+        new_file = _create_temporary(self._path)
+        try:
+            new_toc = {}
+            self._pre_mailbox_hook(new_file)
+            for key in sorted(self._toc.keys()):
+                start, stop = self._toc[key]
+                self._file.seek(start)
+                self._pre_message_hook(new_file)
+                new_start = new_file.tell()
+                while True:
+                    buffer = self._file.read(min(4096,
+                                                 stop - self._file.tell()))
+                    if buffer == '':
+                        break
+                    new_file.write(buffer)
+                new_toc[key] = (new_start, new_file.tell())
+                self._post_message_hook(new_file)
+            self._file_length = new_file.tell()
+        except:
+            new_file.close()
+            os.remove(new_file.name)
+            raise
+        _sync_close(new_file)
+        # self._file is about to get replaced, so no need to sync.
+        self._file.close()
+        # Make sure the new file's mode is the same as the old file's
+        mode = os.stat(self._path).st_mode
+        os.chmod(new_file.name, mode)
+        try:
+            os.rename(new_file.name, self._path)
+        except OSError, e:
+            if e.errno == errno.EEXIST or \
+              (os.name == 'os2' and e.errno == errno.EACCES):
+                os.remove(self._path)
+                os.rename(new_file.name, self._path)
+            else:
+                raise
+        self._file = open(self._path, 'rb+')
+        self._toc = new_toc
+        self._pending = False
+        self._pending_sync = False
+        if self._locked:
+            _lock_file(self._file, dotlock=False)
+
+    def _pre_mailbox_hook(self, f):
+        """Called before writing the mailbox to file f."""
+        return
+
+    def _pre_message_hook(self, f):
+        """Called before writing each message to file f."""
+        return
+
+    def _post_message_hook(self, f):
+        """Called after writing each message to file f."""
+        return
+
+    def close(self):
+        """Flush and close the mailbox."""
+        self.flush()
+        if self._locked:
+            self.unlock()
+        self._file.close()  # Sync has been done by self.flush() above.
+
+    def _lookup(self, key=None):
+        """Return (start, stop) or raise KeyError."""
+        if self._toc is None:
+            self._generate_toc()
+        if key is not None:
+            try:
+                return self._toc[key]
+            except KeyError:
+                raise KeyError('No message with key: %s' % key)
+
+    def _append_message(self, message):
+        """Append message to mailbox and return (start, stop) offsets."""
+        self._file.seek(0, 2)
+        before = self._file.tell()
+        if len(self._toc) == 0 and not self._pending:
+            # This is the first message, and the _pre_mailbox_hook
+            # hasn't yet been called. If self._pending is True,
+            # messages have been removed, so _pre_mailbox_hook must
+            # have been called already.
+            self._pre_mailbox_hook(self._file)
+        try:
+            self._pre_message_hook(self._file)
+            offsets = self._install_message(message)
+            self._post_message_hook(self._file)
+        except BaseException:
+            self._file.truncate(before)
+            raise
+        self._file.flush()
+        self._file_length = self._file.tell()  # Record current length of mailbox
+        return offsets
+
+
+
+class _mboxMMDF(_singlefileMailbox):
+    """An mbox or MMDF mailbox."""
+
+    _mangle_from_ = True
+
+    def get_message(self, key):
+        """Return a Message representation or raise a KeyError."""
+        start, stop = self._lookup(key)
+        self._file.seek(start)
+        from_line = self._file.readline().replace(os.linesep, '')
+        string = self._file.read(stop - self._file.tell())
+        msg = self._message_factory(string.replace(os.linesep, '\n'))
+        msg.set_from(from_line[5:])
+        return msg
+
+    def get_string(self, key, from_=False):
+        """Return a string representation or raise a KeyError."""
+        start, stop = self._lookup(key)
+        self._file.seek(start)
+        if not from_:
+            self._file.readline()
+        string = self._file.read(stop - self._file.tell())
+        return string.replace(os.linesep, '\n')
+
+    def get_file(self, key, from_=False):
+        """Return a file-like representation or raise a KeyError."""
+        start, stop = self._lookup(key)
+        self._file.seek(start)
+        if not from_:
+            self._file.readline()
+        return _PartialFile(self._file, self._file.tell(), stop)
+
+    def _install_message(self, message):
+        """Format a message and blindly write to self._file."""
+        from_line = None
+        if isinstance(message, str) and message.startswith('From '):
+            newline = message.find('\n')
+            if newline != -1:
+                from_line = message[:newline]
+                message = message[newline + 1:]
+            else:
+                from_line = message
+                message = ''
+        elif isinstance(message, _mboxMMDFMessage):
+            from_line = 'From ' + message.get_from()
+        elif isinstance(message, email.message.Message):
+            from_line = message.get_unixfrom()  # May be None.
+        if from_line is None:
+            from_line = 'From MAILER-DAEMON %s' % time.asctime(time.gmtime())
+        start = self._file.tell()
+        self._file.write(from_line + os.linesep)
+        self._dump_message(message, self._file, self._mangle_from_)
+        stop = self._file.tell()
+        return (start, stop)
+
+
+class mbox(_mboxMMDF):
+    """A classic mbox mailbox."""
+
+    _mangle_from_ = True
+
+    # All messages must end in a newline character, and
+    # _post_message_hooks outputs an empty line between messages.
+    _append_newline = True
+
+    def __init__(self, path, factory=None, create=True):
+        """Initialize an mbox mailbox."""
+        self._message_factory = mboxMessage
+        _mboxMMDF.__init__(self, path, factory, create)
+
+    def _post_message_hook(self, f):
+        """Called after writing each message to file f."""
+        f.write(os.linesep)
+
+    def _generate_toc(self):
+        """Generate key-to-(start, stop) table of contents."""
+        starts, stops = [], []
+        last_was_empty = False
+        self._file.seek(0)
+        while True:
+            line_pos = self._file.tell()
+            line = self._file.readline()
+            if line.startswith('From '):
+                if len(stops) < len(starts):
+                    if last_was_empty:
+                        stops.append(line_pos - len(os.linesep))
+                    else:
+                        # The last line before the "From " line wasn't
+                        # blank, but we consider it a start of a
+                        # message anyway.
+                        stops.append(line_pos)
+                starts.append(line_pos)
+                last_was_empty = False
+            elif not line:
+                if last_was_empty:
+                    stops.append(line_pos - len(os.linesep))
+                else:
+                    stops.append(line_pos)
+                break
+            elif line == os.linesep:
+                last_was_empty = True
+            else:
+                last_was_empty = False
+        self._toc = dict(enumerate(zip(starts, stops)))
+        self._next_key = len(self._toc)
+        self._file_length = self._file.tell()
+
+
+class MMDF(_mboxMMDF):
+    """An MMDF mailbox."""
+
+    def __init__(self, path, factory=None, create=True):
+        """Initialize an MMDF mailbox."""
+        self._message_factory = MMDFMessage
+        _mboxMMDF.__init__(self, path, factory, create)
+
+    def _pre_message_hook(self, f):
+        """Called before writing each message to file f."""
+        f.write('\001\001\001\001' + os.linesep)
+
+    def _post_message_hook(self, f):
+        """Called after writing each message to file f."""
+        f.write(os.linesep + '\001\001\001\001' + os.linesep)
+
+    def _generate_toc(self):
+        """Generate key-to-(start, stop) table of contents."""
+        starts, stops = [], []
+        self._file.seek(0)
+        next_pos = 0
+        while True:
+            line_pos = next_pos
+            line = self._file.readline()
+            next_pos = self._file.tell()
+            if line.startswith('\001\001\001\001' + os.linesep):
+                starts.append(next_pos)
+                while True:
+                    line_pos = next_pos
+                    line = self._file.readline()
+                    next_pos = self._file.tell()
+                    if line == '\001\001\001\001' + os.linesep:
+                        stops.append(line_pos - len(os.linesep))
+                        break
+                    elif line == '':
+                        stops.append(line_pos)
+                        break
+            elif line == '':
+                break
+        self._toc = dict(enumerate(zip(starts, stops)))
+        self._next_key = len(self._toc)
+        self._file.seek(0, 2)
+        self._file_length = self._file.tell()
+
+
+class MH(Mailbox):
+    """An MH mailbox."""
+
+    def __init__(self, path, factory=None, create=True):
+        """Initialize an MH instance."""
+        Mailbox.__init__(self, path, factory, create)
+        if not os.path.exists(self._path):
+            if create:
+                os.mkdir(self._path, 0700)
+                os.close(os.open(os.path.join(self._path, '.mh_sequences'),
+                                 os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0600))
+            else:
+                raise NoSuchMailboxError(self._path)
+        self._locked = False
+
+    def add(self, message):
+        """Add message and return assigned key."""
+        keys = self.keys()
+        if len(keys) == 0:
+            new_key = 1
+        else:
+            new_key = max(keys) + 1
+        new_path = os.path.join(self._path, str(new_key))
+        f = _create_carefully(new_path)
+        closed = False
+        try:
+            if self._locked:
+                _lock_file(f)
+            try:
+                try:
+                    self._dump_message(message, f)
+                except BaseException:
+                    # Unlock and close so it can be deleted on Windows
+                    if self._locked:
+                        _unlock_file(f)
+                    _sync_close(f)
+                    closed = True
+                    os.remove(new_path)
+                    raise
+                if isinstance(message, MHMessage):
+                    self._dump_sequences(message, new_key)
+            finally:
+                if self._locked:
+                    _unlock_file(f)
+        finally:
+            if not closed:
+                _sync_close(f)
+        return new_key
+
+    def remove(self, key):
+        """Remove the keyed message; raise KeyError if it doesn't exist."""
+        path = os.path.join(self._path, str(key))
+        try:
+            f = open(path, 'rb+')
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                raise KeyError('No message with key: %s' % key)
+            else:
+                raise
+        else:
+            f.close()
+            os.remove(path)
+
+    def __setitem__(self, key, message):
+        """Replace the keyed message; raise KeyError if it doesn't exist."""
+        path = os.path.join(self._path, str(key))
+        try:
+            f = open(path, 'rb+')
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                raise KeyError('No message with key: %s' % key)
+            else:
+                raise
+        try:
+            if self._locked:
+                _lock_file(f)
+            try:
+                os.close(os.open(path, os.O_WRONLY | os.O_TRUNC))
+                self._dump_message(message, f)
+                if isinstance(message, MHMessage):
+                    self._dump_sequences(message, key)
+            finally:
+                if self._locked:
+                    _unlock_file(f)
+        finally:
+            _sync_close(f)
+
+    def get_message(self, key):
+        """Return a Message representation or raise a KeyError."""
+        try:
+            if self._locked:
+                f = open(os.path.join(self._path, str(key)), 'r+')
+            else:
+                f = open(os.path.join(self._path, str(key)), 'r')
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                raise KeyError('No message with key: %s' % key)
+            else:
+                raise
+        try:
+            if self._locked:
+                _lock_file(f)
+            try:
+                msg = MHMessage(f)
+            finally:
+                if self._locked:
+                    _unlock_file(f)
+        finally:
+            f.close()
+        for name, key_list in self.get_sequences().iteritems():
+            if key in key_list:
+                msg.add_sequence(name)
+        return msg
+
+    def get_string(self, key):
+        """Return a string representation or raise a KeyError."""
+        try:
+            if self._locked:
+                f = open(os.path.join(self._path, str(key)), 'r+')
+            else:
+                f = open(os.path.join(self._path, str(key)), 'r')
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                raise KeyError('No message with key: %s' % key)
+            else:
+                raise
+        try:
+            if self._locked:
+                _lock_file(f)
+            try:
+                return f.read()
+            finally:
+                if self._locked:
+                    _unlock_file(f)
+        finally:
+            f.close()
+
+    def get_file(self, key):
+        """Return a file-like representation or raise a KeyError."""
+        try:
+            f = open(os.path.join(self._path, str(key)), 'rb')
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                raise KeyError('No message with key: %s' % key)
+            else:
+                raise
+        return _ProxyFile(f)
+
+    def iterkeys(self):
+        """Return an iterator over keys."""
+        return iter(sorted(int(entry) for entry in os.listdir(self._path)
+                                      if entry.isdigit()))
+
+    def has_key(self, key):
+        """Return True if the keyed message exists, False otherwise."""
+        return os.path.exists(os.path.join(self._path, str(key)))
+
+    def __len__(self):
+        """Return a count of messages in the mailbox."""
+        return len(list(self.iterkeys()))
+
+    def lock(self):
+        """Lock the mailbox."""
+        if not self._locked:
+            self._file = open(os.path.join(self._path, '.mh_sequences'), 'rb+')
+            _lock_file(self._file)
+            self._locked = True
+
+    def unlock(self):
+        """Unlock the mailbox if it is locked."""
+        if self._locked:
+            _unlock_file(self._file)
+            _sync_close(self._file)
+            del self._file
+            self._locked = False
+
+    def flush(self):
+        """Write any pending changes to the disk."""
+        return
+
+    def close(self):
+        """Flush and close the mailbox."""
+        if self._locked:
+            self.unlock()
+
+    def list_folders(self):
+        """Return a list of folder names."""
+        result = []
+        for entry in os.listdir(self._path):
+            if os.path.isdir(os.path.join(self._path, entry)):
+                result.append(entry)
+        return result
+
+    def get_folder(self, folder):
+        """Return an MH instance for the named folder."""
+        return MH(os.path.join(self._path, folder),
+                  factory=self._factory, create=False)
+
+    def add_folder(self, folder):
+        """Create a folder and return an MH instance representing it."""
+        return MH(os.path.join(self._path, folder),
+                  factory=self._factory)
+
+    def remove_folder(self, folder):
+        """Delete the named folder, which must be empty."""
+        path = os.path.join(self._path, folder)
+        entries = os.listdir(path)
+        if entries == ['.mh_sequences']:
+            os.remove(os.path.join(path, '.mh_sequences'))
+        elif entries == []:
+            pass
+        else:
+            raise NotEmptyError('Folder not empty: %s' % self._path)
+        os.rmdir(path)
+
+    def get_sequences(self):
+        """Return a name-to-key-list dictionary to define each sequence."""
+        results = {}
+        f = open(os.path.join(self._path, '.mh_sequences'), 'r')
+        try:
+            all_keys = set(self.keys())
+            for line in f:
+                try:
+                    name, contents = line.split(':')
+                    keys = set()
+                    for spec in contents.split():
+                        if spec.isdigit():
+                            keys.add(int(spec))
+                        else:
+                            start, stop = (int(x) for x in spec.split('-'))
+                            keys.update(range(start, stop + 1))
+                    results[name] = [key for key in sorted(keys) \
+                                         if key in all_keys]
+                    if len(results[name]) == 0:
+                        del results[name]
+                except ValueError:
+                    raise FormatError('Invalid sequence specification: %s' %
+                                      line.rstrip())
+        finally:
+            f.close()
+        return results
+
+    def set_sequences(self, sequences):
+        """Set sequences using the given name-to-key-list dictionary."""
+        f = open(os.path.join(self._path, '.mh_sequences'), 'r+')
+        try:
+            os.close(os.open(f.name, os.O_WRONLY | os.O_TRUNC))
+            for name, keys in sequences.iteritems():
+                if len(keys) == 0:
+                    continue
+                f.write('%s:' % name)
+                prev = None
+                completing = False
+                for key in sorted(set(keys)):
+                    if key - 1 == prev:
+                        if not completing:
+                            completing = True
+                            f.write('-')
+                    elif completing:
+                        completing = False
+                        f.write('%s %s' % (prev, key))
+                    else:
+                        f.write(' %s' % key)
+                    prev = key
+                if completing:
+                    f.write(str(prev) + '\n')
+                else:
+                    f.write('\n')
+        finally:
+            _sync_close(f)
+
+    def pack(self):
+        """Re-name messages to eliminate numbering gaps. Invalidates keys."""
+        sequences = self.get_sequences()
+        prev = 0
+        changes = []
+        for key in self.iterkeys():
+            if key - 1 != prev:
+                changes.append((key, prev + 1))
+                if hasattr(os, 'link'):
+                    os.link(os.path.join(self._path, str(key)),
+                            os.path.join(self._path, str(prev + 1)))
+                    os.unlink(os.path.join(self._path, str(key)))
+                else:
+                    os.rename(os.path.join(self._path, str(key)),
+                              os.path.join(self._path, str(prev + 1)))
+            prev += 1
+        self._next_key = prev + 1
+        if len(changes) == 0:
+            return
+        for name, key_list in sequences.items():
+            for old, new in changes:
+                if old in key_list:
+                    key_list[key_list.index(old)] = new
+        self.set_sequences(sequences)
+
+    def _dump_sequences(self, message, key):
+        """Inspect a new MHMessage and update sequences appropriately."""
+        pending_sequences = message.get_sequences()
+        all_sequences = self.get_sequences()
+        for name, key_list in all_sequences.iteritems():
+            if name in pending_sequences:
+                key_list.append(key)
+            elif key in key_list:
+                del key_list[key_list.index(key)]
+        for sequence in pending_sequences:
+            if sequence not in all_sequences:
+                all_sequences[sequence] = [key]
+        self.set_sequences(all_sequences)
+
+
+class Babyl(_singlefileMailbox):
+    """An Rmail-style Babyl mailbox."""
+
+    _special_labels = frozenset(('unseen', 'deleted', 'filed', 'answered',
+                                 'forwarded', 'edited', 'resent'))
+
+    def __init__(self, path, factory=None, create=True):
+        """Initialize a Babyl mailbox."""
+        _singlefileMailbox.__init__(self, path, factory, create)
+        self._labels = {}
+
+    def add(self, message):
+        """Add message and return assigned key."""
+        key = _singlefileMailbox.add(self, message)
+        if isinstance(message, BabylMessage):
+            self._labels[key] = message.get_labels()
+        return key
+
+    def remove(self, key):
+        """Remove the keyed message; raise KeyError if it doesn't exist."""
+        _singlefileMailbox.remove(self, key)
+        if key in self._labels:
+            del self._labels[key]
+
+    def __setitem__(self, key, message):
+        """Replace the keyed message; raise KeyError if it doesn't exist."""
+        _singlefileMailbox.__setitem__(self, key, message)
+        if isinstance(message, BabylMessage):
+            self._labels[key] = message.get_labels()
+
+    def get_message(self, key):
+        """Return a Message representation or raise a KeyError."""
+        start, stop = self._lookup(key)
+        self._file.seek(start)
+        self._file.readline()   # Skip '1,' line specifying labels.
+        original_headers = StringIO.StringIO()
+        while True:
+            line = self._file.readline()
+            if line == '*** EOOH ***' + os.linesep or line == '':
+                break
+            original_headers.write(line.replace(os.linesep, '\n'))
+        visible_headers = StringIO.StringIO()
+        while True:
+            line = self._file.readline()
+            if line == os.linesep or line == '':
+                break
+            visible_headers.write(line.replace(os.linesep, '\n'))
+        body = self._file.read(stop - self._file.tell()).replace(os.linesep,
+                                                                 '\n')
+        msg = BabylMessage(original_headers.getvalue() + body)
+        msg.set_visible(visible_headers.getvalue())
+        if key in self._labels:
+            msg.set_labels(self._labels[key])
+        return msg
+
+    def get_string(self, key):
+        """Return a string representation or raise a KeyError."""
+        start, stop = self._lookup(key)
+        self._file.seek(start)
+        self._file.readline()   # Skip '1,' line specifying labels.
+        original_headers = StringIO.StringIO()
+        while True:
+            line = self._file.readline()
+            if line == '*** EOOH ***' + os.linesep or line == '':
+                break
+            original_headers.write(line.replace(os.linesep, '\n'))
+        while True:
+            line = self._file.readline()
+            if line == os.linesep or line == '':
+                break
+        return original_headers.getvalue() + \
+               self._file.read(stop - self._file.tell()).replace(os.linesep,
+                                                                 '\n')
+
+    def get_file(self, key):
+        """Return a file-like representation or raise a KeyError."""
+        return StringIO.StringIO(self.get_string(key).replace('\n',
+                                                              os.linesep))
+
+    def get_labels(self):
+        """Return a list of user-defined labels in the mailbox."""
+        self._lookup()
+        labels = set()
+        for label_list in self._labels.values():
+            labels.update(label_list)
+        labels.difference_update(self._special_labels)
+        return list(labels)
+
+    def _generate_toc(self):
+        """Generate key-to-(start, stop) table of contents."""
+        starts, stops = [], []
+        self._file.seek(0)
+        next_pos = 0
+        label_lists = []
+        while True:
+            line_pos = next_pos
+            line = self._file.readline()
+            next_pos = self._file.tell()
+            if line == '\037\014' + os.linesep:
+                if len(stops) < len(starts):
+                    stops.append(line_pos - len(os.linesep))
+                starts.append(next_pos)
+                labels = [label.strip() for label
+                                        in self._file.readline()[1:].split(',')
+                                        if label.strip() != '']
+                label_lists.append(labels)
+            elif line == '\037' or line == '\037' + os.linesep:
+                if len(stops) < len(starts):
+                    stops.append(line_pos - len(os.linesep))
+            elif line == '':
+                stops.append(line_pos - len(os.linesep))
+                break
+        self._toc = dict(enumerate(zip(starts, stops)))
+        self._labels = dict(enumerate(label_lists))
+        self._next_key = len(self._toc)
+        self._file.seek(0, 2)
+        self._file_length = self._file.tell()
+
+    def _pre_mailbox_hook(self, f):
+        """Called before writing the mailbox to file f."""
+        f.write('BABYL OPTIONS:%sVersion: 5%sLabels:%s%s\037' %
+                (os.linesep, os.linesep, ','.join(self.get_labels()),
+                 os.linesep))
+
+    def _pre_message_hook(self, f):
+        """Called before writing each message to file f."""
+        f.write('\014' + os.linesep)
+
+    def _post_message_hook(self, f):
+        """Called after writing each message to file f."""
+        f.write(os.linesep + '\037')
+
+    def _install_message(self, message):
+        """Write message contents and return (start, stop)."""
+        start = self._file.tell()
+        if isinstance(message, BabylMessage):
+            special_labels = []
+            labels = []
+            for label in message.get_labels():
+                if label in self._special_labels:
+                    special_labels.append(label)
+                else:
+                    labels.append(label)
+            self._file.write('1')
+            for label in special_labels:
+                self._file.write(', ' + label)
+            self._file.write(',,')
+            for label in labels:
+                self._file.write(' ' + label + ',')
+            self._file.write(os.linesep)
+        else:
+            self._file.write('1,,' + os.linesep)
+        if isinstance(message, email.message.Message):
+            orig_buffer = StringIO.StringIO()
+            orig_generator = email.generator.Generator(orig_buffer, False, 0)
+            orig_generator.flatten(message)
+            orig_buffer.seek(0)
+            while True:
+                line = orig_buffer.readline()
+                self._file.write(line.replace('\n', os.linesep))
+                if line == '\n' or line == '':
+                    break
+            self._file.write('*** EOOH ***' + os.linesep)
+            if isinstance(message, BabylMessage):
+                vis_buffer = StringIO.StringIO()
+                vis_generator = email.generator.Generator(vis_buffer, False, 0)
+                vis_generator.flatten(message.get_visible())
+                while True:
+                    line = vis_buffer.readline()
+                    self._file.write(line.replace('\n', os.linesep))
+                    if line == '\n' or line == '':
+                        break
+            else:
+                orig_buffer.seek(0)
+                while True:
+                    line = orig_buffer.readline()
+                    self._file.write(line.replace('\n', os.linesep))
+                    if line == '\n' or line == '':
+                        break
+            while True:
+                buffer = orig_buffer.read(4096) # Buffer size is arbitrary.
+                if buffer == '':
+                    break
+                self._file.write(buffer.replace('\n', os.linesep))
+        elif isinstance(message, str):
+            body_start = message.find('\n\n') + 2
+            if body_start - 2 != -1:
+                self._file.write(message[:body_start].replace('\n',
+                                                              os.linesep))
+                self._file.write('*** EOOH ***' + os.linesep)
+                self._file.write(message[:body_start].replace('\n',
+                                                              os.linesep))
+                self._file.write(message[body_start:].replace('\n',
+                                                              os.linesep))
+            else:
+                self._file.write('*** EOOH ***' + os.linesep + os.linesep)
+                self._file.write(message.replace('\n', os.linesep))
+        elif hasattr(message, 'readline'):
+            original_pos = message.tell()
+            first_pass = True
+            while True:
+                line = message.readline()
+                self._file.write(line.replace('\n', os.linesep))
+                if line == '\n' or line == '':
+                    if first_pass:
+                        first_pass = False
+                        self._file.write('*** EOOH ***' + os.linesep)
+                        message.seek(original_pos)
+                    else:
+                        break
+            while True:
+                buffer = message.read(4096)     # Buffer size is arbitrary.
+                if buffer == '':
+                    break
+                self._file.write(buffer.replace('\n', os.linesep))
+        else:
+            raise TypeError('Invalid message type: %s' % type(message))
+        stop = self._file.tell()
+        return (start, stop)
+
+
+class Message(email.message.Message):
+    """Message with mailbox-format-specific properties."""
+
+    def __init__(self, message=None):
+        """Initialize a Message instance."""
+        if isinstance(message, email.message.Message):
+            self._become_message(copy.deepcopy(message))
+            if isinstance(message, Message):
+                message._explain_to(self)
+        elif isinstance(message, str):
+            self._become_message(email.message_from_string(message))
+        elif hasattr(message, "read"):
+            self._become_message(email.message_from_file(message))
+        elif message is None:
+            email.message.Message.__init__(self)
+        else:
+            raise TypeError('Invalid message type: %s' % type(message))
+
+    def _become_message(self, message):
+        """Assume the non-format-specific state of message."""
+        for name in ('_headers', '_unixfrom', '_payload', '_charset',
+                     'preamble', 'epilogue', 'defects', '_default_type'):
+            self.__dict__[name] = message.__dict__[name]
+
+    def _explain_to(self, message):
+        """Copy format-specific state to message insofar as possible."""
+        if isinstance(message, Message):
+            return  # There's nothing format-specific to explain.
+        else:
+            raise TypeError('Cannot convert to specified type')
+
+
+class MaildirMessage(Message):
+    """Message with Maildir-specific properties."""
+
+    def __init__(self, message=None):
+        """Initialize a MaildirMessage instance."""
+        self._subdir = 'new'
+        self._info = ''
+        self._date = time.time()
+        Message.__init__(self, message)
+
+    def get_subdir(self):
+        """Return 'new' or 'cur'."""
+        return self._subdir
+
+    def set_subdir(self, subdir):
+        """Set subdir to 'new' or 'cur'."""
+        if subdir == 'new' or subdir == 'cur':
+            self._subdir = subdir
+        else:
+            raise ValueError("subdir must be 'new' or 'cur': %s" % subdir)
+
+    def get_flags(self):
+        """Return as a string the flags that are set."""
+        if self._info.startswith('2,'):
+            return self._info[2:]
+        else:
+            return ''
+
+    def set_flags(self, flags):
+        """Set the given flags and unset all others."""
+        self._info = '2,' + ''.join(sorted(flags))
+
+    def add_flag(self, flag):
+        """Set the given flag(s) without changing others."""
+        self.set_flags(''.join(set(self.get_flags()) | set(flag)))
+
+    def remove_flag(self, flag):
+        """Unset the given string flag(s) without changing others."""
+        if self.get_flags() != '':
+            self.set_flags(''.join(set(self.get_flags()) - set(flag)))
+
+    def get_date(self):
+        """Return delivery date of message, in seconds since the epoch."""
+        return self._date
+
+    def set_date(self, date):
+        """Set delivery date of message, in seconds since the epoch."""
+        try:
+            self._date = float(date)
+        except ValueError:
+            raise TypeError("can't convert to float: %s" % date)
+
+    def get_info(self):
+        """Get the message's "info" as a string."""
+        return self._info
+
+    def set_info(self, info):
+        """Set the message's "info" string."""
+        if isinstance(info, str):
+            self._info = info
+        else:
+            raise TypeError('info must be a string: %s' % type(info))
+
+    def _explain_to(self, message):
+        """Copy Maildir-specific state to message insofar as possible."""
+        if isinstance(message, MaildirMessage):
+            message.set_flags(self.get_flags())
+            message.set_subdir(self.get_subdir())
+            message.set_date(self.get_date())
+        elif isinstance(message, _mboxMMDFMessage):
+            flags = set(self.get_flags())
+            if 'S' in flags:
+                message.add_flag('R')
+            if self.get_subdir() == 'cur':
+                message.add_flag('O')
+            if 'T' in flags:
+                message.add_flag('D')
+            if 'F' in flags:
+                message.add_flag('F')
+            if 'R' in flags:
+                message.add_flag('A')
+            message.set_from('MAILER-DAEMON', time.gmtime(self.get_date()))
+        elif isinstance(message, MHMessage):
+            flags = set(self.get_flags())
+            if 'S' not in flags:
+                message.add_sequence('unseen')
+            if 'R' in flags:
+                message.add_sequence('replied')
+            if 'F' in flags:
+                message.add_sequence('flagged')
+        elif isinstance(message, BabylMessage):
+            flags = set(self.get_flags())
+            if 'S' not in flags:
+                message.add_label('unseen')
+            if 'T' in flags:
+                message.add_label('deleted')
+            if 'R' in flags:
+                message.add_label('answered')
+            if 'P' in flags:
+                message.add_label('forwarded')
+        elif isinstance(message, Message):
+            pass
+        else:
+            raise TypeError('Cannot convert to specified type: %s' %
+                            type(message))
+
+
+class _mboxMMDFMessage(Message):
+    """Message with mbox- or MMDF-specific properties."""
+
+    def __init__(self, message=None):
+        """Initialize an mboxMMDFMessage instance."""
+        self.set_from('MAILER-DAEMON', True)
+        if isinstance(message, email.message.Message):
+            unixfrom = message.get_unixfrom()
+            if unixfrom is not None and unixfrom.startswith('From '):
+                self.set_from(unixfrom[5:])
+        Message.__init__(self, message)
+
+    def get_from(self):
+        """Return contents of "From " line."""
+        return self._from
+
+    def set_from(self, from_, time_=None):
+        """Set "From " line, formatting and appending time_ if specified."""
+        if time_ is not None:
+            if time_ is True:
+                time_ = time.gmtime()
+            from_ += ' ' + time.asctime(time_)
+        self._from = from_
+
+    def get_flags(self):
+        """Return as a string the flags that are set."""
+        return self.get('Status', '') + self.get('X-Status', '')
+
+    def set_flags(self, flags):
+        """Set the given flags and unset all others."""
+        flags = set(flags)
+        status_flags, xstatus_flags = '', ''
+        for flag in ('R', 'O'):
+            if flag in flags:
+                status_flags += flag
+                flags.remove(flag)
+        for flag in ('D', 'F', 'A'):
+            if flag in flags:
+                xstatus_flags += flag
+                flags.remove(flag)
+        xstatus_flags += ''.join(sorted(flags))
+        try:
+            self.replace_header('Status', status_flags)
+        except KeyError:
+            self.add_header('Status', status_flags)
+        try:
+            self.replace_header('X-Status', xstatus_flags)
+        except KeyError:
+            self.add_header('X-Status', xstatus_flags)
+
+    def add_flag(self, flag):
+        """Set the given flag(s) without changing others."""
+        self.set_flags(''.join(set(self.get_flags()) | set(flag)))
+
+    def remove_flag(self, flag):
+        """Unset the given string flag(s) without changing others."""
+        if 'Status' in self or 'X-Status' in self:
+            self.set_flags(''.join(set(self.get_flags()) - set(flag)))
+
+    def _explain_to(self, message):
+        """Copy mbox- or MMDF-specific state to message insofar as possible."""
+        if isinstance(message, MaildirMessage):
+            flags = set(self.get_flags())
+            if 'O' in flags:
+                message.set_subdir('cur')
+            if 'F' in flags:
+                message.add_flag('F')
+            if 'A' in flags:
+                message.add_flag('R')
+            if 'R' in flags:
+                message.add_flag('S')
+            if 'D' in flags:
+                message.add_flag('T')
+            del message['status']
+            del message['x-status']
+            maybe_date = ' '.join(self.get_from().split()[-5:])
+            try:
+                message.set_date(calendar.timegm(time.strptime(maybe_date,
+                                                      '%a %b %d %H:%M:%S %Y')))
+            except (ValueError, OverflowError):
+                pass
+        elif isinstance(message, _mboxMMDFMessage):
+            message.set_flags(self.get_flags())
+            message.set_from(self.get_from())
+        elif isinstance(message, MHMessage):
+            flags = set(self.get_flags())
+            if 'R' not in flags:
+                message.add_sequence('unseen')
+            if 'A' in flags:
+                message.add_sequence('replied')
+            if 'F' in flags:
+                message.add_sequence('flagged')
+            del message['status']
+            del message['x-status']
+        elif isinstance(message, BabylMessage):
+            flags = set(self.get_flags())
+            if 'R' not in flags:
+                message.add_label('unseen')
+            if 'D' in flags:
+                message.add_label('deleted')
+            if 'A' in flags:
+                message.add_label('answered')
+            del message['status']
+            del message['x-status']
+        elif isinstance(message, Message):
+            pass
+        else:
+            raise TypeError('Cannot convert to specified type: %s' %
+                            type(message))
+
+
+class mboxMessage(_mboxMMDFMessage):
+    """Message with mbox-specific properties."""
+
+
+class MHMessage(Message):
+    """Message with MH-specific properties."""
+
+    def __init__(self, message=None):
+        """Initialize an MHMessage instance."""
+        self._sequences = []
+        Message.__init__(self, message)
+
+    def get_sequences(self):
+        """Return a list of sequences that include the message."""
+        return self._sequences[:]
+
+    def set_sequences(self, sequences):
+        """Set the list of sequences that include the message."""
+        self._sequences = list(sequences)
+
+    def add_sequence(self, sequence):
+        """Add sequence to list of sequences including the message."""
+        if isinstance(sequence, str):
+            if not sequence in self._sequences:
+                self._sequences.append(sequence)
+        else:
+            raise TypeError('sequence must be a string: %s' % type(sequence))
+
+    def remove_sequence(self, sequence):
+        """Remove sequence from the list of sequences including the message."""
+        try:
+            self._sequences.remove(sequence)
+        except ValueError:
+            pass
+
+    def _explain_to(self, message):
+        """Copy MH-specific state to message insofar as possible."""
+        if isinstance(message, MaildirMessage):
+            sequences = set(self.get_sequences())
+            if 'unseen' in sequences:
+                message.set_subdir('cur')
+            else:
+                message.set_subdir('cur')
+                message.add_flag('S')
+            if 'flagged' in sequences:
+                message.add_flag('F')
+            if 'replied' in sequences:
+                message.add_flag('R')
+        elif isinstance(message, _mboxMMDFMessage):
+            sequences = set(self.get_sequences())
+            if 'unseen' not in sequences:
+                message.add_flag('RO')
+            else:
+                message.add_flag('O')
+            if 'flagged' in sequences:
+                message.add_flag('F')
+            if 'replied' in sequences:
+                message.add_flag('A')
+        elif isinstance(message, MHMessage):
+            for sequence in self.get_sequences():
+                message.add_sequence(sequence)
+        elif isinstance(message, BabylMessage):
+            sequences = set(self.get_sequences())
+            if 'unseen' in sequences:
+                message.add_label('unseen')
+            if 'replied' in sequences:
+                message.add_label('answered')
+        elif isinstance(message, Message):
+            pass
+        else:
+            raise TypeError('Cannot convert to specified type: %s' %
+                            type(message))
+
+
+class BabylMessage(Message):
+    """Message with Babyl-specific properties."""
+
+    def __init__(self, message=None):
+        """Initialize an BabylMessage instance."""
+        self._labels = []
+        self._visible = Message()
+        Message.__init__(self, message)
+
+    def get_labels(self):
+        """Return a list of labels on the message."""
+        return self._labels[:]
+
+    def set_labels(self, labels):
+        """Set the list of labels on the message."""
+        self._labels = list(labels)
+
+    def add_label(self, label):
+        """Add label to list of labels on the message."""
+        if isinstance(label, str):
+            if label not in self._labels:
+                self._labels.append(label)
+        else:
+            raise TypeError('label must be a string: %s' % type(label))
+
+    def remove_label(self, label):
+        """Remove label from the list of labels on the message."""
+        try:
+            self._labels.remove(label)
+        except ValueError:
+            pass
+
+    def get_visible(self):
+        """Return a Message representation of visible headers."""
+        return Message(self._visible)
+
+    def set_visible(self, visible):
+        """Set the Message representation of visible headers."""
+        self._visible = Message(visible)
+
+    def update_visible(self):
+        """Update and/or sensibly generate a set of visible headers."""
+        for header in self._visible.keys():
+            if header in self:
+                self._visible.replace_header(header, self[header])
+            else:
+                del self._visible[header]
+        for header in ('Date', 'From', 'Reply-To', 'To', 'CC', 'Subject'):
+            if header in self and header not in self._visible:
+                self._visible[header] = self[header]
+
+    def _explain_to(self, message):
+        """Copy Babyl-specific state to message insofar as possible."""
+        if isinstance(message, MaildirMessage):
+            labels = set(self.get_labels())
+            if 'unseen' in labels:
+                message.set_subdir('cur')
+            else:
+                message.set_subdir('cur')
+                message.add_flag('S')
+            if 'forwarded' in labels or 'resent' in labels:
+                message.add_flag('P')
+            if 'answered' in labels:
+                message.add_flag('R')
+            if 'deleted' in labels:
+                message.add_flag('T')
+        elif isinstance(message, _mboxMMDFMessage):
+            labels = set(self.get_labels())
+            if 'unseen' not in labels:
+                message.add_flag('RO')
+            else:
+                message.add_flag('O')
+            if 'deleted' in labels:
+                message.add_flag('D')
+            if 'answered' in labels:
+                message.add_flag('A')
+        elif isinstance(message, MHMessage):
+            labels = set(self.get_labels())
+            if 'unseen' in labels:
+                message.add_sequence('unseen')
+            if 'answered' in labels:
+                message.add_sequence('replied')
+        elif isinstance(message, BabylMessage):
+            message.set_visible(self.get_visible())
+            for label in self.get_labels():
+                message.add_label(label)
+        elif isinstance(message, Message):
+            pass
+        else:
+            raise TypeError('Cannot convert to specified type: %s' %
+                            type(message))
+
+
+class MMDFMessage(_mboxMMDFMessage):
+    """Message with MMDF-specific properties."""
+
+
+class _ProxyFile:
+    """A read-only wrapper of a file."""
+
+    def __init__(self, f, pos=None):
+        """Initialize a _ProxyFile."""
+        self._file = f
+        if pos is None:
+            self._pos = f.tell()
+        else:
+            self._pos = pos
+
+    def read(self, size=None):
+        """Read bytes."""
+        return self._read(size, self._file.read)
+
+    def readline(self, size=None):
+        """Read a line."""
+        return self._read(size, self._file.readline)
+
+    def readlines(self, sizehint=None):
+        """Read multiple lines."""
+        result = []
+        for line in self:
+            result.append(line)
+            if sizehint is not None:
+                sizehint -= len(line)
+                if sizehint <= 0:
+                    break
+        return result
+
+    def __iter__(self):
+        """Iterate over lines."""
+        return iter(self.readline, "")
+
+    def tell(self):
+        """Return the position."""
+        return self._pos
+
+    def seek(self, offset, whence=0):
+        """Change position."""
+        if whence == 1:
+            self._file.seek(self._pos)
+        self._file.seek(offset, whence)
+        self._pos = self._file.tell()
+
+    def close(self):
+        """Close the file."""
+        if hasattr(self, '_file'):
+            if hasattr(self._file, 'close'):
+                self._file.close()
+            del self._file
+
+    def _read(self, size, read_method):
+        """Read size bytes using read_method."""
+        if size is None:
+            size = -1
+        self._file.seek(self._pos)
+        result = read_method(size)
+        self._pos = self._file.tell()
+        return result
+
+
+class _PartialFile(_ProxyFile):
+    """A read-only wrapper of part of a file."""
+
+    def __init__(self, f, start=None, stop=None):
+        """Initialize a _PartialFile."""
+        _ProxyFile.__init__(self, f, start)
+        self._start = start
+        self._stop = stop
+
+    def tell(self):
+        """Return the position with respect to start."""
+        return _ProxyFile.tell(self) - self._start
+
+    def seek(self, offset, whence=0):
+        """Change position, possibly with respect to start or stop."""
+        if whence == 0:
+            self._pos = self._start
+            whence = 1
+        elif whence == 2:
+            self._pos = self._stop
+            whence = 1
+        _ProxyFile.seek(self, offset, whence)
+
+    def _read(self, size, read_method):
+        """Read size bytes using read_method, honoring start and stop."""
+        remaining = self._stop - self._pos
+        if remaining <= 0:
+            return ''
+        if size is None or size < 0 or size > remaining:
+            size = remaining
+        return _ProxyFile._read(self, size, read_method)
+
+    def close(self):
+        # do *not* close the underlying file object for partial files,
+        # since it's global to the mailbox object
+        if hasattr(self, '_file'):
+            del self._file
+
+
+def _lock_file(f, dotlock=True):
+    """Lock file f using lockf and dot locking."""
+    dotlock_done = False
+    try:
+        if fcntl:
+            try:
+                fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
+            except IOError, e:
+                if e.errno in (errno.EAGAIN, errno.EACCES, errno.EROFS):
+                    raise ExternalClashError('lockf: lock unavailable: %s' %
+                                             f.name)
+                else:
+                    raise
+        if dotlock:
+            try:
+                pre_lock = _create_temporary(f.name + '.lock')
+                pre_lock.close()
+            except IOError, e:
+                if e.errno in (errno.EACCES, errno.EROFS):
+                    return  # Without write access, just skip dotlocking.
+                else:
+                    raise
+            try:
+                if hasattr(os, 'link'):
+                    os.link(pre_lock.name, f.name + '.lock')
+                    dotlock_done = True
+                    os.unlink(pre_lock.name)
+                else:
+                    os.rename(pre_lock.name, f.name + '.lock')
+                    dotlock_done = True
+            except OSError, e:
+                if e.errno == errno.EEXIST or \
+                  (os.name == 'os2' and e.errno == errno.EACCES):
+                    os.remove(pre_lock.name)
+                    raise ExternalClashError('dot lock unavailable: %s' %
+                                             f.name)
+                else:
+                    raise
+    except:
+        if fcntl:
+            fcntl.lockf(f, fcntl.LOCK_UN)
+        if dotlock_done:
+            os.remove(f.name + '.lock')
+        raise
+
+def _unlock_file(f):
+    """Unlock file f using lockf and dot locking."""
+    if fcntl:
+        fcntl.lockf(f, fcntl.LOCK_UN)
+    if os.path.exists(f.name + '.lock'):
+        os.remove(f.name + '.lock')
+
+def _create_carefully(path):
+    """Create a file if it doesn't exist and open for reading and writing."""
+    fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0666)
+    try:
+        return open(path, 'rb+')
+    finally:
+        os.close(fd)
+
+def _create_temporary(path):
+    """Create a temp file based on path and open for reading and writing."""
+    return _create_carefully('%s.%s.%s.%s' % (path, int(time.time()),
+                                              socket.gethostname(),
+                                              os.getpid()))
+
+def _sync_flush(f):
+    """Ensure changes to file f are physically on disk."""
+    f.flush()
+    if hasattr(os, 'fsync'):
+        os.fsync(f.fileno())
+
+def _sync_close(f):
+    """Close file f, ensuring all changes are physically on disk."""
+    _sync_flush(f)
+    f.close()
+
+## Start: classes from the original module (for backward compatibility).
+
+# Note that the Maildir class, whose name is unchanged, itself offers a next()
+# method for backward compatibility.
+
+class _Mailbox:
+
+    def __init__(self, fp, factory=rfc822.Message):
+        self.fp = fp
+        self.seekp = 0
+        self.factory = factory
+
+    def __iter__(self):
+        return iter(self.next, None)
+
+    def next(self):
+        while 1:
+            self.fp.seek(self.seekp)
+            try:
+                self._search_start()
+            except EOFError:
+                self.seekp = self.fp.tell()
+                return None
+            start = self.fp.tell()
+            self._search_end()
+            self.seekp = stop = self.fp.tell()
+            if start != stop:
+                break
+        return self.factory(_PartialFile(self.fp, start, stop))
+
+# Recommended to use PortableUnixMailbox instead!
+class UnixMailbox(_Mailbox):
+
+    def _search_start(self):
+        while 1:
+            pos = self.fp.tell()
+            line = self.fp.readline()
+            if not line:
+                raise EOFError
+            if line[:5] == 'From ' and self._isrealfromline(line):
+                self.fp.seek(pos)
+                return
+
+    def _search_end(self):
+        self.fp.readline()      # Throw away header line
+        while 1:
+            pos = self.fp.tell()
+            line = self.fp.readline()
+            if not line:
+                return
+            if line[:5] == 'From ' and self._isrealfromline(line):
+                self.fp.seek(pos)
+                return
+
+    # An overridable mechanism to test for From-line-ness.  You can either
+    # specify a different regular expression or define a whole new
+    # _isrealfromline() method.  Note that this only gets called for lines
+    # starting with the 5 characters "From ".
+    #
+    # BAW: According to
+    #http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html
+    # the only portable, reliable way to find message delimiters in a BSD (i.e
+    # Unix mailbox) style folder is to search for "\n\nFrom .*\n", or at the
+    # beginning of the file, "^From .*\n".  While _fromlinepattern below seems
+    # like a good idea, in practice, there are too many variations for more
+    # strict parsing of the line to be completely accurate.
+    #
+    # _strict_isrealfromline() is the old version which tries to do stricter
+    # parsing of the From_ line.  _portable_isrealfromline() simply returns
+    # true, since it's never called if the line doesn't already start with
+    # "From ".
+    #
+    # This algorithm, and the way it interacts with _search_start() and
+    # _search_end() may not be completely correct, because it doesn't check
+    # that the two characters preceding "From " are \n\n or the beginning of
+    # the file.  Fixing this would require a more extensive rewrite than is
+    # necessary.  For convenience, we've added a PortableUnixMailbox class
+    # which does no checking of the format of the 'From' line.
+
+    _fromlinepattern = (r"From \s*[^\s]+\s+\w\w\w\s+\w\w\w\s+\d?\d\s+"
+                        r"\d?\d:\d\d(:\d\d)?(\s+[^\s]+)?\s+\d\d\d\d\s*"
+                        r"[^\s]*\s*"
+                        "$")
+    _regexp = None
+
+    def _strict_isrealfromline(self, line):
+        if not self._regexp:
+            import re
+            self._regexp = re.compile(self._fromlinepattern)
+        return self._regexp.match(line)
+
+    def _portable_isrealfromline(self, line):
+        return True
+
+    _isrealfromline = _strict_isrealfromline
+
+
+class PortableUnixMailbox(UnixMailbox):
+    _isrealfromline = UnixMailbox._portable_isrealfromline
+
+
+class MmdfMailbox(_Mailbox):
+
+    def _search_start(self):
+        while 1:
+            line = self.fp.readline()
+            if not line:
+                raise EOFError
+            if line[:5] == '\001\001\001\001\n':
+                return
+
+    def _search_end(self):
+        while 1:
+            pos = self.fp.tell()
+            line = self.fp.readline()
+            if not line:
+                return
+            if line == '\001\001\001\001\n':
+                self.fp.seek(pos)
+                return
+
+
+class MHMailbox:
+
+    def __init__(self, dirname, factory=rfc822.Message):
+        import re
+        pat = re.compile('^[1-9][0-9]*$')
+        self.dirname = dirname
+        # the three following lines could be combined into:
+        # list = map(long, filter(pat.match, os.listdir(self.dirname)))
+        list = os.listdir(self.dirname)
+        list = filter(pat.match, list)
+        list = map(long, list)
+        list.sort()
+        # This only works in Python 1.6 or later;
+        # before that str() added 'L':
+        self.boxes = map(str, list)
+        self.boxes.reverse()
+        self.factory = factory
+
+    def __iter__(self):
+        return iter(self.next, None)
+
+    def next(self):
+        if not self.boxes:
+            return None
+        fn = self.boxes.pop()
+        fp = open(os.path.join(self.dirname, fn))
+        msg = self.factory(fp)
+        try:
+            msg._mh_msgno = fn
+        except (AttributeError, TypeError):
+            pass
+        return msg
+
+
+class BabylMailbox(_Mailbox):
+
+    def _search_start(self):
+        while 1:
+            line = self.fp.readline()
+            if not line:
+                raise EOFError
+            if line == '*** EOOH ***\n':
+                return
+
+    def _search_end(self):
+        while 1:
+            pos = self.fp.tell()
+            line = self.fp.readline()
+            if not line:
+                return
+            if line == '\037\014\n' or line == '\037':
+                self.fp.seek(pos)
+                return
+
+## End: classes from the original module (for backward compatibility).
+
+
+class Error(Exception):
+    """Raised for module-specific errors."""
+
+class NoSuchMailboxError(Error):
+    """The specified mailbox does not exist and won't be created."""
+
+class NotEmptyError(Error):
+    """The specified mailbox is not empty and deletion was requested."""
+
+class ExternalClashError(Error):
+    """Another process caused an action to fail."""
+
+class FormatError(Error):
+    """A file appears to have an invalid format."""
diff --git a/src/main/resources/PythonLibs/mailcap.py b/src/main/resources/PythonLibs/mailcap.py
new file mode 100644
index 0000000000000000000000000000000000000000..b2ddacd046db4555b65ebd84455dc38a70e9b486
--- /dev/null
+++ b/src/main/resources/PythonLibs/mailcap.py
@@ -0,0 +1,255 @@
+"""Mailcap file handling.  See RFC 1524."""
+
+import os
+
+__all__ = ["getcaps","findmatch"]
+
+# Part 1: top-level interface.
+
+def getcaps():
+    """Return a dictionary containing the mailcap database.
+
+    The dictionary maps a MIME type (in all lowercase, e.g. 'text/plain')
+    to a list of dictionaries corresponding to mailcap entries.  The list
+    collects all the entries for that MIME type from all available mailcap
+    files.  Each dictionary contains key-value pairs for that MIME type,
+    where the viewing command is stored with the key "view".
+
+    """
+    caps = {}
+    for mailcap in listmailcapfiles():
+        try:
+            fp = open(mailcap, 'r')
+        except IOError:
+            continue
+        morecaps = readmailcapfile(fp)
+        fp.close()
+        for key, value in morecaps.iteritems():
+            if not key in caps:
+                caps[key] = value
+            else:
+                caps[key] = caps[key] + value
+    return caps
+
+def listmailcapfiles():
+    """Return a list of all mailcap files found on the system."""
+    # XXX Actually, this is Unix-specific
+    if 'MAILCAPS' in os.environ:
+        str = os.environ['MAILCAPS']
+        mailcaps = str.split(':')
+    else:
+        if 'HOME' in os.environ:
+            home = os.environ['HOME']
+        else:
+            # Don't bother with getpwuid()
+            home = '.' # Last resort
+        mailcaps = [home + '/.mailcap', '/etc/mailcap',
+                '/usr/etc/mailcap', '/usr/local/etc/mailcap']
+    return mailcaps
+
+
+# Part 2: the parser.
+
+def readmailcapfile(fp):
+    """Read a mailcap file and return a dictionary keyed by MIME type.
+
+    Each MIME type is mapped to an entry consisting of a list of
+    dictionaries; the list will contain more than one such dictionary
+    if a given MIME type appears more than once in the mailcap file.
+    Each dictionary contains key-value pairs for that MIME type, where
+    the viewing command is stored with the key "view".
+    """
+    caps = {}
+    while 1:
+        line = fp.readline()
+        if not line: break
+        # Ignore comments and blank lines
+        if line[0] == '#' or line.strip() == '':
+            continue
+        nextline = line
+        # Join continuation lines
+        while nextline[-2:] == '\\\n':
+            nextline = fp.readline()
+            if not nextline: nextline = '\n'
+            line = line[:-2] + nextline
+        # Parse the line
+        key, fields = parseline(line)
+        if not (key and fields):
+            continue
+        # Normalize the key
+        types = key.split('/')
+        for j in range(len(types)):
+            types[j] = types[j].strip()
+        key = '/'.join(types).lower()
+        # Update the database
+        if key in caps:
+            caps[key].append(fields)
+        else:
+            caps[key] = [fields]
+    return caps
+
+def parseline(line):
+    """Parse one entry in a mailcap file and return a dictionary.
+
+    The viewing command is stored as the value with the key "view",
+    and the rest of the fields produce key-value pairs in the dict.
+    """
+    fields = []
+    i, n = 0, len(line)
+    while i < n:
+        field, i = parsefield(line, i, n)
+        fields.append(field)
+        i = i+1 # Skip semicolon
+    if len(fields) < 2:
+        return None, None
+    key, view, rest = fields[0], fields[1], fields[2:]
+    fields = {'view': view}
+    for field in rest:
+        i = field.find('=')
+        if i < 0:
+            fkey = field
+            fvalue = ""
+        else:
+            fkey = field[:i].strip()
+            fvalue = field[i+1:].strip()
+        if fkey in fields:
+            # Ignore it
+            pass
+        else:
+            fields[fkey] = fvalue
+    return key, fields
+
+def parsefield(line, i, n):
+    """Separate one key-value pair in a mailcap entry."""
+    start = i
+    while i < n:
+        c = line[i]
+        if c == ';':
+            break
+        elif c == '\\':
+            i = i+2
+        else:
+            i = i+1
+    return line[start:i].strip(), i
+
+
+# Part 3: using the database.
+
+def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]):
+    """Find a match for a mailcap entry.
+
+    Return a tuple containing the command line, and the mailcap entry
+    used; (None, None) if no match is found.  This may invoke the
+    'test' command of several matching entries before deciding which
+    entry to use.
+
+    """
+    entries = lookup(caps, MIMEtype, key)
+    # XXX This code should somehow check for the needsterminal flag.
+    for e in entries:
+        if 'test' in e:
+            test = subst(e['test'], filename, plist)
+            if test and os.system(test) != 0:
+                continue
+        command = subst(e[key], MIMEtype, filename, plist)
+        return command, e
+    return None, None
+
+def lookup(caps, MIMEtype, key=None):
+    entries = []
+    if MIMEtype in caps:
+        entries = entries + caps[MIMEtype]
+    MIMEtypes = MIMEtype.split('/')
+    MIMEtype = MIMEtypes[0] + '/*'
+    if MIMEtype in caps:
+        entries = entries + caps[MIMEtype]
+    if key is not None:
+        entries = filter(lambda e, key=key: key in e, entries)
+    return entries
+
+def subst(field, MIMEtype, filename, plist=[]):
+    # XXX Actually, this is Unix-specific
+    res = ''
+    i, n = 0, len(field)
+    while i < n:
+        c = field[i]; i = i+1
+        if c != '%':
+            if c == '\\':
+                c = field[i:i+1]; i = i+1
+            res = res + c
+        else:
+            c = field[i]; i = i+1
+            if c == '%':
+                res = res + c
+            elif c == 's':
+                res = res + filename
+            elif c == 't':
+                res = res + MIMEtype
+            elif c == '{':
+                start = i
+                while i < n and field[i] != '}':
+                    i = i+1
+                name = field[start:i]
+                i = i+1
+                res = res + findparam(name, plist)
+            # XXX To do:
+            # %n == number of parts if type is multipart/*
+            # %F == list of alternating type and filename for parts
+            else:
+                res = res + '%' + c
+    return res
+
+def findparam(name, plist):
+    name = name.lower() + '='
+    n = len(name)
+    for p in plist:
+        if p[:n].lower() == name:
+            return p[n:]
+    return ''
+
+
+# Part 4: test program.
+
+def test():
+    import sys
+    caps = getcaps()
+    if not sys.argv[1:]:
+        show(caps)
+        return
+    for i in range(1, len(sys.argv), 2):
+        args = sys.argv[i:i+2]
+        if len(args) < 2:
+            print "usage: mailcap [MIMEtype file] ..."
+            return
+        MIMEtype = args[0]
+        file = args[1]
+        command, e = findmatch(caps, MIMEtype, 'view', file)
+        if not command:
+            print "No viewer found for", type
+        else:
+            print "Executing:", command
+            sts = os.system(command)
+            if sts:
+                print "Exit status:", sts
+
+def show(caps):
+    print "Mailcap files:"
+    for fn in listmailcapfiles(): print "\t" + fn
+    print
+    if not caps: caps = getcaps()
+    print "Mailcap entries:"
+    print
+    ckeys = caps.keys()
+    ckeys.sort()
+    for type in ckeys:
+        print type
+        entries = caps[type]
+        for e in entries:
+            keys = e.keys()
+            keys.sort()
+            for k in keys:
+                print "  %-15s" % k, e[k]
+            print
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/markupbase.py b/src/main/resources/PythonLibs/markupbase.py
new file mode 100644
index 0000000000000000000000000000000000000000..ddeb9835b80e5d76144c82a96cd394ccc9fe6fb8
--- /dev/null
+++ b/src/main/resources/PythonLibs/markupbase.py
@@ -0,0 +1,396 @@
+"""Shared support for scanning document type declarations in HTML and XHTML.
+
+This module is used as a foundation for the HTMLParser and sgmllib
+modules (indirectly, for htmllib as well).  It has no documented
+public API and should not be used directly.
+
+"""
+
+import re
+
+_declname_match = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9]*\s*').match
+_declstringlit_match = re.compile(r'(\'[^\']*\'|"[^"]*")\s*').match
+_commentclose = re.compile(r'--\s*>')
+_markedsectionclose = re.compile(r']\s*]\s*>')
+
+# An analysis of the MS-Word extensions is available at
+# http://www.planetpublish.com/xmlarena/xap/Thursday/WordtoXML.pdf
+
+_msmarkedsectionclose = re.compile(r']\s*>')
+
+del re
+
+
+class ParserBase:
+    """Parser base class which provides some common support methods used
+    by the SGML/HTML and XHTML parsers."""
+
+    def __init__(self):
+        if self.__class__ is ParserBase:
+            raise RuntimeError(
+                "markupbase.ParserBase must be subclassed")
+
+    def error(self, message):
+        raise NotImplementedError(
+            "subclasses of ParserBase must override error()")
+
+    def reset(self):
+        self.lineno = 1
+        self.offset = 0
+
+    def getpos(self):
+        """Return current line number and offset."""
+        return self.lineno, self.offset
+
+    # Internal -- update line number and offset.  This should be
+    # called for each piece of data exactly once, in order -- in other
+    # words the concatenation of all the input strings to this
+    # function should be exactly the entire input.
+    def updatepos(self, i, j):
+        if i >= j:
+            return j
+        rawdata = self.rawdata
+        nlines = rawdata.count("\n", i, j)
+        if nlines:
+            self.lineno = self.lineno + nlines
+            pos = rawdata.rindex("\n", i, j) # Should not fail
+            self.offset = j-(pos+1)
+        else:
+            self.offset = self.offset + j-i
+        return j
+
+    _decl_otherchars = ''
+
+    # Internal -- parse declaration (for use by subclasses).
+    def parse_declaration(self, i):
+        # This is some sort of declaration; in "HTML as
+        # deployed," this should only be the document type
+        # declaration ("<!DOCTYPE html...>").
+        # ISO 8879:1986, however, has more complex
+        # declaration syntax for elements in <!...>, including:
+        # --comment--
+        # [marked section]
+        # name in the following list: ENTITY, DOCTYPE, ELEMENT,
+        # ATTLIST, NOTATION, SHORTREF, USEMAP,
+        # LINKTYPE, LINK, IDLINK, USELINK, SYSTEM
+        rawdata = self.rawdata
+        j = i + 2
+        assert rawdata[i:j] == "<!", "unexpected call to parse_declaration"
+        if rawdata[j:j+1] == ">":
+            # the empty comment <!>
+            return j + 1
+        if rawdata[j:j+1] in ("-", ""):
+            # Start of comment followed by buffer boundary,
+            # or just a buffer boundary.
+            return -1
+        # A simple, practical version could look like: ((name|stringlit) S*) + '>'
+        n = len(rawdata)
+        if rawdata[j:j+2] == '--': #comment
+            # Locate --.*-- as the body of the comment
+            return self.parse_comment(i)
+        elif rawdata[j] == '[': #marked section
+            # Locate [statusWord [...arbitrary SGML...]] as the body of the marked section
+            # Where statusWord is one of TEMP, CDATA, IGNORE, INCLUDE, RCDATA
+            # Note that this is extended by Microsoft Office "Save as Web" function
+            # to include [if...] and [endif].
+            return self.parse_marked_section(i)
+        else: #all other declaration elements
+            decltype, j = self._scan_name(j, i)
+        if j < 0:
+            return j
+        if decltype == "doctype":
+            self._decl_otherchars = ''
+        while j < n:
+            c = rawdata[j]
+            if c == ">":
+                # end of declaration syntax
+                data = rawdata[i+2:j]
+                if decltype == "doctype":
+                    self.handle_decl(data)
+                else:
+                    # According to the HTML5 specs sections "8.2.4.44 Bogus
+                    # comment state" and "8.2.4.45 Markup declaration open
+                    # state", a comment token should be emitted.
+                    # Calling unknown_decl provides more flexibility though.
+                    self.unknown_decl(data)
+                return j + 1
+            if c in "\"'":
+                m = _declstringlit_match(rawdata, j)
+                if not m:
+                    return -1 # incomplete
+                j = m.end()
+            elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
+                name, j = self._scan_name(j, i)
+            elif c in self._decl_otherchars:
+                j = j + 1
+            elif c == "[":
+                # this could be handled in a separate doctype parser
+                if decltype == "doctype":
+                    j = self._parse_doctype_subset(j + 1, i)
+                elif decltype in ("attlist", "linktype", "link", "element"):
+                    # must tolerate []'d groups in a content model in an element declaration
+                    # also in data attribute specifications of attlist declaration
+                    # also link type declaration subsets in linktype declarations
+                    # also link attribute specification lists in link declarations
+                    self.error("unsupported '[' char in %s declaration" % decltype)
+                else:
+                    self.error("unexpected '[' char in declaration")
+            else:
+                self.error(
+                    "unexpected %r char in declaration" % rawdata[j])
+            if j < 0:
+                return j
+        return -1 # incomplete
+
+    # Internal -- parse a marked section
+    # Override this to handle MS-word extension syntax <![if word]>content<![endif]>
+    def parse_marked_section(self, i, report=1):
+        rawdata= self.rawdata
+        assert rawdata[i:i+3] == '<![', "unexpected call to parse_marked_section()"
+        sectName, j = self._scan_name( i+3, i )
+        if j < 0:
+            return j
+        if sectName in ("temp", "cdata", "ignore", "include", "rcdata"):
+            # look for standard ]]> ending
+            match= _markedsectionclose.search(rawdata, i+3)
+        elif sectName in ("if", "else", "endif"):
+            # look for MS Office ]> ending
+            match= _msmarkedsectionclose.search(rawdata, i+3)
+        else:
+            self.error('unknown status keyword %r in marked section' % rawdata[i+3:j])
+        if not match:
+            return -1
+        if report:
+            j = match.start(0)
+            self.unknown_decl(rawdata[i+3: j])
+        return match.end(0)
+
+    # Internal -- parse comment, return length or -1 if not terminated
+    def parse_comment(self, i, report=1):
+        rawdata = self.rawdata
+        if rawdata[i:i+4] != '<!--':
+            self.error('unexpected call to parse_comment()')
+        match = _commentclose.search(rawdata, i+4)
+        if not match:
+            return -1
+        if report:
+            j = match.start(0)
+            self.handle_comment(rawdata[i+4: j])
+        return match.end(0)
+
+    # Internal -- scan past the internal subset in a <!DOCTYPE declaration,
+    # returning the index just past any whitespace following the trailing ']'.
+    def _parse_doctype_subset(self, i, declstartpos):
+        rawdata = self.rawdata
+        n = len(rawdata)
+        j = i
+        while j < n:
+            c = rawdata[j]
+            if c == "<":
+                s = rawdata[j:j+2]
+                if s == "<":
+                    # end of buffer; incomplete
+                    return -1
+                if s != "<!":
+                    self.updatepos(declstartpos, j + 1)
+                    self.error("unexpected char in internal subset (in %r)" % s)
+                if (j + 2) == n:
+                    # end of buffer; incomplete
+                    return -1
+                if (j + 4) > n:
+                    # end of buffer; incomplete
+                    return -1
+                if rawdata[j:j+4] == "<!--":
+                    j = self.parse_comment(j, report=0)
+                    if j < 0:
+                        return j
+                    continue
+                name, j = self._scan_name(j + 2, declstartpos)
+                if j == -1:
+                    return -1
+                if name not in ("attlist", "element", "entity", "notation"):
+                    self.updatepos(declstartpos, j + 2)
+                    self.error(
+                        "unknown declaration %r in internal subset" % name)
+                # handle the individual names
+                meth = getattr(self, "_parse_doctype_" + name)
+                j = meth(j, declstartpos)
+                if j < 0:
+                    return j
+            elif c == "%":
+                # parameter entity reference
+                if (j + 1) == n:
+                    # end of buffer; incomplete
+                    return -1
+                s, j = self._scan_name(j + 1, declstartpos)
+                if j < 0:
+                    return j
+                if rawdata[j] == ";":
+                    j = j + 1
+            elif c == "]":
+                j = j + 1
+                while j < n and rawdata[j].isspace():
+                    j = j + 1
+                if j < n:
+                    if rawdata[j] == ">":
+                        return j
+                    self.updatepos(declstartpos, j)
+                    self.error("unexpected char after internal subset")
+                else:
+                    return -1
+            elif c.isspace():
+                j = j + 1
+            else:
+                self.updatepos(declstartpos, j)
+                self.error("unexpected char %r in internal subset" % c)
+        # end of buffer reached
+        return -1
+
+    # Internal -- scan past <!ELEMENT declarations
+    def _parse_doctype_element(self, i, declstartpos):
+        name, j = self._scan_name(i, declstartpos)
+        if j == -1:
+            return -1
+        # style content model; just skip until '>'
+        rawdata = self.rawdata
+        if '>' in rawdata[j:]:
+            return rawdata.find(">", j) + 1
+        return -1
+
+    # Internal -- scan past <!ATTLIST declarations
+    def _parse_doctype_attlist(self, i, declstartpos):
+        rawdata = self.rawdata
+        name, j = self._scan_name(i, declstartpos)
+        c = rawdata[j:j+1]
+        if c == "":
+            return -1
+        if c == ">":
+            return j + 1
+        while 1:
+            # scan a series of attribute descriptions; simplified:
+            #   name type [value] [#constraint]
+            name, j = self._scan_name(j, declstartpos)
+            if j < 0:
+                return j
+            c = rawdata[j:j+1]
+            if c == "":
+                return -1
+            if c == "(":
+                # an enumerated type; look for ')'
+                if ")" in rawdata[j:]:
+                    j = rawdata.find(")", j) + 1
+                else:
+                    return -1
+                while rawdata[j:j+1].isspace():
+                    j = j + 1
+                if not rawdata[j:]:
+                    # end of buffer, incomplete
+                    return -1
+            else:
+                name, j = self._scan_name(j, declstartpos)
+            c = rawdata[j:j+1]
+            if not c:
+                return -1
+            if c in "'\"":
+                m = _declstringlit_match(rawdata, j)
+                if m:
+                    j = m.end()
+                else:
+                    return -1
+                c = rawdata[j:j+1]
+                if not c:
+                    return -1
+            if c == "#":
+                if rawdata[j:] == "#":
+                    # end of buffer
+                    return -1
+                name, j = self._scan_name(j + 1, declstartpos)
+                if j < 0:
+                    return j
+                c = rawdata[j:j+1]
+                if not c:
+                    return -1
+            if c == '>':
+                # all done
+                return j + 1
+
+    # Internal -- scan past <!NOTATION declarations
+    def _parse_doctype_notation(self, i, declstartpos):
+        name, j = self._scan_name(i, declstartpos)
+        if j < 0:
+            return j
+        rawdata = self.rawdata
+        while 1:
+            c = rawdata[j:j+1]
+            if not c:
+                # end of buffer; incomplete
+                return -1
+            if c == '>':
+                return j + 1
+            if c in "'\"":
+                m = _declstringlit_match(rawdata, j)
+                if not m:
+                    return -1
+                j = m.end()
+            else:
+                name, j = self._scan_name(j, declstartpos)
+                if j < 0:
+                    return j
+
+    # Internal -- scan past <!ENTITY declarations
+    def _parse_doctype_entity(self, i, declstartpos):
+        rawdata = self.rawdata
+        if rawdata[i:i+1] == "%":
+            j = i + 1
+            while 1:
+                c = rawdata[j:j+1]
+                if not c:
+                    return -1
+                if c.isspace():
+                    j = j + 1
+                else:
+                    break
+        else:
+            j = i
+        name, j = self._scan_name(j, declstartpos)
+        if j < 0:
+            return j
+        while 1:
+            c = self.rawdata[j:j+1]
+            if not c:
+                return -1
+            if c in "'\"":
+                m = _declstringlit_match(rawdata, j)
+                if m:
+                    j = m.end()
+                else:
+                    return -1    # incomplete
+            elif c == ">":
+                return j + 1
+            else:
+                name, j = self._scan_name(j, declstartpos)
+                if j < 0:
+                    return j
+
+    # Internal -- scan a name token and the new position and the token, or
+    # return -1 if we've reached the end of the buffer.
+    def _scan_name(self, i, declstartpos):
+        rawdata = self.rawdata
+        n = len(rawdata)
+        if i == n:
+            return None, -1
+        m = _declname_match(rawdata, i)
+        if m:
+            s = m.group()
+            name = s.strip()
+            if (i + len(s)) == n:
+                return None, -1  # end of buffer
+            return name.lower(), m.end()
+        else:
+            self.updatepos(declstartpos, i)
+            self.error("expected name token at %r"
+                       % rawdata[declstartpos:declstartpos+20])
+
+    # To be overridden -- handlers for unknown objects
+    def unknown_decl(self, data):
+        pass
diff --git a/src/main/resources/PythonLibs/marshal.py b/src/main/resources/PythonLibs/marshal.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea8b2913444e6c8cfeecbb04649fdb5ec7f507d1
--- /dev/null
+++ b/src/main/resources/PythonLibs/marshal.py
@@ -0,0 +1,28 @@
+"""Marshal module written in Python.
+
+This doesn't marshal code objects, but supports everything else.
+Performance or careful error checking is not an issue.
+
+"""
+
+import cStringIO
+from _marshal import Marshaller, Unmarshaller
+
+def dump(x, f, version=2):
+    Marshaller(f, version).dump(x)
+
+# XXX - added just for debugging. remove!
+def load(f, debug=False):
+    u = Unmarshaller(f)
+    if debug:
+        u._debug()
+    return u.load()
+
+def dumps(x, version=2):
+    f = cStringIO.StringIO()
+    dump(x, f, version)
+    return f.getvalue()
+
+def loads(s):
+    f = cStringIO.StringIO(s)
+    return load(f)
diff --git a/src/main/resources/PythonLibs/md5.py b/src/main/resources/PythonLibs/md5.py
new file mode 100644
index 0000000000000000000000000000000000000000..a44ca3b49340283afa075b12b3abd7ed0bbf8815
--- /dev/null
+++ b/src/main/resources/PythonLibs/md5.py
@@ -0,0 +1,14 @@
+# $Id$
+#
+#  Copyright (C) 2005   Gregory P. Smith (greg@krypto.org)
+#  Licensed to PSF under a Contributor Agreement.
+
+import warnings
+warnings.warn("the md5 module is deprecated; use hashlib instead",
+                DeprecationWarning, 2)
+
+from hashlib import md5
+new = md5
+
+blocksize = 1        # legacy value (wrong in any useful sense)
+digest_size = 16
diff --git a/src/main/resources/PythonLibs/mhlib.py b/src/main/resources/PythonLibs/mhlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..856e87804cd968ca90a21e27c5be22e30236c1ce
--- /dev/null
+++ b/src/main/resources/PythonLibs/mhlib.py
@@ -0,0 +1,1005 @@
+"""MH interface -- purely object-oriented (well, almost)
+
+Executive summary:
+
+import mhlib
+
+mh = mhlib.MH()         # use default mailbox directory and profile
+mh = mhlib.MH(mailbox)  # override mailbox location (default from profile)
+mh = mhlib.MH(mailbox, profile) # override mailbox and profile
+
+mh.error(format, ...)   # print error message -- can be overridden
+s = mh.getprofile(key)  # profile entry (None if not set)
+path = mh.getpath()     # mailbox pathname
+name = mh.getcontext()  # name of current folder
+mh.setcontext(name)     # set name of current folder
+
+list = mh.listfolders() # names of top-level folders
+list = mh.listallfolders() # names of all folders, including subfolders
+list = mh.listsubfolders(name) # direct subfolders of given folder
+list = mh.listallsubfolders(name) # all subfolders of given folder
+
+mh.makefolder(name)     # create new folder
+mh.deletefolder(name)   # delete folder -- must have no subfolders
+
+f = mh.openfolder(name) # new open folder object
+
+f.error(format, ...)    # same as mh.error(format, ...)
+path = f.getfullname()  # folder's full pathname
+path = f.getsequencesfilename() # full pathname of folder's sequences file
+path = f.getmessagefilename(n)  # full pathname of message n in folder
+
+list = f.listmessages() # list of messages in folder (as numbers)
+n = f.getcurrent()      # get current message
+f.setcurrent(n)         # set current message
+list = f.parsesequence(seq)     # parse msgs syntax into list of messages
+n = f.getlast()         # get last message (0 if no messagse)
+f.setlast(n)            # set last message (internal use only)
+
+dict = f.getsequences() # dictionary of sequences in folder {name: list}
+f.putsequences(dict)    # write sequences back to folder
+
+f.createmessage(n, fp)  # add message from file f as number n
+f.removemessages(list)  # remove messages in list from folder
+f.refilemessages(list, tofolder) # move messages in list to other folder
+f.movemessage(n, tofolder, ton)  # move one message to a given destination
+f.copymessage(n, tofolder, ton)  # copy one message to a given destination
+
+m = f.openmessage(n)    # new open message object (costs a file descriptor)
+m is a derived class of mimetools.Message(rfc822.Message), with:
+s = m.getheadertext()   # text of message's headers
+s = m.getheadertext(pred) # text of message's headers, filtered by pred
+s = m.getbodytext()     # text of message's body, decoded
+s = m.getbodytext(0)    # text of message's body, not decoded
+"""
+from warnings import warnpy3k
+warnpy3k("the mhlib module has been removed in Python 3.0; use the mailbox "
+            "module instead", stacklevel=2)
+del warnpy3k
+
+# XXX To do, functionality:
+# - annotate messages
+# - send messages
+#
+# XXX To do, organization:
+# - move IntSet to separate file
+# - move most Message functionality to module mimetools
+
+
+# Customizable defaults
+
+MH_PROFILE = '~/.mh_profile'
+PATH = '~/Mail'
+MH_SEQUENCES = '.mh_sequences'
+FOLDER_PROTECT = 0700
+
+
+# Imported modules
+
+import os
+import sys
+import re
+import mimetools
+import multifile
+import shutil
+from bisect import bisect
+
+__all__ = ["MH","Error","Folder","Message"]
+
+# Exported constants
+
+class Error(Exception):
+    pass
+
+
+class MH:
+    """Class representing a particular collection of folders.
+    Optional constructor arguments are the pathname for the directory
+    containing the collection, and the MH profile to use.
+    If either is omitted or empty a default is used; the default
+    directory is taken from the MH profile if it is specified there."""
+
+    def __init__(self, path = None, profile = None):
+        """Constructor."""
+        if profile is None: profile = MH_PROFILE
+        self.profile = os.path.expanduser(profile)
+        if path is None: path = self.getprofile('Path')
+        if not path: path = PATH
+        if not os.path.isabs(path) and path[0] != '~':
+            path = os.path.join('~', path)
+        path = os.path.expanduser(path)
+        if not os.path.isdir(path): raise Error, 'MH() path not found'
+        self.path = path
+
+    def __repr__(self):
+        """String representation."""
+        return 'MH(%r, %r)' % (self.path, self.profile)
+
+    def error(self, msg, *args):
+        """Routine to print an error.  May be overridden by a derived class."""
+        sys.stderr.write('MH error: %s\n' % (msg % args))
+
+    def getprofile(self, key):
+        """Return a profile entry, None if not found."""
+        return pickline(self.profile, key)
+
+    def getpath(self):
+        """Return the path (the name of the collection's directory)."""
+        return self.path
+
+    def getcontext(self):
+        """Return the name of the current folder."""
+        context = pickline(os.path.join(self.getpath(), 'context'),
+                  'Current-Folder')
+        if not context: context = 'inbox'
+        return context
+
+    def setcontext(self, context):
+        """Set the name of the current folder."""
+        fn = os.path.join(self.getpath(), 'context')
+        f = open(fn, "w")
+        f.write("Current-Folder: %s\n" % context)
+        f.close()
+
+    def listfolders(self):
+        """Return the names of the top-level folders."""
+        folders = []
+        path = self.getpath()
+        for name in os.listdir(path):
+            fullname = os.path.join(path, name)
+            if os.path.isdir(fullname):
+                folders.append(name)
+        folders.sort()
+        return folders
+
+    def listsubfolders(self, name):
+        """Return the names of the subfolders in a given folder
+        (prefixed with the given folder name)."""
+        fullname = os.path.join(self.path, name)
+        # Get the link count so we can avoid listing folders
+        # that have no subfolders.
+        nlinks = os.stat(fullname).st_nlink
+        if nlinks <= 2:
+            return []
+        subfolders = []
+        subnames = os.listdir(fullname)
+        for subname in subnames:
+            fullsubname = os.path.join(fullname, subname)
+            if os.path.isdir(fullsubname):
+                name_subname = os.path.join(name, subname)
+                subfolders.append(name_subname)
+                # Stop looking for subfolders when
+                # we've seen them all
+                nlinks = nlinks - 1
+                if nlinks <= 2:
+                    break
+        subfolders.sort()
+        return subfolders
+
+    def listallfolders(self):
+        """Return the names of all folders and subfolders, recursively."""
+        return self.listallsubfolders('')
+
+    def listallsubfolders(self, name):
+        """Return the names of subfolders in a given folder, recursively."""
+        fullname = os.path.join(self.path, name)
+        # Get the link count so we can avoid listing folders
+        # that have no subfolders.
+        nlinks = os.stat(fullname).st_nlink
+        if nlinks <= 2:
+            return []
+        subfolders = []
+        subnames = os.listdir(fullname)
+        for subname in subnames:
+            if subname[0] == ',' or isnumeric(subname): continue
+            fullsubname = os.path.join(fullname, subname)
+            if os.path.isdir(fullsubname):
+                name_subname = os.path.join(name, subname)
+                subfolders.append(name_subname)
+                if not os.path.islink(fullsubname):
+                    subsubfolders = self.listallsubfolders(
+                              name_subname)
+                    subfolders = subfolders + subsubfolders
+                # Stop looking for subfolders when
+                # we've seen them all
+                nlinks = nlinks - 1
+                if nlinks <= 2:
+                    break
+        subfolders.sort()
+        return subfolders
+
+    def openfolder(self, name):
+        """Return a new Folder object for the named folder."""
+        return Folder(self, name)
+
+    def makefolder(self, name):
+        """Create a new folder (or raise os.error if it cannot be created)."""
+        protect = pickline(self.profile, 'Folder-Protect')
+        if protect and isnumeric(protect):
+            mode = int(protect, 8)
+        else:
+            mode = FOLDER_PROTECT
+        os.mkdir(os.path.join(self.getpath(), name), mode)
+
+    def deletefolder(self, name):
+        """Delete a folder.  This removes files in the folder but not
+        subdirectories.  Raise os.error if deleting the folder itself fails."""
+        fullname = os.path.join(self.getpath(), name)
+        for subname in os.listdir(fullname):
+            fullsubname = os.path.join(fullname, subname)
+            try:
+                os.unlink(fullsubname)
+            except os.error:
+                self.error('%s not deleted, continuing...' %
+                          fullsubname)
+        os.rmdir(fullname)
+
+
+numericprog = re.compile('^[1-9][0-9]*$')
+def isnumeric(str):
+    return numericprog.match(str) is not None
+
+class Folder:
+    """Class representing a particular folder."""
+
+    def __init__(self, mh, name):
+        """Constructor."""
+        self.mh = mh
+        self.name = name
+        if not os.path.isdir(self.getfullname()):
+            raise Error, 'no folder %s' % name
+
+    def __repr__(self):
+        """String representation."""
+        return 'Folder(%r, %r)' % (self.mh, self.name)
+
+    def error(self, *args):
+        """Error message handler."""
+        self.mh.error(*args)
+
+    def getfullname(self):
+        """Return the full pathname of the folder."""
+        return os.path.join(self.mh.path, self.name)
+
+    def getsequencesfilename(self):
+        """Return the full pathname of the folder's sequences file."""
+        return os.path.join(self.getfullname(), MH_SEQUENCES)
+
+    def getmessagefilename(self, n):
+        """Return the full pathname of a message in the folder."""
+        return os.path.join(self.getfullname(), str(n))
+
+    def listsubfolders(self):
+        """Return list of direct subfolders."""
+        return self.mh.listsubfolders(self.name)
+
+    def listallsubfolders(self):
+        """Return list of all subfolders."""
+        return self.mh.listallsubfolders(self.name)
+
+    def listmessages(self):
+        """Return the list of messages currently present in the folder.
+        As a side effect, set self.last to the last message (or 0)."""
+        messages = []
+        match = numericprog.match
+        append = messages.append
+        for name in os.listdir(self.getfullname()):
+            if match(name):
+                append(name)
+        messages = map(int, messages)
+        messages.sort()
+        if messages:
+            self.last = messages[-1]
+        else:
+            self.last = 0
+        return messages
+
+    def getsequences(self):
+        """Return the set of sequences for the folder."""
+        sequences = {}
+        fullname = self.getsequencesfilename()
+        try:
+            f = open(fullname, 'r')
+        except IOError:
+            return sequences
+        while 1:
+            line = f.readline()
+            if not line: break
+            fields = line.split(':')
+            if len(fields) != 2:
+                self.error('bad sequence in %s: %s' %
+                          (fullname, line.strip()))
+            key = fields[0].strip()
+            value = IntSet(fields[1].strip(), ' ').tolist()
+            sequences[key] = value
+        return sequences
+
+    def putsequences(self, sequences):
+        """Write the set of sequences back to the folder."""
+        fullname = self.getsequencesfilename()
+        f = None
+        for key, seq in sequences.iteritems():
+            s = IntSet('', ' ')
+            s.fromlist(seq)
+            if not f: f = open(fullname, 'w')
+            f.write('%s: %s\n' % (key, s.tostring()))
+        if not f:
+            try:
+                os.unlink(fullname)
+            except os.error:
+                pass
+        else:
+            f.close()
+
+    def getcurrent(self):
+        """Return the current message.  Raise Error when there is none."""
+        seqs = self.getsequences()
+        try:
+            return max(seqs['cur'])
+        except (ValueError, KeyError):
+            raise Error, "no cur message"
+
+    def setcurrent(self, n):
+        """Set the current message."""
+        updateline(self.getsequencesfilename(), 'cur', str(n), 0)
+
+    def parsesequence(self, seq):
+        """Parse an MH sequence specification into a message list.
+        Attempt to mimic mh-sequence(5) as close as possible.
+        Also attempt to mimic observed behavior regarding which
+        conditions cause which error messages."""
+        # XXX Still not complete (see mh-format(5)).
+        # Missing are:
+        # - 'prev', 'next' as count
+        # - Sequence-Negation option
+        all = self.listmessages()
+        # Observed behavior: test for empty folder is done first
+        if not all:
+            raise Error, "no messages in %s" % self.name
+        # Common case first: all is frequently the default
+        if seq == 'all':
+            return all
+        # Test for X:Y before X-Y because 'seq:-n' matches both
+        i = seq.find(':')
+        if i >= 0:
+            head, dir, tail = seq[:i], '', seq[i+1:]
+            if tail[:1] in '-+':
+                dir, tail = tail[:1], tail[1:]
+            if not isnumeric(tail):
+                raise Error, "bad message list %s" % seq
+            try:
+                count = int(tail)
+            except (ValueError, OverflowError):
+                # Can't use sys.maxint because of i+count below
+                count = len(all)
+            try:
+                anchor = self._parseindex(head, all)
+            except Error, msg:
+                seqs = self.getsequences()
+                if not head in seqs:
+                    if not msg:
+                        msg = "bad message list %s" % seq
+                    raise Error, msg, sys.exc_info()[2]
+                msgs = seqs[head]
+                if not msgs:
+                    raise Error, "sequence %s empty" % head
+                if dir == '-':
+                    return msgs[-count:]
+                else:
+                    return msgs[:count]
+            else:
+                if not dir:
+                    if head in ('prev', 'last'):
+                        dir = '-'
+                if dir == '-':
+                    i = bisect(all, anchor)
+                    return all[max(0, i-count):i]
+                else:
+                    i = bisect(all, anchor-1)
+                    return all[i:i+count]
+        # Test for X-Y next
+        i = seq.find('-')
+        if i >= 0:
+            begin = self._parseindex(seq[:i], all)
+            end = self._parseindex(seq[i+1:], all)
+            i = bisect(all, begin-1)
+            j = bisect(all, end)
+            r = all[i:j]
+            if not r:
+                raise Error, "bad message list %s" % seq
+            return r
+        # Neither X:Y nor X-Y; must be a number or a (pseudo-)sequence
+        try:
+            n = self._parseindex(seq, all)
+        except Error, msg:
+            seqs = self.getsequences()
+            if not seq in seqs:
+                if not msg:
+                    msg = "bad message list %s" % seq
+                raise Error, msg
+            return seqs[seq]
+        else:
+            if n not in all:
+                if isnumeric(seq):
+                    raise Error, "message %d doesn't exist" % n
+                else:
+                    raise Error, "no %s message" % seq
+            else:
+                return [n]
+
+    def _parseindex(self, seq, all):
+        """Internal: parse a message number (or cur, first, etc.)."""
+        if isnumeric(seq):
+            try:
+                return int(seq)
+            except (OverflowError, ValueError):
+                return sys.maxint
+        if seq in ('cur', '.'):
+            return self.getcurrent()
+        if seq == 'first':
+            return all[0]
+        if seq == 'last':
+            return all[-1]
+        if seq == 'next':
+            n = self.getcurrent()
+            i = bisect(all, n)
+            try:
+                return all[i]
+            except IndexError:
+                raise Error, "no next message"
+        if seq == 'prev':
+            n = self.getcurrent()
+            i = bisect(all, n-1)
+            if i == 0:
+                raise Error, "no prev message"
+            try:
+                return all[i-1]
+            except IndexError:
+                raise Error, "no prev message"
+        raise Error, None
+
+    def openmessage(self, n):
+        """Open a message -- returns a Message object."""
+        return Message(self, n)
+
+    def removemessages(self, list):
+        """Remove one or more messages -- may raise os.error."""
+        errors = []
+        deleted = []
+        for n in list:
+            path = self.getmessagefilename(n)
+            commapath = self.getmessagefilename(',' + str(n))
+            try:
+                os.unlink(commapath)
+            except os.error:
+                pass
+            try:
+                os.rename(path, commapath)
+            except os.error, msg:
+                errors.append(msg)
+            else:
+                deleted.append(n)
+        if deleted:
+            self.removefromallsequences(deleted)
+        if errors:
+            if len(errors) == 1:
+                raise os.error, errors[0]
+            else:
+                raise os.error, ('multiple errors:', errors)
+
+    def refilemessages(self, list, tofolder, keepsequences=0):
+        """Refile one or more messages -- may raise os.error.
+        'tofolder' is an open folder object."""
+        errors = []
+        refiled = {}
+        for n in list:
+            ton = tofolder.getlast() + 1
+            path = self.getmessagefilename(n)
+            topath = tofolder.getmessagefilename(ton)
+            try:
+                os.rename(path, topath)
+            except os.error:
+                # Try copying
+                try:
+                    shutil.copy2(path, topath)
+                    os.unlink(path)
+                except (IOError, os.error), msg:
+                    errors.append(msg)
+                    try:
+                        os.unlink(topath)
+                    except os.error:
+                        pass
+                    continue
+            tofolder.setlast(ton)
+            refiled[n] = ton
+        if refiled:
+            if keepsequences:
+                tofolder._copysequences(self, refiled.items())
+            self.removefromallsequences(refiled.keys())
+        if errors:
+            if len(errors) == 1:
+                raise os.error, errors[0]
+            else:
+                raise os.error, ('multiple errors:', errors)
+
+    def _copysequences(self, fromfolder, refileditems):
+        """Helper for refilemessages() to copy sequences."""
+        fromsequences = fromfolder.getsequences()
+        tosequences = self.getsequences()
+        changed = 0
+        for name, seq in fromsequences.items():
+            try:
+                toseq = tosequences[name]
+                new = 0
+            except KeyError:
+                toseq = []
+                new = 1
+            for fromn, ton in refileditems:
+                if fromn in seq:
+                    toseq.append(ton)
+                    changed = 1
+            if new and toseq:
+                tosequences[name] = toseq
+        if changed:
+            self.putsequences(tosequences)
+
+    def movemessage(self, n, tofolder, ton):
+        """Move one message over a specific destination message,
+        which may or may not already exist."""
+        path = self.getmessagefilename(n)
+        # Open it to check that it exists
+        f = open(path)
+        f.close()
+        del f
+        topath = tofolder.getmessagefilename(ton)
+        backuptopath = tofolder.getmessagefilename(',%d' % ton)
+        try:
+            os.rename(topath, backuptopath)
+        except os.error:
+            pass
+        try:
+            os.rename(path, topath)
+        except os.error:
+            # Try copying
+            ok = 0
+            try:
+                tofolder.setlast(None)
+                shutil.copy2(path, topath)
+                ok = 1
+            finally:
+                if not ok:
+                    try:
+                        os.unlink(topath)
+                    except os.error:
+                        pass
+            os.unlink(path)
+        self.removefromallsequences([n])
+
+    def copymessage(self, n, tofolder, ton):
+        """Copy one message over a specific destination message,
+        which may or may not already exist."""
+        path = self.getmessagefilename(n)
+        # Open it to check that it exists
+        f = open(path)
+        f.close()
+        del f
+        topath = tofolder.getmessagefilename(ton)
+        backuptopath = tofolder.getmessagefilename(',%d' % ton)
+        try:
+            os.rename(topath, backuptopath)
+        except os.error:
+            pass
+        ok = 0
+        try:
+            tofolder.setlast(None)
+            shutil.copy2(path, topath)
+            ok = 1
+        finally:
+            if not ok:
+                try:
+                    os.unlink(topath)
+                except os.error:
+                    pass
+
+    def createmessage(self, n, txt):
+        """Create a message, with text from the open file txt."""
+        path = self.getmessagefilename(n)
+        backuppath = self.getmessagefilename(',%d' % n)
+        try:
+            os.rename(path, backuppath)
+        except os.error:
+            pass
+        ok = 0
+        BUFSIZE = 16*1024
+        try:
+            f = open(path, "w")
+            while 1:
+                buf = txt.read(BUFSIZE)
+                if not buf:
+                    break
+                f.write(buf)
+            f.close()
+            ok = 1
+        finally:
+            if not ok:
+                try:
+                    os.unlink(path)
+                except os.error:
+                    pass
+
+    def removefromallsequences(self, list):
+        """Remove one or more messages from all sequences (including last)
+        -- but not from 'cur'!!!"""
+        if hasattr(self, 'last') and self.last in list:
+            del self.last
+        sequences = self.getsequences()
+        changed = 0
+        for name, seq in sequences.items():
+            if name == 'cur':
+                continue
+            for n in list:
+                if n in seq:
+                    seq.remove(n)
+                    changed = 1
+                    if not seq:
+                        del sequences[name]
+        if changed:
+            self.putsequences(sequences)
+
+    def getlast(self):
+        """Return the last message number."""
+        if not hasattr(self, 'last'):
+            self.listmessages() # Set self.last
+        return self.last
+
+    def setlast(self, last):
+        """Set the last message number."""
+        if last is None:
+            if hasattr(self, 'last'):
+                del self.last
+        else:
+            self.last = last
+
+class Message(mimetools.Message):
+
+    def __init__(self, f, n, fp = None):
+        """Constructor."""
+        self.folder = f
+        self.number = n
+        if fp is None:
+            path = f.getmessagefilename(n)
+            fp = open(path, 'r')
+        mimetools.Message.__init__(self, fp)
+
+    def __repr__(self):
+        """String representation."""
+        return 'Message(%s, %s)' % (repr(self.folder), self.number)
+
+    def getheadertext(self, pred = None):
+        """Return the message's header text as a string.  If an
+        argument is specified, it is used as a filter predicate to
+        decide which headers to return (its argument is the header
+        name converted to lower case)."""
+        if pred is None:
+            return ''.join(self.headers)
+        headers = []
+        hit = 0
+        for line in self.headers:
+            if not line[0].isspace():
+                i = line.find(':')
+                if i > 0:
+                    hit = pred(line[:i].lower())
+            if hit: headers.append(line)
+        return ''.join(headers)
+
+    def getbodytext(self, decode = 1):
+        """Return the message's body text as string.  This undoes a
+        Content-Transfer-Encoding, but does not interpret other MIME
+        features (e.g. multipart messages).  To suppress decoding,
+        pass 0 as an argument."""
+        self.fp.seek(self.startofbody)
+        encoding = self.getencoding()
+        if not decode or encoding in ('', '7bit', '8bit', 'binary'):
+            return self.fp.read()
+        try:
+            from cStringIO import StringIO
+        except ImportError:
+            from StringIO import StringIO
+        output = StringIO()
+        mimetools.decode(self.fp, output, encoding)
+        return output.getvalue()
+
+    def getbodyparts(self):
+        """Only for multipart messages: return the message's body as a
+        list of SubMessage objects.  Each submessage object behaves
+        (almost) as a Message object."""
+        if self.getmaintype() != 'multipart':
+            raise Error, 'Content-Type is not multipart/*'
+        bdry = self.getparam('boundary')
+        if not bdry:
+            raise Error, 'multipart/* without boundary param'
+        self.fp.seek(self.startofbody)
+        mf = multifile.MultiFile(self.fp)
+        mf.push(bdry)
+        parts = []
+        while mf.next():
+            n = "%s.%r" % (self.number, 1 + len(parts))
+            part = SubMessage(self.folder, n, mf)
+            parts.append(part)
+        mf.pop()
+        return parts
+
+    def getbody(self):
+        """Return body, either a string or a list of messages."""
+        if self.getmaintype() == 'multipart':
+            return self.getbodyparts()
+        else:
+            return self.getbodytext()
+
+
+class SubMessage(Message):
+
+    def __init__(self, f, n, fp):
+        """Constructor."""
+        Message.__init__(self, f, n, fp)
+        if self.getmaintype() == 'multipart':
+            self.body = Message.getbodyparts(self)
+        else:
+            self.body = Message.getbodytext(self)
+        self.bodyencoded = Message.getbodytext(self, decode=0)
+            # XXX If this is big, should remember file pointers
+
+    def __repr__(self):
+        """String representation."""
+        f, n, fp = self.folder, self.number, self.fp
+        return 'SubMessage(%s, %s, %s)' % (f, n, fp)
+
+    def getbodytext(self, decode = 1):
+        if not decode:
+            return self.bodyencoded
+        if type(self.body) == type(''):
+            return self.body
+
+    def getbodyparts(self):
+        if type(self.body) == type([]):
+            return self.body
+
+    def getbody(self):
+        return self.body
+
+
+class IntSet:
+    """Class implementing sets of integers.
+
+    This is an efficient representation for sets consisting of several
+    continuous ranges, e.g. 1-100,200-400,402-1000 is represented
+    internally as a list of three pairs: [(1,100), (200,400),
+    (402,1000)].  The internal representation is always kept normalized.
+
+    The constructor has up to three arguments:
+    - the string used to initialize the set (default ''),
+    - the separator between ranges (default ',')
+    - the separator between begin and end of a range (default '-')
+    The separators must be strings (not regexprs) and should be different.
+
+    The tostring() function yields a string that can be passed to another
+    IntSet constructor; __repr__() is a valid IntSet constructor itself.
+    """
+
+    # XXX The default begin/end separator means that negative numbers are
+    #     not supported very well.
+    #
+    # XXX There are currently no operations to remove set elements.
+
+    def __init__(self, data = None, sep = ',', rng = '-'):
+        self.pairs = []
+        self.sep = sep
+        self.rng = rng
+        if data: self.fromstring(data)
+
+    def reset(self):
+        self.pairs = []
+
+    def __cmp__(self, other):
+        return cmp(self.pairs, other.pairs)
+
+    def __hash__(self):
+        return hash(self.pairs)
+
+    def __repr__(self):
+        return 'IntSet(%r, %r, %r)' % (self.tostring(), self.sep, self.rng)
+
+    def normalize(self):
+        self.pairs.sort()
+        i = 1
+        while i < len(self.pairs):
+            alo, ahi = self.pairs[i-1]
+            blo, bhi = self.pairs[i]
+            if ahi >= blo-1:
+                self.pairs[i-1:i+1] = [(alo, max(ahi, bhi))]
+            else:
+                i = i+1
+
+    def tostring(self):
+        s = ''
+        for lo, hi in self.pairs:
+            if lo == hi: t = repr(lo)
+            else: t = repr(lo) + self.rng + repr(hi)
+            if s: s = s + (self.sep + t)
+            else: s = t
+        return s
+
+    def tolist(self):
+        l = []
+        for lo, hi in self.pairs:
+            m = range(lo, hi+1)
+            l = l + m
+        return l
+
+    def fromlist(self, list):
+        for i in list:
+            self.append(i)
+
+    def clone(self):
+        new = IntSet()
+        new.pairs = self.pairs[:]
+        return new
+
+    def min(self):
+        return self.pairs[0][0]
+
+    def max(self):
+        return self.pairs[-1][-1]
+
+    def contains(self, x):
+        for lo, hi in self.pairs:
+            if lo <= x <= hi: return True
+        return False
+
+    def append(self, x):
+        for i in range(len(self.pairs)):
+            lo, hi = self.pairs[i]
+            if x < lo: # Need to insert before
+                if x+1 == lo:
+                    self.pairs[i] = (x, hi)
+                else:
+                    self.pairs.insert(i, (x, x))
+                if i > 0 and x-1 == self.pairs[i-1][1]:
+                    # Merge with previous
+                    self.pairs[i-1:i+1] = [
+                            (self.pairs[i-1][0],
+                             self.pairs[i][1])
+                          ]
+                return
+            if x <= hi: # Already in set
+                return
+        i = len(self.pairs) - 1
+        if i >= 0:
+            lo, hi = self.pairs[i]
+            if x-1 == hi:
+                self.pairs[i] = lo, x
+                return
+        self.pairs.append((x, x))
+
+    def addpair(self, xlo, xhi):
+        if xlo > xhi: return
+        self.pairs.append((xlo, xhi))
+        self.normalize()
+
+    def fromstring(self, data):
+        new = []
+        for part in data.split(self.sep):
+            list = []
+            for subp in part.split(self.rng):
+                s = subp.strip()
+                list.append(int(s))
+            if len(list) == 1:
+                new.append((list[0], list[0]))
+            elif len(list) == 2 and list[0] <= list[1]:
+                new.append((list[0], list[1]))
+            else:
+                raise ValueError, 'bad data passed to IntSet'
+        self.pairs = self.pairs + new
+        self.normalize()
+
+
+# Subroutines to read/write entries in .mh_profile and .mh_sequences
+
+def pickline(file, key, casefold = 1):
+    try:
+        f = open(file, 'r')
+    except IOError:
+        return None
+    pat = re.escape(key) + ':'
+    prog = re.compile(pat, casefold and re.IGNORECASE)
+    while 1:
+        line = f.readline()
+        if not line: break
+        if prog.match(line):
+            text = line[len(key)+1:]
+            while 1:
+                line = f.readline()
+                if not line or not line[0].isspace():
+                    break
+                text = text + line
+            return text.strip()
+    return None
+
+def updateline(file, key, value, casefold = 1):
+    try:
+        f = open(file, 'r')
+        lines = f.readlines()
+        f.close()
+    except IOError:
+        lines = []
+    pat = re.escape(key) + ':(.*)\n'
+    prog = re.compile(pat, casefold and re.IGNORECASE)
+    if value is None:
+        newline = None
+    else:
+        newline = '%s: %s\n' % (key, value)
+    for i in range(len(lines)):
+        line = lines[i]
+        if prog.match(line):
+            if newline is None:
+                del lines[i]
+            else:
+                lines[i] = newline
+            break
+    else:
+        if newline is not None:
+            lines.append(newline)
+    tempfile = file + "~"
+    f = open(tempfile, 'w')
+    for line in lines:
+        f.write(line)
+    f.close()
+    os.rename(tempfile, file)
+
+
+# Test program
+
+def test():
+    global mh, f
+    os.system('rm -rf $HOME/Mail/@test')
+    mh = MH()
+    def do(s): print s; print eval(s)
+    do('mh.listfolders()')
+    do('mh.listallfolders()')
+    testfolders = ['@test', '@test/test1', '@test/test2',
+                   '@test/test1/test11', '@test/test1/test12',
+                   '@test/test1/test11/test111']
+    for t in testfolders: do('mh.makefolder(%r)' % (t,))
+    do('mh.listsubfolders(\'@test\')')
+    do('mh.listallsubfolders(\'@test\')')
+    f = mh.openfolder('@test')
+    do('f.listsubfolders()')
+    do('f.listallsubfolders()')
+    do('f.getsequences()')
+    seqs = f.getsequences()
+    seqs['foo'] = IntSet('1-10 12-20', ' ').tolist()
+    print seqs
+    f.putsequences(seqs)
+    do('f.getsequences()')
+    for t in reversed(testfolders): do('mh.deletefolder(%r)' % (t,))
+    do('mh.getcontext()')
+    context = mh.getcontext()
+    f = mh.openfolder(context)
+    do('f.getcurrent()')
+    for seq in ('first', 'last', 'cur', '.', 'prev', 'next',
+                'first:3', 'last:3', 'cur:3', 'cur:-3',
+                'prev:3', 'next:3',
+                '1:3', '1:-3', '100:3', '100:-3', '10000:3', '10000:-3',
+                'all'):
+        try:
+            do('f.parsesequence(%r)' % (seq,))
+        except Error, msg:
+            print "Error:", msg
+        stuff = os.popen("pick %r 2>/dev/null" % (seq,)).read()
+        list = map(int, stuff.split())
+        print list, "<-- pick"
+    do('f.listmessages()')
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/mimetools.py b/src/main/resources/PythonLibs/mimetools.py
new file mode 100644
index 0000000000000000000000000000000000000000..71ca8f8593f2b64d08ddeb02a38dee1fef827f1c
--- /dev/null
+++ b/src/main/resources/PythonLibs/mimetools.py
@@ -0,0 +1,250 @@
+"""Various tools used by MIME-reading or MIME-writing programs."""
+
+
+import os
+import sys
+import tempfile
+from warnings import filterwarnings, catch_warnings
+with catch_warnings():
+    if sys.py3kwarning:
+        filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning)
+    import rfc822
+
+from warnings import warnpy3k
+warnpy3k("in 3.x, mimetools has been removed in favor of the email package",
+         stacklevel=2)
+
+__all__ = ["Message","choose_boundary","encode","decode","copyliteral",
+           "copybinary"]
+
+class Message(rfc822.Message):
+    """A derived class of rfc822.Message that knows about MIME headers and
+    contains some hooks for decoding encoded and multipart messages."""
+
+    def __init__(self, fp, seekable = 1):
+        rfc822.Message.__init__(self, fp, seekable)
+        self.encodingheader = \
+                self.getheader('content-transfer-encoding')
+        self.typeheader = \
+                self.getheader('content-type')
+        self.parsetype()
+        self.parseplist()
+
+    def parsetype(self):
+        str = self.typeheader
+        if str is None:
+            str = 'text/plain'
+        if ';' in str:
+            i = str.index(';')
+            self.plisttext = str[i:]
+            str = str[:i]
+        else:
+            self.plisttext = ''
+        fields = str.split('/')
+        for i in range(len(fields)):
+            fields[i] = fields[i].strip().lower()
+        self.type = '/'.join(fields)
+        self.maintype = fields[0]
+        self.subtype = '/'.join(fields[1:])
+
+    def parseplist(self):
+        str = self.plisttext
+        self.plist = []
+        while str[:1] == ';':
+            str = str[1:]
+            if ';' in str:
+                # XXX Should parse quotes!
+                end = str.index(';')
+            else:
+                end = len(str)
+            f = str[:end]
+            if '=' in f:
+                i = f.index('=')
+                f = f[:i].strip().lower() + \
+                        '=' + f[i+1:].strip()
+            self.plist.append(f.strip())
+            str = str[end:]
+
+    def getplist(self):
+        return self.plist
+
+    def getparam(self, name):
+        name = name.lower() + '='
+        n = len(name)
+        for p in self.plist:
+            if p[:n] == name:
+                return rfc822.unquote(p[n:])
+        return None
+
+    def getparamnames(self):
+        result = []
+        for p in self.plist:
+            i = p.find('=')
+            if i >= 0:
+                result.append(p[:i].lower())
+        return result
+
+    def getencoding(self):
+        if self.encodingheader is None:
+            return '7bit'
+        return self.encodingheader.lower()
+
+    def gettype(self):
+        return self.type
+
+    def getmaintype(self):
+        return self.maintype
+
+    def getsubtype(self):
+        return self.subtype
+
+
+
+
+# Utility functions
+# -----------------
+
+try:
+    import thread
+except ImportError:
+    import dummy_thread as thread
+_counter_lock = thread.allocate_lock()
+del thread
+
+_counter = 0
+def _get_next_counter():
+    global _counter
+    _counter_lock.acquire()
+    _counter += 1
+    result = _counter
+    _counter_lock.release()
+    return result
+
+_prefix = None
+
+def choose_boundary():
+    """Return a string usable as a multipart boundary.
+
+    The string chosen is unique within a single program run, and
+    incorporates the user id (if available), process id (if available),
+    and current time.  So it's very unlikely the returned string appears
+    in message text, but there's no guarantee.
+
+    The boundary contains dots so you have to quote it in the header."""
+
+    global _prefix
+    import time
+    if _prefix is None:
+        import socket
+        try:
+            hostid = socket.gethostbyname(socket.gethostname())
+        except socket.gaierror:
+            hostid = '127.0.0.1'
+        try:
+            uid = repr(os.getuid())
+        except AttributeError:
+            uid = '1'
+        try:
+            pid = repr(os.getpid())
+        except AttributeError:
+            pid = '1'
+        _prefix = hostid + '.' + uid + '.' + pid
+    return "%s.%.3f.%d" % (_prefix, time.time(), _get_next_counter())
+
+
+# Subroutines for decoding some common content-transfer-types
+
+def decode(input, output, encoding):
+    """Decode common content-transfer-encodings (base64, quopri, uuencode)."""
+    if encoding == 'base64':
+        import base64
+        return base64.decode(input, output)
+    if encoding == 'quoted-printable':
+        import quopri
+        return quopri.decode(input, output)
+    if encoding in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
+        import uu
+        return uu.decode(input, output)
+    if encoding in ('7bit', '8bit'):
+        return output.write(input.read())
+    if encoding in decodetab:
+        pipethrough(input, decodetab[encoding], output)
+    else:
+        raise ValueError, \
+              'unknown Content-Transfer-Encoding: %s' % encoding
+
+def encode(input, output, encoding):
+    """Encode common content-transfer-encodings (base64, quopri, uuencode)."""
+    if encoding == 'base64':
+        import base64
+        return base64.encode(input, output)
+    if encoding == 'quoted-printable':
+        import quopri
+        return quopri.encode(input, output, 0)
+    if encoding in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
+        import uu
+        return uu.encode(input, output)
+    if encoding in ('7bit', '8bit'):
+        return output.write(input.read())
+    if encoding in encodetab:
+        pipethrough(input, encodetab[encoding], output)
+    else:
+        raise ValueError, \
+              'unknown Content-Transfer-Encoding: %s' % encoding
+
+# The following is no longer used for standard encodings
+
+# XXX This requires that uudecode and mmencode are in $PATH
+
+uudecode_pipe = '''(
+TEMP=/tmp/@uu.$$
+sed "s%^begin [0-7][0-7]* .*%begin 600 $TEMP%" | uudecode
+cat $TEMP
+rm $TEMP
+)'''
+
+decodetab = {
+        'uuencode':             uudecode_pipe,
+        'x-uuencode':           uudecode_pipe,
+        'uue':                  uudecode_pipe,
+        'x-uue':                uudecode_pipe,
+        'quoted-printable':     'mmencode -u -q',
+        'base64':               'mmencode -u -b',
+}
+
+encodetab = {
+        'x-uuencode':           'uuencode tempfile',
+        'uuencode':             'uuencode tempfile',
+        'x-uue':                'uuencode tempfile',
+        'uue':                  'uuencode tempfile',
+        'quoted-printable':     'mmencode -q',
+        'base64':               'mmencode -b',
+}
+
+def pipeto(input, command):
+    pipe = os.popen(command, 'w')
+    copyliteral(input, pipe)
+    pipe.close()
+
+def pipethrough(input, command, output):
+    (fd, tempname) = tempfile.mkstemp()
+    temp = os.fdopen(fd, 'w')
+    copyliteral(input, temp)
+    temp.close()
+    pipe = os.popen(command + ' <' + tempname, 'r')
+    copybinary(pipe, output)
+    pipe.close()
+    os.unlink(tempname)
+
+def copyliteral(input, output):
+    while 1:
+        line = input.readline()
+        if not line: break
+        output.write(line)
+
+def copybinary(input, output):
+    BUFSIZE = 8192
+    while 1:
+        line = input.read(BUFSIZE)
+        if not line: break
+        output.write(line)
diff --git a/src/main/resources/PythonLibs/mimetypes.py b/src/main/resources/PythonLibs/mimetypes.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba4ea8257b660b0f8f1043aed2bc3a06bdfb40c5
--- /dev/null
+++ b/src/main/resources/PythonLibs/mimetypes.py
@@ -0,0 +1,592 @@
+"""Guess the MIME type of a file.
+
+This module defines two useful functions:
+
+guess_type(url, strict=1) -- guess the MIME type and encoding of a URL.
+
+guess_extension(type, strict=1) -- guess the extension for a given MIME type.
+
+It also contains the following, for tuning the behavior:
+
+Data:
+
+knownfiles -- list of files to parse
+inited -- flag set when init() has been called
+suffix_map -- dictionary mapping suffixes to suffixes
+encodings_map -- dictionary mapping suffixes to encodings
+types_map -- dictionary mapping suffixes to types
+
+Functions:
+
+init([files]) -- parse a list of files, default knownfiles (on Windows, the
+  default values are taken from the registry)
+read_mime_types(file) -- parse one file, return a dictionary or None
+"""
+
+import os
+import sys
+import posixpath
+import urllib
+try:
+    import _winreg
+except ImportError:
+    _winreg = None
+
+__all__ = [
+    "guess_type","guess_extension","guess_all_extensions",
+    "add_type","read_mime_types","init"
+]
+
+knownfiles = [
+    "/etc/mime.types",
+    "/etc/httpd/mime.types",                    # Mac OS X
+    "/etc/httpd/conf/mime.types",               # Apache
+    "/etc/apache/mime.types",                   # Apache 1
+    "/etc/apache2/mime.types",                  # Apache 2
+    "/usr/local/etc/httpd/conf/mime.types",
+    "/usr/local/lib/netscape/mime.types",
+    "/usr/local/etc/httpd/conf/mime.types",     # Apache 1.2
+    "/usr/local/etc/mime.types",                # Apache 1.3
+    ]
+
+inited = False
+_db = None
+
+
+class MimeTypes:
+    """MIME-types datastore.
+
+    This datastore can handle information from mime.types-style files
+    and supports basic determination of MIME type from a filename or
+    URL, and can guess a reasonable extension given a MIME type.
+    """
+
+    def __init__(self, filenames=(), strict=True):
+        if not inited:
+            init()
+        self.encodings_map = encodings_map.copy()
+        self.suffix_map = suffix_map.copy()
+        self.types_map = ({}, {}) # dict for (non-strict, strict)
+        self.types_map_inv = ({}, {})
+        for (ext, type) in types_map.items():
+            self.add_type(type, ext, True)
+        for (ext, type) in common_types.items():
+            self.add_type(type, ext, False)
+        for name in filenames:
+            self.read(name, strict)
+
+    def add_type(self, type, ext, strict=True):
+        """Add a mapping between a type and an extension.
+
+        When the extension is already known, the new
+        type will replace the old one. When the type
+        is already known the extension will be added
+        to the list of known extensions.
+
+        If strict is true, information will be added to
+        list of standard types, else to the list of non-standard
+        types.
+        """
+        self.types_map[strict][ext] = type
+        exts = self.types_map_inv[strict].setdefault(type, [])
+        if ext not in exts:
+            exts.append(ext)
+
+    def guess_type(self, url, strict=True):
+        """Guess the type of a file based on its URL.
+
+        Return value is a tuple (type, encoding) where type is None if
+        the type can't be guessed (no or unknown suffix) or a string
+        of the form type/subtype, usable for a MIME Content-type
+        header; and encoding is None for no encoding or the name of
+        the program used to encode (e.g. compress or gzip).  The
+        mappings are table driven.  Encoding suffixes are case
+        sensitive; type suffixes are first tried case sensitive, then
+        case insensitive.
+
+        The suffixes .tgz, .taz and .tz (case sensitive!) are all
+        mapped to '.tar.gz'.  (This is table-driven too, using the
+        dictionary suffix_map.)
+
+        Optional `strict' argument when False adds a bunch of commonly found,
+        but non-standard types.
+        """
+        scheme, url = urllib.splittype(url)
+        if scheme == 'data':
+            # syntax of data URLs:
+            # dataurl   := "data:" [ mediatype ] [ ";base64" ] "," data
+            # mediatype := [ type "/" subtype ] *( ";" parameter )
+            # data      := *urlchar
+            # parameter := attribute "=" value
+            # type/subtype defaults to "text/plain"
+            comma = url.find(',')
+            if comma < 0:
+                # bad data URL
+                return None, None
+            semi = url.find(';', 0, comma)
+            if semi >= 0:
+                type = url[:semi]
+            else:
+                type = url[:comma]
+            if '=' in type or '/' not in type:
+                type = 'text/plain'
+            return type, None           # never compressed, so encoding is None
+        base, ext = posixpath.splitext(url)
+        while ext in self.suffix_map:
+            base, ext = posixpath.splitext(base + self.suffix_map[ext])
+        if ext in self.encodings_map:
+            encoding = self.encodings_map[ext]
+            base, ext = posixpath.splitext(base)
+        else:
+            encoding = None
+        types_map = self.types_map[True]
+        if ext in types_map:
+            return types_map[ext], encoding
+        elif ext.lower() in types_map:
+            return types_map[ext.lower()], encoding
+        elif strict:
+            return None, encoding
+        types_map = self.types_map[False]
+        if ext in types_map:
+            return types_map[ext], encoding
+        elif ext.lower() in types_map:
+            return types_map[ext.lower()], encoding
+        else:
+            return None, encoding
+
+    def guess_all_extensions(self, type, strict=True):
+        """Guess the extensions for a file based on its MIME type.
+
+        Return value is a list of strings giving the possible filename
+        extensions, including the leading dot ('.').  The extension is not
+        guaranteed to have been associated with any particular data stream,
+        but would be mapped to the MIME type `type' by guess_type().
+
+        Optional `strict' argument when false adds a bunch of commonly found,
+        but non-standard types.
+        """
+        type = type.lower()
+        extensions = self.types_map_inv[True].get(type, [])
+        if not strict:
+            for ext in self.types_map_inv[False].get(type, []):
+                if ext not in extensions:
+                    extensions.append(ext)
+        return extensions
+
+    def guess_extension(self, type, strict=True):
+        """Guess the extension for a file based on its MIME type.
+
+        Return value is a string giving a filename extension,
+        including the leading dot ('.').  The extension is not
+        guaranteed to have been associated with any particular data
+        stream, but would be mapped to the MIME type `type' by
+        guess_type().  If no extension can be guessed for `type', None
+        is returned.
+
+        Optional `strict' argument when false adds a bunch of commonly found,
+        but non-standard types.
+        """
+        extensions = self.guess_all_extensions(type, strict)
+        if not extensions:
+            return None
+        return extensions[0]
+
+    def read(self, filename, strict=True):
+        """
+        Read a single mime.types-format file, specified by pathname.
+
+        If strict is true, information will be added to
+        list of standard types, else to the list of non-standard
+        types.
+        """
+        with open(filename) as fp:
+            self.readfp(fp, strict)
+
+    def readfp(self, fp, strict=True):
+        """
+        Read a single mime.types-format file.
+
+        If strict is true, information will be added to
+        list of standard types, else to the list of non-standard
+        types.
+        """
+        while 1:
+            line = fp.readline()
+            if not line:
+                break
+            words = line.split()
+            for i in range(len(words)):
+                if words[i][0] == '#':
+                    del words[i:]
+                    break
+            if not words:
+                continue
+            type, suffixes = words[0], words[1:]
+            for suff in suffixes:
+                self.add_type(type, '.' + suff, strict)
+
+    def read_windows_registry(self, strict=True):
+        """
+        Load the MIME types database from Windows registry.
+
+        If strict is true, information will be added to
+        list of standard types, else to the list of non-standard
+        types.
+        """
+
+        # Windows only
+        if not _winreg:
+            return
+
+        def enum_types(mimedb):
+            i = 0
+            while True:
+                try:
+                    ctype = _winreg.EnumKey(mimedb, i)
+                except EnvironmentError:
+                    break
+                try:
+                    ctype = ctype.encode(default_encoding) # omit in 3.x!
+                except UnicodeEncodeError:
+                    pass
+                else:
+                    yield ctype
+                i += 1
+
+        default_encoding = sys.getdefaultencoding()
+        with _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,
+                             r'MIME\Database\Content Type') as mimedb:
+            for ctype in enum_types(mimedb):
+                try:
+                    with _winreg.OpenKey(mimedb, ctype) as key:
+                        suffix, datatype = _winreg.QueryValueEx(key,
+                                                                'Extension')
+                except EnvironmentError:
+                    continue
+                if datatype != _winreg.REG_SZ:
+                    continue
+                try:
+                    suffix = suffix.encode(default_encoding) # omit in 3.x!
+                except UnicodeEncodeError:
+                    continue
+                self.add_type(ctype, suffix, strict)
+
+
+def guess_type(url, strict=True):
+    """Guess the type of a file based on its URL.
+
+    Return value is a tuple (type, encoding) where type is None if the
+    type can't be guessed (no or unknown suffix) or a string of the
+    form type/subtype, usable for a MIME Content-type header; and
+    encoding is None for no encoding or the name of the program used
+    to encode (e.g. compress or gzip).  The mappings are table
+    driven.  Encoding suffixes are case sensitive; type suffixes are
+    first tried case sensitive, then case insensitive.
+
+    The suffixes .tgz, .taz and .tz (case sensitive!) are all mapped
+    to ".tar.gz".  (This is table-driven too, using the dictionary
+    suffix_map).
+
+    Optional `strict' argument when false adds a bunch of commonly found, but
+    non-standard types.
+    """
+    if _db is None:
+        init()
+    return _db.guess_type(url, strict)
+
+
+def guess_all_extensions(type, strict=True):
+    """Guess the extensions for a file based on its MIME type.
+
+    Return value is a list of strings giving the possible filename
+    extensions, including the leading dot ('.').  The extension is not
+    guaranteed to have been associated with any particular data
+    stream, but would be mapped to the MIME type `type' by
+    guess_type().  If no extension can be guessed for `type', None
+    is returned.
+
+    Optional `strict' argument when false adds a bunch of commonly found,
+    but non-standard types.
+    """
+    if _db is None:
+        init()
+    return _db.guess_all_extensions(type, strict)
+
+def guess_extension(type, strict=True):
+    """Guess the extension for a file based on its MIME type.
+
+    Return value is a string giving a filename extension, including the
+    leading dot ('.').  The extension is not guaranteed to have been
+    associated with any particular data stream, but would be mapped to the
+    MIME type `type' by guess_type().  If no extension can be guessed for
+    `type', None is returned.
+
+    Optional `strict' argument when false adds a bunch of commonly found,
+    but non-standard types.
+    """
+    if _db is None:
+        init()
+    return _db.guess_extension(type, strict)
+
+def add_type(type, ext, strict=True):
+    """Add a mapping between a type and an extension.
+
+    When the extension is already known, the new
+    type will replace the old one. When the type
+    is already known the extension will be added
+    to the list of known extensions.
+
+    If strict is true, information will be added to
+    list of standard types, else to the list of non-standard
+    types.
+    """
+    if _db is None:
+        init()
+    return _db.add_type(type, ext, strict)
+
+
+def init(files=None):
+    global suffix_map, types_map, encodings_map, common_types
+    global inited, _db
+    inited = True    # so that MimeTypes.__init__() doesn't call us again
+    db = MimeTypes()
+    if files is None:
+        if _winreg:
+            db.read_windows_registry()
+        files = knownfiles
+    for file in files:
+        if os.path.isfile(file):
+            db.read(file)
+    encodings_map = db.encodings_map
+    suffix_map = db.suffix_map
+    types_map = db.types_map[True]
+    common_types = db.types_map[False]
+    # Make the DB a global variable now that it is fully initialized
+    _db = db
+
+
+def read_mime_types(file):
+    try:
+        f = open(file)
+    except IOError:
+        return None
+    db = MimeTypes()
+    db.readfp(f, True)
+    return db.types_map[True]
+
+
+def _default_mime_types():
+    global suffix_map
+    global encodings_map
+    global types_map
+    global common_types
+
+    suffix_map = {
+        '.tgz': '.tar.gz',
+        '.taz': '.tar.gz',
+        '.tz': '.tar.gz',
+        '.tbz2': '.tar.bz2',
+        }
+
+    encodings_map = {
+        '.gz': 'gzip',
+        '.Z': 'compress',
+        '.bz2': 'bzip2',
+        }
+
+    # Before adding new types, make sure they are either registered with IANA,
+    # at http://www.isi.edu/in-notes/iana/assignments/media-types
+    # or extensions, i.e. using the x- prefix
+
+    # If you add to these, please keep them sorted!
+    types_map = {
+        '.a'      : 'application/octet-stream',
+        '.ai'     : 'application/postscript',
+        '.aif'    : 'audio/x-aiff',
+        '.aifc'   : 'audio/x-aiff',
+        '.aiff'   : 'audio/x-aiff',
+        '.au'     : 'audio/basic',
+        '.avi'    : 'video/x-msvideo',
+        '.bat'    : 'text/plain',
+        '.bcpio'  : 'application/x-bcpio',
+        '.bin'    : 'application/octet-stream',
+        '.bmp'    : 'image/x-ms-bmp',
+        '.c'      : 'text/plain',
+        # Duplicates :(
+        '.cdf'    : 'application/x-cdf',
+        '.cdf'    : 'application/x-netcdf',
+        '.cpio'   : 'application/x-cpio',
+        '.csh'    : 'application/x-csh',
+        '.css'    : 'text/css',
+        '.dll'    : 'application/octet-stream',
+        '.doc'    : 'application/msword',
+        '.dot'    : 'application/msword',
+        '.dvi'    : 'application/x-dvi',
+        '.eml'    : 'message/rfc822',
+        '.eps'    : 'application/postscript',
+        '.etx'    : 'text/x-setext',
+        '.exe'    : 'application/octet-stream',
+        '.gif'    : 'image/gif',
+        '.gtar'   : 'application/x-gtar',
+        '.h'      : 'text/plain',
+        '.hdf'    : 'application/x-hdf',
+        '.htm'    : 'text/html',
+        '.html'   : 'text/html',
+        '.ico'    : 'image/vnd.microsoft.icon',
+        '.ief'    : 'image/ief',
+        '.jpe'    : 'image/jpeg',
+        '.jpeg'   : 'image/jpeg',
+        '.jpg'    : 'image/jpeg',
+        '.js'     : 'application/javascript',
+        '.ksh'    : 'text/plain',
+        '.latex'  : 'application/x-latex',
+        '.m1v'    : 'video/mpeg',
+        '.man'    : 'application/x-troff-man',
+        '.me'     : 'application/x-troff-me',
+        '.mht'    : 'message/rfc822',
+        '.mhtml'  : 'message/rfc822',
+        '.mif'    : 'application/x-mif',
+        '.mov'    : 'video/quicktime',
+        '.movie'  : 'video/x-sgi-movie',
+        '.mp2'    : 'audio/mpeg',
+        '.mp3'    : 'audio/mpeg',
+        '.mp4'    : 'video/mp4',
+        '.mpa'    : 'video/mpeg',
+        '.mpe'    : 'video/mpeg',
+        '.mpeg'   : 'video/mpeg',
+        '.mpg'    : 'video/mpeg',
+        '.ms'     : 'application/x-troff-ms',
+        '.nc'     : 'application/x-netcdf',
+        '.nws'    : 'message/rfc822',
+        '.o'      : 'application/octet-stream',
+        '.obj'    : 'application/octet-stream',
+        '.oda'    : 'application/oda',
+        '.p12'    : 'application/x-pkcs12',
+        '.p7c'    : 'application/pkcs7-mime',
+        '.pbm'    : 'image/x-portable-bitmap',
+        '.pdf'    : 'application/pdf',
+        '.pfx'    : 'application/x-pkcs12',
+        '.pgm'    : 'image/x-portable-graymap',
+        '.pl'     : 'text/plain',
+        '.png'    : 'image/png',
+        '.pnm'    : 'image/x-portable-anymap',
+        '.pot'    : 'application/vnd.ms-powerpoint',
+        '.ppa'    : 'application/vnd.ms-powerpoint',
+        '.ppm'    : 'image/x-portable-pixmap',
+        '.pps'    : 'application/vnd.ms-powerpoint',
+        '.ppt'    : 'application/vnd.ms-powerpoint',
+        '.ps'     : 'application/postscript',
+        '.pwz'    : 'application/vnd.ms-powerpoint',
+        '.py'     : 'text/x-python',
+        '.pyc'    : 'application/x-python-code',
+        '.pyo'    : 'application/x-python-code',
+        '.qt'     : 'video/quicktime',
+        '.ra'     : 'audio/x-pn-realaudio',
+        '.ram'    : 'application/x-pn-realaudio',
+        '.ras'    : 'image/x-cmu-raster',
+        '.rdf'    : 'application/xml',
+        '.rgb'    : 'image/x-rgb',
+        '.roff'   : 'application/x-troff',
+        '.rtx'    : 'text/richtext',
+        '.sgm'    : 'text/x-sgml',
+        '.sgml'   : 'text/x-sgml',
+        '.sh'     : 'application/x-sh',
+        '.shar'   : 'application/x-shar',
+        '.snd'    : 'audio/basic',
+        '.so'     : 'application/octet-stream',
+        '.src'    : 'application/x-wais-source',
+        '.sv4cpio': 'application/x-sv4cpio',
+        '.sv4crc' : 'application/x-sv4crc',
+        '.swf'    : 'application/x-shockwave-flash',
+        '.t'      : 'application/x-troff',
+        '.tar'    : 'application/x-tar',
+        '.tcl'    : 'application/x-tcl',
+        '.tex'    : 'application/x-tex',
+        '.texi'   : 'application/x-texinfo',
+        '.texinfo': 'application/x-texinfo',
+        '.tif'    : 'image/tiff',
+        '.tiff'   : 'image/tiff',
+        '.tr'     : 'application/x-troff',
+        '.tsv'    : 'text/tab-separated-values',
+        '.txt'    : 'text/plain',
+        '.ustar'  : 'application/x-ustar',
+        '.vcf'    : 'text/x-vcard',
+        '.wav'    : 'audio/x-wav',
+        '.wiz'    : 'application/msword',
+        '.wsdl'   : 'application/xml',
+        '.xbm'    : 'image/x-xbitmap',
+        '.xlb'    : 'application/vnd.ms-excel',
+        # Duplicates :(
+        '.xls'    : 'application/excel',
+        '.xls'    : 'application/vnd.ms-excel',
+        '.xml'    : 'text/xml',
+        '.xpdl'   : 'application/xml',
+        '.xpm'    : 'image/x-xpixmap',
+        '.xsl'    : 'application/xml',
+        '.xwd'    : 'image/x-xwindowdump',
+        '.zip'    : 'application/zip',
+        }
+
+    # These are non-standard types, commonly found in the wild.  They will
+    # only match if strict=0 flag is given to the API methods.
+
+    # Please sort these too
+    common_types = {
+        '.jpg' : 'image/jpg',
+        '.mid' : 'audio/midi',
+        '.midi': 'audio/midi',
+        '.pct' : 'image/pict',
+        '.pic' : 'image/pict',
+        '.pict': 'image/pict',
+        '.rtf' : 'application/rtf',
+        '.xul' : 'text/xul'
+        }
+
+
+_default_mime_types()
+
+
+if __name__ == '__main__':
+    import getopt
+
+    USAGE = """\
+Usage: mimetypes.py [options] type
+
+Options:
+    --help / -h       -- print this message and exit
+    --lenient / -l    -- additionally search of some common, but non-standard
+                         types.
+    --extension / -e  -- guess extension instead of type
+
+More than one type argument may be given.
+"""
+
+    def usage(code, msg=''):
+        print USAGE
+        if msg: print msg
+        sys.exit(code)
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'hle',
+                                   ['help', 'lenient', 'extension'])
+    except getopt.error, msg:
+        usage(1, msg)
+
+    strict = 1
+    extension = 0
+    for opt, arg in opts:
+        if opt in ('-h', '--help'):
+            usage(0)
+        elif opt in ('-l', '--lenient'):
+            strict = 0
+        elif opt in ('-e', '--extension'):
+            extension = 1
+    for gtype in args:
+        if extension:
+            guess = guess_extension(gtype, strict)
+            if not guess: print "I don't know anything about type", gtype
+            else: print guess
+        else:
+            guess, encoding = guess_type(gtype, strict)
+            if not guess: print "I don't know anything about type", gtype
+            else: print 'type:', guess, 'encoding:', encoding
diff --git a/src/main/resources/PythonLibs/mimify.py b/src/main/resources/PythonLibs/mimify.py
new file mode 100644
index 0000000000000000000000000000000000000000..1c15983d1e2647c13e04422e29f27bb42db1d647
--- /dev/null
+++ b/src/main/resources/PythonLibs/mimify.py
@@ -0,0 +1,468 @@
+#! /usr/bin/env python
+
+"""Mimification and unmimification of mail messages.
+
+Decode quoted-printable parts of a mail message or encode using
+quoted-printable.
+
+Usage:
+        mimify(input, output)
+        unmimify(input, output, decode_base64 = 0)
+to encode and decode respectively.  Input and output may be the name
+of a file or an open file object.  Only a readline() method is used
+on the input file, only a write() method is used on the output file.
+When using file names, the input and output file names may be the
+same.
+
+Interactive usage:
+        mimify.py -e [infile [outfile]]
+        mimify.py -d [infile [outfile]]
+to encode and decode respectively.  Infile defaults to standard
+input and outfile to standard output.
+"""
+
+# Configure
+MAXLEN = 200    # if lines longer than this, encode as quoted-printable
+CHARSET = 'ISO-8859-1'  # default charset for non-US-ASCII mail
+QUOTE = '> '            # string replies are quoted with
+# End configure
+
+import re
+
+import warnings
+warnings.warn("the mimify module is deprecated; use the email package instead",
+                DeprecationWarning, 2)
+
+__all__ = ["mimify","unmimify","mime_encode_header","mime_decode_header"]
+
+qp = re.compile('^content-transfer-encoding:\\s*quoted-printable', re.I)
+base64_re = re.compile('^content-transfer-encoding:\\s*base64', re.I)
+mp = re.compile('^content-type:.*multipart/.*boundary="?([^;"\n]*)', re.I|re.S)
+chrset = re.compile('^(content-type:.*charset=")(us-ascii|iso-8859-[0-9]+)(".*)', re.I|re.S)
+he = re.compile('^-*\n')
+mime_code = re.compile('=([0-9a-f][0-9a-f])', re.I)
+mime_head = re.compile('=\\?iso-8859-1\\?q\\?([^? \t\n]+)\\?=', re.I)
+repl = re.compile('^subject:\\s+re: ', re.I)
+
+class File:
+    """A simple fake file object that knows about limited read-ahead and
+    boundaries.  The only supported method is readline()."""
+
+    def __init__(self, file, boundary):
+        self.file = file
+        self.boundary = boundary
+        self.peek = None
+
+    def readline(self):
+        if self.peek is not None:
+            return ''
+        line = self.file.readline()
+        if not line:
+            return line
+        if self.boundary:
+            if line == self.boundary + '\n':
+                self.peek = line
+                return ''
+            if line == self.boundary + '--\n':
+                self.peek = line
+                return ''
+        return line
+
+class HeaderFile:
+    def __init__(self, file):
+        self.file = file
+        self.peek = None
+
+    def readline(self):
+        if self.peek is not None:
+            line = self.peek
+            self.peek = None
+        else:
+            line = self.file.readline()
+        if not line:
+            return line
+        if he.match(line):
+            return line
+        while 1:
+            self.peek = self.file.readline()
+            if len(self.peek) == 0 or \
+               (self.peek[0] != ' ' and self.peek[0] != '\t'):
+                return line
+            line = line + self.peek
+            self.peek = None
+
+def mime_decode(line):
+    """Decode a single line of quoted-printable text to 8bit."""
+    newline = ''
+    pos = 0
+    while 1:
+        res = mime_code.search(line, pos)
+        if res is None:
+            break
+        newline = newline + line[pos:res.start(0)] + \
+                  chr(int(res.group(1), 16))
+        pos = res.end(0)
+    return newline + line[pos:]
+
+def mime_decode_header(line):
+    """Decode a header line to 8bit."""
+    newline = ''
+    pos = 0
+    while 1:
+        res = mime_head.search(line, pos)
+        if res is None:
+            break
+        match = res.group(1)
+        # convert underscores to spaces (before =XX conversion!)
+        match = ' '.join(match.split('_'))
+        newline = newline + line[pos:res.start(0)] + mime_decode(match)
+        pos = res.end(0)
+    return newline + line[pos:]
+
+def unmimify_part(ifile, ofile, decode_base64 = 0):
+    """Convert a quoted-printable part of a MIME mail message to 8bit."""
+    multipart = None
+    quoted_printable = 0
+    is_base64 = 0
+    is_repl = 0
+    if ifile.boundary and ifile.boundary[:2] == QUOTE:
+        prefix = QUOTE
+    else:
+        prefix = ''
+
+    # read header
+    hfile = HeaderFile(ifile)
+    while 1:
+        line = hfile.readline()
+        if not line:
+            return
+        if prefix and line[:len(prefix)] == prefix:
+            line = line[len(prefix):]
+            pref = prefix
+        else:
+            pref = ''
+        line = mime_decode_header(line)
+        if qp.match(line):
+            quoted_printable = 1
+            continue        # skip this header
+        if decode_base64 and base64_re.match(line):
+            is_base64 = 1
+            continue
+        ofile.write(pref + line)
+        if not prefix and repl.match(line):
+            # we're dealing with a reply message
+            is_repl = 1
+        mp_res = mp.match(line)
+        if mp_res:
+            multipart = '--' + mp_res.group(1)
+        if he.match(line):
+            break
+    if is_repl and (quoted_printable or multipart):
+        is_repl = 0
+
+    # read body
+    while 1:
+        line = ifile.readline()
+        if not line:
+            return
+        line = re.sub(mime_head, '\\1', line)
+        if prefix and line[:len(prefix)] == prefix:
+            line = line[len(prefix):]
+            pref = prefix
+        else:
+            pref = ''
+##              if is_repl and len(line) >= 4 and line[:4] == QUOTE+'--' and line[-3:] != '--\n':
+##                      multipart = line[:-1]
+        while multipart:
+            if line == multipart + '--\n':
+                ofile.write(pref + line)
+                multipart = None
+                line = None
+                break
+            if line == multipart + '\n':
+                ofile.write(pref + line)
+                nifile = File(ifile, multipart)
+                unmimify_part(nifile, ofile, decode_base64)
+                line = nifile.peek
+                if not line:
+                    # premature end of file
+                    break
+                continue
+            # not a boundary between parts
+            break
+        if line and quoted_printable:
+            while line[-2:] == '=\n':
+                line = line[:-2]
+                newline = ifile.readline()
+                if newline[:len(QUOTE)] == QUOTE:
+                    newline = newline[len(QUOTE):]
+                line = line + newline
+            line = mime_decode(line)
+        if line and is_base64 and not pref:
+            import base64
+            line = base64.decodestring(line)
+        if line:
+            ofile.write(pref + line)
+
+def unmimify(infile, outfile, decode_base64 = 0):
+    """Convert quoted-printable parts of a MIME mail message to 8bit."""
+    if type(infile) == type(''):
+        ifile = open(infile)
+        if type(outfile) == type('') and infile == outfile:
+            import os
+            d, f = os.path.split(infile)
+            os.rename(infile, os.path.join(d, ',' + f))
+    else:
+        ifile = infile
+    if type(outfile) == type(''):
+        ofile = open(outfile, 'w')
+    else:
+        ofile = outfile
+    nifile = File(ifile, None)
+    unmimify_part(nifile, ofile, decode_base64)
+    ofile.flush()
+
+mime_char = re.compile('[=\177-\377]') # quote these chars in body
+mime_header_char = re.compile('[=?\177-\377]') # quote these in header
+
+def mime_encode(line, header):
+    """Code a single line as quoted-printable.
+    If header is set, quote some extra characters."""
+    if header:
+        reg = mime_header_char
+    else:
+        reg = mime_char
+    newline = ''
+    pos = 0
+    if len(line) >= 5 and line[:5] == 'From ':
+        # quote 'From ' at the start of a line for stupid mailers
+        newline = ('=%02x' % ord('F')).upper()
+        pos = 1
+    while 1:
+        res = reg.search(line, pos)
+        if res is None:
+            break
+        newline = newline + line[pos:res.start(0)] + \
+                  ('=%02x' % ord(res.group(0))).upper()
+        pos = res.end(0)
+    line = newline + line[pos:]
+
+    newline = ''
+    while len(line) >= 75:
+        i = 73
+        while line[i] == '=' or line[i-1] == '=':
+            i = i - 1
+        i = i + 1
+        newline = newline + line[:i] + '=\n'
+        line = line[i:]
+    return newline + line
+
+mime_header = re.compile('([ \t(]|^)([-a-zA-Z0-9_+]*[\177-\377][-a-zA-Z0-9_+\177-\377]*)(?=[ \t)]|\n)')
+
+def mime_encode_header(line):
+    """Code a single header line as quoted-printable."""
+    newline = ''
+    pos = 0
+    while 1:
+        res = mime_header.search(line, pos)
+        if res is None:
+            break
+        newline = '%s%s%s=?%s?Q?%s?=' % \
+                  (newline, line[pos:res.start(0)], res.group(1),
+                   CHARSET, mime_encode(res.group(2), 1))
+        pos = res.end(0)
+    return newline + line[pos:]
+
+mv = re.compile('^mime-version:', re.I)
+cte = re.compile('^content-transfer-encoding:', re.I)
+iso_char = re.compile('[\177-\377]')
+
+def mimify_part(ifile, ofile, is_mime):
+    """Convert an 8bit part of a MIME mail message to quoted-printable."""
+    has_cte = is_qp = is_base64 = 0
+    multipart = None
+    must_quote_body = must_quote_header = has_iso_chars = 0
+
+    header = []
+    header_end = ''
+    message = []
+    message_end = ''
+    # read header
+    hfile = HeaderFile(ifile)
+    while 1:
+        line = hfile.readline()
+        if not line:
+            break
+        if not must_quote_header and iso_char.search(line):
+            must_quote_header = 1
+        if mv.match(line):
+            is_mime = 1
+        if cte.match(line):
+            has_cte = 1
+            if qp.match(line):
+                is_qp = 1
+            elif base64_re.match(line):
+                is_base64 = 1
+        mp_res = mp.match(line)
+        if mp_res:
+            multipart = '--' + mp_res.group(1)
+        if he.match(line):
+            header_end = line
+            break
+        header.append(line)
+
+    # read body
+    while 1:
+        line = ifile.readline()
+        if not line:
+            break
+        if multipart:
+            if line == multipart + '--\n':
+                message_end = line
+                break
+            if line == multipart + '\n':
+                message_end = line
+                break
+        if is_base64:
+            message.append(line)
+            continue
+        if is_qp:
+            while line[-2:] == '=\n':
+                line = line[:-2]
+                newline = ifile.readline()
+                if newline[:len(QUOTE)] == QUOTE:
+                    newline = newline[len(QUOTE):]
+                line = line + newline
+            line = mime_decode(line)
+        message.append(line)
+        if not has_iso_chars:
+            if iso_char.search(line):
+                has_iso_chars = must_quote_body = 1
+        if not must_quote_body:
+            if len(line) > MAXLEN:
+                must_quote_body = 1
+
+    # convert and output header and body
+    for line in header:
+        if must_quote_header:
+            line = mime_encode_header(line)
+        chrset_res = chrset.match(line)
+        if chrset_res:
+            if has_iso_chars:
+                # change us-ascii into iso-8859-1
+                if chrset_res.group(2).lower() == 'us-ascii':
+                    line = '%s%s%s' % (chrset_res.group(1),
+                                       CHARSET,
+                                       chrset_res.group(3))
+            else:
+                # change iso-8859-* into us-ascii
+                line = '%sus-ascii%s' % chrset_res.group(1, 3)
+        if has_cte and cte.match(line):
+            line = 'Content-Transfer-Encoding: '
+            if is_base64:
+                line = line + 'base64\n'
+            elif must_quote_body:
+                line = line + 'quoted-printable\n'
+            else:
+                line = line + '7bit\n'
+        ofile.write(line)
+    if (must_quote_header or must_quote_body) and not is_mime:
+        ofile.write('Mime-Version: 1.0\n')
+        ofile.write('Content-Type: text/plain; ')
+        if has_iso_chars:
+            ofile.write('charset="%s"\n' % CHARSET)
+        else:
+            ofile.write('charset="us-ascii"\n')
+    if must_quote_body and not has_cte:
+        ofile.write('Content-Transfer-Encoding: quoted-printable\n')
+    ofile.write(header_end)
+
+    for line in message:
+        if must_quote_body:
+            line = mime_encode(line, 0)
+        ofile.write(line)
+    ofile.write(message_end)
+
+    line = message_end
+    while multipart:
+        if line == multipart + '--\n':
+            # read bit after the end of the last part
+            while 1:
+                line = ifile.readline()
+                if not line:
+                    return
+                if must_quote_body:
+                    line = mime_encode(line, 0)
+                ofile.write(line)
+        if line == multipart + '\n':
+            nifile = File(ifile, multipart)
+            mimify_part(nifile, ofile, 1)
+            line = nifile.peek
+            if not line:
+                # premature end of file
+                break
+            ofile.write(line)
+            continue
+        # unexpectedly no multipart separator--copy rest of file
+        while 1:
+            line = ifile.readline()
+            if not line:
+                return
+            if must_quote_body:
+                line = mime_encode(line, 0)
+            ofile.write(line)
+
+def mimify(infile, outfile):
+    """Convert 8bit parts of a MIME mail message to quoted-printable."""
+    if type(infile) == type(''):
+        ifile = open(infile)
+        if type(outfile) == type('') and infile == outfile:
+            import os
+            d, f = os.path.split(infile)
+            os.rename(infile, os.path.join(d, ',' + f))
+    else:
+        ifile = infile
+    if type(outfile) == type(''):
+        ofile = open(outfile, 'w')
+    else:
+        ofile = outfile
+    nifile = File(ifile, None)
+    mimify_part(nifile, ofile, 0)
+    ofile.flush()
+
+import sys
+if __name__ == '__main__' or (len(sys.argv) > 0 and sys.argv[0] == 'mimify'):
+    import getopt
+    usage = 'Usage: mimify [-l len] -[ed] [infile [outfile]]'
+
+    decode_base64 = 0
+    opts, args = getopt.getopt(sys.argv[1:], 'l:edb')
+    if len(args) not in (0, 1, 2):
+        print usage
+        sys.exit(1)
+    if (('-e', '') in opts) == (('-d', '') in opts) or \
+       ((('-b', '') in opts) and (('-d', '') not in opts)):
+        print usage
+        sys.exit(1)
+    for o, a in opts:
+        if o == '-e':
+            encode = mimify
+        elif o == '-d':
+            encode = unmimify
+        elif o == '-l':
+            try:
+                MAXLEN = int(a)
+            except (ValueError, OverflowError):
+                print usage
+                sys.exit(1)
+        elif o == '-b':
+            decode_base64 = 1
+    if len(args) == 0:
+        encode_args = (sys.stdin, sys.stdout)
+    elif len(args) == 1:
+        encode_args = (args[0], sys.stdout)
+    else:
+        encode_args = (args[0], args[1])
+    if decode_base64:
+        encode_args = encode_args + (decode_base64,)
+    encode(*encode_args)
diff --git a/src/main/resources/PythonLibs/modjy/__init__.py b/src/main/resources/PythonLibs/modjy/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..a172fcc2ee30f9473f75aaba569b19e32d752e0c
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/__init__.py
@@ -0,0 +1,22 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+__all__ = ['modjy', 'modjy_exceptions', 'modjy_impl', 'modjy_log', 'modjy_params', 'modjy_publish', 'modjy_response', 'modjy_write', 'modjy_wsgi',]
+
diff --git a/src/main/resources/PythonLibs/modjy/modjy.py b/src/main/resources/PythonLibs/modjy/modjy.py
new file mode 100644
index 0000000000000000000000000000000000000000..cd6c398a5261f201271a32a08336c779be9f71c7
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy.py
@@ -0,0 +1,121 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+import jarray
+import synchronize
+import sys
+import types
+
+sys.add_package("javax.servlet")
+sys.add_package("javax.servlet.http")
+sys.add_package("org.python.core")
+
+from modjy_exceptions import *
+from modjy_log import *
+from modjy_params import modjy_param_mgr, modjy_servlet_params 
+from modjy_wsgi import modjy_wsgi
+from modjy_response import start_response_object
+from modjy_impl import modjy_impl
+from modjy_publish import modjy_publisher
+
+from javax.servlet.http import HttpServlet
+
+class modjy_servlet(HttpServlet, modjy_publisher, modjy_wsgi, modjy_impl):
+
+    def __init__(self):
+        HttpServlet.__init__(self)
+
+    def do_param(self, name, value):
+        if name[:3] == 'log':
+            getattr(self.log, "set_%s" % name)(value)
+        else:
+            self.params[name] = value
+        
+    def process_param_container(self, param_container):
+        param_enum = param_container.getInitParameterNames()
+        while param_enum.hasMoreElements():
+            param_name = param_enum.nextElement()
+            self.do_param(param_name, param_container.getInitParameter(param_name))
+
+    def get_params(self):
+        self.process_param_container(self.servlet_context)
+        self.process_param_container(self.servlet)
+
+    def init(self, delegator):
+        self.servlet = delegator
+        self.servlet_context = self.servlet.getServletContext()
+        self.servlet_config = self.servlet.getServletConfig()
+        self.log = modjy_logger(self.servlet_context)
+        self.params = modjy_param_mgr(modjy_servlet_params)
+        self.get_params()
+        self.init_impl()
+        self.init_publisher()
+        import modjy_exceptions
+        self.exc_handler = getattr(modjy_exceptions, '%s_handler' % self.params['exc_handler'])()
+
+    def service (self, req, resp):
+        wsgi_environ = {}
+        try:
+            self.dispatch_to_application(req, resp, wsgi_environ)
+        except ModjyException, mx:
+            self.log.error("Exception servicing request: %s" % str(mx))
+            typ, value, tb = sys.exc_info()[:]
+            self.exc_handler.handle(req, resp, wsgi_environ, mx, (typ, value, tb) )
+
+    def get_j2ee_ns(self, req, resp):
+        return {
+            'servlet':         self.servlet,
+            'servlet_context': self.servlet_context,
+            'servlet_config':  self.servlet_config,
+            'request':         req,
+            'response':        resp,
+        }
+
+    def dispatch_to_application(self, req, resp, environ):
+        app_callable = self.get_app_object(req, environ)
+        self.set_wsgi_environment(req, resp, environ, self.params, self.get_j2ee_ns(req, resp))
+        response_callable = start_response_object(req, resp)
+        try:
+            app_return = self.call_application(app_callable, environ, response_callable)
+            if app_return is None:
+                raise ReturnNotIterable("Application returned None: must return an iterable")
+            self.deal_with_app_return(environ, response_callable, app_return)
+        except ModjyException, mx:
+            self.raise_exc(mx.__class__, str(mx))
+        except Exception, x:
+            self.raise_exc(ApplicationException, str(x))
+
+    def call_application(self, app_callable, environ, response_callable):
+        if self.params['multithread']:
+            return app_callable.__call__(environ, response_callable)
+        else:
+            return synchronize.apply_synchronized( \
+                app_callable, \
+                app_callable, \
+                (environ, response_callable))
+
+    def expand_relative_path(self, path):
+        if path.startswith("$"):
+            return self.servlet.getServletContext().getRealPath(path[1:])
+        return path
+
+    def raise_exc(self, exc_class, message):
+        self.log.error(message)
+        raise exc_class(message)
diff --git a/src/main/resources/PythonLibs/modjy/modjy_exceptions.py b/src/main/resources/PythonLibs/modjy/modjy_exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..8ce6e35ac61c94eeb1250846151a1e7229a23cf4
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_exceptions.py
@@ -0,0 +1,91 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+import sys
+import StringIO
+import traceback
+
+from java.lang import IllegalStateException
+from java.io import IOException
+from javax.servlet import ServletException
+
+class ModjyException(Exception): pass
+
+class ModjyIOException(ModjyException): pass
+
+class ConfigException(ModjyException): pass
+class BadParameter(ConfigException): pass
+class ApplicationNotFound(ConfigException): pass
+class NoCallable(ConfigException): pass
+
+class RequestException(ModjyException): pass
+
+class ApplicationException(ModjyException): pass
+class StartResponseNotCalled(ApplicationException): pass
+class StartResponseCalledTwice(ApplicationException): pass
+class ResponseCommitted(ApplicationException): pass
+class HopByHopHeaderSet(ApplicationException): pass
+class WrongLength(ApplicationException): pass
+class BadArgument(ApplicationException): pass
+class ReturnNotIterable(ApplicationException): pass
+class NonStringOutput(ApplicationException): pass
+
+class exception_handler:
+
+    def handle(self, req, resp, environ, exc, exc_info):
+        pass
+
+    def get_status_and_message(self, req, resp, exc):
+        return resp.SC_INTERNAL_SERVER_ERROR, "Server configuration error"
+
+#
+#    Special exception handler for testing
+#
+
+class testing_handler(exception_handler):
+
+    def handle(self, req, resp, environ, exc, exc_info):
+        typ, value, tb = exc_info
+        err_msg = StringIO.StringIO()
+        err_msg.write("%s: %s\n" % (typ, value,) )
+        err_msg.write(">Environment\n")
+        for k in environ.keys():
+            err_msg.write("%s=%s\n" % (k, repr(environ[k])) )
+        err_msg.write("<Environment\n")
+        err_msg.write(">TraceBack\n")
+        for line in traceback.format_exception(typ, value, tb):
+            err_msg.write(line)
+        err_msg.write("<TraceBack\n")
+        try:
+            status, message = self.get_status_and_message(req, resp, exc)
+            resp.setStatus(status)
+            resp.setContentLength(len(err_msg.getvalue()))
+            resp.getOutputStream().write(err_msg.getvalue())
+        except IllegalStateException, ise:
+            raise exc # Let the container deal with it
+
+#
+#    Standard exception handler
+#
+
+class standard_handler(exception_handler):
+
+    def handle(self, req, resp, environ, exc, exc_info):
+        raise exc_info[0], exc_info[1], exc_info[2]
diff --git a/src/main/resources/PythonLibs/modjy/modjy_impl.py b/src/main/resources/PythonLibs/modjy/modjy_impl.py
new file mode 100644
index 0000000000000000000000000000000000000000..82662937f489c8979dfdf689ed815ccaf8f3fc02
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_impl.py
@@ -0,0 +1,101 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+import types
+import sys
+
+from modjy_exceptions import *
+
+class modjy_impl:
+
+    def deal_with_app_return(self, environ, start_response_callable, app_return):
+        self.log.debug("Processing app return type: %s" % str(type(app_return)))
+        if isinstance(app_return, types.StringTypes):
+            raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return)))
+        if type(app_return) is types.FileType:
+            pass # TBD: What to do here? can't call fileno()
+        if hasattr(app_return, '__len__') and callable(app_return.__len__):
+            expected_pieces = app_return.__len__()
+        else:
+            expected_pieces = -1
+        try:
+            try:
+                ix = 0
+                for next_piece in app_return:
+                    if not isinstance(next_piece, types.StringTypes):
+                        raise NonStringOutput("Application returned iterable containing non-strings: %s" % str(type(next_piece)))
+                    if ix == 0:
+                        # The application may have called start_response in the first iteration
+                        if not start_response_callable.called:
+                            raise StartResponseNotCalled("Start_response callable was never called.")
+                        if not start_response_callable.content_length \
+                            and expected_pieces == 1 \
+                            and start_response_callable.write_callable.num_writes == 0:
+                                # Take the length of the first piece
+                                start_response_callable.set_content_length(len(next_piece))
+                    start_response_callable.write_callable(next_piece)
+                    ix += 1
+                    if ix == expected_pieces:
+                        break
+                if expected_pieces != -1 and ix != expected_pieces:
+                    raise WrongLength("Iterator len() was wrong. Expected %d pieces: got %d" % (expected_pieces, ix) )
+            except AttributeError, ax:
+                if str(ax) == "__getitem__":
+                    raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return)))
+                else:
+                    raise ax
+            except TypeError, tx:
+                raise ReturnNotIterable("Application returned object that was not an iterable: %s" % str(type(app_return)))
+            except ModjyException, mx:
+                raise mx
+            except Exception, x:
+                raise ApplicationException(x)
+        finally:
+            if hasattr(app_return, 'close') and callable(app_return.close):
+                app_return.close()
+
+    def init_impl(self):
+        self.do_j_env_params()
+
+    def add_packages(self, package_list):
+        packages = [p.strip() for p in package_list.split(';')]
+        for p in packages:
+            self.log.info("Adding java package %s to jython" % p)
+            sys.add_package(p)
+
+    def add_classdirs(self, classdir_list):
+        classdirs = [cd.strip() for cd in classdir_list.split(';')]
+        for cd in classdirs:
+            self.log.info("Adding directory %s to jython class file search path" % cd)
+            sys.add_classdir(cd)
+
+    def add_extdirs(self, extdir_list):
+        extdirs = [ed.strip() for ed in extdir_list.split(';')]
+        for ed in extdirs:
+            self.log.info("Adding directory %s for .jars and .zips search path" % ed)
+            sys.add_extdir(self.expand_relative_path(ed))
+
+    def do_j_env_params(self):
+        if self.params['packages']:
+            self.add_packages(self.params['packages'])
+        if self.params['classdirs']:
+            self.add_classdirs(self.params['classdirs'])
+        if self.params['extdirs']:
+            self.add_extdirs(self.params['extdirs'])
diff --git a/src/main/resources/PythonLibs/modjy/modjy_input.py b/src/main/resources/PythonLibs/modjy/modjy_input.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca6e72702a661cdc5ef244400c9981d38cade2f5
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_input.py
@@ -0,0 +1,167 @@
+###
+#
+# Copyright Alan Kennedy.
+#
+# You may contact the copyright holder at this uri:
+#
+# http://www.xhaus.com/contact/modjy
+#
+# The licence under which this code is released is the Apache License v2.0.
+#
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+#
+# You may also read a copy of the license at the following web address.
+#
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+#
+# This code adapted from the socket._fileobject class
+#
+
+import jarray
+
+class modjy_input_object(object):
+
+    def __init__(self, servlet_inputstream, bufsize=8192):
+        self.istream = servlet_inputstream
+        self.buffer_size = bufsize
+        self.buffer = ""
+
+    def istream_read(self, n):
+        data = jarray.zeros(n, 'b')
+        m = self.istream.read(data)
+        if m == -1: # indicates EOF has been reached, so we just return the empty string
+            return ""
+        elif m <= 0:
+            return ""
+        if m < n:
+            data = data[:m]
+        return data.tostring()
+
+    def read(self, size=-1):
+        data = self.buffer
+        if size < 0:
+            # Read until EOF
+            buffers = []
+            if data:
+                buffers.append(data)
+            self.buffer = ""
+            recv_size = self.buffer_size
+            while True:
+                data = self.istream_read(recv_size)
+                if not data:
+                    break
+                buffers.append(data)
+            return "".join(buffers)
+        else:
+            # Read until size bytes or EOF seen, whichever comes first
+            buf_len = len(data)
+            if buf_len >= size:
+                self.buffer = data[size:]
+                return data[:size]
+            buffers = []
+            if data:
+                buffers.append(data)
+            self.buffer = ""
+            while True:
+                left = size - buf_len
+                recv_size = max(self.buffer_size, left)
+                data = self.istream_read(recv_size)
+                if not data:
+                    break
+                buffers.append(data)
+                n = len(data)
+                if n >= left:
+                    self.buffer = data[left:]
+                    buffers[-1] = data[:left]
+                    break
+                buf_len += n
+            return "".join(buffers)
+
+    def readline(self, size=-1):
+        data = self.buffer
+        if size < 0:
+            # Read until \n or EOF, whichever comes first
+            nl = data.find('\n')
+            if nl >= 0:
+                nl += 1
+                self.buffer = data[nl:]
+                return data[:nl]
+            buffers = []
+            if data:
+                buffers.append(data)
+            self.buffer = ""
+            while True:
+                data = self.istream_read(self.buffer_size)
+                if not data:
+                    break
+                buffers.append(data)
+                nl = data.find('\n')
+                if nl >= 0:
+                    nl += 1
+                    self.buffer = data[nl:]
+                    buffers[-1] = data[:nl]
+                    break
+            return "".join(buffers)
+        else:
+            # Read until size bytes or \n or EOF seen, whichever comes first
+            nl = data.find('\n', 0, size)
+            if nl >= 0:
+                nl += 1
+                self.buffer = data[nl:]
+                return data[:nl]
+            buf_len = len(data)
+            if buf_len >= size:
+                self.buffer = data[size:]
+                return data[:size]
+            buffers = []
+            if data:
+                buffers.append(data)
+            self.buffer = ""
+            while True:
+                data = self.istream_read(self.buffer_size)
+                if not data:
+                    break
+                buffers.append(data)
+                left = size - buf_len
+                nl = data.find('\n', 0, left)
+                if nl >= 0:
+                    nl += 1
+                    self.buffer = data[nl:]
+                    buffers[-1] = data[:nl]
+                    break
+                n = len(data)
+                if n >= left:
+                    self.buffer = data[left:]
+                    buffers[-1] = data[:left]
+                    break
+                buf_len += n
+            return "".join(buffers)
+
+    def readlines(self, sizehint=0):
+        total = 0
+        list = []
+        while True:
+            line = self.readline()
+            if not line:
+                break
+            list.append(line)
+            total += len(line)
+            if sizehint and total >= sizehint:
+                break
+        return list
+
+    # Iterator protocols
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        line = self.readline()
+        if not line:
+            raise StopIteration
+        return line
diff --git a/src/main/resources/PythonLibs/modjy/modjy_log.py b/src/main/resources/PythonLibs/modjy/modjy_log.py
new file mode 100644
index 0000000000000000000000000000000000000000..9931e340b558096474f70f151c28a6cd9005dff3
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_log.py
@@ -0,0 +1,80 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+import java
+
+import sys
+
+DEBUG = 'debug'
+INFO = 'info'
+WARN = 'warn'
+ERROR = 'error'
+FATAL = 'fatal'
+
+levels_dict = {}
+ix = 0
+for level in [DEBUG, INFO, WARN, ERROR, FATAL, ]:
+    levels_dict[level]=ix
+    ix += 1
+
+class modjy_logger:
+
+    def __init__(self, context):
+        self.log_ctx = context
+        self.format_str = "%(lvl)s:\t%(msg)s"
+        self.log_level = levels_dict[DEBUG]
+
+    def _log(self, level, level_str, msg, exc):
+        if level >= self.log_level:
+            msg = self.format_str % {'lvl': level_str, 'msg': msg, }
+            if exc:
+#                java.lang.System.err.println(msg, exc)
+                self.log_ctx.log(msg, exc)
+            else:
+#                java.lang.System.err.println(msg)
+                self.log_ctx.log(msg)
+
+    def debug(self, msg, exc=None):
+        self._log(0, DEBUG, msg, exc)
+
+    def info(self, msg, exc=None):
+        self._log(1, INFO, msg, exc)
+
+    def warn(self, msg, exc=None):
+        self._log(2, WARN, msg, exc)
+
+    def error(self, msg, exc=None):
+        self._log(3, ERROR, msg, exc)
+
+    def fatal(self, msg, exc=None):
+        self._log(4, FATAL, msg, exc)
+
+    def set_log_level(self, level_string):
+        try:
+            self.log_level = levels_dict[level_string]
+        except KeyError:
+            raise BadParameter("Invalid log level: '%s'" % level_string)
+
+    def set_log_format(self, format_string):
+        # BUG! Format string never actually used in this function.
+        try:
+            self._log(debug, "This is a log formatting test", None)
+        except KeyError:
+            raise BadParameter("Bad format string: '%s'" % format_string)
diff --git a/src/main/resources/PythonLibs/modjy/modjy_params.py b/src/main/resources/PythonLibs/modjy/modjy_params.py
new file mode 100644
index 0000000000000000000000000000000000000000..b6c400c5578020391d0820c83aa406115dc51184
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_params.py
@@ -0,0 +1,84 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+from UserDict import UserDict
+
+BOOLEAN = ('boolean', int)
+INTEGER = ('integer', int)
+FLOAT   = ('float', float)
+STRING  = ('string', None)
+
+modjy_servlet_params = {
+
+    'multithread':          (BOOLEAN, 1),
+    'cache_callables':      (BOOLEAN, 1),
+    'reload_on_mod':        (BOOLEAN, 0),
+
+    'app_import_name':      (STRING, None),
+
+    'app_directory':        (STRING, None),
+    'app_filename':         (STRING, 'application.py'),
+    'app_callable_name':    (STRING, 'handler'),
+    'callable_query_name':  (STRING, None),
+
+    'exc_handler':          (STRING, 'standard'),
+
+    'log_level':            (STRING, 'info'),
+
+    'packages':             (STRING, None),
+    'classdirs':            (STRING, None),
+    'extdirs':              (STRING, None),
+
+    'initial_env':          (STRING, None),
+}
+
+class modjy_param_mgr(UserDict):
+
+    def __init__(self, param_types):
+        UserDict.__init__(self)
+        self.param_types = param_types
+        for pname in self.param_types.keys():
+            typ, default = self.param_types[pname]
+            self.__setitem__(pname, default)
+
+    def __getitem__(self, name):
+        return self._get_defaulted_value(name)
+
+    def __setitem__(self, name, value):
+        self.data[name] = self._convert_value(name, value)
+
+    def _convert_value(self, name, value):
+        if self.param_types.has_key(name):
+            typ, default = self.param_types[name]
+            typ_str, typ_func = typ
+            if typ_func:
+                try:
+                    return typ_func(value)
+                except ValueError:
+                    raise BadParameter("Illegal value for %s parameter '%s': %s" % (typ_str, name, value) )
+        return value
+
+    def _get_defaulted_value(self, name):
+        if self.data.has_key(name):
+            return self.data[name]
+        if self.param_types.has_key(name):
+            typ, default = self.param_types[name]
+            return default
+        raise KeyError(name)
diff --git a/src/main/resources/PythonLibs/modjy/modjy_publish.py b/src/main/resources/PythonLibs/modjy/modjy_publish.py
new file mode 100644
index 0000000000000000000000000000000000000000..adb3b1ad14286b06b5012b364337c5457c0193d1
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_publish.py
@@ -0,0 +1,143 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+import sys
+import synchronize
+
+from java.io import File
+
+from modjy_exceptions import *
+
+class modjy_publisher:
+
+    def init_publisher(self):
+        self.cache = None
+        if self.params['app_directory']:
+            self.app_directory = self.expand_relative_path(self.params['app_directory'])
+        else:
+            self.app_directory = self.servlet_context.getRealPath('/')
+        self.params['app_directory'] = self.app_directory
+        if self.app_directory is not None and not self.app_directory in sys.path:
+            sys.path.append(self.app_directory)
+
+    def map_uri(self, req, environ):
+        source_uri = '%s%s%s' % (self.app_directory, File.separator, self.params['app_filename'])
+        callable_name = self.params['app_callable_name']
+        if self.params['callable_query_name']:
+            query_string = req.getQueryString()
+            if query_string:
+                for name_val in query_string.split('&'):
+                    if name_val.find('=') != -1:
+                        name, value = name_val.split('=', 1)
+                    else:
+                        name, value = name_val, ''
+                    if name == self.params['callable_query_name']:
+                        callable_name = value
+            else:
+                callable_name = ''
+        return source_uri, callable_name
+
+    def get_app_object(self, req, environ):
+        environ["SCRIPT_NAME"] = "%s%s" % (req.getContextPath(), req.getServletPath())
+        path_info = req.getPathInfo() or ""
+        environ["PATH_INFO"] = path_info
+        environ["PATH_TRANSLATED"] = File(self.app_directory, path_info).getPath()
+
+        if self.params['app_import_name']:
+            return self.get_app_object_importable(self.params['app_import_name'])
+        else:
+            if self.cache is None:
+                self.cache = {}
+            return self.get_app_object_old_style(req, environ)
+
+    get_app_object = synchronize.make_synchronized(get_app_object)
+
+    def get_app_object_importable(self, importable_name):
+        self.log.debug("Attempting to import application callable '%s'\n" % (importable_name, ))
+        # Under the importable mechanism, the cache contains a single object
+        if self.cache is None:
+            application, instantiable, method_name = self.load_importable(importable_name.strip())
+            if instantiable and self.params['cache_callables']:
+                application = application()
+            self.cache = application, instantiable, method_name
+        application, instantiable, method_name = self.cache
+        self.log.debug("Application is " + str(application))
+        if instantiable and not self.params['cache_callables']:
+            application = application()
+            self.log.debug("Instantiated application is " + str(application))
+        if method_name is not None:
+            if not hasattr(application, method_name):
+                self.log.fatal("Attribute error application callable '%s' as no method '%s'" % (application, method_name))
+                self.raise_exc(ApplicationNotFound, "Attribute error application callable '%s' as no method '%s'" % (application, method_name))
+            application = getattr(application, method_name)
+            self.log.debug("Application method is " + str(application))
+        return application
+
+    def load_importable(self, name):
+        try:
+            instantiable = False ; method_name = None
+            importable_name = name
+            if name.find('()') != -1:
+                instantiable = True
+                importable_name, method_name = name.split('()')
+                if method_name.startswith('.'):
+                    method_name = method_name[1:]
+                if not method_name:
+                    method_name = None
+            module_path, from_name = importable_name.rsplit('.', 1)
+            imported = __import__(module_path, globals(), locals(), [from_name])
+            imported = getattr(imported, from_name)
+            return imported, instantiable, method_name
+        except (ImportError, AttributeError), aix:
+            self.log.fatal("Import error import application callable '%s': %s\n" % (name, str(aix)))
+            self.raise_exc(ApplicationNotFound, "Failed to import app callable '%s': %s" % (name, str(aix)))
+
+    def get_app_object_old_style(self, req, environ):
+        source_uri, callable_name = self.map_uri(req, environ)
+        source_filename = source_uri
+        if not self.params['cache_callables']:
+            self.log.debug("Caching of callables disabled")
+            return self.load_object(source_filename, callable_name)
+        if not self.cache.has_key( (source_filename, callable_name) ):
+            self.log.debug("Callable object not in cache: %s#%s" % (source_filename, callable_name) )
+            return self.load_object(source_filename, callable_name)
+        app_callable, last_mod = self.cache.get( (source_filename, callable_name) )
+        self.log.debug("Callable object was in cache: %s#%s" % (source_filename, callable_name) )
+        if self.params['reload_on_mod']:
+            f = File(source_filename)
+            if f.lastModified() > last_mod:
+                self.log.info("Source file '%s' has been modified: reloading" % source_filename)
+                return self.load_object(source_filename, callable_name)
+        return app_callable
+
+    def load_object(self, path, callable_name):
+        try:
+            app_ns = {} ; execfile(path, app_ns)
+            app_callable = app_ns[callable_name]
+            f = File(path)
+            self.cache[ (path, callable_name) ] = (app_callable, f.lastModified())
+            return app_callable
+        except IOError, ioe:
+            self.raise_exc(ApplicationNotFound, "Application filename not found: %s" % path)
+        except KeyError, k:
+            self.raise_exc(NoCallable, "No callable named '%s' in %s" % (callable_name, path))
+        except Exception, x:
+            self.raise_exc(NoCallable, "Error loading jython callable '%s': %s" % (callable_name, str(x)) )
+
diff --git a/src/main/resources/PythonLibs/modjy/modjy_response.py b/src/main/resources/PythonLibs/modjy/modjy_response.py
new file mode 100644
index 0000000000000000000000000000000000000000..52c9bc096aa203e7b80f31afa60dc72d0b76f273
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_response.py
@@ -0,0 +1,113 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+import types
+
+from java.lang import System
+
+from modjy_exceptions import *
+from modjy_write import write_object
+
+# From: http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
+
+hop_by_hop_headers = {
+    'connection': None,
+    'keep-alive': None,
+    'proxy-authenticate': None,
+    'proxy-authorization': None,
+    'te': None,
+    'trailers': None,
+    'transfer-encoding': None,
+    'upgrade': None,
+}
+
+class start_response_object:
+
+    def __init__(self, req, resp):
+        self.http_req = req
+        self.http_resp = resp
+        self.write_callable = None
+        self.called = 0
+        self.content_length = None
+
+    # I'm doing the parameters this way to facilitate porting back to java
+    def __call__(self, *args, **keywords):
+        if len(args) < 2 or len(args) > 3:
+            raise BadArgument("Start response callback requires either two or three arguments: got %s" % str(args))
+        if len(args) == 3:
+            exc_info = args[2]
+            try:
+                try:
+                    self.http_resp.reset()
+                except IllegalStateException, isx:
+                    raise exc_info[0], exc_info[1], exc_info[2]
+            finally:
+                exc_info = None
+        else:
+            if self.called > 0:
+                raise StartResponseCalledTwice("Start response callback may only be called once, without exception information.")
+        status_str = args[0]
+        headers_list = args[1]
+        if not isinstance(status_str, types.StringType):
+            raise BadArgument("Start response callback requires string as first argument")
+        if not isinstance(headers_list, types.ListType):
+            raise BadArgument("Start response callback requires list as second argument")
+        try:
+            status_code, status_message_str = status_str.split(" ", 1)
+            self.http_resp.setStatus(int(status_code))
+        except ValueError:
+            raise BadArgument("Status string must be of the form '<int> <string>'")
+        self.make_write_object()
+        try:
+            for header_name, header_value in headers_list:
+                header_name_lower = header_name.lower()
+                if hop_by_hop_headers.has_key(header_name_lower):
+                    raise HopByHopHeaderSet("Under WSGI, it is illegal to set hop-by-hop headers, i.e. '%s'" % header_name)
+                if header_name_lower == "content-length":
+                    try:
+                        self.set_content_length(int(header_value))
+                    except ValueError, v:
+                        raise BadArgument("Content-Length header value must be a string containing an integer, not '%s'" % header_value)
+                else:
+                    final_value = header_value.encode('latin-1')
+                    # Here would be the place to check for control characters, whitespace, etc
+                    self.http_resp.addHeader(header_name, final_value)
+        except (AttributeError, TypeError), t:
+            raise BadArgument("Start response callback headers must contain a list of (<string>,<string>) tuples")
+        except UnicodeError, u:
+            raise BadArgument("Encoding error: header values may only contain latin-1 characters, not '%s'" % repr(header_value))
+        except ValueError, v:
+            raise BadArgument("Headers list must contain 2-tuples")
+        self.called += 1
+        return self.write_callable
+
+    def set_content_length(self, length):
+        if self.write_callable.num_writes == 0:
+            self.content_length = length
+            self.http_resp.setContentLength(length)
+        else:
+            raise ResponseCommitted("Cannot set content-length: response is already commited.")
+
+    def make_write_object(self):
+        try:
+            self.write_callable = write_object(self.http_resp.getOutputStream())
+        except IOException, iox:
+            raise IOError(iox)
+        return self.write_callable
diff --git a/src/main/resources/PythonLibs/modjy/modjy_write.py b/src/main/resources/PythonLibs/modjy/modjy_write.py
new file mode 100644
index 0000000000000000000000000000000000000000..e3d105c02cf128b215db261b5bc2cb4ee13159c9
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_write.py
@@ -0,0 +1,43 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+import types
+
+from modjy_exceptions import *
+
+class write_object:
+
+    def __init__(self, ostream):
+        self.ostream = ostream
+        self.num_writes = 0
+
+    def __call__(self, *args, **keywords):
+        if len(args) != 1 or not isinstance(args[0], types.StringTypes):
+            raise NonStringOutput("Invocation of write callable requires exactly one string argument")
+        try:
+            self.ostream.write(args[0]) # Jython implicitly converts the (binary) string to a byte array
+            # WSGI requires that all output be flushed before returning to the application
+            # According to the java docs: " The flush method of OutputStream does nothing."
+            # Still, leave it in place for now: it's in the right place should this
+            # code ever be ported to another platform.
+            self.ostream.flush()
+            self.num_writes += 1
+        except Exception, x:
+            raise ModjyIOException(x)
diff --git a/src/main/resources/PythonLibs/modjy/modjy_wsgi.py b/src/main/resources/PythonLibs/modjy/modjy_wsgi.py
new file mode 100644
index 0000000000000000000000000000000000000000..9788ce2e85bb31ec6afe00b415962e64f64c312a
--- /dev/null
+++ b/src/main/resources/PythonLibs/modjy/modjy_wsgi.py
@@ -0,0 +1,157 @@
+###
+#
+# Copyright Alan Kennedy. 
+# 
+# You may contact the copyright holder at this uri:
+# 
+# http://www.xhaus.com/contact/modjy
+# 
+# The licence under which this code is released is the Apache License v2.0.
+# 
+# The terms and conditions of this license are listed in a file contained
+# in the distribution that also contained this file, under the name
+# LICENSE.txt.
+# 
+# You may also read a copy of the license at the following web address.
+# 
+# http://modjy.xhaus.com/LICENSE.txt
+#
+###
+
+from java.lang import System
+
+try:
+    from org.python.core.util import FileUtil
+    create_py_file = FileUtil.wrap
+except ImportError:
+    from org.python.core import PyFile
+    create_py_file = PyFile
+
+from modjy_exceptions import *
+from modjy_input import modjy_input_object
+
+server_name = "modjy"
+server_param_prefix = "%s.param" % server_name
+j2ee_ns_prefix = "j2ee"
+
+cgi_var_char_encoding = "iso-8859-1"
+
+class modjy_wsgi:
+
+    #
+    #    WSGI constants
+    #
+
+    empty_pystring = u""
+    wsgi_version = (1,0)
+
+    #
+    #    Container-specific constants
+    #
+
+    modjy_version = (0, 25, 3)
+
+    def set_string_envvar(self, dict, name, value):
+        if value is None:
+            value =  self.empty_pystring
+        value =  value.encode(cgi_var_char_encoding)
+        dict[name] = value
+
+    def set_string_envvar_optional(self, dict, name, value, default_value):
+        if value != default_value:
+            self.set_string_envvar(dict, name, value)
+
+    def set_int_envvar(self, dict, name, value, default_value):
+        if value == default_value:
+            value = self.empty_pystring
+        else:
+            value = unicode(value)
+        self.set_string_envvar(dict, name, value)
+
+    def set_container_specific_wsgi_vars(self, req, resp, dict, params):
+        dict["%s.version" % server_name] = self.modjy_version
+        for pname in params.keys():
+            dict["%s.%s" % (server_param_prefix, pname)] = params[pname]
+
+    def set_j2ee_specific_wsgi_vars(self, dict, j2ee_ns):
+        for p in j2ee_ns.keys():
+            dict["%s.%s" % (j2ee_ns_prefix, p)] = j2ee_ns[p]
+
+    def set_required_cgi_environ (self, req, resp, dict):
+        self.set_string_envvar(dict, "REQUEST_METHOD", req.getMethod())
+        self.set_string_envvar(dict, "QUERY_STRING", req.getQueryString())
+        self.set_string_envvar(dict, "CONTENT_TYPE", req.getContentType())
+        self.set_int_envvar(dict, "CONTENT_LENGTH", req.getContentLength(), -1)
+        self.set_string_envvar(dict, "SERVER_NAME", req.getLocalName())
+        self.set_int_envvar(dict, "SERVER_PORT", req.getLocalPort(), 0)
+
+    def set_other_cgi_environ (self, req, resp, dict):
+        if req.isSecure():
+            self.set_string_envvar(dict, "HTTPS", 'on')
+        else:
+            self.set_string_envvar(dict, "HTTPS", 'off')
+        self.set_string_envvar(dict, "SERVER_PROTOCOL", req.getProtocol())
+        self.set_string_envvar(dict, "REMOTE_HOST", req.getRemoteHost())
+        self.set_string_envvar(dict, "REMOTE_ADDR", req.getRemoteAddr())
+        self.set_int_envvar(dict, "REMOTE_PORT", req.getRemotePort(), -1)
+        self.set_string_envvar_optional(dict, "AUTH_TYPE", req.getAuthType(), None)
+        self.set_string_envvar_optional(dict, "REMOTE_USER", req.getRemoteUser(), None)
+
+    def set_http_header_environ(self, req, resp, dict):
+        header_name_enum = req.getHeaderNames()
+        while header_name_enum.hasMoreElements():
+            curr_header_name = header_name_enum.nextElement()
+            values = None
+            values_enum = req.getHeaders(curr_header_name)
+            while values_enum.hasMoreElements():
+                next_value  = values_enum.nextElement().encode(cgi_var_char_encoding)
+                if values is None:
+                    values = next_value
+                else:
+                    if isinstance(values, list):
+                        values.append(next_value)
+                    else:
+                        values = [values]
+            dict["HTTP_%s" % str(curr_header_name).replace('-', '_').upper()] = values
+
+    def set_required_wsgi_vars(self, req, resp, dict):
+        dict["wsgi.version"] = self.wsgi_version
+        dict["wsgi.url_scheme"] = req.getScheme()
+        dict["wsgi.multithread"] = \
+            int(dict["%s.cache_callables" % server_param_prefix]) \
+                and \
+            int(dict["%s.multithread" % server_param_prefix])
+        dict["wsgi.multiprocess"] = self.wsgi_multiprocess = 0
+        dict["wsgi.run_once"] = not(dict["%s.cache_callables" % server_param_prefix])
+
+    def set_wsgi_streams(self, req, resp, dict):
+        try:
+            dict["wsgi.input"]  = modjy_input_object(req.getInputStream())
+            dict["wsgi.errors"] = create_py_file(System.err)
+        except IOException, iox:
+            raise ModjyIOException(iox)
+
+    def set_wsgi_classes(self, req, resp, dict):
+        # dict["wsgi.file_wrapper"]  = modjy_file_wrapper
+        pass
+
+    def set_user_specified_environment(self, req, resp, wsgi_environ, params):
+        if not params.has_key('initial_env') or not params['initial_env']:
+            return
+        user_env_string = params['initial_env']
+        for l in user_env_string.split('\n'):
+            l = l.strip()
+            if l:
+                name, value = l.split(':', 1)
+                wsgi_environ[name.strip()] = value.strip()
+
+    def set_wsgi_environment(self, req, resp, wsgi_environ, params, j2ee_ns):
+        self.set_container_specific_wsgi_vars(req, resp, wsgi_environ, params)
+        self.set_j2ee_specific_wsgi_vars(wsgi_environ, j2ee_ns)
+        self.set_required_cgi_environ(req, resp, wsgi_environ)
+        self.set_other_cgi_environ(req, resp, wsgi_environ)
+        self.set_http_header_environ(req, resp, wsgi_environ)
+        self.set_required_wsgi_vars(req, resp, wsgi_environ)
+        self.set_wsgi_streams(req, resp, wsgi_environ)
+        self.set_wsgi_classes(req, resp, wsgi_environ)
+        self.set_user_specified_environment(req, resp, wsgi_environ, params)
diff --git a/src/main/resources/PythonLibs/multifile.py b/src/main/resources/PythonLibs/multifile.py
new file mode 100644
index 0000000000000000000000000000000000000000..35b0200c248adc9988588afa3747582fb4c285e7
--- /dev/null
+++ b/src/main/resources/PythonLibs/multifile.py
@@ -0,0 +1,162 @@
+"""A readline()-style interface to the parts of a multipart message.
+
+The MultiFile class makes each part of a multipart message "feel" like
+an ordinary file, as long as you use fp.readline().  Allows recursive
+use, for nested multipart messages.  Probably best used together
+with module mimetools.
+
+Suggested use:
+
+real_fp = open(...)
+fp = MultiFile(real_fp)
+
+"read some lines from fp"
+fp.push(separator)
+while 1:
+        "read lines from fp until it returns an empty string" (A)
+        if not fp.next(): break
+fp.pop()
+"read remaining lines from fp until it returns an empty string"
+
+The latter sequence may be used recursively at (A).
+It is also allowed to use multiple push()...pop() sequences.
+
+If seekable is given as 0, the class code will not do the bookkeeping
+it normally attempts in order to make seeks relative to the beginning of the
+current file part.  This may be useful when using MultiFile with a non-
+seekable stream object.
+"""
+from warnings import warn
+warn("the multifile module has been deprecated since Python 2.5",
+        DeprecationWarning, stacklevel=2)
+del warn
+
+__all__ = ["MultiFile","Error"]
+
+class Error(Exception):
+    pass
+
+class MultiFile:
+
+    seekable = 0
+
+    def __init__(self, fp, seekable=1):
+        self.fp = fp
+        self.stack = []
+        self.level = 0
+        self.last = 0
+        if seekable:
+            self.seekable = 1
+            self.start = self.fp.tell()
+            self.posstack = []
+
+    def tell(self):
+        if self.level > 0:
+            return self.lastpos
+        return self.fp.tell() - self.start
+
+    def seek(self, pos, whence=0):
+        here = self.tell()
+        if whence:
+            if whence == 1:
+                pos = pos + here
+            elif whence == 2:
+                if self.level > 0:
+                    pos = pos + self.lastpos
+                else:
+                    raise Error, "can't use whence=2 yet"
+        if not 0 <= pos <= here or \
+                        self.level > 0 and pos > self.lastpos:
+            raise Error, 'bad MultiFile.seek() call'
+        self.fp.seek(pos + self.start)
+        self.level = 0
+        self.last = 0
+
+    def readline(self):
+        if self.level > 0:
+            return ''
+        line = self.fp.readline()
+        # Real EOF?
+        if not line:
+            self.level = len(self.stack)
+            self.last = (self.level > 0)
+            if self.last:
+                raise Error, 'sudden EOF in MultiFile.readline()'
+            return ''
+        assert self.level == 0
+        # Fast check to see if this is just data
+        if self.is_data(line):
+            return line
+        else:
+            # Ignore trailing whitespace on marker lines
+            marker = line.rstrip()
+        # No?  OK, try to match a boundary.
+        # Return the line (unstripped) if we don't.
+        for i, sep in enumerate(reversed(self.stack)):
+            if marker == self.section_divider(sep):
+                self.last = 0
+                break
+            elif marker == self.end_marker(sep):
+                self.last = 1
+                break
+        else:
+            return line
+        # We only get here if we see a section divider or EOM line
+        if self.seekable:
+            self.lastpos = self.tell() - len(line)
+        self.level = i+1
+        if self.level > 1:
+            raise Error,'Missing endmarker in MultiFile.readline()'
+        return ''
+
+    def readlines(self):
+        list = []
+        while 1:
+            line = self.readline()
+            if not line: break
+            list.append(line)
+        return list
+
+    def read(self): # Note: no size argument -- read until EOF only!
+        return ''.join(self.readlines())
+
+    def next(self):
+        while self.readline(): pass
+        if self.level > 1 or self.last:
+            return 0
+        self.level = 0
+        self.last = 0
+        if self.seekable:
+            self.start = self.fp.tell()
+        return 1
+
+    def push(self, sep):
+        if self.level > 0:
+            raise Error, 'bad MultiFile.push() call'
+        self.stack.append(sep)
+        if self.seekable:
+            self.posstack.append(self.start)
+            self.start = self.fp.tell()
+
+    def pop(self):
+        if self.stack == []:
+            raise Error, 'bad MultiFile.pop() call'
+        if self.level <= 1:
+            self.last = 0
+        else:
+            abslastpos = self.lastpos + self.start
+        self.level = max(0, self.level - 1)
+        self.stack.pop()
+        if self.seekable:
+            self.start = self.posstack.pop()
+            if self.level > 0:
+                self.lastpos = abslastpos - self.start
+
+    def is_data(self, line):
+        return line[:2] != '--'
+
+    def section_divider(self, str):
+        return "--" + str
+
+    def end_marker(self, str):
+        return "--" + str + "--"
diff --git a/src/main/resources/PythonLibs/mutex.py b/src/main/resources/PythonLibs/mutex.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8acba4a35f93301bea1c528fb3286dc2384b33d
--- /dev/null
+++ b/src/main/resources/PythonLibs/mutex.py
@@ -0,0 +1,55 @@
+"""Mutual exclusion -- for use with module sched
+
+A mutex has two pieces of state -- a 'locked' bit and a queue.
+When the mutex is not locked, the queue is empty.
+Otherwise, the queue contains 0 or more (function, argument) pairs
+representing functions (or methods) waiting to acquire the lock.
+When the mutex is unlocked while the queue is not empty,
+the first queue entry is removed and its function(argument) pair called,
+implying it now has the lock.
+
+Of course, no multi-threading is implied -- hence the funny interface
+for lock, where a function is called once the lock is aquired.
+"""
+from warnings import warnpy3k
+warnpy3k("the mutex module has been removed in Python 3.0", stacklevel=2)
+del warnpy3k
+
+from collections import deque
+
+class mutex:
+    def __init__(self):
+        """Create a new mutex -- initially unlocked."""
+        self.locked = False
+        self.queue = deque()
+
+    def test(self):
+        """Test the locked bit of the mutex."""
+        return self.locked
+
+    def testandset(self):
+        """Atomic test-and-set -- grab the lock if it is not set,
+        return True if it succeeded."""
+        if not self.locked:
+            self.locked = True
+            return True
+        else:
+            return False
+
+    def lock(self, function, argument):
+        """Lock a mutex, call the function with supplied argument
+        when it is acquired.  If the mutex is already locked, place
+        function and argument in the queue."""
+        if self.testandset():
+            function(argument)
+        else:
+            self.queue.append((function, argument))
+
+    def unlock(self):
+        """Unlock a mutex.  If the queue is not empty, call the next
+        function with its argument."""
+        if self.queue:
+            function, argument = self.queue.popleft()
+            function(argument)
+        else:
+            self.locked = False
diff --git a/src/main/resources/PythonLibs/netrc.py b/src/main/resources/PythonLibs/netrc.py
new file mode 100644
index 0000000000000000000000000000000000000000..370ad2c88d06f480f2c55435f7b3218adea67e77
--- /dev/null
+++ b/src/main/resources/PythonLibs/netrc.py
@@ -0,0 +1,119 @@
+"""An object-oriented interface to .netrc files."""
+
+# Module and documentation by Eric S. Raymond, 21 Dec 1998
+
+from __future__ import with_statement
+import os, shlex
+
+__all__ = ["netrc", "NetrcParseError"]
+
+
+class NetrcParseError(Exception):
+    """Exception raised on syntax errors in the .netrc file."""
+    def __init__(self, msg, filename=None, lineno=None):
+        self.filename = filename
+        self.lineno = lineno
+        self.msg = msg
+        Exception.__init__(self, msg)
+
+    def __str__(self):
+        return "%s (%s, line %s)" % (self.msg, self.filename, self.lineno)
+
+
+class netrc:
+    def __init__(self, file=None):
+        if file is None:
+            try:
+                file = os.path.join(os.environ['HOME'], ".netrc")
+            except KeyError:
+                raise IOError("Could not find .netrc: $HOME is not set")
+        self.hosts = {}
+        self.macros = {}
+        with open(file) as fp:
+            self._parse(file, fp)
+
+    def _parse(self, file, fp):
+        lexer = shlex.shlex(fp)
+        lexer.wordchars += r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
+        lexer.commenters = lexer.commenters.replace('#', '')
+        while 1:
+            # Look for a machine, default, or macdef top-level keyword
+            toplevel = tt = lexer.get_token()
+            if not tt:
+                break
+            elif tt[0] == '#':
+                fp.readline();
+                continue;
+            elif tt == 'machine':
+                entryname = lexer.get_token()
+            elif tt == 'default':
+                entryname = 'default'
+            elif tt == 'macdef':                # Just skip to end of macdefs
+                entryname = lexer.get_token()
+                self.macros[entryname] = []
+                lexer.whitespace = ' \t'
+                while 1:
+                    line = lexer.instream.readline()
+                    if not line or line == '\012':
+                        lexer.whitespace = ' \t\r\n'
+                        break
+                    self.macros[entryname].append(line)
+                continue
+            else:
+                raise NetrcParseError(
+                    "bad toplevel token %r" % tt, file, lexer.lineno)
+
+            # We're looking at start of an entry for a named machine or default.
+            login = ''
+            account = password = None
+            self.hosts[entryname] = {}
+            while 1:
+                tt = lexer.get_token()
+                if (tt=='' or tt == 'machine' or
+                    tt == 'default' or tt =='macdef'):
+                    if password:
+                        self.hosts[entryname] = (login, account, password)
+                        lexer.push_token(tt)
+                        break
+                    else:
+                        raise NetrcParseError(
+                            "malformed %s entry %s terminated by %s"
+                            % (toplevel, entryname, repr(tt)),
+                            file, lexer.lineno)
+                elif tt == 'login' or tt == 'user':
+                    login = lexer.get_token()
+                elif tt == 'account':
+                    account = lexer.get_token()
+                elif tt == 'password':
+                    password = lexer.get_token()
+                else:
+                    raise NetrcParseError("bad follower token %r" % tt,
+                                          file, lexer.lineno)
+
+    def authenticators(self, host):
+        """Return a (user, account, password) tuple for given host."""
+        if host in self.hosts:
+            return self.hosts[host]
+        elif 'default' in self.hosts:
+            return self.hosts['default']
+        else:
+            return None
+
+    def __repr__(self):
+        """Dump the class data in the format of a .netrc file."""
+        rep = ""
+        for host in self.hosts.keys():
+            attrs = self.hosts[host]
+            rep = rep + "machine "+ host + "\n\tlogin " + repr(attrs[0]) + "\n"
+            if attrs[1]:
+                rep = rep + "account " + repr(attrs[1])
+            rep = rep + "\tpassword " + repr(attrs[2]) + "\n"
+        for macro in self.macros.keys():
+            rep = rep + "macdef " + macro + "\n"
+            for line in self.macros[macro]:
+                rep = rep + line
+            rep = rep + "\n"
+        return rep
+
+if __name__ == '__main__':
+    print netrc()
diff --git a/src/main/resources/PythonLibs/new.py b/src/main/resources/PythonLibs/new.py
new file mode 100644
index 0000000000000000000000000000000000000000..c9048e55dfa8a50bbd3bc8c5294cbca3c79c5b5b
--- /dev/null
+++ b/src/main/resources/PythonLibs/new.py
@@ -0,0 +1,19 @@
+"""Create new objects of various types.  Deprecated.
+
+This module is no longer required except for backward compatibility.
+Objects of most types can now be created by calling the type object.
+"""
+from warnings import warnpy3k
+warnpy3k("The 'new' module has been removed in Python 3.0; use the 'types' "
+            "module instead.", stacklevel=2)
+del warnpy3k
+
+from types import ClassType as classobj
+from types import FunctionType as function
+from types import InstanceType as instance
+from types import MethodType as instancemethod
+from types import ModuleType as module
+
+# XXX: Jython can't really create a code object like CPython does
+# (according to test.test_new)
+from org.python.core import PyBytecode as code
diff --git a/src/main/resources/PythonLibs/nntplib.py b/src/main/resources/PythonLibs/nntplib.py
new file mode 100644
index 0000000000000000000000000000000000000000..2dc82a90ae175f4de21504bae8b97098b073dcde
--- /dev/null
+++ b/src/main/resources/PythonLibs/nntplib.py
@@ -0,0 +1,627 @@
+"""An NNTP client class based on RFC 977: Network News Transfer Protocol.
+
+Example:
+
+>>> from nntplib import NNTP
+>>> s = NNTP('news')
+>>> resp, count, first, last, name = s.group('comp.lang.python')
+>>> print 'Group', name, 'has', count, 'articles, range', first, 'to', last
+Group comp.lang.python has 51 articles, range 5770 to 5821
+>>> resp, subs = s.xhdr('subject', first + '-' + last)
+>>> resp = s.quit()
+>>>
+
+Here 'resp' is the server response line.
+Error responses are turned into exceptions.
+
+To post an article from a file:
+>>> f = open(filename, 'r') # file containing article, including header
+>>> resp = s.post(f)
+>>>
+
+For descriptions of all methods, read the comments in the code below.
+Note that all arguments and return values representing article numbers
+are strings, not numbers, since they are rarely used for calculations.
+"""
+
+# RFC 977 by Brian Kantor and Phil Lapsley.
+# xover, xgtitle, xpath, date methods by Kevan Heydon
+
+
+# Imports
+import re
+import socket
+
+__all__ = ["NNTP","NNTPReplyError","NNTPTemporaryError",
+           "NNTPPermanentError","NNTPProtocolError","NNTPDataError",
+           "error_reply","error_temp","error_perm","error_proto",
+           "error_data",]
+
+# Exceptions raised when an error or invalid response is received
+class NNTPError(Exception):
+    """Base class for all nntplib exceptions"""
+    def __init__(self, *args):
+        Exception.__init__(self, *args)
+        try:
+            self.response = args[0]
+        except IndexError:
+            self.response = 'No response given'
+
+class NNTPReplyError(NNTPError):
+    """Unexpected [123]xx reply"""
+    pass
+
+class NNTPTemporaryError(NNTPError):
+    """4xx errors"""
+    pass
+
+class NNTPPermanentError(NNTPError):
+    """5xx errors"""
+    pass
+
+class NNTPProtocolError(NNTPError):
+    """Response does not begin with [1-5]"""
+    pass
+
+class NNTPDataError(NNTPError):
+    """Error in response data"""
+    pass
+
+# for backwards compatibility
+error_reply = NNTPReplyError
+error_temp = NNTPTemporaryError
+error_perm = NNTPPermanentError
+error_proto = NNTPProtocolError
+error_data = NNTPDataError
+
+
+
+# Standard port used by NNTP servers
+NNTP_PORT = 119
+
+
+# Response numbers that are followed by additional text (e.g. article)
+LONGRESP = ['100', '215', '220', '221', '222', '224', '230', '231', '282']
+
+
+# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
+CRLF = '\r\n'
+
+
+
+# The class itself
+class NNTP:
+    def __init__(self, host, port=NNTP_PORT, user=None, password=None,
+                 readermode=None, usenetrc=True):
+        """Initialize an instance.  Arguments:
+        - host: hostname to connect to
+        - port: port to connect to (default the standard NNTP port)
+        - user: username to authenticate with
+        - password: password to use with username
+        - readermode: if true, send 'mode reader' command after
+                      connecting.
+
+        readermode is sometimes necessary if you are connecting to an
+        NNTP server on the local machine and intend to call
+        reader-specific commands, such as `group'.  If you get
+        unexpected NNTPPermanentErrors, you might need to set
+        readermode.
+        """
+        self.host = host
+        self.port = port
+        self.sock = socket.create_connection((host, port))
+        self.file = self.sock.makefile('rb')
+        self.debugging = 0
+        self.welcome = self.getresp()
+
+        # 'mode reader' is sometimes necessary to enable 'reader' mode.
+        # However, the order in which 'mode reader' and 'authinfo' need to
+        # arrive differs between some NNTP servers. Try to send
+        # 'mode reader', and if it fails with an authorization failed
+        # error, try again after sending authinfo.
+        readermode_afterauth = 0
+        if readermode:
+            try:
+                self.welcome = self.shortcmd('mode reader')
+            except NNTPPermanentError:
+                # error 500, probably 'not implemented'
+                pass
+            except NNTPTemporaryError, e:
+                if user and e.response[:3] == '480':
+                    # Need authorization before 'mode reader'
+                    readermode_afterauth = 1
+                else:
+                    raise
+        # If no login/password was specified, try to get them from ~/.netrc
+        # Presume that if .netc has an entry, NNRP authentication is required.
+        try:
+            if usenetrc and not user:
+                import netrc
+                credentials = netrc.netrc()
+                auth = credentials.authenticators(host)
+                if auth:
+                    user = auth[0]
+                    password = auth[2]
+        except IOError:
+            pass
+        # Perform NNRP authentication if needed.
+        if user:
+            resp = self.shortcmd('authinfo user '+user)
+            if resp[:3] == '381':
+                if not password:
+                    raise NNTPReplyError(resp)
+                else:
+                    resp = self.shortcmd(
+                            'authinfo pass '+password)
+                    if resp[:3] != '281':
+                        raise NNTPPermanentError(resp)
+            if readermode_afterauth:
+                try:
+                    self.welcome = self.shortcmd('mode reader')
+                except NNTPPermanentError:
+                    # error 500, probably 'not implemented'
+                    pass
+
+
+    # Get the welcome message from the server
+    # (this is read and squirreled away by __init__()).
+    # If the response code is 200, posting is allowed;
+    # if it 201, posting is not allowed
+
+    def getwelcome(self):
+        """Get the welcome message from the server
+        (this is read and squirreled away by __init__()).
+        If the response code is 200, posting is allowed;
+        if it 201, posting is not allowed."""
+
+        if self.debugging: print '*welcome*', repr(self.welcome)
+        return self.welcome
+
+    def set_debuglevel(self, level):
+        """Set the debugging level.  Argument 'level' means:
+        0: no debugging output (default)
+        1: print commands and responses but not body text etc.
+        2: also print raw lines read and sent before stripping CR/LF"""
+
+        self.debugging = level
+    debug = set_debuglevel
+
+    def putline(self, line):
+        """Internal: send one line to the server, appending CRLF."""
+        line = line + CRLF
+        if self.debugging > 1: print '*put*', repr(line)
+        self.sock.sendall(line)
+
+    def putcmd(self, line):
+        """Internal: send one command to the server (through putline())."""
+        if self.debugging: print '*cmd*', repr(line)
+        self.putline(line)
+
+    def getline(self):
+        """Internal: return one line from the server, stripping CRLF.
+        Raise EOFError if the connection is closed."""
+        line = self.file.readline()
+        if self.debugging > 1:
+            print '*get*', repr(line)
+        if not line: raise EOFError
+        if line[-2:] == CRLF: line = line[:-2]
+        elif line[-1:] in CRLF: line = line[:-1]
+        return line
+
+    def getresp(self):
+        """Internal: get a response from the server.
+        Raise various errors if the response indicates an error."""
+        resp = self.getline()
+        if self.debugging: print '*resp*', repr(resp)
+        c = resp[:1]
+        if c == '4':
+            raise NNTPTemporaryError(resp)
+        if c == '5':
+            raise NNTPPermanentError(resp)
+        if c not in '123':
+            raise NNTPProtocolError(resp)
+        return resp
+
+    def getlongresp(self, file=None):
+        """Internal: get a response plus following text from the server.
+        Raise various errors if the response indicates an error."""
+
+        openedFile = None
+        try:
+            # If a string was passed then open a file with that name
+            if isinstance(file, str):
+                openedFile = file = open(file, "w")
+
+            resp = self.getresp()
+            if resp[:3] not in LONGRESP:
+                raise NNTPReplyError(resp)
+            list = []
+            while 1:
+                line = self.getline()
+                if line == '.':
+                    break
+                if line[:2] == '..':
+                    line = line[1:]
+                if file:
+                    file.write(line + "\n")
+                else:
+                    list.append(line)
+        finally:
+            # If this method created the file, then it must close it
+            if openedFile:
+                openedFile.close()
+
+        return resp, list
+
+    def shortcmd(self, line):
+        """Internal: send a command and get the response."""
+        self.putcmd(line)
+        return self.getresp()
+
+    def longcmd(self, line, file=None):
+        """Internal: send a command and get the response plus following text."""
+        self.putcmd(line)
+        return self.getlongresp(file)
+
+    def newgroups(self, date, time, file=None):
+        """Process a NEWGROUPS command.  Arguments:
+        - date: string 'yymmdd' indicating the date
+        - time: string 'hhmmss' indicating the time
+        Return:
+        - resp: server response if successful
+        - list: list of newsgroup names"""
+
+        return self.longcmd('NEWGROUPS ' + date + ' ' + time, file)
+
+    def newnews(self, group, date, time, file=None):
+        """Process a NEWNEWS command.  Arguments:
+        - group: group name or '*'
+        - date: string 'yymmdd' indicating the date
+        - time: string 'hhmmss' indicating the time
+        Return:
+        - resp: server response if successful
+        - list: list of message ids"""
+
+        cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time
+        return self.longcmd(cmd, file)
+
+    def list(self, file=None):
+        """Process a LIST command.  Return:
+        - resp: server response if successful
+        - list: list of (group, last, first, flag) (strings)"""
+
+        resp, list = self.longcmd('LIST', file)
+        for i in range(len(list)):
+            # Parse lines into "group last first flag"
+            list[i] = tuple(list[i].split())
+        return resp, list
+
+    def description(self, group):
+
+        """Get a description for a single group.  If more than one
+        group matches ('group' is a pattern), return the first.  If no
+        group matches, return an empty string.
+
+        This elides the response code from the server, since it can
+        only be '215' or '285' (for xgtitle) anyway.  If the response
+        code is needed, use the 'descriptions' method.
+
+        NOTE: This neither checks for a wildcard in 'group' nor does
+        it check whether the group actually exists."""
+
+        resp, lines = self.descriptions(group)
+        if len(lines) == 0:
+            return ""
+        else:
+            return lines[0][1]
+
+    def descriptions(self, group_pattern):
+        """Get descriptions for a range of groups."""
+        line_pat = re.compile("^(?P<group>[^ \t]+)[ \t]+(.*)$")
+        # Try the more std (acc. to RFC2980) LIST NEWSGROUPS first
+        resp, raw_lines = self.longcmd('LIST NEWSGROUPS ' + group_pattern)
+        if resp[:3] != "215":
+            # Now the deprecated XGTITLE.  This either raises an error
+            # or succeeds with the same output structure as LIST
+            # NEWSGROUPS.
+            resp, raw_lines = self.longcmd('XGTITLE ' + group_pattern)
+        lines = []
+        for raw_line in raw_lines:
+            match = line_pat.search(raw_line.strip())
+            if match:
+                lines.append(match.group(1, 2))
+        return resp, lines
+
+    def group(self, name):
+        """Process a GROUP command.  Argument:
+        - group: the group name
+        Returns:
+        - resp: server response if successful
+        - count: number of articles (string)
+        - first: first article number (string)
+        - last: last article number (string)
+        - name: the group name"""
+
+        resp = self.shortcmd('GROUP ' + name)
+        if resp[:3] != '211':
+            raise NNTPReplyError(resp)
+        words = resp.split()
+        count = first = last = 0
+        n = len(words)
+        if n > 1:
+            count = words[1]
+            if n > 2:
+                first = words[2]
+                if n > 3:
+                    last = words[3]
+                    if n > 4:
+                        name = words[4].lower()
+        return resp, count, first, last, name
+
+    def help(self, file=None):
+        """Process a HELP command.  Returns:
+        - resp: server response if successful
+        - list: list of strings"""
+
+        return self.longcmd('HELP',file)
+
+    def statparse(self, resp):
+        """Internal: parse the response of a STAT, NEXT or LAST command."""
+        if resp[:2] != '22':
+            raise NNTPReplyError(resp)
+        words = resp.split()
+        nr = 0
+        id = ''
+        n = len(words)
+        if n > 1:
+            nr = words[1]
+            if n > 2:
+                id = words[2]
+        return resp, nr, id
+
+    def statcmd(self, line):
+        """Internal: process a STAT, NEXT or LAST command."""
+        resp = self.shortcmd(line)
+        return self.statparse(resp)
+
+    def stat(self, id):
+        """Process a STAT command.  Argument:
+        - id: article number or message id
+        Returns:
+        - resp: server response if successful
+        - nr:   the article number
+        - id:   the message id"""
+
+        return self.statcmd('STAT ' + id)
+
+    def next(self):
+        """Process a NEXT command.  No arguments.  Return as for STAT."""
+        return self.statcmd('NEXT')
+
+    def last(self):
+        """Process a LAST command.  No arguments.  Return as for STAT."""
+        return self.statcmd('LAST')
+
+    def artcmd(self, line, file=None):
+        """Internal: process a HEAD, BODY or ARTICLE command."""
+        resp, list = self.longcmd(line, file)
+        resp, nr, id = self.statparse(resp)
+        return resp, nr, id, list
+
+    def head(self, id):
+        """Process a HEAD command.  Argument:
+        - id: article number or message id
+        Returns:
+        - resp: server response if successful
+        - nr: article number
+        - id: message id
+        - list: the lines of the article's header"""
+
+        return self.artcmd('HEAD ' + id)
+
+    def body(self, id, file=None):
+        """Process a BODY command.  Argument:
+        - id: article number or message id
+        - file: Filename string or file object to store the article in
+        Returns:
+        - resp: server response if successful
+        - nr: article number
+        - id: message id
+        - list: the lines of the article's body or an empty list
+                if file was used"""
+
+        return self.artcmd('BODY ' + id, file)
+
+    def article(self, id):
+        """Process an ARTICLE command.  Argument:
+        - id: article number or message id
+        Returns:
+        - resp: server response if successful
+        - nr: article number
+        - id: message id
+        - list: the lines of the article"""
+
+        return self.artcmd('ARTICLE ' + id)
+
+    def slave(self):
+        """Process a SLAVE command.  Returns:
+        - resp: server response if successful"""
+
+        return self.shortcmd('SLAVE')
+
+    def xhdr(self, hdr, str, file=None):
+        """Process an XHDR command (optional server extension).  Arguments:
+        - hdr: the header type (e.g. 'subject')
+        - str: an article nr, a message id, or a range nr1-nr2
+        Returns:
+        - resp: server response if successful
+        - list: list of (nr, value) strings"""
+
+        pat = re.compile('^([0-9]+) ?(.*)\n?')
+        resp, lines = self.longcmd('XHDR ' + hdr + ' ' + str, file)
+        for i in range(len(lines)):
+            line = lines[i]
+            m = pat.match(line)
+            if m:
+                lines[i] = m.group(1, 2)
+        return resp, lines
+
+    def xover(self, start, end, file=None):
+        """Process an XOVER command (optional server extension) Arguments:
+        - start: start of range
+        - end: end of range
+        Returns:
+        - resp: server response if successful
+        - list: list of (art-nr, subject, poster, date,
+                         id, references, size, lines)"""
+
+        resp, lines = self.longcmd('XOVER ' + start + '-' + end, file)
+        xover_lines = []
+        for line in lines:
+            elem = line.split("\t")
+            try:
+                xover_lines.append((elem[0],
+                                    elem[1],
+                                    elem[2],
+                                    elem[3],
+                                    elem[4],
+                                    elem[5].split(),
+                                    elem[6],
+                                    elem[7]))
+            except IndexError:
+                raise NNTPDataError(line)
+        return resp,xover_lines
+
+    def xgtitle(self, group, file=None):
+        """Process an XGTITLE command (optional server extension) Arguments:
+        - group: group name wildcard (i.e. news.*)
+        Returns:
+        - resp: server response if successful
+        - list: list of (name,title) strings"""
+
+        line_pat = re.compile("^([^ \t]+)[ \t]+(.*)$")
+        resp, raw_lines = self.longcmd('XGTITLE ' + group, file)
+        lines = []
+        for raw_line in raw_lines:
+            match = line_pat.search(raw_line.strip())
+            if match:
+                lines.append(match.group(1, 2))
+        return resp, lines
+
+    def xpath(self,id):
+        """Process an XPATH command (optional server extension) Arguments:
+        - id: Message id of article
+        Returns:
+        resp: server response if successful
+        path: directory path to article"""
+
+        resp = self.shortcmd("XPATH " + id)
+        if resp[:3] != '223':
+            raise NNTPReplyError(resp)
+        try:
+            [resp_num, path] = resp.split()
+        except ValueError:
+            raise NNTPReplyError(resp)
+        else:
+            return resp, path
+
+    def date (self):
+        """Process the DATE command. Arguments:
+        None
+        Returns:
+        resp: server response if successful
+        date: Date suitable for newnews/newgroups commands etc.
+        time: Time suitable for newnews/newgroups commands etc."""
+
+        resp = self.shortcmd("DATE")
+        if resp[:3] != '111':
+            raise NNTPReplyError(resp)
+        elem = resp.split()
+        if len(elem) != 2:
+            raise NNTPDataError(resp)
+        date = elem[1][2:8]
+        time = elem[1][-6:]
+        if len(date) != 6 or len(time) != 6:
+            raise NNTPDataError(resp)
+        return resp, date, time
+
+
+    def post(self, f):
+        """Process a POST command.  Arguments:
+        - f: file containing the article
+        Returns:
+        - resp: server response if successful"""
+
+        resp = self.shortcmd('POST')
+        # Raises error_??? if posting is not allowed
+        if resp[0] != '3':
+            raise NNTPReplyError(resp)
+        while 1:
+            line = f.readline()
+            if not line:
+                break
+            if line[-1] == '\n':
+                line = line[:-1]
+            if line[:1] == '.':
+                line = '.' + line
+            self.putline(line)
+        self.putline('.')
+        return self.getresp()
+
+    def ihave(self, id, f):
+        """Process an IHAVE command.  Arguments:
+        - id: message-id of the article
+        - f:  file containing the article
+        Returns:
+        - resp: server response if successful
+        Note that if the server refuses the article an exception is raised."""
+
+        resp = self.shortcmd('IHAVE ' + id)
+        # Raises error_??? if the server already has it
+        if resp[0] != '3':
+            raise NNTPReplyError(resp)
+        while 1:
+            line = f.readline()
+            if not line:
+                break
+            if line[-1] == '\n':
+                line = line[:-1]
+            if line[:1] == '.':
+                line = '.' + line
+            self.putline(line)
+        self.putline('.')
+        return self.getresp()
+
+    def quit(self):
+        """Process a QUIT command and close the socket.  Returns:
+        - resp: server response if successful"""
+
+        resp = self.shortcmd('QUIT')
+        self.file.close()
+        self.sock.close()
+        del self.file, self.sock
+        return resp
+
+
+# Test retrieval when run as a script.
+# Assumption: if there's a local news server, it's called 'news'.
+# Assumption: if user queries a remote news server, it's named
+# in the environment variable NNTPSERVER (used by slrn and kin)
+# and we want readermode off.
+if __name__ == '__main__':
+    import os
+    newshost = 'news' and os.environ["NNTPSERVER"]
+    if newshost.find('.') == -1:
+        mode = 'readermode'
+    else:
+        mode = None
+    s = NNTP(newshost, readermode=mode)
+    resp, count, first, last, name = s.group('comp.lang.python')
+    print resp
+    print 'Group', name, 'has', count, 'articles, range', first, 'to', last
+    resp, subs = s.xhdr('subject', first + '-' + last)
+    print resp
+    for item in subs:
+        print "%7s %s" % item
+    resp = s.quit()
+    print resp
diff --git a/src/main/resources/PythonLibs/ntpath.py b/src/main/resources/PythonLibs/ntpath.py
new file mode 100644
index 0000000000000000000000000000000000000000..762ad22e80ad4d5e034868a231eb2a50c0c1eff2
--- /dev/null
+++ b/src/main/resources/PythonLibs/ntpath.py
@@ -0,0 +1,532 @@
+# Module 'ntpath' -- common operations on WinNT/Win95 pathnames
+"""Common pathname manipulations, WindowsNT/95 version.
+
+Instead of importing this module directly, import os and refer to this
+module as os.path.
+"""
+
+import os
+import sys
+import stat
+import genericpath
+import warnings
+
+from genericpath import *
+
+__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
+           "basename","dirname","commonprefix","getsize","getmtime",
+           "getatime","getctime", "islink","exists","lexists","isdir","isfile",
+           "ismount","walk","expanduser","expandvars","normpath","abspath",
+           "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
+           "extsep","devnull","realpath","supports_unicode_filenames","relpath"]
+
+# strings representing various path-related bits and pieces
+curdir = '.'
+pardir = '..'
+extsep = '.'
+sep = '\\'
+pathsep = ';'
+altsep = '/'
+defpath = '.;C:\\bin'
+if 'ce' in sys.builtin_module_names:
+    defpath = '\\Windows'
+elif 'os2' in sys.builtin_module_names:
+    # OS/2 w/ VACPP
+    altsep = '/'
+devnull = 'nul'
+
+# Normalize the case of a pathname and map slashes to backslashes.
+# Other normalizations (such as optimizing '../' away) are not done
+# (this is done by normpath).
+
+def normcase(s):
+    """Normalize case of pathname.
+
+    Makes all characters lowercase and all slashes into backslashes."""
+    return s.replace("/", "\\").lower()
+
+
+# Return whether a path is absolute.
+# Trivial in Posix, harder on the Mac or MS-DOS.
+# For DOS it is absolute if it starts with a slash or backslash (current
+# volume), or if a pathname after the volume letter and colon / UNC resource
+# starts with a slash or backslash.
+
+def isabs(s):
+    """Test whether a path is absolute"""
+    s = splitdrive(s)[1]
+    return s != '' and s[:1] in '/\\'
+
+
+# Join two (or more) paths.
+
+def join(a, *p):
+    """Join two or more pathname components, inserting "\\" as needed.
+    If any component is an absolute path, all previous path components
+    will be discarded."""
+    path = a
+    for b in p:
+        b_wins = 0  # set to 1 iff b makes path irrelevant
+        if path == "":
+            b_wins = 1
+
+        elif isabs(b):
+            # This probably wipes out path so far.  However, it's more
+            # complicated if path begins with a drive letter:
+            #     1. join('c:', '/a') == 'c:/a'
+            #     2. join('c:/', '/a') == 'c:/a'
+            # But
+            #     3. join('c:/a', '/b') == '/b'
+            #     4. join('c:', 'd:/') = 'd:/'
+            #     5. join('c:/', 'd:/') = 'd:/'
+            if path[1:2] != ":" or b[1:2] == ":":
+                # Path doesn't start with a drive letter, or cases 4 and 5.
+                b_wins = 1
+
+            # Else path has a drive letter, and b doesn't but is absolute.
+            elif len(path) > 3 or (len(path) == 3 and
+                                   path[-1] not in "/\\"):
+                # case 3
+                b_wins = 1
+
+        if b_wins:
+            path = b
+        else:
+            # Join, and ensure there's a separator.
+            assert len(path) > 0
+            if path[-1] in "/\\":
+                if b and b[0] in "/\\":
+                    path += b[1:]
+                else:
+                    path += b
+            elif path[-1] == ":":
+                path += b
+            elif b:
+                if b[0] in "/\\":
+                    path += b
+                else:
+                    path += "\\" + b
+            else:
+                # path is not empty and does not end with a backslash,
+                # but b is empty; since, e.g., split('a/') produces
+                # ('a', ''), it's best if join() adds a backslash in
+                # this case.
+                path += '\\'
+
+    return path
+
+
+# Split a path in a drive specification (a drive letter followed by a
+# colon) and the path specification.
+# It is always true that drivespec + pathspec == p
+def splitdrive(p):
+    """Split a pathname into drive and path specifiers. Returns a 2-tuple
+"(drive,path)";  either part may be empty"""
+    if p[1:2] == ':':
+        return p[0:2], p[2:]
+    return '', p
+
+
+# Parse UNC paths
+def splitunc(p):
+    """Split a pathname into UNC mount point and relative path specifiers.
+
+    Return a 2-tuple (unc, rest); either part may be empty.
+    If unc is not empty, it has the form '//host/mount' (or similar
+    using backslashes).  unc+rest is always the input path.
+    Paths containing drive letters never have an UNC part.
+    """
+    if p[1:2] == ':':
+        return '', p # Drive letter present
+    firstTwo = p[0:2]
+    if firstTwo == '//' or firstTwo == '\\\\':
+        # is a UNC path:
+        # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter
+        # \\machine\mountpoint\directories...
+        #           directory ^^^^^^^^^^^^^^^
+        normp = normcase(p)
+        index = normp.find('\\', 2)
+        if index == -1:
+            ##raise RuntimeError, 'illegal UNC path: "' + p + '"'
+            return ("", p)
+        index = normp.find('\\', index + 1)
+        if index == -1:
+            index = len(p)
+        return p[:index], p[index:]
+    return '', p
+
+
+# Split a path in head (everything up to the last '/') and tail (the
+# rest).  After the trailing '/' is stripped, the invariant
+# join(head, tail) == p holds.
+# The resulting head won't end in '/' unless it is the root.
+
+def split(p):
+    """Split a pathname.
+
+    Return tuple (head, tail) where tail is everything after the final slash.
+    Either part may be empty."""
+
+    d, p = splitdrive(p)
+    # set i to index beyond p's last slash
+    i = len(p)
+    while i and p[i-1] not in '/\\':
+        i = i - 1
+    head, tail = p[:i], p[i:]  # now tail has no slashes
+    # remove trailing slashes from head, unless it's all slashes
+    head2 = head
+    while head2 and head2[-1] in '/\\':
+        head2 = head2[:-1]
+    head = head2 or head
+    return d + head, tail
+
+
+# Split a path in root and extension.
+# The extension is everything starting at the last dot in the last
+# pathname component; the root is everything before that.
+# It is always true that root + ext == p.
+
+def splitext(p):
+    return genericpath._splitext(p, sep, altsep, extsep)
+splitext.__doc__ = genericpath._splitext.__doc__
+
+
+# Return the tail (basename) part of a path.
+
+def basename(p):
+    """Returns the final component of a pathname"""
+    return split(p)[1]
+
+
+# Return the head (dirname) part of a path.
+
+def dirname(p):
+    """Returns the directory component of a pathname"""
+    return split(p)[0]
+
+# Is a path a symbolic link?
+# This will always return false on systems where posix.lstat doesn't exist.
+
+def islink(path):
+    """Test for symbolic link.
+    On WindowsNT/95 and OS/2 always returns false
+    """
+    return False
+
+# alias exists to lexists
+lexists = exists
+
+# Is a path a mount point?  Either a root (with or without drive letter)
+# or an UNC path with at most a / or \ after the mount point.
+
+def ismount(path):
+    """Test whether a path is a mount point (defined as root of drive)"""
+    unc, rest = splitunc(path)
+    if unc:
+        return rest in ("", "/", "\\")
+    p = splitdrive(path)[1]
+    return len(p) == 1 and p[0] in '/\\'
+
+
+# Directory tree walk.
+# For each directory under top (including top itself, but excluding
+# '.' and '..'), func(arg, dirname, filenames) is called, where
+# dirname is the name of the directory and filenames is the list
+# of files (and subdirectories etc.) in the directory.
+# The func may modify the filenames list, to implement a filter,
+# or to impose a different order of visiting.
+
+def walk(top, func, arg):
+    """Directory tree walk with callback function.
+
+    For each directory in the directory tree rooted at top (including top
+    itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
+    dirname is the name of the directory, and fnames a list of the names of
+    the files and subdirectories in dirname (excluding '.' and '..').  func
+    may modify the fnames list in-place (e.g. via del or slice assignment),
+    and walk will only recurse into the subdirectories whose names remain in
+    fnames; this can be used to implement a filter, or to impose a specific
+    order of visiting.  No semantics are defined for, or required of, arg,
+    beyond that arg is always passed to func.  It can be used, e.g., to pass
+    a filename pattern, or a mutable object designed to accumulate
+    statistics.  Passing None for arg is common."""
+    warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.",
+                      stacklevel=2)
+    try:
+        names = os.listdir(top)
+    except os.error:
+        return
+    func(arg, top, names)
+    for name in names:
+        name = join(top, name)
+        if isdir(name):
+            walk(name, func, arg)
+
+
+# Expand paths beginning with '~' or '~user'.
+# '~' means $HOME; '~user' means that user's home directory.
+# If the path doesn't begin with '~', or if the user or $HOME is unknown,
+# the path is returned unchanged (leaving error reporting to whatever
+# function is called with the expanded path as argument).
+# See also module 'glob' for expansion of *, ? and [...] in pathnames.
+# (A function should also be defined to do full *sh-style environment
+# variable expansion.)
+
+def expanduser(path):
+    """Expand ~ and ~user constructs.
+
+    If user or $HOME is unknown, do nothing."""
+    if path[:1] != '~':
+        return path
+    i, n = 1, len(path)
+    while i < n and path[i] not in '/\\':
+        i = i + 1
+
+    if 'HOME' in os.environ:
+        userhome = os.environ['HOME']
+    elif 'USERPROFILE' in os.environ:
+        userhome = os.environ['USERPROFILE']
+    elif not 'HOMEPATH' in os.environ:
+        return path
+    else:
+        try:
+            drive = os.environ['HOMEDRIVE']
+        except KeyError:
+            drive = ''
+        userhome = join(drive, os.environ['HOMEPATH'])
+
+    if i != 1: #~user
+        userhome = join(dirname(userhome), path[1:i])
+
+    return userhome + path[i:]
+
+
+# Expand paths containing shell variable substitutions.
+# The following rules apply:
+#       - no expansion within single quotes
+#       - '$$' is translated into '$'
+#       - '%%' is translated into '%' if '%%' are not seen in %var1%%var2%
+#       - ${varname} is accepted.
+#       - $varname is accepted.
+#       - %varname% is accepted.
+#       - varnames can be made out of letters, digits and the characters '_-'
+#         (though is not verifed in the ${varname} and %varname% cases)
+# XXX With COMMAND.COM you can use any characters in a variable name,
+# XXX except '^|<>='.
+
+def expandvars(path):
+    """Expand shell variables of the forms $var, ${var} and %var%.
+
+    Unknown variables are left unchanged."""
+    if '$' not in path and '%' not in path:
+        return path
+    import string
+    varchars = string.ascii_letters + string.digits + '_-'
+    res = ''
+    index = 0
+    pathlen = len(path)
+    while index < pathlen:
+        c = path[index]
+        if c == '\'':   # no expansion within single quotes
+            path = path[index + 1:]
+            pathlen = len(path)
+            try:
+                index = path.index('\'')
+                res = res + '\'' + path[:index + 1]
+            except ValueError:
+                res = res + path
+                index = pathlen - 1
+        elif c == '%':  # variable or '%'
+            if path[index + 1:index + 2] == '%':
+                res = res + c
+                index = index + 1
+            else:
+                path = path[index+1:]
+                pathlen = len(path)
+                try:
+                    index = path.index('%')
+                except ValueError:
+                    res = res + '%' + path
+                    index = pathlen - 1
+                else:
+                    var = path[:index]
+                    if var in os.environ:
+                        res = res + os.environ[var]
+                    else:
+                        res = res + '%' + var + '%'
+        elif c == '$':  # variable or '$$'
+            if path[index + 1:index + 2] == '$':
+                res = res + c
+                index = index + 1
+            elif path[index + 1:index + 2] == '{':
+                path = path[index+2:]
+                pathlen = len(path)
+                try:
+                    index = path.index('}')
+                    var = path[:index]
+                    if var in os.environ:
+                        res = res + os.environ[var]
+                    else:
+                        res = res + '${' + var + '}'
+                except ValueError:
+                    res = res + '${' + path
+                    index = pathlen - 1
+            else:
+                var = ''
+                index = index + 1
+                c = path[index:index + 1]
+                while c != '' and c in varchars:
+                    var = var + c
+                    index = index + 1
+                    c = path[index:index + 1]
+                if var in os.environ:
+                    res = res + os.environ[var]
+                else:
+                    res = res + '$' + var
+                if c != '':
+                    index = index - 1
+        else:
+            res = res + c
+        index = index + 1
+    return res
+
+
+# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
+# Previously, this function also truncated pathnames to 8+3 format,
+# but as this module is called "ntpath", that's obviously wrong!
+
+def normpath(path):
+    """Normalize path, eliminating double slashes, etc."""
+    # Preserve unicode (if path is unicode)
+    backslash, dot = (u'\\', u'.') if isinstance(path, unicode) else ('\\', '.')
+    if path.startswith(('\\\\.\\', '\\\\?\\')):
+        # in the case of paths with these prefixes:
+        # \\.\ -> device names
+        # \\?\ -> literal paths
+        # do not do any normalization, but return the path unchanged
+        return path
+    path = path.replace("/", "\\")
+    prefix, path = splitdrive(path)
+    # We need to be careful here. If the prefix is empty, and the path starts
+    # with a backslash, it could either be an absolute path on the current
+    # drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It
+    # is therefore imperative NOT to collapse multiple backslashes blindly in
+    # that case.
+    # The code below preserves multiple backslashes when there is no drive
+    # letter. This means that the invalid filename \\\a\b is preserved
+    # unchanged, where a\\\b is normalised to a\b. It's not clear that there
+    # is any better behaviour for such edge cases.
+    if prefix == '':
+        # No drive letter - preserve initial backslashes
+        while path[:1] == "\\":
+            prefix = prefix + backslash
+            path = path[1:]
+    else:
+        # We have a drive letter - collapse initial backslashes
+        if path.startswith("\\"):
+            prefix = prefix + backslash
+            path = path.lstrip("\\")
+    comps = path.split("\\")
+    i = 0
+    while i < len(comps):
+        if comps[i] in ('.', ''):
+            del comps[i]
+        elif comps[i] == '..':
+            if i > 0 and comps[i-1] != '..':
+                del comps[i-1:i+1]
+                i -= 1
+            elif i == 0 and prefix.endswith("\\"):
+                del comps[i]
+            else:
+                i += 1
+        else:
+            i += 1
+    # If the path is now empty, substitute '.'
+    if not prefix and not comps:
+        comps.append(dot)
+    return prefix + backslash.join(comps)
+
+
+# Return an absolute path.
+try:
+    from nt import _getfullpathname
+
+except ImportError: # not running on Windows - mock up something sensible
+    import java.io.File
+    from org.python.core.Py import newString
+
+    def abspath(path):
+        """Return the absolute version of a path."""
+        if not isabs(path):
+            if isinstance(path, unicode):
+                cwd = os.getcwdu()
+            else:
+                cwd = os.getcwd()
+            path = join(cwd, path)
+        if not splitunc(path)[0] and not splitdrive(path)[0]:
+            # cwd lacks a UNC mount point, so it should have a drive
+            # letter (but lacks one): determine it
+            canon_path = newString(java.io.File(path).getCanonicalPath())
+            drive = splitdrive(canon_path)[0]
+            path = join(drive, path)
+        return normpath(path)
+
+else:  # use native Windows method on Windows
+    def abspath(path):
+        """Return the absolute version of a path."""
+
+        if path: # Empty path must return current working directory.
+            try:
+                path = _getfullpathname(path)
+            except WindowsError:
+                pass # Bad path - return unchanged.
+        elif isinstance(path, unicode):
+            path = os.getcwdu()
+        else:
+            path = os.getcwd()
+        return normpath(path)
+
+# realpath is a no-op on systems without islink support
+realpath = abspath
+# Win9x family and earlier have no Unicode filename support.
+supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
+                              sys.getwindowsversion()[3] >= 2)
+
+def _abspath_split(path):
+    abs = abspath(normpath(path))
+    prefix, rest = splitunc(abs)
+    is_unc = bool(prefix)
+    if not is_unc:
+        prefix, rest = splitdrive(abs)
+    return is_unc, prefix, [x for x in rest.split(sep) if x]
+
+def relpath(path, start=curdir):
+    """Return a relative version of a path"""
+
+    if not path:
+        raise ValueError("no path specified")
+
+    start_is_unc, start_prefix, start_list = _abspath_split(start)
+    path_is_unc, path_prefix, path_list = _abspath_split(path)
+
+    if path_is_unc ^ start_is_unc:
+        raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+                                                            % (path, start))
+    if path_prefix.lower() != start_prefix.lower():
+        if path_is_unc:
+            raise ValueError("path is on UNC root %s, start on UNC root %s"
+                                                % (path_prefix, start_prefix))
+        else:
+            raise ValueError("path is on drive %s, start on drive %s"
+                                                % (path_prefix, start_prefix))
+    # Work out how much of the filepath is shared by start and path.
+    i = 0
+    for e1, e2 in zip(start_list, path_list):
+        if e1.lower() != e2.lower():
+            break
+        i += 1
+
+    rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
+    if not rel_list:
+        return curdir
+    return join(*rel_list)
diff --git a/src/main/resources/PythonLibs/nturl2path.py b/src/main/resources/PythonLibs/nturl2path.py
new file mode 100644
index 0000000000000000000000000000000000000000..10ea27280789f5a6bcfc7a2fb6c94ab6b9df5645
--- /dev/null
+++ b/src/main/resources/PythonLibs/nturl2path.py
@@ -0,0 +1,66 @@
+"""Convert a NT pathname to a file URL and vice versa."""
+
+def url2pathname(url):
+    """OS-specific conversion from a relative URL of the 'file' scheme
+    to a file system path; not recommended for general use."""
+    # e.g.
+    # ///C|/foo/bar/spam.foo
+    # becomes
+    # C:\foo\bar\spam.foo
+    import string, urllib
+    # Windows itself uses ":" even in URLs.
+    url = url.replace(':', '|')
+    if not '|' in url:
+        # No drive specifier, just convert slashes
+        if url[:4] == '////':
+            # path is something like ////host/path/on/remote/host
+            # convert this to \\host\path\on\remote\host
+            # (notice halving of slashes at the start of the path)
+            url = url[2:]
+        components = url.split('/')
+        # make sure not to convert quoted slashes :-)
+        return urllib.unquote('\\'.join(components))
+    comp = url.split('|')
+    if len(comp) != 2 or comp[0][-1] not in string.ascii_letters:
+        error = 'Bad URL: ' + url
+        raise IOError, error
+    drive = comp[0][-1].upper()
+    path = drive + ':'
+    components = comp[1].split('/')
+    for comp in components:
+        if comp:
+            path = path + '\\' + urllib.unquote(comp)
+    # Issue #11474: url like '/C|/' should convert into 'C:\\'
+    if path.endswith(':') and url.endswith('/'):
+        path += '\\'
+    return path
+
+def pathname2url(p):
+    """OS-specific conversion from a file system path to a relative URL
+    of the 'file' scheme; not recommended for general use."""
+    # e.g.
+    # C:\foo\bar\spam.foo
+    # becomes
+    # ///C|/foo/bar/spam.foo
+    import urllib
+    if not ':' in p:
+        # No drive specifier, just convert slashes and quote the name
+        if p[:2] == '\\\\':
+        # path is something like \\host\path\on\remote\host
+        # convert this to ////host/path/on/remote/host
+        # (notice doubling of slashes at the start of the path)
+            p = '\\\\' + p
+        components = p.split('\\')
+        return urllib.quote('/'.join(components))
+    comp = p.split(':')
+    if len(comp) != 2 or len(comp[0]) > 1:
+        error = 'Bad path: ' + p
+        raise IOError, error
+
+    drive = urllib.quote(comp[0].upper())
+    components = comp[1].split('\\')
+    path = '///' + drive + ':'
+    for comp in components:
+        if comp:
+            path = path + '/' + urllib.quote(comp)
+    return path
diff --git a/src/main/resources/PythonLibs/numbers.py b/src/main/resources/PythonLibs/numbers.py
new file mode 100644
index 0000000000000000000000000000000000000000..bdc6dd65213b967b88537d386961bb9389de6902
--- /dev/null
+++ b/src/main/resources/PythonLibs/numbers.py
@@ -0,0 +1,391 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Abstract Base Classes (ABCs) for numbers, according to PEP 3141.
+
+TODO: Fill out more detailed documentation on the operators."""
+
+from __future__ import division
+from abc import ABCMeta, abstractmethod, abstractproperty
+
+__all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
+
+class Number(object):
+    """All numbers inherit from this class.
+
+    If you just want to check if an argument x is a number, without
+    caring what kind, use isinstance(x, Number).
+    """
+    __metaclass__ = ABCMeta
+    __slots__ = ()
+
+    # Concrete numeric types must provide their own hash implementation
+    __hash__ = None
+
+
+## Notes on Decimal
+## ----------------
+## Decimal has all of the methods specified by the Real abc, but it should
+## not be registered as a Real because decimals do not interoperate with
+## binary floats (i.e.  Decimal('3.14') + 2.71828 is undefined).  But,
+## abstract reals are expected to interoperate (i.e. R1 + R2 should be
+## expected to work if R1 and R2 are both Reals).
+
+class Complex(Number):
+    """Complex defines the operations that work on the builtin complex type.
+
+    In short, those are: a conversion to complex, .real, .imag, +, -,
+    *, /, abs(), .conjugate, ==, and !=.
+
+    If it is given heterogenous arguments, and doesn't have special
+    knowledge about them, it should fall back to the builtin complex
+    type as described below.
+    """
+
+    __slots__ = ()
+
+    @abstractmethod
+    def __complex__(self):
+        """Return a builtin complex instance. Called for complex(self)."""
+
+    # Will be __bool__ in 3.0.
+    def __nonzero__(self):
+        """True if self != 0. Called for bool(self)."""
+        return self != 0
+
+    @abstractproperty
+    def real(self):
+        """Retrieve the real component of this number.
+
+        This should subclass Real.
+        """
+        raise NotImplementedError
+
+    @abstractproperty
+    def imag(self):
+        """Retrieve the imaginary component of this number.
+
+        This should subclass Real.
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def __add__(self, other):
+        """self + other"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __radd__(self, other):
+        """other + self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __neg__(self):
+        """-self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __pos__(self):
+        """+self"""
+        raise NotImplementedError
+
+    def __sub__(self, other):
+        """self - other"""
+        return self + -other
+
+    def __rsub__(self, other):
+        """other - self"""
+        return -self + other
+
+    @abstractmethod
+    def __mul__(self, other):
+        """self * other"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rmul__(self, other):
+        """other * self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __div__(self, other):
+        """self / other without __future__ division
+
+        May promote to float.
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rdiv__(self, other):
+        """other / self without __future__ division"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __truediv__(self, other):
+        """self / other with __future__ division.
+
+        Should promote to float when necessary.
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rtruediv__(self, other):
+        """other / self with __future__ division"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __pow__(self, exponent):
+        """self**exponent; should promote to float or complex when necessary."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rpow__(self, base):
+        """base ** self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __abs__(self):
+        """Returns the Real distance from 0. Called for abs(self)."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def conjugate(self):
+        """(x+y*i).conjugate() returns (x-y*i)."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __eq__(self, other):
+        """self == other"""
+        raise NotImplementedError
+
+    def __ne__(self, other):
+        """self != other"""
+        # The default __ne__ doesn't negate __eq__ until 3.0.
+        return not (self == other)
+
+Complex.register(complex)
+
+
+class Real(Complex):
+    """To Complex, Real adds the operations that work on real numbers.
+
+    In short, those are: a conversion to float, trunc(), divmod,
+    %, <, <=, >, and >=.
+
+    Real also provides defaults for the derived operations.
+    """
+
+    __slots__ = ()
+
+    @abstractmethod
+    def __float__(self):
+        """Any Real can be converted to a native float object.
+
+        Called for float(self)."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __trunc__(self):
+        """trunc(self): Truncates self to an Integral.
+
+        Returns an Integral i such that:
+          * i>0 iff self>0;
+          * abs(i) <= abs(self);
+          * for any Integral j satisfying the first two conditions,
+            abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
+        i.e. "truncate towards 0".
+        """
+        raise NotImplementedError
+
+    def __divmod__(self, other):
+        """divmod(self, other): The pair (self // other, self % other).
+
+        Sometimes this can be computed faster than the pair of
+        operations.
+        """
+        return (self // other, self % other)
+
+    def __rdivmod__(self, other):
+        """divmod(other, self): The pair (self // other, self % other).
+
+        Sometimes this can be computed faster than the pair of
+        operations.
+        """
+        return (other // self, other % self)
+
+    @abstractmethod
+    def __floordiv__(self, other):
+        """self // other: The floor() of self/other."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rfloordiv__(self, other):
+        """other // self: The floor() of other/self."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __mod__(self, other):
+        """self % other"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rmod__(self, other):
+        """other % self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __lt__(self, other):
+        """self < other
+
+        < on Reals defines a total ordering, except perhaps for NaN."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __le__(self, other):
+        """self <= other"""
+        raise NotImplementedError
+
+    # Concrete implementations of Complex abstract methods.
+    def __complex__(self):
+        """complex(self) == complex(float(self), 0)"""
+        return complex(float(self))
+
+    @property
+    def real(self):
+        """Real numbers are their real component."""
+        return +self
+
+    @property
+    def imag(self):
+        """Real numbers have no imaginary component."""
+        return 0
+
+    def conjugate(self):
+        """Conjugate is a no-op for Reals."""
+        return +self
+
+Real.register(float)
+
+
+class Rational(Real):
+    """.numerator and .denominator should be in lowest terms."""
+
+    __slots__ = ()
+
+    @abstractproperty
+    def numerator(self):
+        raise NotImplementedError
+
+    @abstractproperty
+    def denominator(self):
+        raise NotImplementedError
+
+    # Concrete implementation of Real's conversion to float.
+    def __float__(self):
+        """float(self) = self.numerator / self.denominator
+
+        It's important that this conversion use the integer's "true"
+        division rather than casting one side to float before dividing
+        so that ratios of huge integers convert without overflowing.
+
+        """
+        return self.numerator / self.denominator
+
+
+class Integral(Rational):
+    """Integral adds a conversion to long and the bit-string operations."""
+
+    __slots__ = ()
+
+    @abstractmethod
+    def __long__(self):
+        """long(self)"""
+        raise NotImplementedError
+
+    def __index__(self):
+        """Called whenever an index is needed, such as in slicing"""
+        return long(self)
+
+    @abstractmethod
+    def __pow__(self, exponent, modulus=None):
+        """self ** exponent % modulus, but maybe faster.
+
+        Accept the modulus argument if you want to support the
+        3-argument version of pow(). Raise a TypeError if exponent < 0
+        or any argument isn't Integral. Otherwise, just implement the
+        2-argument version described in Complex.
+        """
+        raise NotImplementedError
+
+    @abstractmethod
+    def __lshift__(self, other):
+        """self << other"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rlshift__(self, other):
+        """other << self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rshift__(self, other):
+        """self >> other"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rrshift__(self, other):
+        """other >> self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __and__(self, other):
+        """self & other"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rand__(self, other):
+        """other & self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __xor__(self, other):
+        """self ^ other"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __rxor__(self, other):
+        """other ^ self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __or__(self, other):
+        """self | other"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __ror__(self, other):
+        """other | self"""
+        raise NotImplementedError
+
+    @abstractmethod
+    def __invert__(self):
+        """~self"""
+        raise NotImplementedError
+
+    # Concrete implementations of Rational and Real abstract methods.
+    def __float__(self):
+        """float(self) == float(long(self))"""
+        return float(long(self))
+
+    @property
+    def numerator(self):
+        """Integers are their own numerators."""
+        return +self
+
+    @property
+    def denominator(self):
+        """Integers have a denominator of 1."""
+        return 1
+
+Integral.register(int)
+Integral.register(long)
diff --git a/src/main/resources/PythonLibs/opcode.py b/src/main/resources/PythonLibs/opcode.py
new file mode 100644
index 0000000000000000000000000000000000000000..e403365b6a26818d22eab123f840b88a3a4e1fde
--- /dev/null
+++ b/src/main/resources/PythonLibs/opcode.py
@@ -0,0 +1,192 @@
+
+"""
+opcode module - potentially shared between dis and other modules which
+operate on bytecodes (e.g. peephole optimizers).
+"""
+
+__all__ = ["cmp_op", "hasconst", "hasname", "hasjrel", "hasjabs",
+           "haslocal", "hascompare", "hasfree", "opname", "opmap",
+           "HAVE_ARGUMENT", "EXTENDED_ARG"]
+
+cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
+        'is not', 'exception match', 'BAD')
+
+hasconst = []
+hasname = []
+hasjrel = []
+hasjabs = []
+haslocal = []
+hascompare = []
+hasfree = []
+
+opmap = {}
+opname = [''] * 256
+for op in range(256): opname[op] = '<%r>' % (op,)
+del op
+
+def def_op(name, op):
+    opname[op] = name
+    opmap[name] = op
+
+def name_op(name, op):
+    def_op(name, op)
+    hasname.append(op)
+
+def jrel_op(name, op):
+    def_op(name, op)
+    hasjrel.append(op)
+
+def jabs_op(name, op):
+    def_op(name, op)
+    hasjabs.append(op)
+
+# Instruction opcodes for compiled code
+# Blank lines correspond to available opcodes
+
+def_op('STOP_CODE', 0)
+def_op('POP_TOP', 1)
+def_op('ROT_TWO', 2)
+def_op('ROT_THREE', 3)
+def_op('DUP_TOP', 4)
+def_op('ROT_FOUR', 5)
+
+def_op('NOP', 9)
+def_op('UNARY_POSITIVE', 10)
+def_op('UNARY_NEGATIVE', 11)
+def_op('UNARY_NOT', 12)
+def_op('UNARY_CONVERT', 13)
+
+def_op('UNARY_INVERT', 15)
+
+def_op('BINARY_POWER', 19)
+def_op('BINARY_MULTIPLY', 20)
+def_op('BINARY_DIVIDE', 21)
+def_op('BINARY_MODULO', 22)
+def_op('BINARY_ADD', 23)
+def_op('BINARY_SUBTRACT', 24)
+def_op('BINARY_SUBSCR', 25)
+def_op('BINARY_FLOOR_DIVIDE', 26)
+def_op('BINARY_TRUE_DIVIDE', 27)
+def_op('INPLACE_FLOOR_DIVIDE', 28)
+def_op('INPLACE_TRUE_DIVIDE', 29)
+def_op('SLICE+0', 30)
+def_op('SLICE+1', 31)
+def_op('SLICE+2', 32)
+def_op('SLICE+3', 33)
+
+def_op('STORE_SLICE+0', 40)
+def_op('STORE_SLICE+1', 41)
+def_op('STORE_SLICE+2', 42)
+def_op('STORE_SLICE+3', 43)
+
+def_op('DELETE_SLICE+0', 50)
+def_op('DELETE_SLICE+1', 51)
+def_op('DELETE_SLICE+2', 52)
+def_op('DELETE_SLICE+3', 53)
+
+def_op('STORE_MAP', 54)
+def_op('INPLACE_ADD', 55)
+def_op('INPLACE_SUBTRACT', 56)
+def_op('INPLACE_MULTIPLY', 57)
+def_op('INPLACE_DIVIDE', 58)
+def_op('INPLACE_MODULO', 59)
+def_op('STORE_SUBSCR', 60)
+def_op('DELETE_SUBSCR', 61)
+def_op('BINARY_LSHIFT', 62)
+def_op('BINARY_RSHIFT', 63)
+def_op('BINARY_AND', 64)
+def_op('BINARY_XOR', 65)
+def_op('BINARY_OR', 66)
+def_op('INPLACE_POWER', 67)
+def_op('GET_ITER', 68)
+
+def_op('PRINT_EXPR', 70)
+def_op('PRINT_ITEM', 71)
+def_op('PRINT_NEWLINE', 72)
+def_op('PRINT_ITEM_TO', 73)
+def_op('PRINT_NEWLINE_TO', 74)
+def_op('INPLACE_LSHIFT', 75)
+def_op('INPLACE_RSHIFT', 76)
+def_op('INPLACE_AND', 77)
+def_op('INPLACE_XOR', 78)
+def_op('INPLACE_OR', 79)
+def_op('BREAK_LOOP', 80)
+def_op('WITH_CLEANUP', 81)
+def_op('LOAD_LOCALS', 82)
+def_op('RETURN_VALUE', 83)
+def_op('IMPORT_STAR', 84)
+def_op('EXEC_STMT', 85)
+def_op('YIELD_VALUE', 86)
+def_op('POP_BLOCK', 87)
+def_op('END_FINALLY', 88)
+def_op('BUILD_CLASS', 89)
+
+HAVE_ARGUMENT = 90              # Opcodes from here have an argument:
+
+name_op('STORE_NAME', 90)       # Index in name list
+name_op('DELETE_NAME', 91)      # ""
+def_op('UNPACK_SEQUENCE', 92)   # Number of tuple items
+jrel_op('FOR_ITER', 93)
+def_op('LIST_APPEND', 94)
+name_op('STORE_ATTR', 95)       # Index in name list
+name_op('DELETE_ATTR', 96)      # ""
+name_op('STORE_GLOBAL', 97)     # ""
+name_op('DELETE_GLOBAL', 98)    # ""
+def_op('DUP_TOPX', 99)          # number of items to duplicate
+def_op('LOAD_CONST', 100)       # Index in const list
+hasconst.append(100)
+name_op('LOAD_NAME', 101)       # Index in name list
+def_op('BUILD_TUPLE', 102)      # Number of tuple items
+def_op('BUILD_LIST', 103)       # Number of list items
+def_op('BUILD_SET', 104)        # Number of set items
+def_op('BUILD_MAP', 105)        # Number of dict entries (upto 255)
+name_op('LOAD_ATTR', 106)       # Index in name list
+def_op('COMPARE_OP', 107)       # Comparison operator
+hascompare.append(107)
+name_op('IMPORT_NAME', 108)     # Index in name list
+name_op('IMPORT_FROM', 109)     # Index in name list
+jrel_op('JUMP_FORWARD', 110)    # Number of bytes to skip
+jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
+jabs_op('JUMP_IF_TRUE_OR_POP', 112)  # ""
+jabs_op('JUMP_ABSOLUTE', 113)        # ""
+jabs_op('POP_JUMP_IF_FALSE', 114)    # ""
+jabs_op('POP_JUMP_IF_TRUE', 115)     # ""
+
+name_op('LOAD_GLOBAL', 116)     # Index in name list
+
+jabs_op('CONTINUE_LOOP', 119)   # Target address
+jrel_op('SETUP_LOOP', 120)      # Distance to target address
+jrel_op('SETUP_EXCEPT', 121)    # ""
+jrel_op('SETUP_FINALLY', 122)   # ""
+
+def_op('LOAD_FAST', 124)        # Local variable number
+haslocal.append(124)
+def_op('STORE_FAST', 125)       # Local variable number
+haslocal.append(125)
+def_op('DELETE_FAST', 126)      # Local variable number
+haslocal.append(126)
+
+def_op('RAISE_VARARGS', 130)    # Number of raise arguments (1, 2, or 3)
+def_op('CALL_FUNCTION', 131)    # #args + (#kwargs << 8)
+def_op('MAKE_FUNCTION', 132)    # Number of args with default values
+def_op('BUILD_SLICE', 133)      # Number of items
+def_op('MAKE_CLOSURE', 134)
+def_op('LOAD_CLOSURE', 135)
+hasfree.append(135)
+def_op('LOAD_DEREF', 136)
+hasfree.append(136)
+def_op('STORE_DEREF', 137)
+hasfree.append(137)
+
+def_op('CALL_FUNCTION_VAR', 140)     # #args + (#kwargs << 8)
+def_op('CALL_FUNCTION_KW', 141)      # #args + (#kwargs << 8)
+def_op('CALL_FUNCTION_VAR_KW', 142)  # #args + (#kwargs << 8)
+
+jrel_op('SETUP_WITH', 143)
+
+def_op('EXTENDED_ARG', 145)
+EXTENDED_ARG = 145
+def_op('SET_ADD', 146)
+def_op('MAP_ADD', 147)
+
+del def_op, name_op, jrel_op, jabs_op
diff --git a/src/main/resources/PythonLibs/optparse.py b/src/main/resources/PythonLibs/optparse.py
new file mode 100644
index 0000000000000000000000000000000000000000..731a2bb5edf8541dd1b8a7bc1eae7ae3e7c945eb
--- /dev/null
+++ b/src/main/resources/PythonLibs/optparse.py
@@ -0,0 +1,1703 @@
+"""A powerful, extensible, and easy-to-use option parser.
+
+By Greg Ward <gward@python.net>
+
+Originally distributed as Optik.
+
+For support, use the optik-users@lists.sourceforge.net mailing list
+(http://lists.sourceforge.net/lists/listinfo/optik-users).
+
+Simple usage example:
+
+   from optparse import OptionParser
+
+   parser = OptionParser()
+   parser.add_option("-f", "--file", dest="filename",
+                     help="write report to FILE", metavar="FILE")
+   parser.add_option("-q", "--quiet",
+                     action="store_false", dest="verbose", default=True,
+                     help="don't print status messages to stdout")
+
+   (options, args) = parser.parse_args()
+"""
+
+__version__ = "1.5.3"
+
+__all__ = ['Option',
+           'make_option',
+           'SUPPRESS_HELP',
+           'SUPPRESS_USAGE',
+           'Values',
+           'OptionContainer',
+           'OptionGroup',
+           'OptionParser',
+           'HelpFormatter',
+           'IndentedHelpFormatter',
+           'TitledHelpFormatter',
+           'OptParseError',
+           'OptionError',
+           'OptionConflictError',
+           'OptionValueError',
+           'BadOptionError']
+
+__copyright__ = """
+Copyright (c) 2001-2006 Gregory P. Ward.  All rights reserved.
+Copyright (c) 2002-2006 Python Software Foundation.  All rights reserved.
+
+Redistribution and use in source and binary forms, 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.
+
+  * Neither the name of the author nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+THIS SOFTWARE 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 AUTHOR 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
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""
+
+import sys, os
+import types
+import textwrap
+
+def _repr(self):
+    return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self)
+
+
+# This file was generated from:
+#   Id: option_parser.py 527 2006-07-23 15:21:30Z greg
+#   Id: option.py 522 2006-06-11 16:22:03Z gward
+#   Id: help.py 527 2006-07-23 15:21:30Z greg
+#   Id: errors.py 509 2006-04-20 00:58:24Z gward
+
+try:
+    from gettext import gettext
+except ImportError:
+    def gettext(message):
+        return message
+_ = gettext
+
+
+class OptParseError (Exception):
+    def __init__(self, msg):
+        self.msg = msg
+
+    def __str__(self):
+        return self.msg
+
+
+class OptionError (OptParseError):
+    """
+    Raised if an Option instance is created with invalid or
+    inconsistent arguments.
+    """
+
+    def __init__(self, msg, option):
+        self.msg = msg
+        self.option_id = str(option)
+
+    def __str__(self):
+        if self.option_id:
+            return "option %s: %s" % (self.option_id, self.msg)
+        else:
+            return self.msg
+
+class OptionConflictError (OptionError):
+    """
+    Raised if conflicting options are added to an OptionParser.
+    """
+
+class OptionValueError (OptParseError):
+    """
+    Raised if an invalid option value is encountered on the command
+    line.
+    """
+
+class BadOptionError (OptParseError):
+    """
+    Raised if an invalid option is seen on the command line.
+    """
+    def __init__(self, opt_str):
+        self.opt_str = opt_str
+
+    def __str__(self):
+        return _("no such option: %s") % self.opt_str
+
+class AmbiguousOptionError (BadOptionError):
+    """
+    Raised if an ambiguous option is seen on the command line.
+    """
+    def __init__(self, opt_str, possibilities):
+        BadOptionError.__init__(self, opt_str)
+        self.possibilities = possibilities
+
+    def __str__(self):
+        return (_("ambiguous option: %s (%s?)")
+                % (self.opt_str, ", ".join(self.possibilities)))
+
+
+class HelpFormatter:
+
+    """
+    Abstract base class for formatting option help.  OptionParser
+    instances should use one of the HelpFormatter subclasses for
+    formatting help; by default IndentedHelpFormatter is used.
+
+    Instance attributes:
+      parser : OptionParser
+        the controlling OptionParser instance
+      indent_increment : int
+        the number of columns to indent per nesting level
+      max_help_position : int
+        the maximum starting column for option help text
+      help_position : int
+        the calculated starting column for option help text;
+        initially the same as the maximum
+      width : int
+        total number of columns for output (pass None to constructor for
+        this value to be taken from the $COLUMNS environment variable)
+      level : int
+        current indentation level
+      current_indent : int
+        current indentation level (in columns)
+      help_width : int
+        number of columns available for option help text (calculated)
+      default_tag : str
+        text to replace with each option's default value, "%default"
+        by default.  Set to false value to disable default value expansion.
+      option_strings : { Option : str }
+        maps Option instances to the snippet of help text explaining
+        the syntax of that option, e.g. "-h, --help" or
+        "-fFILE, --file=FILE"
+      _short_opt_fmt : str
+        format string controlling how short options with values are
+        printed in help text.  Must be either "%s%s" ("-fFILE") or
+        "%s %s" ("-f FILE"), because those are the two syntaxes that
+        Optik supports.
+      _long_opt_fmt : str
+        similar but for long options; must be either "%s %s" ("--file FILE")
+        or "%s=%s" ("--file=FILE").
+    """
+
+    NO_DEFAULT_VALUE = "none"
+
+    def __init__(self,
+                 indent_increment,
+                 max_help_position,
+                 width,
+                 short_first):
+        self.parser = None
+        self.indent_increment = indent_increment
+        self.help_position = self.max_help_position = max_help_position
+        if width is None:
+            try:
+                width = int(os.environ['COLUMNS'])
+            except (KeyError, ValueError):
+                width = 80
+            width -= 2
+        self.width = width
+        self.current_indent = 0
+        self.level = 0
+        self.help_width = None          # computed later
+        self.short_first = short_first
+        self.default_tag = "%default"
+        self.option_strings = {}
+        self._short_opt_fmt = "%s %s"
+        self._long_opt_fmt = "%s=%s"
+
+    def set_parser(self, parser):
+        self.parser = parser
+
+    def set_short_opt_delimiter(self, delim):
+        if delim not in ("", " "):
+            raise ValueError(
+                "invalid metavar delimiter for short options: %r" % delim)
+        self._short_opt_fmt = "%s" + delim + "%s"
+
+    def set_long_opt_delimiter(self, delim):
+        if delim not in ("=", " "):
+            raise ValueError(
+                "invalid metavar delimiter for long options: %r" % delim)
+        self._long_opt_fmt = "%s" + delim + "%s"
+
+    def indent(self):
+        self.current_indent += self.indent_increment
+        self.level += 1
+
+    def dedent(self):
+        self.current_indent -= self.indent_increment
+        assert self.current_indent >= 0, "Indent decreased below 0."
+        self.level -= 1
+
+    def format_usage(self, usage):
+        raise NotImplementedError, "subclasses must implement"
+
+    def format_heading(self, heading):
+        raise NotImplementedError, "subclasses must implement"
+
+    def _format_text(self, text):
+        """
+        Format a paragraph of free-form text for inclusion in the
+        help output at the current indentation level.
+        """
+        text_width = self.width - self.current_indent
+        indent = " "*self.current_indent
+        return textwrap.fill(text,
+                             text_width,
+                             initial_indent=indent,
+                             subsequent_indent=indent)
+
+    def format_description(self, description):
+        if description:
+            return self._format_text(description) + "\n"
+        else:
+            return ""
+
+    def format_epilog(self, epilog):
+        if epilog:
+            return "\n" + self._format_text(epilog) + "\n"
+        else:
+            return ""
+
+
+    def expand_default(self, option):
+        if self.parser is None or not self.default_tag:
+            return option.help
+
+        default_value = self.parser.defaults.get(option.dest)
+        if default_value is NO_DEFAULT or default_value is None:
+            default_value = self.NO_DEFAULT_VALUE
+
+        return option.help.replace(self.default_tag, str(default_value))
+
+    def format_option(self, option):
+        # The help for each option consists of two parts:
+        #   * the opt strings and metavars
+        #     eg. ("-x", or "-fFILENAME, --file=FILENAME")
+        #   * the user-supplied help string
+        #     eg. ("turn on expert mode", "read data from FILENAME")
+        #
+        # If possible, we write both of these on the same line:
+        #   -x      turn on expert mode
+        #
+        # But if the opt string list is too long, we put the help
+        # string on a second line, indented to the same column it would
+        # start in if it fit on the first line.
+        #   -fFILENAME, --file=FILENAME
+        #           read data from FILENAME
+        result = []
+        opts = self.option_strings[option]
+        opt_width = self.help_position - self.current_indent - 2
+        if len(opts) > opt_width:
+            opts = "%*s%s\n" % (self.current_indent, "", opts)
+            indent_first = self.help_position
+        else:                       # start help on same line as opts
+            opts = "%*s%-*s  " % (self.current_indent, "", opt_width, opts)
+            indent_first = 0
+        result.append(opts)
+        if option.help:
+            help_text = self.expand_default(option)
+            help_lines = textwrap.wrap(help_text, self.help_width)
+            result.append("%*s%s\n" % (indent_first, "", help_lines[0]))
+            result.extend(["%*s%s\n" % (self.help_position, "", line)
+                           for line in help_lines[1:]])
+        elif opts[-1] != "\n":
+            result.append("\n")
+        return "".join(result)
+
+    def store_option_strings(self, parser):
+        self.indent()
+        max_len = 0
+        for opt in parser.option_list:
+            strings = self.format_option_strings(opt)
+            self.option_strings[opt] = strings
+            max_len = max(max_len, len(strings) + self.current_indent)
+        self.indent()
+        for group in parser.option_groups:
+            for opt in group.option_list:
+                strings = self.format_option_strings(opt)
+                self.option_strings[opt] = strings
+                max_len = max(max_len, len(strings) + self.current_indent)
+        self.dedent()
+        self.dedent()
+        self.help_position = min(max_len + 2, self.max_help_position)
+        self.help_width = self.width - self.help_position
+
+    def format_option_strings(self, option):
+        """Return a comma-separated list of option strings & metavariables."""
+        if option.takes_value():
+            metavar = option.metavar or option.dest.upper()
+            short_opts = [self._short_opt_fmt % (sopt, metavar)
+                          for sopt in option._short_opts]
+            long_opts = [self._long_opt_fmt % (lopt, metavar)
+                         for lopt in option._long_opts]
+        else:
+            short_opts = option._short_opts
+            long_opts = option._long_opts
+
+        if self.short_first:
+            opts = short_opts + long_opts
+        else:
+            opts = long_opts + short_opts
+
+        return ", ".join(opts)
+
+class IndentedHelpFormatter (HelpFormatter):
+    """Format help with indented section bodies.
+    """
+
+    def __init__(self,
+                 indent_increment=2,
+                 max_help_position=24,
+                 width=None,
+                 short_first=1):
+        HelpFormatter.__init__(
+            self, indent_increment, max_help_position, width, short_first)
+
+    def format_usage(self, usage):
+        return _("Usage: %s\n") % usage
+
+    def format_heading(self, heading):
+        return "%*s%s:\n" % (self.current_indent, "", heading)
+
+
+class TitledHelpFormatter (HelpFormatter):
+    """Format help with underlined section headers.
+    """
+
+    def __init__(self,
+                 indent_increment=0,
+                 max_help_position=24,
+                 width=None,
+                 short_first=0):
+        HelpFormatter.__init__ (
+            self, indent_increment, max_help_position, width, short_first)
+
+    def format_usage(self, usage):
+        return "%s  %s\n" % (self.format_heading(_("Usage")), usage)
+
+    def format_heading(self, heading):
+        return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading))
+
+
+def _parse_num(val, type):
+    if val[:2].lower() == "0x":         # hexadecimal
+        radix = 16
+    elif val[:2].lower() == "0b":       # binary
+        radix = 2
+        val = val[2:] or "0"            # have to remove "0b" prefix
+    elif val[:1] == "0":                # octal
+        radix = 8
+    else:                               # decimal
+        radix = 10
+
+    return type(val, radix)
+
+def _parse_int(val):
+    return _parse_num(val, int)
+
+def _parse_long(val):
+    return _parse_num(val, long)
+
+_builtin_cvt = { "int" : (_parse_int, _("integer")),
+                 "long" : (_parse_long, _("long integer")),
+                 "float" : (float, _("floating-point")),
+                 "complex" : (complex, _("complex")) }
+
+def check_builtin(option, opt, value):
+    (cvt, what) = _builtin_cvt[option.type]
+    try:
+        return cvt(value)
+    except ValueError:
+        raise OptionValueError(
+            _("option %s: invalid %s value: %r") % (opt, what, value))
+
+def check_choice(option, opt, value):
+    if value in option.choices:
+        return value
+    else:
+        choices = ", ".join(map(repr, option.choices))
+        raise OptionValueError(
+            _("option %s: invalid choice: %r (choose from %s)")
+            % (opt, value, choices))
+
+# Not supplying a default is different from a default of None,
+# so we need an explicit "not supplied" value.
+NO_DEFAULT = ("NO", "DEFAULT")
+
+
+class Option:
+    """
+    Instance attributes:
+      _short_opts : [string]
+      _long_opts : [string]
+
+      action : string
+      type : string
+      dest : string
+      default : any
+      nargs : int
+      const : any
+      choices : [string]
+      callback : function
+      callback_args : (any*)
+      callback_kwargs : { string : any }
+      help : string
+      metavar : string
+    """
+
+    # The list of instance attributes that may be set through
+    # keyword args to the constructor.
+    ATTRS = ['action',
+             'type',
+             'dest',
+             'default',
+             'nargs',
+             'const',
+             'choices',
+             'callback',
+             'callback_args',
+             'callback_kwargs',
+             'help',
+             'metavar']
+
+    # The set of actions allowed by option parsers.  Explicitly listed
+    # here so the constructor can validate its arguments.
+    ACTIONS = ("store",
+               "store_const",
+               "store_true",
+               "store_false",
+               "append",
+               "append_const",
+               "count",
+               "callback",
+               "help",
+               "version")
+
+    # The set of actions that involve storing a value somewhere;
+    # also listed just for constructor argument validation.  (If
+    # the action is one of these, there must be a destination.)
+    STORE_ACTIONS = ("store",
+                     "store_const",
+                     "store_true",
+                     "store_false",
+                     "append",
+                     "append_const",
+                     "count")
+
+    # The set of actions for which it makes sense to supply a value
+    # type, ie. which may consume an argument from the command line.
+    TYPED_ACTIONS = ("store",
+                     "append",
+                     "callback")
+
+    # The set of actions which *require* a value type, ie. that
+    # always consume an argument from the command line.
+    ALWAYS_TYPED_ACTIONS = ("store",
+                            "append")
+
+    # The set of actions which take a 'const' attribute.
+    CONST_ACTIONS = ("store_const",
+                     "append_const")
+
+    # The set of known types for option parsers.  Again, listed here for
+    # constructor argument validation.
+    TYPES = ("string", "int", "long", "float", "complex", "choice")
+
+    # Dictionary of argument checking functions, which convert and
+    # validate option arguments according to the option type.
+    #
+    # Signature of checking functions is:
+    #   check(option : Option, opt : string, value : string) -> any
+    # where
+    #   option is the Option instance calling the checker
+    #   opt is the actual option seen on the command-line
+    #     (eg. "-a", "--file")
+    #   value is the option argument seen on the command-line
+    #
+    # The return value should be in the appropriate Python type
+    # for option.type -- eg. an integer if option.type == "int".
+    #
+    # If no checker is defined for a type, arguments will be
+    # unchecked and remain strings.
+    TYPE_CHECKER = { "int"    : check_builtin,
+                     "long"   : check_builtin,
+                     "float"  : check_builtin,
+                     "complex": check_builtin,
+                     "choice" : check_choice,
+                   }
+
+
+    # CHECK_METHODS is a list of unbound method objects; they are called
+    # by the constructor, in order, after all attributes are
+    # initialized.  The list is created and filled in later, after all
+    # the methods are actually defined.  (I just put it here because I
+    # like to define and document all class attributes in the same
+    # place.)  Subclasses that add another _check_*() method should
+    # define their own CHECK_METHODS list that adds their check method
+    # to those from this class.
+    CHECK_METHODS = None
+
+
+    # -- Constructor/initialization methods ----------------------------
+
+    def __init__(self, *opts, **attrs):
+        # Set _short_opts, _long_opts attrs from 'opts' tuple.
+        # Have to be set now, in case no option strings are supplied.
+        self._short_opts = []
+        self._long_opts = []
+        opts = self._check_opt_strings(opts)
+        self._set_opt_strings(opts)
+
+        # Set all other attrs (action, type, etc.) from 'attrs' dict
+        self._set_attrs(attrs)
+
+        # Check all the attributes we just set.  There are lots of
+        # complicated interdependencies, but luckily they can be farmed
+        # out to the _check_*() methods listed in CHECK_METHODS -- which
+        # could be handy for subclasses!  The one thing these all share
+        # is that they raise OptionError if they discover a problem.
+        for checker in self.CHECK_METHODS:
+            checker(self)
+
+    def _check_opt_strings(self, opts):
+        # Filter out None because early versions of Optik had exactly
+        # one short option and one long option, either of which
+        # could be None.
+        opts = filter(None, opts)
+        if not opts:
+            raise TypeError("at least one option string must be supplied")
+        return opts
+
+    def _set_opt_strings(self, opts):
+        for opt in opts:
+            if len(opt) < 2:
+                raise OptionError(
+                    "invalid option string %r: "
+                    "must be at least two characters long" % opt, self)
+            elif len(opt) == 2:
+                if not (opt[0] == "-" and opt[1] != "-"):
+                    raise OptionError(
+                        "invalid short option string %r: "
+                        "must be of the form -x, (x any non-dash char)" % opt,
+                        self)
+                self._short_opts.append(opt)
+            else:
+                if not (opt[0:2] == "--" and opt[2] != "-"):
+                    raise OptionError(
+                        "invalid long option string %r: "
+                        "must start with --, followed by non-dash" % opt,
+                        self)
+                self._long_opts.append(opt)
+
+    def _set_attrs(self, attrs):
+        for attr in self.ATTRS:
+            if attr in attrs:
+                setattr(self, attr, attrs[attr])
+                del attrs[attr]
+            else:
+                if attr == 'default':
+                    setattr(self, attr, NO_DEFAULT)
+                else:
+                    setattr(self, attr, None)
+        if attrs:
+            attrs = attrs.keys()
+            attrs.sort()
+            raise OptionError(
+                "invalid keyword arguments: %s" % ", ".join(attrs),
+                self)
+
+
+    # -- Constructor validation methods --------------------------------
+
+    def _check_action(self):
+        if self.action is None:
+            self.action = "store"
+        elif self.action not in self.ACTIONS:
+            raise OptionError("invalid action: %r" % self.action, self)
+
+    def _check_type(self):
+        if self.type is None:
+            if self.action in self.ALWAYS_TYPED_ACTIONS:
+                if self.choices is not None:
+                    # The "choices" attribute implies "choice" type.
+                    self.type = "choice"
+                else:
+                    # No type given?  "string" is the most sensible default.
+                    self.type = "string"
+        else:
+            # Allow type objects or builtin type conversion functions
+            # (int, str, etc.) as an alternative to their names.  (The
+            # complicated check of __builtin__ is only necessary for
+            # Python 2.1 and earlier, and is short-circuited by the
+            # first check on modern Pythons.)
+            import __builtin__
+            if ( type(self.type) is types.TypeType or
+                 (hasattr(self.type, "__name__") and
+                  getattr(__builtin__, self.type.__name__, None) is self.type) ):
+                self.type = self.type.__name__
+
+            if self.type == "str":
+                self.type = "string"
+
+            if self.type not in self.TYPES:
+                raise OptionError("invalid option type: %r" % self.type, self)
+            if self.action not in self.TYPED_ACTIONS:
+                raise OptionError(
+                    "must not supply a type for action %r" % self.action, self)
+
+    def _check_choice(self):
+        if self.type == "choice":
+            if self.choices is None:
+                raise OptionError(
+                    "must supply a list of choices for type 'choice'", self)
+            elif type(self.choices) not in (types.TupleType, types.ListType):
+                raise OptionError(
+                    "choices must be a list of strings ('%s' supplied)"
+                    % str(type(self.choices)).split("'")[1], self)
+        elif self.choices is not None:
+            raise OptionError(
+                "must not supply choices for type %r" % self.type, self)
+
+    def _check_dest(self):
+        # No destination given, and we need one for this action.  The
+        # self.type check is for callbacks that take a value.
+        takes_value = (self.action in self.STORE_ACTIONS or
+                       self.type is not None)
+        if self.dest is None and takes_value:
+
+            # Glean a destination from the first long option string,
+            # or from the first short option string if no long options.
+            if self._long_opts:
+                # eg. "--foo-bar" -> "foo_bar"
+                self.dest = self._long_opts[0][2:].replace('-', '_')
+            else:
+                self.dest = self._short_opts[0][1]
+
+    def _check_const(self):
+        if self.action not in self.CONST_ACTIONS and self.const is not None:
+            raise OptionError(
+                "'const' must not be supplied for action %r" % self.action,
+                self)
+
+    def _check_nargs(self):
+        if self.action in self.TYPED_ACTIONS:
+            if self.nargs is None:
+                self.nargs = 1
+        elif self.nargs is not None:
+            raise OptionError(
+                "'nargs' must not be supplied for action %r" % self.action,
+                self)
+
+    def _check_callback(self):
+        if self.action == "callback":
+            if not hasattr(self.callback, '__call__'):
+                raise OptionError(
+                    "callback not callable: %r" % self.callback, self)
+            if (self.callback_args is not None and
+                type(self.callback_args) is not types.TupleType):
+                raise OptionError(
+                    "callback_args, if supplied, must be a tuple: not %r"
+                    % self.callback_args, self)
+            if (self.callback_kwargs is not None and
+                type(self.callback_kwargs) is not types.DictType):
+                raise OptionError(
+                    "callback_kwargs, if supplied, must be a dict: not %r"
+                    % self.callback_kwargs, self)
+        else:
+            if self.callback is not None:
+                raise OptionError(
+                    "callback supplied (%r) for non-callback option"
+                    % self.callback, self)
+            if self.callback_args is not None:
+                raise OptionError(
+                    "callback_args supplied for non-callback option", self)
+            if self.callback_kwargs is not None:
+                raise OptionError(
+                    "callback_kwargs supplied for non-callback option", self)
+
+
+    CHECK_METHODS = [_check_action,
+                     _check_type,
+                     _check_choice,
+                     _check_dest,
+                     _check_const,
+                     _check_nargs,
+                     _check_callback]
+
+
+    # -- Miscellaneous methods -----------------------------------------
+
+    def __str__(self):
+        return "/".join(self._short_opts + self._long_opts)
+
+    __repr__ = _repr
+
+    def takes_value(self):
+        return self.type is not None
+
+    def get_opt_string(self):
+        if self._long_opts:
+            return self._long_opts[0]
+        else:
+            return self._short_opts[0]
+
+
+    # -- Processing methods --------------------------------------------
+
+    def check_value(self, opt, value):
+        checker = self.TYPE_CHECKER.get(self.type)
+        if checker is None:
+            return value
+        else:
+            return checker(self, opt, value)
+
+    def convert_value(self, opt, value):
+        if value is not None:
+            if self.nargs == 1:
+                return self.check_value(opt, value)
+            else:
+                return tuple([self.check_value(opt, v) for v in value])
+
+    def process(self, opt, value, values, parser):
+
+        # First, convert the value(s) to the right type.  Howl if any
+        # value(s) are bogus.
+        value = self.convert_value(opt, value)
+
+        # And then take whatever action is expected of us.
+        # This is a separate method to make life easier for
+        # subclasses to add new actions.
+        return self.take_action(
+            self.action, self.dest, opt, value, values, parser)
+
+    def take_action(self, action, dest, opt, value, values, parser):
+        if action == "store":
+            setattr(values, dest, value)
+        elif action == "store_const":
+            setattr(values, dest, self.const)
+        elif action == "store_true":
+            setattr(values, dest, True)
+        elif action == "store_false":
+            setattr(values, dest, False)
+        elif action == "append":
+            values.ensure_value(dest, []).append(value)
+        elif action == "append_const":
+            values.ensure_value(dest, []).append(self.const)
+        elif action == "count":
+            setattr(values, dest, values.ensure_value(dest, 0) + 1)
+        elif action == "callback":
+            args = self.callback_args or ()
+            kwargs = self.callback_kwargs or {}
+            self.callback(self, opt, value, parser, *args, **kwargs)
+        elif action == "help":
+            parser.print_help()
+            parser.exit()
+        elif action == "version":
+            parser.print_version()
+            parser.exit()
+        else:
+            raise ValueError("unknown action %r" % self.action)
+
+        return 1
+
+# class Option
+
+
+SUPPRESS_HELP = "SUPPRESS"+"HELP"
+SUPPRESS_USAGE = "SUPPRESS"+"USAGE"
+
+try:
+    basestring
+except NameError:
+    def isbasestring(x):
+        return isinstance(x, (types.StringType, types.UnicodeType))
+else:
+    def isbasestring(x):
+        return isinstance(x, basestring)
+
+class Values:
+
+    def __init__(self, defaults=None):
+        if defaults:
+            for (attr, val) in defaults.items():
+                setattr(self, attr, val)
+
+    def __str__(self):
+        return str(self.__dict__)
+
+    __repr__ = _repr
+
+    def __cmp__(self, other):
+        if isinstance(other, Values):
+            return cmp(self.__dict__, other.__dict__)
+        elif isinstance(other, types.DictType):
+            return cmp(self.__dict__, other)
+        else:
+            return -1
+
+    def _update_careful(self, dict):
+        """
+        Update the option values from an arbitrary dictionary, but only
+        use keys from dict that already have a corresponding attribute
+        in self.  Any keys in dict without a corresponding attribute
+        are silently ignored.
+        """
+        for attr in dir(self):
+            if attr in dict:
+                dval = dict[attr]
+                if dval is not None:
+                    setattr(self, attr, dval)
+
+    def _update_loose(self, dict):
+        """
+        Update the option values from an arbitrary dictionary,
+        using all keys from the dictionary regardless of whether
+        they have a corresponding attribute in self or not.
+        """
+        self.__dict__.update(dict)
+
+    def _update(self, dict, mode):
+        if mode == "careful":
+            self._update_careful(dict)
+        elif mode == "loose":
+            self._update_loose(dict)
+        else:
+            raise ValueError, "invalid update mode: %r" % mode
+
+    def read_module(self, modname, mode="careful"):
+        __import__(modname)
+        mod = sys.modules[modname]
+        self._update(vars(mod), mode)
+
+    def read_file(self, filename, mode="careful"):
+        vars = {}
+        execfile(filename, vars)
+        self._update(vars, mode)
+
+    def ensure_value(self, attr, value):
+        if not hasattr(self, attr) or getattr(self, attr) is None:
+            setattr(self, attr, value)
+        return getattr(self, attr)
+
+
+class OptionContainer:
+
+    """
+    Abstract base class.
+
+    Class attributes:
+      standard_option_list : [Option]
+        list of standard options that will be accepted by all instances
+        of this parser class (intended to be overridden by subclasses).
+
+    Instance attributes:
+      option_list : [Option]
+        the list of Option objects contained by this OptionContainer
+      _short_opt : { string : Option }
+        dictionary mapping short option strings, eg. "-f" or "-X",
+        to the Option instances that implement them.  If an Option
+        has multiple short option strings, it will appears in this
+        dictionary multiple times. [1]
+      _long_opt : { string : Option }
+        dictionary mapping long option strings, eg. "--file" or
+        "--exclude", to the Option instances that implement them.
+        Again, a given Option can occur multiple times in this
+        dictionary. [1]
+      defaults : { string : any }
+        dictionary mapping option destination names to default
+        values for each destination [1]
+
+    [1] These mappings are common to (shared by) all components of the
+        controlling OptionParser, where they are initially created.
+
+    """
+
+    def __init__(self, option_class, conflict_handler, description):
+        # Initialize the option list and related data structures.
+        # This method must be provided by subclasses, and it must
+        # initialize at least the following instance attributes:
+        # option_list, _short_opt, _long_opt, defaults.
+        self._create_option_list()
+
+        self.option_class = option_class
+        self.set_conflict_handler(conflict_handler)
+        self.set_description(description)
+
+    def _create_option_mappings(self):
+        # For use by OptionParser constructor -- create the master
+        # option mappings used by this OptionParser and all
+        # OptionGroups that it owns.
+        self._short_opt = {}            # single letter -> Option instance
+        self._long_opt = {}             # long option -> Option instance
+        self.defaults = {}              # maps option dest -> default value
+
+
+    def _share_option_mappings(self, parser):
+        # For use by OptionGroup constructor -- use shared option
+        # mappings from the OptionParser that owns this OptionGroup.
+        self._short_opt = parser._short_opt
+        self._long_opt = parser._long_opt
+        self.defaults = parser.defaults
+
+    def set_conflict_handler(self, handler):
+        if handler not in ("error", "resolve"):
+            raise ValueError, "invalid conflict_resolution value %r" % handler
+        self.conflict_handler = handler
+
+    def set_description(self, description):
+        self.description = description
+
+    def get_description(self):
+        return self.description
+
+
+    def destroy(self):
+        """see OptionParser.destroy()."""
+        del self._short_opt
+        del self._long_opt
+        del self.defaults
+
+
+    # -- Option-adding methods -----------------------------------------
+
+    def _check_conflict(self, option):
+        conflict_opts = []
+        for opt in option._short_opts:
+            if opt in self._short_opt:
+                conflict_opts.append((opt, self._short_opt[opt]))
+        for opt in option._long_opts:
+            if opt in self._long_opt:
+                conflict_opts.append((opt, self._long_opt[opt]))
+
+        if conflict_opts:
+            handler = self.conflict_handler
+            if handler == "error":
+                raise OptionConflictError(
+                    "conflicting option string(s): %s"
+                    % ", ".join([co[0] for co in conflict_opts]),
+                    option)
+            elif handler == "resolve":
+                for (opt, c_option) in conflict_opts:
+                    if opt.startswith("--"):
+                        c_option._long_opts.remove(opt)
+                        del self._long_opt[opt]
+                    else:
+                        c_option._short_opts.remove(opt)
+                        del self._short_opt[opt]
+                    if not (c_option._short_opts or c_option._long_opts):
+                        c_option.container.option_list.remove(c_option)
+
+    def add_option(self, *args, **kwargs):
+        """add_option(Option)
+           add_option(opt_str, ..., kwarg=val, ...)
+        """
+        if type(args[0]) in types.StringTypes:
+            option = self.option_class(*args, **kwargs)
+        elif len(args) == 1 and not kwargs:
+            option = args[0]
+            if not isinstance(option, Option):
+                raise TypeError, "not an Option instance: %r" % option
+        else:
+            raise TypeError, "invalid arguments"
+
+        self._check_conflict(option)
+
+        self.option_list.append(option)
+        option.container = self
+        for opt in option._short_opts:
+            self._short_opt[opt] = option
+        for opt in option._long_opts:
+            self._long_opt[opt] = option
+
+        if option.dest is not None:     # option has a dest, we need a default
+            if option.default is not NO_DEFAULT:
+                self.defaults[option.dest] = option.default
+            elif option.dest not in self.defaults:
+                self.defaults[option.dest] = None
+
+        return option
+
+    def add_options(self, option_list):
+        for option in option_list:
+            self.add_option(option)
+
+    # -- Option query/removal methods ----------------------------------
+
+    def get_option(self, opt_str):
+        return (self._short_opt.get(opt_str) or
+                self._long_opt.get(opt_str))
+
+    def has_option(self, opt_str):
+        return (opt_str in self._short_opt or
+                opt_str in self._long_opt)
+
+    def remove_option(self, opt_str):
+        option = self._short_opt.get(opt_str)
+        if option is None:
+            option = self._long_opt.get(opt_str)
+        if option is None:
+            raise ValueError("no such option %r" % opt_str)
+
+        for opt in option._short_opts:
+            del self._short_opt[opt]
+        for opt in option._long_opts:
+            del self._long_opt[opt]
+        option.container.option_list.remove(option)
+
+
+    # -- Help-formatting methods ---------------------------------------
+
+    def format_option_help(self, formatter):
+        if not self.option_list:
+            return ""
+        result = []
+        for option in self.option_list:
+            if not option.help is SUPPRESS_HELP:
+                result.append(formatter.format_option(option))
+        return "".join(result)
+
+    def format_description(self, formatter):
+        return formatter.format_description(self.get_description())
+
+    def format_help(self, formatter):
+        result = []
+        if self.description:
+            result.append(self.format_description(formatter))
+        if self.option_list:
+            result.append(self.format_option_help(formatter))
+        return "\n".join(result)
+
+
+class OptionGroup (OptionContainer):
+
+    def __init__(self, parser, title, description=None):
+        self.parser = parser
+        OptionContainer.__init__(
+            self, parser.option_class, parser.conflict_handler, description)
+        self.title = title
+
+    def _create_option_list(self):
+        self.option_list = []
+        self._share_option_mappings(self.parser)
+
+    def set_title(self, title):
+        self.title = title
+
+    def destroy(self):
+        """see OptionParser.destroy()."""
+        OptionContainer.destroy(self)
+        del self.option_list
+
+    # -- Help-formatting methods ---------------------------------------
+
+    def format_help(self, formatter):
+        result = formatter.format_heading(self.title)
+        formatter.indent()
+        result += OptionContainer.format_help(self, formatter)
+        formatter.dedent()
+        return result
+
+
+class OptionParser (OptionContainer):
+
+    """
+    Class attributes:
+      standard_option_list : [Option]
+        list of standard options that will be accepted by all instances
+        of this parser class (intended to be overridden by subclasses).
+
+    Instance attributes:
+      usage : string
+        a usage string for your program.  Before it is displayed
+        to the user, "%prog" will be expanded to the name of
+        your program (self.prog or os.path.basename(sys.argv[0])).
+      prog : string
+        the name of the current program (to override
+        os.path.basename(sys.argv[0])).
+      description : string
+        A paragraph of text giving a brief overview of your program.
+        optparse reformats this paragraph to fit the current terminal
+        width and prints it when the user requests help (after usage,
+        but before the list of options).
+      epilog : string
+        paragraph of help text to print after option help
+
+      option_groups : [OptionGroup]
+        list of option groups in this parser (option groups are
+        irrelevant for parsing the command-line, but very useful
+        for generating help)
+
+      allow_interspersed_args : bool = true
+        if true, positional arguments may be interspersed with options.
+        Assuming -a and -b each take a single argument, the command-line
+          -ablah foo bar -bboo baz
+        will be interpreted the same as
+          -ablah -bboo -- foo bar baz
+        If this flag were false, that command line would be interpreted as
+          -ablah -- foo bar -bboo baz
+        -- ie. we stop processing options as soon as we see the first
+        non-option argument.  (This is the tradition followed by
+        Python's getopt module, Perl's Getopt::Std, and other argument-
+        parsing libraries, but it is generally annoying to users.)
+
+      process_default_values : bool = true
+        if true, option default values are processed similarly to option
+        values from the command line: that is, they are passed to the
+        type-checking function for the option's type (as long as the
+        default value is a string).  (This really only matters if you
+        have defined custom types; see SF bug #955889.)  Set it to false
+        to restore the behaviour of Optik 1.4.1 and earlier.
+
+      rargs : [string]
+        the argument list currently being parsed.  Only set when
+        parse_args() is active, and continually trimmed down as
+        we consume arguments.  Mainly there for the benefit of
+        callback options.
+      largs : [string]
+        the list of leftover arguments that we have skipped while
+        parsing options.  If allow_interspersed_args is false, this
+        list is always empty.
+      values : Values
+        the set of option values currently being accumulated.  Only
+        set when parse_args() is active.  Also mainly for callbacks.
+
+    Because of the 'rargs', 'largs', and 'values' attributes,
+    OptionParser is not thread-safe.  If, for some perverse reason, you
+    need to parse command-line arguments simultaneously in different
+    threads, use different OptionParser instances.
+
+    """
+
+    standard_option_list = []
+
+    def __init__(self,
+                 usage=None,
+                 option_list=None,
+                 option_class=Option,
+                 version=None,
+                 conflict_handler="error",
+                 description=None,
+                 formatter=None,
+                 add_help_option=True,
+                 prog=None,
+                 epilog=None):
+        OptionContainer.__init__(
+            self, option_class, conflict_handler, description)
+        self.set_usage(usage)
+        self.prog = prog
+        self.version = version
+        self.allow_interspersed_args = True
+        self.process_default_values = True
+        if formatter is None:
+            formatter = IndentedHelpFormatter()
+        self.formatter = formatter
+        self.formatter.set_parser(self)
+        self.epilog = epilog
+
+        # Populate the option list; initial sources are the
+        # standard_option_list class attribute, the 'option_list'
+        # argument, and (if applicable) the _add_version_option() and
+        # _add_help_option() methods.
+        self._populate_option_list(option_list,
+                                   add_help=add_help_option)
+
+        self._init_parsing_state()
+
+
+    def destroy(self):
+        """
+        Declare that you are done with this OptionParser.  This cleans up
+        reference cycles so the OptionParser (and all objects referenced by
+        it) can be garbage-collected promptly.  After calling destroy(), the
+        OptionParser is unusable.
+        """
+        OptionContainer.destroy(self)
+        for group in self.option_groups:
+            group.destroy()
+        del self.option_list
+        del self.option_groups
+        del self.formatter
+
+
+    # -- Private methods -----------------------------------------------
+    # (used by our or OptionContainer's constructor)
+
+    def _create_option_list(self):
+        self.option_list = []
+        self.option_groups = []
+        self._create_option_mappings()
+
+    def _add_help_option(self):
+        self.add_option("-h", "--help",
+                        action="help",
+                        help=_("show this help message and exit"))
+
+    def _add_version_option(self):
+        self.add_option("--version",
+                        action="version",
+                        help=_("show program's version number and exit"))
+
+    def _populate_option_list(self, option_list, add_help=True):
+        if self.standard_option_list:
+            self.add_options(self.standard_option_list)
+        if option_list:
+            self.add_options(option_list)
+        if self.version:
+            self._add_version_option()
+        if add_help:
+            self._add_help_option()
+
+    def _init_parsing_state(self):
+        # These are set in parse_args() for the convenience of callbacks.
+        self.rargs = None
+        self.largs = None
+        self.values = None
+
+
+    # -- Simple modifier methods ---------------------------------------
+
+    def set_usage(self, usage):
+        if usage is None:
+            self.usage = _("%prog [options]")
+        elif usage is SUPPRESS_USAGE:
+            self.usage = None
+        # For backwards compatibility with Optik 1.3 and earlier.
+        elif usage.lower().startswith("usage: "):
+            self.usage = usage[7:]
+        else:
+            self.usage = usage
+
+    def enable_interspersed_args(self):
+        """Set parsing to not stop on the first non-option, allowing
+        interspersing switches with command arguments. This is the
+        default behavior. See also disable_interspersed_args() and the
+        class documentation description of the attribute
+        allow_interspersed_args."""
+        self.allow_interspersed_args = True
+
+    def disable_interspersed_args(self):
+        """Set parsing to stop on the first non-option. Use this if
+        you have a command processor which runs another command that
+        has options of its own and you want to make sure these options
+        don't get confused.
+        """
+        self.allow_interspersed_args = False
+
+    def set_process_default_values(self, process):
+        self.process_default_values = process
+
+    def set_default(self, dest, value):
+        self.defaults[dest] = value
+
+    def set_defaults(self, **kwargs):
+        self.defaults.update(kwargs)
+
+    def _get_all_options(self):
+        options = self.option_list[:]
+        for group in self.option_groups:
+            options.extend(group.option_list)
+        return options
+
+    def get_default_values(self):
+        if not self.process_default_values:
+            # Old, pre-Optik 1.5 behaviour.
+            return Values(self.defaults)
+
+        defaults = self.defaults.copy()
+        for option in self._get_all_options():
+            default = defaults.get(option.dest)
+            if isbasestring(default):
+                opt_str = option.get_opt_string()
+                defaults[option.dest] = option.check_value(opt_str, default)
+
+        return Values(defaults)
+
+
+    # -- OptionGroup methods -------------------------------------------
+
+    def add_option_group(self, *args, **kwargs):
+        # XXX lots of overlap with OptionContainer.add_option()
+        if type(args[0]) is types.StringType:
+            group = OptionGroup(self, *args, **kwargs)
+        elif len(args) == 1 and not kwargs:
+            group = args[0]
+            if not isinstance(group, OptionGroup):
+                raise TypeError, "not an OptionGroup instance: %r" % group
+            if group.parser is not self:
+                raise ValueError, "invalid OptionGroup (wrong parser)"
+        else:
+            raise TypeError, "invalid arguments"
+
+        self.option_groups.append(group)
+        return group
+
+    def get_option_group(self, opt_str):
+        option = (self._short_opt.get(opt_str) or
+                  self._long_opt.get(opt_str))
+        if option and option.container is not self:
+            return option.container
+        return None
+
+
+    # -- Option-parsing methods ----------------------------------------
+
+    def _get_args(self, args):
+        if args is None:
+            return sys.argv[1:]
+        else:
+            return args[:]              # don't modify caller's list
+
+    def parse_args(self, args=None, values=None):
+        """
+        parse_args(args : [string] = sys.argv[1:],
+                   values : Values = None)
+        -> (values : Values, args : [string])
+
+        Parse the command-line options found in 'args' (default:
+        sys.argv[1:]).  Any errors result in a call to 'error()', which
+        by default prints the usage message to stderr and calls
+        sys.exit() with an error message.  On success returns a pair
+        (values, args) where 'values' is an Values instance (with all
+        your option values) and 'args' is the list of arguments left
+        over after parsing options.
+        """
+        rargs = self._get_args(args)
+        if values is None:
+            values = self.get_default_values()
+
+        # Store the halves of the argument list as attributes for the
+        # convenience of callbacks:
+        #   rargs
+        #     the rest of the command-line (the "r" stands for
+        #     "remaining" or "right-hand")
+        #   largs
+        #     the leftover arguments -- ie. what's left after removing
+        #     options and their arguments (the "l" stands for "leftover"
+        #     or "left-hand")
+        self.rargs = rargs
+        self.largs = largs = []
+        self.values = values
+
+        try:
+            stop = self._process_args(largs, rargs, values)
+        except (BadOptionError, OptionValueError), err:
+            self.error(str(err))
+
+        args = largs + rargs
+        return self.check_values(values, args)
+
+    def check_values(self, values, args):
+        """
+        check_values(values : Values, args : [string])
+        -> (values : Values, args : [string])
+
+        Check that the supplied option values and leftover arguments are
+        valid.  Returns the option values and leftover arguments
+        (possibly adjusted, possibly completely new -- whatever you
+        like).  Default implementation just returns the passed-in
+        values; subclasses may override as desired.
+        """
+        return (values, args)
+
+    def _process_args(self, largs, rargs, values):
+        """_process_args(largs : [string],
+                         rargs : [string],
+                         values : Values)
+
+        Process command-line arguments and populate 'values', consuming
+        options and arguments from 'rargs'.  If 'allow_interspersed_args' is
+        false, stop at the first non-option argument.  If true, accumulate any
+        interspersed non-option arguments in 'largs'.
+        """
+        while rargs:
+            arg = rargs[0]
+            # We handle bare "--" explicitly, and bare "-" is handled by the
+            # standard arg handler since the short arg case ensures that the
+            # len of the opt string is greater than 1.
+            if arg == "--":
+                del rargs[0]
+                return
+            elif arg[0:2] == "--":
+                # process a single long option (possibly with value(s))
+                self._process_long_opt(rargs, values)
+            elif arg[:1] == "-" and len(arg) > 1:
+                # process a cluster of short options (possibly with
+                # value(s) for the last one only)
+                self._process_short_opts(rargs, values)
+            elif self.allow_interspersed_args:
+                largs.append(arg)
+                del rargs[0]
+            else:
+                return                  # stop now, leave this arg in rargs
+
+        # Say this is the original argument list:
+        # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)]
+        #                            ^
+        # (we are about to process arg(i)).
+        #
+        # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of
+        # [arg0, ..., arg(i-1)] (any options and their arguments will have
+        # been removed from largs).
+        #
+        # The while loop will usually consume 1 or more arguments per pass.
+        # If it consumes 1 (eg. arg is an option that takes no arguments),
+        # then after _process_arg() is done the situation is:
+        #
+        #   largs = subset of [arg0, ..., arg(i)]
+        #   rargs = [arg(i+1), ..., arg(N-1)]
+        #
+        # If allow_interspersed_args is false, largs will always be
+        # *empty* -- still a subset of [arg0, ..., arg(i-1)], but
+        # not a very interesting subset!
+
+    def _match_long_opt(self, opt):
+        """_match_long_opt(opt : string) -> string
+
+        Determine which long option string 'opt' matches, ie. which one
+        it is an unambiguous abbrevation for.  Raises BadOptionError if
+        'opt' doesn't unambiguously match any long option string.
+        """
+        return _match_abbrev(opt, self._long_opt)
+
+    def _process_long_opt(self, rargs, values):
+        arg = rargs.pop(0)
+
+        # Value explicitly attached to arg?  Pretend it's the next
+        # argument.
+        if "=" in arg:
+            (opt, next_arg) = arg.split("=", 1)
+            rargs.insert(0, next_arg)
+            had_explicit_value = True
+        else:
+            opt = arg
+            had_explicit_value = False
+
+        opt = self._match_long_opt(opt)
+        option = self._long_opt[opt]
+        if option.takes_value():
+            nargs = option.nargs
+            if len(rargs) < nargs:
+                if nargs == 1:
+                    self.error(_("%s option requires an argument") % opt)
+                else:
+                    self.error(_("%s option requires %d arguments")
+                               % (opt, nargs))
+            elif nargs == 1:
+                value = rargs.pop(0)
+            else:
+                value = tuple(rargs[0:nargs])
+                del rargs[0:nargs]
+
+        elif had_explicit_value:
+            self.error(_("%s option does not take a value") % opt)
+
+        else:
+            value = None
+
+        option.process(opt, value, values, self)
+
+    def _process_short_opts(self, rargs, values):
+        arg = rargs.pop(0)
+        stop = False
+        i = 1
+        for ch in arg[1:]:
+            opt = "-" + ch
+            option = self._short_opt.get(opt)
+            i += 1                      # we have consumed a character
+
+            if not option:
+                raise BadOptionError(opt)
+            if option.takes_value():
+                # Any characters left in arg?  Pretend they're the
+                # next arg, and stop consuming characters of arg.
+                if i < len(arg):
+                    rargs.insert(0, arg[i:])
+                    stop = True
+
+                nargs = option.nargs
+                if len(rargs) < nargs:
+                    if nargs == 1:
+                        self.error(_("%s option requires an argument") % opt)
+                    else:
+                        self.error(_("%s option requires %d arguments")
+                                   % (opt, nargs))
+                elif nargs == 1:
+                    value = rargs.pop(0)
+                else:
+                    value = tuple(rargs[0:nargs])
+                    del rargs[0:nargs]
+
+            else:                       # option doesn't take a value
+                value = None
+
+            option.process(opt, value, values, self)
+
+            if stop:
+                break
+
+
+    # -- Feedback methods ----------------------------------------------
+
+    def get_prog_name(self):
+        if self.prog is None:
+            return os.path.basename(sys.argv[0])
+        else:
+            return self.prog
+
+    def expand_prog_name(self, s):
+        return s.replace("%prog", self.get_prog_name())
+
+    def get_description(self):
+        return self.expand_prog_name(self.description)
+
+    def exit(self, status=0, msg=None):
+        if msg:
+            sys.stderr.write(msg)
+        sys.exit(status)
+
+    def error(self, msg):
+        """error(msg : string)
+
+        Print a usage message incorporating 'msg' to stderr and exit.
+        If you override this in a subclass, it should not return -- it
+        should either exit or raise an exception.
+        """
+        self.print_usage(sys.stderr)
+        self.exit(2, "%s: error: %s\n" % (self.get_prog_name(), msg))
+
+    def get_usage(self):
+        if self.usage:
+            return self.formatter.format_usage(
+                self.expand_prog_name(self.usage))
+        else:
+            return ""
+
+    def print_usage(self, file=None):
+        """print_usage(file : file = stdout)
+
+        Print the usage message for the current program (self.usage) to
+        'file' (default stdout).  Any occurrence of the string "%prog" in
+        self.usage is replaced with the name of the current program
+        (basename of sys.argv[0]).  Does nothing if self.usage is empty
+        or not defined.
+        """
+        if self.usage:
+            print >>file, self.get_usage()
+
+    def get_version(self):
+        if self.version:
+            return self.expand_prog_name(self.version)
+        else:
+            return ""
+
+    def print_version(self, file=None):
+        """print_version(file : file = stdout)
+
+        Print the version message for this program (self.version) to
+        'file' (default stdout).  As with print_usage(), any occurrence
+        of "%prog" in self.version is replaced by the current program's
+        name.  Does nothing if self.version is empty or undefined.
+        """
+        if self.version:
+            print >>file, self.get_version()
+
+    def format_option_help(self, formatter=None):
+        if formatter is None:
+            formatter = self.formatter
+        formatter.store_option_strings(self)
+        result = []
+        result.append(formatter.format_heading(_("Options")))
+        formatter.indent()
+        if self.option_list:
+            result.append(OptionContainer.format_option_help(self, formatter))
+            result.append("\n")
+        for group in self.option_groups:
+            result.append(group.format_help(formatter))
+            result.append("\n")
+        formatter.dedent()
+        # Drop the last "\n", or the header if no options or option groups:
+        return "".join(result[:-1])
+
+    def format_epilog(self, formatter):
+        return formatter.format_epilog(self.epilog)
+
+    def format_help(self, formatter=None):
+        if formatter is None:
+            formatter = self.formatter
+        result = []
+        if self.usage:
+            result.append(self.get_usage() + "\n")
+        if self.description:
+            result.append(self.format_description(formatter) + "\n")
+        result.append(self.format_option_help(formatter))
+        result.append(self.format_epilog(formatter))
+        return "".join(result)
+
+    # used by test suite
+    def _get_encoding(self, file):
+        encoding = getattr(file, "encoding", None)
+        if not encoding:
+            encoding = sys.getdefaultencoding()
+        return encoding
+
+    def print_help(self, file=None):
+        """print_help(file : file = stdout)
+
+        Print an extended help message, listing all options and any
+        help text provided with them, to 'file' (default stdout).
+        """
+        if file is None:
+            file = sys.stdout
+        encoding = self._get_encoding(file)
+        file.write(self.format_help().encode(encoding, "replace"))
+
+# class OptionParser
+
+
+def _match_abbrev(s, wordmap):
+    """_match_abbrev(s : string, wordmap : {string : Option}) -> string
+
+    Return the string key in 'wordmap' for which 's' is an unambiguous
+    abbreviation.  If 's' is found to be ambiguous or doesn't match any of
+    'words', raise BadOptionError.
+    """
+    # Is there an exact match?
+    if s in wordmap:
+        return s
+    else:
+        # Isolate all words with s as a prefix.
+        possibilities = [word for word in wordmap.keys()
+                         if word.startswith(s)]
+        # No exact match, so there had better be just one possibility.
+        if len(possibilities) == 1:
+            return possibilities[0]
+        elif not possibilities:
+            raise BadOptionError(s)
+        else:
+            # More than one possible completion: ambiguous prefix.
+            possibilities.sort()
+            raise AmbiguousOptionError(s, possibilities)
+
+
+# Some day, there might be many Option classes.  As of Optik 1.3, the
+# preferred way to instantiate Options is indirectly, via make_option(),
+# which will become a factory function when there are many Option
+# classes.
+make_option = Option
diff --git a/src/main/resources/PythonLibs/os.py b/src/main/resources/PythonLibs/os.py
new file mode 100644
index 0000000000000000000000000000000000000000..f2561e88d798fa6d5ea133052c3b949e47819956
--- /dev/null
+++ b/src/main/resources/PythonLibs/os.py
@@ -0,0 +1,721 @@
+r"""OS routines for Mac, NT, or Posix depending on what system we're on.
+
+This exports:
+  - all functions from posix, nt, os2, or ce, e.g. unlink, stat, etc.
+  - os.path is one of the modules posixpath, or ntpath
+  - os.name is 'posix', 'nt', 'os2', 'ce' or 'riscos'
+  - os.curdir is a string representing the current directory ('.' or ':')
+  - os.pardir is a string representing the parent directory ('..' or '::')
+  - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
+  - os.extsep is the extension separator ('.' or '/')
+  - os.altsep is the alternate pathname separator (None or '/')
+  - os.pathsep is the component separator used in $PATH etc
+  - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
+  - os.defpath is the default search path for executables
+  - os.devnull is the file path of the null device ('/dev/null', etc.)
+
+Programs that import and use 'os' stand a better chance of being
+portable between different platforms.  Of course, they must then
+only use functions that are defined by all platforms (e.g., unlink
+and opendir), and leave all pathname manipulation to os.path
+(e.g., split and join).
+"""
+
+#'
+
+import sys, errno
+
+_names = sys.builtin_module_names
+
+# Note:  more names are added to __all__ later.
+__all__ = ["altsep", "curdir", "pardir", "sep", "extsep", "pathsep", "linesep",
+           "defpath", "name", "path", "devnull",
+           "SEEK_SET", "SEEK_CUR", "SEEK_END"]
+
+def _get_exports_list(module):
+    try:
+        return list(module.__all__)
+    except AttributeError:
+        return [n for n in dir(module) if n[0] != '_']
+
+name = 'java'
+if 'posix' in _names:
+    _name = 'posix'
+    linesep = '\n'
+    from posix import *
+    try:
+        from posix import _exit
+    except ImportError:
+        pass
+    import posixpath as path
+
+    import posix
+    __all__.extend(_get_exports_list(posix))
+    del posix
+
+elif 'nt' in _names:
+    _name = 'nt'
+    linesep = '\r\n'
+    from nt import *
+    try:
+        from nt import _exit
+    except ImportError:
+        pass
+    import ntpath as path
+
+    import nt
+    __all__.extend(_get_exports_list(nt))
+    del nt
+
+elif 'os2' in _names:
+    _name = 'os2'
+    linesep = '\r\n'
+    from os2 import *
+    try:
+        from os2 import _exit
+    except ImportError:
+        pass
+    if sys.version.find('EMX GCC') == -1:
+        import ntpath as path
+    else:
+        import os2emxpath as path
+        from _emx_link import link
+
+    import os2
+    __all__.extend(_get_exports_list(os2))
+    del os2
+
+elif 'ce' in _names:
+    _name = 'ce'
+    linesep = '\r\n'
+    from ce import *
+    try:
+        from ce import _exit
+    except ImportError:
+        pass
+    # We can use the standard Windows path.
+    import ntpath as path
+
+    import ce
+    __all__.extend(_get_exports_list(ce))
+    del ce
+
+elif 'riscos' in _names:
+    _name = 'riscos'
+    linesep = '\n'
+    from riscos import *
+    try:
+        from riscos import _exit
+    except ImportError:
+        pass
+    import riscospath as path
+
+    import riscos
+    __all__.extend(_get_exports_list(riscos))
+    del riscos
+
+elif 'ibmi' in _names:
+    _name = 'ibmi'
+    linesep = '\n'
+    from ibmi import *
+    try:
+        from ibmi import _exit
+    except ImportError:
+        pass
+    import posixpath as path
+
+    import ibmi
+    __all__.extend(_get_exports_list(ibmi))
+    del ibmi
+
+else:
+    raise ImportError, 'no os specific module found'
+
+sys.modules['os.path'] = path
+from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
+    devnull)
+
+del _names
+
+# Python uses fixed values for the SEEK_ constants; they are mapped
+# to native constants if necessary in posixmodule.c
+SEEK_SET = 0
+SEEK_CUR = 1
+SEEK_END = 2
+
+#'
+
+# Super directory utilities.
+# (Inspired by Eric Raymond; the doc strings are mostly his)
+
+def makedirs(name, mode=0777):
+    """makedirs(path [, mode=0777])
+
+    Super-mkdir; create a leaf directory and all intermediate ones.
+    Works like mkdir, except that any intermediate path segment (not
+    just the rightmost) will be created if it does not exist.  This is
+    recursive.
+
+    """
+    head, tail = path.split(name)
+    if not tail:
+        head, tail = path.split(head)
+    if head and tail and not path.exists(head):
+        try:
+            makedirs(head, mode)
+        except OSError, e:
+            # be happy if someone already created the path
+            if e.errno != errno.EEXIST:
+                raise
+        if tail == curdir:           # xxx/newdir/. exists if xxx/newdir exists
+            return
+    mkdir(name, mode)
+
+def removedirs(name):
+    """removedirs(path)
+
+    Super-rmdir; remove a leaf directory and all empty intermediate
+    ones.  Works like rmdir except that, if the leaf directory is
+    successfully removed, directories corresponding to rightmost path
+    segments will be pruned away until either the whole path is
+    consumed or an error occurs.  Errors during this latter phase are
+    ignored -- they generally mean that a directory was not empty.
+
+    """
+    rmdir(name)
+    head, tail = path.split(name)
+    if not tail:
+        head, tail = path.split(head)
+    while head and tail:
+        try:
+            rmdir(head)
+        except error:
+            break
+        head, tail = path.split(head)
+
+def renames(old, new):
+    """renames(old, new)
+
+    Super-rename; create directories as necessary and delete any left
+    empty.  Works like rename, except creation of any intermediate
+    directories needed to make the new pathname good is attempted
+    first.  After the rename, directories corresponding to rightmost
+    path segments of the old name will be pruned way until either the
+    whole path is consumed or a nonempty directory is found.
+
+    Note: this function can fail with the new directory structure made
+    if you lack permissions needed to unlink the leaf directory or
+    file.
+
+    """
+    head, tail = path.split(new)
+    if head and tail and not path.exists(head):
+        makedirs(head)
+    rename(old, new)
+    head, tail = path.split(old)
+    if head and tail:
+        try:
+            removedirs(head)
+        except error:
+            pass
+
+__all__.extend(["makedirs", "removedirs", "renames"])
+
+def walk(top, topdown=True, onerror=None, followlinks=False):
+    """Directory tree generator.
+
+    For each directory in the directory tree rooted at top (including top
+    itself, but excluding '.' and '..'), yields a 3-tuple
+
+        dirpath, dirnames, filenames
+
+    dirpath is a string, the path to the directory.  dirnames is a list of
+    the names of the subdirectories in dirpath (excluding '.' and '..').
+    filenames is a list of the names of the non-directory files in dirpath.
+    Note that the names in the lists are just names, with no path components.
+    To get a full path (which begins with top) to a file or directory in
+    dirpath, do os.path.join(dirpath, name).
+
+    If optional arg 'topdown' is true or not specified, the triple for a
+    directory is generated before the triples for any of its subdirectories
+    (directories are generated top down).  If topdown is false, the triple
+    for a directory is generated after the triples for all of its
+    subdirectories (directories are generated bottom up).
+
+    When topdown is true, the caller can modify the dirnames list in-place
+    (e.g., via del or slice assignment), and walk will only recurse into the
+    subdirectories whose names remain in dirnames; this can be used to prune
+    the search, or to impose a specific order of visiting.  Modifying
+    dirnames when topdown is false is ineffective, since the directories in
+    dirnames have already been generated by the time dirnames itself is
+    generated.
+
+    By default errors from the os.listdir() call are ignored.  If
+    optional arg 'onerror' is specified, it should be a function; it
+    will be called with one argument, an os.error instance.  It can
+    report the error to continue with the walk, or raise the exception
+    to abort the walk.  Note that the filename is available as the
+    filename attribute of the exception object.
+
+    By default, os.walk does not follow symbolic links to subdirectories on
+    systems that support them.  In order to get this functionality, set the
+    optional argument 'followlinks' to true.
+
+    Caution:  if you pass a relative pathname for top, don't change the
+    current working directory between resumptions of walk.  walk never
+    changes the current directory, and assumes that the client doesn't
+    either.
+
+    Example:
+
+    import os
+    from os.path import join, getsize
+    for root, dirs, files in os.walk('python/Lib/email'):
+        print root, "consumes",
+        print sum([getsize(join(root, name)) for name in files]),
+        print "bytes in", len(files), "non-directory files"
+        if 'CVS' in dirs:
+            dirs.remove('CVS')  # don't visit CVS directories
+    """
+
+    from os.path import join, isdir, islink
+
+    # We may not have read permission for top, in which case we can't
+    # get a list of the files the directory contains.  os.path.walk
+    # always suppressed the exception then, rather than blow up for a
+    # minor reason when (say) a thousand readable directories are still
+    # left to visit.  That logic is copied here.
+    try:
+        # Note that listdir and error are globals in this module due
+        # to earlier import-*.
+        names = listdir(top)
+    except error, err:
+        if onerror is not None:
+            onerror(err)
+        return
+
+    dirs, nondirs = [], []
+    for name in names:
+        if isdir(join(top, name)):
+            dirs.append(name)
+        else:
+            nondirs.append(name)
+
+    if topdown:
+        yield top, dirs, nondirs
+    for name in dirs:
+        path = join(top, name)
+        if followlinks or not islink(path):
+            for x in walk(path, topdown, onerror, followlinks):
+                yield x
+    if not topdown:
+        yield top, dirs, nondirs
+
+__all__.append("walk")
+
+# Make sure os.environ exists, at least
+try:
+    environ
+except NameError:
+    environ = {}
+
+def _exists(name):
+    # CPython eval's the name, whereas looking in __all__ works for
+    # Jython and is much faster
+    return name in __all__
+
+if _exists('execv'):
+
+    def execl(file, *args):
+        """execl(file, *args)
+
+        Execute the executable file with argument list args, replacing the
+        current process. """
+        execv(file, args)
+
+    def execle(file, *args):
+        """execle(file, *args, env)
+
+        Execute the executable file with argument list args and
+        environment env, replacing the current process. """
+        env = args[-1]
+        execve(file, args[:-1], env)
+
+    def execlp(file, *args):
+        """execlp(file, *args)
+
+        Execute the executable file (which is searched for along $PATH)
+        with argument list args, replacing the current process. """
+        execvp(file, args)
+
+    def execlpe(file, *args):
+        """execlpe(file, *args, env)
+
+        Execute the executable file (which is searched for along $PATH)
+        with argument list args and environment env, replacing the current
+        process. """
+        env = args[-1]
+        execvpe(file, args[:-1], env)
+
+    def execvp(file, args):
+        """execp(file, args)
+
+        Execute the executable file (which is searched for along $PATH)
+        with argument list args, replacing the current process.
+        args may be a list or tuple of strings. """
+        _execvpe(file, args)
+
+    def execvpe(file, args, env):
+        """execvpe(file, args, env)
+
+        Execute the executable file (which is searched for along $PATH)
+        with argument list args and environment env , replacing the
+        current process.
+        args may be a list or tuple of strings. """
+        _execvpe(file, args, env)
+
+    __all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
+
+    def _execvpe(file, args, env=None):
+        if env is not None:
+            func = execve
+            argrest = (args, env)
+        else:
+            func = execv
+            argrest = (args,)
+            env = environ
+
+        head, tail = path.split(file)
+        if head:
+            func(file, *argrest)
+            return
+        if 'PATH' in env:
+            envpath = env['PATH']
+        else:
+            envpath = defpath
+        PATH = envpath.split(pathsep)
+        saved_exc = None
+        saved_tb = None
+        for dir in PATH:
+            fullname = path.join(dir, file)
+            try:
+                func(fullname, *argrest)
+            except error, e:
+                tb = sys.exc_info()[2]
+                if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR
+                    and saved_exc is None):
+                    saved_exc = e
+                    saved_tb = tb
+        if saved_exc:
+            raise error, saved_exc, saved_tb
+        raise error, e, tb
+
+# Change environ to automatically call putenv() if it exists
+try:
+    # This will fail if there's no putenv
+    putenv
+except NameError:
+    pass
+else:
+    # Fake unsetenv() for Windows
+    # not sure about os2 here but
+    # I'm guessing they are the same.
+
+    if name in ('os2', 'nt'):
+        def unsetenv(key):
+            putenv(key, "")
+
+    if _name == "riscos":
+        # On RISC OS, all env access goes through getenv and putenv
+        from riscosenviron import _Environ
+    elif _name in ('os2', 'nt'):  # Where Env Var Names Must Be UPPERCASE
+        import UserDict
+
+        # But we store them as upper case
+        class _Environ(UserDict.IterableUserDict):
+            def __init__(self, environ):
+                UserDict.UserDict.__init__(self)
+                data = self.data
+                for k, v in environ.items():
+                    data[k.upper()] = v
+            def __setitem__(self, key, item):
+                self.data[key.upper()] = item
+            def __getitem__(self, key):
+                return self.data[key.upper()]
+            def __delitem__(self, key):
+                del self.data[key.upper()]
+            def has_key(self, key):
+                return key.upper() in self.data
+            def __contains__(self, key):
+                return key.upper() in self.data
+            def get(self, key, failobj=None):
+                return self.data.get(key.upper(), failobj)
+            def update(self, dict=None, **kwargs):
+                if dict:
+                    try:
+                        keys = dict.keys()
+                    except AttributeError:
+                        # List of (key, value)
+                        for k, v in dict:
+                            self[k] = v
+                    else:
+                        # got keys
+                        # cannot use items(), since mappings
+                        # may not have them.
+                        for k in keys:
+                            self[k] = dict[k]
+                if kwargs:
+                    self.update(kwargs)
+            def copy(self):
+                return dict(self)
+
+        environ = _Environ(environ)
+
+def getenv(key, default=None):
+    """Get an environment variable, return None if it doesn't exist.
+    The optional second argument can specify an alternate default."""
+    return environ.get(key, default)
+__all__.append("getenv")
+
+# Supply spawn*() (probably only for Unix)
+if _exists("fork") and not _exists("spawnv") and _exists("execv"):
+
+    P_WAIT = 0
+    P_NOWAIT = P_NOWAITO = 1
+
+    # XXX Should we support P_DETACH?  I suppose it could fork()**2
+    # and close the std I/O streams.  Also, P_OVERLAY is the same
+    # as execv*()?
+
+    def _spawnvef(mode, file, args, env, func):
+        # Internal helper; func is the exec*() function to use
+        pid = fork()
+        if not pid:
+            # Child
+            try:
+                if env is None:
+                    func(file, args)
+                else:
+                    func(file, args, env)
+            except:
+                _exit(127)
+        else:
+            # Parent
+            if mode == P_NOWAIT:
+                return pid # Caller is responsible for waiting!
+            while 1:
+                wpid, sts = waitpid(pid, 0)
+                if WIFSTOPPED(sts):
+                    continue
+                elif WIFSIGNALED(sts):
+                    return -WTERMSIG(sts)
+                elif WIFEXITED(sts):
+                    return WEXITSTATUS(sts)
+                else:
+                    raise error, "Not stopped, signaled or exited???"
+
+    def spawnv(mode, file, args):
+        """spawnv(mode, file, args) -> integer
+
+Execute file with arguments from args in a subprocess.
+If mode == P_NOWAIT return the pid of the process.
+If mode == P_WAIT return the process's exit code if it exits normally;
+otherwise return -SIG, where SIG is the signal that killed it. """
+        return _spawnvef(mode, file, args, None, execv)
+
+    def spawnve(mode, file, args, env):
+        """spawnve(mode, file, args, env) -> integer
+
+Execute file with arguments from args in a subprocess with the
+specified environment.
+If mode == P_NOWAIT return the pid of the process.
+If mode == P_WAIT return the process's exit code if it exits normally;
+otherwise return -SIG, where SIG is the signal that killed it. """
+        return _spawnvef(mode, file, args, env, execve)
+
+    # Note: spawnvp[e] is't currently supported on Windows
+
+    def spawnvp(mode, file, args):
+        """spawnvp(mode, file, args) -> integer
+
+Execute file (which is looked for along $PATH) with arguments from
+args in a subprocess.
+If mode == P_NOWAIT return the pid of the process.
+If mode == P_WAIT return the process's exit code if it exits normally;
+otherwise return -SIG, where SIG is the signal that killed it. """
+        return _spawnvef(mode, file, args, None, execvp)
+
+    def spawnvpe(mode, file, args, env):
+        """spawnvpe(mode, file, args, env) -> integer
+
+Execute file (which is looked for along $PATH) with arguments from
+args in a subprocess with the supplied environment.
+If mode == P_NOWAIT return the pid of the process.
+If mode == P_WAIT return the process's exit code if it exits normally;
+otherwise return -SIG, where SIG is the signal that killed it. """
+        return _spawnvef(mode, file, args, env, execvpe)
+
+if _exists("spawnv"):
+    # These aren't supplied by the basic Windows code
+    # but can be easily implemented in Python
+
+    def spawnl(mode, file, *args):
+        """spawnl(mode, file, *args) -> integer
+
+Execute file with arguments from args in a subprocess.
+If mode == P_NOWAIT return the pid of the process.
+If mode == P_WAIT return the process's exit code if it exits normally;
+otherwise return -SIG, where SIG is the signal that killed it. """
+        return spawnv(mode, file, args)
+
+    def spawnle(mode, file, *args):
+        """spawnle(mode, file, *args, env) -> integer
+
+Execute file with arguments from args in a subprocess with the
+supplied environment.
+If mode == P_NOWAIT return the pid of the process.
+If mode == P_WAIT return the process's exit code if it exits normally;
+otherwise return -SIG, where SIG is the signal that killed it. """
+        env = args[-1]
+        return spawnve(mode, file, args[:-1], env)
+
+
+    __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",])
+
+
+if _exists("spawnvp"):
+    # At the moment, Windows doesn't implement spawnvp[e],
+    # so it won't have spawnlp[e] either.
+    def spawnlp(mode, file, *args):
+        """spawnlp(mode, file, *args) -> integer
+
+Execute file (which is looked for along $PATH) with arguments from
+args in a subprocess with the supplied environment.
+If mode == P_NOWAIT return the pid of the process.
+If mode == P_WAIT return the process's exit code if it exits normally;
+otherwise return -SIG, where SIG is the signal that killed it. """
+        return spawnvp(mode, file, args)
+
+    def spawnlpe(mode, file, *args):
+        """spawnlpe(mode, file, *args, env) -> integer
+
+Execute file (which is looked for along $PATH) with arguments from
+args in a subprocess with the supplied environment.
+If mode == P_NOWAIT return the pid of the process.
+If mode == P_WAIT return the process's exit code if it exits normally;
+otherwise return -SIG, where SIG is the signal that killed it. """
+        env = args[-1]
+        return spawnvpe(mode, file, args[:-1], env)
+
+
+    __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",])
+
+
+# Supply popen2 etc. (for Unix)
+if sys.platform.startswith('java') or _exists("fork"):
+    if not _exists("popen2"):
+        def popen2(cmd, mode="t", bufsize=-1):
+            """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
+            may be a sequence, in which case arguments will be passed directly to
+            the program without shell intervention (as with os.spawnv()).  If 'cmd'
+            is a string it will be passed to the shell (as with os.system()). If
+            'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
+            file objects (child_stdin, child_stdout) are returned."""
+            import subprocess
+            PIPE = subprocess.PIPE
+            p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
+                                 bufsize=bufsize, stdin=PIPE, stdout=PIPE,
+                                 close_fds=True)
+            return p.stdin, p.stdout
+        __all__.append("popen2")
+
+    if not _exists("popen3"):
+        def popen3(cmd, mode="t", bufsize=-1):
+            """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
+            may be a sequence, in which case arguments will be passed directly to
+            the program without shell intervention (as with os.spawnv()).  If 'cmd'
+            is a string it will be passed to the shell (as with os.system()). If
+            'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
+            file objects (child_stdin, child_stdout, child_stderr) are returned."""
+            import subprocess
+            PIPE = subprocess.PIPE
+            p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
+                                 bufsize=bufsize, stdin=PIPE, stdout=PIPE,
+                                 stderr=PIPE, close_fds=True)
+            return p.stdin, p.stdout, p.stderr
+        __all__.append("popen3")
+
+    if not _exists("popen4"):
+        def popen4(cmd, mode="t", bufsize=-1):
+            """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
+            may be a sequence, in which case arguments will be passed directly to
+            the program without shell intervention (as with os.spawnv()).  If 'cmd'
+            is a string it will be passed to the shell (as with os.system()). If
+            'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
+            file objects (child_stdin, child_stdout_stderr) are returned."""
+            import subprocess
+            PIPE = subprocess.PIPE
+            p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
+                                 bufsize=bufsize, stdin=PIPE, stdout=PIPE,
+                                 stderr=subprocess.STDOUT, close_fds=True)
+            return p.stdin, p.stdout
+        __all__.append("popen4")
+
+if not _exists("urandom"):
+    def urandom(n):
+        """urandom(n) -> str
+
+        Return a string of n random bytes suitable for cryptographic use.
+
+        """
+        try:
+            _urandomfd = open("/dev/urandom", O_RDONLY)
+        except (OSError, IOError):
+            raise NotImplementedError("/dev/urandom (or equivalent) not found")
+        bytes = ""
+        while len(bytes) < n:
+            bytes += read(_urandomfd, n - len(bytes))
+        close(_urandomfd)
+        return bytes
+
+# Supply os.popen()
+def popen(cmd, mode='r', bufsize=-1):
+    """popen(command [, mode='r' [, bufsize]]) -> pipe
+
+    Open a pipe to/from a command returning a file object.
+    """
+    if not isinstance(cmd, (str, unicode)):
+        raise TypeError('invalid cmd type (%s, expected string)' % type(cmd))
+    if mode not in ('r', 'w'):
+        raise ValueError("invalid mode %r" % mode)
+    import subprocess
+    if mode == 'r':
+        proc = subprocess.Popen(cmd, bufsize=bufsize, shell=True,
+                                stdout=subprocess.PIPE)
+        fp = proc.stdout
+    elif mode == 'w':
+        proc = subprocess.Popen(cmd, bufsize=bufsize, shell=True,
+                                stdin=subprocess.PIPE)
+        fp = proc.stdin
+    # files from subprocess are in binary mode but popen needs text mode
+    fp = fdopen(fp.fileno(), mode, bufsize)
+    return _wrap_close(fp, proc)
+
+# Helper for popen() -- a proxy for a file whose close waits for the process
+class _wrap_close(object):
+    def __init__(self, stream, proc):
+        self._stream = stream
+        self._proc = proc
+    def close(self):
+        self._stream.close()
+        returncode = self._proc.wait()
+        if returncode == 0:
+            return None
+        if _name == 'nt':
+            return returncode
+        else:
+            return returncode
+    def __getattr__(self, name):
+        return getattr(self._stream, name)
+    def __iter__(self):
+        return iter(self._stream)
diff --git a/src/main/resources/PythonLibs/pawt/__init__.py b/src/main/resources/PythonLibs/pawt/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..c621f40d4a5db67ddbf56ac9b7b2e1da3bcb1b4c
--- /dev/null
+++ b/src/main/resources/PythonLibs/pawt/__init__.py
@@ -0,0 +1,35 @@
+import sys
+from java import awt
+
+def test(panel, size=None, name='AWT Tester'):
+    f = awt.Frame(name, windowClosing=lambda event: sys.exit(0))
+    if hasattr(panel, 'init'):
+        panel.init()
+
+    f.add('Center', panel)
+    f.pack()
+    if size is not None:
+        f.setSize(apply(awt.Dimension, size))
+    f.setVisible(1)
+    return f
+
+class GridBag:
+    def __init__(self, frame, **defaults):
+        self.frame = frame
+        self.gridbag = awt.GridBagLayout()
+        self.defaults = defaults
+        frame.setLayout(self.gridbag)
+
+    def addRow(self, widget, **kw):
+        kw['gridwidth'] = 'REMAINDER'
+        apply(self.add, (widget, ), kw)
+
+    def add(self, widget, **kw):
+        constraints = awt.GridBagConstraints()
+
+        for key, value in self.defaults.items()+kw.items():
+            if isinstance(value, type('')):
+                value = getattr(awt.GridBagConstraints, value)
+            setattr(constraints, key, value)
+        self.gridbag.setConstraints(widget, constraints)
+        self.frame.add(widget)
diff --git a/src/main/resources/PythonLibs/pawt/colors.py b/src/main/resources/PythonLibs/pawt/colors.py
new file mode 100644
index 0000000000000000000000000000000000000000..a20948e046c20180ed67cdaa405b2f3292141662
--- /dev/null
+++ b/src/main/resources/PythonLibs/pawt/colors.py
@@ -0,0 +1,144 @@
+from java.awt import Color
+
+aliceblue = Color(240, 248, 255)
+antiquewhite = Color(250, 235, 215)
+aqua = Color(0, 255, 255)
+aquamarine = Color(127, 255, 212)
+azure = Color(240, 255, 255)
+beige = Color(245, 245, 220)
+bisque = Color(255, 228, 196)
+black = Color(0, 0, 0)
+blanchedalmond = Color(255, 235, 205)
+blue = Color(0, 0, 255)
+blueviolet = Color(138, 43, 226)
+brown = Color(165, 42, 42)
+burlywood = Color(222, 184, 135)
+cadetblue = Color(95, 158, 160)
+chartreuse = Color(127, 255, 0)
+chocolate = Color(210, 105, 30)
+coral = Color(255, 127, 80)
+cornflowerblue = Color(100, 149, 237)
+cornsilk = Color(255, 248, 220)
+crimson = Color(220, 20, 60)
+cyan = Color(0, 255, 255)
+darkblue = Color(0, 0, 139)
+darkcyan = Color(0, 139, 139)
+darkgoldenrod = Color(184, 134, 11)
+darkgray = Color(169, 169, 169)
+darkgreen = Color(0, 100, 0)
+darkkhaki = Color(189, 183, 107)
+darkmagenta = Color(139, 0, 139)
+darkolivegreen = Color(85, 107, 47)
+darkorange = Color(255, 140, 0)
+darkorchid = Color(153, 50, 204)
+darkred = Color(139, 0, 0)
+darksalmon = Color(233, 150, 122)
+darkseagreen = Color(143, 188, 143)
+darkslateblue = Color(72, 61, 139)
+darkslategray = Color(47, 79, 79)
+darkturquoise = Color(0, 206, 209)
+darkviolet = Color(148, 0, 211)
+deeppink = Color(255, 20, 147)
+deepskyblue = Color(0, 191, 255)
+dimgray = Color(105, 105, 105)
+dodgerblue = Color(30, 144, 255)
+firebrick = Color(178, 34, 34)
+floralwhite = Color(255, 250, 240)
+forestgreen = Color(34, 139, 34)
+fuchsia = Color(255, 0, 255)
+gainsboro = Color(220, 220, 220)
+ghostwhite = Color(248, 248, 255)
+gold = Color(255, 215, 0)
+goldenrod = Color(218, 165, 32)
+gray = Color(128, 128, 128)
+green = Color(0, 128, 0)
+greenyellow = Color(173, 255, 47)
+honeydew = Color(240, 255, 240)
+hotpink = Color(255, 105, 180)
+indianred = Color(205, 92, 92)
+indigo = Color(75, 0, 130)
+ivory = Color(255, 255, 240)
+khaki = Color(240, 230, 140)
+lavender = Color(230, 230, 250)
+lavenderblush = Color(255, 240, 245)
+lawngreen = Color(124, 252, 0)
+lemonchiffon = Color(255, 250, 205)
+lightblue = Color(173, 216, 230)
+lightcoral = Color(240, 128, 128)
+lightcyan = Color(224, 255, 255)
+lightgoldenrodyellow = Color(250, 250, 210)
+lightgreen = Color(144, 238, 144)
+lightgrey = Color(211, 211, 211)
+lightpink = Color(255, 182, 193)
+lightsalmon = Color(255, 160, 122)
+lightseagreen = Color(32, 178, 170)
+lightskyblue = Color(135, 206, 250)
+lightslategray = Color(119, 136, 153)
+lightsteelblue = Color(176, 196, 222)
+lightyellow = Color(255, 255, 224)
+lime = Color(0, 255, 0)
+limegreen = Color(50, 205, 50)
+linen = Color(250, 240, 230)
+magenta = Color(255, 0, 255)
+maroon = Color(128, 0, 0)
+mediumaquamarine = Color(102, 205, 170)
+mediumblue = Color(0, 0, 205)
+mediumorchid = Color(186, 85, 211)
+mediumpurple = Color(147, 112, 219)
+mediumseagreen = Color(60, 179, 113)
+mediumslateblue = Color(123, 104, 238)
+mediumspringgreen = Color(0, 250, 154)
+mediumturquoise = Color(72, 209, 204)
+mediumvioletred = Color(199, 21, 133)
+midnightblue = Color(25, 25, 112)
+mintcream = Color(245, 255, 250)
+mistyrose = Color(255, 228, 225)
+moccasin = Color(255, 228, 181)
+navajowhite = Color(255, 222, 173)
+navy = Color(0, 0, 128)
+oldlace = Color(253, 245, 230)
+olive = Color(128, 128, 0)
+olivedrab = Color(107, 142, 35)
+orange = Color(255, 165, 0)
+orangered = Color(255, 69, 0)
+orchid = Color(218, 112, 214)
+palegoldenrod = Color(238, 232, 170)
+palegreen = Color(152, 251, 152)
+paleturquoise = Color(175, 238, 238)
+palevioletred = Color(219, 112, 147)
+papayawhip = Color(255, 239, 213)
+peachpuff = Color(255, 218, 185)
+peru = Color(205, 133, 63)
+pink = Color(255, 192, 203)
+plum = Color(221, 160, 221)
+powderblue = Color(176, 224, 230)
+purple = Color(128, 0, 128)
+red = Color(255, 0, 0)
+rosybrown = Color(188, 143, 143)
+royalblue = Color(65, 105, 225)
+saddlebrown = Color(139, 69, 19)
+salmon = Color(250, 128, 114)
+sandybrown = Color(244, 164, 96)
+seagreen = Color(46, 139, 87)
+seashell = Color(255, 245, 238)
+sienna = Color(160, 82, 45)
+silver = Color(192, 192, 192)
+skyblue = Color(135, 206, 235)
+slateblue = Color(106, 90, 205)
+slategray = Color(112, 128, 144)
+snow = Color(255, 250, 250)
+springgreen = Color(0, 255, 127)
+steelblue = Color(70, 130, 180)
+tan = Color(210, 180, 140)
+teal = Color(0, 128, 128)
+thistle = Color(216, 191, 216)
+tomato = Color(255, 99, 71)
+turquoise = Color(64, 224, 208)
+violet = Color(238, 130, 238)
+wheat = Color(245, 222, 179)
+white = Color(255, 255, 255)
+whitesmoke = Color(245, 245, 245)
+yellow = Color(255, 255, 0)
+yellowgreen = Color(154, 205, 50)
+
+del Color
diff --git a/src/main/resources/PythonLibs/pawt/swing.py b/src/main/resources/PythonLibs/pawt/swing.py
new file mode 100644
index 0000000000000000000000000000000000000000..5c255df6a2a95c3d98bc15043a2deb19fbfa021b
--- /dev/null
+++ b/src/main/resources/PythonLibs/pawt/swing.py
@@ -0,0 +1,24 @@
+"""
+No longer needed, but keeping for backwards compatibility.
+"""
+from javax import swing
+import sys
+
+def test(panel, size=None, name='Swing Tester'):
+    f = swing.JFrame(name, windowClosing=lambda event: sys.exit(0))
+    if hasattr(panel, 'init'):
+        panel.init()
+
+    f.contentPane.add(panel)
+    f.pack()
+    if size is not None:
+        from java import awt
+        f.setSize(apply(awt.Dimension, size))
+    f.setVisible(1)
+    return f
+
+if swing is not None:
+    import pawt, sys
+    pawt.swing = swing
+    sys.modules['pawt.swing'] = swing
+    swing.__dict__['test'] = test
diff --git a/src/main/resources/PythonLibs/pdb.py b/src/main/resources/PythonLibs/pdb.py
new file mode 100644
index 0000000000000000000000000000000000000000..5468d3fcaff88c22d0be9d14e34f89c18a30a303
--- /dev/null
+++ b/src/main/resources/PythonLibs/pdb.py
@@ -0,0 +1,1338 @@
+#! /usr/bin/env python
+
+"""A Python debugger."""
+
+# (See pdb.doc for documentation.)
+
+import sys
+import linecache
+import cmd
+import bdb
+from repr import Repr
+import os
+import re
+import pprint
+import traceback
+
+
+class Restart(Exception):
+    """Causes a debugger to be restarted for the debugged python program."""
+    pass
+
+# Create a custom safe Repr instance and increase its maxstring.
+# The default of 30 truncates error messages too easily.
+_repr = Repr()
+_repr.maxstring = 200
+_saferepr = _repr.repr
+
+__all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace",
+           "post_mortem", "help"]
+
+def find_function(funcname, filename):
+    cre = re.compile(r'def\s+%s\s*[(]' % re.escape(funcname))
+    try:
+        fp = open(filename)
+    except IOError:
+        return None
+    # consumer of this info expects the first line to be 1
+    lineno = 1
+    answer = None
+    while 1:
+        line = fp.readline()
+        if line == '':
+            break
+        if cre.match(line):
+            answer = funcname, filename, lineno
+            break
+        lineno = lineno + 1
+    fp.close()
+    return answer
+
+
+# Interaction prompt line will separate file and call info from code
+# text using value of line_prefix string.  A newline and arrow may
+# be to your liking.  You can set it once pdb is imported using the
+# command "pdb.line_prefix = '\n% '".
+# line_prefix = ': '    # Use this to get the old situation back
+line_prefix = '\n-> '   # Probably a better default
+
+class Pdb(bdb.Bdb, cmd.Cmd):
+
+    def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None):
+        bdb.Bdb.__init__(self, skip=skip)
+        cmd.Cmd.__init__(self, completekey, stdin, stdout)
+        if stdout:
+            self.use_rawinput = 0
+        self.prompt = '(Pdb) '
+        self.aliases = {}
+        self.mainpyfile = ''
+        self._wait_for_mainpyfile = 0
+        # Try to load readline if it exists
+        try:
+            import readline
+        except ImportError:
+            pass
+
+        # Read $HOME/.pdbrc and ./.pdbrc
+        self.rcLines = []
+        if 'HOME' in os.environ:
+            envHome = os.environ['HOME']
+            try:
+                rcFile = open(os.path.join(envHome, ".pdbrc"))
+            except IOError:
+                pass
+            else:
+                for line in rcFile.readlines():
+                    self.rcLines.append(line)
+                rcFile.close()
+        try:
+            rcFile = open(".pdbrc")
+        except IOError:
+            pass
+        else:
+            for line in rcFile.readlines():
+                self.rcLines.append(line)
+            rcFile.close()
+
+        self.commands = {} # associates a command list to breakpoint numbers
+        self.commands_doprompt = {} # for each bp num, tells if the prompt
+                                    # must be disp. after execing the cmd list
+        self.commands_silent = {} # for each bp num, tells if the stack trace
+                                  # must be disp. after execing the cmd list
+        self.commands_defining = False # True while in the process of defining
+                                       # a command list
+        self.commands_bnum = None # The breakpoint number for which we are
+                                  # defining a list
+
+    def reset(self):
+        bdb.Bdb.reset(self)
+        self.forget()
+
+    def forget(self):
+        self.lineno = None
+        self.stack = []
+        self.curindex = 0
+        self.curframe = None
+
+    def setup(self, f, t):
+        self.forget()
+        self.stack, self.curindex = self.get_stack(f, t)
+        self.curframe = self.stack[self.curindex][0]
+        # The f_locals dictionary is updated from the actual frame
+        # locals whenever the .f_locals accessor is called, so we
+        # cache it here to ensure that modifications are not overwritten.
+        self.curframe_locals = self.curframe.f_locals
+        self.execRcLines()
+
+    # Can be executed earlier than 'setup' if desired
+    def execRcLines(self):
+        if self.rcLines:
+            # Make local copy because of recursion
+            rcLines = self.rcLines
+            # executed only once
+            self.rcLines = []
+            for line in rcLines:
+                line = line[:-1]
+                if len(line) > 0 and line[0] != '#':
+                    self.onecmd(line)
+
+    # Override Bdb methods
+
+    def user_call(self, frame, argument_list):
+        """This method is called when there is the remote possibility
+        that we ever need to stop in this function."""
+        if self._wait_for_mainpyfile:
+            return
+        if self.stop_here(frame):
+            print >>self.stdout, '--Call--'
+            self.interaction(frame, None)
+
+    def user_line(self, frame):
+        """This function is called when we stop or break at this line."""
+        if self._wait_for_mainpyfile:
+            if (self.mainpyfile != self.canonic(frame.f_code.co_filename)
+                or frame.f_lineno<= 0):
+                return
+            self._wait_for_mainpyfile = 0
+        if self.bp_commands(frame):
+            self.interaction(frame, None)
+
+    def bp_commands(self,frame):
+        """Call every command that was set for the current active breakpoint
+        (if there is one).
+
+        Returns True if the normal interaction function must be called,
+        False otherwise."""
+        # self.currentbp is set in bdb in Bdb.break_here if a breakpoint was hit
+        if getattr(self, "currentbp", False) and \
+               self.currentbp in self.commands:
+            currentbp = self.currentbp
+            self.currentbp = 0
+            lastcmd_back = self.lastcmd
+            self.setup(frame, None)
+            for line in self.commands[currentbp]:
+                self.onecmd(line)
+            self.lastcmd = lastcmd_back
+            if not self.commands_silent[currentbp]:
+                self.print_stack_entry(self.stack[self.curindex])
+            if self.commands_doprompt[currentbp]:
+                self.cmdloop()
+            self.forget()
+            return
+        return 1
+
+    def user_return(self, frame, return_value):
+        """This function is called when a return trap is set here."""
+        if self._wait_for_mainpyfile:
+            return
+        frame.f_locals['__return__'] = return_value
+        print >>self.stdout, '--Return--'
+        self.interaction(frame, None)
+
+    def user_exception(self, frame, exc_info):
+        """This function is called if an exception occurs,
+        but only if we are to stop at or just below this level."""
+        if self._wait_for_mainpyfile:
+            return
+        exc_type, exc_value, exc_traceback = exc_info
+        frame.f_locals['__exception__'] = exc_type, exc_value
+        if type(exc_type) == type(''):
+            exc_type_name = exc_type
+        else: exc_type_name = exc_type.__name__
+        print >>self.stdout, exc_type_name + ':', _saferepr(exc_value)
+        self.interaction(frame, exc_traceback)
+
+    # General interaction function
+
+    def interaction(self, frame, traceback):
+        self.setup(frame, traceback)
+        self.print_stack_entry(self.stack[self.curindex])
+        self.cmdloop()
+        self.forget()
+
+    def displayhook(self, obj):
+        """Custom displayhook for the exec in default(), which prevents
+        assignment of the _ variable in the builtins.
+        """
+        # reproduce the behavior of the standard displayhook, not printing None
+        if obj is not None:
+            print repr(obj)
+
+    def default(self, line):
+        if line[:1] == '!': line = line[1:]
+        locals = self.curframe_locals
+        globals = self.curframe.f_globals
+        try:
+            code = compile(line + '\n', '<stdin>', 'single')
+            save_stdout = sys.stdout
+            save_stdin = sys.stdin
+            save_displayhook = sys.displayhook
+            try:
+                sys.stdin = self.stdin
+                sys.stdout = self.stdout
+                sys.displayhook = self.displayhook
+                exec code in globals, locals
+            finally:
+                sys.stdout = save_stdout
+                sys.stdin = save_stdin
+                sys.displayhook = save_displayhook
+        except:
+            t, v = sys.exc_info()[:2]
+            if type(t) == type(''):
+                exc_type_name = t
+            else: exc_type_name = t.__name__
+            print >>self.stdout, '***', exc_type_name + ':', v
+
+    def precmd(self, line):
+        """Handle alias expansion and ';;' separator."""
+        if not line.strip():
+            return line
+        args = line.split()
+        while args[0] in self.aliases:
+            line = self.aliases[args[0]]
+            ii = 1
+            for tmpArg in args[1:]:
+                line = line.replace("%" + str(ii),
+                                      tmpArg)
+                ii = ii + 1
+            line = line.replace("%*", ' '.join(args[1:]))
+            args = line.split()
+        # split into ';;' separated commands
+        # unless it's an alias command
+        if args[0] != 'alias':
+            marker = line.find(';;')
+            if marker >= 0:
+                # queue up everything after marker
+                next = line[marker+2:].lstrip()
+                self.cmdqueue.append(next)
+                line = line[:marker].rstrip()
+        return line
+
+    def onecmd(self, line):
+        """Interpret the argument as though it had been typed in response
+        to the prompt.
+
+        Checks whether this line is typed at the normal prompt or in
+        a breakpoint command list definition.
+        """
+        if not self.commands_defining:
+            return cmd.Cmd.onecmd(self, line)
+        else:
+            return self.handle_command_def(line)
+
+    def handle_command_def(self,line):
+        """Handles one command line during command list definition."""
+        cmd, arg, line = self.parseline(line)
+        if not cmd:
+            return
+        if cmd == 'silent':
+            self.commands_silent[self.commands_bnum] = True
+            return # continue to handle other cmd def in the cmd list
+        elif cmd == 'end':
+            self.cmdqueue = []
+            return 1 # end of cmd list
+        cmdlist = self.commands[self.commands_bnum]
+        if arg:
+            cmdlist.append(cmd+' '+arg)
+        else:
+            cmdlist.append(cmd)
+        # Determine if we must stop
+        try:
+            func = getattr(self, 'do_' + cmd)
+        except AttributeError:
+            func = self.default
+        # one of the resuming commands
+        if func.func_name in self.commands_resuming:
+            self.commands_doprompt[self.commands_bnum] = False
+            self.cmdqueue = []
+            return 1
+        return
+
+    # Command definitions, called by cmdloop()
+    # The argument is the remaining string on the command line
+    # Return true to exit from the command loop
+
+    do_h = cmd.Cmd.do_help
+
+    def do_commands(self, arg):
+        """Defines a list of commands associated to a breakpoint.
+
+        Those commands will be executed whenever the breakpoint causes
+        the program to stop execution."""
+        if not arg:
+            bnum = len(bdb.Breakpoint.bpbynumber)-1
+        else:
+            try:
+                bnum = int(arg)
+            except:
+                print >>self.stdout, "Usage : commands [bnum]\n        ..." \
+                                     "\n        end"
+                return
+        self.commands_bnum = bnum
+        self.commands[bnum] = []
+        self.commands_doprompt[bnum] = True
+        self.commands_silent[bnum] = False
+        prompt_back = self.prompt
+        self.prompt = '(com) '
+        self.commands_defining = True
+        try:
+            self.cmdloop()
+        finally:
+            self.commands_defining = False
+            self.prompt = prompt_back
+
+    def do_break(self, arg, temporary = 0):
+        # break [ ([filename:]lineno | function) [, "condition"] ]
+        if not arg:
+            if self.breaks:  # There's at least one
+                print >>self.stdout, "Num Type         Disp Enb   Where"
+                for bp in bdb.Breakpoint.bpbynumber:
+                    if bp:
+                        bp.bpprint(self.stdout)
+            return
+        # parse arguments; comma has lowest precedence
+        # and cannot occur in filename
+        filename = None
+        lineno = None
+        cond = None
+        comma = arg.find(',')
+        if comma > 0:
+            # parse stuff after comma: "condition"
+            cond = arg[comma+1:].lstrip()
+            arg = arg[:comma].rstrip()
+        # parse stuff before comma: [filename:]lineno | function
+        colon = arg.rfind(':')
+        funcname = None
+        if colon >= 0:
+            filename = arg[:colon].rstrip()
+            f = self.lookupmodule(filename)
+            if not f:
+                print >>self.stdout, '*** ', repr(filename),
+                print >>self.stdout, 'not found from sys.path'
+                return
+            else:
+                filename = f
+            arg = arg[colon+1:].lstrip()
+            try:
+                lineno = int(arg)
+            except ValueError, msg:
+                print >>self.stdout, '*** Bad lineno:', arg
+                return
+        else:
+            # no colon; can be lineno or function
+            try:
+                lineno = int(arg)
+            except ValueError:
+                try:
+                    func = eval(arg,
+                                self.curframe.f_globals,
+                                self.curframe_locals)
+                except:
+                    func = arg
+                try:
+                    if hasattr(func, 'im_func'):
+                        func = func.im_func
+                    code = func.func_code
+                    #use co_name to identify the bkpt (function names
+                    #could be aliased, but co_name is invariant)
+                    funcname = code.co_name
+                    lineno = code.co_firstlineno
+                    filename = code.co_filename
+                except:
+                    # last thing to try
+                    (ok, filename, ln) = self.lineinfo(arg)
+                    if not ok:
+                        print >>self.stdout, '*** The specified object',
+                        print >>self.stdout, repr(arg),
+                        print >>self.stdout, 'is not a function'
+                        print >>self.stdout, 'or was not found along sys.path.'
+                        return
+                    funcname = ok # ok contains a function name
+                    lineno = int(ln)
+        if not filename:
+            filename = self.defaultFile()
+        # Check for reasonable breakpoint
+        line = self.checkline(filename, lineno)
+        if line:
+            # now set the break point
+            err = self.set_break(filename, line, temporary, cond, funcname)
+            if err: print >>self.stdout, '***', err
+            else:
+                bp = self.get_breaks(filename, line)[-1]
+                print >>self.stdout, "Breakpoint %d at %s:%d" % (bp.number,
+                                                                 bp.file,
+                                                                 bp.line)
+
+    # To be overridden in derived debuggers
+    def defaultFile(self):
+        """Produce a reasonable default."""
+        filename = self.curframe.f_code.co_filename
+        if filename == '<string>' and self.mainpyfile:
+            filename = self.mainpyfile
+        return filename
+
+    do_b = do_break
+
+    def do_tbreak(self, arg):
+        self.do_break(arg, 1)
+
+    def lineinfo(self, identifier):
+        failed = (None, None, None)
+        # Input is identifier, may be in single quotes
+        idstring = identifier.split("'")
+        if len(idstring) == 1:
+            # not in single quotes
+            id = idstring[0].strip()
+        elif len(idstring) == 3:
+            # quoted
+            id = idstring[1].strip()
+        else:
+            return failed
+        if id == '': return failed
+        parts = id.split('.')
+        # Protection for derived debuggers
+        if parts[0] == 'self':
+            del parts[0]
+            if len(parts) == 0:
+                return failed
+        # Best first guess at file to look at
+        fname = self.defaultFile()
+        if len(parts) == 1:
+            item = parts[0]
+        else:
+            # More than one part.
+            # First is module, second is method/class
+            f = self.lookupmodule(parts[0])
+            if f:
+                fname = f
+            item = parts[1]
+        answer = find_function(item, fname)
+        return answer or failed
+
+    def checkline(self, filename, lineno):
+        """Check whether specified line seems to be executable.
+
+        Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
+        line or EOF). Warning: testing is not comprehensive.
+        """
+        # this method should be callable before starting debugging, so default
+        # to "no globals" if there is no current frame
+        globs = self.curframe.f_globals if hasattr(self, 'curframe') else None
+        line = linecache.getline(filename, lineno, globs)
+        if not line:
+            print >>self.stdout, 'End of file'
+            return 0
+        line = line.strip()
+        # Don't allow setting breakpoint at a blank line
+        if (not line or (line[0] == '#') or
+             (line[:3] == '"""') or line[:3] == "'''"):
+            print >>self.stdout, '*** Blank or comment'
+            return 0
+        return lineno
+
+    def do_enable(self, arg):
+        args = arg.split()
+        for i in args:
+            try:
+                i = int(i)
+            except ValueError:
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
+                continue
+
+            if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
+                print >>self.stdout, 'No breakpoint numbered', i
+                continue
+
+            bp = bdb.Breakpoint.bpbynumber[i]
+            if bp:
+                bp.enable()
+
+    def do_disable(self, arg):
+        args = arg.split()
+        for i in args:
+            try:
+                i = int(i)
+            except ValueError:
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
+                continue
+
+            if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
+                print >>self.stdout, 'No breakpoint numbered', i
+                continue
+
+            bp = bdb.Breakpoint.bpbynumber[i]
+            if bp:
+                bp.disable()
+
+    def do_condition(self, arg):
+        # arg is breakpoint number and condition
+        args = arg.split(' ', 1)
+        try:
+            bpnum = int(args[0].strip())
+        except ValueError:
+            # something went wrong
+            print >>self.stdout, \
+                'Breakpoint index %r is not a number' % args[0]
+            return
+        try:
+            cond = args[1]
+        except:
+            cond = None
+        try:
+            bp = bdb.Breakpoint.bpbynumber[bpnum]
+        except IndexError:
+            print >>self.stdout, 'Breakpoint index %r is not valid' % args[0]
+            return
+        if bp:
+            bp.cond = cond
+            if not cond:
+                print >>self.stdout, 'Breakpoint', bpnum,
+                print >>self.stdout, 'is now unconditional.'
+
+    def do_ignore(self,arg):
+        """arg is bp number followed by ignore count."""
+        args = arg.split()
+        try:
+            bpnum = int(args[0].strip())
+        except ValueError:
+            # something went wrong
+            print >>self.stdout, \
+                'Breakpoint index %r is not a number' % args[0]
+            return
+        try:
+            count = int(args[1].strip())
+        except:
+            count = 0
+        try:
+            bp = bdb.Breakpoint.bpbynumber[bpnum]
+        except IndexError:
+            print >>self.stdout, 'Breakpoint index %r is not valid' % args[0]
+            return
+        if bp:
+            bp.ignore = count
+            if count > 0:
+                reply = 'Will ignore next '
+                if count > 1:
+                    reply = reply + '%d crossings' % count
+                else:
+                    reply = reply + '1 crossing'
+                print >>self.stdout, reply + ' of breakpoint %d.' % bpnum
+            else:
+                print >>self.stdout, 'Will stop next time breakpoint',
+                print >>self.stdout, bpnum, 'is reached.'
+
+    def do_clear(self, arg):
+        """Three possibilities, tried in this order:
+        clear -> clear all breaks, ask for confirmation
+        clear file:lineno -> clear all breaks at file:lineno
+        clear bpno bpno ... -> clear breakpoints by number"""
+        if not arg:
+            try:
+                reply = raw_input('Clear all breaks? ')
+            except EOFError:
+                reply = 'no'
+            reply = reply.strip().lower()
+            if reply in ('y', 'yes'):
+                self.clear_all_breaks()
+            return
+        if ':' in arg:
+            # Make sure it works for "clear C:\foo\bar.py:12"
+            i = arg.rfind(':')
+            filename = arg[:i]
+            arg = arg[i+1:]
+            try:
+                lineno = int(arg)
+            except ValueError:
+                err = "Invalid line number (%s)" % arg
+            else:
+                err = self.clear_break(filename, lineno)
+            if err: print >>self.stdout, '***', err
+            return
+        numberlist = arg.split()
+        for i in numberlist:
+            try:
+                i = int(i)
+            except ValueError:
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
+                continue
+
+            if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
+                print >>self.stdout, 'No breakpoint numbered', i
+                continue
+            err = self.clear_bpbynumber(i)
+            if err:
+                print >>self.stdout, '***', err
+            else:
+                print >>self.stdout, 'Deleted breakpoint', i
+    do_cl = do_clear # 'c' is already an abbreviation for 'continue'
+
+    def do_where(self, arg):
+        self.print_stack_trace()
+    do_w = do_where
+    do_bt = do_where
+
+    def do_up(self, arg):
+        if self.curindex == 0:
+            print >>self.stdout, '*** Oldest frame'
+        else:
+            self.curindex = self.curindex - 1
+            self.curframe = self.stack[self.curindex][0]
+            self.curframe_locals = self.curframe.f_locals
+            self.print_stack_entry(self.stack[self.curindex])
+            self.lineno = None
+    do_u = do_up
+
+    def do_down(self, arg):
+        if self.curindex + 1 == len(self.stack):
+            print >>self.stdout, '*** Newest frame'
+        else:
+            self.curindex = self.curindex + 1
+            self.curframe = self.stack[self.curindex][0]
+            self.curframe_locals = self.curframe.f_locals
+            self.print_stack_entry(self.stack[self.curindex])
+            self.lineno = None
+    do_d = do_down
+
+    def do_until(self, arg):
+        self.set_until(self.curframe)
+        return 1
+    do_unt = do_until
+
+    def do_step(self, arg):
+        self.set_step()
+        return 1
+    do_s = do_step
+
+    def do_next(self, arg):
+        self.set_next(self.curframe)
+        return 1
+    do_n = do_next
+
+    def do_run(self, arg):
+        """Restart program by raising an exception to be caught in the main
+        debugger loop.  If arguments were given, set them in sys.argv."""
+        if arg:
+            import shlex
+            argv0 = sys.argv[0:1]
+            sys.argv = shlex.split(arg)
+            sys.argv[:0] = argv0
+        raise Restart
+
+    do_restart = do_run
+
+    def do_return(self, arg):
+        self.set_return(self.curframe)
+        return 1
+    do_r = do_return
+
+    def do_continue(self, arg):
+        self.set_continue()
+        return 1
+    do_c = do_cont = do_continue
+
+    def do_jump(self, arg):
+        if self.curindex + 1 != len(self.stack):
+            print >>self.stdout, "*** You can only jump within the bottom frame"
+            return
+        try:
+            arg = int(arg)
+        except ValueError:
+            print >>self.stdout, "*** The 'jump' command requires a line number."
+        else:
+            try:
+                # Do the jump, fix up our copy of the stack, and display the
+                # new position
+                self.curframe.f_lineno = arg
+                self.stack[self.curindex] = self.stack[self.curindex][0], arg
+                self.print_stack_entry(self.stack[self.curindex])
+            except ValueError, e:
+                print >>self.stdout, '*** Jump failed:', e
+    do_j = do_jump
+
+    def do_debug(self, arg):
+        sys.settrace(None)
+        globals = self.curframe.f_globals
+        locals = self.curframe_locals
+        p = Pdb(self.completekey, self.stdin, self.stdout)
+        p.prompt = "(%s) " % self.prompt.strip()
+        print >>self.stdout, "ENTERING RECURSIVE DEBUGGER"
+        sys.call_tracing(p.run, (arg, globals, locals))
+        print >>self.stdout, "LEAVING RECURSIVE DEBUGGER"
+        sys.settrace(self.trace_dispatch)
+        self.lastcmd = p.lastcmd
+
+    def do_quit(self, arg):
+        self._user_requested_quit = 1
+        self.set_quit()
+        return 1
+
+    do_q = do_quit
+    do_exit = do_quit
+
+    def do_EOF(self, arg):
+        print >>self.stdout
+        self._user_requested_quit = 1
+        self.set_quit()
+        return 1
+
+    def do_args(self, arg):
+        co = self.curframe.f_code
+        dict = self.curframe_locals
+        n = co.co_argcount
+        if co.co_flags & 4: n = n+1
+        if co.co_flags & 8: n = n+1
+        for i in range(n):
+            name = co.co_varnames[i]
+            print >>self.stdout, name, '=',
+            if name in dict: print >>self.stdout, dict[name]
+            else: print >>self.stdout, "*** undefined ***"
+    do_a = do_args
+
+    def do_retval(self, arg):
+        if '__return__' in self.curframe_locals:
+            print >>self.stdout, self.curframe_locals['__return__']
+        else:
+            print >>self.stdout, '*** Not yet returned!'
+    do_rv = do_retval
+
+    def _getval(self, arg):
+        try:
+            return eval(arg, self.curframe.f_globals,
+                        self.curframe_locals)
+        except:
+            t, v = sys.exc_info()[:2]
+            if isinstance(t, str):
+                exc_type_name = t
+            else: exc_type_name = t.__name__
+            print >>self.stdout, '***', exc_type_name + ':', repr(v)
+            raise
+
+    def do_p(self, arg):
+        try:
+            print >>self.stdout, repr(self._getval(arg))
+        except:
+            pass
+
+    def do_pp(self, arg):
+        try:
+            pprint.pprint(self._getval(arg), self.stdout)
+        except:
+            pass
+
+    def do_list(self, arg):
+        self.lastcmd = 'list'
+        last = None
+        if arg:
+            try:
+                x = eval(arg, {}, {})
+                if type(x) == type(()):
+                    first, last = x
+                    first = int(first)
+                    last = int(last)
+                    if last < first:
+                        # Assume it's a count
+                        last = first + last
+                else:
+                    first = max(1, int(x) - 5)
+            except:
+                print >>self.stdout, '*** Error in argument:', repr(arg)
+                return
+        elif self.lineno is None:
+            first = max(1, self.curframe.f_lineno - 5)
+        else:
+            first = self.lineno + 1
+        if last is None:
+            last = first + 10
+        filename = self.curframe.f_code.co_filename
+        breaklist = self.get_file_breaks(filename)
+        try:
+            for lineno in range(first, last+1):
+                line = linecache.getline(filename, lineno,
+                                         self.curframe.f_globals)
+                if not line:
+                    print >>self.stdout, '[EOF]'
+                    break
+                else:
+                    s = repr(lineno).rjust(3)
+                    if len(s) < 4: s = s + ' '
+                    if lineno in breaklist: s = s + 'B'
+                    else: s = s + ' '
+                    if lineno == self.curframe.f_lineno:
+                        s = s + '->'
+                    print >>self.stdout, s + '\t' + line,
+                    self.lineno = lineno
+        except KeyboardInterrupt:
+            pass
+    do_l = do_list
+
+    def do_whatis(self, arg):
+        try:
+            value = eval(arg, self.curframe.f_globals,
+                            self.curframe_locals)
+        except:
+            t, v = sys.exc_info()[:2]
+            if type(t) == type(''):
+                exc_type_name = t
+            else: exc_type_name = t.__name__
+            print >>self.stdout, '***', exc_type_name + ':', repr(v)
+            return
+        code = None
+        # Is it a function?
+        try: code = value.func_code
+        except: pass
+        if code:
+            print >>self.stdout, 'Function', code.co_name
+            return
+        # Is it an instance method?
+        try: code = value.im_func.func_code
+        except: pass
+        if code:
+            print >>self.stdout, 'Method', code.co_name
+            return
+        # None of the above...
+        print >>self.stdout, type(value)
+
+    def do_alias(self, arg):
+        args = arg.split()
+        if len(args) == 0:
+            keys = self.aliases.keys()
+            keys.sort()
+            for alias in keys:
+                print >>self.stdout, "%s = %s" % (alias, self.aliases[alias])
+            return
+        if args[0] in self.aliases and len(args) == 1:
+            print >>self.stdout, "%s = %s" % (args[0], self.aliases[args[0]])
+        else:
+            self.aliases[args[0]] = ' '.join(args[1:])
+
+    def do_unalias(self, arg):
+        args = arg.split()
+        if len(args) == 0: return
+        if args[0] in self.aliases:
+            del self.aliases[args[0]]
+
+    #list of all the commands making the program resume execution.
+    commands_resuming = ['do_continue', 'do_step', 'do_next', 'do_return',
+                         'do_quit', 'do_jump']
+
+    # Print a traceback starting at the top stack frame.
+    # The most recently entered frame is printed last;
+    # this is different from dbx and gdb, but consistent with
+    # the Python interpreter's stack trace.
+    # It is also consistent with the up/down commands (which are
+    # compatible with dbx and gdb: up moves towards 'main()'
+    # and down moves towards the most recent stack frame).
+
+    def print_stack_trace(self):
+        try:
+            for frame_lineno in self.stack:
+                self.print_stack_entry(frame_lineno)
+        except KeyboardInterrupt:
+            pass
+
+    def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix):
+        frame, lineno = frame_lineno
+        if frame is self.curframe:
+            print >>self.stdout, '>',
+        else:
+            print >>self.stdout, ' ',
+        print >>self.stdout, self.format_stack_entry(frame_lineno,
+                                                     prompt_prefix)
+
+
+    # Help methods (derived from pdb.doc)
+
+    def help_help(self):
+        self.help_h()
+
+    def help_h(self):
+        print >>self.stdout, """h(elp)
+Without argument, print the list of available commands.
+With a command name as argument, print help about that command
+"help pdb" pipes the full documentation file to the $PAGER
+"help exec" gives help on the ! command"""
+
+    def help_where(self):
+        self.help_w()
+
+    def help_w(self):
+        print >>self.stdout, """w(here)
+Print a stack trace, with the most recent frame at the bottom.
+An arrow indicates the "current frame", which determines the
+context of most commands.  'bt' is an alias for this command."""
+
+    help_bt = help_w
+
+    def help_down(self):
+        self.help_d()
+
+    def help_d(self):
+        print >>self.stdout, """d(own)
+Move the current frame one level down in the stack trace
+(to a newer frame)."""
+
+    def help_up(self):
+        self.help_u()
+
+    def help_u(self):
+        print >>self.stdout, """u(p)
+Move the current frame one level up in the stack trace
+(to an older frame)."""
+
+    def help_break(self):
+        self.help_b()
+
+    def help_b(self):
+        print >>self.stdout, """b(reak) ([file:]lineno | function) [, condition]
+With a line number argument, set a break there in the current
+file.  With a function name, set a break at first executable line
+of that function.  Without argument, list all breaks.  If a second
+argument is present, it is a string specifying an expression
+which must evaluate to true before the breakpoint is honored.
+
+The line number may be prefixed with a filename and a colon,
+to specify a breakpoint in another file (probably one that
+hasn't been loaded yet).  The file is searched for on sys.path;
+the .py suffix may be omitted."""
+
+    def help_clear(self):
+        self.help_cl()
+
+    def help_cl(self):
+        print >>self.stdout, "cl(ear) filename:lineno"
+        print >>self.stdout, """cl(ear) [bpnumber [bpnumber...]]
+With a space separated list of breakpoint numbers, clear
+those breakpoints.  Without argument, clear all breaks (but
+first ask confirmation).  With a filename:lineno argument,
+clear all breaks at that line in that file.
+
+Note that the argument is different from previous versions of
+the debugger (in python distributions 1.5.1 and before) where
+a linenumber was used instead of either filename:lineno or
+breakpoint numbers."""
+
+    def help_tbreak(self):
+        print >>self.stdout, """tbreak  same arguments as break, but breakpoint
+is removed when first hit."""
+
+    def help_enable(self):
+        print >>self.stdout, """enable bpnumber [bpnumber ...]
+Enables the breakpoints given as a space separated list of
+bp numbers."""
+
+    def help_disable(self):
+        print >>self.stdout, """disable bpnumber [bpnumber ...]
+Disables the breakpoints given as a space separated list of
+bp numbers."""
+
+    def help_ignore(self):
+        print >>self.stdout, """ignore bpnumber count
+Sets the ignore count for the given breakpoint number.  A breakpoint
+becomes active when the ignore count is zero.  When non-zero, the
+count is decremented each time the breakpoint is reached and the
+breakpoint is not disabled and any associated condition evaluates
+to true."""
+
+    def help_condition(self):
+        print >>self.stdout, """condition bpnumber str_condition
+str_condition is a string specifying an expression which
+must evaluate to true before the breakpoint is honored.
+If str_condition is absent, any existing condition is removed;
+i.e., the breakpoint is made unconditional."""
+
+    def help_step(self):
+        self.help_s()
+
+    def help_s(self):
+        print >>self.stdout, """s(tep)
+Execute the current line, stop at the first possible occasion
+(either in a function that is called or in the current function)."""
+
+    def help_until(self):
+        self.help_unt()
+
+    def help_unt(self):
+        print """unt(il)
+Continue execution until the line with a number greater than the current
+one is reached or until the current frame returns"""
+
+    def help_next(self):
+        self.help_n()
+
+    def help_n(self):
+        print >>self.stdout, """n(ext)
+Continue execution until the next line in the current function
+is reached or it returns."""
+
+    def help_return(self):
+        self.help_r()
+
+    def help_r(self):
+        print >>self.stdout, """r(eturn)
+Continue execution until the current function returns."""
+
+    def help_continue(self):
+        self.help_c()
+
+    def help_cont(self):
+        self.help_c()
+
+    def help_c(self):
+        print >>self.stdout, """c(ont(inue))
+Continue execution, only stop when a breakpoint is encountered."""
+
+    def help_jump(self):
+        self.help_j()
+
+    def help_j(self):
+        print >>self.stdout, """j(ump) lineno
+Set the next line that will be executed."""
+
+    def help_debug(self):
+        print >>self.stdout, """debug code
+Enter a recursive debugger that steps through the code argument
+(which is an arbitrary expression or statement to be executed
+in the current environment)."""
+
+    def help_list(self):
+        self.help_l()
+
+    def help_l(self):
+        print >>self.stdout, """l(ist) [first [,last]]
+List source code for the current file.
+Without arguments, list 11 lines around the current line
+or continue the previous listing.
+With one argument, list 11 lines starting at that line.
+With two arguments, list the given range;
+if the second argument is less than the first, it is a count."""
+
+    def help_args(self):
+        self.help_a()
+
+    def help_a(self):
+        print >>self.stdout, """a(rgs)
+Print the arguments of the current function."""
+
+    def help_p(self):
+        print >>self.stdout, """p expression
+Print the value of the expression."""
+
+    def help_pp(self):
+        print >>self.stdout, """pp expression
+Pretty-print the value of the expression."""
+
+    def help_exec(self):
+        print >>self.stdout, """(!) statement
+Execute the (one-line) statement in the context of
+the current stack frame.
+The exclamation point can be omitted unless the first word
+of the statement resembles a debugger command.
+To assign to a global variable you must always prefix the
+command with a 'global' command, e.g.:
+(Pdb) global list_options; list_options = ['-l']
+(Pdb)"""
+
+    def help_run(self):
+        print """run [args...]
+Restart the debugged python program. If a string is supplied, it is
+splitted with "shlex" and the result is used as the new sys.argv.
+History, breakpoints, actions and debugger options are preserved.
+"restart" is an alias for "run"."""
+
+    help_restart = help_run
+
+    def help_quit(self):
+        self.help_q()
+
+    def help_q(self):
+        print >>self.stdout, """q(uit) or exit - Quit from the debugger.
+The program being executed is aborted."""
+
+    help_exit = help_q
+
+    def help_whatis(self):
+        print >>self.stdout, """whatis arg
+Prints the type of the argument."""
+
+    def help_EOF(self):
+        print >>self.stdout, """EOF
+Handles the receipt of EOF as a command."""
+
+    def help_alias(self):
+        print >>self.stdout, """alias [name [command [parameter parameter ...]]]
+Creates an alias called 'name' the executes 'command'.  The command
+must *not* be enclosed in quotes.  Replaceable parameters are
+indicated by %1, %2, and so on, while %* is replaced by all the
+parameters.  If no command is given, the current alias for name
+is shown. If no name is given, all aliases are listed.
+
+Aliases may be nested and can contain anything that can be
+legally typed at the pdb prompt.  Note!  You *can* override
+internal pdb commands with aliases!  Those internal commands
+are then hidden until the alias is removed.  Aliasing is recursively
+applied to the first word of the command line; all other words
+in the line are left alone.
+
+Some useful aliases (especially when placed in the .pdbrc file) are:
+
+#Print instance variables (usage "pi classInst")
+alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k]
+
+#Print instance variables in self
+alias ps pi self
+"""
+
+    def help_unalias(self):
+        print >>self.stdout, """unalias name
+Deletes the specified alias."""
+
+    def help_commands(self):
+        print >>self.stdout, """commands [bpnumber]
+(com) ...
+(com) end
+(Pdb)
+
+Specify a list of commands for breakpoint number bpnumber.  The
+commands themselves appear on the following lines.  Type a line
+containing just 'end' to terminate the commands.
+
+To remove all commands from a breakpoint, type commands and
+follow it immediately with  end; that is, give no commands.
+
+With no bpnumber argument, commands refers to the last
+breakpoint set.
+
+You can use breakpoint commands to start your program up again.
+Simply use the continue command, or step, or any other
+command that resumes execution.
+
+Specifying any command resuming execution (currently continue,
+step, next, return, jump, quit and their abbreviations) terminates
+the command list (as if that command was immediately followed by end).
+This is because any time you resume execution
+(even with a simple next or step), you may encounter
+another breakpoint--which could have its own command list, leading to
+ambiguities about which list to execute.
+
+   If you use the 'silent' command in the command list, the
+usual message about stopping at a breakpoint is not printed.  This may
+be desirable for breakpoints that are to print a specific message and
+then continue.  If none of the other commands print anything, you
+see no sign that the breakpoint was reached.
+"""
+
+    def help_pdb(self):
+        help()
+
+    def lookupmodule(self, filename):
+        """Helper function for break/clear parsing -- may be overridden.
+
+        lookupmodule() translates (possibly incomplete) file or module name
+        into an absolute file name.
+        """
+        if os.path.isabs(filename) and  os.path.exists(filename):
+            return filename
+        f = os.path.join(sys.path[0], filename)
+        if  os.path.exists(f) and self.canonic(f) == self.mainpyfile:
+            return f
+        root, ext = os.path.splitext(filename)
+        if ext == '':
+            filename = filename + '.py'
+        if os.path.isabs(filename):
+            return filename
+        for dirname in sys.path:
+            while os.path.islink(dirname):
+                dirname = os.readlink(dirname)
+            fullname = os.path.join(dirname, filename)
+            if os.path.exists(fullname):
+                return fullname
+        return None
+
+    def _runscript(self, filename):
+        # The script has to run in __main__ namespace (or imports from
+        # __main__ will break).
+        #
+        # So we clear up the __main__ and set several special variables
+        # (this gets rid of pdb's globals and cleans old variables on restarts).
+        import __main__
+        __main__.__dict__.clear()
+        __main__.__dict__.update({"__name__"    : "__main__",
+                                  "__file__"    : filename,
+                                  "__builtins__": __builtins__,
+                                 })
+
+        # When bdb sets tracing, a number of call and line events happens
+        # BEFORE debugger even reaches user's code (and the exact sequence of
+        # events depends on python version). So we take special measures to
+        # avoid stopping before we reach the main script (see user_line and
+        # user_call for details).
+        self._wait_for_mainpyfile = 1
+        self.mainpyfile = self.canonic(filename)
+        self._user_requested_quit = 0
+        statement = 'execfile(%r)' % filename
+        self.run(statement)
+
+# Simplified interface
+
+def run(statement, globals=None, locals=None):
+    Pdb().run(statement, globals, locals)
+
+def runeval(expression, globals=None, locals=None):
+    return Pdb().runeval(expression, globals, locals)
+
+def runctx(statement, globals, locals):
+    # B/W compatibility
+    run(statement, globals, locals)
+
+def runcall(*args, **kwds):
+    return Pdb().runcall(*args, **kwds)
+
+def set_trace():
+    Pdb().set_trace(sys._getframe().f_back)
+
+# Post-Mortem interface
+
+def post_mortem(t=None):
+    # handling the default
+    if t is None:
+        # sys.exc_info() returns (type, value, traceback) if an exception is
+        # being handled, otherwise it returns None
+        t = sys.exc_info()[2]
+        if t is None:
+            raise ValueError("A valid traceback must be passed if no "
+                                               "exception is being handled")
+
+    p = Pdb()
+    p.reset()
+    p.interaction(None, t)
+
+def pm():
+    post_mortem(sys.last_traceback)
+
+
+# Main program for testing
+
+TESTCMD = 'import x; x.main()'
+
+def test():
+    run(TESTCMD)
+
+# print help
+def help():
+    for dirname in sys.path:
+        fullname = os.path.join(dirname, 'pdb.doc')
+        if os.path.exists(fullname):
+            sts = os.system('${PAGER-more} '+fullname)
+            if sts: print '*** Pager exit status:', sts
+            break
+    else:
+        print 'Sorry, can\'t find the help file "pdb.doc"',
+        print 'along the Python search path'
+
+def main():
+    if not sys.argv[1:] or sys.argv[1] in ("--help", "-h"):
+        print "usage: pdb.py scriptfile [arg] ..."
+        sys.exit(2)
+
+    mainpyfile =  sys.argv[1]     # Get script filename
+    if not os.path.exists(mainpyfile):
+        print 'Error:', mainpyfile, 'does not exist'
+        sys.exit(1)
+
+    del sys.argv[0]         # Hide "pdb.py" from argument list
+
+    # Replace pdb's dir with script's dir in front of module search path.
+    sys.path[0] = os.path.dirname(mainpyfile)
+
+    # Note on saving/restoring sys.argv: it's a good idea when sys.argv was
+    # modified by the script being debugged. It's a bad idea when it was
+    # changed by the user from the command line. There is a "restart" command
+    # which allows explicit specification of command line arguments.
+    pdb = Pdb()
+    while True:
+        try:
+            pdb._runscript(mainpyfile)
+            if pdb._user_requested_quit:
+                break
+            print "The program finished and will be restarted"
+        except Restart:
+            print "Restarting", mainpyfile, "with arguments:"
+            print "\t" + " ".join(sys.argv[1:])
+        except SystemExit:
+            # In most cases SystemExit does not warrant a post-mortem session.
+            print "The program exited via sys.exit(). Exit status: ",
+            print sys.exc_info()[1]
+        except:
+            traceback.print_exc()
+            print "Uncaught exception. Entering post mortem debugging"
+            print "Running 'cont' or 'step' will restart the program"
+            t = sys.exc_info()[2]
+            pdb.interaction(None, t)
+            print "Post mortem debugger finished. The " + mainpyfile + \
+                  " will be restarted"
+
+
+# When invoked as main program, invoke the debugger on a script
+if __name__ == '__main__':
+    import pdb
+    pdb.main()
diff --git a/src/main/resources/PythonLibs/pickle.py b/src/main/resources/PythonLibs/pickle.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b95cbaca76027a5f01590b7c6ae39d90671b40e
--- /dev/null
+++ b/src/main/resources/PythonLibs/pickle.py
@@ -0,0 +1,1391 @@
+"""Create portable serialized representations of Python objects.
+
+See module cPickle for a (much) faster implementation.
+See module copy_reg for a mechanism for registering custom picklers.
+See module pickletools source for extensive comments.
+
+Classes:
+
+    Pickler
+    Unpickler
+
+Functions:
+
+    dump(object, file)
+    dumps(object) -> string
+    load(file) -> object
+    loads(string) -> object
+
+Misc variables:
+
+    __version__
+    format_version
+    compatible_formats
+
+"""
+
+__version__ = "$Revision: 72223 $"       # Code version
+
+from types import *
+from copy_reg import dispatch_table
+from copy_reg import _extension_registry, _inverted_registry, _extension_cache
+import marshal
+import sys
+import struct
+import re
+
+__all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler",
+           "Unpickler", "dump", "dumps", "load", "loads"]
+
+# These are purely informational; no code uses these.
+format_version = "2.0"                  # File format version we write
+compatible_formats = ["1.0",            # Original protocol 0
+                      "1.1",            # Protocol 0 with INST added
+                      "1.2",            # Original protocol 1
+                      "1.3",            # Protocol 1 with BINFLOAT added
+                      "2.0",            # Protocol 2
+                      ]                 # Old format versions we can read
+
+# Keep in synch with cPickle.  This is the highest protocol number we
+# know how to read.
+HIGHEST_PROTOCOL = 2
+
+# Why use struct.pack() for pickling but marshal.loads() for
+# unpickling?  struct.pack() is 40% faster than marshal.dumps(), but
+# marshal.loads() is twice as fast as struct.unpack()!
+mloads = marshal.loads
+
+class PickleError(Exception):
+    """A common base class for the other pickling exceptions."""
+    pass
+
+class PicklingError(PickleError):
+    """This exception is raised when an unpicklable object is passed to the
+    dump() method.
+
+    """
+    pass
+
+class UnpicklingError(PickleError):
+    """This exception is raised when there is a problem unpickling an object,
+    such as a security violation.
+
+    Note that other exceptions may also be raised during unpickling, including
+    (but not necessarily limited to) AttributeError, EOFError, ImportError,
+    and IndexError.
+
+    """
+    pass
+
+# An instance of _Stop is raised by Unpickler.load_stop() in response to
+# the STOP opcode, passing the object that is the result of unpickling.
+class _Stop(Exception):
+    def __init__(self, value):
+        self.value = value
+
+# Jython has PyStringMap; it's a dict subclass with string keys
+try:
+    from org.python.core import PyStringMap
+except ImportError:
+    PyStringMap = None
+
+# UnicodeType may or may not be exported (normally imported from types)
+try:
+    UnicodeType
+except NameError:
+    UnicodeType = None
+
+# Pickle opcodes.  See pickletools.py for extensive docs.  The listing
+# here is in kind-of alphabetical order of 1-character pickle code.
+# pickletools groups them by purpose.
+
+MARK            = '('   # push special markobject on stack
+STOP            = '.'   # every pickle ends with STOP
+POP             = '0'   # discard topmost stack item
+POP_MARK        = '1'   # discard stack top through topmost markobject
+DUP             = '2'   # duplicate top stack item
+FLOAT           = 'F'   # push float object; decimal string argument
+INT             = 'I'   # push integer or bool; decimal string argument
+BININT          = 'J'   # push four-byte signed int
+BININT1         = 'K'   # push 1-byte unsigned int
+LONG            = 'L'   # push long; decimal string argument
+BININT2         = 'M'   # push 2-byte unsigned int
+NONE            = 'N'   # push None
+PERSID          = 'P'   # push persistent object; id is taken from string arg
+BINPERSID       = 'Q'   #  "       "         "  ;  "  "   "     "  stack
+REDUCE          = 'R'   # apply callable to argtuple, both on stack
+STRING          = 'S'   # push string; NL-terminated string argument
+BINSTRING       = 'T'   # push string; counted binary string argument
+SHORT_BINSTRING = 'U'   #  "     "   ;    "      "       "      " < 256 bytes
+UNICODE         = 'V'   # push Unicode string; raw-unicode-escaped'd argument
+BINUNICODE      = 'X'   #   "     "       "  ; counted UTF-8 string argument
+APPEND          = 'a'   # append stack top to list below it
+BUILD           = 'b'   # call __setstate__ or __dict__.update()
+GLOBAL          = 'c'   # push self.find_class(modname, name); 2 string args
+DICT            = 'd'   # build a dict from stack items
+EMPTY_DICT      = '}'   # push empty dict
+APPENDS         = 'e'   # extend list on stack by topmost stack slice
+GET             = 'g'   # push item from memo on stack; index is string arg
+BINGET          = 'h'   #   "    "    "    "   "   "  ;   "    " 1-byte arg
+INST            = 'i'   # build & push class instance
+LONG_BINGET     = 'j'   # push item from memo on stack; index is 4-byte arg
+LIST            = 'l'   # build list from topmost stack items
+EMPTY_LIST      = ']'   # push empty list
+OBJ             = 'o'   # build & push class instance
+PUT             = 'p'   # store stack top in memo; index is string arg
+BINPUT          = 'q'   #   "     "    "   "   " ;   "    " 1-byte arg
+LONG_BINPUT     = 'r'   #   "     "    "   "   " ;   "    " 4-byte arg
+SETITEM         = 's'   # add key+value pair to dict
+TUPLE           = 't'   # build tuple from topmost stack items
+EMPTY_TUPLE     = ')'   # push empty tuple
+SETITEMS        = 'u'   # modify dict by adding topmost key+value pairs
+BINFLOAT        = 'G'   # push float; arg is 8-byte float encoding
+
+TRUE            = 'I01\n'  # not an opcode; see INT docs in pickletools.py
+FALSE           = 'I00\n'  # not an opcode; see INT docs in pickletools.py
+
+# Protocol 2
+
+PROTO           = '\x80'  # identify pickle protocol
+NEWOBJ          = '\x81'  # build object by applying cls.__new__ to argtuple
+EXT1            = '\x82'  # push object from extension registry; 1-byte index
+EXT2            = '\x83'  # ditto, but 2-byte index
+EXT4            = '\x84'  # ditto, but 4-byte index
+TUPLE1          = '\x85'  # build 1-tuple from stack top
+TUPLE2          = '\x86'  # build 2-tuple from two topmost stack items
+TUPLE3          = '\x87'  # build 3-tuple from three topmost stack items
+NEWTRUE         = '\x88'  # push True
+NEWFALSE        = '\x89'  # push False
+LONG1           = '\x8a'  # push long from < 256 bytes
+LONG4           = '\x8b'  # push really big long
+
+_tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3]
+
+
+__all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$",x)])
+del x
+
+
+# Pickling machinery
+
+class Pickler:
+
+    def __init__(self, file, protocol=None):
+        """This takes a file-like object for writing a pickle data stream.
+
+        The optional protocol argument tells the pickler to use the
+        given protocol; supported protocols are 0, 1, 2.  The default
+        protocol is 0, to be backwards compatible.  (Protocol 0 is the
+        only protocol that can be written to a file opened in text
+        mode and read back successfully.  When using a protocol higher
+        than 0, make sure the file is opened in binary mode, both when
+        pickling and unpickling.)
+
+        Protocol 1 is more efficient than protocol 0; protocol 2 is
+        more efficient than protocol 1.
+
+        Specifying a negative protocol version selects the highest
+        protocol version supported.  The higher the protocol used, the
+        more recent the version of Python needed to read the pickle
+        produced.
+
+        The file parameter must have a write() method that accepts a single
+        string argument.  It can thus be an open file object, a StringIO
+        object, or any other custom object that meets this interface.
+
+        """
+        if protocol is None:
+            protocol = 0
+        if protocol < 0:
+            protocol = HIGHEST_PROTOCOL
+        elif not 0 <= protocol <= HIGHEST_PROTOCOL:
+            raise ValueError("pickle protocol must be <= %d" % HIGHEST_PROTOCOL)
+        self.write = file.write
+        self.memo = {}
+        self.proto = int(protocol)
+        self.bin = protocol >= 1
+        self.fast = 0
+
+    def clear_memo(self):
+        """Clears the pickler's "memo".
+
+        The memo is the data structure that remembers which objects the
+        pickler has already seen, so that shared or recursive objects are
+        pickled by reference and not by value.  This method is useful when
+        re-using picklers.
+
+        """
+        self.memo.clear()
+
+    def dump(self, obj):
+        """Write a pickled representation of obj to the open file."""
+        if self.proto >= 2:
+            self.write(PROTO + chr(self.proto))
+        self.save(obj)
+        self.write(STOP)
+
+    def memoize(self, obj):
+        """Store an object in the memo."""
+
+        # The Pickler memo is a dictionary mapping object ids to 2-tuples
+        # that contain the Unpickler memo key and the object being memoized.
+        # The memo key is written to the pickle and will become
+        # the key in the Unpickler's memo.  The object is stored in the
+        # Pickler memo so that transient objects are kept alive during
+        # pickling.
+
+        # The use of the Unpickler memo length as the memo key is just a
+        # convention.  The only requirement is that the memo values be unique.
+        # But there appears no advantage to any other scheme, and this
+        # scheme allows the Unpickler memo to be implemented as a plain (but
+        # growable) array, indexed by memo key.
+        if self.fast:
+            return
+        assert id(obj) not in self.memo
+        memo_len = len(self.memo)
+        self.write(self.put(memo_len))
+        self.memo[id(obj)] = memo_len, obj
+
+    # Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i.
+    def put(self, i, pack=struct.pack):
+        if self.bin:
+            if i < 256:
+                return BINPUT + chr(i)
+            else:
+                return LONG_BINPUT + pack("<i", i)
+
+        return PUT + repr(i) + '\n'
+
+    # Return a GET (BINGET, LONG_BINGET) opcode string, with argument i.
+    def get(self, i, pack=struct.pack):
+        if self.bin:
+            if i < 256:
+                return BINGET + chr(i)
+            else:
+                return LONG_BINGET + pack("<i", i)
+
+        return GET + repr(i) + '\n'
+
+    def save(self, obj):
+        # Check for persistent id (defined by a subclass)
+        pid = self.persistent_id(obj)
+        if pid:
+            self.save_pers(pid)
+            return
+
+        # Check the memo
+        x = self.memo.get(id(obj))
+        if x:
+            self.write(self.get(x[0]))
+            return
+
+        # Check the type dispatch table
+        t = type(obj)
+        f = self.dispatch.get(t)
+        if f:
+            f(self, obj) # Call unbound method with explicit self
+            return
+
+        # Check copy_reg.dispatch_table
+        reduce = dispatch_table.get(t)
+        if reduce:
+            rv = reduce(obj)
+        else:
+            # Check for a class with a custom metaclass; treat as regular class
+            try:
+                issc = issubclass(t, TypeType)
+            except TypeError: # t is not a class (old Boost; see SF #502085)
+                issc = 0
+            if issc:
+                self.save_global(obj)
+                return
+
+            # Check for a __reduce_ex__ method, fall back to __reduce__
+            reduce = getattr(obj, "__reduce_ex__", None)
+            if reduce:
+                rv = reduce(self.proto)
+            else:
+                reduce = getattr(obj, "__reduce__", None)
+                if reduce:
+                    rv = reduce()
+                else:
+                    raise PicklingError("Can't pickle %r object: %r" %
+                                        (t.__name__, obj))
+
+        # Check for string returned by reduce(), meaning "save as global"
+        if type(rv) is StringType:
+            self.save_global(obj, rv)
+            return
+
+        # Assert that reduce() returned a tuple
+        if type(rv) is not TupleType:
+            raise PicklingError("%s must return string or tuple" % reduce)
+
+        # Assert that it returned an appropriately sized tuple
+        l = len(rv)
+        if not (2 <= l <= 5):
+            raise PicklingError("Tuple returned by %s must have "
+                                "two to five elements" % reduce)
+
+        # Save the reduce() output and finally memoize the object
+        self.save_reduce(obj=obj, *rv)
+
+    def persistent_id(self, obj):
+        # This exists so a subclass can override it
+        return None
+
+    def save_pers(self, pid):
+        # Save a persistent id reference
+        if self.bin:
+            self.save(pid)
+            self.write(BINPERSID)
+        else:
+            self.write(PERSID + str(pid) + '\n')
+
+    def save_reduce(self, func, args, state=None,
+                    listitems=None, dictitems=None, obj=None):
+        # This API is called by some subclasses
+
+        # Assert that args is a tuple or None
+        if not isinstance(args, TupleType):
+            raise PicklingError("args from reduce() should be a tuple")
+
+        # Assert that func is callable
+        if not hasattr(func, '__call__'):
+            raise PicklingError("func from reduce should be callable")
+
+        save = self.save
+        write = self.write
+
+        # Protocol 2 special case: if func's name is __newobj__, use NEWOBJ
+        if self.proto >= 2 and getattr(func, "__name__", "") == "__newobj__":
+            # A __reduce__ implementation can direct protocol 2 to
+            # use the more efficient NEWOBJ opcode, while still
+            # allowing protocol 0 and 1 to work normally.  For this to
+            # work, the function returned by __reduce__ should be
+            # called __newobj__, and its first argument should be a
+            # new-style class.  The implementation for __newobj__
+            # should be as follows, although pickle has no way to
+            # verify this:
+            #
+            # def __newobj__(cls, *args):
+            #     return cls.__new__(cls, *args)
+            #
+            # Protocols 0 and 1 will pickle a reference to __newobj__,
+            # while protocol 2 (and above) will pickle a reference to
+            # cls, the remaining args tuple, and the NEWOBJ code,
+            # which calls cls.__new__(cls, *args) at unpickling time
+            # (see load_newobj below).  If __reduce__ returns a
+            # three-tuple, the state from the third tuple item will be
+            # pickled regardless of the protocol, calling __setstate__
+            # at unpickling time (see load_build below).
+            #
+            # Note that no standard __newobj__ implementation exists;
+            # you have to provide your own.  This is to enforce
+            # compatibility with Python 2.2 (pickles written using
+            # protocol 0 or 1 in Python 2.3 should be unpicklable by
+            # Python 2.2).
+            cls = args[0]
+            if not hasattr(cls, "__new__"):
+                raise PicklingError(
+                    "args[0] from __newobj__ args has no __new__")
+            if obj is not None and cls is not obj.__class__:
+                raise PicklingError(
+                    "args[0] from __newobj__ args has the wrong class")
+            args = args[1:]
+            save(cls)
+            save(args)
+            write(NEWOBJ)
+        else:
+            save(func)
+            save(args)
+            write(REDUCE)
+
+        if obj is not None:
+            self.memoize(obj)
+
+        # More new special cases (that work with older protocols as
+        # well): when __reduce__ returns a tuple with 4 or 5 items,
+        # the 4th and 5th item should be iterators that provide list
+        # items and dict items (as (key, value) tuples), or None.
+
+        if listitems is not None:
+            self._batch_appends(listitems)
+
+        if dictitems is not None:
+            self._batch_setitems(dictitems)
+
+        if state is not None:
+            save(state)
+            write(BUILD)
+
+    # Methods below this point are dispatched through the dispatch table
+
+    dispatch = {}
+
+    def save_none(self, obj):
+        self.write(NONE)
+    dispatch[NoneType] = save_none
+
+    def save_bool(self, obj):
+        if self.proto >= 2:
+            self.write(obj and NEWTRUE or NEWFALSE)
+        else:
+            self.write(obj and TRUE or FALSE)
+    dispatch[bool] = save_bool
+
+    def save_int(self, obj, pack=struct.pack):
+        if self.bin:
+            # If the int is small enough to fit in a signed 4-byte 2's-comp
+            # format, we can store it more efficiently than the general
+            # case.
+            # First one- and two-byte unsigned ints:
+            if obj >= 0:
+                if obj <= 0xff:
+                    self.write(BININT1 + chr(obj))
+                    return
+                if obj <= 0xffff:
+                    self.write("%c%c%c" % (BININT2, obj&0xff, obj>>8))
+                    return
+            # Next check for 4-byte signed ints:
+            high_bits = obj >> 31  # note that Python shift sign-extends
+            if high_bits == 0 or high_bits == -1:
+                # All high bits are copies of bit 2**31, so the value
+                # fits in a 4-byte signed int.
+                self.write(BININT + pack("<i", obj))
+                return
+        # Text pickle, or int too big to fit in signed 4-byte format.
+        self.write(INT + repr(obj) + '\n')
+    dispatch[IntType] = save_int
+
+    def save_long(self, obj, pack=struct.pack):
+        if self.proto >= 2:
+            bytes = encode_long(obj)
+            n = len(bytes)
+            if n < 256:
+                self.write(LONG1 + chr(n) + bytes)
+            else:
+                self.write(LONG4 + pack("<i", n) + bytes)
+            return
+        self.write(LONG + repr(obj) + '\n')
+    dispatch[LongType] = save_long
+
+    def save_float(self, obj, pack=struct.pack):
+        if self.bin:
+            self.write(BINFLOAT + pack('>d', obj))
+        else:
+            self.write(FLOAT + repr(obj) + '\n')
+    dispatch[FloatType] = save_float
+
+    def save_string(self, obj, pack=struct.pack):
+        if self.bin:
+            n = len(obj)
+            if n < 256:
+                self.write(SHORT_BINSTRING + chr(n) + obj)
+            else:
+                self.write(BINSTRING + pack("<i", n) + obj)
+        else:
+            self.write(STRING + repr(obj) + '\n')
+        self.memoize(obj)
+    dispatch[StringType] = save_string
+
+    def save_unicode(self, obj, pack=struct.pack):
+        if self.bin:
+            encoding = obj.encode('utf-8')
+            n = len(encoding)
+            self.write(BINUNICODE + pack("<i", n) + encoding)
+        else:
+            obj = obj.replace("\\", "\\u005c")
+            obj = obj.replace("\n", "\\u000a")
+            self.write(UNICODE + obj.encode('raw-unicode-escape') + '\n')
+        self.memoize(obj)
+    dispatch[UnicodeType] = save_unicode
+
+    if StringType is UnicodeType:
+        # This is true for Jython
+        def save_string(self, obj, pack=struct.pack):
+            unicode = obj.isunicode()
+
+            if self.bin:
+                if unicode:
+                    obj = obj.encode("utf-8")
+                l = len(obj)
+                if l < 256 and not unicode:
+                    self.write(SHORT_BINSTRING + chr(l) + obj)
+                else:
+                    s = pack("<i", l)
+                    if unicode:
+                        self.write(BINUNICODE + s + obj)
+                    else:
+                        self.write(BINSTRING + s + obj)
+            else:
+                if unicode:
+                    obj = obj.replace("\\", "\\u005c")
+                    obj = obj.replace("\n", "\\u000a")
+                    obj = obj.encode('raw-unicode-escape')
+                    self.write(UNICODE + obj + '\n')
+                else:
+                    self.write(STRING + repr(obj) + '\n')
+            self.memoize(obj)
+        dispatch[StringType] = save_string
+
+    def save_tuple(self, obj):
+        write = self.write
+        proto = self.proto
+
+        n = len(obj)
+        if n == 0:
+            if proto:
+                write(EMPTY_TUPLE)
+            else:
+                write(MARK + TUPLE)
+            return
+
+        save = self.save
+        memo = self.memo
+        if n <= 3 and proto >= 2:
+            for element in obj:
+                save(element)
+            # Subtle.  Same as in the big comment below.
+            if id(obj) in memo:
+                get = self.get(memo[id(obj)][0])
+                write(POP * n + get)
+            else:
+                write(_tuplesize2code[n])
+                self.memoize(obj)
+            return
+
+        # proto 0 or proto 1 and tuple isn't empty, or proto > 1 and tuple
+        # has more than 3 elements.
+        write(MARK)
+        for element in obj:
+            save(element)
+
+        if id(obj) in memo:
+            # Subtle.  d was not in memo when we entered save_tuple(), so
+            # the process of saving the tuple's elements must have saved
+            # the tuple itself:  the tuple is recursive.  The proper action
+            # now is to throw away everything we put on the stack, and
+            # simply GET the tuple (it's already constructed).  This check
+            # could have been done in the "for element" loop instead, but
+            # recursive tuples are a rare thing.
+            get = self.get(memo[id(obj)][0])
+            if proto:
+                write(POP_MARK + get)
+            else:   # proto 0 -- POP_MARK not available
+                write(POP * (n+1) + get)
+            return
+
+        # No recursion.
+        self.write(TUPLE)
+        self.memoize(obj)
+
+    dispatch[TupleType] = save_tuple
+
+    # save_empty_tuple() isn't used by anything in Python 2.3.  However, I
+    # found a Pickler subclass in Zope3 that calls it, so it's not harmless
+    # to remove it.
+    def save_empty_tuple(self, obj):
+        self.write(EMPTY_TUPLE)
+
+    def save_list(self, obj):
+        write = self.write
+
+        if self.bin:
+            write(EMPTY_LIST)
+        else:   # proto 0 -- can't use EMPTY_LIST
+            write(MARK + LIST)
+
+        self.memoize(obj)
+        self._batch_appends(iter(obj))
+
+    dispatch[ListType] = save_list
+
+    # Keep in synch with cPickle's BATCHSIZE.  Nothing will break if it gets
+    # out of synch, though.
+    _BATCHSIZE = 1000
+
+    def _batch_appends(self, items):
+        # Helper to batch up APPENDS sequences
+        save = self.save
+        write = self.write
+
+        if not self.bin:
+            for x in items:
+                save(x)
+                write(APPEND)
+            return
+
+        r = xrange(self._BATCHSIZE)
+        while items is not None:
+            tmp = []
+            for i in r:
+                try:
+                    x = items.next()
+                    tmp.append(x)
+                except StopIteration:
+                    items = None
+                    break
+            n = len(tmp)
+            if n > 1:
+                write(MARK)
+                for x in tmp:
+                    save(x)
+                write(APPENDS)
+            elif n:
+                save(tmp[0])
+                write(APPEND)
+            # else tmp is empty, and we're done
+
+    def save_dict(self, obj):
+        write = self.write
+
+        if self.bin:
+            write(EMPTY_DICT)
+        else:   # proto 0 -- can't use EMPTY_DICT
+            write(MARK + DICT)
+
+        self.memoize(obj)
+        self._batch_setitems(obj.iteritems())
+
+    dispatch[DictionaryType] = save_dict
+    if not PyStringMap is None:
+        dispatch[PyStringMap] = save_dict
+
+    def _batch_setitems(self, items):
+        # Helper to batch up SETITEMS sequences; proto >= 1 only
+        save = self.save
+        write = self.write
+
+        if not self.bin:
+            for k, v in items:
+                save(k)
+                save(v)
+                write(SETITEM)
+            return
+
+        r = xrange(self._BATCHSIZE)
+        while items is not None:
+            tmp = []
+            for i in r:
+                try:
+                    tmp.append(items.next())
+                except StopIteration:
+                    items = None
+                    break
+            n = len(tmp)
+            if n > 1:
+                write(MARK)
+                for k, v in tmp:
+                    save(k)
+                    save(v)
+                write(SETITEMS)
+            elif n:
+                k, v = tmp[0]
+                save(k)
+                save(v)
+                write(SETITEM)
+            # else tmp is empty, and we're done
+
+    def save_inst(self, obj):
+        cls = obj.__class__
+
+        memo  = self.memo
+        write = self.write
+        save  = self.save
+
+        if hasattr(obj, '__getinitargs__'):
+            args = obj.__getinitargs__()
+            len(args) # XXX Assert it's a sequence
+            _keep_alive(args, memo)
+        else:
+            args = ()
+
+        write(MARK)
+
+        if self.bin:
+            save(cls)
+            for arg in args:
+                save(arg)
+            write(OBJ)
+        else:
+            for arg in args:
+                save(arg)
+            write(INST + cls.__module__ + '\n' + cls.__name__ + '\n')
+
+        self.memoize(obj)
+
+        try:
+            getstate = obj.__getstate__
+        except AttributeError:
+            stuff = obj.__dict__
+        else:
+            stuff = getstate()
+            _keep_alive(stuff, memo)
+        save(stuff)
+        write(BUILD)
+
+    dispatch[InstanceType] = save_inst
+
+    def save_global(self, obj, name=None, pack=struct.pack):
+        write = self.write
+        memo = self.memo
+
+        if name is None:
+            name = obj.__name__
+
+        module = getattr(obj, "__module__", None)
+        if module is None:
+            module = whichmodule(obj, name)
+
+        try:
+            __import__(module)
+            mod = sys.modules[module]
+            klass = getattr(mod, name)
+        except (ImportError, KeyError, AttributeError):
+            raise PicklingError(
+                "Can't pickle %r: it's not found as %s.%s" %
+                (obj, module, name))
+        else:
+            if klass is not obj:
+                raise PicklingError(
+                    "Can't pickle %r: it's not the same object as %s.%s" %
+                    (obj, module, name))
+
+        if self.proto >= 2:
+            code = _extension_registry.get((module, name))
+            if code:
+                assert code > 0
+                if code <= 0xff:
+                    write(EXT1 + chr(code))
+                elif code <= 0xffff:
+                    write("%c%c%c" % (EXT2, code&0xff, code>>8))
+                else:
+                    write(EXT4 + pack("<i", code))
+                return
+
+        write(GLOBAL + module + '\n' + name + '\n')
+        self.memoize(obj)
+
+    dispatch[ClassType] = save_global
+    dispatch[FunctionType] = save_global
+    dispatch[BuiltinFunctionType] = save_global
+    dispatch[TypeType] = save_global
+
+# Pickling helpers
+
+def _keep_alive(x, memo):
+    """Keeps a reference to the object x in the memo.
+
+    Because we remember objects by their id, we have
+    to assure that possibly temporary objects are kept
+    alive by referencing them.
+    We store a reference at the id of the memo, which should
+    normally not be used unless someone tries to deepcopy
+    the memo itself...
+    """
+    try:
+        memo[id(memo)].append(x)
+    except KeyError:
+        # aha, this is the first one :-)
+        memo[id(memo)]=[x]
+
+
+# A cache for whichmodule(), mapping a function object to the name of
+# the module in which the function was found.
+
+classmap = {} # called classmap for backwards compatibility
+
+def whichmodule(func, funcname):
+    """Figure out the module in which a function occurs.
+
+    Search sys.modules for the module.
+    Cache in classmap.
+    Return a module name.
+    If the function cannot be found, return "__main__".
+    """
+    # Python functions should always get an __module__ from their globals.
+    mod = getattr(func, "__module__", None)
+    if mod is not None:
+        return mod
+    if func in classmap:
+        return classmap[func]
+
+    for name, module in sys.modules.items():
+        if module is None:
+            continue # skip dummy package entries
+        if name != '__main__' and getattr(module, funcname, None) is func:
+            break
+    else:
+        name = '__main__'
+    classmap[func] = name
+    return name
+
+
+# Unpickling machinery
+
+class Unpickler:
+
+    def __init__(self, file):
+        """This takes a file-like object for reading a pickle data stream.
+
+        The protocol version of the pickle is detected automatically, so no
+        proto argument is needed.
+
+        The file-like object must have two methods, a read() method that
+        takes an integer argument, and a readline() method that requires no
+        arguments.  Both methods should return a string.  Thus file-like
+        object can be a file object opened for reading, a StringIO object,
+        or any other custom object that meets this interface.
+        """
+        self.readline = file.readline
+        self.read = file.read
+        self.memo = {}
+
+    def load(self):
+        """Read a pickled object representation from the open file.
+
+        Return the reconstituted object hierarchy specified in the file.
+        """
+        self.mark = object() # any new unique object
+        self.stack = []
+        self.append = self.stack.append
+        read = self.read
+        dispatch = self.dispatch
+        try:
+            while 1:
+                key = read(1)
+                dispatch[key](self)
+        except _Stop, stopinst:
+            return stopinst.value
+
+    # Return largest index k such that self.stack[k] is self.mark.
+    # If the stack doesn't contain a mark, eventually raises IndexError.
+    # This could be sped by maintaining another stack, of indices at which
+    # the mark appears.  For that matter, the latter stack would suffice,
+    # and we wouldn't need to push mark objects on self.stack at all.
+    # Doing so is probably a good thing, though, since if the pickle is
+    # corrupt (or hostile) we may get a clue from finding self.mark embedded
+    # in unpickled objects.
+    def marker(self):
+        stack = self.stack
+        mark = self.mark
+        k = len(stack)-1
+        while stack[k] is not mark: k = k-1
+        return k
+
+    dispatch = {}
+
+    def load_eof(self):
+        raise EOFError
+    dispatch[''] = load_eof
+
+    def load_proto(self):
+        proto = ord(self.read(1))
+        if not 0 <= proto <= 2:
+            raise ValueError, "unsupported pickle protocol: %d" % proto
+    dispatch[PROTO] = load_proto
+
+    def load_persid(self):
+        pid = self.readline()[:-1]
+        self.append(self.persistent_load(pid))
+    dispatch[PERSID] = load_persid
+
+    def load_binpersid(self):
+        pid = self.stack.pop()
+        self.append(self.persistent_load(pid))
+    dispatch[BINPERSID] = load_binpersid
+
+    def load_none(self):
+        self.append(None)
+    dispatch[NONE] = load_none
+
+    def load_false(self):
+        self.append(False)
+    dispatch[NEWFALSE] = load_false
+
+    def load_true(self):
+        self.append(True)
+    dispatch[NEWTRUE] = load_true
+
+    def load_int(self):
+        data = self.readline()
+        if data == FALSE[1:]:
+            val = False
+        elif data == TRUE[1:]:
+            val = True
+        else:
+            try:
+                val = int(data)
+            except ValueError:
+                val = long(data)
+        self.append(val)
+    dispatch[INT] = load_int
+
+    def load_binint(self):
+        self.append(mloads('i' + self.read(4)))
+    dispatch[BININT] = load_binint
+
+    def load_binint1(self):
+        self.append(ord(self.read(1)))
+    dispatch[BININT1] = load_binint1
+
+    def load_binint2(self):
+        self.append(mloads('i' + self.read(2) + '\000\000'))
+    dispatch[BININT2] = load_binint2
+
+    def load_long(self):
+        self.append(long(self.readline()[:-1], 0))
+    dispatch[LONG] = load_long
+
+    def load_long1(self):
+        n = ord(self.read(1))
+        bytes = self.read(n)
+        self.append(decode_long(bytes))
+    dispatch[LONG1] = load_long1
+
+    def load_long4(self):
+        n = mloads('i' + self.read(4))
+        bytes = self.read(n)
+        self.append(decode_long(bytes))
+    dispatch[LONG4] = load_long4
+
+    def load_float(self):
+        self.append(float(self.readline()[:-1]))
+    dispatch[FLOAT] = load_float
+
+    def load_binfloat(self, unpack=struct.unpack):
+        self.append(unpack('>d', self.read(8))[0])
+    dispatch[BINFLOAT] = load_binfloat
+
+    def load_string(self):
+        rep = self.readline()[:-1]
+        for q in "\"'": # double or single quote
+            if rep.startswith(q):
+                if not rep.endswith(q):
+                    raise ValueError, "insecure string pickle"
+                rep = rep[len(q):-len(q)]
+                break
+        else:
+            raise ValueError, "insecure string pickle"
+        self.append(rep.decode("string-escape"))
+    dispatch[STRING] = load_string
+
+    def load_binstring(self):
+        len = mloads('i' + self.read(4))
+        self.append(self.read(len))
+    dispatch[BINSTRING] = load_binstring
+
+    def load_unicode(self):
+        self.append(unicode(self.readline()[:-1],'raw-unicode-escape'))
+    dispatch[UNICODE] = load_unicode
+
+    def load_binunicode(self):
+        len = mloads('i' + self.read(4))
+        self.append(unicode(self.read(len),'utf-8'))
+    dispatch[BINUNICODE] = load_binunicode
+
+    def load_short_binstring(self):
+        len = ord(self.read(1))
+        self.append(self.read(len))
+    dispatch[SHORT_BINSTRING] = load_short_binstring
+
+    def load_tuple(self):
+        k = self.marker()
+        self.stack[k:] = [tuple(self.stack[k+1:])]
+    dispatch[TUPLE] = load_tuple
+
+    def load_empty_tuple(self):
+        self.stack.append(())
+    dispatch[EMPTY_TUPLE] = load_empty_tuple
+
+    def load_tuple1(self):
+        self.stack[-1] = (self.stack[-1],)
+    dispatch[TUPLE1] = load_tuple1
+
+    def load_tuple2(self):
+        self.stack[-2:] = [(self.stack[-2], self.stack[-1])]
+    dispatch[TUPLE2] = load_tuple2
+
+    def load_tuple3(self):
+        self.stack[-3:] = [(self.stack[-3], self.stack[-2], self.stack[-1])]
+    dispatch[TUPLE3] = load_tuple3
+
+    def load_empty_list(self):
+        self.stack.append([])
+    dispatch[EMPTY_LIST] = load_empty_list
+
+    def load_empty_dictionary(self):
+        self.stack.append({})
+    dispatch[EMPTY_DICT] = load_empty_dictionary
+
+    def load_list(self):
+        k = self.marker()
+        self.stack[k:] = [self.stack[k+1:]]
+    dispatch[LIST] = load_list
+
+    def load_dict(self):
+        k = self.marker()
+        d = {}
+        items = self.stack[k+1:]
+        for i in range(0, len(items), 2):
+            key = items[i]
+            value = items[i+1]
+            d[key] = value
+        self.stack[k:] = [d]
+    dispatch[DICT] = load_dict
+
+    # INST and OBJ differ only in how they get a class object.  It's not
+    # only sensible to do the rest in a common routine, the two routines
+    # previously diverged and grew different bugs.
+    # klass is the class to instantiate, and k points to the topmost mark
+    # object, following which are the arguments for klass.__init__.
+    def _instantiate(self, klass, k):
+        args = tuple(self.stack[k+1:])
+        del self.stack[k:]
+        instantiated = 0
+        if (not args and
+                type(klass) is ClassType and
+                not hasattr(klass, "__getinitargs__")):
+            try:
+                value = _EmptyClass()
+                value.__class__ = klass
+                instantiated = 1
+            except RuntimeError:
+                # In restricted execution, assignment to inst.__class__ is
+                # prohibited
+                pass
+        if not instantiated:
+            try:
+                value = klass(*args)
+            except TypeError, err:
+                raise TypeError, "in constructor for %s: %s" % (
+                    klass.__name__, str(err)), sys.exc_info()[2]
+        self.append(value)
+
+    def load_inst(self):
+        module = self.readline()[:-1]
+        name = self.readline()[:-1]
+        klass = self.find_class(module, name)
+        self._instantiate(klass, self.marker())
+    dispatch[INST] = load_inst
+
+    def load_obj(self):
+        # Stack is ... markobject classobject arg1 arg2 ...
+        k = self.marker()
+        klass = self.stack.pop(k+1)
+        self._instantiate(klass, k)
+    dispatch[OBJ] = load_obj
+
+    def load_newobj(self):
+        args = self.stack.pop()
+        cls = self.stack[-1]
+        obj = cls.__new__(cls, *args)
+        self.stack[-1] = obj
+    dispatch[NEWOBJ] = load_newobj
+
+    def load_global(self):
+        module = self.readline()[:-1]
+        name = self.readline()[:-1]
+        klass = self.find_class(module, name)
+        self.append(klass)
+    dispatch[GLOBAL] = load_global
+
+    def load_ext1(self):
+        code = ord(self.read(1))
+        self.get_extension(code)
+    dispatch[EXT1] = load_ext1
+
+    def load_ext2(self):
+        code = mloads('i' + self.read(2) + '\000\000')
+        self.get_extension(code)
+    dispatch[EXT2] = load_ext2
+
+    def load_ext4(self):
+        code = mloads('i' + self.read(4))
+        self.get_extension(code)
+    dispatch[EXT4] = load_ext4
+
+    def get_extension(self, code):
+        nil = []
+        obj = _extension_cache.get(code, nil)
+        if obj is not nil:
+            self.append(obj)
+            return
+        key = _inverted_registry.get(code)
+        if not key:
+            raise ValueError("unregistered extension code %d" % code)
+        obj = self.find_class(*key)
+        _extension_cache[code] = obj
+        self.append(obj)
+
+    def find_class(self, module, name):
+        # Subclasses may override this
+        __import__(module)
+        mod = sys.modules[module]
+        klass = getattr(mod, name)
+        return klass
+
+    def load_reduce(self):
+        stack = self.stack
+        args = stack.pop()
+        func = stack[-1]
+        value = func(*args)
+        stack[-1] = value
+    dispatch[REDUCE] = load_reduce
+
+    def load_pop(self):
+        del self.stack[-1]
+    dispatch[POP] = load_pop
+
+    def load_pop_mark(self):
+        k = self.marker()
+        del self.stack[k:]
+    dispatch[POP_MARK] = load_pop_mark
+
+    def load_dup(self):
+        self.append(self.stack[-1])
+    dispatch[DUP] = load_dup
+
+    def load_get(self):
+        self.append(self.memo[self.readline()[:-1]])
+    dispatch[GET] = load_get
+
+    def load_binget(self):
+        i = ord(self.read(1))
+        self.append(self.memo[repr(i)])
+    dispatch[BINGET] = load_binget
+
+    def load_long_binget(self):
+        i = mloads('i' + self.read(4))
+        self.append(self.memo[repr(i)])
+    dispatch[LONG_BINGET] = load_long_binget
+
+    def load_put(self):
+        self.memo[self.readline()[:-1]] = self.stack[-1]
+    dispatch[PUT] = load_put
+
+    def load_binput(self):
+        i = ord(self.read(1))
+        self.memo[repr(i)] = self.stack[-1]
+    dispatch[BINPUT] = load_binput
+
+    def load_long_binput(self):
+        i = mloads('i' + self.read(4))
+        self.memo[repr(i)] = self.stack[-1]
+    dispatch[LONG_BINPUT] = load_long_binput
+
+    def load_append(self):
+        stack = self.stack
+        value = stack.pop()
+        list = stack[-1]
+        list.append(value)
+    dispatch[APPEND] = load_append
+
+    def load_appends(self):
+        stack = self.stack
+        mark = self.marker()
+        list = stack[mark - 1]
+        list.extend(stack[mark + 1:])
+        del stack[mark:]
+    dispatch[APPENDS] = load_appends
+
+    def load_setitem(self):
+        stack = self.stack
+        value = stack.pop()
+        key = stack.pop()
+        dict = stack[-1]
+        dict[key] = value
+    dispatch[SETITEM] = load_setitem
+
+    def load_setitems(self):
+        stack = self.stack
+        mark = self.marker()
+        dict = stack[mark - 1]
+        for i in range(mark + 1, len(stack), 2):
+            dict[stack[i]] = stack[i + 1]
+
+        del stack[mark:]
+    dispatch[SETITEMS] = load_setitems
+
+    def load_build(self):
+        stack = self.stack
+        state = stack.pop()
+        inst = stack[-1]
+        setstate = getattr(inst, "__setstate__", None)
+        if setstate:
+            setstate(state)
+            return
+        slotstate = None
+        if isinstance(state, tuple) and len(state) == 2:
+            state, slotstate = state
+        if state:
+            try:
+                d = inst.__dict__
+                try:
+                    for k, v in state.iteritems():
+                        d[intern(k)] = v
+                # keys in state don't have to be strings
+                # don't blow up, but don't go out of our way
+                except TypeError:
+                    d.update(state)
+
+            except RuntimeError:
+                # XXX In restricted execution, the instance's __dict__
+                # is not accessible.  Use the old way of unpickling
+                # the instance variables.  This is a semantic
+                # difference when unpickling in restricted
+                # vs. unrestricted modes.
+                # Note, however, that cPickle has never tried to do the
+                # .update() business, and always uses
+                #     PyObject_SetItem(inst.__dict__, key, value) in a
+                # loop over state.items().
+                for k, v in state.items():
+                    setattr(inst, k, v)
+        if slotstate:
+            for k, v in slotstate.items():
+                setattr(inst, k, v)
+    dispatch[BUILD] = load_build
+
+    def load_mark(self):
+        self.append(self.mark)
+    dispatch[MARK] = load_mark
+
+    def load_stop(self):
+        value = self.stack.pop()
+        raise _Stop(value)
+    dispatch[STOP] = load_stop
+
+# Helper class for load_inst/load_obj
+
+class _EmptyClass:
+    pass
+
+# Encode/decode longs in linear time.
+
+import binascii as _binascii
+
+def encode_long(x):
+    r"""Encode a long to a two's complement little-endian binary string.
+    Note that 0L is a special case, returning an empty string, to save a
+    byte in the LONG1 pickling context.
+
+    >>> encode_long(0L)
+    ''
+    >>> encode_long(255L)
+    '\xff\x00'
+    >>> encode_long(32767L)
+    '\xff\x7f'
+    >>> encode_long(-256L)
+    '\x00\xff'
+    >>> encode_long(-32768L)
+    '\x00\x80'
+    >>> encode_long(-128L)
+    '\x80'
+    >>> encode_long(127L)
+    '\x7f'
+    >>>
+    """
+
+    if x == 0:
+        return ''
+    if x > 0:
+        ashex = hex(x)
+        assert ashex.startswith("0x")
+        njunkchars = 2 + ashex.endswith('L')
+        nibbles = len(ashex) - njunkchars
+        if nibbles & 1:
+            # need an even # of nibbles for unhexlify
+            ashex = "0x0" + ashex[2:]
+        elif int(ashex[2], 16) >= 8:
+            # "looks negative", so need a byte of sign bits
+            ashex = "0x00" + ashex[2:]
+    else:
+        # Build the 256's-complement:  (1L << nbytes) + x.  The trick is
+        # to find the number of bytes in linear time (although that should
+        # really be a constant-time task).
+        ashex = hex(-x)
+        assert ashex.startswith("0x")
+        njunkchars = 2 + ashex.endswith('L')
+        nibbles = len(ashex) - njunkchars
+        if nibbles & 1:
+            # Extend to a full byte.
+            nibbles += 1
+        nbits = nibbles * 4
+        x += 1L << nbits
+        assert x > 0
+        ashex = hex(x)
+        njunkchars = 2 + ashex.endswith('L')
+        newnibbles = len(ashex) - njunkchars
+        if newnibbles < nibbles:
+            ashex = "0x" + "0" * (nibbles - newnibbles) + ashex[2:]
+        if int(ashex[2], 16) < 8:
+            # "looks positive", so need a byte of sign bits
+            ashex = "0xff" + ashex[2:]
+
+    if ashex.endswith('L'):
+        ashex = ashex[2:-1]
+    else:
+        ashex = ashex[2:]
+    assert len(ashex) & 1 == 0, (x, ashex)
+    binary = _binascii.unhexlify(ashex)
+    return binary[::-1]
+
+def decode_long(data):
+    r"""Decode a long from a two's complement little-endian binary string.
+
+    >>> decode_long('')
+    0L
+    >>> decode_long("\xff\x00")
+    255L
+    >>> decode_long("\xff\x7f")
+    32767L
+    >>> decode_long("\x00\xff")
+    -256L
+    >>> decode_long("\x00\x80")
+    -32768L
+    >>> decode_long("\x80")
+    -128L
+    >>> decode_long("\x7f")
+    127L
+    """
+
+    nbytes = len(data)
+    if nbytes == 0:
+        return 0L
+    ashex = _binascii.hexlify(data[::-1])
+    n = long(ashex, 16) # quadratic time before Python 2.3; linear now
+    if data[-1] >= '\x80':
+        n -= 1L << (nbytes * 8)
+    return n
+
+# Shorthands
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+def dump(obj, file, protocol=None):
+    Pickler(file, protocol).dump(obj)
+
+def dumps(obj, protocol=None):
+    file = StringIO()
+    Pickler(file, protocol).dump(obj)
+    return file.getvalue()
+
+def load(file):
+    return Unpickler(file).load()
+
+def loads(str):
+    file = StringIO(str)
+    return Unpickler(file).load()
+
+# Doctest
+
+def _test():
+    import doctest
+    return doctest.testmod()
+
+if __name__ == "__main__":
+    _test()
diff --git a/src/main/resources/PythonLibs/pickletools.py b/src/main/resources/PythonLibs/pickletools.py
new file mode 100644
index 0000000000000000000000000000000000000000..d717728d417811a7943ee05a5c536d420b691010
--- /dev/null
+++ b/src/main/resources/PythonLibs/pickletools.py
@@ -0,0 +1,2274 @@
+'''"Executable documentation" for the pickle module.
+
+Extensive comments about the pickle protocols and pickle-machine opcodes
+can be found here.  Some functions meant for external use:
+
+genops(pickle)
+   Generate all the opcodes in a pickle, as (opcode, arg, position) triples.
+
+dis(pickle, out=None, memo=None, indentlevel=4)
+   Print a symbolic disassembly of a pickle.
+'''
+
+__all__ = ['dis', 'genops', 'optimize']
+
+# Other ideas:
+#
+# - A pickle verifier:  read a pickle and check it exhaustively for
+#   well-formedness.  dis() does a lot of this already.
+#
+# - A protocol identifier:  examine a pickle and return its protocol number
+#   (== the highest .proto attr value among all the opcodes in the pickle).
+#   dis() already prints this info at the end.
+#
+# - A pickle optimizer:  for example, tuple-building code is sometimes more
+#   elaborate than necessary, catering for the possibility that the tuple
+#   is recursive.  Or lots of times a PUT is generated that's never accessed
+#   by a later GET.
+
+
+"""
+"A pickle" is a program for a virtual pickle machine (PM, but more accurately
+called an unpickling machine).  It's a sequence of opcodes, interpreted by the
+PM, building an arbitrarily complex Python object.
+
+For the most part, the PM is very simple:  there are no looping, testing, or
+conditional instructions, no arithmetic and no function calls.  Opcodes are
+executed once each, from first to last, until a STOP opcode is reached.
+
+The PM has two data areas, "the stack" and "the memo".
+
+Many opcodes push Python objects onto the stack; e.g., INT pushes a Python
+integer object on the stack, whose value is gotten from a decimal string
+literal immediately following the INT opcode in the pickle bytestream.  Other
+opcodes take Python objects off the stack.  The result of unpickling is
+whatever object is left on the stack when the final STOP opcode is executed.
+
+The memo is simply an array of objects, or it can be implemented as a dict
+mapping little integers to objects.  The memo serves as the PM's "long term
+memory", and the little integers indexing the memo are akin to variable
+names.  Some opcodes pop a stack object into the memo at a given index,
+and others push a memo object at a given index onto the stack again.
+
+At heart, that's all the PM has.  Subtleties arise for these reasons:
+
++ Object identity.  Objects can be arbitrarily complex, and subobjects
+  may be shared (for example, the list [a, a] refers to the same object a
+  twice).  It can be vital that unpickling recreate an isomorphic object
+  graph, faithfully reproducing sharing.
+
++ Recursive objects.  For example, after "L = []; L.append(L)", L is a
+  list, and L[0] is the same list.  This is related to the object identity
+  point, and some sequences of pickle opcodes are subtle in order to
+  get the right result in all cases.
+
++ Things pickle doesn't know everything about.  Examples of things pickle
+  does know everything about are Python's builtin scalar and container
+  types, like ints and tuples.  They generally have opcodes dedicated to
+  them.  For things like module references and instances of user-defined
+  classes, pickle's knowledge is limited.  Historically, many enhancements
+  have been made to the pickle protocol in order to do a better (faster,
+  and/or more compact) job on those.
+
++ Backward compatibility and micro-optimization.  As explained below,
+  pickle opcodes never go away, not even when better ways to do a thing
+  get invented.  The repertoire of the PM just keeps growing over time.
+  For example, protocol 0 had two opcodes for building Python integers (INT
+  and LONG), protocol 1 added three more for more-efficient pickling of short
+  integers, and protocol 2 added two more for more-efficient pickling of
+  long integers (before protocol 2, the only ways to pickle a Python long
+  took time quadratic in the number of digits, for both pickling and
+  unpickling).  "Opcode bloat" isn't so much a subtlety as a source of
+  wearying complication.
+
+
+Pickle protocols:
+
+For compatibility, the meaning of a pickle opcode never changes.  Instead new
+pickle opcodes get added, and each version's unpickler can handle all the
+pickle opcodes in all protocol versions to date.  So old pickles continue to
+be readable forever.  The pickler can generally be told to restrict itself to
+the subset of opcodes available under previous protocol versions too, so that
+users can create pickles under the current version readable by older
+versions.  However, a pickle does not contain its version number embedded
+within it.  If an older unpickler tries to read a pickle using a later
+protocol, the result is most likely an exception due to seeing an unknown (in
+the older unpickler) opcode.
+
+The original pickle used what's now called "protocol 0", and what was called
+"text mode" before Python 2.3.  The entire pickle bytestream is made up of
+printable 7-bit ASCII characters, plus the newline character, in protocol 0.
+That's why it was called text mode.  Protocol 0 is small and elegant, but
+sometimes painfully inefficient.
+
+The second major set of additions is now called "protocol 1", and was called
+"binary mode" before Python 2.3.  This added many opcodes with arguments
+consisting of arbitrary bytes, including NUL bytes and unprintable "high bit"
+bytes.  Binary mode pickles can be substantially smaller than equivalent
+text mode pickles, and sometimes faster too; e.g., BININT represents a 4-byte
+int as 4 bytes following the opcode, which is cheaper to unpickle than the
+(perhaps) 11-character decimal string attached to INT.  Protocol 1 also added
+a number of opcodes that operate on many stack elements at once (like APPENDS
+and SETITEMS), and "shortcut" opcodes (like EMPTY_DICT and EMPTY_TUPLE).
+
+The third major set of additions came in Python 2.3, and is called "protocol
+2".  This added:
+
+- A better way to pickle instances of new-style classes (NEWOBJ).
+
+- A way for a pickle to identify its protocol (PROTO).
+
+- Time- and space- efficient pickling of long ints (LONG{1,4}).
+
+- Shortcuts for small tuples (TUPLE{1,2,3}}.
+
+- Dedicated opcodes for bools (NEWTRUE, NEWFALSE).
+
+- The "extension registry", a vector of popular objects that can be pushed
+  efficiently by index (EXT{1,2,4}).  This is akin to the memo and GET, but
+  the registry contents are predefined (there's nothing akin to the memo's
+  PUT).
+
+Another independent change with Python 2.3 is the abandonment of any
+pretense that it might be safe to load pickles received from untrusted
+parties -- no sufficient security analysis has been done to guarantee
+this and there isn't a use case that warrants the expense of such an
+analysis.
+
+To this end, all tests for __safe_for_unpickling__ or for
+copy_reg.safe_constructors are removed from the unpickling code.
+References to these variables in the descriptions below are to be seen
+as describing unpickling in Python 2.2 and before.
+"""
+
+# Meta-rule:  Descriptions are stored in instances of descriptor objects,
+# with plain constructors.  No meta-language is defined from which
+# descriptors could be constructed.  If you want, e.g., XML, write a little
+# program to generate XML from the objects.
+
+##############################################################################
+# Some pickle opcodes have an argument, following the opcode in the
+# bytestream.  An argument is of a specific type, described by an instance
+# of ArgumentDescriptor.  These are not to be confused with arguments taken
+# off the stack -- ArgumentDescriptor applies only to arguments embedded in
+# the opcode stream, immediately following an opcode.
+
+# Represents the number of bytes consumed by an argument delimited by the
+# next newline character.
+UP_TO_NEWLINE = -1
+
+# Represents the number of bytes consumed by a two-argument opcode where
+# the first argument gives the number of bytes in the second argument.
+TAKEN_FROM_ARGUMENT1 = -2   # num bytes is 1-byte unsigned int
+TAKEN_FROM_ARGUMENT4 = -3   # num bytes is 4-byte signed little-endian int
+
+class ArgumentDescriptor(object):
+    __slots__ = (
+        # name of descriptor record, also a module global name; a string
+        'name',
+
+        # length of argument, in bytes; an int; UP_TO_NEWLINE and
+        # TAKEN_FROM_ARGUMENT{1,4} are negative values for variable-length
+        # cases
+        'n',
+
+        # a function taking a file-like object, reading this kind of argument
+        # from the object at the current position, advancing the current
+        # position by n bytes, and returning the value of the argument
+        'reader',
+
+        # human-readable docs for this arg descriptor; a string
+        'doc',
+    )
+
+    def __init__(self, name, n, reader, doc):
+        assert isinstance(name, str)
+        self.name = name
+
+        assert isinstance(n, int) and (n >= 0 or
+                                       n in (UP_TO_NEWLINE,
+                                             TAKEN_FROM_ARGUMENT1,
+                                             TAKEN_FROM_ARGUMENT4))
+        self.n = n
+
+        self.reader = reader
+
+        assert isinstance(doc, str)
+        self.doc = doc
+
+from struct import unpack as _unpack
+
+def read_uint1(f):
+    r"""
+    >>> import StringIO
+    >>> read_uint1(StringIO.StringIO('\xff'))
+    255
+    """
+
+    data = f.read(1)
+    if data:
+        return ord(data)
+    raise ValueError("not enough data in stream to read uint1")
+
+uint1 = ArgumentDescriptor(
+            name='uint1',
+            n=1,
+            reader=read_uint1,
+            doc="One-byte unsigned integer.")
+
+
+def read_uint2(f):
+    r"""
+    >>> import StringIO
+    >>> read_uint2(StringIO.StringIO('\xff\x00'))
+    255
+    >>> read_uint2(StringIO.StringIO('\xff\xff'))
+    65535
+    """
+
+    data = f.read(2)
+    if len(data) == 2:
+        return _unpack("<H", data)[0]
+    raise ValueError("not enough data in stream to read uint2")
+
+uint2 = ArgumentDescriptor(
+            name='uint2',
+            n=2,
+            reader=read_uint2,
+            doc="Two-byte unsigned integer, little-endian.")
+
+
+def read_int4(f):
+    r"""
+    >>> import StringIO
+    >>> read_int4(StringIO.StringIO('\xff\x00\x00\x00'))
+    255
+    >>> read_int4(StringIO.StringIO('\x00\x00\x00\x80')) == -(2**31)
+    True
+    """
+
+    data = f.read(4)
+    if len(data) == 4:
+        return _unpack("<i", data)[0]
+    raise ValueError("not enough data in stream to read int4")
+
+int4 = ArgumentDescriptor(
+           name='int4',
+           n=4,
+           reader=read_int4,
+           doc="Four-byte signed integer, little-endian, 2's complement.")
+
+
+def read_stringnl(f, decode=True, stripquotes=True):
+    r"""
+    >>> import StringIO
+    >>> read_stringnl(StringIO.StringIO("'abcd'\nefg\n"))
+    'abcd'
+
+    >>> read_stringnl(StringIO.StringIO("\n"))
+    Traceback (most recent call last):
+    ...
+    ValueError: no string quotes around ''
+
+    >>> read_stringnl(StringIO.StringIO("\n"), stripquotes=False)
+    ''
+
+    >>> read_stringnl(StringIO.StringIO("''\n"))
+    ''
+
+    >>> read_stringnl(StringIO.StringIO('"abcd"'))
+    Traceback (most recent call last):
+    ...
+    ValueError: no newline found when trying to read stringnl
+
+    Embedded escapes are undone in the result.
+    >>> read_stringnl(StringIO.StringIO(r"'a\n\\b\x00c\td'" + "\n'e'"))
+    'a\n\\b\x00c\td'
+    """
+
+    data = f.readline()
+    if not data.endswith('\n'):
+        raise ValueError("no newline found when trying to read stringnl")
+    data = data[:-1]    # lose the newline
+
+    if stripquotes:
+        for q in "'\"":
+            if data.startswith(q):
+                if not data.endswith(q):
+                    raise ValueError("strinq quote %r not found at both "
+                                     "ends of %r" % (q, data))
+                data = data[1:-1]
+                break
+        else:
+            raise ValueError("no string quotes around %r" % data)
+
+    # I'm not sure when 'string_escape' was added to the std codecs; it's
+    # crazy not to use it if it's there.
+    if decode:
+        data = data.decode('string_escape')
+    return data
+
+stringnl = ArgumentDescriptor(
+               name='stringnl',
+               n=UP_TO_NEWLINE,
+               reader=read_stringnl,
+               doc="""A newline-terminated string.
+
+                   This is a repr-style string, with embedded escapes, and
+                   bracketing quotes.
+                   """)
+
+def read_stringnl_noescape(f):
+    return read_stringnl(f, decode=False, stripquotes=False)
+
+stringnl_noescape = ArgumentDescriptor(
+                        name='stringnl_noescape',
+                        n=UP_TO_NEWLINE,
+                        reader=read_stringnl_noescape,
+                        doc="""A newline-terminated string.
+
+                        This is a str-style string, without embedded escapes,
+                        or bracketing quotes.  It should consist solely of
+                        printable ASCII characters.
+                        """)
+
+def read_stringnl_noescape_pair(f):
+    r"""
+    >>> import StringIO
+    >>> read_stringnl_noescape_pair(StringIO.StringIO("Queue\nEmpty\njunk"))
+    'Queue Empty'
+    """
+
+    return "%s %s" % (read_stringnl_noescape(f), read_stringnl_noescape(f))
+
+stringnl_noescape_pair = ArgumentDescriptor(
+                             name='stringnl_noescape_pair',
+                             n=UP_TO_NEWLINE,
+                             reader=read_stringnl_noescape_pair,
+                             doc="""A pair of newline-terminated strings.
+
+                             These are str-style strings, without embedded
+                             escapes, or bracketing quotes.  They should
+                             consist solely of printable ASCII characters.
+                             The pair is returned as a single string, with
+                             a single blank separating the two strings.
+                             """)
+
+def read_string4(f):
+    r"""
+    >>> import StringIO
+    >>> read_string4(StringIO.StringIO("\x00\x00\x00\x00abc"))
+    ''
+    >>> read_string4(StringIO.StringIO("\x03\x00\x00\x00abcdef"))
+    'abc'
+    >>> read_string4(StringIO.StringIO("\x00\x00\x00\x03abcdef"))
+    Traceback (most recent call last):
+    ...
+    ValueError: expected 50331648 bytes in a string4, but only 6 remain
+    """
+
+    n = read_int4(f)
+    if n < 0:
+        raise ValueError("string4 byte count < 0: %d" % n)
+    data = f.read(n)
+    if len(data) == n:
+        return data
+    raise ValueError("expected %d bytes in a string4, but only %d remain" %
+                     (n, len(data)))
+
+string4 = ArgumentDescriptor(
+              name="string4",
+              n=TAKEN_FROM_ARGUMENT4,
+              reader=read_string4,
+              doc="""A counted string.
+
+              The first argument is a 4-byte little-endian signed int giving
+              the number of bytes in the string, and the second argument is
+              that many bytes.
+              """)
+
+
+def read_string1(f):
+    r"""
+    >>> import StringIO
+    >>> read_string1(StringIO.StringIO("\x00"))
+    ''
+    >>> read_string1(StringIO.StringIO("\x03abcdef"))
+    'abc'
+    """
+
+    n = read_uint1(f)
+    assert n >= 0
+    data = f.read(n)
+    if len(data) == n:
+        return data
+    raise ValueError("expected %d bytes in a string1, but only %d remain" %
+                     (n, len(data)))
+
+string1 = ArgumentDescriptor(
+              name="string1",
+              n=TAKEN_FROM_ARGUMENT1,
+              reader=read_string1,
+              doc="""A counted string.
+
+              The first argument is a 1-byte unsigned int giving the number
+              of bytes in the string, and the second argument is that many
+              bytes.
+              """)
+
+
+def read_unicodestringnl(f):
+    r"""
+    >>> import StringIO
+    >>> read_unicodestringnl(StringIO.StringIO("abc\uabcd\njunk"))
+    u'abc\uabcd'
+    """
+
+    data = f.readline()
+    if not data.endswith('\n'):
+        raise ValueError("no newline found when trying to read "
+                         "unicodestringnl")
+    data = data[:-1]    # lose the newline
+    return unicode(data, 'raw-unicode-escape')
+
+unicodestringnl = ArgumentDescriptor(
+                      name='unicodestringnl',
+                      n=UP_TO_NEWLINE,
+                      reader=read_unicodestringnl,
+                      doc="""A newline-terminated Unicode string.
+
+                      This is raw-unicode-escape encoded, so consists of
+                      printable ASCII characters, and may contain embedded
+                      escape sequences.
+                      """)
+
+def read_unicodestring4(f):
+    r"""
+    >>> import StringIO
+    >>> s = u'abcd\uabcd'
+    >>> enc = s.encode('utf-8')
+    >>> enc
+    'abcd\xea\xaf\x8d'
+    >>> n = chr(len(enc)) + chr(0) * 3  # little-endian 4-byte length
+    >>> t = read_unicodestring4(StringIO.StringIO(n + enc + 'junk'))
+    >>> s == t
+    True
+
+    >>> read_unicodestring4(StringIO.StringIO(n + enc[:-1]))
+    Traceback (most recent call last):
+    ...
+    ValueError: expected 7 bytes in a unicodestring4, but only 6 remain
+    """
+
+    n = read_int4(f)
+    if n < 0:
+        raise ValueError("unicodestring4 byte count < 0: %d" % n)
+    data = f.read(n)
+    if len(data) == n:
+        return unicode(data, 'utf-8')
+    raise ValueError("expected %d bytes in a unicodestring4, but only %d "
+                     "remain" % (n, len(data)))
+
+unicodestring4 = ArgumentDescriptor(
+                    name="unicodestring4",
+                    n=TAKEN_FROM_ARGUMENT4,
+                    reader=read_unicodestring4,
+                    doc="""A counted Unicode string.
+
+                    The first argument is a 4-byte little-endian signed int
+                    giving the number of bytes in the string, and the second
+                    argument-- the UTF-8 encoding of the Unicode string --
+                    contains that many bytes.
+                    """)
+
+
+def read_decimalnl_short(f):
+    r"""
+    >>> import StringIO
+    >>> read_decimalnl_short(StringIO.StringIO("1234\n56"))
+    1234
+
+    >>> read_decimalnl_short(StringIO.StringIO("1234L\n56"))
+    Traceback (most recent call last):
+    ...
+    ValueError: trailing 'L' not allowed in '1234L'
+    """
+
+    s = read_stringnl(f, decode=False, stripquotes=False)
+    if s.endswith("L"):
+        raise ValueError("trailing 'L' not allowed in %r" % s)
+
+    # It's not necessarily true that the result fits in a Python short int:
+    # the pickle may have been written on a 64-bit box.  There's also a hack
+    # for True and False here.
+    if s == "00":
+        return False
+    elif s == "01":
+        return True
+
+    try:
+        return int(s)
+    except OverflowError:
+        return long(s)
+
+def read_decimalnl_long(f):
+    r"""
+    >>> import StringIO
+
+    >>> read_decimalnl_long(StringIO.StringIO("1234\n56"))
+    Traceback (most recent call last):
+    ...
+    ValueError: trailing 'L' required in '1234'
+
+    Someday the trailing 'L' will probably go away from this output.
+
+    >>> read_decimalnl_long(StringIO.StringIO("1234L\n56"))
+    1234L
+
+    >>> read_decimalnl_long(StringIO.StringIO("123456789012345678901234L\n6"))
+    123456789012345678901234L
+    """
+
+    s = read_stringnl(f, decode=False, stripquotes=False)
+    if not s.endswith("L"):
+        raise ValueError("trailing 'L' required in %r" % s)
+    return long(s)
+
+
+decimalnl_short = ArgumentDescriptor(
+                      name='decimalnl_short',
+                      n=UP_TO_NEWLINE,
+                      reader=read_decimalnl_short,
+                      doc="""A newline-terminated decimal integer literal.
+
+                          This never has a trailing 'L', and the integer fit
+                          in a short Python int on the box where the pickle
+                          was written -- but there's no guarantee it will fit
+                          in a short Python int on the box where the pickle
+                          is read.
+                          """)
+
+decimalnl_long = ArgumentDescriptor(
+                     name='decimalnl_long',
+                     n=UP_TO_NEWLINE,
+                     reader=read_decimalnl_long,
+                     doc="""A newline-terminated decimal integer literal.
+
+                         This has a trailing 'L', and can represent integers
+                         of any size.
+                         """)
+
+
+def read_floatnl(f):
+    r"""
+    >>> import StringIO
+    >>> read_floatnl(StringIO.StringIO("-1.25\n6"))
+    -1.25
+    """
+    s = read_stringnl(f, decode=False, stripquotes=False)
+    return float(s)
+
+floatnl = ArgumentDescriptor(
+              name='floatnl',
+              n=UP_TO_NEWLINE,
+              reader=read_floatnl,
+              doc="""A newline-terminated decimal floating literal.
+
+              In general this requires 17 significant digits for roundtrip
+              identity, and pickling then unpickling infinities, NaNs, and
+              minus zero doesn't work across boxes, or on some boxes even
+              on itself (e.g., Windows can't read the strings it produces
+              for infinities or NaNs).
+              """)
+
+def read_float8(f):
+    r"""
+    >>> import StringIO, struct
+    >>> raw = struct.pack(">d", -1.25)
+    >>> raw
+    '\xbf\xf4\x00\x00\x00\x00\x00\x00'
+    >>> read_float8(StringIO.StringIO(raw + "\n"))
+    -1.25
+    """
+
+    data = f.read(8)
+    if len(data) == 8:
+        return _unpack(">d", data)[0]
+    raise ValueError("not enough data in stream to read float8")
+
+
+float8 = ArgumentDescriptor(
+             name='float8',
+             n=8,
+             reader=read_float8,
+             doc="""An 8-byte binary representation of a float, big-endian.
+
+             The format is unique to Python, and shared with the struct
+             module (format string '>d') "in theory" (the struct and cPickle
+             implementations don't share the code -- they should).  It's
+             strongly related to the IEEE-754 double format, and, in normal
+             cases, is in fact identical to the big-endian 754 double format.
+             On other boxes the dynamic range is limited to that of a 754
+             double, and "add a half and chop" rounding is used to reduce
+             the precision to 53 bits.  However, even on a 754 box,
+             infinities, NaNs, and minus zero may not be handled correctly
+             (may not survive roundtrip pickling intact).
+             """)
+
+# Protocol 2 formats
+
+from pickle import decode_long
+
+def read_long1(f):
+    r"""
+    >>> import StringIO
+    >>> read_long1(StringIO.StringIO("\x00"))
+    0L
+    >>> read_long1(StringIO.StringIO("\x02\xff\x00"))
+    255L
+    >>> read_long1(StringIO.StringIO("\x02\xff\x7f"))
+    32767L
+    >>> read_long1(StringIO.StringIO("\x02\x00\xff"))
+    -256L
+    >>> read_long1(StringIO.StringIO("\x02\x00\x80"))
+    -32768L
+    """
+
+    n = read_uint1(f)
+    data = f.read(n)
+    if len(data) != n:
+        raise ValueError("not enough data in stream to read long1")
+    return decode_long(data)
+
+long1 = ArgumentDescriptor(
+    name="long1",
+    n=TAKEN_FROM_ARGUMENT1,
+    reader=read_long1,
+    doc="""A binary long, little-endian, using 1-byte size.
+
+    This first reads one byte as an unsigned size, then reads that
+    many bytes and interprets them as a little-endian 2's-complement long.
+    If the size is 0, that's taken as a shortcut for the long 0L.
+    """)
+
+def read_long4(f):
+    r"""
+    >>> import StringIO
+    >>> read_long4(StringIO.StringIO("\x02\x00\x00\x00\xff\x00"))
+    255L
+    >>> read_long4(StringIO.StringIO("\x02\x00\x00\x00\xff\x7f"))
+    32767L
+    >>> read_long4(StringIO.StringIO("\x02\x00\x00\x00\x00\xff"))
+    -256L
+    >>> read_long4(StringIO.StringIO("\x02\x00\x00\x00\x00\x80"))
+    -32768L
+    >>> read_long1(StringIO.StringIO("\x00\x00\x00\x00"))
+    0L
+    """
+
+    n = read_int4(f)
+    if n < 0:
+        raise ValueError("long4 byte count < 0: %d" % n)
+    data = f.read(n)
+    if len(data) != n:
+        raise ValueError("not enough data in stream to read long4")
+    return decode_long(data)
+
+long4 = ArgumentDescriptor(
+    name="long4",
+    n=TAKEN_FROM_ARGUMENT4,
+    reader=read_long4,
+    doc="""A binary representation of a long, little-endian.
+
+    This first reads four bytes as a signed size (but requires the
+    size to be >= 0), then reads that many bytes and interprets them
+    as a little-endian 2's-complement long.  If the size is 0, that's taken
+    as a shortcut for the long 0L, although LONG1 should really be used
+    then instead (and in any case where # of bytes < 256).
+    """)
+
+
+##############################################################################
+# Object descriptors.  The stack used by the pickle machine holds objects,
+# and in the stack_before and stack_after attributes of OpcodeInfo
+# descriptors we need names to describe the various types of objects that can
+# appear on the stack.
+
+class StackObject(object):
+    __slots__ = (
+        # name of descriptor record, for info only
+        'name',
+
+        # type of object, or tuple of type objects (meaning the object can
+        # be of any type in the tuple)
+        'obtype',
+
+        # human-readable docs for this kind of stack object; a string
+        'doc',
+    )
+
+    def __init__(self, name, obtype, doc):
+        assert isinstance(name, str)
+        self.name = name
+
+        assert isinstance(obtype, type) or isinstance(obtype, tuple)
+        if isinstance(obtype, tuple):
+            for contained in obtype:
+                assert isinstance(contained, type)
+        self.obtype = obtype
+
+        assert isinstance(doc, str)
+        self.doc = doc
+
+    def __repr__(self):
+        return self.name
+
+
+pyint = StackObject(
+            name='int',
+            obtype=int,
+            doc="A short (as opposed to long) Python integer object.")
+
+pylong = StackObject(
+             name='long',
+             obtype=long,
+             doc="A long (as opposed to short) Python integer object.")
+
+pyinteger_or_bool = StackObject(
+                        name='int_or_bool',
+                        obtype=(int, long, bool),
+                        doc="A Python integer object (short or long), or "
+                            "a Python bool.")
+
+pybool = StackObject(
+             name='bool',
+             obtype=(bool,),
+             doc="A Python bool object.")
+
+pyfloat = StackObject(
+              name='float',
+              obtype=float,
+              doc="A Python float object.")
+
+pystring = StackObject(
+               name='str',
+               obtype=str,
+               doc="A Python string object.")
+
+pyunicode = StackObject(
+                name='unicode',
+                obtype=unicode,
+                doc="A Python Unicode string object.")
+
+pynone = StackObject(
+             name="None",
+             obtype=type(None),
+             doc="The Python None object.")
+
+pytuple = StackObject(
+              name="tuple",
+              obtype=tuple,
+              doc="A Python tuple object.")
+
+pylist = StackObject(
+             name="list",
+             obtype=list,
+             doc="A Python list object.")
+
+pydict = StackObject(
+             name="dict",
+             obtype=dict,
+             doc="A Python dict object.")
+
+anyobject = StackObject(
+                name='any',
+                obtype=object,
+                doc="Any kind of object whatsoever.")
+
+markobject = StackObject(
+                 name="mark",
+                 obtype=StackObject,
+                 doc="""'The mark' is a unique object.
+
+                 Opcodes that operate on a variable number of objects
+                 generally don't embed the count of objects in the opcode,
+                 or pull it off the stack.  Instead the MARK opcode is used
+                 to push a special marker object on the stack, and then
+                 some other opcodes grab all the objects from the top of
+                 the stack down to (but not including) the topmost marker
+                 object.
+                 """)
+
+stackslice = StackObject(
+                 name="stackslice",
+                 obtype=StackObject,
+                 doc="""An object representing a contiguous slice of the stack.
+
+                 This is used in conjuction with markobject, to represent all
+                 of the stack following the topmost markobject.  For example,
+                 the POP_MARK opcode changes the stack from
+
+                     [..., markobject, stackslice]
+                 to
+                     [...]
+
+                 No matter how many object are on the stack after the topmost
+                 markobject, POP_MARK gets rid of all of them (including the
+                 topmost markobject too).
+                 """)
+
+##############################################################################
+# Descriptors for pickle opcodes.
+
+class OpcodeInfo(object):
+
+    __slots__ = (
+        # symbolic name of opcode; a string
+        'name',
+
+        # the code used in a bytestream to represent the opcode; a
+        # one-character string
+        'code',
+
+        # If the opcode has an argument embedded in the byte string, an
+        # instance of ArgumentDescriptor specifying its type.  Note that
+        # arg.reader(s) can be used to read and decode the argument from
+        # the bytestream s, and arg.doc documents the format of the raw
+        # argument bytes.  If the opcode doesn't have an argument embedded
+        # in the bytestream, arg should be None.
+        'arg',
+
+        # what the stack looks like before this opcode runs; a list
+        'stack_before',
+
+        # what the stack looks like after this opcode runs; a list
+        'stack_after',
+
+        # the protocol number in which this opcode was introduced; an int
+        'proto',
+
+        # human-readable docs for this opcode; a string
+        'doc',
+    )
+
+    def __init__(self, name, code, arg,
+                 stack_before, stack_after, proto, doc):
+        assert isinstance(name, str)
+        self.name = name
+
+        assert isinstance(code, str)
+        assert len(code) == 1
+        self.code = code
+
+        assert arg is None or isinstance(arg, ArgumentDescriptor)
+        self.arg = arg
+
+        assert isinstance(stack_before, list)
+        for x in stack_before:
+            assert isinstance(x, StackObject)
+        self.stack_before = stack_before
+
+        assert isinstance(stack_after, list)
+        for x in stack_after:
+            assert isinstance(x, StackObject)
+        self.stack_after = stack_after
+
+        assert isinstance(proto, int) and 0 <= proto <= 2
+        self.proto = proto
+
+        assert isinstance(doc, str)
+        self.doc = doc
+
+I = OpcodeInfo
+opcodes = [
+
+    # Ways to spell integers.
+
+    I(name='INT',
+      code='I',
+      arg=decimalnl_short,
+      stack_before=[],
+      stack_after=[pyinteger_or_bool],
+      proto=0,
+      doc="""Push an integer or bool.
+
+      The argument is a newline-terminated decimal literal string.
+
+      The intent may have been that this always fit in a short Python int,
+      but INT can be generated in pickles written on a 64-bit box that
+      require a Python long on a 32-bit box.  The difference between this
+      and LONG then is that INT skips a trailing 'L', and produces a short
+      int whenever possible.
+
+      Another difference is due to that, when bool was introduced as a
+      distinct type in 2.3, builtin names True and False were also added to
+      2.2.2, mapping to ints 1 and 0.  For compatibility in both directions,
+      True gets pickled as INT + "I01\\n", and False as INT + "I00\\n".
+      Leading zeroes are never produced for a genuine integer.  The 2.3
+      (and later) unpicklers special-case these and return bool instead;
+      earlier unpicklers ignore the leading "0" and return the int.
+      """),
+
+    I(name='BININT',
+      code='J',
+      arg=int4,
+      stack_before=[],
+      stack_after=[pyint],
+      proto=1,
+      doc="""Push a four-byte signed integer.
+
+      This handles the full range of Python (short) integers on a 32-bit
+      box, directly as binary bytes (1 for the opcode and 4 for the integer).
+      If the integer is non-negative and fits in 1 or 2 bytes, pickling via
+      BININT1 or BININT2 saves space.
+      """),
+
+    I(name='BININT1',
+      code='K',
+      arg=uint1,
+      stack_before=[],
+      stack_after=[pyint],
+      proto=1,
+      doc="""Push a one-byte unsigned integer.
+
+      This is a space optimization for pickling very small non-negative ints,
+      in range(256).
+      """),
+
+    I(name='BININT2',
+      code='M',
+      arg=uint2,
+      stack_before=[],
+      stack_after=[pyint],
+      proto=1,
+      doc="""Push a two-byte unsigned integer.
+
+      This is a space optimization for pickling small positive ints, in
+      range(256, 2**16).  Integers in range(256) can also be pickled via
+      BININT2, but BININT1 instead saves a byte.
+      """),
+
+    I(name='LONG',
+      code='L',
+      arg=decimalnl_long,
+      stack_before=[],
+      stack_after=[pylong],
+      proto=0,
+      doc="""Push a long integer.
+
+      The same as INT, except that the literal ends with 'L', and always
+      unpickles to a Python long.  There doesn't seem a real purpose to the
+      trailing 'L'.
+
+      Note that LONG takes time quadratic in the number of digits when
+      unpickling (this is simply due to the nature of decimal->binary
+      conversion).  Proto 2 added linear-time (in C; still quadratic-time
+      in Python) LONG1 and LONG4 opcodes.
+      """),
+
+    I(name="LONG1",
+      code='\x8a',
+      arg=long1,
+      stack_before=[],
+      stack_after=[pylong],
+      proto=2,
+      doc="""Long integer using one-byte length.
+
+      A more efficient encoding of a Python long; the long1 encoding
+      says it all."""),
+
+    I(name="LONG4",
+      code='\x8b',
+      arg=long4,
+      stack_before=[],
+      stack_after=[pylong],
+      proto=2,
+      doc="""Long integer using found-byte length.
+
+      A more efficient encoding of a Python long; the long4 encoding
+      says it all."""),
+
+    # Ways to spell strings (8-bit, not Unicode).
+
+    I(name='STRING',
+      code='S',
+      arg=stringnl,
+      stack_before=[],
+      stack_after=[pystring],
+      proto=0,
+      doc="""Push a Python string object.
+
+      The argument is a repr-style string, with bracketing quote characters,
+      and perhaps embedded escapes.  The argument extends until the next
+      newline character.
+      """),
+
+    I(name='BINSTRING',
+      code='T',
+      arg=string4,
+      stack_before=[],
+      stack_after=[pystring],
+      proto=1,
+      doc="""Push a Python string object.
+
+      There are two arguments:  the first is a 4-byte little-endian signed int
+      giving the number of bytes in the string, and the second is that many
+      bytes, which are taken literally as the string content.
+      """),
+
+    I(name='SHORT_BINSTRING',
+      code='U',
+      arg=string1,
+      stack_before=[],
+      stack_after=[pystring],
+      proto=1,
+      doc="""Push a Python string object.
+
+      There are two arguments:  the first is a 1-byte unsigned int giving
+      the number of bytes in the string, and the second is that many bytes,
+      which are taken literally as the string content.
+      """),
+
+    # Ways to spell None.
+
+    I(name='NONE',
+      code='N',
+      arg=None,
+      stack_before=[],
+      stack_after=[pynone],
+      proto=0,
+      doc="Push None on the stack."),
+
+    # Ways to spell bools, starting with proto 2.  See INT for how this was
+    # done before proto 2.
+
+    I(name='NEWTRUE',
+      code='\x88',
+      arg=None,
+      stack_before=[],
+      stack_after=[pybool],
+      proto=2,
+      doc="""True.
+
+      Push True onto the stack."""),
+
+    I(name='NEWFALSE',
+      code='\x89',
+      arg=None,
+      stack_before=[],
+      stack_after=[pybool],
+      proto=2,
+      doc="""True.
+
+      Push False onto the stack."""),
+
+    # Ways to spell Unicode strings.
+
+    I(name='UNICODE',
+      code='V',
+      arg=unicodestringnl,
+      stack_before=[],
+      stack_after=[pyunicode],
+      proto=0,  # this may be pure-text, but it's a later addition
+      doc="""Push a Python Unicode string object.
+
+      The argument is a raw-unicode-escape encoding of a Unicode string,
+      and so may contain embedded escape sequences.  The argument extends
+      until the next newline character.
+      """),
+
+    I(name='BINUNICODE',
+      code='X',
+      arg=unicodestring4,
+      stack_before=[],
+      stack_after=[pyunicode],
+      proto=1,
+      doc="""Push a Python Unicode string object.
+
+      There are two arguments:  the first is a 4-byte little-endian signed int
+      giving the number of bytes in the string.  The second is that many
+      bytes, and is the UTF-8 encoding of the Unicode string.
+      """),
+
+    # Ways to spell floats.
+
+    I(name='FLOAT',
+      code='F',
+      arg=floatnl,
+      stack_before=[],
+      stack_after=[pyfloat],
+      proto=0,
+      doc="""Newline-terminated decimal float literal.
+
+      The argument is repr(a_float), and in general requires 17 significant
+      digits for roundtrip conversion to be an identity (this is so for
+      IEEE-754 double precision values, which is what Python float maps to
+      on most boxes).
+
+      In general, FLOAT cannot be used to transport infinities, NaNs, or
+      minus zero across boxes (or even on a single box, if the platform C
+      library can't read the strings it produces for such things -- Windows
+      is like that), but may do less damage than BINFLOAT on boxes with
+      greater precision or dynamic range than IEEE-754 double.
+      """),
+
+    I(name='BINFLOAT',
+      code='G',
+      arg=float8,
+      stack_before=[],
+      stack_after=[pyfloat],
+      proto=1,
+      doc="""Float stored in binary form, with 8 bytes of data.
+
+      This generally requires less than half the space of FLOAT encoding.
+      In general, BINFLOAT cannot be used to transport infinities, NaNs, or
+      minus zero, raises an exception if the exponent exceeds the range of
+      an IEEE-754 double, and retains no more than 53 bits of precision (if
+      there are more than that, "add a half and chop" rounding is used to
+      cut it back to 53 significant bits).
+      """),
+
+    # Ways to build lists.
+
+    I(name='EMPTY_LIST',
+      code=']',
+      arg=None,
+      stack_before=[],
+      stack_after=[pylist],
+      proto=1,
+      doc="Push an empty list."),
+
+    I(name='APPEND',
+      code='a',
+      arg=None,
+      stack_before=[pylist, anyobject],
+      stack_after=[pylist],
+      proto=0,
+      doc="""Append an object to a list.
+
+      Stack before:  ... pylist anyobject
+      Stack after:   ... pylist+[anyobject]
+
+      although pylist is really extended in-place.
+      """),
+
+    I(name='APPENDS',
+      code='e',
+      arg=None,
+      stack_before=[pylist, markobject, stackslice],
+      stack_after=[pylist],
+      proto=1,
+      doc="""Extend a list by a slice of stack objects.
+
+      Stack before:  ... pylist markobject stackslice
+      Stack after:   ... pylist+stackslice
+
+      although pylist is really extended in-place.
+      """),
+
+    I(name='LIST',
+      code='l',
+      arg=None,
+      stack_before=[markobject, stackslice],
+      stack_after=[pylist],
+      proto=0,
+      doc="""Build a list out of the topmost stack slice, after markobject.
+
+      All the stack entries following the topmost markobject are placed into
+      a single Python list, which single list object replaces all of the
+      stack from the topmost markobject onward.  For example,
+
+      Stack before: ... markobject 1 2 3 'abc'
+      Stack after:  ... [1, 2, 3, 'abc']
+      """),
+
+    # Ways to build tuples.
+
+    I(name='EMPTY_TUPLE',
+      code=')',
+      arg=None,
+      stack_before=[],
+      stack_after=[pytuple],
+      proto=1,
+      doc="Push an empty tuple."),
+
+    I(name='TUPLE',
+      code='t',
+      arg=None,
+      stack_before=[markobject, stackslice],
+      stack_after=[pytuple],
+      proto=0,
+      doc="""Build a tuple out of the topmost stack slice, after markobject.
+
+      All the stack entries following the topmost markobject are placed into
+      a single Python tuple, which single tuple object replaces all of the
+      stack from the topmost markobject onward.  For example,
+
+      Stack before: ... markobject 1 2 3 'abc'
+      Stack after:  ... (1, 2, 3, 'abc')
+      """),
+
+    I(name='TUPLE1',
+      code='\x85',
+      arg=None,
+      stack_before=[anyobject],
+      stack_after=[pytuple],
+      proto=2,
+      doc="""Build a one-tuple out of the topmost item on the stack.
+
+      This code pops one value off the stack and pushes a tuple of
+      length 1 whose one item is that value back onto it.  In other
+      words:
+
+          stack[-1] = tuple(stack[-1:])
+      """),
+
+    I(name='TUPLE2',
+      code='\x86',
+      arg=None,
+      stack_before=[anyobject, anyobject],
+      stack_after=[pytuple],
+      proto=2,
+      doc="""Build a two-tuple out of the top two items on the stack.
+
+      This code pops two values off the stack and pushes a tuple of
+      length 2 whose items are those values back onto it.  In other
+      words:
+
+          stack[-2:] = [tuple(stack[-2:])]
+      """),
+
+    I(name='TUPLE3',
+      code='\x87',
+      arg=None,
+      stack_before=[anyobject, anyobject, anyobject],
+      stack_after=[pytuple],
+      proto=2,
+      doc="""Build a three-tuple out of the top three items on the stack.
+
+      This code pops three values off the stack and pushes a tuple of
+      length 3 whose items are those values back onto it.  In other
+      words:
+
+          stack[-3:] = [tuple(stack[-3:])]
+      """),
+
+    # Ways to build dicts.
+
+    I(name='EMPTY_DICT',
+      code='}',
+      arg=None,
+      stack_before=[],
+      stack_after=[pydict],
+      proto=1,
+      doc="Push an empty dict."),
+
+    I(name='DICT',
+      code='d',
+      arg=None,
+      stack_before=[markobject, stackslice],
+      stack_after=[pydict],
+      proto=0,
+      doc="""Build a dict out of the topmost stack slice, after markobject.
+
+      All the stack entries following the topmost markobject are placed into
+      a single Python dict, which single dict object replaces all of the
+      stack from the topmost markobject onward.  The stack slice alternates
+      key, value, key, value, ....  For example,
+
+      Stack before: ... markobject 1 2 3 'abc'
+      Stack after:  ... {1: 2, 3: 'abc'}
+      """),
+
+    I(name='SETITEM',
+      code='s',
+      arg=None,
+      stack_before=[pydict, anyobject, anyobject],
+      stack_after=[pydict],
+      proto=0,
+      doc="""Add a key+value pair to an existing dict.
+
+      Stack before:  ... pydict key value
+      Stack after:   ... pydict
+
+      where pydict has been modified via pydict[key] = value.
+      """),
+
+    I(name='SETITEMS',
+      code='u',
+      arg=None,
+      stack_before=[pydict, markobject, stackslice],
+      stack_after=[pydict],
+      proto=1,
+      doc="""Add an arbitrary number of key+value pairs to an existing dict.
+
+      The slice of the stack following the topmost markobject is taken as
+      an alternating sequence of keys and values, added to the dict
+      immediately under the topmost markobject.  Everything at and after the
+      topmost markobject is popped, leaving the mutated dict at the top
+      of the stack.
+
+      Stack before:  ... pydict markobject key_1 value_1 ... key_n value_n
+      Stack after:   ... pydict
+
+      where pydict has been modified via pydict[key_i] = value_i for i in
+      1, 2, ..., n, and in that order.
+      """),
+
+    # Stack manipulation.
+
+    I(name='POP',
+      code='0',
+      arg=None,
+      stack_before=[anyobject],
+      stack_after=[],
+      proto=0,
+      doc="Discard the top stack item, shrinking the stack by one item."),
+
+    I(name='DUP',
+      code='2',
+      arg=None,
+      stack_before=[anyobject],
+      stack_after=[anyobject, anyobject],
+      proto=0,
+      doc="Push the top stack item onto the stack again, duplicating it."),
+
+    I(name='MARK',
+      code='(',
+      arg=None,
+      stack_before=[],
+      stack_after=[markobject],
+      proto=0,
+      doc="""Push markobject onto the stack.
+
+      markobject is a unique object, used by other opcodes to identify a
+      region of the stack containing a variable number of objects for them
+      to work on.  See markobject.doc for more detail.
+      """),
+
+    I(name='POP_MARK',
+      code='1',
+      arg=None,
+      stack_before=[markobject, stackslice],
+      stack_after=[],
+      proto=1,
+      doc="""Pop all the stack objects at and above the topmost markobject.
+
+      When an opcode using a variable number of stack objects is done,
+      POP_MARK is used to remove those objects, and to remove the markobject
+      that delimited their starting position on the stack.
+      """),
+
+    # Memo manipulation.  There are really only two operations (get and put),
+    # each in all-text, "short binary", and "long binary" flavors.
+
+    I(name='GET',
+      code='g',
+      arg=decimalnl_short,
+      stack_before=[],
+      stack_after=[anyobject],
+      proto=0,
+      doc="""Read an object from the memo and push it on the stack.
+
+      The index of the memo object to push is given by the newline-terminated
+      decimal string following.  BINGET and LONG_BINGET are space-optimized
+      versions.
+      """),
+
+    I(name='BINGET',
+      code='h',
+      arg=uint1,
+      stack_before=[],
+      stack_after=[anyobject],
+      proto=1,
+      doc="""Read an object from the memo and push it on the stack.
+
+      The index of the memo object to push is given by the 1-byte unsigned
+      integer following.
+      """),
+
+    I(name='LONG_BINGET',
+      code='j',
+      arg=int4,
+      stack_before=[],
+      stack_after=[anyobject],
+      proto=1,
+      doc="""Read an object from the memo and push it on the stack.
+
+      The index of the memo object to push is given by the 4-byte signed
+      little-endian integer following.
+      """),
+
+    I(name='PUT',
+      code='p',
+      arg=decimalnl_short,
+      stack_before=[],
+      stack_after=[],
+      proto=0,
+      doc="""Store the stack top into the memo.  The stack is not popped.
+
+      The index of the memo location to write into is given by the newline-
+      terminated decimal string following.  BINPUT and LONG_BINPUT are
+      space-optimized versions.
+      """),
+
+    I(name='BINPUT',
+      code='q',
+      arg=uint1,
+      stack_before=[],
+      stack_after=[],
+      proto=1,
+      doc="""Store the stack top into the memo.  The stack is not popped.
+
+      The index of the memo location to write into is given by the 1-byte
+      unsigned integer following.
+      """),
+
+    I(name='LONG_BINPUT',
+      code='r',
+      arg=int4,
+      stack_before=[],
+      stack_after=[],
+      proto=1,
+      doc="""Store the stack top into the memo.  The stack is not popped.
+
+      The index of the memo location to write into is given by the 4-byte
+      signed little-endian integer following.
+      """),
+
+    # Access the extension registry (predefined objects).  Akin to the GET
+    # family.
+
+    I(name='EXT1',
+      code='\x82',
+      arg=uint1,
+      stack_before=[],
+      stack_after=[anyobject],
+      proto=2,
+      doc="""Extension code.
+
+      This code and the similar EXT2 and EXT4 allow using a registry
+      of popular objects that are pickled by name, typically classes.
+      It is envisioned that through a global negotiation and
+      registration process, third parties can set up a mapping between
+      ints and object names.
+
+      In order to guarantee pickle interchangeability, the extension
+      code registry ought to be global, although a range of codes may
+      be reserved for private use.
+
+      EXT1 has a 1-byte integer argument.  This is used to index into the
+      extension registry, and the object at that index is pushed on the stack.
+      """),
+
+    I(name='EXT2',
+      code='\x83',
+      arg=uint2,
+      stack_before=[],
+      stack_after=[anyobject],
+      proto=2,
+      doc="""Extension code.
+
+      See EXT1.  EXT2 has a two-byte integer argument.
+      """),
+
+    I(name='EXT4',
+      code='\x84',
+      arg=int4,
+      stack_before=[],
+      stack_after=[anyobject],
+      proto=2,
+      doc="""Extension code.
+
+      See EXT1.  EXT4 has a four-byte integer argument.
+      """),
+
+    # Push a class object, or module function, on the stack, via its module
+    # and name.
+
+    I(name='GLOBAL',
+      code='c',
+      arg=stringnl_noescape_pair,
+      stack_before=[],
+      stack_after=[anyobject],
+      proto=0,
+      doc="""Push a global object (module.attr) on the stack.
+
+      Two newline-terminated strings follow the GLOBAL opcode.  The first is
+      taken as a module name, and the second as a class name.  The class
+      object module.class is pushed on the stack.  More accurately, the
+      object returned by self.find_class(module, class) is pushed on the
+      stack, so unpickling subclasses can override this form of lookup.
+      """),
+
+    # Ways to build objects of classes pickle doesn't know about directly
+    # (user-defined classes).  I despair of documenting this accurately
+    # and comprehensibly -- you really have to read the pickle code to
+    # find all the special cases.
+
+    I(name='REDUCE',
+      code='R',
+      arg=None,
+      stack_before=[anyobject, anyobject],
+      stack_after=[anyobject],
+      proto=0,
+      doc="""Push an object built from a callable and an argument tuple.
+
+      The opcode is named to remind of the __reduce__() method.
+
+      Stack before: ... callable pytuple
+      Stack after:  ... callable(*pytuple)
+
+      The callable and the argument tuple are the first two items returned
+      by a __reduce__ method.  Applying the callable to the argtuple is
+      supposed to reproduce the original object, or at least get it started.
+      If the __reduce__ method returns a 3-tuple, the last component is an
+      argument to be passed to the object's __setstate__, and then the REDUCE
+      opcode is followed by code to create setstate's argument, and then a
+      BUILD opcode to apply  __setstate__ to that argument.
+
+      If type(callable) is not ClassType, REDUCE complains unless the
+      callable has been registered with the copy_reg module's
+      safe_constructors dict, or the callable has a magic
+      '__safe_for_unpickling__' attribute with a true value.  I'm not sure
+      why it does this, but I've sure seen this complaint often enough when
+      I didn't want to <wink>.
+      """),
+
+    I(name='BUILD',
+      code='b',
+      arg=None,
+      stack_before=[anyobject, anyobject],
+      stack_after=[anyobject],
+      proto=0,
+      doc="""Finish building an object, via __setstate__ or dict update.
+
+      Stack before: ... anyobject argument
+      Stack after:  ... anyobject
+
+      where anyobject may have been mutated, as follows:
+
+      If the object has a __setstate__ method,
+
+          anyobject.__setstate__(argument)
+
+      is called.
+
+      Else the argument must be a dict, the object must have a __dict__, and
+      the object is updated via
+
+          anyobject.__dict__.update(argument)
+
+      This may raise RuntimeError in restricted execution mode (which
+      disallows access to __dict__ directly); in that case, the object
+      is updated instead via
+
+          for k, v in argument.items():
+              anyobject[k] = v
+      """),
+
+    I(name='INST',
+      code='i',
+      arg=stringnl_noescape_pair,
+      stack_before=[markobject, stackslice],
+      stack_after=[anyobject],
+      proto=0,
+      doc="""Build a class instance.
+
+      This is the protocol 0 version of protocol 1's OBJ opcode.
+      INST is followed by two newline-terminated strings, giving a
+      module and class name, just as for the GLOBAL opcode (and see
+      GLOBAL for more details about that).  self.find_class(module, name)
+      is used to get a class object.
+
+      In addition, all the objects on the stack following the topmost
+      markobject are gathered into a tuple and popped (along with the
+      topmost markobject), just as for the TUPLE opcode.
+
+      Now it gets complicated.  If all of these are true:
+
+        + The argtuple is empty (markobject was at the top of the stack
+          at the start).
+
+        + It's an old-style class object (the type of the class object is
+          ClassType).
+
+        + The class object does not have a __getinitargs__ attribute.
+
+      then we want to create an old-style class instance without invoking
+      its __init__() method (pickle has waffled on this over the years; not
+      calling __init__() is current wisdom).  In this case, an instance of
+      an old-style dummy class is created, and then we try to rebind its
+      __class__ attribute to the desired class object.  If this succeeds,
+      the new instance object is pushed on the stack, and we're done.  In
+      restricted execution mode it can fail (assignment to __class__ is
+      disallowed), and I'm not really sure what happens then -- it looks
+      like the code ends up calling the class object's __init__ anyway,
+      via falling into the next case.
+
+      Else (the argtuple is not empty, it's not an old-style class object,
+      or the class object does have a __getinitargs__ attribute), the code
+      first insists that the class object have a __safe_for_unpickling__
+      attribute.  Unlike as for the __safe_for_unpickling__ check in REDUCE,
+      it doesn't matter whether this attribute has a true or false value, it
+      only matters whether it exists (XXX this is a bug; cPickle
+      requires the attribute to be true).  If __safe_for_unpickling__
+      doesn't exist, UnpicklingError is raised.
+
+      Else (the class object does have a __safe_for_unpickling__ attr),
+      the class object obtained from INST's arguments is applied to the
+      argtuple obtained from the stack, and the resulting instance object
+      is pushed on the stack.
+
+      NOTE:  checks for __safe_for_unpickling__ went away in Python 2.3.
+      """),
+
+    I(name='OBJ',
+      code='o',
+      arg=None,
+      stack_before=[markobject, anyobject, stackslice],
+      stack_after=[anyobject],
+      proto=1,
+      doc="""Build a class instance.
+
+      This is the protocol 1 version of protocol 0's INST opcode, and is
+      very much like it.  The major difference is that the class object
+      is taken off the stack, allowing it to be retrieved from the memo
+      repeatedly if several instances of the same class are created.  This
+      can be much more efficient (in both time and space) than repeatedly
+      embedding the module and class names in INST opcodes.
+
+      Unlike INST, OBJ takes no arguments from the opcode stream.  Instead
+      the class object is taken off the stack, immediately above the
+      topmost markobject:
+
+      Stack before: ... markobject classobject stackslice
+      Stack after:  ... new_instance_object
+
+      As for INST, the remainder of the stack above the markobject is
+      gathered into an argument tuple, and then the logic seems identical,
+      except that no __safe_for_unpickling__ check is done (XXX this is
+      a bug; cPickle does test __safe_for_unpickling__).  See INST for
+      the gory details.
+
+      NOTE:  In Python 2.3, INST and OBJ are identical except for how they
+      get the class object.  That was always the intent; the implementations
+      had diverged for accidental reasons.
+      """),
+
+    I(name='NEWOBJ',
+      code='\x81',
+      arg=None,
+      stack_before=[anyobject, anyobject],
+      stack_after=[anyobject],
+      proto=2,
+      doc="""Build an object instance.
+
+      The stack before should be thought of as containing a class
+      object followed by an argument tuple (the tuple being the stack
+      top).  Call these cls and args.  They are popped off the stack,
+      and the value returned by cls.__new__(cls, *args) is pushed back
+      onto the stack.
+      """),
+
+    # Machine control.
+
+    I(name='PROTO',
+      code='\x80',
+      arg=uint1,
+      stack_before=[],
+      stack_after=[],
+      proto=2,
+      doc="""Protocol version indicator.
+
+      For protocol 2 and above, a pickle must start with this opcode.
+      The argument is the protocol version, an int in range(2, 256).
+      """),
+
+    I(name='STOP',
+      code='.',
+      arg=None,
+      stack_before=[anyobject],
+      stack_after=[],
+      proto=0,
+      doc="""Stop the unpickling machine.
+
+      Every pickle ends with this opcode.  The object at the top of the stack
+      is popped, and that's the result of unpickling.  The stack should be
+      empty then.
+      """),
+
+    # Ways to deal with persistent IDs.
+
+    I(name='PERSID',
+      code='P',
+      arg=stringnl_noescape,
+      stack_before=[],
+      stack_after=[anyobject],
+      proto=0,
+      doc="""Push an object identified by a persistent ID.
+
+      The pickle module doesn't define what a persistent ID means.  PERSID's
+      argument is a newline-terminated str-style (no embedded escapes, no
+      bracketing quote characters) string, which *is* "the persistent ID".
+      The unpickler passes this string to self.persistent_load().  Whatever
+      object that returns is pushed on the stack.  There is no implementation
+      of persistent_load() in Python's unpickler:  it must be supplied by an
+      unpickler subclass.
+      """),
+
+    I(name='BINPERSID',
+      code='Q',
+      arg=None,
+      stack_before=[anyobject],
+      stack_after=[anyobject],
+      proto=1,
+      doc="""Push an object identified by a persistent ID.
+
+      Like PERSID, except the persistent ID is popped off the stack (instead
+      of being a string embedded in the opcode bytestream).  The persistent
+      ID is passed to self.persistent_load(), and whatever object that
+      returns is pushed on the stack.  See PERSID for more detail.
+      """),
+]
+del I
+
+# Verify uniqueness of .name and .code members.
+name2i = {}
+code2i = {}
+
+for i, d in enumerate(opcodes):
+    if d.name in name2i:
+        raise ValueError("repeated name %r at indices %d and %d" %
+                         (d.name, name2i[d.name], i))
+    if d.code in code2i:
+        raise ValueError("repeated code %r at indices %d and %d" %
+                         (d.code, code2i[d.code], i))
+
+    name2i[d.name] = i
+    code2i[d.code] = i
+
+del name2i, code2i, i, d
+
+##############################################################################
+# Build a code2op dict, mapping opcode characters to OpcodeInfo records.
+# Also ensure we've got the same stuff as pickle.py, although the
+# introspection here is dicey.
+
+code2op = {}
+for d in opcodes:
+    code2op[d.code] = d
+del d
+
+def assure_pickle_consistency(verbose=False):
+    import pickle, re
+
+    copy = code2op.copy()
+    for name in pickle.__all__:
+        if not re.match("[A-Z][A-Z0-9_]+$", name):
+            if verbose:
+                print "skipping %r: it doesn't look like an opcode name" % name
+            continue
+        picklecode = getattr(pickle, name)
+        if not isinstance(picklecode, str) or len(picklecode) != 1:
+            if verbose:
+                print ("skipping %r: value %r doesn't look like a pickle "
+                       "code" % (name, picklecode))
+            continue
+        if picklecode in copy:
+            if verbose:
+                print "checking name %r w/ code %r for consistency" % (
+                      name, picklecode)
+            d = copy[picklecode]
+            if d.name != name:
+                raise ValueError("for pickle code %r, pickle.py uses name %r "
+                                 "but we're using name %r" % (picklecode,
+                                                              name,
+                                                              d.name))
+            # Forget this one.  Any left over in copy at the end are a problem
+            # of a different kind.
+            del copy[picklecode]
+        else:
+            raise ValueError("pickle.py appears to have a pickle opcode with "
+                             "name %r and code %r, but we don't" %
+                             (name, picklecode))
+    if copy:
+        msg = ["we appear to have pickle opcodes that pickle.py doesn't have:"]
+        for code, d in copy.items():
+            msg.append("    name %r with code %r" % (d.name, code))
+        raise ValueError("\n".join(msg))
+
+assure_pickle_consistency()
+del assure_pickle_consistency
+
+##############################################################################
+# A pickle opcode generator.
+
+def genops(pickle):
+    """Generate all the opcodes in a pickle.
+
+    'pickle' is a file-like object, or string, containing the pickle.
+
+    Each opcode in the pickle is generated, from the current pickle position,
+    stopping after a STOP opcode is delivered.  A triple is generated for
+    each opcode:
+
+        opcode, arg, pos
+
+    opcode is an OpcodeInfo record, describing the current opcode.
+
+    If the opcode has an argument embedded in the pickle, arg is its decoded
+    value, as a Python object.  If the opcode doesn't have an argument, arg
+    is None.
+
+    If the pickle has a tell() method, pos was the value of pickle.tell()
+    before reading the current opcode.  If the pickle is a string object,
+    it's wrapped in a StringIO object, and the latter's tell() result is
+    used.  Else (the pickle doesn't have a tell(), and it's not obvious how
+    to query its current position) pos is None.
+    """
+
+    import cStringIO as StringIO
+
+    if isinstance(pickle, str):
+        pickle = StringIO.StringIO(pickle)
+
+    if hasattr(pickle, "tell"):
+        getpos = pickle.tell
+    else:
+        getpos = lambda: None
+
+    while True:
+        pos = getpos()
+        code = pickle.read(1)
+        opcode = code2op.get(code)
+        if opcode is None:
+            if code == "":
+                raise ValueError("pickle exhausted before seeing STOP")
+            else:
+                raise ValueError("at position %s, opcode %r unknown" % (
+                                 pos is None and "<unknown>" or pos,
+                                 code))
+        if opcode.arg is None:
+            arg = None
+        else:
+            arg = opcode.arg.reader(pickle)
+        yield opcode, arg, pos
+        if code == '.':
+            assert opcode.name == 'STOP'
+            break
+
+##############################################################################
+# A pickle optimizer.
+
+def optimize(p):
+    'Optimize a pickle string by removing unused PUT opcodes'
+    gets = set()            # set of args used by a GET opcode
+    puts = []               # (arg, startpos, stoppos) for the PUT opcodes
+    prevpos = None          # set to pos if previous opcode was a PUT
+    for opcode, arg, pos in genops(p):
+        if prevpos is not None:
+            puts.append((prevarg, prevpos, pos))
+            prevpos = None
+        if 'PUT' in opcode.name:
+            prevarg, prevpos = arg, pos
+        elif 'GET' in opcode.name:
+            gets.add(arg)
+
+    # Copy the pickle string except for PUTS without a corresponding GET
+    s = []
+    i = 0
+    for arg, start, stop in puts:
+        j = stop if (arg in gets) else start
+        s.append(p[i:j])
+        i = stop
+    s.append(p[i:])
+    return ''.join(s)
+
+##############################################################################
+# A symbolic pickle disassembler.
+
+def dis(pickle, out=None, memo=None, indentlevel=4):
+    """Produce a symbolic disassembly of a pickle.
+
+    'pickle' is a file-like object, or string, containing a (at least one)
+    pickle.  The pickle is disassembled from the current position, through
+    the first STOP opcode encountered.
+
+    Optional arg 'out' is a file-like object to which the disassembly is
+    printed.  It defaults to sys.stdout.
+
+    Optional arg 'memo' is a Python dict, used as the pickle's memo.  It
+    may be mutated by dis(), if the pickle contains PUT or BINPUT opcodes.
+    Passing the same memo object to another dis() call then allows disassembly
+    to proceed across multiple pickles that were all created by the same
+    pickler with the same memo.  Ordinarily you don't need to worry about this.
+
+    Optional arg indentlevel is the number of blanks by which to indent
+    a new MARK level.  It defaults to 4.
+
+    In addition to printing the disassembly, some sanity checks are made:
+
+    + All embedded opcode arguments "make sense".
+
+    + Explicit and implicit pop operations have enough items on the stack.
+
+    + When an opcode implicitly refers to a markobject, a markobject is
+      actually on the stack.
+
+    + A memo entry isn't referenced before it's defined.
+
+    + The markobject isn't stored in the memo.
+
+    + A memo entry isn't redefined.
+    """
+
+    # Most of the hair here is for sanity checks, but most of it is needed
+    # anyway to detect when a protocol 0 POP takes a MARK off the stack
+    # (which in turn is needed to indent MARK blocks correctly).
+
+    stack = []          # crude emulation of unpickler stack
+    if memo is None:
+        memo = {}       # crude emulation of unpicker memo
+    maxproto = -1       # max protocol number seen
+    markstack = []      # bytecode positions of MARK opcodes
+    indentchunk = ' ' * indentlevel
+    errormsg = None
+    for opcode, arg, pos in genops(pickle):
+        if pos is not None:
+            print >> out, "%5d:" % pos,
+
+        line = "%-4s %s%s" % (repr(opcode.code)[1:-1],
+                              indentchunk * len(markstack),
+                              opcode.name)
+
+        maxproto = max(maxproto, opcode.proto)
+        before = opcode.stack_before    # don't mutate
+        after = opcode.stack_after      # don't mutate
+        numtopop = len(before)
+
+        # See whether a MARK should be popped.
+        markmsg = None
+        if markobject in before or (opcode.name == "POP" and
+                                    stack and
+                                    stack[-1] is markobject):
+            assert markobject not in after
+            if __debug__:
+                if markobject in before:
+                    assert before[-1] is stackslice
+            if markstack:
+                markpos = markstack.pop()
+                if markpos is None:
+                    markmsg = "(MARK at unknown opcode offset)"
+                else:
+                    markmsg = "(MARK at %d)" % markpos
+                # Pop everything at and after the topmost markobject.
+                while stack[-1] is not markobject:
+                    stack.pop()
+                stack.pop()
+                # Stop later code from popping too much.
+                try:
+                    numtopop = before.index(markobject)
+                except ValueError:
+                    assert opcode.name == "POP"
+                    numtopop = 0
+            else:
+                errormsg = markmsg = "no MARK exists on stack"
+
+        # Check for correct memo usage.
+        if opcode.name in ("PUT", "BINPUT", "LONG_BINPUT"):
+            assert arg is not None
+            if arg in memo:
+                errormsg = "memo key %r already defined" % arg
+            elif not stack:
+                errormsg = "stack is empty -- can't store into memo"
+            elif stack[-1] is markobject:
+                errormsg = "can't store markobject in the memo"
+            else:
+                memo[arg] = stack[-1]
+
+        elif opcode.name in ("GET", "BINGET", "LONG_BINGET"):
+            if arg in memo:
+                assert len(after) == 1
+                after = [memo[arg]]     # for better stack emulation
+            else:
+                errormsg = "memo key %r has never been stored into" % arg
+
+        if arg is not None or markmsg:
+            # make a mild effort to align arguments
+            line += ' ' * (10 - len(opcode.name))
+            if arg is not None:
+                line += ' ' + repr(arg)
+            if markmsg:
+                line += ' ' + markmsg
+        print >> out, line
+
+        if errormsg:
+            # Note that we delayed complaining until the offending opcode
+            # was printed.
+            raise ValueError(errormsg)
+
+        # Emulate the stack effects.
+        if len(stack) < numtopop:
+            raise ValueError("tries to pop %d items from stack with "
+                             "only %d items" % (numtopop, len(stack)))
+        if numtopop:
+            del stack[-numtopop:]
+        if markobject in after:
+            assert markobject not in before
+            markstack.append(pos)
+
+        stack.extend(after)
+
+    print >> out, "highest protocol among opcodes =", maxproto
+    if stack:
+        raise ValueError("stack not empty after STOP: %r" % stack)
+
+# For use in the doctest, simply as an example of a class to pickle.
+class _Example:
+    def __init__(self, value):
+        self.value = value
+
+_dis_test = r"""
+>>> import pickle
+>>> x = [1, 2, (3, 4), {'abc': u"def"}]
+>>> pkl = pickle.dumps(x, 0)
+>>> dis(pkl)
+    0: (    MARK
+    1: l        LIST       (MARK at 0)
+    2: p    PUT        0
+    5: I    INT        1
+    8: a    APPEND
+    9: I    INT        2
+   12: a    APPEND
+   13: (    MARK
+   14: I        INT        3
+   17: I        INT        4
+   20: t        TUPLE      (MARK at 13)
+   21: p    PUT        1
+   24: a    APPEND
+   25: (    MARK
+   26: d        DICT       (MARK at 25)
+   27: p    PUT        2
+   30: S    STRING     'abc'
+   37: p    PUT        3
+   40: V    UNICODE    u'def'
+   45: p    PUT        4
+   48: s    SETITEM
+   49: a    APPEND
+   50: .    STOP
+highest protocol among opcodes = 0
+
+Try again with a "binary" pickle.
+
+>>> pkl = pickle.dumps(x, 1)
+>>> dis(pkl)
+    0: ]    EMPTY_LIST
+    1: q    BINPUT     0
+    3: (    MARK
+    4: K        BININT1    1
+    6: K        BININT1    2
+    8: (        MARK
+    9: K            BININT1    3
+   11: K            BININT1    4
+   13: t            TUPLE      (MARK at 8)
+   14: q        BINPUT     1
+   16: }        EMPTY_DICT
+   17: q        BINPUT     2
+   19: U        SHORT_BINSTRING 'abc'
+   24: q        BINPUT     3
+   26: X        BINUNICODE u'def'
+   34: q        BINPUT     4
+   36: s        SETITEM
+   37: e        APPENDS    (MARK at 3)
+   38: .    STOP
+highest protocol among opcodes = 1
+
+Exercise the INST/OBJ/BUILD family.
+
+>>> import pickletools
+>>> dis(pickle.dumps(pickletools.dis, 0))
+    0: c    GLOBAL     'pickletools dis'
+   17: p    PUT        0
+   20: .    STOP
+highest protocol among opcodes = 0
+
+>>> from pickletools import _Example
+>>> x = [_Example(42)] * 2
+>>> dis(pickle.dumps(x, 0))
+    0: (    MARK
+    1: l        LIST       (MARK at 0)
+    2: p    PUT        0
+    5: (    MARK
+    6: i        INST       'pickletools _Example' (MARK at 5)
+   28: p    PUT        1
+   31: (    MARK
+   32: d        DICT       (MARK at 31)
+   33: p    PUT        2
+   36: S    STRING     'value'
+   45: p    PUT        3
+   48: I    INT        42
+   52: s    SETITEM
+   53: b    BUILD
+   54: a    APPEND
+   55: g    GET        1
+   58: a    APPEND
+   59: .    STOP
+highest protocol among opcodes = 0
+
+>>> dis(pickle.dumps(x, 1))
+    0: ]    EMPTY_LIST
+    1: q    BINPUT     0
+    3: (    MARK
+    4: (        MARK
+    5: c            GLOBAL     'pickletools _Example'
+   27: q            BINPUT     1
+   29: o            OBJ        (MARK at 4)
+   30: q        BINPUT     2
+   32: }        EMPTY_DICT
+   33: q        BINPUT     3
+   35: U        SHORT_BINSTRING 'value'
+   42: q        BINPUT     4
+   44: K        BININT1    42
+   46: s        SETITEM
+   47: b        BUILD
+   48: h        BINGET     2
+   50: e        APPENDS    (MARK at 3)
+   51: .    STOP
+highest protocol among opcodes = 1
+
+Try "the canonical" recursive-object test.
+
+>>> L = []
+>>> T = L,
+>>> L.append(T)
+>>> L[0] is T
+True
+>>> T[0] is L
+True
+>>> L[0][0] is L
+True
+>>> T[0][0] is T
+True
+>>> dis(pickle.dumps(L, 0))
+    0: (    MARK
+    1: l        LIST       (MARK at 0)
+    2: p    PUT        0
+    5: (    MARK
+    6: g        GET        0
+    9: t        TUPLE      (MARK at 5)
+   10: p    PUT        1
+   13: a    APPEND
+   14: .    STOP
+highest protocol among opcodes = 0
+
+>>> dis(pickle.dumps(L, 1))
+    0: ]    EMPTY_LIST
+    1: q    BINPUT     0
+    3: (    MARK
+    4: h        BINGET     0
+    6: t        TUPLE      (MARK at 3)
+    7: q    BINPUT     1
+    9: a    APPEND
+   10: .    STOP
+highest protocol among opcodes = 1
+
+Note that, in the protocol 0 pickle of the recursive tuple, the disassembler
+has to emulate the stack in order to realize that the POP opcode at 16 gets
+rid of the MARK at 0.
+
+>>> dis(pickle.dumps(T, 0))
+    0: (    MARK
+    1: (        MARK
+    2: l            LIST       (MARK at 1)
+    3: p        PUT        0
+    6: (        MARK
+    7: g            GET        0
+   10: t            TUPLE      (MARK at 6)
+   11: p        PUT        1
+   14: a        APPEND
+   15: 0        POP
+   16: 0        POP        (MARK at 0)
+   17: g    GET        1
+   20: .    STOP
+highest protocol among opcodes = 0
+
+>>> dis(pickle.dumps(T, 1))
+    0: (    MARK
+    1: ]        EMPTY_LIST
+    2: q        BINPUT     0
+    4: (        MARK
+    5: h            BINGET     0
+    7: t            TUPLE      (MARK at 4)
+    8: q        BINPUT     1
+   10: a        APPEND
+   11: 1        POP_MARK   (MARK at 0)
+   12: h    BINGET     1
+   14: .    STOP
+highest protocol among opcodes = 1
+
+Try protocol 2.
+
+>>> dis(pickle.dumps(L, 2))
+    0: \x80 PROTO      2
+    2: ]    EMPTY_LIST
+    3: q    BINPUT     0
+    5: h    BINGET     0
+    7: \x85 TUPLE1
+    8: q    BINPUT     1
+   10: a    APPEND
+   11: .    STOP
+highest protocol among opcodes = 2
+
+>>> dis(pickle.dumps(T, 2))
+    0: \x80 PROTO      2
+    2: ]    EMPTY_LIST
+    3: q    BINPUT     0
+    5: h    BINGET     0
+    7: \x85 TUPLE1
+    8: q    BINPUT     1
+   10: a    APPEND
+   11: 0    POP
+   12: h    BINGET     1
+   14: .    STOP
+highest protocol among opcodes = 2
+"""
+
+_memo_test = r"""
+>>> import pickle
+>>> from StringIO import StringIO
+>>> f = StringIO()
+>>> p = pickle.Pickler(f, 2)
+>>> x = [1, 2, 3]
+>>> p.dump(x)
+>>> p.dump(x)
+>>> f.seek(0)
+>>> memo = {}
+>>> dis(f, memo=memo)
+    0: \x80 PROTO      2
+    2: ]    EMPTY_LIST
+    3: q    BINPUT     0
+    5: (    MARK
+    6: K        BININT1    1
+    8: K        BININT1    2
+   10: K        BININT1    3
+   12: e        APPENDS    (MARK at 5)
+   13: .    STOP
+highest protocol among opcodes = 2
+>>> dis(f, memo=memo)
+   14: \x80 PROTO      2
+   16: h    BINGET     0
+   18: .    STOP
+highest protocol among opcodes = 2
+"""
+
+__test__ = {'disassembler_test': _dis_test,
+            'disassembler_memo_test': _memo_test,
+           }
+
+def _test():
+    import doctest
+    return doctest.testmod()
+
+if __name__ == "__main__":
+    _test()
diff --git a/src/main/resources/PythonLibs/pipes.py b/src/main/resources/PythonLibs/pipes.py
new file mode 100644
index 0000000000000000000000000000000000000000..26750f6ab88d8f43465710bee33936997bbc1553
--- /dev/null
+++ b/src/main/resources/PythonLibs/pipes.py
@@ -0,0 +1,278 @@
+"""Conversion pipeline templates.
+
+The problem:
+------------
+
+Suppose you have some data that you want to convert to another format,
+such as from GIF image format to PPM image format.  Maybe the
+conversion involves several steps (e.g. piping it through compress or
+uuencode).  Some of the conversion steps may require that their input
+is a disk file, others may be able to read standard input; similar for
+their output.  The input to the entire conversion may also be read
+from a disk file or from an open file, and similar for its output.
+
+The module lets you construct a pipeline template by sticking one or
+more conversion steps together.  It will take care of creating and
+removing temporary files if they are necessary to hold intermediate
+data.  You can then use the template to do conversions from many
+different sources to many different destinations.  The temporary
+file names used are different each time the template is used.
+
+The templates are objects so you can create templates for many
+different conversion steps and store them in a dictionary, for
+instance.
+
+
+Directions:
+-----------
+
+To create a template:
+    t = Template()
+
+To add a conversion step to a template:
+   t.append(command, kind)
+where kind is a string of two characters: the first is '-' if the
+command reads its standard input or 'f' if it requires a file; the
+second likewise for the output. The command must be valid /bin/sh
+syntax.  If input or output files are required, they are passed as
+$IN and $OUT; otherwise, it must be  possible to use the command in
+a pipeline.
+
+To add a conversion step at the beginning:
+   t.prepend(command, kind)
+
+To convert a file to another file using a template:
+  sts = t.copy(infile, outfile)
+If infile or outfile are the empty string, standard input is read or
+standard output is written, respectively.  The return value is the
+exit status of the conversion pipeline.
+
+To open a file for reading or writing through a conversion pipeline:
+   fp = t.open(file, mode)
+where mode is 'r' to read the file, or 'w' to write it -- just like
+for the built-in function open() or for os.popen().
+
+To create a new template object initialized to a given one:
+   t2 = t.clone()
+"""                                     # '
+
+
+import re
+import os
+import tempfile
+import string
+
+__all__ = ["Template"]
+
+# Conversion step kinds
+
+FILEIN_FILEOUT = 'ff'                   # Must read & write real files
+STDIN_FILEOUT  = '-f'                   # Must write a real file
+FILEIN_STDOUT  = 'f-'                   # Must read a real file
+STDIN_STDOUT   = '--'                   # Normal pipeline element
+SOURCE         = '.-'                   # Must be first, writes stdout
+SINK           = '-.'                   # Must be last, reads stdin
+
+stepkinds = [FILEIN_FILEOUT, STDIN_FILEOUT, FILEIN_STDOUT, STDIN_STDOUT, \
+             SOURCE, SINK]
+
+
+class Template:
+    """Class representing a pipeline template."""
+
+    def __init__(self):
+        """Template() returns a fresh pipeline template."""
+        self.debugging = 0
+        self.reset()
+
+    def __repr__(self):
+        """t.__repr__() implements repr(t)."""
+        return '<Template instance, steps=%r>' % (self.steps,)
+
+    def reset(self):
+        """t.reset() restores a pipeline template to its initial state."""
+        self.steps = []
+
+    def clone(self):
+        """t.clone() returns a new pipeline template with identical
+        initial state as the current one."""
+        t = Template()
+        t.steps = self.steps[:]
+        t.debugging = self.debugging
+        return t
+
+    def debug(self, flag):
+        """t.debug(flag) turns debugging on or off."""
+        self.debugging = flag
+
+    def append(self, cmd, kind):
+        """t.append(cmd, kind) adds a new step at the end."""
+        if type(cmd) is not type(''):
+            raise TypeError, \
+                  'Template.append: cmd must be a string'
+        if kind not in stepkinds:
+            raise ValueError, \
+                  'Template.append: bad kind %r' % (kind,)
+        if kind == SOURCE:
+            raise ValueError, \
+                  'Template.append: SOURCE can only be prepended'
+        if self.steps and self.steps[-1][1] == SINK:
+            raise ValueError, \
+                  'Template.append: already ends with SINK'
+        if kind[0] == 'f' and not re.search(r'\$IN\b', cmd):
+            raise ValueError, \
+                  'Template.append: missing $IN in cmd'
+        if kind[1] == 'f' and not re.search(r'\$OUT\b', cmd):
+            raise ValueError, \
+                  'Template.append: missing $OUT in cmd'
+        self.steps.append((cmd, kind))
+
+    def prepend(self, cmd, kind):
+        """t.prepend(cmd, kind) adds a new step at the front."""
+        if type(cmd) is not type(''):
+            raise TypeError, \
+                  'Template.prepend: cmd must be a string'
+        if kind not in stepkinds:
+            raise ValueError, \
+                  'Template.prepend: bad kind %r' % (kind,)
+        if kind == SINK:
+            raise ValueError, \
+                  'Template.prepend: SINK can only be appended'
+        if self.steps and self.steps[0][1] == SOURCE:
+            raise ValueError, \
+                  'Template.prepend: already begins with SOURCE'
+        if kind[0] == 'f' and not re.search(r'\$IN\b', cmd):
+            raise ValueError, \
+                  'Template.prepend: missing $IN in cmd'
+        if kind[1] == 'f' and not re.search(r'\$OUT\b', cmd):
+            raise ValueError, \
+                  'Template.prepend: missing $OUT in cmd'
+        self.steps.insert(0, (cmd, kind))
+
+    def open(self, file, rw):
+        """t.open(file, rw) returns a pipe or file object open for
+        reading or writing; the file is the other end of the pipeline."""
+        if rw == 'r':
+            return self.open_r(file)
+        if rw == 'w':
+            return self.open_w(file)
+        raise ValueError, \
+              'Template.open: rw must be \'r\' or \'w\', not %r' % (rw,)
+
+    def open_r(self, file):
+        """t.open_r(file) and t.open_w(file) implement
+        t.open(file, 'r') and t.open(file, 'w') respectively."""
+        if not self.steps:
+            return open(file, 'r')
+        if self.steps[-1][1] == SINK:
+            raise ValueError, \
+                  'Template.open_r: pipeline ends width SINK'
+        cmd = self.makepipeline(file, '')
+        return os.popen(cmd, 'r')
+
+    def open_w(self, file):
+        if not self.steps:
+            return open(file, 'w')
+        if self.steps[0][1] == SOURCE:
+            raise ValueError, \
+                  'Template.open_w: pipeline begins with SOURCE'
+        cmd = self.makepipeline('', file)
+        return os.popen(cmd, 'w')
+
+    def copy(self, infile, outfile):
+        return os.system(self.makepipeline(infile, outfile))
+
+    def makepipeline(self, infile, outfile):
+        cmd = makepipeline(infile, self.steps, outfile)
+        if self.debugging:
+            print cmd
+            cmd = 'set -x; ' + cmd
+        return cmd
+
+
+def makepipeline(infile, steps, outfile):
+    # Build a list with for each command:
+    # [input filename or '', command string, kind, output filename or '']
+
+    list = []
+    for cmd, kind in steps:
+        list.append(['', cmd, kind, ''])
+    #
+    # Make sure there is at least one step
+    #
+    if not list:
+        list.append(['', 'cat', '--', ''])
+    #
+    # Take care of the input and output ends
+    #
+    [cmd, kind] = list[0][1:3]
+    if kind[0] == 'f' and not infile:
+        list.insert(0, ['', 'cat', '--', ''])
+    list[0][0] = infile
+    #
+    [cmd, kind] = list[-1][1:3]
+    if kind[1] == 'f' and not outfile:
+        list.append(['', 'cat', '--', ''])
+    list[-1][-1] = outfile
+    #
+    # Invent temporary files to connect stages that need files
+    #
+    garbage = []
+    for i in range(1, len(list)):
+        lkind = list[i-1][2]
+        rkind = list[i][2]
+        if lkind[1] == 'f' or rkind[0] == 'f':
+            (fd, temp) = tempfile.mkstemp()
+            os.close(fd)
+            garbage.append(temp)
+            list[i-1][-1] = list[i][0] = temp
+    #
+    for item in list:
+        [inf, cmd, kind, outf] = item
+        if kind[1] == 'f':
+            cmd = 'OUT=' + quote(outf) + '; ' + cmd
+        if kind[0] == 'f':
+            cmd = 'IN=' + quote(inf) + '; ' + cmd
+        if kind[0] == '-' and inf:
+            cmd = cmd + ' <' + quote(inf)
+        if kind[1] == '-' and outf:
+            cmd = cmd + ' >' + quote(outf)
+        item[1] = cmd
+    #
+    cmdlist = list[0][1]
+    for item in list[1:]:
+        [cmd, kind] = item[1:3]
+        if item[0] == '':
+            if 'f' in kind:
+                cmd = '{ ' + cmd + '; }'
+            cmdlist = cmdlist + ' |\n' + cmd
+        else:
+            cmdlist = cmdlist + '\n' + cmd
+    #
+    if garbage:
+        rmcmd = 'rm -f'
+        for file in garbage:
+            rmcmd = rmcmd + ' ' + quote(file)
+        trapcmd = 'trap ' + quote(rmcmd + '; exit') + ' 1 2 3 13 14 15'
+        cmdlist = trapcmd + '\n' + cmdlist + '\n' + rmcmd
+    #
+    return cmdlist
+
+
+# Reliably quote a string as a single argument for /bin/sh
+
+# Safe unquoted
+_safechars = frozenset(string.ascii_letters + string.digits + '@%_-+=:,./')
+
+def quote(file):
+    """Return a shell-escaped version of the file string."""
+    for c in file:
+        if c not in _safechars:
+            break
+    else:
+        if not file:
+            return "''"
+        return file
+    # use single quotes, and put single quotes into double quotes
+    # the string $'b is then quoted as '$'"'"'b'
+    return "'" + file.replace("'", "'\"'\"'") + "'"
diff --git a/src/main/resources/PythonLibs/pkgutil.py b/src/main/resources/PythonLibs/pkgutil.py
new file mode 100644
index 0000000000000000000000000000000000000000..681f887429f72d2223bb076e407907b28bbe5fc3
--- /dev/null
+++ b/src/main/resources/PythonLibs/pkgutil.py
@@ -0,0 +1,595 @@
+"""Utilities to support packages."""
+
+# NOTE: This module must remain compatible with Python 2.3, as it is shared
+# by setuptools for distribution with Python 2.3 and up.
+
+import os
+import sys
+import imp
+import os.path
+from types import ModuleType
+from org.python.core import imp as _imp, BytecodeLoader
+
+__all__ = [
+    'get_importer', 'iter_importers', 'get_loader', 'find_loader',
+    'walk_packages', 'iter_modules',
+    'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
+]
+
+
+# equivalent to CPythonLib's pkgutil.read_code except that we need
+# diff args to pass into our underlying imp implementation, as
+# accessed by _imp here
+
+def read_jython_code(fullname, file, filename):
+    data = _imp.readCode(filename, file, False)
+    return BytecodeLoader.makeCode(fullname + "$py", data, filename)
+
+read_code = read_jython_code
+
+def simplegeneric(func):
+    """Make a trivial single-dispatch generic function"""
+    registry = {}
+    def wrapper(*args, **kw):
+        ob = args[0]
+        try:
+            cls = ob.__class__
+        except AttributeError:
+            cls = type(ob)
+        try:
+            mro = cls.__mro__
+        except AttributeError:
+            try:
+                class cls(cls, object):
+                    pass
+                mro = cls.__mro__[1:]
+            except TypeError:
+                mro = object,   # must be an ExtensionClass or some such  :(
+        for t in mro:
+            if t in registry:
+                return registry[t](*args, **kw)
+        else:
+            return func(*args, **kw)
+    try:
+        wrapper.__name__ = func.__name__
+    except (TypeError, AttributeError):
+        pass    # Python 2.3 doesn't allow functions to be renamed
+
+    def register(typ, func=None):
+        if func is None:
+            return lambda f: register(typ, f)
+        registry[typ] = func
+        return func
+
+    wrapper.__dict__ = func.__dict__
+    wrapper.__doc__ = func.__doc__
+    wrapper.register = register
+    return wrapper
+
+
+def walk_packages(path=None, prefix='', onerror=None):
+    """Yields (module_loader, name, ispkg) for all modules recursively
+    on path, or, if path is None, all accessible modules.
+
+    'path' should be either None or a list of paths to look for
+    modules in.
+
+    'prefix' is a string to output on the front of every module name
+    on output.
+
+    Note that this function must import all *packages* (NOT all
+    modules!) on the given path, in order to access the __path__
+    attribute to find submodules.
+
+    'onerror' is a function which gets called with one argument (the
+    name of the package which was being imported) if any exception
+    occurs while trying to import a package.  If no onerror function is
+    supplied, ImportErrors are caught and ignored, while all other
+    exceptions are propagated, terminating the search.
+
+    Examples:
+
+    # list all modules python can access
+    walk_packages()
+
+    # list all submodules of ctypes
+    walk_packages(ctypes.__path__, ctypes.__name__+'.')
+    """
+
+    def seen(p, m={}):
+        if p in m:
+            return True
+        m[p] = True
+
+    for importer, name, ispkg in iter_modules(path, prefix):
+        yield importer, name, ispkg
+
+        if ispkg:
+            try:
+                __import__(name)
+            except ImportError:
+                if onerror is not None:
+                    onerror(name)
+            except Exception:
+                if onerror is not None:
+                    onerror(name)
+                else:
+                    raise
+            else:
+                path = getattr(sys.modules[name], '__path__', None) or []
+
+                # don't traverse path items we've seen before
+                path = [p for p in path if not seen(p)]
+
+                for item in walk_packages(path, name+'.', onerror):
+                    yield item
+
+
+def iter_modules(path=None, prefix=''):
+    """Yields (module_loader, name, ispkg) for all submodules on path,
+    or, if path is None, all top-level modules on sys.path.
+
+    'path' should be either None or a list of paths to look for
+    modules in.
+
+    'prefix' is a string to output on the front of every module name
+    on output.
+    """
+
+    if path is None:
+        importers = iter_importers()
+    else:
+        importers = map(get_importer, path)
+
+    yielded = {}
+    for i in importers:
+        for name, ispkg in iter_importer_modules(i, prefix):
+            if name not in yielded:
+                yielded[name] = 1
+                yield i, name, ispkg
+
+
+#@simplegeneric
+def iter_importer_modules(importer, prefix=''):
+    if not hasattr(importer, 'iter_modules'):
+        return []
+    return importer.iter_modules(prefix)
+
+iter_importer_modules = simplegeneric(iter_importer_modules)
+
+
+class ImpImporter:
+    """PEP 302 Importer that wraps Python's "classic" import algorithm
+
+    ImpImporter(dirname) produces a PEP 302 importer that searches that
+    directory.  ImpImporter(None) produces a PEP 302 importer that searches
+    the current sys.path, plus any modules that are frozen or built-in.
+
+    Note that ImpImporter does not currently support being used by placement
+    on sys.meta_path.
+    """
+
+    def __init__(self, path=None):
+        self.path = path
+
+    def find_module(self, fullname, path=None):
+        # Note: we ignore 'path' argument since it is only used via meta_path
+        subname = fullname.split(".")[-1]
+        if subname != fullname and self.path is None:
+            return None
+        if self.path is None:
+            path = None
+        else:
+            path = [os.path.realpath(self.path)]
+        try:
+            file, filename, etc = imp.find_module(subname, path)
+        except ImportError:
+            return None
+        return ImpLoader(fullname, file, filename, etc)
+
+    def iter_modules(self, prefix=''):
+        if self.path is None or not os.path.isdir(self.path):
+            return
+
+        yielded = {}
+        import inspect
+
+        filenames = os.listdir(self.path)
+        filenames.sort()  # handle packages before same-named modules
+
+        for fn in filenames:
+            modname = inspect.getmodulename(fn)
+            if modname=='__init__' or modname in yielded:
+                continue
+
+            path = os.path.join(self.path, fn)
+            ispkg = False
+
+            if not modname and os.path.isdir(path) and '.' not in fn:
+                modname = fn
+                for fn in os.listdir(path):
+                    subname = inspect.getmodulename(fn)
+                    if subname=='__init__':
+                        ispkg = True
+                        break
+                else:
+                    continue    # not a package
+
+            if modname and '.' not in modname:
+                yielded[modname] = 1
+                yield prefix + modname, ispkg
+
+
+class ImpLoader:
+    """PEP 302 Loader that wraps Python's "classic" import algorithm
+    """
+    code = source = None
+
+    def __init__(self, fullname, file, filename, etc):
+        self.file = file
+        self.filename = filename
+        self.fullname = fullname
+        self.etc = etc
+
+    def load_module(self, fullname):
+        self._reopen()
+        try:
+            mod = imp.load_module(fullname, self.file, self.filename, self.etc)
+        finally:
+            if self.file:
+                self.file.close()
+        # Note: we don't set __loader__ because we want the module to look
+        # normal; i.e. this is just a wrapper for standard import machinery
+        return mod
+
+    def get_data(self, pathname):
+        f = open(pathname, "rb")
+        try:
+            return f.read()
+        finally:
+            f.close()
+
+    def _reopen(self):
+        if self.file and self.file.closed:
+            mod_type = self.etc[2]
+            if mod_type==imp.PY_SOURCE:
+                self.file = open(self.filename, 'rU')
+            elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
+                self.file = open(self.filename, 'rb')
+
+    def _fix_name(self, fullname):
+        if fullname is None:
+            fullname = self.fullname
+        elif fullname != self.fullname:
+            raise ImportError("Loader for module %s cannot handle "
+                              "module %s" % (self.fullname, fullname))
+        return fullname
+
+    def is_package(self, fullname):
+        fullname = self._fix_name(fullname)
+        return self.etc[2]==imp.PKG_DIRECTORY
+
+    def get_code(self, fullname=None):
+        fullname = self._fix_name(fullname)
+        if self.code is None:
+            mod_type = self.etc[2]
+            if mod_type==imp.PY_SOURCE:
+                source = self.get_source(fullname)
+                self.code = compile(source, self.filename, 'exec')
+            elif mod_type==imp.PY_COMPILED:
+                self._reopen()
+                try:
+                    self.code = read_jython_code(fullname, self.file, self.filename)
+                finally:
+                    self.file.close()
+            elif mod_type==imp.PKG_DIRECTORY:
+                self.code = self._get_delegate().get_code()
+        return self.code
+
+    def get_source(self, fullname=None):
+        fullname = self._fix_name(fullname)
+        if self.source is None:
+            mod_type = self.etc[2]
+            if mod_type==imp.PY_SOURCE:
+                self._reopen()
+                try:
+                    self.source = self.file.read()
+                finally:
+                    self.file.close()
+            elif mod_type==imp.PY_COMPILED:
+                if os.path.exists(self.filename[:-1]):
+                    f = open(self.filename[:-1], 'rU')
+                    try:
+                        self.source = f.read()
+                    finally:
+                        f.close()
+            elif mod_type==imp.PKG_DIRECTORY:
+                self.source = self._get_delegate().get_source()
+        return self.source
+
+
+    def _get_delegate(self):
+        return ImpImporter(self.filename).find_module('__init__')
+
+    def get_filename(self, fullname=None):
+        fullname = self._fix_name(fullname)
+        mod_type = self.etc[2]
+        if self.etc[2]==imp.PKG_DIRECTORY:
+            return self._get_delegate().get_filename()
+        elif self.etc[2] in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
+            return self.filename
+        return None
+
+
+try:
+    import zipimport
+    from zipimport import zipimporter
+
+    def iter_zipimport_modules(importer, prefix=''):
+        dirlist = zipimport._zip_directory_cache[importer.archive].keys()
+        dirlist.sort()
+        _prefix = importer.prefix
+        plen = len(_prefix)
+        yielded = {}
+        import inspect
+        for fn in dirlist:
+            if not fn.startswith(_prefix):
+                continue
+
+            fn = fn[plen:].split(os.sep)
+
+            if len(fn)==2 and fn[1].startswith('__init__.py'):
+                if fn[0] not in yielded:
+                    yielded[fn[0]] = 1
+                    yield fn[0], True
+
+            if len(fn)!=1:
+                continue
+
+            modname = inspect.getmodulename(fn[0])
+            if modname=='__init__':
+                continue
+
+            if modname and '.' not in modname and modname not in yielded:
+                yielded[modname] = 1
+                yield prefix + modname, False
+
+    iter_importer_modules.register(zipimporter, iter_zipimport_modules)
+
+except ImportError:
+    pass
+
+
+def get_importer(path_item):
+    """Retrieve a PEP 302 importer for the given path item
+
+    The returned importer is cached in sys.path_importer_cache
+    if it was newly created by a path hook.
+
+    If there is no importer, a wrapper around the basic import
+    machinery is returned. This wrapper is never inserted into
+    the importer cache (None is inserted instead).
+
+    The cache (or part of it) can be cleared manually if a
+    rescan of sys.path_hooks is necessary.
+    """
+    try:
+        importer = sys.path_importer_cache[path_item]
+    except KeyError:
+        for path_hook in sys.path_hooks:
+            try:
+                importer = path_hook(path_item)
+                break
+            except ImportError:
+                pass
+        else:
+            importer = None
+        sys.path_importer_cache.setdefault(path_item, importer)
+
+    if importer is None:
+        try:
+            importer = ImpImporter(path_item)
+        except ImportError:
+            importer = None
+    return importer
+
+
+def iter_importers(fullname=""):
+    """Yield PEP 302 importers for the given module name
+
+    If fullname contains a '.', the importers will be for the package
+    containing fullname, otherwise they will be importers for sys.meta_path,
+    sys.path, and Python's "classic" import machinery, in that order.  If
+    the named module is in a package, that package is imported as a side
+    effect of invoking this function.
+
+    Non PEP 302 mechanisms (e.g. the Windows registry) used by the
+    standard import machinery to find files in alternative locations
+    are partially supported, but are searched AFTER sys.path. Normally,
+    these locations are searched BEFORE sys.path, preventing sys.path
+    entries from shadowing them.
+
+    For this to cause a visible difference in behaviour, there must
+    be a module or package name that is accessible via both sys.path
+    and one of the non PEP 302 file system mechanisms. In this case,
+    the emulation will find the former version, while the builtin
+    import mechanism will find the latter.
+
+    Items of the following types can be affected by this discrepancy:
+        imp.C_EXTENSION, imp.PY_SOURCE, imp.PY_COMPILED, imp.PKG_DIRECTORY
+    """
+    if fullname.startswith('.'):
+        raise ImportError("Relative module names not supported")
+    if '.' in fullname:
+        # Get the containing package's __path__
+        pkg = '.'.join(fullname.split('.')[:-1])
+        if pkg not in sys.modules:
+            __import__(pkg)
+        path = getattr(sys.modules[pkg], '__path__', None) or []
+    else:
+        for importer in sys.meta_path:
+            yield importer
+        path = sys.path
+    for item in path:
+        yield get_importer(item)
+    if '.' not in fullname:
+        yield ImpImporter()
+
+def get_loader(module_or_name):
+    """Get a PEP 302 "loader" object for module_or_name
+
+    If the module or package is accessible via the normal import
+    mechanism, a wrapper around the relevant part of that machinery
+    is returned.  Returns None if the module cannot be found or imported.
+    If the named module is not already imported, its containing package
+    (if any) is imported, in order to establish the package __path__.
+
+    This function uses iter_importers(), and is thus subject to the same
+    limitations regarding platform-specific special import locations such
+    as the Windows registry.
+    """
+    if module_or_name in sys.modules:
+        module_or_name = sys.modules[module_or_name]
+    if isinstance(module_or_name, ModuleType):
+        module = module_or_name
+        loader = getattr(module, '__loader__', None)
+        if loader is not None:
+            return loader
+        fullname = module.__name__
+    elif module_or_name == sys:
+        # Jython sys is not a real module; fake it here for now since
+        # making it a module requires a fair amount of decoupling from
+        # PySystemState
+        fullname = "sys"
+    else:
+        fullname = module_or_name
+    return find_loader(fullname)
+
+def find_loader(fullname):
+    """Find a PEP 302 "loader" object for fullname
+
+    If fullname contains dots, path must be the containing package's __path__.
+    Returns None if the module cannot be found or imported. This function uses
+    iter_importers(), and is thus subject to the same limitations regarding
+    platform-specific special import locations such as the Windows registry.
+    """
+    for importer in iter_importers(fullname):
+        loader = importer.find_module(fullname)
+        if loader is not None:
+            return loader
+
+    return None
+
+
+def extend_path(path, name):
+    """Extend a package's path.
+
+    Intended use is to place the following code in a package's __init__.py:
+
+        from pkgutil import extend_path
+        __path__ = extend_path(__path__, __name__)
+
+    This will add to the package's __path__ all subdirectories of
+    directories on sys.path named after the package.  This is useful
+    if one wants to distribute different parts of a single logical
+    package as multiple directories.
+
+    It also looks for *.pkg files beginning where * matches the name
+    argument.  This feature is similar to *.pth files (see site.py),
+    except that it doesn't special-case lines starting with 'import'.
+    A *.pkg file is trusted at face value: apart from checking for
+    duplicates, all entries found in a *.pkg file are added to the
+    path, regardless of whether they are exist the filesystem.  (This
+    is a feature.)
+
+    If the input path is not a list (as is the case for frozen
+    packages) it is returned unchanged.  The input path is not
+    modified; an extended copy is returned.  Items are only appended
+    to the copy at the end.
+
+    It is assumed that sys.path is a sequence.  Items of sys.path that
+    are not (unicode or 8-bit) strings referring to existing
+    directories are ignored.  Unicode items of sys.path that cause
+    errors when used as filenames may cause this function to raise an
+    exception (in line with os.path.isdir() behavior).
+    """
+
+    if not isinstance(path, list):
+        # This could happen e.g. when this is called from inside a
+        # frozen package.  Return the path unchanged in that case.
+        return path
+
+    pname = os.path.join(*name.split('.')) # Reconstitute as relative path
+    # Just in case os.extsep != '.'
+    sname = os.extsep.join(name.split('.'))
+    sname_pkg = sname + os.extsep + "pkg"
+    init_py = "__init__" + os.extsep + "py"
+
+    path = path[:] # Start with a copy of the existing path
+
+    for dir in sys.path:
+        if not isinstance(dir, basestring) or not os.path.isdir(dir):
+            continue
+        subdir = os.path.join(dir, pname)
+        # XXX This may still add duplicate entries to path on
+        # case-insensitive filesystems
+        initfile = os.path.join(subdir, init_py)
+        if subdir not in path and os.path.isfile(initfile):
+            path.append(subdir)
+        # XXX Is this the right thing for subpackages like zope.app?
+        # It looks for a file named "zope.app.pkg"
+        pkgfile = os.path.join(dir, sname_pkg)
+        if os.path.isfile(pkgfile):
+            try:
+                f = open(pkgfile)
+            except IOError, msg:
+                sys.stderr.write("Can't open %s: %s\n" %
+                                 (pkgfile, msg))
+            else:
+                try:
+                    for line in f:
+                        line = line.rstrip('\n')
+                        if not line or line.startswith('#'):
+                            continue
+                        path.append(line) # Don't check for existence!
+                finally:
+                    f.close()
+
+    return path
+
+def get_data(package, resource):
+    """Get a resource from a package.
+
+    This is a wrapper round the PEP 302 loader get_data API. The package
+    argument should be the name of a package, in standard module format
+    (foo.bar). The resource argument should be in the form of a relative
+    filename, using '/' as the path separator. The parent directory name '..'
+    is not allowed, and nor is a rooted name (starting with a '/').
+
+    The function returns a binary string, which is the contents of the
+    specified resource.
+
+    For packages located in the filesystem, which have already been imported,
+    this is the rough equivalent of
+
+        d = os.path.dirname(sys.modules[package].__file__)
+        data = open(os.path.join(d, resource), 'rb').read()
+
+    If the package cannot be located or loaded, or it uses a PEP 302 loader
+    which does not support get_data(), then None is returned.
+    """
+
+    loader = get_loader(package)
+    if loader is None or not hasattr(loader, 'get_data'):
+        return None
+    mod = sys.modules.get(package) or loader.load_module(package)
+    if mod is None or not hasattr(mod, '__file__'):
+        return None
+
+    # Modify the resource name to be compatible with the loader.get_data
+    # signature - an os.path format "filename" starting with the dirname of
+    # the package's __file__
+    parts = resource.split('/')
+    parts.insert(0, os.path.dirname(mod.__file__))
+    resource_name = os.path.join(*parts)
+    return loader.get_data(resource_name)
diff --git a/src/main/resources/PythonLibs/platform.py b/src/main/resources/PythonLibs/platform.py
new file mode 100644
index 0000000000000000000000000000000000000000..855d856e137eaa90fdeded6013509c31a42d3c29
--- /dev/null
+++ b/src/main/resources/PythonLibs/platform.py
@@ -0,0 +1,1654 @@
+#!/usr/bin/env python
+
+""" This module tries to retrieve as much platform-identifying data as
+    possible. It makes this information available via function APIs.
+
+    If called from the command line, it prints the platform
+    information concatenated as single string to stdout. The output
+    format is useable as part of a filename.
+
+"""
+#    This module is maintained by Marc-Andre Lemburg <mal@egenix.com>.
+#    If you find problems, please submit bug reports/patches via the
+#    Python bug tracker (http://bugs.python.org) and assign them to "lemburg".
+#
+#    Note: Please keep this module compatible to Python 1.5.2.
+#
+#    Still needed:
+#    * more support for WinCE
+#    * support for MS-DOS (PythonDX ?)
+#    * support for Amiga and other still unsupported platforms running Python
+#    * support for additional Linux distributions
+#
+#    Many thanks to all those who helped adding platform-specific
+#    checks (in no particular order):
+#
+#      Charles G Waldman, David Arnold, Gordon McMillan, Ben Darnell,
+#      Jeff Bauer, Cliff Crawford, Ivan Van Laningham, Josef
+#      Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
+#      Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
+#      Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support),
+#      Colin Kong, Trent Mick, Guido van Rossum, Anthony Baxter
+#
+#    History:
+#
+#    <see CVS and SVN checkin messages for history>
+#
+#    1.0.7 - added DEV_NULL
+#    1.0.6 - added linux_distribution()
+#    1.0.5 - fixed Java support to allow running the module on Jython
+#    1.0.4 - added IronPython support
+#    1.0.3 - added normalization of Windows system name
+#    1.0.2 - added more Windows support
+#    1.0.1 - reformatted to make doc.py happy
+#    1.0.0 - reformatted a bit and checked into Python CVS
+#    0.8.0 - added sys.version parser and various new access
+#            APIs (python_version(), python_compiler(), etc.)
+#    0.7.2 - fixed architecture() to use sizeof(pointer) where available
+#    0.7.1 - added support for Caldera OpenLinux
+#    0.7.0 - some fixes for WinCE; untabified the source file
+#    0.6.2 - support for OpenVMS - requires version 1.5.2-V006 or higher and
+#            vms_lib.getsyi() configured
+#    0.6.1 - added code to prevent 'uname -p' on platforms which are
+#            known not to support it
+#    0.6.0 - fixed win32_ver() to hopefully work on Win95,98,NT and Win2k;
+#            did some cleanup of the interfaces - some APIs have changed
+#    0.5.5 - fixed another type in the MacOS code... should have
+#            used more coffee today ;-)
+#    0.5.4 - fixed a few typos in the MacOS code
+#    0.5.3 - added experimental MacOS support; added better popen()
+#            workarounds in _syscmd_ver() -- still not 100% elegant
+#            though
+#    0.5.2 - fixed uname() to return '' instead of 'unknown' in all
+#            return values (the system uname command tends to return
+#            'unknown' instead of just leaving the field emtpy)
+#    0.5.1 - included code for slackware dist; added exception handlers
+#            to cover up situations where platforms don't have os.popen
+#            (e.g. Mac) or fail on socket.gethostname(); fixed libc
+#            detection RE
+#    0.5.0 - changed the API names referring to system commands to *syscmd*;
+#            added java_ver(); made syscmd_ver() a private
+#            API (was system_ver() in previous versions) -- use uname()
+#            instead; extended the win32_ver() to also return processor
+#            type information
+#    0.4.0 - added win32_ver() and modified the platform() output for WinXX
+#    0.3.4 - fixed a bug in _follow_symlinks()
+#    0.3.3 - fixed popen() and "file" command invokation bugs
+#    0.3.2 - added architecture() API and support for it in platform()
+#    0.3.1 - fixed syscmd_ver() RE to support Windows NT
+#    0.3.0 - added system alias support
+#    0.2.3 - removed 'wince' again... oh well.
+#    0.2.2 - added 'wince' to syscmd_ver() supported platforms
+#    0.2.1 - added cache logic and changed the platform string format
+#    0.2.0 - changed the API to use functions instead of module globals
+#            since some action take too long to be run on module import
+#    0.1.0 - first release
+#
+#    You can always get the latest version of this module at:
+#
+#             http://www.egenix.com/files/python/platform.py
+#
+#    If that URL should fail, try contacting the author.
+
+__copyright__ = """
+    Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com
+    Copyright (c) 2000-2010, eGenix.com Software GmbH; mailto:info@egenix.com
+
+    Permission to use, copy, modify, and distribute this software and its
+    documentation for any purpose and without fee or royalty is hereby granted,
+    provided that the above copyright notice appear in all copies and that
+    both that copyright notice and this permission notice appear in
+    supporting documentation or portions thereof, including modifications,
+    that you make.
+
+    EGENIX.COM SOFTWARE GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO
+    THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+    FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+    INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+    FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+    NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
+
+"""
+
+__version__ = '1.0.7'
+
+import sys,string,os,re
+
+### Globals & Constants
+if sys.platform.startswith("java"):
+    from java.lang import System
+    from org.python.core.Py import newString
+
+# Determine the platform's /dev/null device
+try:
+    DEV_NULL = os.devnull
+except AttributeError:
+    # os.devnull was added in Python 2.4, so emulate it for earlier
+    # Python versions
+    if sys.platform in ('dos','win32','win16','os2'):
+        # Use the old CP/M NUL as device name
+        DEV_NULL = 'NUL'
+    else:
+        # Standard Unix uses /dev/null
+        DEV_NULL = '/dev/null'
+
+### Platform specific APIs
+
+_libc_search = re.compile(r'(__libc_init)'
+                          '|'
+                          '(GLIBC_([0-9.]+))'
+                          '|'
+                          '(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)')
+
+def libc_ver(executable=sys.executable,lib='',version='',
+
+             chunksize=2048):
+
+    """ Tries to determine the libc version that the file executable
+        (which defaults to the Python interpreter) is linked against.
+
+        Returns a tuple of strings (lib,version) which default to the
+        given parameters in case the lookup fails.
+
+        Note that the function has intimate knowledge of how different
+        libc versions add symbols to the executable and thus is probably
+        only useable for executables compiled using gcc.
+
+        The file is read and scanned in chunks of chunksize bytes.
+
+    """
+    if hasattr(os.path, 'realpath'):
+        # Python 2.2 introduced os.path.realpath(); it is used
+        # here to work around problems with Cygwin not being
+        # able to open symlinks for reading
+        executable = os.path.realpath(executable)
+    f = open(executable,'rb')
+    binary = f.read(chunksize)
+    pos = 0
+    while 1:
+        m = _libc_search.search(binary,pos)
+        if not m:
+            binary = f.read(chunksize)
+            if not binary:
+                break
+            pos = 0
+            continue
+        libcinit,glibc,glibcversion,so,threads,soversion = m.groups()
+        if libcinit and not lib:
+            lib = 'libc'
+        elif glibc:
+            if lib != 'glibc':
+                lib = 'glibc'
+                version = glibcversion
+            elif glibcversion > version:
+                version = glibcversion
+        elif so:
+            if lib != 'glibc':
+                lib = 'libc'
+                if soversion and soversion > version:
+                    version = soversion
+                if threads and version[-len(threads):] != threads:
+                    version = version + threads
+        pos = m.end()
+    f.close()
+    return lib,version
+
+def _dist_try_harder(distname,version,id):
+
+    """ Tries some special tricks to get the distribution
+        information in case the default method fails.
+
+        Currently supports older SuSE Linux, Caldera OpenLinux and
+        Slackware Linux distributions.
+
+    """
+    if os.path.exists('/var/adm/inst-log/info'):
+        # SuSE Linux stores distribution information in that file
+        info = open('/var/adm/inst-log/info').readlines()
+        distname = 'SuSE'
+        for line in info:
+            tv = string.split(line)
+            if len(tv) == 2:
+                tag,value = tv
+            else:
+                continue
+            if tag == 'MIN_DIST_VERSION':
+                version = string.strip(value)
+            elif tag == 'DIST_IDENT':
+                values = string.split(value,'-')
+                id = values[2]
+        return distname,version,id
+
+    if os.path.exists('/etc/.installed'):
+        # Caldera OpenLinux has some infos in that file (thanks to Colin Kong)
+        info = open('/etc/.installed').readlines()
+        for line in info:
+            pkg = string.split(line,'-')
+            if len(pkg) >= 2 and pkg[0] == 'OpenLinux':
+                # XXX does Caldera support non Intel platforms ? If yes,
+                #     where can we find the needed id ?
+                return 'OpenLinux',pkg[1],id
+
+    if os.path.isdir('/usr/lib/setup'):
+        # Check for slackware verson tag file (thanks to Greg Andruk)
+        verfiles = os.listdir('/usr/lib/setup')
+        for n in range(len(verfiles)-1, -1, -1):
+            if verfiles[n][:14] != 'slack-version-':
+                del verfiles[n]
+        if verfiles:
+            verfiles.sort()
+            distname = 'slackware'
+            version = verfiles[-1][14:]
+            return distname,version,id
+
+    return distname,version,id
+
+_release_filename = re.compile(r'(\w+)[-_](release|version)')
+_lsb_release_version = re.compile(r'(.+)'
+                                   ' release '
+                                   '([\d.]+)'
+                                   '[^(]*(?:\((.+)\))?')
+_release_version = re.compile(r'([^0-9]+)'
+                               '(?: release )?'
+                               '([\d.]+)'
+                               '[^(]*(?:\((.+)\))?')
+
+# See also http://www.novell.com/coolsolutions/feature/11251.html
+# and http://linuxmafia.com/faq/Admin/release-files.html
+# and http://data.linux-ntfs.org/rpm/whichrpm
+# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html
+
+_supported_dists = (
+    'SuSE', 'debian', 'fedora', 'redhat', 'centos',
+    'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
+    'UnitedLinux', 'turbolinux')
+
+def _parse_release_file(firstline):
+
+    # Default to empty 'version' and 'id' strings.  Both defaults are used
+    # when 'firstline' is empty.  'id' defaults to empty when an id can not
+    # be deduced.
+    version = ''
+    id = ''
+
+    # Parse the first line
+    m = _lsb_release_version.match(firstline)
+    if m is not None:
+        # LSB format: "distro release x.x (codename)"
+        return tuple(m.groups())
+
+    # Pre-LSB format: "distro x.x (codename)"
+    m = _release_version.match(firstline)
+    if m is not None:
+        return tuple(m.groups())
+
+    # Unkown format... take the first two words
+    l = string.split(string.strip(firstline))
+    if l:
+        version = l[0]
+        if len(l) > 1:
+            id = l[1]
+    return '', version, id
+
+def linux_distribution(distname='', version='', id='',
+
+                       supported_dists=_supported_dists,
+                       full_distribution_name=1):
+
+    """ Tries to determine the name of the Linux OS distribution name.
+
+        The function first looks for a distribution release file in
+        /etc and then reverts to _dist_try_harder() in case no
+        suitable files are found.
+
+        supported_dists may be given to define the set of Linux
+        distributions to look for. It defaults to a list of currently
+        supported Linux distributions identified by their release file
+        name.
+
+        If full_distribution_name is true (default), the full
+        distribution read from the OS is returned. Otherwise the short
+        name taken from supported_dists is used.
+
+        Returns a tuple (distname,version,id) which default to the
+        args given as parameters.
+
+    """
+    try:
+        etc = os.listdir('/etc')
+    except os.error:
+        # Probably not a Unix system
+        return distname,version,id
+    etc.sort()
+    for file in etc:
+        m = _release_filename.match(file)
+        if m is not None:
+            _distname,dummy = m.groups()
+            if _distname in supported_dists:
+                distname = _distname
+                break
+    else:
+        return _dist_try_harder(distname,version,id)
+
+    # Read the first line
+    f = open('/etc/'+file, 'r')
+    firstline = f.readline()
+    f.close()
+    _distname, _version, _id = _parse_release_file(firstline)
+
+    if _distname and full_distribution_name:
+        distname = _distname
+    if _version:
+        version = _version
+    if _id:
+        id = _id
+    return distname, version, id
+
+# To maintain backwards compatibility:
+
+def dist(distname='',version='',id='',
+
+         supported_dists=_supported_dists):
+
+    """ Tries to determine the name of the Linux OS distribution name.
+
+        The function first looks for a distribution release file in
+        /etc and then reverts to _dist_try_harder() in case no
+        suitable files are found.
+
+        Returns a tuple (distname,version,id) which default to the
+        args given as parameters.
+
+    """
+    return linux_distribution(distname, version, id,
+                              supported_dists=supported_dists,
+                              full_distribution_name=0)
+
+class _popen:
+
+    """ Fairly portable (alternative) popen implementation.
+
+        This is mostly needed in case os.popen() is not available, or
+        doesn't work as advertised, e.g. in Win9X GUI programs like
+        PythonWin or IDLE.
+
+        Writing to the pipe is currently not supported.
+
+    """
+    tmpfile = ''
+    pipe = None
+    bufsize = None
+    mode = 'r'
+
+    def __init__(self,cmd,mode='r',bufsize=None):
+
+        if mode != 'r':
+            raise ValueError,'popen()-emulation only supports read mode'
+        import tempfile
+        self.tmpfile = tmpfile = tempfile.mktemp()
+        os.system(cmd + ' > %s' % tmpfile)
+        self.pipe = open(tmpfile,'rb')
+        self.bufsize = bufsize
+        self.mode = mode
+
+    def read(self):
+
+        return self.pipe.read()
+
+    def readlines(self):
+
+        if self.bufsize is not None:
+            return self.pipe.readlines()
+
+    def close(self,
+
+              remove=os.unlink,error=os.error):
+
+        if self.pipe:
+            rc = self.pipe.close()
+        else:
+            rc = 255
+        if self.tmpfile:
+            try:
+                remove(self.tmpfile)
+            except error:
+                pass
+        return rc
+
+    # Alias
+    __del__ = close
+
+def popen(cmd, mode='r', bufsize=None):
+
+    """ Portable popen() interface.
+    """
+    # Find a working popen implementation preferring win32pipe.popen
+    # over os.popen over _popen
+    popen = None
+    if os.environ.get('OS','') == 'Windows_NT':
+        # On NT win32pipe should work; on Win9x it hangs due to bugs
+        # in the MS C lib (see MS KnowledgeBase article Q150956)
+        try:
+            import win32pipe
+        except ImportError:
+            pass
+        else:
+            popen = win32pipe.popen
+    if popen is None:
+        if hasattr(os,'popen'):
+            popen = os.popen
+            # Check whether it works... it doesn't in GUI programs
+            # on Windows platforms
+            if sys.platform == 'win32': # XXX Others too ?
+                try:
+                    popen('')
+                except os.error:
+                    popen = _popen
+        else:
+            popen = _popen
+    if bufsize is None:
+        return popen(cmd,mode)
+    else:
+        return popen(cmd,mode,bufsize)
+
+def _norm_version(version, build=''):
+
+    """ Normalize the version and build strings and return a single
+        version string using the format major.minor.build (or patchlevel).
+    """
+    l = string.split(version,'.')
+    if build:
+        l.append(build)
+    try:
+        ints = map(int,l)
+    except ValueError:
+        strings = l
+    else:
+        strings = map(str,ints)
+    version = string.join(strings[:3],'.')
+    return version
+
+_ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) '
+                         '.*'
+                         '\[.* ([\d.]+)\])')
+
+# Examples of VER command output:
+#
+#   Windows 2000:  Microsoft Windows 2000 [Version 5.00.2195]
+#   Windows XP:    Microsoft Windows XP [Version 5.1.2600]
+#   Windows Vista: Microsoft Windows [Version 6.0.6002]
+#
+# Note that the "Version" string gets localized on different
+# Windows versions.
+
+def _syscmd_ver(system='', release='', version='',
+
+               supported_platforms=('win32','win16','dos','os2')):
+
+    """ Tries to figure out the OS version used and returns
+        a tuple (system,release,version).
+
+        It uses the "ver" shell command for this which is known
+        to exists on Windows, DOS and OS/2. XXX Others too ?
+
+        In case this fails, the given parameters are used as
+        defaults.
+
+    """
+    if sys.platform not in supported_platforms:
+        return system,release,version
+
+    # Try some common cmd strings
+    for cmd in ('ver','command /c ver','cmd /c ver'):
+        try:
+            pipe = popen(cmd)
+            info = pipe.read()
+            if pipe.close():
+                raise os.error,'command failed'
+            # XXX How can I suppress shell errors from being written
+            #     to stderr ?
+        except os.error,why:
+            #print 'Command %s failed: %s' % (cmd,why)
+            continue
+        except IOError,why:
+            #print 'Command %s failed: %s' % (cmd,why)
+            continue
+        else:
+            break
+    else:
+        return system,release,version
+
+    # Parse the output
+    info = string.strip(info)
+    m = _ver_output.match(info)
+    if m is not None:
+        system,release,version = m.groups()
+        # Strip trailing dots from version and release
+        if release[-1] == '.':
+            release = release[:-1]
+        if version[-1] == '.':
+            version = version[:-1]
+        # Normalize the version and build strings (eliminating additional
+        # zeros)
+        version = _norm_version(version)
+    return system,release,version
+
+def _win32_getvalue(key,name,default=''):
+
+    """ Read a value for name from the registry key.
+
+        In case this fails, default is returned.
+
+    """
+    try:
+        # Use win32api if available
+        from win32api import RegQueryValueEx
+    except ImportError:
+        # On Python 2.0 and later, emulate using _winreg
+        import _winreg
+        RegQueryValueEx = _winreg.QueryValueEx
+    try:
+        return RegQueryValueEx(key,name)
+    except:
+        return default
+
+def win32_ver(release='',version='',csd='',ptype=''):
+
+    """ Get additional version information from the Windows Registry
+        and return a tuple (version,csd,ptype) referring to version
+        number, CSD level (service pack), and OS type (multi/single
+        processor).
+
+        As a hint: ptype returns 'Uniprocessor Free' on single
+        processor NT machines and 'Multiprocessor Free' on multi
+        processor machines. The 'Free' refers to the OS version being
+        free of debugging code. It could also state 'Checked' which
+        means the OS version uses debugging code, i.e. code that
+        checks arguments, ranges, etc. (Thomas Heller).
+
+        Note: this function works best with Mark Hammond's win32
+        package installed, but also on Python 2.3 and later. It
+        obviously only runs on Win32 compatible platforms.
+
+    """
+    # XXX Is there any way to find out the processor type on WinXX ?
+    # XXX Is win32 available on Windows CE ?
+    #
+    # Adapted from code posted by Karl Putland to comp.lang.python.
+    #
+    # The mappings between reg. values and release names can be found
+    # here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
+
+    # Import the needed APIs
+    try:
+        import win32api
+        from win32api import RegQueryValueEx, RegOpenKeyEx, \
+             RegCloseKey, GetVersionEx
+        from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
+             VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
+    except ImportError:
+        # Emulate the win32api module using Python APIs
+        try:
+            sys.getwindowsversion
+        except AttributeError:
+            # No emulation possible, so return the defaults...
+            return release,version,csd,ptype
+        else:
+            # Emulation using _winreg (added in Python 2.0) and
+            # sys.getwindowsversion() (added in Python 2.3)
+            import _winreg
+            GetVersionEx = sys.getwindowsversion
+            RegQueryValueEx = _winreg.QueryValueEx
+            RegOpenKeyEx = _winreg.OpenKeyEx
+            RegCloseKey = _winreg.CloseKey
+            HKEY_LOCAL_MACHINE = _winreg.HKEY_LOCAL_MACHINE
+            VER_PLATFORM_WIN32_WINDOWS = 1
+            VER_PLATFORM_WIN32_NT = 2
+            VER_NT_WORKSTATION = 1
+            VER_NT_SERVER = 3
+            REG_SZ = 1
+
+    # Find out the registry key and some general version infos
+    winver = GetVersionEx()
+    maj,min,buildno,plat,csd = winver
+    version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF)
+    if hasattr(winver, "service_pack"):
+        if winver.service_pack != "":
+            csd = 'SP%s' % winver.service_pack_major
+    else:
+        if csd[:13] == 'Service Pack ':
+            csd = 'SP' + csd[13:]
+
+    if plat == VER_PLATFORM_WIN32_WINDOWS:
+        regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
+        # Try to guess the release name
+        if maj == 4:
+            if min == 0:
+                release = '95'
+            elif min == 10:
+                release = '98'
+            elif min == 90:
+                release = 'Me'
+            else:
+                release = 'postMe'
+        elif maj == 5:
+            release = '2000'
+
+    elif plat == VER_PLATFORM_WIN32_NT:
+        regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
+        if maj <= 4:
+            release = 'NT'
+        elif maj == 5:
+            if min == 0:
+                release = '2000'
+            elif min == 1:
+                release = 'XP'
+            elif min == 2:
+                release = '2003Server'
+            else:
+                release = 'post2003'
+        elif maj == 6:
+            if hasattr(winver, "product_type"):
+                product_type = winver.product_type
+            else:
+                product_type = VER_NT_WORKSTATION
+                # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
+                # or help from the registry, we cannot properly identify
+                # non-workstation versions.
+                try:
+                    key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
+                    name, type = RegQueryValueEx(key, "ProductName")
+                    # Discard any type that isn't REG_SZ
+                    if type == REG_SZ and name.find("Server") != -1:
+                        product_type = VER_NT_SERVER
+                except WindowsError:
+                    # Use default of VER_NT_WORKSTATION
+                    pass
+
+            if min == 0:
+                if product_type == VER_NT_WORKSTATION:
+                    release = 'Vista'
+                else:
+                    release = '2008Server'
+            elif min == 1:
+                if product_type == VER_NT_WORKSTATION:
+                    release = '7'
+                else:
+                    release = '2008ServerR2'
+            elif min == 2:
+                if product_type == VER_NT_WORKSTATION:
+                    release = '8'
+                else:
+                    release = '2012Server'
+            else:
+                release = 'post2012Server'
+
+    else:
+        if not release:
+            # E.g. Win3.1 with win32s
+            release = '%i.%i' % (maj,min)
+        return release,version,csd,ptype
+
+    # Open the registry key
+    try:
+        keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
+        # Get a value to make sure the key exists...
+        RegQueryValueEx(keyCurVer, 'SystemRoot')
+    except:
+        return release,version,csd,ptype
+
+    # Parse values
+    #subversion = _win32_getvalue(keyCurVer,
+    #                            'SubVersionNumber',
+    #                            ('',1))[0]
+    #if subversion:
+    #   release = release + subversion # 95a, 95b, etc.
+    build = _win32_getvalue(keyCurVer,
+                            'CurrentBuildNumber',
+                            ('',1))[0]
+    ptype = _win32_getvalue(keyCurVer,
+                           'CurrentType',
+                           (ptype,1))[0]
+
+    # Normalize version
+    version = _norm_version(version,build)
+
+    # Close key
+    RegCloseKey(keyCurVer)
+    return release,version,csd,ptype
+
+def _mac_ver_lookup(selectors,default=None):
+
+    from gestalt import gestalt
+    import MacOS
+    l = []
+    append = l.append
+    for selector in selectors:
+        try:
+            append(gestalt(selector))
+        except (RuntimeError, MacOS.Error):
+            append(default)
+    return l
+
+def _bcd2str(bcd):
+
+    return hex(bcd)[2:]
+
+def _mac_ver_gestalt():
+    """
+        Thanks to Mark R. Levinson for mailing documentation links and
+        code examples for this function. Documentation for the
+        gestalt() API is available online at:
+
+           http://www.rgaros.nl/gestalt/
+    """
+    # Check whether the version info module is available
+    try:
+        import gestalt
+        import MacOS
+    except ImportError:
+        return None
+    # Get the infos
+    sysv,sysa = _mac_ver_lookup(('sysv','sysa'))
+    # Decode the infos
+    if sysv:
+        major = (sysv & 0xFF00) >> 8
+        minor = (sysv & 0x00F0) >> 4
+        patch = (sysv & 0x000F)
+
+        if (major, minor) >= (10, 4):
+            # the 'sysv' gestald cannot return patchlevels
+            # higher than 9. Apple introduced 3 new
+            # gestalt codes in 10.4 to deal with this
+            # issue (needed because patch levels can
+            # run higher than 9, such as 10.4.11)
+            major,minor,patch = _mac_ver_lookup(('sys1','sys2','sys3'))
+            release = '%i.%i.%i' %(major, minor, patch)
+        else:
+            release = '%s.%i.%i' % (_bcd2str(major),minor,patch)
+
+    if sysa:
+        machine = {0x1: '68k',
+                   0x2: 'PowerPC',
+                   0xa: 'i386'}.get(sysa,'')
+
+    versioninfo=('', '', '')
+    return release,versioninfo,machine
+
+def _mac_ver_xml():
+    fn = '/System/Library/CoreServices/SystemVersion.plist'
+    if not os.path.exists(fn):
+        return None
+
+    try:
+        import plistlib
+    except ImportError:
+        return None
+
+    pl = plistlib.readPlist(fn)
+    release = pl['ProductVersion']
+    versioninfo=('', '', '')
+    machine = os.uname()[4]
+    if machine in ('ppc', 'Power Macintosh'):
+        # for compatibility with the gestalt based code
+        machine = 'PowerPC'
+
+    return release,versioninfo,machine
+
+
+def mac_ver(release='',versioninfo=('','',''),machine=''):
+
+    """ Get MacOS version information and return it as tuple (release,
+        versioninfo, machine) with versioninfo being a tuple (version,
+        dev_stage, non_release_version).
+
+        Entries which cannot be determined are set to the paramter values
+        which default to ''. All tuple entries are strings.
+    """
+
+    # First try reading the information from an XML file which should
+    # always be present
+    info = _mac_ver_xml()
+    if info is not None:
+        return info
+
+    # If that doesn't work for some reason fall back to reading the
+    # information using gestalt calls.
+    info = _mac_ver_gestalt()
+    if info is not None:
+        return info
+
+    # If that also doesn't work return the default values
+    return release,versioninfo,machine
+
+def _java_getprop(name,default):
+
+    try:
+        value = System.getProperty(name)
+        if value is None:
+            return default
+        return newString(value)
+    except AttributeError:
+        return default
+
+def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')):
+
+    """ Version interface for Jython.
+
+        Returns a tuple (release,vendor,vminfo,osinfo) with vminfo being
+        a tuple (vm_name,vm_release,vm_vendor) and osinfo being a
+        tuple (os_name,os_version,os_arch).
+
+        Values which cannot be determined are set to the defaults
+        given as parameters (which all default to '').
+
+    """
+    # Import the needed APIs
+    try:
+        import java.lang
+    except ImportError:
+        return release,vendor,vminfo,osinfo
+
+    vendor = _java_getprop('java.vendor', vendor)
+    release = _java_getprop('java.version', release)
+    vm_name, vm_release, vm_vendor = vminfo
+    vm_name = _java_getprop('java.vm.name', vm_name)
+    vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
+    vm_release = _java_getprop('java.vm.version', vm_release)
+    vminfo = vm_name, vm_release, vm_vendor
+    os_name, os_version, os_arch = osinfo
+    os_arch = _java_getprop('os.arch', os_arch)
+    os_name = _java_getprop('os.name', os_name)
+    os_version = _java_getprop('os.version', os_version)
+    osinfo = os_name, os_version, os_arch
+
+    return release, vendor, vminfo, osinfo
+
+### System name aliasing
+
+def system_alias(system,release,version):
+
+    """ Returns (system,release,version) aliased to common
+        marketing names used for some systems.
+
+        It also does some reordering of the information in some cases
+        where it would otherwise cause confusion.
+
+    """
+    if system == 'Rhapsody':
+        # Apple's BSD derivative
+        # XXX How can we determine the marketing release number ?
+        return 'MacOS X Server',system+release,version
+
+    elif system == 'SunOS':
+        # Sun's OS
+        if release < '5':
+            # These releases use the old name SunOS
+            return system,release,version
+        # Modify release (marketing release = SunOS release - 3)
+        l = string.split(release,'.')
+        if l:
+            try:
+                major = int(l[0])
+            except ValueError:
+                pass
+            else:
+                major = major - 3
+                l[0] = str(major)
+                release = string.join(l,'.')
+        if release < '6':
+            system = 'Solaris'
+        else:
+            # XXX Whatever the new SunOS marketing name is...
+            system = 'Solaris'
+
+    elif system == 'IRIX64':
+        # IRIX reports IRIX64 on platforms with 64-bit support; yet it
+        # is really a version and not a different platform, since 32-bit
+        # apps are also supported..
+        system = 'IRIX'
+        if version:
+            version = version + ' (64bit)'
+        else:
+            version = '64bit'
+
+    elif system in ('win32','win16'):
+        # In case one of the other tricks
+        system = 'Windows'
+
+    return system,release,version
+
+### Various internal helpers
+
+def _platform(*args):
+
+    """ Helper to format the platform string in a filename
+        compatible format e.g. "system-version-machine".
+    """
+    # Format the platform string
+    platform = string.join(
+        map(string.strip,
+            filter(len, args)),
+        '-')
+
+    # Cleanup some possible filename obstacles...
+    replace = string.replace
+    platform = replace(platform,' ','_')
+    platform = replace(platform,'/','-')
+    platform = replace(platform,'\\','-')
+    platform = replace(platform,':','-')
+    platform = replace(platform,';','-')
+    platform = replace(platform,'"','-')
+    platform = replace(platform,'(','-')
+    platform = replace(platform,')','-')
+
+    # No need to report 'unknown' information...
+    platform = replace(platform,'unknown','')
+
+    # Fold '--'s and remove trailing '-'
+    while 1:
+        cleaned = replace(platform,'--','-')
+        if cleaned == platform:
+            break
+        platform = cleaned
+    while platform[-1] == '-':
+        platform = platform[:-1]
+
+    return platform
+
+def _node(default=''):
+
+    """ Helper to determine the node name of this machine.
+    """
+    try:
+        import socket
+    except ImportError:
+        # No sockets...
+        return default
+    try:
+        return socket.gethostname()
+    except socket.error:
+        # Still not working...
+        return default
+
+# os.path.abspath is new in Python 1.5.2:
+if not hasattr(os.path,'abspath'):
+
+    def _abspath(path,
+
+                 isabs=os.path.isabs,join=os.path.join,getcwd=os.getcwd,
+                 normpath=os.path.normpath):
+
+        if not isabs(path):
+            path = join(getcwd(), path)
+        return normpath(path)
+
+else:
+
+    _abspath = os.path.abspath
+
+def _follow_symlinks(filepath):
+
+    """ In case filepath is a symlink, follow it until a
+        real file is reached.
+    """
+    filepath = _abspath(filepath)
+    while os.path.islink(filepath):
+        filepath = os.path.normpath(
+            os.path.join(os.path.dirname(filepath),os.readlink(filepath)))
+    return filepath
+
+def _syscmd_uname(option,default=''):
+
+    """ Interface to the system's uname command.
+    """
+    if sys.platform in ('dos','win32','win16','os2') or \
+       (sys.platform.startswith('java') and os._name == 'nt'):
+        # XXX Others too ?
+        return default
+    try:
+        f = os.popen('uname %s 2> %s' % (option, DEV_NULL))
+    except (AttributeError,os.error):
+        return default
+    output = string.strip(f.read())
+    rc = f.close()
+    if not output or rc:
+        return default
+    else:
+        return output
+
+def _syscmd_file(target,default=''):
+
+    """ Interface to the system's file command.
+
+        The function uses the -b option of the file command to have it
+        ommit the filename in its output and if possible the -L option
+        to have the command follow symlinks. It returns default in
+        case the command should fail.
+
+    """
+
+    # We do the import here to avoid a bootstrap issue.
+    # See c73b90b6dadd changeset.
+    #
+    # [..]
+    # ranlib libpython2.7.a
+    # gcc   -o python \
+    #        Modules/python.o \
+    #        libpython2.7.a -lsocket -lnsl -ldl    -lm
+    # Traceback (most recent call last):
+    #  File "./setup.py", line 8, in <module>
+    #    from platform import machine as platform_machine
+    #  File "[..]/build/Lib/platform.py", line 116, in <module>
+    #    import sys,string,os,re,subprocess
+    #  File "[..]/build/Lib/subprocess.py", line 429, in <module>
+    #    import select
+    # ImportError: No module named select
+
+    import subprocess
+
+    if sys.platform in ('dos','win32','win16','os2'):
+        # XXX Others too ?
+        return default
+    target = _follow_symlinks(target)
+    try:
+        proc = subprocess.Popen(['file', target],
+                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+    except (AttributeError,os.error):
+        return default
+    output = proc.communicate()[0]
+    rc = proc.wait()
+    if not output or rc:
+        return default
+    else:
+        return output
+
+### Information about the used architecture
+
+# Default values for architecture; non-empty strings override the
+# defaults given as parameters
+_default_architecture = {
+    'win32': ('','WindowsPE'),
+    'win16': ('','Windows'),
+    'dos': ('','MSDOS'),
+}
+
+_architecture_split = re.compile(r'[\s,]').split
+
+def architecture(executable=sys.executable,bits='',linkage=''):
+
+    """ Queries the given executable (defaults to the Python interpreter
+        binary) for various architecture information.
+
+        Returns a tuple (bits,linkage) which contains information about
+        the bit architecture and the linkage format used for the
+        executable. Both values are returned as strings.
+
+        Values that cannot be determined are returned as given by the
+        parameter presets. If bits is given as '', the sizeof(pointer)
+        (or sizeof(long) on Python version < 1.5.2) is used as
+        indicator for the supported pointer size.
+
+        The function relies on the system's "file" command to do the
+        actual work. This is available on most if not all Unix
+        platforms. On some non-Unix platforms where the "file" command
+        does not exist and the executable is set to the Python interpreter
+        binary defaults from _default_architecture are used.
+
+    """
+    # Use the sizeof(pointer) as default number of bits if nothing
+    # else is given as default.
+    if not bits:
+        import struct
+        try:
+            size = struct.calcsize('P')
+        except struct.error:
+            # Older installations can only query longs
+            size = struct.calcsize('l')
+        bits = str(size*8) + 'bit'
+
+    # Get data from the 'file' system command
+    if executable:
+        output = _syscmd_file(executable, '')
+    else:
+        output = ''
+
+    if not output and \
+       executable == sys.executable:
+        # "file" command did not return anything; we'll try to provide
+        # some sensible defaults then...
+        if sys.platform in _default_architecture:
+            b, l = _default_architecture[sys.platform]
+            if b:
+                bits = b
+            if l:
+                linkage = l
+        return bits, linkage
+
+    # Split the output into a list of strings omitting the filename
+    fileout = _architecture_split(output)[1:]
+
+    if 'executable' not in fileout:
+        # Format not supported
+        return bits,linkage
+
+    # Bits
+    if '32-bit' in fileout:
+        bits = '32bit'
+    elif 'N32' in fileout:
+        # On Irix only
+        bits = 'n32bit'
+    elif '64-bit' in fileout:
+        bits = '64bit'
+
+    # Linkage
+    if 'ELF' in fileout:
+        linkage = 'ELF'
+    elif 'PE' in fileout:
+        # E.g. Windows uses this format
+        if 'Windows' in fileout:
+            linkage = 'WindowsPE'
+        else:
+            linkage = 'PE'
+    elif 'COFF' in fileout:
+        linkage = 'COFF'
+    elif 'MS-DOS' in fileout:
+        linkage = 'MSDOS'
+    else:
+        # XXX the A.OUT format also falls under this class...
+        pass
+
+    return bits,linkage
+
+### Portable uname() interface
+
+_uname_cache = None
+
+def uname():
+
+    """ Fairly portable uname interface. Returns a tuple
+        of strings (system,node,release,version,machine,processor)
+        identifying the underlying platform.
+
+        Note that unlike the os.uname function this also returns
+        possible processor information as an additional tuple entry.
+
+        Entries which cannot be determined are set to ''.
+
+    """
+    global _uname_cache
+    no_os_uname = 0
+
+    if _uname_cache is not None:
+        return _uname_cache
+
+    processor = ''
+
+    # Get some infos from the builtin os.uname API...
+    try:
+        system,node,release,version,machine = os.uname()
+    except AttributeError:
+        no_os_uname = 1
+
+    if no_os_uname or not filter(None, (system, node, release, version, machine)):
+        # Hmm, no there is either no uname or uname has returned
+        #'unknowns'... we'll have to poke around the system then.
+        if no_os_uname:
+            system = sys.platform
+            release = ''
+            version = ''
+            node = _node()
+            machine = ''
+
+        use_syscmd_ver = 1
+
+        # Try win32_ver() on win32 platforms
+        if system == 'win32':
+            release,version,csd,ptype = win32_ver()
+            if release and version:
+                use_syscmd_ver = 0
+            # Try to use the PROCESSOR_* environment variables
+            # available on Win XP and later; see
+            # http://support.microsoft.com/kb/888731 and
+            # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
+            if not machine:
+                # WOW64 processes mask the native architecture
+                if "PROCESSOR_ARCHITEW6432" in os.environ:
+                    machine = os.environ.get("PROCESSOR_ARCHITEW6432", '')
+                else:
+                    machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
+            if not processor:
+                processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
+
+        # Try the 'ver' system command available on some
+        # platforms
+        if use_syscmd_ver:
+            system,release,version = _syscmd_ver(system)
+            # Normalize system to what win32_ver() normally returns
+            # (_syscmd_ver() tends to return the vendor name as well)
+            if system == 'Microsoft Windows':
+                system = 'Windows'
+            elif system == 'Microsoft' and release == 'Windows':
+                # Under Windows Vista and Windows Server 2008,
+                # Microsoft changed the output of the ver command. The
+                # release is no longer printed.  This causes the
+                # system and release to be misidentified.
+                system = 'Windows'
+                if '6.0' == version[:3]:
+                    release = 'Vista'
+                else:
+                    release = ''
+
+        # In case we still don't know anything useful, we'll try to
+        # help ourselves
+        if system in ('win32','win16'):
+            if not version:
+                if system == 'win32':
+                    version = '32bit'
+                else:
+                    version = '16bit'
+            system = 'Windows'
+
+        elif system[:4] == 'java':
+            release,vendor,vminfo,osinfo = java_ver()
+            system = 'Java'
+            version = string.join(vminfo,', ')
+            if not version:
+                version = vendor
+
+    # System specific extensions
+    if system == 'OpenVMS':
+        # OpenVMS seems to have release and version mixed up
+        if not release or release == '0':
+            release = version
+            version = ''
+        # Get processor information
+        try:
+            import vms_lib
+        except ImportError:
+            pass
+        else:
+            csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
+            if (cpu_number >= 128):
+                processor = 'Alpha'
+            else:
+                processor = 'VAX'
+    if not processor:
+        # Get processor information from the uname system command
+        processor = _syscmd_uname('-p','')
+
+    #If any unknowns still exist, replace them with ''s, which are more portable
+    if system == 'unknown':
+        system = ''
+    if node == 'unknown':
+        node = ''
+    if release == 'unknown':
+        release = ''
+    if version == 'unknown':
+        version = ''
+    if machine == 'unknown':
+        machine = ''
+    if processor == 'unknown':
+        processor = ''
+
+    #  normalize name
+    if system == 'Microsoft' and release == 'Windows':
+        system = 'Windows'
+        release = 'Vista'
+
+    _uname_cache = system,node,release,version,machine,processor
+    return _uname_cache
+
+### Direct interfaces to some of the uname() return values
+
+def system():
+
+    """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
+
+        An empty string is returned if the value cannot be determined.
+
+    """
+    return uname()[0]
+
+def node():
+
+    """ Returns the computer's network name (which may not be fully
+        qualified)
+
+        An empty string is returned if the value cannot be determined.
+
+    """
+    return uname()[1]
+
+def release():
+
+    """ Returns the system's release, e.g. '2.2.0' or 'NT'
+
+        An empty string is returned if the value cannot be determined.
+
+    """
+    return uname()[2]
+
+def version():
+
+    """ Returns the system's release version, e.g. '#3 on degas'
+
+        An empty string is returned if the value cannot be determined.
+
+    """
+    return uname()[3]
+
+def machine():
+
+    """ Returns the machine type, e.g. 'i386'
+
+        An empty string is returned if the value cannot be determined.
+
+    """
+    return uname()[4]
+
+def processor():
+
+    """ Returns the (true) processor name, e.g. 'amdk6'
+
+        An empty string is returned if the value cannot be
+        determined. Note that many platforms do not provide this
+        information or simply return the same value as for machine(),
+        e.g.  NetBSD does this.
+
+    """
+    return uname()[5]
+
+### Various APIs for extracting information from sys.version
+
+_sys_version_parser = re.compile(
+    r'([\w.+]+)\s*'
+    '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
+    '\[([^\]]+)\]?')
+
+_jython_sys_version_parser = re.compile(
+    r'([\d\.]+)')
+
+_ironpython_sys_version_parser = re.compile(
+    r'IronPython\s*'
+    '([\d\.]+)'
+    '(?: \(([\d\.]+)\))?'
+    ' on (.NET [\d\.]+)')
+
+_pypy_sys_version_parser = re.compile(
+    r'([\w.+]+)\s*'
+    '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
+    '\[PyPy [^\]]+\]?')
+
+_sys_version_cache = {}
+
+def _sys_version(sys_version=None):
+
+    """ Returns a parsed version of Python's sys.version as tuple
+        (name, version, branch, revision, buildno, builddate, compiler)
+        referring to the Python implementation name, version, branch,
+        revision, build number, build date/time as string and the compiler
+        identification string.
+
+        Note that unlike the Python sys.version, the returned value
+        for the Python version will always include the patchlevel (it
+        defaults to '.0').
+
+        The function returns empty strings for tuple entries that
+        cannot be determined.
+
+        sys_version may be given to parse an alternative version
+        string, e.g. if the version was read from a different Python
+        interpreter.
+
+    """
+    # Get the Python version
+    if sys_version is None:
+        sys_version = sys.version
+
+    # Try the cache first
+    result = _sys_version_cache.get(sys_version, None)
+    if result is not None:
+        return result
+
+    # Parse it
+    if sys_version[:10] == 'IronPython':
+        # IronPython
+        name = 'IronPython'
+        match = _ironpython_sys_version_parser.match(sys_version)
+        if match is None:
+            raise ValueError(
+                'failed to parse IronPython sys.version: %s' %
+                repr(sys_version))
+        version, alt_version, compiler = match.groups()
+        branch = ''
+        revision = ''
+        buildno = ''
+        builddate = ''
+
+    elif sys.platform[:4] == 'java':
+        # Jython
+        name = 'Jython'
+        match = _jython_sys_version_parser.match(sys_version)
+        if match is None:
+            raise ValueError(
+                'failed to parse Jython sys.version: %s' %
+                repr(sys_version))
+        version, = match.groups()
+        branch = ''
+        revision = ''
+        compiler = sys.platform
+        buildno = ''
+        builddate = ''
+
+    elif "PyPy" in sys_version:
+        # PyPy
+        name = "PyPy"
+        match = _pypy_sys_version_parser.match(sys_version)
+        if match is None:
+            raise ValueError("failed to parse PyPy sys.version: %s" %
+                             repr(sys_version))
+        version, buildno, builddate, buildtime = match.groups()
+        compiler = ""
+
+    else:
+        # CPython
+        match = _sys_version_parser.match(sys_version)
+        if match is None:
+            raise ValueError(
+                'failed to parse CPython sys.version: %s' %
+                repr(sys_version))
+        version, buildno, builddate, buildtime, compiler = \
+              match.groups()
+        name = 'CPython'
+        builddate = builddate + ' ' + buildtime
+
+    if hasattr(sys, 'subversion'):
+        # sys.subversion was added in Python 2.5
+        _, branch, revision = sys.subversion
+    else:
+        branch = ''
+        revision = ''
+
+    # Add the patchlevel version if missing
+    l = string.split(version, '.')
+    if len(l) == 2:
+        l.append('0')
+        version = string.join(l, '.')
+
+    # Build and cache the result
+    result = (name, version, branch, revision, buildno, builddate, compiler)
+    _sys_version_cache[sys_version] = result
+    return result
+
+def python_implementation():
+
+    """ Returns a string identifying the Python implementation.
+
+        Currently, the following implementations are identified:
+          'CPython' (C implementation of Python),
+          'IronPython' (.NET implementation of Python),
+          'Jython' (Java implementation of Python),
+          'PyPy' (Python implementation of Python).
+
+    """
+    return _sys_version()[0]
+
+def python_version():
+
+    """ Returns the Python version as string 'major.minor.patchlevel'
+
+        Note that unlike the Python sys.version, the returned value
+        will always include the patchlevel (it defaults to 0).
+
+    """
+    return _sys_version()[1]
+
+def python_version_tuple():
+
+    """ Returns the Python version as tuple (major, minor, patchlevel)
+        of strings.
+
+        Note that unlike the Python sys.version, the returned value
+        will always include the patchlevel (it defaults to 0).
+
+    """
+    return tuple(string.split(_sys_version()[1], '.'))
+
+def python_branch():
+
+    """ Returns a string identifying the Python implementation
+        branch.
+
+        For CPython this is the Subversion branch from which the
+        Python binary was built.
+
+        If not available, an empty string is returned.
+
+    """
+
+    return _sys_version()[2]
+
+def python_revision():
+
+    """ Returns a string identifying the Python implementation
+        revision.
+
+        For CPython this is the Subversion revision from which the
+        Python binary was built.
+
+        If not available, an empty string is returned.
+
+    """
+    return _sys_version()[3]
+
+def python_build():
+
+    """ Returns a tuple (buildno, builddate) stating the Python
+        build number and date as strings.
+
+    """
+    return _sys_version()[4:6]
+
+def python_compiler():
+
+    """ Returns a string identifying the compiler used for compiling
+        Python.
+
+    """
+    return _sys_version()[6]
+
+### The Opus Magnum of platform strings :-)
+
+_platform_cache = {}
+
+def platform(aliased=0, terse=0):
+
+    """ Returns a single string identifying the underlying platform
+        with as much useful information as possible (but no more :).
+
+        The output is intended to be human readable rather than
+        machine parseable. It may look different on different
+        platforms and this is intended.
+
+        If "aliased" is true, the function will use aliases for
+        various platforms that report system names which differ from
+        their common names, e.g. SunOS will be reported as
+        Solaris. The system_alias() function is used to implement
+        this.
+
+        Setting terse to true causes the function to return only the
+        absolute minimum information needed to identify the platform.
+
+    """
+    result = _platform_cache.get((aliased, terse), None)
+    if result is not None:
+        return result
+
+    # Get uname information and then apply platform specific cosmetics
+    # to it...
+    system,node,release,version,machine,processor = uname()
+    if machine == processor:
+        processor = ''
+    if aliased:
+        system,release,version = system_alias(system,release,version)
+
+    if system == 'Windows':
+        # MS platforms
+        rel,vers,csd,ptype = win32_ver(version)
+        if terse:
+            platform = _platform(system,release)
+        else:
+            platform = _platform(system,release,version,csd)
+
+    elif system in ('Linux',):
+        # Linux based systems
+        distname,distversion,distid = dist('')
+        if distname and not terse:
+            platform = _platform(system,release,machine,processor,
+                                 'with',
+                                 distname,distversion,distid)
+        else:
+            # If the distribution name is unknown check for libc vs. glibc
+            libcname,libcversion = libc_ver(sys.executable)
+            platform = _platform(system,release,machine,processor,
+                                 'with',
+                                 libcname+libcversion)
+    elif system == 'Java':
+        # Java platforms
+        r,v,vminfo,(os_name,os_version,os_arch) = java_ver()
+        if terse or not os_name:
+            platform = _platform(system,release,version)
+        else:
+            platform = _platform(system,release,version,
+                                 'on',
+                                 os_name,os_version,os_arch)
+
+    elif system == 'MacOS':
+        # MacOS platforms
+        if terse:
+            platform = _platform(system,release)
+        else:
+            platform = _platform(system,release,machine)
+
+    else:
+        # Generic handler
+        if terse:
+            platform = _platform(system,release)
+        else:
+            bits,linkage = architecture(sys.executable)
+            platform = _platform(system,release,machine,processor,bits,linkage)
+
+    _platform_cache[(aliased, terse)] = platform
+    return platform
+
+### Command line interface
+
+if __name__ == '__main__':
+    # Default is to print the aliased verbose platform string
+    terse = ('terse' in sys.argv or '--terse' in sys.argv)
+    aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
+    print platform(aliased,terse)
+    sys.exit(0)
diff --git a/src/main/resources/PythonLibs/plistlib.py b/src/main/resources/PythonLibs/plistlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..51944eecb0f01c7bc27b6600e6f33a58272fd0b1
--- /dev/null
+++ b/src/main/resources/PythonLibs/plistlib.py
@@ -0,0 +1,474 @@
+r"""plistlib.py -- a tool to generate and parse MacOSX .plist files.
+
+The PropertyList (.plist) file format is a simple XML pickle supporting
+basic object types, like dictionaries, lists, numbers and strings.
+Usually the top level object is a dictionary.
+
+To write out a plist file, use the writePlist(rootObject, pathOrFile)
+function. 'rootObject' is the top level object, 'pathOrFile' is a
+filename or a (writable) file object.
+
+To parse a plist from a file, use the readPlist(pathOrFile) function,
+with a file name or a (readable) file object as the only argument. It
+returns the top level object (again, usually a dictionary).
+
+To work with plist data in strings, you can use readPlistFromString()
+and writePlistToString().
+
+Values can be strings, integers, floats, booleans, tuples, lists,
+dictionaries, Data or datetime.datetime objects. String values (including
+dictionary keys) may be unicode strings -- they will be written out as
+UTF-8.
+
+The <data> plist type is supported through the Data class. This is a
+thin wrapper around a Python string.
+
+Generate Plist example:
+
+    pl = dict(
+        aString="Doodah",
+        aList=["A", "B", 12, 32.1, [1, 2, 3]],
+        aFloat=0.1,
+        anInt=728,
+        aDict=dict(
+            anotherString="<hello & hi there!>",
+            aUnicodeValue=u'M\xe4ssig, Ma\xdf',
+            aTrueValue=True,
+            aFalseValue=False,
+        ),
+        someData=Data("<binary gunk>"),
+        someMoreData=Data("<lots of binary gunk>" * 10),
+        aDate=datetime.datetime.fromtimestamp(time.mktime(time.gmtime())),
+    )
+    # unicode keys are possible, but a little awkward to use:
+    pl[u'\xc5benraa'] = "That was a unicode key."
+    writePlist(pl, fileName)
+
+Parse Plist example:
+
+    pl = readPlist(pathOrFile)
+    print pl["aKey"]
+"""
+
+
+__all__ = [
+    "readPlist", "writePlist", "readPlistFromString", "writePlistToString",
+    "readPlistFromResource", "writePlistToResource",
+    "Plist", "Data", "Dict"
+]
+# Note: the Plist and Dict classes have been deprecated.
+
+import binascii
+import datetime
+from cStringIO import StringIO
+import re
+import warnings
+
+
+def readPlist(pathOrFile):
+    """Read a .plist file. 'pathOrFile' may either be a file name or a
+    (readable) file object. Return the unpacked root object (which
+    usually is a dictionary).
+    """
+    didOpen = 0
+    if isinstance(pathOrFile, (str, unicode)):
+        pathOrFile = open(pathOrFile)
+        didOpen = 1
+    p = PlistParser()
+    rootObject = p.parse(pathOrFile)
+    if didOpen:
+        pathOrFile.close()
+    return rootObject
+
+
+def writePlist(rootObject, pathOrFile):
+    """Write 'rootObject' to a .plist file. 'pathOrFile' may either be a
+    file name or a (writable) file object.
+    """
+    didOpen = 0
+    if isinstance(pathOrFile, (str, unicode)):
+        pathOrFile = open(pathOrFile, "w")
+        didOpen = 1
+    writer = PlistWriter(pathOrFile)
+    writer.writeln("<plist version=\"1.0\">")
+    writer.writeValue(rootObject)
+    writer.writeln("</plist>")
+    if didOpen:
+        pathOrFile.close()
+
+
+def readPlistFromString(data):
+    """Read a plist data from a string. Return the root object.
+    """
+    return readPlist(StringIO(data))
+
+
+def writePlistToString(rootObject):
+    """Return 'rootObject' as a plist-formatted string.
+    """
+    f = StringIO()
+    writePlist(rootObject, f)
+    return f.getvalue()
+
+
+def readPlistFromResource(path, restype='plst', resid=0):
+    """Read plst resource from the resource fork of path.
+    """
+    warnings.warnpy3k("In 3.x, readPlistFromResource is removed.",
+                      stacklevel=2)
+    from Carbon.File import FSRef, FSGetResourceForkName
+    from Carbon.Files import fsRdPerm
+    from Carbon import Res
+    fsRef = FSRef(path)
+    resNum = Res.FSOpenResourceFile(fsRef, FSGetResourceForkName(), fsRdPerm)
+    Res.UseResFile(resNum)
+    plistData = Res.Get1Resource(restype, resid).data
+    Res.CloseResFile(resNum)
+    return readPlistFromString(plistData)
+
+
+def writePlistToResource(rootObject, path, restype='plst', resid=0):
+    """Write 'rootObject' as a plst resource to the resource fork of path.
+    """
+    warnings.warnpy3k("In 3.x, writePlistToResource is removed.", stacklevel=2)
+    from Carbon.File import FSRef, FSGetResourceForkName
+    from Carbon.Files import fsRdWrPerm
+    from Carbon import Res
+    plistData = writePlistToString(rootObject)
+    fsRef = FSRef(path)
+    resNum = Res.FSOpenResourceFile(fsRef, FSGetResourceForkName(), fsRdWrPerm)
+    Res.UseResFile(resNum)
+    try:
+        Res.Get1Resource(restype, resid).RemoveResource()
+    except Res.Error:
+        pass
+    res = Res.Resource(plistData)
+    res.AddResource(restype, resid, '')
+    res.WriteResource()
+    Res.CloseResFile(resNum)
+
+
+class DumbXMLWriter:
+
+    def __init__(self, file, indentLevel=0, indent="\t"):
+        self.file = file
+        self.stack = []
+        self.indentLevel = indentLevel
+        self.indent = indent
+
+    def beginElement(self, element):
+        self.stack.append(element)
+        self.writeln("<%s>" % element)
+        self.indentLevel += 1
+
+    def endElement(self, element):
+        assert self.indentLevel > 0
+        assert self.stack.pop() == element
+        self.indentLevel -= 1
+        self.writeln("</%s>" % element)
+
+    def simpleElement(self, element, value=None):
+        if value is not None:
+            value = _escapeAndEncode(value)
+            self.writeln("<%s>%s</%s>" % (element, value, element))
+        else:
+            self.writeln("<%s/>" % element)
+
+    def writeln(self, line):
+        if line:
+            self.file.write(self.indentLevel * self.indent + line + "\n")
+        else:
+            self.file.write("\n")
+
+
+# Contents should conform to a subset of ISO 8601
+# (in particular, YYYY '-' MM '-' DD 'T' HH ':' MM ':' SS 'Z'.  Smaller units may be omitted with
+#  a loss of precision)
+_dateParser = re.compile(r"(?P<year>\d\d\d\d)(?:-(?P<month>\d\d)(?:-(?P<day>\d\d)(?:T(?P<hour>\d\d)(?::(?P<minute>\d\d)(?::(?P<second>\d\d))?)?)?)?)?Z")
+
+def _dateFromString(s):
+    order = ('year', 'month', 'day', 'hour', 'minute', 'second')
+    gd = _dateParser.match(s).groupdict()
+    lst = []
+    for key in order:
+        val = gd[key]
+        if val is None:
+            break
+        lst.append(int(val))
+    return datetime.datetime(*lst)
+
+def _dateToString(d):
+    return '%04d-%02d-%02dT%02d:%02d:%02dZ' % (
+        d.year, d.month, d.day,
+        d.hour, d.minute, d.second
+    )
+
+
+# Regex to find any control chars, except for \t \n and \r
+_controlCharPat = re.compile(
+    r"[\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f"
+    r"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]")
+
+def _escapeAndEncode(text):
+    m = _controlCharPat.search(text)
+    if m is not None:
+        raise ValueError("strings can't contains control characters; "
+                         "use plistlib.Data instead")
+    text = text.replace("\r\n", "\n")       # convert DOS line endings
+    text = text.replace("\r", "\n")         # convert Mac line endings
+    text = text.replace("&", "&amp;")       # escape '&'
+    text = text.replace("<", "&lt;")        # escape '<'
+    text = text.replace(">", "&gt;")        # escape '>'
+    return text.encode("utf-8")             # encode as UTF-8
+
+
+PLISTHEADER = """\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+"""
+
+class PlistWriter(DumbXMLWriter):
+
+    def __init__(self, file, indentLevel=0, indent="\t", writeHeader=1):
+        if writeHeader:
+            file.write(PLISTHEADER)
+        DumbXMLWriter.__init__(self, file, indentLevel, indent)
+
+    def writeValue(self, value):
+        if isinstance(value, (str, unicode)):
+            self.simpleElement("string", value)
+        elif isinstance(value, bool):
+            # must switch for bool before int, as bool is a
+            # subclass of int...
+            if value:
+                self.simpleElement("true")
+            else:
+                self.simpleElement("false")
+        elif isinstance(value, (int, long)):
+            self.simpleElement("integer", "%d" % value)
+        elif isinstance(value, float):
+            self.simpleElement("real", repr(value))
+        elif isinstance(value, dict):
+            self.writeDict(value)
+        elif isinstance(value, Data):
+            self.writeData(value)
+        elif isinstance(value, datetime.datetime):
+            self.simpleElement("date", _dateToString(value))
+        elif isinstance(value, (tuple, list)):
+            self.writeArray(value)
+        else:
+            raise TypeError("unsuported type: %s" % type(value))
+
+    def writeData(self, data):
+        self.beginElement("data")
+        self.indentLevel -= 1
+        maxlinelength = 76 - len(self.indent.replace("\t", " " * 8) *
+                                 self.indentLevel)
+        for line in data.asBase64(maxlinelength).split("\n"):
+            if line:
+                self.writeln(line)
+        self.indentLevel += 1
+        self.endElement("data")
+
+    def writeDict(self, d):
+        self.beginElement("dict")
+        items = d.items()
+        items.sort()
+        for key, value in items:
+            if not isinstance(key, (str, unicode)):
+                raise TypeError("keys must be strings")
+            self.simpleElement("key", key)
+            self.writeValue(value)
+        self.endElement("dict")
+
+    def writeArray(self, array):
+        self.beginElement("array")
+        for value in array:
+            self.writeValue(value)
+        self.endElement("array")
+
+
+class _InternalDict(dict):
+
+    # This class is needed while Dict is scheduled for deprecation:
+    # we only need to warn when a *user* instantiates Dict or when
+    # the "attribute notation for dict keys" is used.
+
+    def __getattr__(self, attr):
+        try:
+            value = self[attr]
+        except KeyError:
+            raise AttributeError, attr
+        from warnings import warn
+        warn("Attribute access from plist dicts is deprecated, use d[key] "
+             "notation instead", PendingDeprecationWarning, 2)
+        return value
+
+    def __setattr__(self, attr, value):
+        from warnings import warn
+        warn("Attribute access from plist dicts is deprecated, use d[key] "
+             "notation instead", PendingDeprecationWarning, 2)
+        self[attr] = value
+
+    def __delattr__(self, attr):
+        try:
+            del self[attr]
+        except KeyError:
+            raise AttributeError, attr
+        from warnings import warn
+        warn("Attribute access from plist dicts is deprecated, use d[key] "
+             "notation instead", PendingDeprecationWarning, 2)
+
+class Dict(_InternalDict):
+
+    def __init__(self, **kwargs):
+        from warnings import warn
+        warn("The plistlib.Dict class is deprecated, use builtin dict instead",
+             PendingDeprecationWarning, 2)
+        super(Dict, self).__init__(**kwargs)
+
+
+class Plist(_InternalDict):
+
+    """This class has been deprecated. Use readPlist() and writePlist()
+    functions instead, together with regular dict objects.
+    """
+
+    def __init__(self, **kwargs):
+        from warnings import warn
+        warn("The Plist class is deprecated, use the readPlist() and "
+             "writePlist() functions instead", PendingDeprecationWarning, 2)
+        super(Plist, self).__init__(**kwargs)
+
+    def fromFile(cls, pathOrFile):
+        """Deprecated. Use the readPlist() function instead."""
+        rootObject = readPlist(pathOrFile)
+        plist = cls()
+        plist.update(rootObject)
+        return plist
+    fromFile = classmethod(fromFile)
+
+    def write(self, pathOrFile):
+        """Deprecated. Use the writePlist() function instead."""
+        writePlist(self, pathOrFile)
+
+
+def _encodeBase64(s, maxlinelength=76):
+    # copied from base64.encodestring(), with added maxlinelength argument
+    maxbinsize = (maxlinelength//4)*3
+    pieces = []
+    for i in range(0, len(s), maxbinsize):
+        chunk = s[i : i + maxbinsize]
+        pieces.append(binascii.b2a_base64(chunk))
+    return "".join(pieces)
+
+class Data:
+
+    """Wrapper for binary data."""
+
+    def __init__(self, data):
+        self.data = data
+
+    def fromBase64(cls, data):
+        # base64.decodestring just calls binascii.a2b_base64;
+        # it seems overkill to use both base64 and binascii.
+        return cls(binascii.a2b_base64(data))
+    fromBase64 = classmethod(fromBase64)
+
+    def asBase64(self, maxlinelength=76):
+        return _encodeBase64(self.data, maxlinelength)
+
+    def __cmp__(self, other):
+        if isinstance(other, self.__class__):
+            return cmp(self.data, other.data)
+        elif isinstance(other, str):
+            return cmp(self.data, other)
+        else:
+            return cmp(id(self), id(other))
+
+    def __repr__(self):
+        return "%s(%s)" % (self.__class__.__name__, repr(self.data))
+
+
+class PlistParser:
+
+    def __init__(self):
+        self.stack = []
+        self.currentKey = None
+        self.root = None
+
+    def parse(self, fileobj):
+        from xml.parsers.expat import ParserCreate
+        parser = ParserCreate()
+        parser.StartElementHandler = self.handleBeginElement
+        parser.EndElementHandler = self.handleEndElement
+        parser.CharacterDataHandler = self.handleData
+        parser.ParseFile(fileobj)
+        return self.root
+
+    def handleBeginElement(self, element, attrs):
+        self.data = []
+        handler = getattr(self, "begin_" + element, None)
+        if handler is not None:
+            handler(attrs)
+
+    def handleEndElement(self, element):
+        handler = getattr(self, "end_" + element, None)
+        if handler is not None:
+            handler()
+
+    def handleData(self, data):
+        self.data.append(data)
+
+    def addObject(self, value):
+        if self.currentKey is not None:
+            self.stack[-1][self.currentKey] = value
+            self.currentKey = None
+        elif not self.stack:
+            # this is the root object
+            self.root = value
+        else:
+            self.stack[-1].append(value)
+
+    def getData(self):
+        data = "".join(self.data)
+        try:
+            data = data.encode("ascii")
+        except UnicodeError:
+            pass
+        self.data = []
+        return data
+
+    # element handlers
+
+    def begin_dict(self, attrs):
+        d = _InternalDict()
+        self.addObject(d)
+        self.stack.append(d)
+    def end_dict(self):
+        self.stack.pop()
+
+    def end_key(self):
+        self.currentKey = self.getData()
+
+    def begin_array(self, attrs):
+        a = []
+        self.addObject(a)
+        self.stack.append(a)
+    def end_array(self):
+        self.stack.pop()
+
+    def end_true(self):
+        self.addObject(True)
+    def end_false(self):
+        self.addObject(False)
+    def end_integer(self):
+        self.addObject(int(self.getData()))
+    def end_real(self):
+        self.addObject(float(self.getData()))
+    def end_string(self):
+        self.addObject(self.getData())
+    def end_data(self):
+        self.addObject(Data.fromBase64(self.getData()))
+    def end_date(self):
+        self.addObject(_dateFromString(self.getData()))
diff --git a/src/main/resources/PythonLibs/popen2.py b/src/main/resources/PythonLibs/popen2.py
new file mode 100644
index 0000000000000000000000000000000000000000..88dadafbb43c32e2f4062b014375615fe50d9a8d
--- /dev/null
+++ b/src/main/resources/PythonLibs/popen2.py
@@ -0,0 +1,190 @@
+"""Spawn a command with pipes to its stdin, stdout, and optionally stderr.
+
+The normal os.popen(cmd, mode) call spawns a shell command and provides a
+file interface to just the input or output of the process depending on
+whether mode is 'r' or 'w'.  This module provides the functions popen2(cmd)
+and popen3(cmd) which return two or three pipes to the spawned command.
+"""
+
+import os
+import subprocess
+import sys
+
+__all__ = ["popen2", "popen3", "popen4"]
+
+MAXFD = subprocess.MAXFD
+_active = subprocess._active
+_cleanup = subprocess._cleanup
+
+class Popen3:
+    """Class representing a child process.  Normally instances are created
+    by the factory functions popen2() and popen3()."""
+
+    sts = -1                    # Child not completed yet
+
+    def __init__(self, cmd, capturestderr=False, bufsize=-1):
+        """The parameter 'cmd' is the shell command to execute in a
+        sub-process.  On UNIX, 'cmd' may be a sequence, in which case arguments
+        will be passed directly to the program without shell intervention (as
+        with os.spawnv()).  If 'cmd' is a string it will be passed to the shell
+        (as with os.system()).   The 'capturestderr' flag, if true, specifies
+        that the object should capture standard error output of the child
+        process.  The default is false.  If the 'bufsize' parameter is
+        specified, it specifies the size of the I/O buffers to/from the child
+        process."""
+        stderr = subprocess.PIPE if capturestderr else None
+        PIPE = subprocess.PIPE
+        self._popen = subprocess.Popen(cmd, bufsize=bufsize,
+                                       shell=isinstance(cmd, basestring),
+                                       stdin=PIPE, stdout=PIPE, stderr=stderr)
+        self._setup(cmd)
+
+    def _setup(self, cmd):
+        """Setup the Popen attributes."""
+        self.cmd = cmd
+        self.pid = self._popen.pid
+        self.tochild = self._popen.stdin
+        self.fromchild = self._popen.stdout
+        self.childerr = self._popen.stderr
+
+    def __del__(self):
+        # XXX: Should let _popen __del__ on its own, but it's a new
+        # style class: http://bugs.jython.org/issue1057
+        if hasattr(self, '_popen'):
+            self._popen.__del__()
+
+    def poll(self, _deadstate=None):
+        """Return the exit status of the child process if it has finished,
+        or -1 if it hasn't finished yet."""
+        if self.sts < 0:
+            result = self._popen.poll(_deadstate)
+            if result is not None:
+                self.sts = result
+        return self.sts
+
+    def wait(self):
+        """Wait for and return the exit status of the child process."""
+        if self.sts < 0:
+            self.sts = self._popen.wait()
+        return self.sts
+
+
+class Popen4(Popen3):
+    childerr = None
+
+    def __init__(self, cmd, bufsize=-1):
+        PIPE = subprocess.PIPE
+        self._popen = subprocess.Popen(cmd, bufsize=bufsize,
+                                       shell=isinstance(cmd, basestring),
+                                       stdin=PIPE, stdout=PIPE,
+                                       stderr=subprocess.STDOUT)
+        self._setup(cmd)
+
+
+if sys.platform[:3] == "win" or sys.platform == "os2emx":
+    # Some things don't make sense on non-Unix platforms.
+    del Popen3, Popen4
+
+    def popen2(cmd, bufsize=-1, mode='t'):
+        """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
+        be a sequence, in which case arguments will be passed directly to the
+        program without shell intervention (as with os.spawnv()). If 'cmd' is a
+        string it will be passed to the shell (as with os.system()). If
+        'bufsize' is specified, it sets the buffer size for the I/O pipes. The
+        file objects (child_stdout, child_stdin) are returned."""
+        w, r = os.popen2(cmd, mode, bufsize)
+        return r, w
+
+    def popen3(cmd, bufsize=-1, mode='t'):
+        """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
+        be a sequence, in which case arguments will be passed directly to the
+        program without shell intervention (as with os.spawnv()). If 'cmd' is a
+        string it will be passed to the shell (as with os.system()). If
+        'bufsize' is specified, it sets the buffer size for the I/O pipes. The
+        file objects (child_stdout, child_stdin, child_stderr) are returned."""
+        w, r, e = os.popen3(cmd, mode, bufsize)
+        return r, w, e
+
+    def popen4(cmd, bufsize=-1, mode='t'):
+        """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
+        be a sequence, in which case arguments will be passed directly to the
+        program without shell intervention (as with os.spawnv()). If 'cmd' is a
+        string it will be passed to the shell (as with os.system()). If
+        'bufsize' is specified, it sets the buffer size for the I/O pipes. The
+        file objects (child_stdout_stderr, child_stdin) are returned."""
+        w, r = os.popen4(cmd, mode, bufsize)
+        return r, w
+else:
+    def popen2(cmd, bufsize=-1, mode='t'):
+        """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
+        be a sequence, in which case arguments will be passed directly to the
+        program without shell intervention (as with os.spawnv()). If 'cmd' is a
+        string it will be passed to the shell (as with os.system()). If
+        'bufsize' is specified, it sets the buffer size for the I/O pipes. The
+        file objects (child_stdout, child_stdin) are returned."""
+        inst = Popen3(cmd, False, bufsize)
+        return inst.fromchild, inst.tochild
+
+    def popen3(cmd, bufsize=-1, mode='t'):
+        """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
+        be a sequence, in which case arguments will be passed directly to the
+        program without shell intervention (as with os.spawnv()). If 'cmd' is a
+        string it will be passed to the shell (as with os.system()). If
+        'bufsize' is specified, it sets the buffer size for the I/O pipes. The
+        file objects (child_stdout, child_stdin, child_stderr) are returned."""
+        inst = Popen3(cmd, True, bufsize)
+        return inst.fromchild, inst.tochild, inst.childerr
+
+    def popen4(cmd, bufsize=-1, mode='t'):
+        """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
+        be a sequence, in which case arguments will be passed directly to the
+        program without shell intervention (as with os.spawnv()). If 'cmd' is a
+        string it will be passed to the shell (as with os.system()). If
+        'bufsize' is specified, it sets the buffer size for the I/O pipes. The
+        file objects (child_stdout_stderr, child_stdin) are returned."""
+        inst = Popen4(cmd, bufsize)
+        return inst.fromchild, inst.tochild
+
+    __all__.extend(["Popen3", "Popen4"])
+
+def _test():
+    # When the test runs, there shouldn't be any open pipes
+    _cleanup()
+    assert not _active, "Active pipes when test starts " + repr([c.cmd for c in _active])
+    cmd  = "cat"
+    teststr = "ab cd\n"
+    if os.name in ("nt", "java"):
+        cmd = "more"
+    # "more" doesn't act the same way across Windows flavors,
+    # sometimes adding an extra newline at the start or the
+    # end.  So we strip whitespace off both ends for comparison.
+    expected = teststr.strip()
+    print "testing popen2..."
+    r, w = popen2(cmd)
+    w.write(teststr)
+    w.close()
+    got = r.read()
+    if got.strip() != expected:
+        raise ValueError("wrote %r read %r" % (teststr, got))
+    print "testing popen3..."
+    try:
+        r, w, e = popen3([cmd])
+    except:
+        r, w, e = popen3(cmd)
+    w.write(teststr)
+    w.close()
+    got = r.read()
+    if got.strip() != expected:
+        raise ValueError("wrote %r read %r" % (teststr, got))
+    got = e.read()
+    if got:
+        raise ValueError("unexpected %r on stderr" % (got,))
+    for inst in _active[:]:
+        inst.wait()
+    _cleanup()
+    if _active:
+        raise ValueError("_active not empty")
+    print "All OK"
+
+if __name__ == '__main__':
+    _test()
diff --git a/src/main/resources/PythonLibs/poplib.py b/src/main/resources/PythonLibs/poplib.py
new file mode 100644
index 0000000000000000000000000000000000000000..e2b33ef10f499fd75ab1d709b1a3c9d7b4ca4437
--- /dev/null
+++ b/src/main/resources/PythonLibs/poplib.py
@@ -0,0 +1,417 @@
+"""A POP3 client class.
+
+Based on the J. Myers POP3 draft, Jan. 96
+"""
+
+# Author: David Ascher <david_ascher@brown.edu>
+#         [heavily stealing from nntplib.py]
+# Updated: Piers Lauder <piers@cs.su.oz.au> [Jul '97]
+# String method conversion and test jig improvements by ESR, February 2001.
+# Added the POP3_SSL class. Methods loosely based on IMAP_SSL. Hector Urtubia <urtubia@mrbook.org> Aug 2003
+
+# Example (see the test function at the end of this file)
+
+# Imports
+
+import re, socket
+
+__all__ = ["POP3","error_proto"]
+
+# Exception raised when an error or invalid response is received:
+
+class error_proto(Exception): pass
+
+# Standard Port
+POP3_PORT = 110
+
+# POP SSL PORT
+POP3_SSL_PORT = 995
+
+# Line terminators (we always output CRLF, but accept any of CRLF, LFCR, LF)
+CR = '\r'
+LF = '\n'
+CRLF = CR+LF
+
+
+class POP3:
+
+    """This class supports both the minimal and optional command sets.
+    Arguments can be strings or integers (where appropriate)
+    (e.g.: retr(1) and retr('1') both work equally well.
+
+    Minimal Command Set:
+            USER name               user(name)
+            PASS string             pass_(string)
+            STAT                    stat()
+            LIST [msg]              list(msg = None)
+            RETR msg                retr(msg)
+            DELE msg                dele(msg)
+            NOOP                    noop()
+            RSET                    rset()
+            QUIT                    quit()
+
+    Optional Commands (some servers support these):
+            RPOP name               rpop(name)
+            APOP name digest        apop(name, digest)
+            TOP msg n               top(msg, n)
+            UIDL [msg]              uidl(msg = None)
+
+    Raises one exception: 'error_proto'.
+
+    Instantiate with:
+            POP3(hostname, port=110)
+
+    NB:     the POP protocol locks the mailbox from user
+            authorization until QUIT, so be sure to get in, suck
+            the messages, and quit, each time you access the
+            mailbox.
+
+            POP is a line-based protocol, which means large mail
+            messages consume lots of python cycles reading them
+            line-by-line.
+
+            If it's available on your mail server, use IMAP4
+            instead, it doesn't suffer from the two problems
+            above.
+    """
+
+
+    def __init__(self, host, port=POP3_PORT,
+                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
+        self.host = host
+        self.port = port
+        self.sock = socket.create_connection((host, port), timeout)
+        self.file = self.sock.makefile('rb')
+        self._debugging = 0
+        self.welcome = self._getresp()
+
+
+    def _putline(self, line):
+        if self._debugging > 1: print '*put*', repr(line)
+        self.sock.sendall('%s%s' % (line, CRLF))
+
+
+    # Internal: send one command to the server (through _putline())
+
+    def _putcmd(self, line):
+        if self._debugging: print '*cmd*', repr(line)
+        self._putline(line)
+
+
+    # Internal: return one line from the server, stripping CRLF.
+    # This is where all the CPU time of this module is consumed.
+    # Raise error_proto('-ERR EOF') if the connection is closed.
+
+    def _getline(self):
+        line = self.file.readline()
+        if self._debugging > 1: print '*get*', repr(line)
+        if not line: raise error_proto('-ERR EOF')
+        octets = len(line)
+        # server can send any combination of CR & LF
+        # however, 'readline()' returns lines ending in LF
+        # so only possibilities are ...LF, ...CRLF, CR...LF
+        if line[-2:] == CRLF:
+            return line[:-2], octets
+        if line[0] == CR:
+            return line[1:-1], octets
+        return line[:-1], octets
+
+
+    # Internal: get a response from the server.
+    # Raise 'error_proto' if the response doesn't start with '+'.
+
+    def _getresp(self):
+        resp, o = self._getline()
+        if self._debugging > 1: print '*resp*', repr(resp)
+        c = resp[:1]
+        if c != '+':
+            raise error_proto(resp)
+        return resp
+
+
+    # Internal: get a response plus following text from the server.
+
+    def _getlongresp(self):
+        resp = self._getresp()
+        list = []; octets = 0
+        line, o = self._getline()
+        while line != '.':
+            if line[:2] == '..':
+                o = o-1
+                line = line[1:]
+            octets = octets + o
+            list.append(line)
+            line, o = self._getline()
+        return resp, list, octets
+
+
+    # Internal: send a command and get the response
+
+    def _shortcmd(self, line):
+        self._putcmd(line)
+        return self._getresp()
+
+
+    # Internal: send a command and get the response plus following text
+
+    def _longcmd(self, line):
+        self._putcmd(line)
+        return self._getlongresp()
+
+
+    # These can be useful:
+
+    def getwelcome(self):
+        return self.welcome
+
+
+    def set_debuglevel(self, level):
+        self._debugging = level
+
+
+    # Here are all the POP commands:
+
+    def user(self, user):
+        """Send user name, return response
+
+        (should indicate password required).
+        """
+        return self._shortcmd('USER %s' % user)
+
+
+    def pass_(self, pswd):
+        """Send password, return response
+
+        (response includes message count, mailbox size).
+
+        NB: mailbox is locked by server from here to 'quit()'
+        """
+        return self._shortcmd('PASS %s' % pswd)
+
+
+    def stat(self):
+        """Get mailbox status.
+
+        Result is tuple of 2 ints (message count, mailbox size)
+        """
+        retval = self._shortcmd('STAT')
+        rets = retval.split()
+        if self._debugging: print '*stat*', repr(rets)
+        numMessages = int(rets[1])
+        sizeMessages = int(rets[2])
+        return (numMessages, sizeMessages)
+
+
+    def list(self, which=None):
+        """Request listing, return result.
+
+        Result without a message number argument is in form
+        ['response', ['mesg_num octets', ...], octets].
+
+        Result when a message number argument is given is a
+        single response: the "scan listing" for that message.
+        """
+        if which is not None:
+            return self._shortcmd('LIST %s' % which)
+        return self._longcmd('LIST')
+
+
+    def retr(self, which):
+        """Retrieve whole message number 'which'.
+
+        Result is in form ['response', ['line', ...], octets].
+        """
+        return self._longcmd('RETR %s' % which)
+
+
+    def dele(self, which):
+        """Delete message number 'which'.
+
+        Result is 'response'.
+        """
+        return self._shortcmd('DELE %s' % which)
+
+
+    def noop(self):
+        """Does nothing.
+
+        One supposes the response indicates the server is alive.
+        """
+        return self._shortcmd('NOOP')
+
+
+    def rset(self):
+        """Unmark all messages marked for deletion."""
+        return self._shortcmd('RSET')
+
+
+    def quit(self):
+        """Signoff: commit changes on server, unlock mailbox, close connection."""
+        try:
+            resp = self._shortcmd('QUIT')
+        except error_proto, val:
+            resp = val
+        self.file.close()
+        self.sock.close()
+        del self.file, self.sock
+        return resp
+
+    #__del__ = quit
+
+
+    # optional commands:
+
+    def rpop(self, user):
+        """Not sure what this does."""
+        return self._shortcmd('RPOP %s' % user)
+
+
+    timestamp = re.compile(r'\+OK.*(<[^>]+>)')
+
+    def apop(self, user, secret):
+        """Authorisation
+
+        - only possible if server has supplied a timestamp in initial greeting.
+
+        Args:
+                user    - mailbox user;
+                secret  - secret shared between client and server.
+
+        NB: mailbox is locked by server from here to 'quit()'
+        """
+        m = self.timestamp.match(self.welcome)
+        if not m:
+            raise error_proto('-ERR APOP not supported by server')
+        import hashlib
+        digest = hashlib.md5(m.group(1)+secret).digest()
+        digest = ''.join(map(lambda x:'%02x'%ord(x), digest))
+        return self._shortcmd('APOP %s %s' % (user, digest))
+
+
+    def top(self, which, howmuch):
+        """Retrieve message header of message number 'which'
+        and first 'howmuch' lines of message body.
+
+        Result is in form ['response', ['line', ...], octets].
+        """
+        return self._longcmd('TOP %s %s' % (which, howmuch))
+
+
+    def uidl(self, which=None):
+        """Return message digest (unique id) list.
+
+        If 'which', result contains unique id for that message
+        in the form 'response mesgnum uid', otherwise result is
+        the list ['response', ['mesgnum uid', ...], octets]
+        """
+        if which is not None:
+            return self._shortcmd('UIDL %s' % which)
+        return self._longcmd('UIDL')
+
+try:
+    import ssl
+except ImportError:
+    pass
+else:
+
+    class POP3_SSL(POP3):
+        """POP3 client class over SSL connection
+
+        Instantiate with: POP3_SSL(hostname, port=995, keyfile=None, certfile=None)
+
+               hostname - the hostname of the pop3 over ssl server
+               port - port number
+               keyfile - PEM formatted file that countains your private key
+               certfile - PEM formatted certificate chain file
+
+            See the methods of the parent class POP3 for more documentation.
+        """
+
+        def __init__(self, host, port = POP3_SSL_PORT, keyfile = None, certfile = None):
+            self.host = host
+            self.port = port
+            self.keyfile = keyfile
+            self.certfile = certfile
+            self.buffer = ""
+            msg = "getaddrinfo returns an empty list"
+            self.sock = None
+            for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
+                af, socktype, proto, canonname, sa = res
+                try:
+                    self.sock = socket.socket(af, socktype, proto)
+                    self.sock.connect(sa)
+                except socket.error, msg:
+                    if self.sock:
+                        self.sock.close()
+                    self.sock = None
+                    continue
+                break
+            if not self.sock:
+                raise socket.error, msg
+            self.file = self.sock.makefile('rb')
+            self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile)
+            self._debugging = 0
+            self.welcome = self._getresp()
+
+        def _fillBuffer(self):
+            localbuf = self.sslobj.read()
+            if len(localbuf) == 0:
+                raise error_proto('-ERR EOF')
+            self.buffer += localbuf
+
+        def _getline(self):
+            line = ""
+            renewline = re.compile(r'.*?\n')
+            match = renewline.match(self.buffer)
+            while not match:
+                self._fillBuffer()
+                match = renewline.match(self.buffer)
+            line = match.group(0)
+            self.buffer = renewline.sub('' ,self.buffer, 1)
+            if self._debugging > 1: print '*get*', repr(line)
+
+            octets = len(line)
+            if line[-2:] == CRLF:
+                return line[:-2], octets
+            if line[0] == CR:
+                return line[1:-1], octets
+            return line[:-1], octets
+
+        def _putline(self, line):
+            if self._debugging > 1: print '*put*', repr(line)
+            line += CRLF
+            bytes = len(line)
+            while bytes > 0:
+                sent = self.sslobj.write(line)
+                if sent == bytes:
+                    break    # avoid copy
+                line = line[sent:]
+                bytes = bytes - sent
+
+        def quit(self):
+            """Signoff: commit changes on server, unlock mailbox, close connection."""
+            try:
+                resp = self._shortcmd('QUIT')
+            except error_proto, val:
+                resp = val
+            self.sock.close()
+            del self.sslobj, self.sock
+            return resp
+
+    __all__.append("POP3_SSL")
+
+if __name__ == "__main__":
+    import sys
+    a = POP3(sys.argv[1])
+    print a.getwelcome()
+    a.user(sys.argv[2])
+    a.pass_(sys.argv[3])
+    a.list()
+    (numMsgs, totalSize) = a.stat()
+    for i in range(1, numMsgs + 1):
+        (header, msg, octets) = a.retr(i)
+        print "Message %d:" % i
+        for line in msg:
+            print '   ' + line
+        print '-----------------------'
+    a.quit()
diff --git a/src/main/resources/PythonLibs/posixfile.py b/src/main/resources/PythonLibs/posixfile.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff2910779bc6511afe41066a600ce53f16545bae
--- /dev/null
+++ b/src/main/resources/PythonLibs/posixfile.py
@@ -0,0 +1,237 @@
+"""Extended file operations available in POSIX.
+
+f = posixfile.open(filename, [mode, [bufsize]])
+      will create a new posixfile object
+
+f = posixfile.fileopen(fileobject)
+      will create a posixfile object from a builtin file object
+
+f.file()
+      will return the original builtin file object
+
+f.dup()
+      will return a new file object based on a new filedescriptor
+
+f.dup2(fd)
+      will return a new file object based on the given filedescriptor
+
+f.flags(mode)
+      will turn on the associated flag (merge)
+      mode can contain the following characters:
+
+  (character representing a flag)
+      a       append only flag
+      c       close on exec flag
+      n       no delay flag
+      s       synchronization flag
+  (modifiers)
+      !       turn flags 'off' instead of default 'on'
+      =       copy flags 'as is' instead of default 'merge'
+      ?       return a string in which the characters represent the flags
+              that are set
+
+      note: - the '!' and '=' modifiers are mutually exclusive.
+            - the '?' modifier will return the status of the flags after they
+              have been changed by other characters in the mode string
+
+f.lock(mode [, len [, start [, whence]]])
+      will (un)lock a region
+      mode can contain the following characters:
+
+  (character representing type of lock)
+      u       unlock
+      r       read lock
+      w       write lock
+  (modifiers)
+      |       wait until the lock can be granted
+      ?       return the first lock conflicting with the requested lock
+              or 'None' if there is no conflict. The lock returned is in the
+              format (mode, len, start, whence, pid) where mode is a
+              character representing the type of lock ('r' or 'w')
+
+      note: - the '?' modifier prevents a region from being locked; it is
+              query only
+"""
+import warnings
+warnings.warn("The posixfile module is deprecated; "
+                "fcntl.lockf() provides better locking", DeprecationWarning, 2)
+
+class _posixfile_:
+    """File wrapper class that provides extra POSIX file routines."""
+
+    states = ['open', 'closed']
+
+    #
+    # Internal routines
+    #
+    def __repr__(self):
+        file = self._file_
+        return "<%s posixfile '%s', mode '%s' at %s>" % \
+                (self.states[file.closed], file.name, file.mode, \
+                 hex(id(self))[2:])
+
+    #
+    # Initialization routines
+    #
+    def open(self, name, mode='r', bufsize=-1):
+        import __builtin__
+        return self.fileopen(__builtin__.open(name, mode, bufsize))
+
+    def fileopen(self, file):
+        import types
+        if repr(type(file)) != "<type 'file'>":
+            raise TypeError, 'posixfile.fileopen() arg must be file object'
+        self._file_  = file
+        # Copy basic file methods
+        for maybemethod in dir(file):
+            if not maybemethod.startswith('_'):
+                attr = getattr(file, maybemethod)
+                if isinstance(attr, types.BuiltinMethodType):
+                    setattr(self, maybemethod, attr)
+        return self
+
+    #
+    # New methods
+    #
+    def file(self):
+        return self._file_
+
+    def dup(self):
+        import posix
+
+        if not hasattr(posix, 'fdopen'):
+            raise AttributeError, 'dup() method unavailable'
+
+        return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
+
+    def dup2(self, fd):
+        import posix
+
+        if not hasattr(posix, 'fdopen'):
+            raise AttributeError, 'dup() method unavailable'
+
+        posix.dup2(self._file_.fileno(), fd)
+        return posix.fdopen(fd, self._file_.mode)
+
+    def flags(self, *which):
+        import fcntl, os
+
+        if which:
+            if len(which) > 1:
+                raise TypeError, 'Too many arguments'
+            which = which[0]
+        else: which = '?'
+
+        l_flags = 0
+        if 'n' in which: l_flags = l_flags | os.O_NDELAY
+        if 'a' in which: l_flags = l_flags | os.O_APPEND
+        if 's' in which: l_flags = l_flags | os.O_SYNC
+
+        file = self._file_
+
+        if '=' not in which:
+            cur_fl = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
+            if '!' in which: l_flags = cur_fl & ~ l_flags
+            else: l_flags = cur_fl | l_flags
+
+        l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags)
+
+        if 'c' in which:
+            arg = ('!' not in which)    # 0 is don't, 1 is do close on exec
+            l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFD, arg)
+
+        if '?' in which:
+            which = ''                  # Return current flags
+            l_flags = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
+            if os.O_APPEND & l_flags: which = which + 'a'
+            if fcntl.fcntl(file.fileno(), fcntl.F_GETFD, 0) & 1:
+                which = which + 'c'
+            if os.O_NDELAY & l_flags: which = which + 'n'
+            if os.O_SYNC & l_flags: which = which + 's'
+            return which
+
+    def lock(self, how, *args):
+        import struct, fcntl
+
+        if 'w' in how: l_type = fcntl.F_WRLCK
+        elif 'r' in how: l_type = fcntl.F_RDLCK
+        elif 'u' in how: l_type = fcntl.F_UNLCK
+        else: raise TypeError, 'no type of lock specified'
+
+        if '|' in how: cmd = fcntl.F_SETLKW
+        elif '?' in how: cmd = fcntl.F_GETLK
+        else: cmd = fcntl.F_SETLK
+
+        l_whence = 0
+        l_start = 0
+        l_len = 0
+
+        if len(args) == 1:
+            l_len = args[0]
+        elif len(args) == 2:
+            l_len, l_start = args
+        elif len(args) == 3:
+            l_len, l_start, l_whence = args
+        elif len(args) > 3:
+            raise TypeError, 'too many arguments'
+
+        # Hack by davem@magnet.com to get locking to go on freebsd;
+        # additions for AIX by Vladimir.Marangozov@imag.fr
+        import sys, os
+        if sys.platform in ('netbsd1',
+                            'openbsd2',
+                            'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
+                            'freebsd6', 'freebsd7', 'freebsd8',
+                            'bsdos2', 'bsdos3', 'bsdos4'):
+            flock = struct.pack('lxxxxlxxxxlhh', \
+                  l_start, l_len, os.getpid(), l_type, l_whence)
+        elif sys.platform in ('aix3', 'aix4'):
+            flock = struct.pack('hhlllii', \
+                  l_type, l_whence, l_start, l_len, 0, 0, 0)
+        else:
+            flock = struct.pack('hhllhh', \
+                  l_type, l_whence, l_start, l_len, 0, 0)
+
+        flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
+
+        if '?' in how:
+            if sys.platform in ('netbsd1',
+                                'openbsd2',
+                                'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
+                                'bsdos2', 'bsdos3', 'bsdos4'):
+                l_start, l_len, l_pid, l_type, l_whence = \
+                    struct.unpack('lxxxxlxxxxlhh', flock)
+            elif sys.platform in ('aix3', 'aix4'):
+                l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
+                    struct.unpack('hhlllii', flock)
+            elif sys.platform == "linux2":
+                l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
+                    struct.unpack('hhllhh', flock)
+            else:
+                l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
+                    struct.unpack('hhllhh', flock)
+
+            if l_type != fcntl.F_UNLCK:
+                if l_type == fcntl.F_RDLCK:
+                    return 'r', l_len, l_start, l_whence, l_pid
+                else:
+                    return 'w', l_len, l_start, l_whence, l_pid
+
+def open(name, mode='r', bufsize=-1):
+    """Public routine to open a file as a posixfile object."""
+    return _posixfile_().open(name, mode, bufsize)
+
+def fileopen(file):
+    """Public routine to get a posixfile object from a Python file object."""
+    return _posixfile_().fileopen(file)
+
+#
+# Constants
+#
+SEEK_SET = 0
+SEEK_CUR = 1
+SEEK_END = 2
+
+#
+# End of posixfile.py
+#
diff --git a/src/main/resources/PythonLibs/posixpath.py b/src/main/resources/PythonLibs/posixpath.py
new file mode 100644
index 0000000000000000000000000000000000000000..f6c0edda71911e53c5de10054829e6d80481e819
--- /dev/null
+++ b/src/main/resources/PythonLibs/posixpath.py
@@ -0,0 +1,513 @@
+"""Common operations on Posix pathnames.
+
+Instead of importing this module directly, import os and refer to
+this module as os.path.  The "os.path" name is an alias for this
+module on Posix systems; on other systems (e.g. Mac, Windows),
+os.path provides the same operations in a manner specific to that
+platform, and is an alias to another module (e.g. macpath, ntpath).
+
+Some of this can actually be useful on non-Posix systems too, e.g.
+for manipulation of the pathname component of URLs.
+"""
+
+import os
+import stat
+
+__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
+           "basename","dirname","commonprefix","getsize","getmtime",
+           "getatime","getctime","islink","exists","lexists","isdir","isfile",
+           "walk","expanduser","expandvars","normpath","abspath",
+           "samefile",
+           "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
+           "devnull","realpath","supports_unicode_filenames", "relpath"]
+
+# strings representing various path-related bits and pieces
+curdir = '.'
+pardir = '..'
+extsep = '.'
+sep = '/'
+pathsep = ':'
+defpath = ':/bin:/usr/bin'
+altsep = None
+devnull = '/dev/null'
+
+# Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
+# On MS-DOS this may also turn slashes into backslashes; however, other
+# normalizations (such as optimizing '../' away) are not allowed
+# (another function should be defined to do that).
+
+def normcase(s):
+    """Normalize case of pathname.  Has no effect under Posix"""
+    return s
+
+
+# Return whether a path is absolute.
+# Trivial in Posix, harder on the Mac or MS-DOS.
+
+def isabs(s):
+    """Test whether a path is absolute"""
+    return s.startswith('/')
+
+
+# Join pathnames.
+# Ignore the previous parts if a part is absolute.
+# Insert a '/' unless the first part is empty or already ends in '/'.
+
+def join(a, *p):
+    """Join two or more pathname components, inserting '/' as needed"""
+    path = a
+    for b in p:
+        if b.startswith('/'):
+            path = b
+        elif path == '' or path.endswith('/'):
+            path +=  b
+        else:
+            path += '/' + b
+    return path
+
+
+# Split a path in head (everything up to the last '/') and tail (the
+# rest).  If the path ends in '/', tail will be empty.  If there is no
+# '/' in the path, head  will be empty.
+# Trailing '/'es are stripped from head unless it is the root.
+
+def split(p):
+    """Split a pathname.  Returns tuple "(head, tail)" where "tail" is
+    everything after the final slash.  Either part may be empty."""
+    i = p.rfind('/') + 1
+    head, tail = p[:i], p[i:]
+    if head and head != '/'*len(head):
+        head = head.rstrip('/')
+    return head, tail
+
+
+# Split a path in root and extension.
+# The extension is everything starting at the last dot in the last
+# pathname component; the root is everything before that.
+# It is always true that root + ext == p.
+
+def splitext(p):
+    """Split the extension from a pathname.  Extension is everything from the
+    last dot to the end.  Returns "(root, ext)", either part may be empty."""
+    i = p.rfind('.')
+    if i<=p.rfind('/'):
+        return p, ''
+    else:
+        return p[:i], p[i:]
+
+
+# Split a pathname into a drive specification and the rest of the
+# path.  Useful on DOS/Windows/NT; on Unix, the drive is always empty.
+
+def splitdrive(p):
+    """Split a pathname into drive and path. On Posix, drive is always
+    empty."""
+    return '', p
+
+
+# Return the tail (basename) part of a path.
+
+def basename(p):
+    """Returns the final component of a pathname"""
+    return split(p)[1]
+
+
+# Return the head (dirname) part of a path.
+
+def dirname(p):
+    """Returns the directory component of a pathname"""
+    return split(p)[0]
+
+
+# Return the longest prefix of all list elements.
+
+def commonprefix(m):
+    "Given a list of pathnames, returns the longest common leading component"
+    if not m: return ''
+    s1 = min(m)
+    s2 = max(m)
+    n = min(len(s1), len(s2))
+    for i in xrange(n):
+        if s1[i] != s2[i]:
+            return s1[:i]
+    return s1[:n]
+
+# Get size, mtime, atime of files.
+
+def getsize(filename):
+    """Return the size of a file, reported by os.stat()."""
+    return os.stat(filename).st_size
+
+def getmtime(filename):
+    """Return the last modification time of a file, reported by os.stat()."""
+    return os.stat(filename).st_mtime
+
+def getatime(filename):
+    """Return the last access time of a file, reported by os.stat()."""
+    return os.stat(filename).st_atime
+
+def getctime(filename):
+    """Return the metadata change time of a file, reported by os.stat()."""
+    return os.stat(filename).st_ctime
+
+# Is a path a symbolic link?
+# This will always return false on systems where os.lstat doesn't exist.
+
+def islink(path):
+    """Test whether a path is a symbolic link"""
+    try:
+        st = os.lstat(path)
+    except (os.error, AttributeError):
+        return False
+    return stat.S_ISLNK(st.st_mode)
+
+
+# Does a path exist?
+# This is false for dangling symbolic links.
+
+def exists(path):
+    """Test whether a path exists.  Returns False for broken symbolic links"""
+    try:
+        st = os.stat(path)
+    except os.error:
+        return False
+    return True
+
+
+# Being true for dangling symbolic links is also useful.
+
+def lexists(path):
+    """Test whether a path exists.  Returns True for broken symbolic links"""
+    try:
+        st = os.lstat(path)
+    except os.error:
+        return False
+    return True
+
+
+# Is a path a directory?
+# This follows symbolic links, so both islink() and isdir() can be true
+# for the same path.
+
+def isdir(path):
+    """Test whether a path is a directory"""
+    try:
+        st = os.stat(path)
+    except os.error:
+        return False
+    return stat.S_ISDIR(st.st_mode)
+
+
+# Is a path a regular file?
+# This follows symbolic links, so both islink() and isfile() can be true
+# for the same path.
+
+def isfile(path):
+    """Test whether a path is a regular file"""
+    try:
+        st = os.stat(path)
+    except os.error:
+        return False
+    return stat.S_ISREG(st.st_mode)
+
+
+# Are two filenames really pointing to the same file?
+
+if not os._native_posix:
+    import java.io.File
+    import java.io.IOException
+    from org.python.core.Py import newString
+
+    def samefile(f1, f2):
+        """Test whether two pathnames reference the same actual file"""
+        canon1 = newString(java.io.File(_ensure_str(f1)).getCanonicalPath())
+        canon2 = newString(java.io.File(_ensure_str(f2)).getCanonicalPath())
+        return canon1 == canon2
+else:
+    def samefile(f1, f2):
+        """Test whether two pathnames reference the same actual file"""
+        s1 = os.stat(f1)
+        s2 = os.stat(f2)
+        return samestat(s1, s2)
+
+
+# XXX: Jython currently lacks fstat
+if hasattr(os, 'fstat'):
+    # Are two open files really referencing the same file?
+    # (Not necessarily the same file descriptor!)
+
+    def sameopenfile(fp1, fp2):
+        """Test whether two open file objects reference the same file"""
+        s1 = os.fstat(fp1)
+        s2 = os.fstat(fp2)
+        return samestat(s1, s2)
+
+    __all__.append("sameopenfile")
+
+
+# XXX: Pure Java stat lacks st_ino/st_dev
+if os._native_posix:
+    # Are two stat buffers (obtained from stat, fstat or lstat)
+    # describing the same file?
+
+    def samestat(s1, s2):
+        """Test whether two stat buffers reference the same file"""
+        return s1.st_ino == s2.st_ino and \
+               s1.st_dev == s2.st_dev
+
+
+    # Is a path a mount point?
+    # (Does this work for all UNIXes?  Is it even guaranteed to work by Posix?)
+
+    def ismount(path):
+        """Test whether a path is a mount point"""
+        try:
+            s1 = os.lstat(path)
+            s2 = os.lstat(join(path, '..'))
+        except os.error:
+            return False # It doesn't exist -- so not a mount point :-)
+        dev1 = s1.st_dev
+        dev2 = s2.st_dev
+        if dev1 != dev2:
+            return True     # path/.. on a different device as path
+        ino1 = s1.st_ino
+        ino2 = s2.st_ino
+        if ino1 == ino2:
+            return True     # path/.. is the same i-node as path
+        return False
+
+    __all__.extend(["samestat", "ismount"])
+
+
+# Directory tree walk.
+# For each directory under top (including top itself, but excluding
+# '.' and '..'), func(arg, dirname, filenames) is called, where
+# dirname is the name of the directory and filenames is the list
+# of files (and subdirectories etc.) in the directory.
+# The func may modify the filenames list, to implement a filter,
+# or to impose a different order of visiting.
+
+def walk(top, func, arg):
+    """Directory tree walk with callback function.
+
+    For each directory in the directory tree rooted at top (including top
+    itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
+    dirname is the name of the directory, and fnames a list of the names of
+    the files and subdirectories in dirname (excluding '.' and '..').  func
+    may modify the fnames list in-place (e.g. via del or slice assignment),
+    and walk will only recurse into the subdirectories whose names remain in
+    fnames; this can be used to implement a filter, or to impose a specific
+    order of visiting.  No semantics are defined for, or required of, arg,
+    beyond that arg is always passed to func.  It can be used, e.g., to pass
+    a filename pattern, or a mutable object designed to accumulate
+    statistics.  Passing None for arg is common."""
+
+    try:
+        names = os.listdir(top)
+    except os.error:
+        return
+    func(arg, top, names)
+    for name in names:
+        name = join(top, name)
+        try:
+            st = os.lstat(name)
+        except os.error:
+            continue
+        if stat.S_ISDIR(st.st_mode):
+            walk(name, func, arg)
+
+
+# Expand paths beginning with '~' or '~user'.
+# '~' means $HOME; '~user' means that user's home directory.
+# If the path doesn't begin with '~', or if the user or $HOME is unknown,
+# the path is returned unchanged (leaving error reporting to whatever
+# function is called with the expanded path as argument).
+# See also module 'glob' for expansion of *, ? and [...] in pathnames.
+# (A function should also be defined to do full *sh-style environment
+# variable expansion.)
+
+def expanduser(path):
+    """Expand ~ and ~user constructions.  If user or $HOME is unknown,
+    do nothing."""
+    if not path.startswith('~'):
+        return path
+    i = path.find('/', 1)
+    if i < 0:
+        i = len(path)
+    if i == 1:
+        if 'HOME' not in os.environ:
+            return path
+        else:
+            userhome = os.environ['HOME']
+    else:
+        # XXX: Jython lacks the pwd module: '~user' isn't supported
+        return path
+    userhome = userhome.rstrip('/')
+    return userhome + path[i:]
+
+
+# Expand paths containing shell variable substitutions.
+# This expands the forms $variable and ${variable} only.
+# Non-existent variables are left unchanged.
+
+_varprog = None
+
+def expandvars(path):
+    """Expand shell variables of form $var and ${var}.  Unknown variables
+    are left unchanged."""
+    global _varprog
+    if '$' not in path:
+        return path
+    if not _varprog:
+        import re
+        _varprog = re.compile(r'\$(\w+|\{[^}]*\})')
+    i = 0
+    while True:
+        m = _varprog.search(path, i)
+        if not m:
+            break
+        i, j = m.span(0)
+        name = m.group(1)
+        if name.startswith('{') and name.endswith('}'):
+            name = name[1:-1]
+        if name in os.environ:
+            tail = path[j:]
+            path = path[:i] + os.environ[name]
+            i = len(path)
+            path += tail
+        else:
+            i = j
+    return path
+
+
+# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
+# It should be understood that this may change the meaning of the path
+# if it contains symbolic links!
+
+def normpath(path):
+    """Normalize path, eliminating double slashes, etc."""
+    if path == '':
+        return '.'
+    initial_slashes = path.startswith('/')
+    # POSIX allows one or two initial slashes, but treats three or more
+    # as single slash.
+    if (initial_slashes and
+        path.startswith('//') and not path.startswith('///')):
+        initial_slashes = 2
+    comps = path.split('/')
+    new_comps = []
+    for comp in comps:
+        if comp in ('', '.'):
+            continue
+        if (comp != '..' or (not initial_slashes and not new_comps) or
+             (new_comps and new_comps[-1] == '..')):
+            new_comps.append(comp)
+        elif new_comps:
+            new_comps.pop()
+    comps = new_comps
+    path = '/'.join(comps)
+    if initial_slashes:
+        path = '/'*initial_slashes + path
+    return path or '.'
+
+
+def abspath(path):
+    """Return an absolute path."""
+    if not isabs(path):
+        path = join(os.getcwd(), path)
+    return normpath(path)
+
+
+# Return a canonical path (i.e. the absolute location of a file on the
+# filesystem).
+
+def realpath(filename):
+    """Return the canonical path of the specified filename, eliminating any
+symbolic links encountered in the path."""
+    if isabs(filename):
+        bits = ['/'] + filename.split('/')[1:]
+    else:
+        bits = [''] + filename.split('/')
+
+    for i in range(2, len(bits)+1):
+        component = join(*bits[0:i])
+        # Resolve symbolic links.
+        if islink(component):
+            resolved = _resolve_link(component)
+            if resolved is None:
+                # Infinite loop -- return original component + rest of the path
+                return abspath(join(*([component] + bits[i:])))
+            else:
+                newpath = join(*([resolved] + bits[i:]))
+                return realpath(newpath)
+
+    return abspath(filename)
+
+
+if not os._native_posix:
+    def _resolve_link(path):
+        """Internal helper function.  Takes a path and follows symlinks
+        until we either arrive at something that isn't a symlink, or
+        encounter a path we've seen before (meaning that there's a loop).
+        """
+        try:
+            return newString(java.io.File(abspath(path)).getCanonicalPath())
+        except java.io.IOException:
+            return None
+else:
+    def _resolve_link(path):
+        """Internal helper function.  Takes a path and follows symlinks
+        until we either arrive at something that isn't a symlink, or
+        encounter a path we've seen before (meaning that there's a loop).
+        """
+        paths_seen = []
+        while islink(path):
+            if path in paths_seen:
+                # Already seen this path, so we must have a symlink loop
+                return None
+            paths_seen.append(path)
+            # Resolve where the link points to
+            resolved = os.readlink(path)
+            if not isabs(resolved):
+                dir = dirname(path)
+                path = normpath(join(dir, resolved))
+            else:
+                path = normpath(resolved)
+        return path
+
+def relpath(path, start=curdir):
+    """Return a relative version of a path"""
+
+    if not path:
+        raise ValueError("no path specified")
+
+    start_list = [x for x in abspath(start).split(sep) if x]
+    path_list = [x for x in abspath(path).split(sep) if x]
+
+    # Work out how much of the filepath is shared by start and path.
+    i = len(commonprefix([start_list, path_list]))
+
+    rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
+    if not rel_list:
+        return curdir
+    return join(*rel_list)
+def _ensure_str(obj):
+    """Ensure obj is a string, otherwise raise a TypeError"""
+    if isinstance(obj, basestring):
+        return obj
+    raise TypeError('coercing to Unicode: need string or buffer, %s found' % \
+                        _type_name(obj))
+
+
+def _type_name(obj):
+    """Determine the appropriate type name of obj for display"""
+    TPFLAGS_HEAPTYPE = 1 << 9
+    type_name = ''
+    obj_type = type(obj)
+    is_heap = obj_type.__flags__ & TPFLAGS_HEAPTYPE == TPFLAGS_HEAPTYPE
+    if not is_heap and obj_type.__module__ != '__builtin__':
+        type_name = '%s.' % obj_type.__module__
+    type_name += obj_type.__name__
+    return type_name
+
+supports_unicode_filenames = False
diff --git a/src/main/resources/PythonLibs/pprint.py b/src/main/resources/PythonLibs/pprint.py
new file mode 100644
index 0000000000000000000000000000000000000000..910283e60913e3c209d0d9d4ed799796155bad31
--- /dev/null
+++ b/src/main/resources/PythonLibs/pprint.py
@@ -0,0 +1,350 @@
+#  Author:      Fred L. Drake, Jr.
+#               fdrake@acm.org
+#
+#  This is a simple little module I wrote to make life easier.  I didn't
+#  see anything quite like it in the library, though I may have overlooked
+#  something.  I wrote this when I was trying to read some heavily nested
+#  tuples with fairly non-descriptive content.  This is modeled very much
+#  after Lisp/Scheme - style pretty-printing of lists.  If you find it
+#  useful, thank small children who sleep at night.
+
+"""Support to pretty-print lists, tuples, & dictionaries recursively.
+
+Very simple, but useful, especially in debugging data structures.
+
+Classes
+-------
+
+PrettyPrinter()
+    Handle pretty-printing operations onto a stream using a configured
+    set of formatting parameters.
+
+Functions
+---------
+
+pformat()
+    Format a Python object into a pretty-printed representation.
+
+pprint()
+    Pretty-print a Python object to a stream [default is sys.stdout].
+
+saferepr()
+    Generate a 'standard' repr()-like value, but protect against recursive
+    data structures.
+
+"""
+
+import sys as _sys
+import warnings
+
+from cStringIO import StringIO as _StringIO
+
+__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
+           "PrettyPrinter"]
+
+# cache these for faster access:
+_commajoin = ", ".join
+_id = id
+_len = len
+_type = type
+
+
+def pprint(object, stream=None, indent=1, width=80, depth=None):
+    """Pretty-print a Python object to a stream [default is sys.stdout]."""
+    printer = PrettyPrinter(
+        stream=stream, indent=indent, width=width, depth=depth)
+    printer.pprint(object)
+
+def pformat(object, indent=1, width=80, depth=None):
+    """Format a Python object into a pretty-printed representation."""
+    return PrettyPrinter(indent=indent, width=width, depth=depth).pformat(object)
+
+def saferepr(object):
+    """Version of repr() which can handle recursive data structures."""
+    return _safe_repr(object, {}, None, 0)[0]
+
+def isreadable(object):
+    """Determine if saferepr(object) is readable by eval()."""
+    return _safe_repr(object, {}, None, 0)[1]
+
+def isrecursive(object):
+    """Determine if object requires a recursive representation."""
+    return _safe_repr(object, {}, None, 0)[2]
+
+def _sorted(iterable):
+    with warnings.catch_warnings():
+        if _sys.py3kwarning:
+            warnings.filterwarnings("ignore", "comparing unequal types "
+                                    "not supported", DeprecationWarning)
+        return sorted(iterable)
+
+class PrettyPrinter:
+    def __init__(self, indent=1, width=80, depth=None, stream=None):
+        """Handle pretty printing operations onto a stream using a set of
+        configured parameters.
+
+        indent
+            Number of spaces to indent for each level of nesting.
+
+        width
+            Attempted maximum number of columns in the output.
+
+        depth
+            The maximum depth to print out nested structures.
+
+        stream
+            The desired output stream.  If omitted (or false), the standard
+            output stream available at construction will be used.
+
+        """
+        indent = int(indent)
+        width = int(width)
+        assert indent >= 0, "indent must be >= 0"
+        assert depth is None or depth > 0, "depth must be > 0"
+        assert width, "width must be != 0"
+        self._depth = depth
+        self._indent_per_level = indent
+        self._width = width
+        if stream is not None:
+            self._stream = stream
+        else:
+            self._stream = _sys.stdout
+
+    def pprint(self, object):
+        self._format(object, self._stream, 0, 0, {}, 0)
+        self._stream.write("\n")
+
+    def pformat(self, object):
+        sio = _StringIO()
+        self._format(object, sio, 0, 0, {}, 0)
+        return sio.getvalue()
+
+    def isrecursive(self, object):
+        return self.format(object, {}, 0, 0)[2]
+
+    def isreadable(self, object):
+        s, readable, recursive = self.format(object, {}, 0, 0)
+        return readable and not recursive
+
+    def _format(self, object, stream, indent, allowance, context, level):
+        level = level + 1
+        objid = _id(object)
+        if objid in context:
+            stream.write(_recursion(object))
+            self._recursive = True
+            self._readable = False
+            return
+        rep = self._repr(object, context, level - 1)
+        typ = _type(object)
+        sepLines = _len(rep) > (self._width - 1 - indent - allowance)
+        write = stream.write
+
+        if self._depth and level > self._depth:
+            write(rep)
+            return
+
+        r = getattr(typ, "__repr__", None)
+        if issubclass(typ, dict) and r is dict.__repr__:
+            write('{')
+            if self._indent_per_level > 1:
+                write((self._indent_per_level - 1) * ' ')
+            length = _len(object)
+            if length:
+                context[objid] = 1
+                indent = indent + self._indent_per_level
+                items = _sorted(object.items())
+                key, ent = items[0]
+                rep = self._repr(key, context, level)
+                write(rep)
+                write(': ')
+                self._format(ent, stream, indent + _len(rep) + 2,
+                              allowance + 1, context, level)
+                if length > 1:
+                    for key, ent in items[1:]:
+                        rep = self._repr(key, context, level)
+                        if sepLines:
+                            write(',\n%s%s: ' % (' '*indent, rep))
+                        else:
+                            write(', %s: ' % rep)
+                        self._format(ent, stream, indent + _len(rep) + 2,
+                                      allowance + 1, context, level)
+                indent = indent - self._indent_per_level
+                del context[objid]
+            write('}')
+            return
+
+        if ((issubclass(typ, list) and r is list.__repr__) or
+            (issubclass(typ, tuple) and r is tuple.__repr__) or
+            (issubclass(typ, set) and r is set.__repr__) or
+            (issubclass(typ, frozenset) and r is frozenset.__repr__)
+           ):
+            length = _len(object)
+            if issubclass(typ, list):
+                write('[')
+                endchar = ']'
+            elif issubclass(typ, set):
+                if not length:
+                    write('set()')
+                    return
+                write('set([')
+                endchar = '])'
+                object = _sorted(object)
+                indent += 4
+            elif issubclass(typ, frozenset):
+                if not length:
+                    write('frozenset()')
+                    return
+                write('frozenset([')
+                endchar = '])'
+                object = _sorted(object)
+                indent += 10
+            else:
+                write('(')
+                endchar = ')'
+            if self._indent_per_level > 1 and sepLines:
+                write((self._indent_per_level - 1) * ' ')
+            if length:
+                context[objid] = 1
+                indent = indent + self._indent_per_level
+                self._format(object[0], stream, indent, allowance + 1,
+                             context, level)
+                if length > 1:
+                    for ent in object[1:]:
+                        if sepLines:
+                            write(',\n' + ' '*indent)
+                        else:
+                            write(', ')
+                        self._format(ent, stream, indent,
+                                      allowance + 1, context, level)
+                indent = indent - self._indent_per_level
+                del context[objid]
+            if issubclass(typ, tuple) and length == 1:
+                write(',')
+            write(endchar)
+            return
+
+        write(rep)
+
+    def _repr(self, object, context, level):
+        repr, readable, recursive = self.format(object, context.copy(),
+                                                self._depth, level)
+        if not readable:
+            self._readable = False
+        if recursive:
+            self._recursive = True
+        return repr
+
+    def format(self, object, context, maxlevels, level):
+        """Format object for a specific context, returning a string
+        and flags indicating whether the representation is 'readable'
+        and whether the object represents a recursive construct.
+        """
+        return _safe_repr(object, context, maxlevels, level)
+
+
+# Return triple (repr_string, isreadable, isrecursive).
+
+def _safe_repr(object, context, maxlevels, level):
+    typ = _type(object)
+    if typ is str:
+        if 'locale' not in _sys.modules:
+            return repr(object), True, False
+        if "'" in object and '"' not in object:
+            closure = '"'
+            quotes = {'"': '\\"'}
+        else:
+            closure = "'"
+            quotes = {"'": "\\'"}
+        qget = quotes.get
+        sio = _StringIO()
+        write = sio.write
+        for char in object:
+            if char.isalpha():
+                write(char)
+            else:
+                write(qget(char, repr(char)[1:-1]))
+        return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False
+
+    r = getattr(typ, "__repr__", None)
+    if issubclass(typ, dict) and r is dict.__repr__:
+        if not object:
+            return "{}", True, False
+        objid = _id(object)
+        if maxlevels and level >= maxlevels:
+            return "{...}", False, objid in context
+        if objid in context:
+            return _recursion(object), False, True
+        context[objid] = 1
+        readable = True
+        recursive = False
+        components = []
+        append = components.append
+        level += 1
+        saferepr = _safe_repr
+        for k, v in _sorted(object.items()):
+            krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
+            vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
+            append("%s: %s" % (krepr, vrepr))
+            readable = readable and kreadable and vreadable
+            if krecur or vrecur:
+                recursive = True
+        del context[objid]
+        return "{%s}" % _commajoin(components), readable, recursive
+
+    if (issubclass(typ, list) and r is list.__repr__) or \
+       (issubclass(typ, tuple) and r is tuple.__repr__):
+        if issubclass(typ, list):
+            if not object:
+                return "[]", True, False
+            format = "[%s]"
+        elif _len(object) == 1:
+            format = "(%s,)"
+        else:
+            if not object:
+                return "()", True, False
+            format = "(%s)"
+        objid = _id(object)
+        if maxlevels and level >= maxlevels:
+            return format % "...", False, objid in context
+        if objid in context:
+            return _recursion(object), False, True
+        context[objid] = 1
+        readable = True
+        recursive = False
+        components = []
+        append = components.append
+        level += 1
+        for o in object:
+            orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
+            append(orepr)
+            if not oreadable:
+                readable = False
+            if orecur:
+                recursive = True
+        del context[objid]
+        return format % _commajoin(components), readable, recursive
+
+    rep = repr(object)
+    return rep, (rep and not rep.startswith('<')), False
+
+
+def _recursion(object):
+    return ("<Recursion on %s with id=%s>"
+            % (_type(object).__name__, _id(object)))
+
+
+def _perfcheck(object=None):
+    import time
+    if object is None:
+        object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
+    p = PrettyPrinter()
+    t1 = time.time()
+    _safe_repr(object, {}, None, 0)
+    t2 = time.time()
+    p.pformat(object)
+    t3 = time.time()
+    print "_safe_repr:", t2 - t1
+    print "pformat:", t3 - t2
+
+if __name__ == "__main__":
+    _perfcheck()
diff --git a/src/main/resources/PythonLibs/profile.py b/src/main/resources/PythonLibs/profile.py
new file mode 100644
index 0000000000000000000000000000000000000000..297aa04cf7cf3f624b8aa7c6d0077c7ee8c8e9e2
--- /dev/null
+++ b/src/main/resources/PythonLibs/profile.py
@@ -0,0 +1,610 @@
+#! /usr/bin/env python
+#
+# Class for profiling python code. rev 1.0  6/2/94
+#
+# Written by James Roskind
+# Based on prior profile module by Sjoerd Mullender...
+#   which was hacked somewhat by: Guido van Rossum
+
+"""Class for profiling Python code."""
+
+# Copyright Disney Enterprises, Inc.  All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+# either express or implied.  See the License for the specific language
+# governing permissions and limitations under the License.
+
+
+import sys
+import os
+import time
+import marshal
+from optparse import OptionParser
+
+__all__ = ["run", "runctx", "help", "Profile"]
+
+# Sample timer for use with
+#i_count = 0
+#def integer_timer():
+#       global i_count
+#       i_count = i_count + 1
+#       return i_count
+#itimes = integer_timer # replace with C coded timer returning integers
+
+#**************************************************************************
+# The following are the static member functions for the profiler class
+# Note that an instance of Profile() is *not* needed to call them.
+#**************************************************************************
+
+def run(statement, filename=None, sort=-1):
+    """Run statement under profiler optionally saving results in filename
+
+    This function takes a single argument that can be passed to the
+    "exec" statement, and an optional file name.  In all cases this
+    routine attempts to "exec" its first argument and gather profiling
+    statistics from the execution. If no file name is present, then this
+    function automatically prints a simple profiling report, sorted by the
+    standard name string (file/line/function-name) that is presented in
+    each line.
+    """
+    prof = Profile()
+    try:
+        prof = prof.run(statement)
+    except SystemExit:
+        pass
+    if filename is not None:
+        prof.dump_stats(filename)
+    else:
+        return prof.print_stats(sort)
+
+def runctx(statement, globals, locals, filename=None, sort=-1):
+    """Run statement under profiler, supplying your own globals and locals,
+    optionally saving results in filename.
+
+    statement and filename have the same semantics as profile.run
+    """
+    prof = Profile()
+    try:
+        prof = prof.runctx(statement, globals, locals)
+    except SystemExit:
+        pass
+
+    if filename is not None:
+        prof.dump_stats(filename)
+    else:
+        return prof.print_stats(sort)
+
+# Backwards compatibility.
+def help():
+    print "Documentation for the profile module can be found "
+    print "in the Python Library Reference, section 'The Python Profiler'."
+
+if hasattr(os, "times"):
+    def _get_time_times(timer=os.times):
+        t = timer()
+        return t[0] + t[1]
+
+# Using getrusage(3) is better than clock(3) if available:
+# on some systems (e.g. FreeBSD), getrusage has a higher resolution
+# Furthermore, on a POSIX system, returns microseconds, which
+# wrap around after 36min.
+_has_res = 0
+try:
+    import resource
+    resgetrusage = lambda: resource.getrusage(resource.RUSAGE_SELF)
+    def _get_time_resource(timer=resgetrusage):
+        t = timer()
+        return t[0] + t[1]
+    _has_res = 1
+except ImportError:
+    pass
+
+class Profile:
+    """Profiler class.
+
+    self.cur is always a tuple.  Each such tuple corresponds to a stack
+    frame that is currently active (self.cur[-2]).  The following are the
+    definitions of its members.  We use this external "parallel stack" to
+    avoid contaminating the program that we are profiling. (old profiler
+    used to write into the frames local dictionary!!) Derived classes
+    can change the definition of some entries, as long as they leave
+    [-2:] intact (frame and previous tuple).  In case an internal error is
+    detected, the -3 element is used as the function name.
+
+    [ 0] = Time that needs to be charged to the parent frame's function.
+           It is used so that a function call will not have to access the
+           timing data for the parent frame.
+    [ 1] = Total time spent in this frame's function, excluding time in
+           subfunctions (this latter is tallied in cur[2]).
+    [ 2] = Total time spent in subfunctions, excluding time executing the
+           frame's function (this latter is tallied in cur[1]).
+    [-3] = Name of the function that corresponds to this frame.
+    [-2] = Actual frame that we correspond to (used to sync exception handling).
+    [-1] = Our parent 6-tuple (corresponds to frame.f_back).
+
+    Timing data for each function is stored as a 5-tuple in the dictionary
+    self.timings[].  The index is always the name stored in self.cur[-3].
+    The following are the definitions of the members:
+
+    [0] = The number of times this function was called, not counting direct
+          or indirect recursion,
+    [1] = Number of times this function appears on the stack, minus one
+    [2] = Total time spent internal to this function
+    [3] = Cumulative time that this function was present on the stack.  In
+          non-recursive functions, this is the total execution time from start
+          to finish of each invocation of a function, including time spent in
+          all subfunctions.
+    [4] = A dictionary indicating for each function name, the number of times
+          it was called by us.
+    """
+
+    bias = 0  # calibration constant
+
+    def __init__(self, timer=None, bias=None):
+        self.timings = {}
+        self.cur = None
+        self.cmd = ""
+        self.c_func_name = ""
+
+        if bias is None:
+            bias = self.bias
+        self.bias = bias     # Materialize in local dict for lookup speed.
+
+        if not timer:
+            if _has_res:
+                self.timer = resgetrusage
+                self.dispatcher = self.trace_dispatch
+                self.get_time = _get_time_resource
+            elif hasattr(time, 'clock'):
+                self.timer = self.get_time = time.clock
+                self.dispatcher = self.trace_dispatch_i
+            elif hasattr(os, 'times'):
+                self.timer = os.times
+                self.dispatcher = self.trace_dispatch
+                self.get_time = _get_time_times
+            else:
+                self.timer = self.get_time = time.time
+                self.dispatcher = self.trace_dispatch_i
+        else:
+            self.timer = timer
+            t = self.timer() # test out timer function
+            try:
+                length = len(t)
+            except TypeError:
+                self.get_time = timer
+                self.dispatcher = self.trace_dispatch_i
+            else:
+                if length == 2:
+                    self.dispatcher = self.trace_dispatch
+                else:
+                    self.dispatcher = self.trace_dispatch_l
+                # This get_time() implementation needs to be defined
+                # here to capture the passed-in timer in the parameter
+                # list (for performance).  Note that we can't assume
+                # the timer() result contains two values in all
+                # cases.
+                def get_time_timer(timer=timer, sum=sum):
+                    return sum(timer())
+                self.get_time = get_time_timer
+        self.t = self.get_time()
+        self.simulate_call('profiler')
+
+    # Heavily optimized dispatch routine for os.times() timer
+
+    def trace_dispatch(self, frame, event, arg):
+        timer = self.timer
+        t = timer()
+        t = t[0] + t[1] - self.t - self.bias
+
+        if event == "c_call":
+            self.c_func_name = arg.__name__
+
+        if self.dispatch[event](self, frame,t):
+            t = timer()
+            self.t = t[0] + t[1]
+        else:
+            r = timer()
+            self.t = r[0] + r[1] - t # put back unrecorded delta
+
+    # Dispatch routine for best timer program (return = scalar, fastest if
+    # an integer but float works too -- and time.clock() relies on that).
+
+    def trace_dispatch_i(self, frame, event, arg):
+        timer = self.timer
+        t = timer() - self.t - self.bias
+
+        if event == "c_call":
+            self.c_func_name = arg.__name__
+
+        if self.dispatch[event](self, frame, t):
+            self.t = timer()
+        else:
+            self.t = timer() - t  # put back unrecorded delta
+
+    # Dispatch routine for macintosh (timer returns time in ticks of
+    # 1/60th second)
+
+    def trace_dispatch_mac(self, frame, event, arg):
+        timer = self.timer
+        t = timer()/60.0 - self.t - self.bias
+
+        if event == "c_call":
+            self.c_func_name = arg.__name__
+
+        if self.dispatch[event](self, frame, t):
+            self.t = timer()/60.0
+        else:
+            self.t = timer()/60.0 - t  # put back unrecorded delta
+
+    # SLOW generic dispatch routine for timer returning lists of numbers
+
+    def trace_dispatch_l(self, frame, event, arg):
+        get_time = self.get_time
+        t = get_time() - self.t - self.bias
+
+        if event == "c_call":
+            self.c_func_name = arg.__name__
+
+        if self.dispatch[event](self, frame, t):
+            self.t = get_time()
+        else:
+            self.t = get_time() - t # put back unrecorded delta
+
+    # In the event handlers, the first 3 elements of self.cur are unpacked
+    # into vrbls w/ 3-letter names.  The last two characters are meant to be
+    # mnemonic:
+    #     _pt  self.cur[0] "parent time"   time to be charged to parent frame
+    #     _it  self.cur[1] "internal time" time spent directly in the function
+    #     _et  self.cur[2] "external time" time spent in subfunctions
+
+    def trace_dispatch_exception(self, frame, t):
+        rpt, rit, ret, rfn, rframe, rcur = self.cur
+        if (rframe is not frame) and rcur:
+            return self.trace_dispatch_return(rframe, t)
+        self.cur = rpt, rit+t, ret, rfn, rframe, rcur
+        return 1
+
+
+    def trace_dispatch_call(self, frame, t):
+        if self.cur and frame.f_back is not self.cur[-2]:
+            rpt, rit, ret, rfn, rframe, rcur = self.cur
+            if not isinstance(rframe, Profile.fake_frame):
+                assert rframe.f_back is frame.f_back, ("Bad call", rfn,
+                                                       rframe, rframe.f_back,
+                                                       frame, frame.f_back)
+                self.trace_dispatch_return(rframe, 0)
+                assert (self.cur is None or \
+                        frame.f_back is self.cur[-2]), ("Bad call",
+                                                        self.cur[-3])
+        fcode = frame.f_code
+        fn = (fcode.co_filename, fcode.co_firstlineno, fcode.co_name)
+        self.cur = (t, 0, 0, fn, frame, self.cur)
+        timings = self.timings
+        if fn in timings:
+            cc, ns, tt, ct, callers = timings[fn]
+            timings[fn] = cc, ns + 1, tt, ct, callers
+        else:
+            timings[fn] = 0, 0, 0, 0, {}
+        return 1
+
+    def trace_dispatch_c_call (self, frame, t):
+        fn = ("", 0, self.c_func_name)
+        self.cur = (t, 0, 0, fn, frame, self.cur)
+        timings = self.timings
+        if fn in timings:
+            cc, ns, tt, ct, callers = timings[fn]
+            timings[fn] = cc, ns+1, tt, ct, callers
+        else:
+            timings[fn] = 0, 0, 0, 0, {}
+        return 1
+
+    def trace_dispatch_return(self, frame, t):
+        if frame is not self.cur[-2]:
+            assert frame is self.cur[-2].f_back, ("Bad return", self.cur[-3])
+            self.trace_dispatch_return(self.cur[-2], 0)
+
+        # Prefix "r" means part of the Returning or exiting frame.
+        # Prefix "p" means part of the Previous or Parent or older frame.
+
+        rpt, rit, ret, rfn, frame, rcur = self.cur
+        rit = rit + t
+        frame_total = rit + ret
+
+        ppt, pit, pet, pfn, pframe, pcur = rcur
+        self.cur = ppt, pit + rpt, pet + frame_total, pfn, pframe, pcur
+
+        timings = self.timings
+        cc, ns, tt, ct, callers = timings[rfn]
+        if not ns:
+            # This is the only occurrence of the function on the stack.
+            # Else this is a (directly or indirectly) recursive call, and
+            # its cumulative time will get updated when the topmost call to
+            # it returns.
+            ct = ct + frame_total
+            cc = cc + 1
+
+        if pfn in callers:
+            callers[pfn] = callers[pfn] + 1  # hack: gather more
+            # stats such as the amount of time added to ct courtesy
+            # of this specific call, and the contribution to cc
+            # courtesy of this call.
+        else:
+            callers[pfn] = 1
+
+        timings[rfn] = cc, ns - 1, tt + rit, ct, callers
+
+        return 1
+
+
+    dispatch = {
+        "call": trace_dispatch_call,
+        "exception": trace_dispatch_exception,
+        "return": trace_dispatch_return,
+        "c_call": trace_dispatch_c_call,
+        "c_exception": trace_dispatch_return,  # the C function returned
+        "c_return": trace_dispatch_return,
+        }
+
+
+    # The next few functions play with self.cmd. By carefully preloading
+    # our parallel stack, we can force the profiled result to include
+    # an arbitrary string as the name of the calling function.
+    # We use self.cmd as that string, and the resulting stats look
+    # very nice :-).
+
+    def set_cmd(self, cmd):
+        if self.cur[-1]: return   # already set
+        self.cmd = cmd
+        self.simulate_call(cmd)
+
+    class fake_code:
+        def __init__(self, filename, line, name):
+            self.co_filename = filename
+            self.co_line = line
+            self.co_name = name
+            self.co_firstlineno = 0
+
+        def __repr__(self):
+            return repr((self.co_filename, self.co_line, self.co_name))
+
+    class fake_frame:
+        def __init__(self, code, prior):
+            self.f_code = code
+            self.f_back = prior
+
+    def simulate_call(self, name):
+        code = self.fake_code('profile', 0, name)
+        if self.cur:
+            pframe = self.cur[-2]
+        else:
+            pframe = None
+        frame = self.fake_frame(code, pframe)
+        self.dispatch['call'](self, frame, 0)
+
+    # collect stats from pending stack, including getting final
+    # timings for self.cmd frame.
+
+    def simulate_cmd_complete(self):
+        get_time = self.get_time
+        t = get_time() - self.t
+        while self.cur[-1]:
+            # We *can* cause assertion errors here if
+            # dispatch_trace_return checks for a frame match!
+            self.dispatch['return'](self, self.cur[-2], t)
+            t = 0
+        self.t = get_time() - t
+
+
+    def print_stats(self, sort=-1):
+        import pstats
+        pstats.Stats(self).strip_dirs().sort_stats(sort). \
+                  print_stats()
+
+    def dump_stats(self, file):
+        f = open(file, 'wb')
+        self.create_stats()
+        marshal.dump(self.stats, f)
+        f.close()
+
+    def create_stats(self):
+        self.simulate_cmd_complete()
+        self.snapshot_stats()
+
+    def snapshot_stats(self):
+        self.stats = {}
+        for func, (cc, ns, tt, ct, callers) in self.timings.iteritems():
+            callers = callers.copy()
+            nc = 0
+            for callcnt in callers.itervalues():
+                nc += callcnt
+            self.stats[func] = cc, nc, tt, ct, callers
+
+
+    # The following two methods can be called by clients to use
+    # a profiler to profile a statement, given as a string.
+
+    def run(self, cmd):
+        import __main__
+        dict = __main__.__dict__
+        return self.runctx(cmd, dict, dict)
+
+    def runctx(self, cmd, globals, locals):
+        self.set_cmd(cmd)
+        sys.setprofile(self.dispatcher)
+        try:
+            exec cmd in globals, locals
+        finally:
+            sys.setprofile(None)
+        return self
+
+    # This method is more useful to profile a single function call.
+    def runcall(self, func, *args, **kw):
+        self.set_cmd(repr(func))
+        sys.setprofile(self.dispatcher)
+        try:
+            return func(*args, **kw)
+        finally:
+            sys.setprofile(None)
+
+
+    #******************************************************************
+    # The following calculates the overhead for using a profiler.  The
+    # problem is that it takes a fair amount of time for the profiler
+    # to stop the stopwatch (from the time it receives an event).
+    # Similarly, there is a delay from the time that the profiler
+    # re-starts the stopwatch before the user's code really gets to
+    # continue.  The following code tries to measure the difference on
+    # a per-event basis.
+    #
+    # Note that this difference is only significant if there are a lot of
+    # events, and relatively little user code per event.  For example,
+    # code with small functions will typically benefit from having the
+    # profiler calibrated for the current platform.  This *could* be
+    # done on the fly during init() time, but it is not worth the
+    # effort.  Also note that if too large a value specified, then
+    # execution time on some functions will actually appear as a
+    # negative number.  It is *normal* for some functions (with very
+    # low call counts) to have such negative stats, even if the
+    # calibration figure is "correct."
+    #
+    # One alternative to profile-time calibration adjustments (i.e.,
+    # adding in the magic little delta during each event) is to track
+    # more carefully the number of events (and cumulatively, the number
+    # of events during sub functions) that are seen.  If this were
+    # done, then the arithmetic could be done after the fact (i.e., at
+    # display time).  Currently, we track only call/return events.
+    # These values can be deduced by examining the callees and callers
+    # vectors for each functions.  Hence we *can* almost correct the
+    # internal time figure at print time (note that we currently don't
+    # track exception event processing counts).  Unfortunately, there
+    # is currently no similar information for cumulative sub-function
+    # time.  It would not be hard to "get all this info" at profiler
+    # time.  Specifically, we would have to extend the tuples to keep
+    # counts of this in each frame, and then extend the defs of timing
+    # tuples to include the significant two figures. I'm a bit fearful
+    # that this additional feature will slow the heavily optimized
+    # event/time ratio (i.e., the profiler would run slower, fur a very
+    # low "value added" feature.)
+    #**************************************************************
+
+    def calibrate(self, m, verbose=0):
+        if self.__class__ is not Profile:
+            raise TypeError("Subclasses must override .calibrate().")
+
+        saved_bias = self.bias
+        self.bias = 0
+        try:
+            return self._calibrate_inner(m, verbose)
+        finally:
+            self.bias = saved_bias
+
+    def _calibrate_inner(self, m, verbose):
+        get_time = self.get_time
+
+        # Set up a test case to be run with and without profiling.  Include
+        # lots of calls, because we're trying to quantify stopwatch overhead.
+        # Do not raise any exceptions, though, because we want to know
+        # exactly how many profile events are generated (one call event, +
+        # one return event, per Python-level call).
+
+        def f1(n):
+            for i in range(n):
+                x = 1
+
+        def f(m, f1=f1):
+            for i in range(m):
+                f1(100)
+
+        f(m)    # warm up the cache
+
+        # elapsed_noprofile <- time f(m) takes without profiling.
+        t0 = get_time()
+        f(m)
+        t1 = get_time()
+        elapsed_noprofile = t1 - t0
+        if verbose:
+            print "elapsed time without profiling =", elapsed_noprofile
+
+        # elapsed_profile <- time f(m) takes with profiling.  The difference
+        # is profiling overhead, only some of which the profiler subtracts
+        # out on its own.
+        p = Profile()
+        t0 = get_time()
+        p.runctx('f(m)', globals(), locals())
+        t1 = get_time()
+        elapsed_profile = t1 - t0
+        if verbose:
+            print "elapsed time with profiling =", elapsed_profile
+
+        # reported_time <- "CPU seconds" the profiler charged to f and f1.
+        total_calls = 0.0
+        reported_time = 0.0
+        for (filename, line, funcname), (cc, ns, tt, ct, callers) in \
+                p.timings.items():
+            if funcname in ("f", "f1"):
+                total_calls += cc
+                reported_time += tt
+
+        if verbose:
+            print "'CPU seconds' profiler reported =", reported_time
+            print "total # calls =", total_calls
+        if total_calls != m + 1:
+            raise ValueError("internal error: total calls = %d" % total_calls)
+
+        # reported_time - elapsed_noprofile = overhead the profiler wasn't
+        # able to measure.  Divide by twice the number of calls (since there
+        # are two profiler events per call in this test) to get the hidden
+        # overhead per event.
+        mean = (reported_time - elapsed_noprofile) / 2.0 / total_calls
+        if verbose:
+            print "mean stopwatch overhead per profile event =", mean
+        return mean
+
+#****************************************************************************
+def Stats(*args):
+    print 'Report generating functions are in the "pstats" module\a'
+
+def main():
+    usage = "profile.py [-o output_file_path] [-s sort] scriptfile [arg] ..."
+    parser = OptionParser(usage=usage)
+    parser.allow_interspersed_args = False
+    parser.add_option('-o', '--outfile', dest="outfile",
+        help="Save stats to <outfile>", default=None)
+    parser.add_option('-s', '--sort', dest="sort",
+        help="Sort order when printing to stdout, based on pstats.Stats class",
+        default=-1)
+
+    if not sys.argv[1:]:
+        parser.print_usage()
+        sys.exit(2)
+
+    (options, args) = parser.parse_args()
+    sys.argv[:] = args
+
+    if len(args) > 0:
+        progname = args[0]
+        sys.path.insert(0, os.path.dirname(progname))
+        with open(progname, 'rb') as fp:
+            code = compile(fp.read(), progname, 'exec')
+        globs = {
+            '__file__': progname,
+            '__name__': '__main__',
+            '__package__': None,
+        }
+        runctx(code, globs, None, options.outfile, options.sort)
+    else:
+        parser.print_usage()
+    return parser
+
+# When invoked as main program, invoke the profiler on a script
+if __name__ == '__main__':
+    main()
diff --git a/src/main/resources/PythonLibs/pstats.py b/src/main/resources/PythonLibs/pstats.py
new file mode 100644
index 0000000000000000000000000000000000000000..4338994e5d4466607d6ca3f7917cddc3ef88d102
--- /dev/null
+++ b/src/main/resources/PythonLibs/pstats.py
@@ -0,0 +1,705 @@
+"""Class for printing reports on profiled python code."""
+
+# Written by James Roskind
+# Based on prior profile module by Sjoerd Mullender...
+#   which was hacked somewhat by: Guido van Rossum
+
+# Copyright Disney Enterprises, Inc.  All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+# either express or implied.  See the License for the specific language
+# governing permissions and limitations under the License.
+
+
+import sys
+import os
+import time
+import marshal
+import re
+from functools import cmp_to_key
+
+__all__ = ["Stats"]
+
+class Stats:
+    """This class is used for creating reports from data generated by the
+    Profile class.  It is a "friend" of that class, and imports data either
+    by direct access to members of Profile class, or by reading in a dictionary
+    that was emitted (via marshal) from the Profile class.
+
+    The big change from the previous Profiler (in terms of raw functionality)
+    is that an "add()" method has been provided to combine Stats from
+    several distinct profile runs.  Both the constructor and the add()
+    method now take arbitrarily many file names as arguments.
+
+    All the print methods now take an argument that indicates how many lines
+    to print.  If the arg is a floating point number between 0 and 1.0, then
+    it is taken as a decimal percentage of the available lines to be printed
+    (e.g., .1 means print 10% of all available lines).  If it is an integer,
+    it is taken to mean the number of lines of data that you wish to have
+    printed.
+
+    The sort_stats() method now processes some additional options (i.e., in
+    addition to the old -1, 0, 1, or 2).  It takes an arbitrary number of
+    quoted strings to select the sort order.  For example sort_stats('time',
+    'name') sorts on the major key of 'internal function time', and on the
+    minor key of 'the name of the function'.  Look at the two tables in
+    sort_stats() and get_sort_arg_defs(self) for more examples.
+
+    All methods return self, so you can string together commands like:
+        Stats('foo', 'goo').strip_dirs().sort_stats('calls').\
+                            print_stats(5).print_callers(5)
+    """
+
+    def __init__(self, *args, **kwds):
+        # I can't figure out how to explictly specify a stream keyword arg
+        # with *args:
+        #   def __init__(self, *args, stream=sys.stdout): ...
+        # so I use **kwds and sqauwk if something unexpected is passed in.
+        self.stream = sys.stdout
+        if "stream" in kwds:
+            self.stream = kwds["stream"]
+            del kwds["stream"]
+        if kwds:
+            keys = kwds.keys()
+            keys.sort()
+            extras = ", ".join(["%s=%s" % (k, kwds[k]) for k in keys])
+            raise ValueError, "unrecognized keyword args: %s" % extras
+        if not len(args):
+            arg = None
+        else:
+            arg = args[0]
+            args = args[1:]
+        self.init(arg)
+        self.add(*args)
+
+    def init(self, arg):
+        self.all_callees = None  # calc only if needed
+        self.files = []
+        self.fcn_list = None
+        self.total_tt = 0
+        self.total_calls = 0
+        self.prim_calls = 0
+        self.max_name_len = 0
+        self.top_level = {}
+        self.stats = {}
+        self.sort_arg_dict = {}
+        self.load_stats(arg)
+        trouble = 1
+        try:
+            self.get_top_level_stats()
+            trouble = 0
+        finally:
+            if trouble:
+                print >> self.stream, "Invalid timing data",
+                if self.files: print >> self.stream, self.files[-1],
+                print >> self.stream
+
+    def load_stats(self, arg):
+        if not arg:  self.stats = {}
+        elif isinstance(arg, basestring):
+            f = open(arg, 'rb')
+            self.stats = marshal.load(f)
+            f.close()
+            try:
+                file_stats = os.stat(arg)
+                arg = time.ctime(file_stats.st_mtime) + "    " + arg
+            except:  # in case this is not unix
+                pass
+            self.files = [ arg ]
+        elif hasattr(arg, 'create_stats'):
+            arg.create_stats()
+            self.stats = arg.stats
+            arg.stats = {}
+        if not self.stats:
+            raise TypeError("Cannot create or construct a %r object from %r"
+                            % (self.__class__, arg))
+        return
+
+    def get_top_level_stats(self):
+        for func, (cc, nc, tt, ct, callers) in self.stats.items():
+            self.total_calls += nc
+            self.prim_calls  += cc
+            self.total_tt    += tt
+            if ("jprofile", 0, "profiler") in callers:
+                self.top_level[func] = None
+            if len(func_std_string(func)) > self.max_name_len:
+                self.max_name_len = len(func_std_string(func))
+
+    def add(self, *arg_list):
+        if not arg_list: return self
+        if len(arg_list) > 1: self.add(*arg_list[1:])
+        other = arg_list[0]
+        if type(self) != type(other) or self.__class__ != other.__class__:
+            other = Stats(other)
+        self.files += other.files
+        self.total_calls += other.total_calls
+        self.prim_calls += other.prim_calls
+        self.total_tt += other.total_tt
+        for func in other.top_level:
+            self.top_level[func] = None
+
+        if self.max_name_len < other.max_name_len:
+            self.max_name_len = other.max_name_len
+
+        self.fcn_list = None
+
+        for func, stat in other.stats.iteritems():
+            if func in self.stats:
+                old_func_stat = self.stats[func]
+            else:
+                old_func_stat = (0, 0, 0, 0, {},)
+            self.stats[func] = add_func_stats(old_func_stat, stat)
+        return self
+
+    def dump_stats(self, filename):
+        """Write the profile data to a file we know how to load back."""
+        f = file(filename, 'wb')
+        try:
+            marshal.dump(self.stats, f)
+        finally:
+            f.close()
+
+    # list the tuple indices and directions for sorting,
+    # along with some printable description
+    sort_arg_dict_default = {
+              "calls"     : (((1,-1),              ), "call count"),
+              "ncalls"    : (((1,-1),              ), "call count"),
+              "cumtime"   : (((3,-1),              ), "cumulative time"),
+              "cumulative": (((3,-1),              ), "cumulative time"),
+              "file"      : (((4, 1),              ), "file name"),
+              "filename"  : (((4, 1),              ), "file name"),
+              "line"      : (((5, 1),              ), "line number"),
+              "module"    : (((4, 1),              ), "file name"),
+              "name"      : (((6, 1),              ), "function name"),
+              "nfl"       : (((6, 1),(4, 1),(5, 1),), "name/file/line"),
+              "pcalls"    : (((0,-1),              ), "primitive call count"),
+              "stdname"   : (((7, 1),              ), "standard name"),
+              "time"      : (((2,-1),              ), "internal time"),
+              "tottime"   : (((2,-1),              ), "internal time"),
+              }
+
+    def get_sort_arg_defs(self):
+        """Expand all abbreviations that are unique."""
+        if not self.sort_arg_dict:
+            self.sort_arg_dict = dict = {}
+            bad_list = {}
+            for word, tup in self.sort_arg_dict_default.iteritems():
+                fragment = word
+                while fragment:
+                    if not fragment:
+                        break
+                    if fragment in dict:
+                        bad_list[fragment] = 0
+                        break
+                    dict[fragment] = tup
+                    fragment = fragment[:-1]
+            for word in bad_list:
+                del dict[word]
+        return self.sort_arg_dict
+
+    def sort_stats(self, *field):
+        if not field:
+            self.fcn_list = 0
+            return self
+        if len(field) == 1 and isinstance(field[0], (int, long)):
+            # Be compatible with old profiler
+            field = [ {-1: "stdname",
+                       0:  "calls",
+                       1:  "time",
+                       2:  "cumulative"}[field[0]] ]
+
+        sort_arg_defs = self.get_sort_arg_defs()
+        sort_tuple = ()
+        self.sort_type = ""
+        connector = ""
+        for word in field:
+            sort_tuple = sort_tuple + sort_arg_defs[word][0]
+            self.sort_type += connector + sort_arg_defs[word][1]
+            connector = ", "
+
+        stats_list = []
+        for func, (cc, nc, tt, ct, callers) in self.stats.iteritems():
+            stats_list.append((cc, nc, tt, ct) + func +
+                              (func_std_string(func), func))
+
+        stats_list.sort(key=cmp_to_key(TupleComp(sort_tuple).compare))
+
+        self.fcn_list = fcn_list = []
+        for tuple in stats_list:
+            fcn_list.append(tuple[-1])
+        return self
+
+    def reverse_order(self):
+        if self.fcn_list:
+            self.fcn_list.reverse()
+        return self
+
+    def strip_dirs(self):
+        oldstats = self.stats
+        self.stats = newstats = {}
+        max_name_len = 0
+        for func, (cc, nc, tt, ct, callers) in oldstats.iteritems():
+            newfunc = func_strip_path(func)
+            if len(func_std_string(newfunc)) > max_name_len:
+                max_name_len = len(func_std_string(newfunc))
+            newcallers = {}
+            for func2, caller in callers.iteritems():
+                newcallers[func_strip_path(func2)] = caller
+
+            if newfunc in newstats:
+                newstats[newfunc] = add_func_stats(
+                                        newstats[newfunc],
+                                        (cc, nc, tt, ct, newcallers))
+            else:
+                newstats[newfunc] = (cc, nc, tt, ct, newcallers)
+        old_top = self.top_level
+        self.top_level = new_top = {}
+        for func in old_top:
+            new_top[func_strip_path(func)] = None
+
+        self.max_name_len = max_name_len
+
+        self.fcn_list = None
+        self.all_callees = None
+        return self
+
+    def calc_callees(self):
+        if self.all_callees: return
+        self.all_callees = all_callees = {}
+        for func, (cc, nc, tt, ct, callers) in self.stats.iteritems():
+            if not func in all_callees:
+                all_callees[func] = {}
+            for func2, caller in callers.iteritems():
+                if not func2 in all_callees:
+                    all_callees[func2] = {}
+                all_callees[func2][func]  = caller
+        return
+
+    #******************************************************************
+    # The following functions support actual printing of reports
+    #******************************************************************
+
+    # Optional "amount" is either a line count, or a percentage of lines.
+
+    def eval_print_amount(self, sel, list, msg):
+        new_list = list
+        if isinstance(sel, basestring):
+            try:
+                rex = re.compile(sel)
+            except re.error:
+                msg += "   <Invalid regular expression %r>\n" % sel
+                return new_list, msg
+            new_list = []
+            for func in list:
+                if rex.search(func_std_string(func)):
+                    new_list.append(func)
+        else:
+            count = len(list)
+            if isinstance(sel, float) and 0.0 <= sel < 1.0:
+                count = int(count * sel + .5)
+                new_list = list[:count]
+            elif isinstance(sel, (int, long)) and 0 <= sel < count:
+                count = sel
+                new_list = list[:count]
+        if len(list) != len(new_list):
+            msg += "   List reduced from %r to %r due to restriction <%r>\n" % (
+                len(list), len(new_list), sel)
+
+        return new_list, msg
+
+    def get_print_list(self, sel_list):
+        width = self.max_name_len
+        if self.fcn_list:
+            stat_list = self.fcn_list[:]
+            msg = "   Ordered by: " + self.sort_type + '\n'
+        else:
+            stat_list = self.stats.keys()
+            msg = "   Random listing order was used\n"
+
+        for selection in sel_list:
+            stat_list, msg = self.eval_print_amount(selection, stat_list, msg)
+
+        count = len(stat_list)
+
+        if not stat_list:
+            return 0, stat_list
+        print >> self.stream, msg
+        if count < len(self.stats):
+            width = 0
+            for func in stat_list:
+                if  len(func_std_string(func)) > width:
+                    width = len(func_std_string(func))
+        return width+2, stat_list
+
+    def print_stats(self, *amount):
+        for filename in self.files:
+            print >> self.stream, filename
+        if self.files: print >> self.stream
+        indent = ' ' * 8
+        for func in self.top_level:
+            print >> self.stream, indent, func_get_function_name(func)
+
+        print >> self.stream, indent, self.total_calls, "function calls",
+        if self.total_calls != self.prim_calls:
+            print >> self.stream, "(%d primitive calls)" % self.prim_calls,
+        print >> self.stream, "in %.3f seconds" % self.total_tt
+        print >> self.stream
+        width, list = self.get_print_list(amount)
+        if list:
+            self.print_title()
+            for func in list:
+                self.print_line(func)
+            print >> self.stream
+            print >> self.stream
+        return self
+
+    def print_callees(self, *amount):
+        width, list = self.get_print_list(amount)
+        if list:
+            self.calc_callees()
+
+            self.print_call_heading(width, "called...")
+            for func in list:
+                if func in self.all_callees:
+                    self.print_call_line(width, func, self.all_callees[func])
+                else:
+                    self.print_call_line(width, func, {})
+            print >> self.stream
+            print >> self.stream
+        return self
+
+    def print_callers(self, *amount):
+        width, list = self.get_print_list(amount)
+        if list:
+            self.print_call_heading(width, "was called by...")
+            for func in list:
+                cc, nc, tt, ct, callers = self.stats[func]
+                self.print_call_line(width, func, callers, "<-")
+            print >> self.stream
+            print >> self.stream
+        return self
+
+    def print_call_heading(self, name_size, column_title):
+        print >> self.stream, "Function ".ljust(name_size) + column_title
+        # print sub-header only if we have new-style callers
+        subheader = False
+        for cc, nc, tt, ct, callers in self.stats.itervalues():
+            if callers:
+                value = callers.itervalues().next()
+                subheader = isinstance(value, tuple)
+                break
+        if subheader:
+            print >> self.stream, " "*name_size + "    ncalls  tottime  cumtime"
+
+    def print_call_line(self, name_size, source, call_dict, arrow="->"):
+        print >> self.stream, func_std_string(source).ljust(name_size) + arrow,
+        if not call_dict:
+            print >> self.stream
+            return
+        clist = call_dict.keys()
+        clist.sort()
+        indent = ""
+        for func in clist:
+            name = func_std_string(func)
+            value = call_dict[func]
+            if isinstance(value, tuple):
+                nc, cc, tt, ct = value
+                if nc != cc:
+                    substats = '%d/%d' % (nc, cc)
+                else:
+                    substats = '%d' % (nc,)
+                substats = '%s %s %s  %s' % (substats.rjust(7+2*len(indent)),
+                                             f8(tt), f8(ct), name)
+                left_width = name_size + 1
+            else:
+                substats = '%s(%r) %s' % (name, value, f8(self.stats[func][3]))
+                left_width = name_size + 3
+            print >> self.stream, indent*left_width + substats
+            indent = " "
+
+    def print_title(self):
+        print >> self.stream, '   ncalls  tottime  percall  cumtime  percall',
+        print >> self.stream, 'filename:lineno(function)'
+
+    def print_line(self, func):  # hack : should print percentages
+        cc, nc, tt, ct, callers = self.stats[func]
+        c = str(nc)
+        if nc != cc:
+            c = c + '/' + str(cc)
+        print >> self.stream, c.rjust(9),
+        print >> self.stream, f8(tt),
+        if nc == 0:
+            print >> self.stream, ' '*8,
+        else:
+            print >> self.stream, f8(float(tt)/nc),
+        print >> self.stream, f8(ct),
+        if cc == 0:
+            print >> self.stream, ' '*8,
+        else:
+            print >> self.stream, f8(float(ct)/cc),
+        print >> self.stream, func_std_string(func)
+
+class TupleComp:
+    """This class provides a generic function for comparing any two tuples.
+    Each instance records a list of tuple-indices (from most significant
+    to least significant), and sort direction (ascending or decending) for
+    each tuple-index.  The compare functions can then be used as the function
+    argument to the system sort() function when a list of tuples need to be
+    sorted in the instances order."""
+
+    def __init__(self, comp_select_list):
+        self.comp_select_list = comp_select_list
+
+    def compare (self, left, right):
+        for index, direction in self.comp_select_list:
+            l = left[index]
+            r = right[index]
+            if l < r:
+                return -direction
+            if l > r:
+                return direction
+        return 0
+
+#**************************************************************************
+# func_name is a triple (file:string, line:int, name:string)
+
+def func_strip_path(func_name):
+    filename, line, name = func_name
+    return os.path.basename(filename), line, name
+
+def func_get_function_name(func):
+    return func[2]
+
+def func_std_string(func_name): # match what old profile produced
+    if func_name[:2] == ('~', 0):
+        # special case for built-in functions
+        name = func_name[2]
+        if name.startswith('<') and name.endswith('>'):
+            return '{%s}' % name[1:-1]
+        else:
+            return name
+    else:
+        return "%s:%d(%s)" % func_name
+
+#**************************************************************************
+# The following functions combine statists for pairs functions.
+# The bulk of the processing involves correctly handling "call" lists,
+# such as callers and callees.
+#**************************************************************************
+
+def add_func_stats(target, source):
+    """Add together all the stats for two profile entries."""
+    cc, nc, tt, ct, callers = source
+    t_cc, t_nc, t_tt, t_ct, t_callers = target
+    return (cc+t_cc, nc+t_nc, tt+t_tt, ct+t_ct,
+              add_callers(t_callers, callers))
+
+def add_callers(target, source):
+    """Combine two caller lists in a single list."""
+    new_callers = {}
+    for func, caller in target.iteritems():
+        new_callers[func] = caller
+    for func, caller in source.iteritems():
+        if func in new_callers:
+            if isinstance(caller, tuple):
+                # format used by cProfile
+                new_callers[func] = tuple([i[0] + i[1] for i in
+                                           zip(caller, new_callers[func])])
+            else:
+                # format used by profile
+                new_callers[func] += caller
+        else:
+            new_callers[func] = caller
+    return new_callers
+
+def count_calls(callers):
+    """Sum the caller statistics to get total number of calls received."""
+    nc = 0
+    for calls in callers.itervalues():
+        nc += calls
+    return nc
+
+#**************************************************************************
+# The following functions support printing of reports
+#**************************************************************************
+
+def f8(x):
+    return "%8.3f" % x
+
+#**************************************************************************
+# Statistics browser added by ESR, April 2001
+#**************************************************************************
+
+if __name__ == '__main__':
+    import cmd
+    try:
+        import readline
+    except ImportError:
+        pass
+
+    class ProfileBrowser(cmd.Cmd):
+        def __init__(self, profile=None):
+            cmd.Cmd.__init__(self)
+            self.prompt = "% "
+            self.stats = None
+            self.stream = sys.stdout
+            if profile is not None:
+                self.do_read(profile)
+
+        def generic(self, fn, line):
+            args = line.split()
+            processed = []
+            for term in args:
+                try:
+                    processed.append(int(term))
+                    continue
+                except ValueError:
+                    pass
+                try:
+                    frac = float(term)
+                    if frac > 1 or frac < 0:
+                        print >> self.stream, "Fraction argument must be in [0, 1]"
+                        continue
+                    processed.append(frac)
+                    continue
+                except ValueError:
+                    pass
+                processed.append(term)
+            if self.stats:
+                getattr(self.stats, fn)(*processed)
+            else:
+                print >> self.stream, "No statistics object is loaded."
+            return 0
+        def generic_help(self):
+            print >> self.stream, "Arguments may be:"
+            print >> self.stream, "* An integer maximum number of entries to print."
+            print >> self.stream, "* A decimal fractional number between 0 and 1, controlling"
+            print >> self.stream, "  what fraction of selected entries to print."
+            print >> self.stream, "* A regular expression; only entries with function names"
+            print >> self.stream, "  that match it are printed."
+
+        def do_add(self, line):
+            if self.stats:
+                self.stats.add(line)
+            else:
+                print >> self.stream, "No statistics object is loaded."
+            return 0
+        def help_add(self):
+            print >> self.stream, "Add profile info from given file to current statistics object."
+
+        def do_callees(self, line):
+            return self.generic('print_callees', line)
+        def help_callees(self):
+            print >> self.stream, "Print callees statistics from the current stat object."
+            self.generic_help()
+
+        def do_callers(self, line):
+            return self.generic('print_callers', line)
+        def help_callers(self):
+            print >> self.stream, "Print callers statistics from the current stat object."
+            self.generic_help()
+
+        def do_EOF(self, line):
+            print >> self.stream, ""
+            return 1
+        def help_EOF(self):
+            print >> self.stream, "Leave the profile brower."
+
+        def do_quit(self, line):
+            return 1
+        def help_quit(self):
+            print >> self.stream, "Leave the profile brower."
+
+        def do_read(self, line):
+            if line:
+                try:
+                    self.stats = Stats(line)
+                except IOError, args:
+                    print >> self.stream, args[1]
+                    return
+                except Exception as err:
+                    print >> self.stream, err.__class__.__name__ + ':', err
+                    return
+                self.prompt = line + "% "
+            elif len(self.prompt) > 2:
+                line = self.prompt[:-2]
+                self.do_read(line)
+            else:
+                print >> self.stream, "No statistics object is current -- cannot reload."
+            return 0
+        def help_read(self):
+            print >> self.stream, "Read in profile data from a specified file."
+            print >> self.stream, "Without argument, reload the current file."
+
+        def do_reverse(self, line):
+            if self.stats:
+                self.stats.reverse_order()
+            else:
+                print >> self.stream, "No statistics object is loaded."
+            return 0
+        def help_reverse(self):
+            print >> self.stream, "Reverse the sort order of the profiling report."
+
+        def do_sort(self, line):
+            if not self.stats:
+                print >> self.stream, "No statistics object is loaded."
+                return
+            abbrevs = self.stats.get_sort_arg_defs()
+            if line and all((x in abbrevs) for x in line.split()):
+                self.stats.sort_stats(*line.split())
+            else:
+                print >> self.stream, "Valid sort keys (unique prefixes are accepted):"
+                for (key, value) in Stats.sort_arg_dict_default.iteritems():
+                    print >> self.stream, "%s -- %s" % (key, value[1])
+            return 0
+        def help_sort(self):
+            print >> self.stream, "Sort profile data according to specified keys."
+            print >> self.stream, "(Typing `sort' without arguments lists valid keys.)"
+        def complete_sort(self, text, *args):
+            return [a for a in Stats.sort_arg_dict_default if a.startswith(text)]
+
+        def do_stats(self, line):
+            return self.generic('print_stats', line)
+        def help_stats(self):
+            print >> self.stream, "Print statistics from the current stat object."
+            self.generic_help()
+
+        def do_strip(self, line):
+            if self.stats:
+                self.stats.strip_dirs()
+            else:
+                print >> self.stream, "No statistics object is loaded."
+        def help_strip(self):
+            print >> self.stream, "Strip leading path information from filenames in the report."
+
+        def help_help(self):
+            print >> self.stream, "Show help for a given command."
+
+        def postcmd(self, stop, line):
+            if stop:
+                return stop
+            return None
+
+    import sys
+    if len(sys.argv) > 1:
+        initprofile = sys.argv[1]
+    else:
+        initprofile = None
+    try:
+        browser = ProfileBrowser(initprofile)
+        print >> browser.stream, "Welcome to the profile statistics browser."
+        browser.cmdloop()
+        print >> browser.stream, "Goodbye."
+    except KeyboardInterrupt:
+        pass
+
+# That's all, folks.
diff --git a/src/main/resources/PythonLibs/pty.py b/src/main/resources/PythonLibs/pty.py
new file mode 100644
index 0000000000000000000000000000000000000000..05ff6860c1bcf0c62979c6539a0c63789303ca55
--- /dev/null
+++ b/src/main/resources/PythonLibs/pty.py
@@ -0,0 +1,180 @@
+"""Pseudo terminal utilities."""
+
+# Bugs: No signal handling.  Doesn't set slave termios and window size.
+#       Only tested on Linux.
+# See:  W. Richard Stevens. 1992.  Advanced Programming in the
+#       UNIX Environment.  Chapter 19.
+# Author: Steen Lumholt -- with additions by Guido.
+
+from select import select
+import os
+import tty
+
+__all__ = ["openpty","fork","spawn"]
+
+STDIN_FILENO = 0
+STDOUT_FILENO = 1
+STDERR_FILENO = 2
+
+CHILD = 0
+
+def openpty():
+    """openpty() -> (master_fd, slave_fd)
+    Open a pty master/slave pair, using os.openpty() if possible."""
+
+    try:
+        return os.openpty()
+    except (AttributeError, OSError):
+        pass
+    master_fd, slave_name = _open_terminal()
+    slave_fd = slave_open(slave_name)
+    return master_fd, slave_fd
+
+def master_open():
+    """master_open() -> (master_fd, slave_name)
+    Open a pty master and return the fd, and the filename of the slave end.
+    Deprecated, use openpty() instead."""
+
+    try:
+        master_fd, slave_fd = os.openpty()
+    except (AttributeError, OSError):
+        pass
+    else:
+        slave_name = os.ttyname(slave_fd)
+        os.close(slave_fd)
+        return master_fd, slave_name
+
+    return _open_terminal()
+
+def _open_terminal():
+    """Open pty master and return (master_fd, tty_name).
+    SGI and generic BSD version, for when openpty() fails."""
+    try:
+        import sgi
+    except ImportError:
+        pass
+    else:
+        try:
+            tty_name, master_fd = sgi._getpty(os.O_RDWR, 0666, 0)
+        except IOError, msg:
+            raise os.error, msg
+        return master_fd, tty_name
+    for x in 'pqrstuvwxyzPQRST':
+        for y in '0123456789abcdef':
+            pty_name = '/dev/pty' + x + y
+            try:
+                fd = os.open(pty_name, os.O_RDWR)
+            except os.error:
+                continue
+            return (fd, '/dev/tty' + x + y)
+    raise os.error, 'out of pty devices'
+
+def slave_open(tty_name):
+    """slave_open(tty_name) -> slave_fd
+    Open the pty slave and acquire the controlling terminal, returning
+    opened filedescriptor.
+    Deprecated, use openpty() instead."""
+
+    result = os.open(tty_name, os.O_RDWR)
+    try:
+        from fcntl import ioctl, I_PUSH
+    except ImportError:
+        return result
+    try:
+        ioctl(result, I_PUSH, "ptem")
+        ioctl(result, I_PUSH, "ldterm")
+    except IOError:
+        pass
+    return result
+
+def fork():
+    """fork() -> (pid, master_fd)
+    Fork and make the child a session leader with a controlling terminal."""
+
+    try:
+        pid, fd = os.forkpty()
+    except (AttributeError, OSError):
+        pass
+    else:
+        if pid == CHILD:
+            try:
+                os.setsid()
+            except OSError:
+                # os.forkpty() already set us session leader
+                pass
+        return pid, fd
+
+    master_fd, slave_fd = openpty()
+    pid = os.fork()
+    if pid == CHILD:
+        # Establish a new session.
+        os.setsid()
+        os.close(master_fd)
+
+        # Slave becomes stdin/stdout/stderr of child.
+        os.dup2(slave_fd, STDIN_FILENO)
+        os.dup2(slave_fd, STDOUT_FILENO)
+        os.dup2(slave_fd, STDERR_FILENO)
+        if (slave_fd > STDERR_FILENO):
+            os.close (slave_fd)
+
+        # Explicitly open the tty to make it become a controlling tty.
+        tmp_fd = os.open(os.ttyname(STDOUT_FILENO), os.O_RDWR)
+        os.close(tmp_fd)
+    else:
+        os.close(slave_fd)
+
+    # Parent and child process.
+    return pid, master_fd
+
+def _writen(fd, data):
+    """Write all the data to a descriptor."""
+    while data != '':
+        n = os.write(fd, data)
+        data = data[n:]
+
+def _read(fd):
+    """Default read function."""
+    return os.read(fd, 1024)
+
+def _copy(master_fd, master_read=_read, stdin_read=_read):
+    """Parent copy loop.
+    Copies
+            pty master -> standard output   (master_read)
+            standard input -> pty master    (stdin_read)"""
+    fds = [master_fd, STDIN_FILENO]
+    while True:
+        rfds, wfds, xfds = select(fds, [], [])
+        if master_fd in rfds:
+            data = master_read(master_fd)
+            if not data:  # Reached EOF.
+                fds.remove(master_fd)
+            else:
+                os.write(STDOUT_FILENO, data)
+        if STDIN_FILENO in rfds:
+            data = stdin_read(STDIN_FILENO)
+            if not data:
+                fds.remove(STDIN_FILENO)
+            else:
+                _writen(master_fd, data)
+
+def spawn(argv, master_read=_read, stdin_read=_read):
+    """Create a spawned process."""
+    if type(argv) == type(''):
+        argv = (argv,)
+    pid, master_fd = fork()
+    if pid == CHILD:
+        os.execlp(argv[0], *argv)
+    try:
+        mode = tty.tcgetattr(STDIN_FILENO)
+        tty.setraw(STDIN_FILENO)
+        restore = 1
+    except tty.error:    # This is the same as termios.error
+        restore = 0
+    try:
+        _copy(master_fd, master_read, stdin_read)
+    except (IOError, OSError):
+        if restore:
+            tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
+
+    os.close(master_fd)
diff --git a/src/main/resources/PythonLibs/pwd.py b/src/main/resources/PythonLibs/pwd.py
new file mode 100644
index 0000000000000000000000000000000000000000..f20169a1b3639fc8e4af19aa12d9984b6f0b5949
--- /dev/null
+++ b/src/main/resources/PythonLibs/pwd.py
@@ -0,0 +1,83 @@
+"""
+This module provides access to the Unix password database.
+
+Password database entries are reported as 7-tuples containing the
+following items from the password database (see `<pwd.h>'), in order:
+pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell.  The
+uid and gid items are integers, all others are strings. An exception
+is raised if the entry asked for cannot be found.
+"""
+
+__all__ = ['getpwuid', 'getpwnam', 'getpwall']
+
+from os import _name, _posix_impl
+from org.python.core.Py import newString
+
+if _name == 'nt':
+    raise ImportError, 'pwd module not supported on Windows'
+
+class struct_passwd(tuple):
+    """
+    pwd.struct_passwd: Results from getpw*() routines.
+
+    This object may be accessed either as a tuple of
+      (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)
+    or via the object attributes as named in the above tuple.
+    """
+
+    attrs = ['pw_name', 'pw_passwd', 'pw_uid', 'pw_gid', 'pw_gecos',
+             'pw_dir', 'pw_shell']
+
+    def __new__(cls, pwd):
+        pwd = (newString(pwd.loginName), newString(pwd.password), int(pwd.UID),
+               int(pwd.GID), newString(pwd.GECOS), newString(pwd.home),
+               newString(pwd.shell))
+        return tuple.__new__(cls, pwd)
+
+    def __getattr__(self, attr):
+        try:
+            return self[self.attrs.index(attr)]
+        except ValueError:
+            raise AttributeError
+
+
+def getpwuid(uid):
+    """
+    getpwuid(uid) -> (pw_name,pw_passwd,pw_uid,
+                      pw_gid,pw_gecos,pw_dir,pw_shell)
+    Return the password database entry for the given numeric user ID.
+    See pwd.__doc__ for more on password database entries.
+    """
+    entry = _posix_impl.getpwuid(uid)
+    if not entry:
+        raise KeyError(uid)
+    return struct_passwd(entry)
+
+
+def getpwnam(name):
+    """
+    getpwnam(name) -> (pw_name,pw_passwd,pw_uid,
+                        pw_gid,pw_gecos,pw_dir,pw_shell)
+    Return the password database entry for the given user name.
+    See pwd.__doc__ for more on password database entries.
+    """
+    entry = _posix_impl.getpwnam(name)
+    if not entry:
+        raise KeyError(name)
+    return struct_passwd(entry)
+
+
+def getpwall():
+    """
+    getpwall() -> list_of_entries
+    Return a list of all available password database entries,
+    in arbitrary order.
+    See pwd.__doc__ for more on password database entries.
+    """
+    entries = []
+    while True:
+        entry = _posix_impl.getpwent()
+        if not entry:
+            break
+        entries.append(struct_passwd(entry))
+    return entries
diff --git a/src/main/resources/PythonLibs/py_compile.py b/src/main/resources/PythonLibs/py_compile.py
new file mode 100644
index 0000000000000000000000000000000000000000..843196d891a28ce3219d8e220ab20f9f4ff9f1df
--- /dev/null
+++ b/src/main/resources/PythonLibs/py_compile.py
@@ -0,0 +1,128 @@
+"""Routine to "compile" a .py file to a .pyc (or .pyo) file.
+
+This module has intimate knowledge of the format of .pyc files.
+"""
+
+import _py_compile
+import os
+import sys
+import traceback
+
+__all__ = ["compile", "main", "PyCompileError"]
+
+
+class PyCompileError(Exception):
+    """Exception raised when an error occurs while attempting to
+    compile the file.
+
+    To raise this exception, use
+
+        raise PyCompileError(exc_type,exc_value,file[,msg])
+
+    where
+
+        exc_type:   exception type to be used in error message
+                    type name can be accesses as class variable
+                    'exc_type_name'
+
+        exc_value:  exception value to be used in error message
+                    can be accesses as class variable 'exc_value'
+
+        file:       name of file being compiled to be used in error message
+                    can be accesses as class variable 'file'
+
+        msg:        string message to be written as error message
+                    If no value is given, a default exception message will be given,
+                    consistent with 'standard' py_compile output.
+                    message (or default) can be accesses as class variable 'msg'
+
+    """
+
+    def __init__(self, exc_type, exc_value, file, msg=''):
+        exc_type_name = exc_type.__name__
+        if exc_type is SyntaxError:
+            tbtext = ''.join(traceback.format_exception_only(exc_type, exc_value))
+            errmsg = tbtext.replace('File "<string>"', 'File "%s"' % file)
+        else:
+            errmsg = "Sorry: %s: %s" % (exc_type_name,exc_value)
+
+        Exception.__init__(self,msg or errmsg,exc_type_name,exc_value,file)
+
+        self.exc_type_name = exc_type_name
+        self.exc_value = exc_value
+        self.file = file
+        self.msg = msg or errmsg
+
+    def __str__(self):
+        return self.msg
+
+
+def compile(file, cfile=None, dfile=None, doraise=False):
+    """Byte-compile one Python source file to Python bytecode.
+
+    Arguments:
+
+    file:    source filename
+    cfile:   target filename; defaults to source with 'c' or 'o' appended
+             ('c' normally, 'o' in optimizing mode, giving .pyc or .pyo)
+    dfile:   purported filename; defaults to source (this is the filename
+             that will show up in error messages)
+    doraise: flag indicating whether or not an exception should be
+             raised when a compile error is found. If an exception
+             occurs and this flag is set to False, a string
+             indicating the nature of the exception will be printed,
+             and the function will return to the caller. If an
+             exception occurs and this flag is set to True, a
+             PyCompileError exception will be raised.
+
+    Note that it isn't necessary to byte-compile Python modules for
+    execution efficiency -- Python itself byte-compiles a module when
+    it is loaded, and if it can, writes out the bytecode to the
+    corresponding .pyc (or .pyo) file.
+
+    However, if a Python installation is shared between users, it is a
+    good idea to byte-compile all modules upon installation, since
+    other users may not be able to write in the source directories,
+    and thus they won't be able to write the .pyc/.pyo file, and then
+    they would be byte-compiling every module each time it is loaded.
+    This can slow down program start-up considerably.
+
+    See compileall.py for a script/module that uses this module to
+    byte-compile all installed files (or all files in selected
+    directories).
+
+    """
+    try:
+        _py_compile.compile(file, cfile, dfile)
+    except Exception,err:
+        py_exc = PyCompileError(err.__class__,err.args,dfile or file)
+        if doraise:
+            raise py_exc
+        else:
+            sys.stderr.write(py_exc.msg + '\n')
+            return
+
+def main(args=None):
+    """Compile several source files.
+
+    The files named in 'args' (or on the command line, if 'args' is
+    not specified) are compiled and the resulting bytecode is cached
+    in the normal manner.  This function does not search a directory
+    structure to locate source files; it only compiles files named
+    explicitly.
+
+    """
+    if args is None:
+        args = sys.argv[1:]
+    rv = 0
+    for filename in args:
+        try:
+            compile(filename, doraise=True)
+        except PyCompileError, err:
+            # return value to indicate at least one failure
+            rv = 1
+            sys.stderr.write(err.msg)
+    return rv
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/src/main/resources/PythonLibs/pycimport.py b/src/main/resources/PythonLibs/pycimport.py
new file mode 100644
index 0000000000000000000000000000000000000000..bcccaa58d9f8f490dc497db30fa4a698d69d908c
--- /dev/null
+++ b/src/main/resources/PythonLibs/pycimport.py
@@ -0,0 +1,83 @@
+import imp
+import os
+import sys
+from marshal import Unmarshaller
+
+__debugging__ = False
+
+def __readPycHeader(file):
+    def read():
+        return ord(file.read(1))
+    magic = read() | (read()<<8)
+    if not ( file.read(1) == '\r' and file.read(1) == '\n' ):
+        raise TypeError("not valid pyc-file")
+    mtime = read() | (read()<<8) | (read()<<16) | (read()<<24)
+    return magic, mtime
+
+def __makeModule(name, code, path):
+    module = sys.modules.get(name)
+    if not module:
+        module = sys.modules[name] = imp.new_module(name)
+    module.__file__ = path
+    exec code in module.__dict__
+    return module
+
+class __Importer(object):
+    def __init__(self, path):
+        if __debugging__: print "Importer invoked"
+        self.__path = path
+    def find_module(self, fullname, path=None):
+        if __debugging__:
+            print "Importer.find_module(fullname=%s, path=%s)" % (
+                repr(fullname), repr(path))
+        path = fullname.split('.')
+        filename = path[-1]
+        path = path[:-1]
+        pycfile = os.path.join(self.__path, *(path + [filename + '.pyc']))
+        pyfile = os.path.join(self.__path, *(path + [filename + '.py']))
+        if os.path.exists(pycfile):
+            f = open(pycfile, 'rb')
+            try:
+                magic, mtime = __readPycHeader(f)
+            except:
+                return None # abort! not a valid pyc-file
+            f.close()
+            if os.path.exists(pyfile):
+                pytime = os.stat(pyfile).st_mtime
+                if pytime > mtime:
+                    return None # abort! py-file was newer
+            return self
+        else:
+            return None # abort! pyc-file does not exist
+    def load_module(self, fullname):
+        path = fullname.split('.')
+        path[-1] += '.pyc'
+        filename = os.path.join(self.__path, *path)
+        f = open(filename, 'rb')
+        magic, mtime = __readPycHeader(f)
+        #code = Unmarshaller(f, magic=magic).load()
+        code = Unmarshaller(f).load()
+        if __debugging__: print "Successfully loaded:", fullname
+        return __makeModule( fullname, code, filename )
+
+class __MetaImporter(object):
+    def __init__(self):
+        self.__importers = {}
+    def find_module(self, fullname, path):
+        if __debugging__: print "MetaImporter.find_module(%s, %s)" % (
+            repr(fullname), repr(path))
+        for _path in sys.path:
+            if _path not in self.__importers:
+                try:
+                    self.__importers[_path] = __Importer(_path)
+                except:
+                    self.__importers[_path] = None
+            importer = self.__importers[_path]
+            if importer is not None:
+                loader = importer.find_module(fullname, path)
+                if loader is not None:
+                    return loader
+        else:
+            return None
+
+sys.meta_path.insert(0, __MetaImporter())
diff --git a/src/main/resources/PythonLibs/pyclbr.py b/src/main/resources/PythonLibs/pyclbr.py
new file mode 100644
index 0000000000000000000000000000000000000000..b8f71ae6b64843f38a1284316fa98d34627882dd
--- /dev/null
+++ b/src/main/resources/PythonLibs/pyclbr.py
@@ -0,0 +1,344 @@
+"""Parse a Python module and describe its classes and methods.
+
+Parse enough of a Python file to recognize imports and class and
+method definitions, and to find out the superclasses of a class.
+
+The interface consists of a single function:
+        readmodule_ex(module [, path])
+where module is the name of a Python module, and path is an optional
+list of directories where the module is to be searched.  If present,
+path is prepended to the system search path sys.path.  The return
+value is a dictionary.  The keys of the dictionary are the names of
+the classes defined in the module (including classes that are defined
+via the from XXX import YYY construct).  The values are class
+instances of the class Class defined here.  One special key/value pair
+is present for packages: the key '__path__' has a list as its value
+which contains the package search path.
+
+A class is described by the class Class in this module.  Instances
+of this class have the following instance variables:
+        module -- the module name
+        name -- the name of the class
+        super -- a list of super classes (Class instances)
+        methods -- a dictionary of methods
+        file -- the file in which the class was defined
+        lineno -- the line in the file on which the class statement occurred
+The dictionary of methods uses the method names as keys and the line
+numbers on which the method was defined as values.
+If the name of a super class is not recognized, the corresponding
+entry in the list of super classes is not a class instance but a
+string giving the name of the super class.  Since import statements
+are recognized and imported modules are scanned as well, this
+shouldn't happen often.
+
+A function is described by the class Function in this module.
+Instances of this class have the following instance variables:
+        module -- the module name
+        name -- the name of the class
+        file -- the file in which the class was defined
+        lineno -- the line in the file on which the class statement occurred
+"""
+
+import sys
+import imp
+import tokenize
+from token import NAME, DEDENT, OP
+from operator import itemgetter
+
+__all__ = ["readmodule", "readmodule_ex", "Class", "Function"]
+
+_modules = {}                           # cache of modules we've seen
+
+# each Python class is represented by an instance of this class
+class Class:
+    '''Class to represent a Python class.'''
+    def __init__(self, module, name, super, file, lineno):
+        self.module = module
+        self.name = name
+        if super is None:
+            super = []
+        self.super = super
+        self.methods = {}
+        self.file = file
+        self.lineno = lineno
+
+    def _addmethod(self, name, lineno):
+        self.methods[name] = lineno
+
+class Function:
+    '''Class to represent a top-level Python function'''
+    def __init__(self, module, name, file, lineno):
+        self.module = module
+        self.name = name
+        self.file = file
+        self.lineno = lineno
+
+def readmodule(module, path=None):
+    '''Backwards compatible interface.
+
+    Call readmodule_ex() and then only keep Class objects from the
+    resulting dictionary.'''
+
+    res = {}
+    for key, value in _readmodule(module, path or []).items():
+        if isinstance(value, Class):
+            res[key] = value
+    return res
+
+def readmodule_ex(module, path=None):
+    '''Read a module file and return a dictionary of classes.
+
+    Search for MODULE in PATH and sys.path, read and parse the
+    module and return a dictionary with one entry for each class
+    found in the module.
+    '''
+    return _readmodule(module, path or [])
+
+def _readmodule(module, path, inpackage=None):
+    '''Do the hard work for readmodule[_ex].
+
+    If INPACKAGE is given, it must be the dotted name of the package in
+    which we are searching for a submodule, and then PATH must be the
+    package search path; otherwise, we are searching for a top-level
+    module, and PATH is combined with sys.path.
+    '''
+    # Compute the full module name (prepending inpackage if set)
+    if inpackage is not None:
+        fullmodule = "%s.%s" % (inpackage, module)
+    else:
+        fullmodule = module
+
+    # Check in the cache
+    if fullmodule in _modules:
+        return _modules[fullmodule]
+
+    # Initialize the dict for this module's contents
+    dict = {}
+
+    # Check if it is a built-in module; we don't do much for these
+    if module in sys.builtin_module_names and inpackage is None:
+        _modules[module] = dict
+        return dict
+
+    # Check for a dotted module name
+    i = module.rfind('.')
+    if i >= 0:
+        package = module[:i]
+        submodule = module[i+1:]
+        parent = _readmodule(package, path, inpackage)
+        if inpackage is not None:
+            package = "%s.%s" % (inpackage, package)
+        if not '__path__' in parent:
+            raise ImportError('No package named {}'.format(package))
+        return _readmodule(submodule, parent['__path__'], package)
+
+    # Search the path for the module
+    f = None
+    if inpackage is not None:
+        f, fname, (_s, _m, ty) = imp.find_module(module, path)
+    else:
+        f, fname, (_s, _m, ty) = imp.find_module(module, path + sys.path)
+    if ty == imp.PKG_DIRECTORY:
+        dict['__path__'] = [fname]
+        path = [fname] + path
+        f, fname, (_s, _m, ty) = imp.find_module('__init__', [fname])
+    _modules[fullmodule] = dict
+    if ty != imp.PY_SOURCE:
+        # not Python source, can't do anything with this module
+        f.close()
+        return dict
+
+    stack = [] # stack of (class, indent) pairs
+
+    g = tokenize.generate_tokens(f.readline)
+    try:
+        for tokentype, token, start, _end, _line in g:
+            if tokentype == DEDENT:
+                lineno, thisindent = start
+                # close nested classes and defs
+                while stack and stack[-1][1] >= thisindent:
+                    del stack[-1]
+            elif token == 'def':
+                lineno, thisindent = start
+                # close previous nested classes and defs
+                while stack and stack[-1][1] >= thisindent:
+                    del stack[-1]
+                tokentype, meth_name, start = g.next()[0:3]
+                if tokentype != NAME:
+                    continue # Syntax error
+                if stack:
+                    cur_class = stack[-1][0]
+                    if isinstance(cur_class, Class):
+                        # it's a method
+                        cur_class._addmethod(meth_name, lineno)
+                    # else it's a nested def
+                else:
+                    # it's a function
+                    dict[meth_name] = Function(fullmodule, meth_name,
+                                               fname, lineno)
+                stack.append((None, thisindent)) # Marker for nested fns
+            elif token == 'class':
+                lineno, thisindent = start
+                # close previous nested classes and defs
+                while stack and stack[-1][1] >= thisindent:
+                    del stack[-1]
+                tokentype, class_name, start = g.next()[0:3]
+                if tokentype != NAME:
+                    continue # Syntax error
+                # parse what follows the class name
+                tokentype, token, start = g.next()[0:3]
+                inherit = None
+                if token == '(':
+                    names = [] # List of superclasses
+                    # there's a list of superclasses
+                    level = 1
+                    super = [] # Tokens making up current superclass
+                    while True:
+                        tokentype, token, start = g.next()[0:3]
+                        if token in (')', ',') and level == 1:
+                            n = "".join(super)
+                            if n in dict:
+                                # we know this super class
+                                n = dict[n]
+                            else:
+                                c = n.split('.')
+                                if len(c) > 1:
+                                    # super class is of the form
+                                    # module.class: look in module for
+                                    # class
+                                    m = c[-2]
+                                    c = c[-1]
+                                    if m in _modules:
+                                        d = _modules[m]
+                                        if c in d:
+                                            n = d[c]
+                            names.append(n)
+                            super = []
+                        if token == '(':
+                            level += 1
+                        elif token == ')':
+                            level -= 1
+                            if level == 0:
+                                break
+                        elif token == ',' and level == 1:
+                            pass
+                        # only use NAME and OP (== dot) tokens for type name
+                        elif tokentype in (NAME, OP) and level == 1:
+                            super.append(token)
+                        # expressions in the base list are not supported
+                    inherit = names
+                cur_class = Class(fullmodule, class_name, inherit,
+                                  fname, lineno)
+                if not stack:
+                    dict[class_name] = cur_class
+                stack.append((cur_class, thisindent))
+            elif token == 'import' and start[1] == 0:
+                modules = _getnamelist(g)
+                for mod, _mod2 in modules:
+                    try:
+                        # Recursively read the imported module
+                        if inpackage is None:
+                            _readmodule(mod, path)
+                        else:
+                            try:
+                                _readmodule(mod, path, inpackage)
+                            except ImportError:
+                                _readmodule(mod, [])
+                    except:
+                        # If we can't find or parse the imported module,
+                        # too bad -- don't die here.
+                        pass
+            elif token == 'from' and start[1] == 0:
+                mod, token = _getname(g)
+                if not mod or token != "import":
+                    continue
+                names = _getnamelist(g)
+                try:
+                    # Recursively read the imported module
+                    d = _readmodule(mod, path, inpackage)
+                except:
+                    # If we can't find or parse the imported module,
+                    # too bad -- don't die here.
+                    continue
+                # add any classes that were defined in the imported module
+                # to our name space if they were mentioned in the list
+                for n, n2 in names:
+                    if n in d:
+                        dict[n2 or n] = d[n]
+                    elif n == '*':
+                        # don't add names that start with _
+                        for n in d:
+                            if n[0] != '_':
+                                dict[n] = d[n]
+    except StopIteration:
+        pass
+
+    f.close()
+    return dict
+
+def _getnamelist(g):
+    # Helper to get a comma-separated list of dotted names plus 'as'
+    # clauses.  Return a list of pairs (name, name2) where name2 is
+    # the 'as' name, or None if there is no 'as' clause.
+    names = []
+    while True:
+        name, token = _getname(g)
+        if not name:
+            break
+        if token == 'as':
+            name2, token = _getname(g)
+        else:
+            name2 = None
+        names.append((name, name2))
+        while token != "," and "\n" not in token:
+            token = g.next()[1]
+        if token != ",":
+            break
+    return names
+
+def _getname(g):
+    # Helper to get a dotted name, return a pair (name, token) where
+    # name is the dotted name, or None if there was no dotted name,
+    # and token is the next input token.
+    parts = []
+    tokentype, token = g.next()[0:2]
+    if tokentype != NAME and token != '*':
+        return (None, token)
+    parts.append(token)
+    while True:
+        tokentype, token = g.next()[0:2]
+        if token != '.':
+            break
+        tokentype, token = g.next()[0:2]
+        if tokentype != NAME:
+            break
+        parts.append(token)
+    return (".".join(parts), token)
+
+def _main():
+    # Main program for testing.
+    import os
+    mod = sys.argv[1]
+    if os.path.exists(mod):
+        path = [os.path.dirname(mod)]
+        mod = os.path.basename(mod)
+        if mod.lower().endswith(".py"):
+            mod = mod[:-3]
+    else:
+        path = []
+    dict = readmodule_ex(mod, path)
+    objs = dict.values()
+    objs.sort(lambda a, b: cmp(getattr(a, 'lineno', 0),
+                               getattr(b, 'lineno', 0)))
+    for obj in objs:
+        if isinstance(obj, Class):
+            print "class", obj.name, obj.super, obj.lineno
+            methods = sorted(obj.methods.iteritems(), key=itemgetter(1))
+            for name, lineno in methods:
+                if name != "__path__":
+                    print "  def", name, lineno
+        elif isinstance(obj, Function):
+            print "def", obj.name, obj.lineno
+
+if __name__ == "__main__":
+    _main()
diff --git a/src/main/resources/PythonLibs/pydoc.py b/src/main/resources/PythonLibs/pydoc.py
new file mode 100644
index 0000000000000000000000000000000000000000..265f6b0bf68b3ea17732d39389637d80d6208b1e
--- /dev/null
+++ b/src/main/resources/PythonLibs/pydoc.py
@@ -0,0 +1,2359 @@
+#!/usr/bin/env python
+# -*- coding: latin-1 -*-
+"""Generate Python documentation in HTML or text for interactive use.
+
+In the Python interpreter, do "from pydoc import help" to provide online
+help.  Calling help(thing) on a Python object documents the object.
+
+Or, at the shell command line outside of Python:
+
+Run "pydoc <name>" to show documentation on something.  <name> may be
+the name of a function, module, package, or a dotted reference to a
+class or function within a module or module in a package.  If the
+argument contains a path segment delimiter (e.g. slash on Unix,
+backslash on Windows) it is treated as the path to a Python source file.
+
+Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
+of all available modules.
+
+Run "pydoc -p <port>" to start an HTTP server on a given port on the
+local machine to generate documentation web pages.
+
+For platforms without a command line, "pydoc -g" starts the HTTP server
+and also pops up a little window for controlling it.
+
+Run "pydoc -w <name>" to write out the HTML documentation for a module
+to a file named "<name>.html".
+
+Module docs for core modules are assumed to be in
+
+    http://docs.python.org/library/
+
+This can be overridden by setting the PYTHONDOCS environment variable
+to a different URL or to a local directory containing the Library
+Reference Manual pages.
+"""
+
+__author__ = "Ka-Ping Yee <ping@lfw.org>"
+__date__ = "26 February 2001"
+
+__version__ = "$Revision: 88564 $"
+__credits__ = """Guido van Rossum, for an excellent programming language.
+Tommy Burnette, the original creator of manpy.
+Paul Prescod, for all his work on onlinehelp.
+Richard Chamberlain, for the first implementation of textdoc.
+"""
+
+# Known bugs that can't be fixed here:
+#   - imp.load_module() cannot be prevented from clobbering existing
+#     loaded modules, so calling synopsis() on a binary module file
+#     changes the contents of any existing module with the same name.
+#   - If the __file__ attribute on a module is a relative path and
+#     the current directory is changed with os.chdir(), an incorrect
+#     path will be displayed.
+
+import sys, imp, os, re, types, inspect, __builtin__, pkgutil, warnings
+from repr import Repr
+from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
+from traceback import extract_tb
+try:
+    from collections import deque
+except ImportError:
+    # Python 2.3 compatibility
+    class deque(list):
+        def popleft(self):
+            return self.pop(0)
+
+# --------------------------------------------------------- common routines
+
+def pathdirs():
+    """Convert sys.path into a list of absolute, existing, unique paths."""
+    dirs = []
+    normdirs = []
+    for dir in sys.path:
+        dir = os.path.abspath(dir or '.')
+        normdir = os.path.normcase(dir)
+        if normdir not in normdirs and os.path.isdir(dir):
+            dirs.append(dir)
+            normdirs.append(normdir)
+    return dirs
+
+def getdoc(object):
+    """Get the doc string or comments for an object."""
+    result = inspect.getdoc(object) or inspect.getcomments(object)
+    return result and re.sub('^ *\n', '', rstrip(result)) or ''
+
+def splitdoc(doc):
+    """Split a doc string into a synopsis line (if any) and the rest."""
+    lines = split(strip(doc), '\n')
+    if len(lines) == 1:
+        return lines[0], ''
+    elif len(lines) >= 2 and not rstrip(lines[1]):
+        return lines[0], join(lines[2:], '\n')
+    return '', join(lines, '\n')
+
+def classname(object, modname):
+    """Get a class name and qualify it with a module name if necessary."""
+    name = object.__name__
+    if object.__module__ != modname:
+        name = object.__module__ + '.' + name
+    return name
+
+def isdata(object):
+    """Check if an object is of a type that probably means it's data."""
+    return not (inspect.ismodule(object) or inspect.isclass(object) or
+                inspect.isroutine(object) or inspect.isframe(object) or
+                inspect.istraceback(object) or inspect.iscode(object))
+
+def replace(text, *pairs):
+    """Do a series of global replacements on a string."""
+    while pairs:
+        text = join(split(text, pairs[0]), pairs[1])
+        pairs = pairs[2:]
+    return text
+
+def cram(text, maxlen):
+    """Omit part of a string if needed to make it fit in a maximum length."""
+    if len(text) > maxlen:
+        pre = max(0, (maxlen-3)//2)
+        post = max(0, maxlen-3-pre)
+        return text[:pre] + '...' + text[len(text)-post:]
+    return text
+
+_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
+def stripid(text):
+    """Remove the hexadecimal id from a Python object representation."""
+    # The behaviour of %p is implementation-dependent in terms of case.
+    return _re_stripid.sub(r'\1', text)
+
+def _is_some_method(obj):
+    return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
+
+def allmethods(cl):
+    methods = {}
+    for key, value in inspect.getmembers(cl, _is_some_method):
+        methods[key] = 1
+    for base in cl.__bases__:
+        methods.update(allmethods(base)) # all your base are belong to us
+    for key in methods.keys():
+        methods[key] = getattr(cl, key)
+    return methods
+
+def _split_list(s, predicate):
+    """Split sequence s via predicate, and return pair ([true], [false]).
+
+    The return value is a 2-tuple of lists,
+        ([x for x in s if predicate(x)],
+         [x for x in s if not predicate(x)])
+    """
+
+    yes = []
+    no = []
+    for x in s:
+        if predicate(x):
+            yes.append(x)
+        else:
+            no.append(x)
+    return yes, no
+
+def visiblename(name, all=None, obj=None):
+    """Decide whether to show documentation on a variable."""
+    # Certain special names are redundant.
+    _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
+                     '__module__', '__name__', '__slots__', '__package__')
+    if name in _hidden_names: return 0
+    # Private names are hidden, but special names are displayed.
+    if name.startswith('__') and name.endswith('__'): return 1
+    # Namedtuples have public fields and methods with a single leading underscore
+    if name.startswith('_') and hasattr(obj, '_fields'):
+        return 1
+    if all is not None:
+        # only document that which the programmer exported in __all__
+        return name in all
+    else:
+        return not name.startswith('_')
+
+def classify_class_attrs(object):
+    """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
+    def fixup(data):
+        name, kind, cls, value = data
+        if inspect.isdatadescriptor(value):
+            kind = 'data descriptor'
+        return name, kind, cls, value
+    return map(fixup, inspect.classify_class_attrs(object))
+
+# ----------------------------------------------------- module manipulation
+
+def ispackage(path):
+    """Guess whether a path refers to a package directory."""
+    if os.path.isdir(path):
+        for ext in ('.py', '.pyc', '.pyo', '$py.class'):
+            if os.path.isfile(os.path.join(path, '__init__' + ext)):
+                return True
+    return False
+
+def source_synopsis(file):
+    line = file.readline()
+    while line[:1] == '#' or not strip(line):
+        line = file.readline()
+        if not line: break
+    line = strip(line)
+    if line[:4] == 'r"""': line = line[1:]
+    if line[:3] == '"""':
+        line = line[3:]
+        if line[-1:] == '\\': line = line[:-1]
+        while not strip(line):
+            line = file.readline()
+            if not line: break
+        result = strip(split(line, '"""')[0])
+    else: result = None
+    return result
+
+def synopsis(filename, cache={}):
+    """Get the one-line summary out of a module file."""
+    mtime = os.stat(filename).st_mtime
+    lastupdate, result = cache.get(filename, (None, None))
+    if lastupdate is None or lastupdate < mtime:
+        info = inspect.getmoduleinfo(filename)
+        try:
+            file = open(filename)
+        except IOError:
+            # module can't be opened, so skip it
+            return None
+        if info and 'b' in info[2]: # binary modules have to be imported
+            try: module = imp.load_module('__temp__', file, filename, info[1:])
+            except: return None
+            result = (module.__doc__ or '').splitlines()[0]
+            del sys.modules['__temp__']
+        else: # text modules can be directly examined
+            result = source_synopsis(file)
+            file.close()
+        cache[filename] = (mtime, result)
+    return result
+
+class ErrorDuringImport(Exception):
+    """Errors that occurred while trying to import something to document it."""
+    def __init__(self, filename, exc_info):
+        exc, value, tb = exc_info
+        self.filename = filename
+        self.exc = exc
+        self.value = value
+        self.tb = tb
+
+    def __str__(self):
+        exc = self.exc
+        if type(exc) is types.ClassType:
+            exc = exc.__name__
+        return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
+
+def importfile(path):
+    """Import a Python source file or compiled file given its path."""
+    magic = imp.get_magic()
+    file = open(path, 'r')
+    if file.read(len(magic)) == magic:
+        kind = imp.PY_COMPILED
+    else:
+        kind = imp.PY_SOURCE
+    file.close()
+    filename = os.path.basename(path)
+    name, ext = os.path.splitext(filename)
+    file = open(path, 'r')
+    try:
+        module = imp.load_module(name, file, path, (ext, 'r', kind))
+    except:
+        raise ErrorDuringImport(path, sys.exc_info())
+    file.close()
+    return module
+
+def safeimport(path, forceload=0, cache={}):
+    """Import a module; handle errors; return None if the module isn't found.
+
+    If the module *is* found but an exception occurs, it's wrapped in an
+    ErrorDuringImport exception and reraised.  Unlike __import__, if a
+    package path is specified, the module at the end of the path is returned,
+    not the package at the beginning.  If the optional 'forceload' argument
+    is 1, we reload the module from disk (unless it's a dynamic extension)."""
+    try:
+        # If forceload is 1 and the module has been previously loaded from
+        # disk, we always have to reload the module.  Checking the file's
+        # mtime isn't good enough (e.g. the module could contain a class
+        # that inherits from another module that has changed).
+        if forceload and path in sys.modules:
+            if path not in sys.builtin_module_names:
+                # Avoid simply calling reload() because it leaves names in
+                # the currently loaded module lying around if they're not
+                # defined in the new source file.  Instead, remove the
+                # module from sys.modules and re-import.  Also remove any
+                # submodules because they won't appear in the newly loaded
+                # module's namespace if they're already in sys.modules.
+                subs = [m for m in sys.modules if m.startswith(path + '.')]
+                for key in [path] + subs:
+                    # Prevent garbage collection.
+                    cache[key] = sys.modules[key]
+                    del sys.modules[key]
+        module = __import__(path)
+    except:
+        # Did the error occur before or after the module was found?
+        (exc, value, tb) = info = sys.exc_info()
+        if path in sys.modules:
+            # An error occurred while executing the imported module.
+            raise ErrorDuringImport(sys.modules[path].__file__, info)
+        elif exc is SyntaxError:
+            # A SyntaxError occurred before we could execute the module.
+            raise ErrorDuringImport(value.filename, info)
+        elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
+            # The import error occurred directly in this function,
+            # which means there is no such module in the path.
+            return None
+        else:
+            # Some other error occurred during the importing process.
+            raise ErrorDuringImport(path, sys.exc_info())
+    for part in split(path, '.')[1:]:
+        try: module = getattr(module, part)
+        except AttributeError: return None
+    return module
+
+# ---------------------------------------------------- formatter base class
+
+class Doc:
+    def document(self, object, name=None, *args):
+        """Generate documentation for an object."""
+        args = (object, name) + args
+        # 'try' clause is to attempt to handle the possibility that inspect
+        # identifies something in a way that pydoc itself has issues handling;
+        # think 'super' and how it is a descriptor (which raises the exception
+        # by lacking a __name__ attribute) and an instance.
+        if inspect.isgetsetdescriptor(object): return self.docdata(*args)
+        if inspect.ismemberdescriptor(object): return self.docdata(*args)
+        try:
+            if inspect.ismodule(object): return self.docmodule(*args)
+            if inspect.isclass(object): return self.docclass(*args)
+            if inspect.isroutine(object): return self.docroutine(*args)
+        except AttributeError:
+            pass
+        if isinstance(object, property): return self.docproperty(*args)
+        return self.docother(*args)
+
+    def fail(self, object, name=None, *args):
+        """Raise an exception for unimplemented types."""
+        message = "don't know how to document object%s of type %s" % (
+            name and ' ' + repr(name), type(object).__name__)
+        raise TypeError, message
+
+    docmodule = docclass = docroutine = docother = docproperty = docdata = fail
+
+    def getdocloc(self, object):
+        """Return the location of module docs or None"""
+
+        try:
+            file = inspect.getabsfile(object)
+        except TypeError:
+            file = '(built-in)'
+
+        docloc = os.environ.get("PYTHONDOCS",
+                                "http://docs.python.org/library")
+        basedir = os.path.join(sys.exec_prefix, "lib",
+                               "python"+sys.version[0:3])
+        if (isinstance(object, type(os)) and
+            (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
+                                 'marshal', 'posix', 'signal', 'sys',
+                                 'thread', 'zipimport') or
+             (file.startswith(basedir) and
+              not file.startswith(os.path.join(basedir, 'site-packages')))) and
+            object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
+            if docloc.startswith("http://"):
+                docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
+            else:
+                docloc = os.path.join(docloc, object.__name__ + ".html")
+        else:
+            docloc = None
+        return docloc
+
+# -------------------------------------------- HTML documentation generator
+
+class HTMLRepr(Repr):
+    """Class for safely making an HTML representation of a Python object."""
+    def __init__(self):
+        Repr.__init__(self)
+        self.maxlist = self.maxtuple = 20
+        self.maxdict = 10
+        self.maxstring = self.maxother = 100
+
+    def escape(self, text):
+        return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
+
+    def repr(self, object):
+        return Repr.repr(self, object)
+
+    def repr1(self, x, level):
+        if hasattr(type(x), '__name__'):
+            methodname = 'repr_' + join(split(type(x).__name__), '_')
+            if hasattr(self, methodname):
+                return getattr(self, methodname)(x, level)
+        return self.escape(cram(stripid(repr(x)), self.maxother))
+
+    def repr_string(self, x, level):
+        test = cram(x, self.maxstring)
+        testrepr = repr(test)
+        if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
+            # Backslashes are only literal in the string and are never
+            # needed to make any special characters, so show a raw string.
+            return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
+        return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
+                      r'<font color="#c040c0">\1</font>',
+                      self.escape(testrepr))
+
+    repr_str = repr_string
+
+    def repr_instance(self, x, level):
+        try:
+            return self.escape(cram(stripid(repr(x)), self.maxstring))
+        except:
+            return self.escape('<%s instance>' % x.__class__.__name__)
+
+    repr_unicode = repr_string
+
+class HTMLDoc(Doc):
+    """Formatter class for HTML documentation."""
+
+    # ------------------------------------------- HTML formatting utilities
+
+    _repr_instance = HTMLRepr()
+    repr = _repr_instance.repr
+    escape = _repr_instance.escape
+
+    def page(self, title, contents):
+        """Format an HTML page."""
+        return '''
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: %s</title>
+</head><body bgcolor="#f0f0f8">
+%s
+</body></html>''' % (title, contents)
+
+    def heading(self, title, fgcol, bgcol, extras=''):
+        """Format a page heading."""
+        return '''
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="%s">
+<td valign=bottom>&nbsp;<br>
+<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
+><td align=right valign=bottom
+><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
+    ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
+
+    def section(self, title, fgcol, bgcol, contents, width=6,
+                prelude='', marginalia=None, gap='&nbsp;'):
+        """Format a section with a heading."""
+        if marginalia is None:
+            marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
+        result = '''<p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="%s">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="%s" face="helvetica, arial">%s</font></td></tr>
+    ''' % (bgcol, fgcol, title)
+        if prelude:
+            result = result + '''
+<tr bgcolor="%s"><td rowspan=2>%s</td>
+<td colspan=2>%s</td></tr>
+<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
+        else:
+            result = result + '''
+<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
+
+        return result + '\n<td width="100%%">%s</td></tr></table>' % contents
+
+    def bigsection(self, title, *args):
+        """Format a section with a big heading."""
+        title = '<big><strong>%s</strong></big>' % title
+        return self.section(title, *args)
+
+    def preformat(self, text):
+        """Format literal preformatted text."""
+        text = self.escape(expandtabs(text))
+        return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
+                             ' ', '&nbsp;', '\n', '<br>\n')
+
+    def multicolumn(self, list, format, cols=4):
+        """Format a list of items into a multi-column list."""
+        result = ''
+        rows = (len(list)+cols-1)//cols
+        for col in range(cols):
+            result = result + '<td width="%d%%" valign=top>' % (100//cols)
+            for i in range(rows*col, rows*col+rows):
+                if i < len(list):
+                    result = result + format(list[i]) + '<br>\n'
+            result = result + '</td>'
+        return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
+
+    def grey(self, text): return '<font color="#909090">%s</font>' % text
+
+    def namelink(self, name, *dicts):
+        """Make a link for an identifier, given name-to-URL mappings."""
+        for dict in dicts:
+            if name in dict:
+                return '<a href="%s">%s</a>' % (dict[name], name)
+        return name
+
+    def classlink(self, object, modname):
+        """Make a link for a class."""
+        name, module = object.__name__, sys.modules.get(object.__module__)
+        if hasattr(module, name) and getattr(module, name) is object:
+            return '<a href="%s.html#%s">%s</a>' % (
+                module.__name__, name, classname(object, modname))
+        return classname(object, modname)
+
+    def modulelink(self, object):
+        """Make a link for a module."""
+        return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
+
+    def modpkglink(self, data):
+        """Make a link for a module or package to display in an index."""
+        name, path, ispackage, shadowed = data
+        if shadowed:
+            return self.grey(name)
+        if path:
+            url = '%s.%s.html' % (path, name)
+        else:
+            url = '%s.html' % name
+        if ispackage:
+            text = '<strong>%s</strong>&nbsp;(package)' % name
+        else:
+            text = name
+        return '<a href="%s">%s</a>' % (url, text)
+
+    def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
+        """Mark up some plain text, given a context of symbols to look for.
+        Each context dictionary maps object names to anchor names."""
+        escape = escape or self.escape
+        results = []
+        here = 0
+        pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
+                                r'RFC[- ]?(\d+)|'
+                                r'PEP[- ]?(\d+)|'
+                                r'(self\.)?(\w+))')
+        while True:
+            match = pattern.search(text, here)
+            if not match: break
+            start, end = match.span()
+            results.append(escape(text[here:start]))
+
+            all, scheme, rfc, pep, selfdot, name = match.groups()
+            if scheme:
+                url = escape(all).replace('"', '&quot;')
+                results.append('<a href="%s">%s</a>' % (url, url))
+            elif rfc:
+                url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
+                results.append('<a href="%s">%s</a>' % (url, escape(all)))
+            elif pep:
+                url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
+                results.append('<a href="%s">%s</a>' % (url, escape(all)))
+            elif text[end:end+1] == '(':
+                results.append(self.namelink(name, methods, funcs, classes))
+            elif selfdot:
+                results.append('self.<strong>%s</strong>' % name)
+            else:
+                results.append(self.namelink(name, classes))
+            here = end
+        results.append(escape(text[here:]))
+        return join(results, '')
+
+    # ---------------------------------------------- type-specific routines
+
+    def formattree(self, tree, modname, parent=None):
+        """Produce HTML for a class tree as given by inspect.getclasstree()."""
+        result = ''
+        for entry in tree:
+            if type(entry) is type(()):
+                c, bases = entry
+                result = result + '<dt><font face="helvetica, arial">'
+                result = result + self.classlink(c, modname)
+                if bases and bases != (parent,):
+                    parents = []
+                    for base in bases:
+                        parents.append(self.classlink(base, modname))
+                    result = result + '(' + join(parents, ', ') + ')'
+                result = result + '\n</font></dt>'
+            elif type(entry) is type([]):
+                result = result + '<dd>\n%s</dd>\n' % self.formattree(
+                    entry, modname, c)
+        return '<dl>\n%s</dl>\n' % result
+
+    def docmodule(self, object, name=None, mod=None, *ignored):
+        """Produce HTML documentation for a module object."""
+        name = object.__name__ # ignore the passed-in name
+        try:
+            all = object.__all__
+        except AttributeError:
+            all = None
+        parts = split(name, '.')
+        links = []
+        for i in range(len(parts)-1):
+            links.append(
+                '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
+                (join(parts[:i+1], '.'), parts[i]))
+        linkedname = join(links + parts[-1:], '.')
+        head = '<big><big><strong>%s</strong></big></big>' % linkedname
+        try:
+            path = inspect.getabsfile(object)
+            url = path
+            if sys.platform == 'win32':
+                import nturl2path
+                url = nturl2path.pathname2url(path)
+            filelink = '<a href="file:%s">%s</a>' % (url, path)
+        except TypeError:
+            filelink = '(built-in)'
+        info = []
+        if hasattr(object, '__version__'):
+            version = str(object.__version__)
+            if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
+                version = strip(version[11:-1])
+            info.append('version %s' % self.escape(version))
+        if hasattr(object, '__date__'):
+            info.append(self.escape(str(object.__date__)))
+        if info:
+            head = head + ' (%s)' % join(info, ', ')
+        docloc = self.getdocloc(object)
+        if docloc is not None:
+            docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
+        else:
+            docloc = ''
+        result = self.heading(
+            head, '#ffffff', '#7799ee',
+            '<a href=".">index</a><br>' + filelink + docloc)
+
+        modules = inspect.getmembers(object, inspect.ismodule)
+
+        classes, cdict = [], {}
+        for key, value in inspect.getmembers(object, inspect.isclass):
+            # if __all__ exists, believe it.  Otherwise use old heuristic.
+            if (all is not None or
+                (inspect.getmodule(value) or object) is object):
+                if visiblename(key, all, object):
+                    classes.append((key, value))
+                    cdict[key] = cdict[value] = '#' + key
+        for key, value in classes:
+            for base in value.__bases__:
+                key, modname = base.__name__, base.__module__
+                module = sys.modules.get(modname)
+                if modname != name and module and hasattr(module, key):
+                    if getattr(module, key) is base:
+                        if not key in cdict:
+                            cdict[key] = cdict[base] = modname + '.html#' + key
+        funcs, fdict = [], {}
+        for key, value in inspect.getmembers(object, inspect.isroutine):
+            # if __all__ exists, believe it.  Otherwise use old heuristic.
+            if (all is not None or
+                inspect.isbuiltin(value) or inspect.getmodule(value) is object):
+                if visiblename(key, all, object):
+                    funcs.append((key, value))
+                    fdict[key] = '#-' + key
+                    if inspect.isfunction(value): fdict[value] = fdict[key]
+        data = []
+        for key, value in inspect.getmembers(object, isdata):
+            if visiblename(key, all, object):
+                data.append((key, value))
+
+        doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
+        doc = doc and '<tt>%s</tt>' % doc
+        result = result + '<p>%s</p>\n' % doc
+
+        if hasattr(object, '__path__'):
+            modpkgs = []
+            for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
+                modpkgs.append((modname, name, ispkg, 0))
+            modpkgs.sort()
+            contents = self.multicolumn(modpkgs, self.modpkglink)
+            result = result + self.bigsection(
+                'Package Contents', '#ffffff', '#aa55cc', contents)
+        elif modules:
+            contents = self.multicolumn(
+                modules, lambda key_value, s=self: s.modulelink(key_value[1]))
+            result = result + self.bigsection(
+                'Modules', '#ffffff', '#aa55cc', contents)
+
+        if classes:
+            classlist = map(lambda key_value: key_value[1], classes)
+            contents = [
+                self.formattree(inspect.getclasstree(classlist, 1), name)]
+            for key, value in classes:
+                contents.append(self.document(value, key, name, fdict, cdict))
+            result = result + self.bigsection(
+                'Classes', '#ffffff', '#ee77aa', join(contents))
+        if funcs:
+            contents = []
+            for key, value in funcs:
+                contents.append(self.document(value, key, name, fdict, cdict))
+            result = result + self.bigsection(
+                'Functions', '#ffffff', '#eeaa77', join(contents))
+        if data:
+            contents = []
+            for key, value in data:
+                contents.append(self.document(value, key))
+            result = result + self.bigsection(
+                'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
+        if hasattr(object, '__author__'):
+            contents = self.markup(str(object.__author__), self.preformat)
+            result = result + self.bigsection(
+                'Author', '#ffffff', '#7799ee', contents)
+        if hasattr(object, '__credits__'):
+            contents = self.markup(str(object.__credits__), self.preformat)
+            result = result + self.bigsection(
+                'Credits', '#ffffff', '#7799ee', contents)
+
+        return result
+
+    def docclass(self, object, name=None, mod=None, funcs={}, classes={},
+                 *ignored):
+        """Produce HTML documentation for a class object."""
+        realname = object.__name__
+        name = name or realname
+        bases = object.__bases__
+
+        contents = []
+        push = contents.append
+
+        # Cute little class to pump out a horizontal rule between sections.
+        class HorizontalRule:
+            def __init__(self):
+                self.needone = 0
+            def maybe(self):
+                if self.needone:
+                    push('<hr>\n')
+                self.needone = 1
+        hr = HorizontalRule()
+
+        # List the mro, if non-trivial.
+        mro = deque(inspect.getmro(object))
+        if len(mro) > 2:
+            hr.maybe()
+            push('<dl><dt>Method resolution order:</dt>\n')
+            for base in mro:
+                push('<dd>%s</dd>\n' % self.classlink(base,
+                                                      object.__module__))
+            push('</dl>\n')
+
+        def spill(msg, attrs, predicate):
+            ok, attrs = _split_list(attrs, predicate)
+            if ok:
+                hr.maybe()
+                push(msg)
+                for name, kind, homecls, value in ok:
+                    try:
+                        value = getattr(object, name)
+                    except Exception:
+                        # Some descriptors may meet a failure in their __get__.
+                        # (bug #1785)
+                        push(self._docdescriptor(name, value, mod))
+                    else:
+                        push(self.document(value, name, mod,
+                                        funcs, classes, mdict, object))
+                    push('\n')
+            return attrs
+
+        def spilldescriptors(msg, attrs, predicate):
+            ok, attrs = _split_list(attrs, predicate)
+            if ok:
+                hr.maybe()
+                push(msg)
+                for name, kind, homecls, value in ok:
+                    push(self._docdescriptor(name, value, mod))
+            return attrs
+
+        def spilldata(msg, attrs, predicate):
+            ok, attrs = _split_list(attrs, predicate)
+            if ok:
+                hr.maybe()
+                push(msg)
+                for name, kind, homecls, value in ok:
+                    base = self.docother(getattr(object, name), name, mod)
+                    if (hasattr(value, '__call__') or
+                            inspect.isdatadescriptor(value)):
+                        doc = getattr(value, "__doc__", None)
+                    else:
+                        doc = None
+                    if doc is None:
+                        push('<dl><dt>%s</dl>\n' % base)
+                    else:
+                        doc = self.markup(getdoc(value), self.preformat,
+                                          funcs, classes, mdict)
+                        doc = '<dd><tt>%s</tt>' % doc
+                        push('<dl><dt>%s%s</dl>\n' % (base, doc))
+                    push('\n')
+            return attrs
+
+        attrs = filter(lambda data: visiblename(data[0], obj=object),
+                       classify_class_attrs(object))
+        mdict = {}
+        for key, kind, homecls, value in attrs:
+            mdict[key] = anchor = '#' + name + '-' + key
+            try:
+                value = getattr(object, name)
+            except Exception:
+                # Some descriptors may meet a failure in their __get__.
+                # (bug #1785)
+                pass
+            try:
+                # The value may not be hashable (e.g., a data attr with
+                # a dict or list value).
+                mdict[value] = anchor
+            except TypeError:
+                pass
+
+        while attrs:
+            if mro:
+                thisclass = mro.popleft()
+            else:
+                thisclass = attrs[0][2]
+            attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
+
+            if thisclass is __builtin__.object:
+                attrs = inherited
+                continue
+            elif thisclass is object:
+                tag = 'defined here'
+            else:
+                tag = 'inherited from %s' % self.classlink(thisclass,
+                                                           object.__module__)
+            tag += ':<br>\n'
+
+            # Sort attrs by name.
+            try:
+                attrs.sort(key=lambda t: t[0])
+            except TypeError:
+                attrs.sort(lambda t1, t2: cmp(t1[0], t2[0]))    # 2.3 compat
+
+            # Pump out the attrs, segregated by kind.
+            attrs = spill('Methods %s' % tag, attrs,
+                          lambda t: t[1] == 'method')
+            attrs = spill('Class methods %s' % tag, attrs,
+                          lambda t: t[1] == 'class method')
+            attrs = spill('Static methods %s' % tag, attrs,
+                          lambda t: t[1] == 'static method')
+            attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
+                                     lambda t: t[1] == 'data descriptor')
+            attrs = spilldata('Data and other attributes %s' % tag, attrs,
+                              lambda t: t[1] == 'data')
+            assert attrs == []
+            attrs = inherited
+
+        contents = ''.join(contents)
+
+        if name == realname:
+            title = '<a name="%s">class <strong>%s</strong></a>' % (
+                name, realname)
+        else:
+            title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
+                name, name, realname)
+        if bases:
+            parents = []
+            for base in bases:
+                parents.append(self.classlink(base, object.__module__))
+            title = title + '(%s)' % join(parents, ', ')
+        doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
+        doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
+
+        return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
+
+    def formatvalue(self, object):
+        """Format an argument default value as text."""
+        return self.grey('=' + self.repr(object))
+
+    def docroutine(self, object, name=None, mod=None,
+                   funcs={}, classes={}, methods={}, cl=None):
+        """Produce HTML documentation for a function or method object."""
+        realname = object.__name__
+        name = name or realname
+        anchor = (cl and cl.__name__ or '') + '-' + name
+        note = ''
+        skipdocs = 0
+        if inspect.ismethod(object):
+            imclass = object.im_class
+            if cl:
+                if imclass is not cl:
+                    note = ' from ' + self.classlink(imclass, mod)
+            else:
+                if object.im_self is not None:
+                    note = ' method of %s instance' % self.classlink(
+                        object.im_self.__class__, mod)
+                else:
+                    note = ' unbound %s method' % self.classlink(imclass,mod)
+            object = object.im_func
+
+        if name == realname:
+            title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
+        else:
+            if (cl and realname in cl.__dict__ and
+                cl.__dict__[realname] is object):
+                reallink = '<a href="#%s">%s</a>' % (
+                    cl.__name__ + '-' + realname, realname)
+                skipdocs = 1
+            else:
+                reallink = realname
+            title = '<a name="%s"><strong>%s</strong></a> = %s' % (
+                anchor, name, reallink)
+        if inspect.isfunction(object):
+            args, varargs, varkw, defaults = inspect.getargspec(object)
+            argspec = inspect.formatargspec(
+                args, varargs, varkw, defaults, formatvalue=self.formatvalue)
+            if realname == '<lambda>':
+                title = '<strong>%s</strong> <em>lambda</em> ' % name
+                argspec = argspec[1:-1] # remove parentheses
+        else:
+            argspec = '(...)'
+
+        decl = title + argspec + (note and self.grey(
+               '<font face="helvetica, arial">%s</font>' % note))
+
+        if skipdocs:
+            return '<dl><dt>%s</dt></dl>\n' % decl
+        else:
+            doc = self.markup(
+                getdoc(object), self.preformat, funcs, classes, methods)
+            doc = doc and '<dd><tt>%s</tt></dd>' % doc
+            return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
+
+    def _docdescriptor(self, name, value, mod):
+        results = []
+        push = results.append
+
+        if name:
+            push('<dl><dt><strong>%s</strong></dt>\n' % name)
+        if value.__doc__ is not None:
+            doc = self.markup(getdoc(value), self.preformat)
+            push('<dd><tt>%s</tt></dd>\n' % doc)
+        push('</dl>\n')
+
+        return ''.join(results)
+
+    def docproperty(self, object, name=None, mod=None, cl=None):
+        """Produce html documentation for a property."""
+        return self._docdescriptor(name, object, mod)
+
+    def docother(self, object, name=None, mod=None, *ignored):
+        """Produce HTML documentation for a data object."""
+        lhs = name and '<strong>%s</strong> = ' % name or ''
+        return lhs + self.repr(object)
+
+    def docdata(self, object, name=None, mod=None, cl=None):
+        """Produce html documentation for a data descriptor."""
+        return self._docdescriptor(name, object, mod)
+
+    def index(self, dir, shadowed=None):
+        """Generate an HTML index for a directory of modules."""
+        modpkgs = []
+        if shadowed is None: shadowed = {}
+        for importer, name, ispkg in pkgutil.iter_modules([dir]):
+            modpkgs.append((name, '', ispkg, name in shadowed))
+            shadowed[name] = 1
+
+        modpkgs.sort()
+        contents = self.multicolumn(modpkgs, self.modpkglink)
+        return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
+
+# -------------------------------------------- text documentation generator
+
+class TextRepr(Repr):
+    """Class for safely making a text representation of a Python object."""
+    def __init__(self):
+        Repr.__init__(self)
+        self.maxlist = self.maxtuple = 20
+        self.maxdict = 10
+        self.maxstring = self.maxother = 100
+
+    def repr1(self, x, level):
+        if hasattr(type(x), '__name__'):
+            methodname = 'repr_' + join(split(type(x).__name__), '_')
+            if hasattr(self, methodname):
+                return getattr(self, methodname)(x, level)
+        return cram(stripid(repr(x)), self.maxother)
+
+    def repr_string(self, x, level):
+        test = cram(x, self.maxstring)
+        testrepr = repr(test)
+        if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
+            # Backslashes are only literal in the string and are never
+            # needed to make any special characters, so show a raw string.
+            return 'r' + testrepr[0] + test + testrepr[0]
+        return testrepr
+
+    repr_str = repr_string
+
+    def repr_instance(self, x, level):
+        try:
+            return cram(stripid(repr(x)), self.maxstring)
+        except:
+            return '<%s instance>' % x.__class__.__name__
+
+class TextDoc(Doc):
+    """Formatter class for text documentation."""
+
+    # ------------------------------------------- text formatting utilities
+
+    _repr_instance = TextRepr()
+    repr = _repr_instance.repr
+
+    def bold(self, text):
+        """Format a string in bold by overstriking."""
+        return join(map(lambda ch: ch + '\b' + ch, text), '')
+
+    def indent(self, text, prefix='    '):
+        """Indent text by prepending a given prefix to each line."""
+        if not text: return ''
+        lines = split(text, '\n')
+        lines = map(lambda line, prefix=prefix: prefix + line, lines)
+        if lines: lines[-1] = rstrip(lines[-1])
+        return join(lines, '\n')
+
+    def section(self, title, contents):
+        """Format a section with a given heading."""
+        return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
+
+    # ---------------------------------------------- type-specific routines
+
+    def formattree(self, tree, modname, parent=None, prefix=''):
+        """Render in text a class tree as returned by inspect.getclasstree()."""
+        result = ''
+        for entry in tree:
+            if type(entry) is type(()):
+                c, bases = entry
+                result = result + prefix + classname(c, modname)
+                if bases and bases != (parent,):
+                    parents = map(lambda c, m=modname: classname(c, m), bases)
+                    result = result + '(%s)' % join(parents, ', ')
+                result = result + '\n'
+            elif type(entry) is type([]):
+                result = result + self.formattree(
+                    entry, modname, c, prefix + '    ')
+        return result
+
+    def docmodule(self, object, name=None, mod=None):
+        """Produce text documentation for a given module object."""
+        name = object.__name__ # ignore the passed-in name
+        synop, desc = splitdoc(getdoc(object))
+        result = self.section('NAME', name + (synop and ' - ' + synop))
+
+        try:
+            all = object.__all__
+        except AttributeError:
+            all = None
+
+        try:
+            file = inspect.getabsfile(object)
+        except TypeError:
+            file = '(built-in)'
+        result = result + self.section('FILE', file)
+
+        docloc = self.getdocloc(object)
+        if docloc is not None:
+            result = result + self.section('MODULE DOCS', docloc)
+
+        if desc:
+            result = result + self.section('DESCRIPTION', desc)
+
+        classes = []
+        for key, value in inspect.getmembers(object, inspect.isclass):
+            # if __all__ exists, believe it.  Otherwise use old heuristic.
+            if (all is not None
+                or (inspect.getmodule(value) or object) is object):
+                if visiblename(key, all, object):
+                    classes.append((key, value))
+        funcs = []
+        for key, value in inspect.getmembers(object, inspect.isroutine):
+            # if __all__ exists, believe it.  Otherwise use old heuristic.
+            if (all is not None or
+                inspect.isbuiltin(value) or inspect.getmodule(value) is object):
+                if visiblename(key, all, object):
+                    funcs.append((key, value))
+        data = []
+        for key, value in inspect.getmembers(object, isdata):
+            if visiblename(key, all, object):
+                data.append((key, value))
+
+        modpkgs = []
+        modpkgs_names = set()
+        if hasattr(object, '__path__'):
+            for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
+                modpkgs_names.add(modname)
+                if ispkg:
+                    modpkgs.append(modname + ' (package)')
+                else:
+                    modpkgs.append(modname)
+
+            modpkgs.sort()
+            result = result + self.section(
+                'PACKAGE CONTENTS', join(modpkgs, '\n'))
+
+        # Detect submodules as sometimes created by C extensions
+        submodules = []
+        for key, value in inspect.getmembers(object, inspect.ismodule):
+            if value.__name__.startswith(name + '.') and key not in modpkgs_names:
+                submodules.append(key)
+        if submodules:
+            submodules.sort()
+            result = result + self.section(
+                'SUBMODULES', join(submodules, '\n'))
+
+        if classes:
+            classlist = map(lambda key_value: key_value[1], classes)
+            contents = [self.formattree(
+                inspect.getclasstree(classlist, 1), name)]
+            for key, value in classes:
+                contents.append(self.document(value, key, name))
+            result = result + self.section('CLASSES', join(contents, '\n'))
+
+        if funcs:
+            contents = []
+            for key, value in funcs:
+                contents.append(self.document(value, key, name))
+            result = result + self.section('FUNCTIONS', join(contents, '\n'))
+
+        if data:
+            contents = []
+            for key, value in data:
+                contents.append(self.docother(value, key, name, maxlen=70))
+            result = result + self.section('DATA', join(contents, '\n'))
+
+        if hasattr(object, '__version__'):
+            version = str(object.__version__)
+            if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
+                version = strip(version[11:-1])
+            result = result + self.section('VERSION', version)
+        if hasattr(object, '__date__'):
+            result = result + self.section('DATE', str(object.__date__))
+        if hasattr(object, '__author__'):
+            result = result + self.section('AUTHOR', str(object.__author__))
+        if hasattr(object, '__credits__'):
+            result = result + self.section('CREDITS', str(object.__credits__))
+        return result
+
+    def docclass(self, object, name=None, mod=None, *ignored):
+        """Produce text documentation for a given class object."""
+        realname = object.__name__
+        name = name or realname
+        bases = object.__bases__
+
+        def makename(c, m=object.__module__):
+            return classname(c, m)
+
+        if name == realname:
+            title = 'class ' + self.bold(realname)
+        else:
+            title = self.bold(name) + ' = class ' + realname
+        if bases:
+            parents = map(makename, bases)
+            title = title + '(%s)' % join(parents, ', ')
+
+        doc = getdoc(object)
+        contents = doc and [doc + '\n'] or []
+        push = contents.append
+
+        # List the mro, if non-trivial.
+        mro = deque(inspect.getmro(object))
+        if len(mro) > 2:
+            push("Method resolution order:")
+            for base in mro:
+                push('    ' + makename(base))
+            push('')
+
+        # Cute little class to pump out a horizontal rule between sections.
+        class HorizontalRule:
+            def __init__(self):
+                self.needone = 0
+            def maybe(self):
+                if self.needone:
+                    push('-' * 70)
+                self.needone = 1
+        hr = HorizontalRule()
+
+        def spill(msg, attrs, predicate):
+            ok, attrs = _split_list(attrs, predicate)
+            if ok:
+                hr.maybe()
+                push(msg)
+                for name, kind, homecls, value in ok:
+                    try:
+                        value = getattr(object, name)
+                    except Exception:
+                        # Some descriptors may meet a failure in their __get__.
+                        # (bug #1785)
+                        push(self._docdescriptor(name, value, mod))
+                    else:
+                        push(self.document(value,
+                                        name, mod, object))
+            return attrs
+
+        def spilldescriptors(msg, attrs, predicate):
+            ok, attrs = _split_list(attrs, predicate)
+            if ok:
+                hr.maybe()
+                push(msg)
+                for name, kind, homecls, value in ok:
+                    push(self._docdescriptor(name, value, mod))
+            return attrs
+
+        def spilldata(msg, attrs, predicate):
+            ok, attrs = _split_list(attrs, predicate)
+            if ok:
+                hr.maybe()
+                push(msg)
+                for name, kind, homecls, value in ok:
+                    if (hasattr(value, '__call__') or
+                            inspect.isdatadescriptor(value)):
+                        doc = getdoc(value)
+                    else:
+                        doc = None
+                    push(self.docother(getattr(object, name),
+                                       name, mod, maxlen=70, doc=doc) + '\n')
+            return attrs
+
+        attrs = filter(lambda data: visiblename(data[0], obj=object),
+                       classify_class_attrs(object))
+        while attrs:
+            if mro:
+                thisclass = mro.popleft()
+            else:
+                thisclass = attrs[0][2]
+            attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
+
+            if thisclass is __builtin__.object:
+                attrs = inherited
+                continue
+            elif thisclass is object:
+                tag = "defined here"
+            else:
+                tag = "inherited from %s" % classname(thisclass,
+                                                      object.__module__)
+
+            # Sort attrs by name.
+            attrs.sort()
+
+            # Pump out the attrs, segregated by kind.
+            attrs = spill("Methods %s:\n" % tag, attrs,
+                          lambda t: t[1] == 'method')
+            attrs = spill("Class methods %s:\n" % tag, attrs,
+                          lambda t: t[1] == 'class method')
+            attrs = spill("Static methods %s:\n" % tag, attrs,
+                          lambda t: t[1] == 'static method')
+            attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
+                                     lambda t: t[1] == 'data descriptor')
+            attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
+                              lambda t: t[1] == 'data')
+            assert attrs == []
+            attrs = inherited
+
+        contents = '\n'.join(contents)
+        if not contents:
+            return title + '\n'
+        return title + '\n' + self.indent(rstrip(contents), ' |  ') + '\n'
+
+    def formatvalue(self, object):
+        """Format an argument default value as text."""
+        return '=' + self.repr(object)
+
+    def docroutine(self, object, name=None, mod=None, cl=None):
+        """Produce text documentation for a function or method object."""
+        realname = object.__name__
+        name = name or realname
+        note = ''
+        skipdocs = 0
+        if inspect.ismethod(object):
+            imclass = object.im_class
+            if cl:
+                if imclass is not cl:
+                    note = ' from ' + classname(imclass, mod)
+            else:
+                if object.im_self is not None:
+                    note = ' method of %s instance' % classname(
+                        object.im_self.__class__, mod)
+                else:
+                    note = ' unbound %s method' % classname(imclass,mod)
+            object = object.im_func
+
+        if name == realname:
+            title = self.bold(realname)
+        else:
+            if (cl and realname in cl.__dict__ and
+                cl.__dict__[realname] is object):
+                skipdocs = 1
+            title = self.bold(name) + ' = ' + realname
+        if inspect.isfunction(object):
+            args, varargs, varkw, defaults = inspect.getargspec(object)
+            argspec = inspect.formatargspec(
+                args, varargs, varkw, defaults, formatvalue=self.formatvalue)
+            if realname == '<lambda>':
+                title = self.bold(name) + ' lambda '
+                argspec = argspec[1:-1] # remove parentheses
+        else:
+            argspec = '(...)'
+        decl = title + argspec + note
+
+        if skipdocs:
+            return decl + '\n'
+        else:
+            doc = getdoc(object) or ''
+            return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
+
+    def _docdescriptor(self, name, value, mod):
+        results = []
+        push = results.append
+
+        if name:
+            push(self.bold(name))
+            push('\n')
+        doc = getdoc(value) or ''
+        if doc:
+            push(self.indent(doc))
+            push('\n')
+        return ''.join(results)
+
+    def docproperty(self, object, name=None, mod=None, cl=None):
+        """Produce text documentation for a property."""
+        return self._docdescriptor(name, object, mod)
+
+    def docdata(self, object, name=None, mod=None, cl=None):
+        """Produce text documentation for a data descriptor."""
+        return self._docdescriptor(name, object, mod)
+
+    def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
+        """Produce text documentation for a data object."""
+        repr = self.repr(object)
+        if maxlen:
+            line = (name and name + ' = ' or '') + repr
+            chop = maxlen - len(line)
+            if chop < 0: repr = repr[:chop] + '...'
+        line = (name and self.bold(name) + ' = ' or '') + repr
+        if doc is not None:
+            line += '\n' + self.indent(str(doc))
+        return line
+
+# --------------------------------------------------------- user interfaces
+
+def pager(text):
+    """The first time this is called, determine what kind of pager to use."""
+    global pager
+    pager = getpager()
+    pager(text)
+
+def getpager():
+    """Decide what method to use for paging through text."""
+    if type(sys.stdout) is not types.FileType:
+        return plainpager
+    if not sys.stdin.isatty() or not sys.stdout.isatty():
+        return plainpager
+    if 'PAGER' in os.environ:
+        if sys.platform == 'win32': # pipes completely broken in Windows
+            return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
+        elif os.environ.get('TERM') in ('dumb', 'emacs'):
+            return lambda text: pipepager(plain(text), os.environ['PAGER'])
+        else:
+            return lambda text: pipepager(text, os.environ['PAGER'])
+    if os.environ.get('TERM') in ('dumb', 'emacs'):
+        return plainpager
+    if sys.platform == 'win32' or sys.platform.startswith('os2'):
+        return lambda text: tempfilepager(plain(text), 'more <')
+    if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
+        return lambda text: pipepager(text, 'less')
+
+    import tempfile
+    (fd, filename) = tempfile.mkstemp()
+    os.close(fd)
+    try:
+        if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
+            return lambda text: pipepager(text, 'more')
+        else:
+            return ttypager
+    finally:
+        os.unlink(filename)
+
+def plain(text):
+    """Remove boldface formatting from text."""
+    return re.sub('.\b', '', text)
+
+def pipepager(text, cmd):
+    """Page through text by feeding it to another program."""
+    pipe = os.popen(cmd, 'w')
+    try:
+        pipe.write(text)
+        pipe.close()
+    except IOError:
+        pass # Ignore broken pipes caused by quitting the pager program.
+
+def tempfilepager(text, cmd):
+    """Page through text by invoking a program on a temporary file."""
+    import tempfile
+    filename = tempfile.mktemp()
+    file = open(filename, 'w')
+    file.write(text)
+    file.close()
+    try:
+        os.system(cmd + ' "' + filename + '"')
+    finally:
+        os.unlink(filename)
+
+def ttypager(text):
+    """Page through text on a text terminal."""
+    lines = split(plain(text), '\n')
+    try:
+        import tty
+        fd = sys.stdin.fileno()
+        old = tty.tcgetattr(fd)
+        tty.setcbreak(fd)
+        getchar = lambda: sys.stdin.read(1)
+    except (ImportError, AttributeError):
+        tty = None
+        getchar = lambda: sys.stdin.readline()[:-1][:1]
+
+    try:
+        r = inc = os.environ.get('LINES', 25) - 1
+        sys.stdout.write(join(lines[:inc], '\n') + '\n')
+        while lines[r:]:
+            sys.stdout.write('-- more --')
+            sys.stdout.flush()
+            c = getchar()
+
+            if c in ('q', 'Q'):
+                sys.stdout.write('\r          \r')
+                break
+            elif c in ('\r', '\n'):
+                sys.stdout.write('\r          \r' + lines[r] + '\n')
+                r = r + 1
+                continue
+            if c in ('b', 'B', '\x1b'):
+                r = r - inc - inc
+                if r < 0: r = 0
+            sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
+            r = r + inc
+
+    finally:
+        if tty:
+            tty.tcsetattr(fd, tty.TCSAFLUSH, old)
+
+def plainpager(text):
+    """Simply print unformatted text.  This is the ultimate fallback."""
+    sys.stdout.write(plain(text))
+
+def describe(thing):
+    """Produce a short description of the given thing."""
+    if inspect.ismodule(thing):
+        if thing.__name__ in sys.builtin_module_names:
+            return 'built-in module ' + thing.__name__
+        if hasattr(thing, '__path__'):
+            return 'package ' + thing.__name__
+        else:
+            return 'module ' + thing.__name__
+    if inspect.isbuiltin(thing):
+        return 'built-in function ' + thing.__name__
+    if inspect.isgetsetdescriptor(thing):
+        return 'getset descriptor %s.%s.%s' % (
+            thing.__objclass__.__module__, thing.__objclass__.__name__,
+            thing.__name__)
+    if inspect.ismemberdescriptor(thing):
+        return 'member descriptor %s.%s.%s' % (
+            thing.__objclass__.__module__, thing.__objclass__.__name__,
+            thing.__name__)
+    if inspect.isclass(thing):
+        return 'class ' + thing.__name__
+    if inspect.isfunction(thing):
+        return 'function ' + thing.__name__
+    if inspect.ismethod(thing):
+        return 'method ' + thing.__name__
+    if type(thing) is types.InstanceType:
+        return 'instance of ' + thing.__class__.__name__
+    return type(thing).__name__
+
+def locate(path, forceload=0):
+    """Locate an object by name or dotted path, importing as necessary."""
+    parts = [part for part in split(path, '.') if part]
+    module, n = None, 0
+    while n < len(parts):
+        nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
+        if nextmodule: module, n = nextmodule, n + 1
+        else: break
+    if module:
+        object = module
+    else:
+        object = __builtin__
+    for part in parts[n:]:
+        try:
+            object = getattr(object, part)
+        except AttributeError:
+            return None
+    return object
+
+# --------------------------------------- interactive interpreter interface
+
+text = TextDoc()
+html = HTMLDoc()
+
+class _OldStyleClass: pass
+_OLD_INSTANCE_TYPE = type(_OldStyleClass())
+
+def resolve(thing, forceload=0):
+    """Given an object or a path to an object, get the object and its name."""
+    if isinstance(thing, str):
+        object = locate(thing, forceload)
+        if not object:
+            raise ImportError, 'no Python documentation found for %r' % thing
+        return object, thing
+    else:
+        name = getattr(thing, '__name__', None)
+        return thing, name if isinstance(name, str) else None
+
+def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
+    """Render text documentation, given an object or a path to an object."""
+    object, name = resolve(thing, forceload)
+    desc = describe(object)
+    module = inspect.getmodule(object)
+    if name and '.' in name:
+        desc += ' in ' + name[:name.rfind('.')]
+    elif module and module is not object:
+        desc += ' in module ' + module.__name__
+    if type(object) is _OLD_INSTANCE_TYPE:
+        # If the passed object is an instance of an old-style class,
+        # document its available methods instead of its value.
+        object = object.__class__
+    elif not (inspect.ismodule(object) or
+              inspect.isclass(object) or
+              inspect.isroutine(object) or
+              inspect.isgetsetdescriptor(object) or
+              inspect.ismemberdescriptor(object) or
+              isinstance(object, property)):
+        # If the passed object is a piece of data or an instance,
+        # document its available methods instead of its value.
+        object = type(object)
+        desc += ' object'
+    return title % desc + '\n\n' + text.document(object, name)
+
+def doc(thing, title='Python Library Documentation: %s', forceload=0):
+    """Display text documentation, given an object or a path to an object."""
+    try:
+        pager(render_doc(thing, title, forceload))
+    except (ImportError, ErrorDuringImport), value:
+        print value
+
+def writedoc(thing, forceload=0):
+    """Write HTML documentation to a file in the current directory."""
+    try:
+        object, name = resolve(thing, forceload)
+        page = html.page(describe(object), html.document(object, name))
+        file = open(name + '.html', 'w')
+        file.write(page)
+        file.close()
+        print 'wrote', name + '.html'
+    except (ImportError, ErrorDuringImport), value:
+        print value
+
+def writedocs(dir, pkgpath='', done=None):
+    """Write out HTML documentation for all modules in a directory tree."""
+    if done is None: done = {}
+    for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
+        writedoc(modname)
+    return
+
+class Helper:
+
+    # These dictionaries map a topic name to either an alias, or a tuple
+    # (label, seealso-items).  The "label" is the label of the corresponding
+    # section in the .rst file under Doc/ and an index into the dictionary
+    # in pydoc_data/topics.py.
+    #
+    # CAUTION: if you change one of these dictionaries, be sure to adapt the
+    #          list of needed labels in Doc/tools/sphinxext/pyspecific.py and
+    #          regenerate the pydoc_data/topics.py file by running
+    #              make pydoc-topics
+    #          in Doc/ and copying the output file into the Lib/ directory.
+
+    keywords = {
+        'and': 'BOOLEAN',
+        'as': 'with',
+        'assert': ('assert', ''),
+        'break': ('break', 'while for'),
+        'class': ('class', 'CLASSES SPECIALMETHODS'),
+        'continue': ('continue', 'while for'),
+        'def': ('function', ''),
+        'del': ('del', 'BASICMETHODS'),
+        'elif': 'if',
+        'else': ('else', 'while for'),
+        'except': 'try',
+        'exec': ('exec', ''),
+        'finally': 'try',
+        'for': ('for', 'break continue while'),
+        'from': 'import',
+        'global': ('global', 'NAMESPACES'),
+        'if': ('if', 'TRUTHVALUE'),
+        'import': ('import', 'MODULES'),
+        'in': ('in', 'SEQUENCEMETHODS2'),
+        'is': 'COMPARISON',
+        'lambda': ('lambda', 'FUNCTIONS'),
+        'not': 'BOOLEAN',
+        'or': 'BOOLEAN',
+        'pass': ('pass', ''),
+        'print': ('print', ''),
+        'raise': ('raise', 'EXCEPTIONS'),
+        'return': ('return', 'FUNCTIONS'),
+        'try': ('try', 'EXCEPTIONS'),
+        'while': ('while', 'break continue if TRUTHVALUE'),
+        'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
+        'yield': ('yield', ''),
+    }
+    # Either add symbols to this dictionary or to the symbols dictionary
+    # directly: Whichever is easier. They are merged later.
+    _symbols_inverse = {
+        'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
+        'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
+                       '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
+        'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
+        'UNARY' : ('-', '~'),
+        'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
+                                '^=', '<<=', '>>=', '**=', '//='),
+        'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
+        'COMPLEX' : ('j', 'J')
+    }
+    symbols = {
+        '%': 'OPERATORS FORMATTING',
+        '**': 'POWER',
+        ',': 'TUPLES LISTS FUNCTIONS',
+        '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
+        '...': 'ELLIPSIS',
+        ':': 'SLICINGS DICTIONARYLITERALS',
+        '@': 'def class',
+        '\\': 'STRINGS',
+        '_': 'PRIVATENAMES',
+        '__': 'PRIVATENAMES SPECIALMETHODS',
+        '`': 'BACKQUOTES',
+        '(': 'TUPLES FUNCTIONS CALLS',
+        ')': 'TUPLES FUNCTIONS CALLS',
+        '[': 'LISTS SUBSCRIPTS SLICINGS',
+        ']': 'LISTS SUBSCRIPTS SLICINGS'
+    }
+    for topic, symbols_ in _symbols_inverse.iteritems():
+        for symbol in symbols_:
+            topics = symbols.get(symbol, topic)
+            if topic not in topics:
+                topics = topics + ' ' + topic
+            symbols[symbol] = topics
+
+    topics = {
+        'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
+                  'FUNCTIONS CLASSES MODULES FILES inspect'),
+        'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
+                    'TYPES'),
+        'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
+        'FORMATTING': ('formatstrings', 'OPERATORS'),
+        'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
+                    'FORMATTING TYPES'),
+        'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
+        'INTEGER': ('integers', 'int range'),
+        'FLOAT': ('floating', 'float math'),
+        'COMPLEX': ('imaginary', 'complex cmath'),
+        'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
+        'MAPPINGS': 'DICTIONARIES',
+        'FUNCTIONS': ('typesfunctions', 'def TYPES'),
+        'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
+        'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
+        'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
+        'FRAMEOBJECTS': 'TYPES',
+        'TRACEBACKS': 'TYPES',
+        'NONE': ('bltin-null-object', ''),
+        'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
+        'FILES': ('bltin-file-objects', ''),
+        'SPECIALATTRIBUTES': ('specialattrs', ''),
+        'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
+        'MODULES': ('typesmodules', 'import'),
+        'PACKAGES': 'import',
+        'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
+                        'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
+                        'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
+                        'LISTS DICTIONARIES BACKQUOTES'),
+        'OPERATORS': 'EXPRESSIONS',
+        'PRECEDENCE': 'EXPRESSIONS',
+        'OBJECTS': ('objects', 'TYPES'),
+        'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
+                           'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
+                           'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
+        'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
+        'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
+        'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
+        'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
+                             'SPECIALMETHODS'),
+        'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
+                             'SPECIALMETHODS'),
+        'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
+        'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
+                          'SPECIALMETHODS'),
+        'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
+        'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
+        'DYNAMICFEATURES': ('dynamic-features', ''),
+        'SCOPING': 'NAMESPACES',
+        'FRAMES': 'NAMESPACES',
+        'EXCEPTIONS': ('exceptions', 'try except finally raise'),
+        'COERCIONS': ('coercion-rules','CONVERSIONS'),
+        'CONVERSIONS': ('conversions', 'COERCIONS'),
+        'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
+        'SPECIALIDENTIFIERS': ('id-classes', ''),
+        'PRIVATENAMES': ('atom-identifiers', ''),
+        'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
+                     'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
+        'TUPLES': 'SEQUENCES',
+        'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
+        'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
+        'LISTLITERALS': ('lists', 'LISTS LITERALS'),
+        'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
+        'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
+        'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
+        'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
+                       'ATTRIBUTEMETHODS'),
+        'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
+        'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
+        'CALLS': ('calls', 'EXPRESSIONS'),
+        'POWER': ('power', 'EXPRESSIONS'),
+        'UNARY': ('unary', 'EXPRESSIONS'),
+        'BINARY': ('binary', 'EXPRESSIONS'),
+        'SHIFTING': ('shifting', 'EXPRESSIONS'),
+        'BITWISE': ('bitwise', 'EXPRESSIONS'),
+        'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
+        'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
+        'ASSERTION': 'assert',
+        'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
+        'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
+        'DELETION': 'del',
+        'PRINTING': 'print',
+        'RETURNING': 'return',
+        'IMPORTING': 'import',
+        'CONDITIONAL': 'if',
+        'LOOPING': ('compound', 'for while break continue'),
+        'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
+        'DEBUGGING': ('debugger', 'pdb'),
+        'CONTEXTMANAGERS': ('context-managers', 'with'),
+    }
+
+    def __init__(self, input=None, output=None):
+        self._input = input
+        self._output = output
+
+    input  = property(lambda self: self._input or sys.stdin)
+    output = property(lambda self: self._output or sys.stdout)
+
+    def __repr__(self):
+        if inspect.stack()[1][3] == '?':
+            self()
+            return ''
+        return '<pydoc.Helper instance>'
+
+    _GoInteractive = object()
+    def __call__(self, request=_GoInteractive):
+        if request is not self._GoInteractive:
+            self.help(request)
+        else:
+            self.intro()
+            self.interact()
+            self.output.write('''
+You are now leaving help and returning to the Python interpreter.
+If you want to ask for help on a particular object directly from the
+interpreter, you can type "help(object)".  Executing "help('string')"
+has the same effect as typing a particular string at the help> prompt.
+''')
+
+    def interact(self):
+        self.output.write('\n')
+        while True:
+            try:
+                request = self.getline('help> ')
+                if not request: break
+            except (KeyboardInterrupt, EOFError):
+                break
+            request = strip(replace(request, '"', '', "'", ''))
+            if lower(request) in ('q', 'quit'): break
+            self.help(request)
+
+    def getline(self, prompt):
+        """Read one line, using raw_input when available."""
+        if self.input is sys.stdin:
+            return raw_input(prompt)
+        else:
+            self.output.write(prompt)
+            self.output.flush()
+            return self.input.readline()
+
+    def help(self, request):
+        if type(request) is type(''):
+            request = request.strip()
+            if request == 'help': self.intro()
+            elif request == 'keywords': self.listkeywords()
+            elif request == 'symbols': self.listsymbols()
+            elif request == 'topics': self.listtopics()
+            elif request == 'modules': self.listmodules()
+            elif request[:8] == 'modules ':
+                self.listmodules(split(request)[1])
+            elif request in self.symbols: self.showsymbol(request)
+            elif request in self.keywords: self.showtopic(request)
+            elif request in self.topics: self.showtopic(request)
+            elif request: doc(request, 'Help on %s:')
+        elif isinstance(request, Helper): self()
+        else: doc(request, 'Help on %s:')
+        self.output.write('\n')
+
+    def intro(self):
+        self.output.write('''
+Welcome to Python %s!  This is the online help utility.
+
+If this is your first time using Python, you should definitely check out
+the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
+
+Enter the name of any module, keyword, or topic to get help on writing
+Python programs and using Python modules.  To quit this help utility and
+return to the interpreter, just type "quit".
+
+To get a list of available modules, keywords, or topics, type "modules",
+"keywords", or "topics".  Each module also comes with a one-line summary
+of what it does; to list the modules whose summaries contain a given word
+such as "spam", type "modules spam".
+''' % tuple([sys.version[:3]]*2))
+
+    def list(self, items, columns=4, width=80):
+        items = items[:]
+        items.sort()
+        colw = width / columns
+        rows = (len(items) + columns - 1) / columns
+        for row in range(rows):
+            for col in range(columns):
+                i = col * rows + row
+                if i < len(items):
+                    self.output.write(items[i])
+                    if col < columns - 1:
+                        self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
+            self.output.write('\n')
+
+    def listkeywords(self):
+        self.output.write('''
+Here is a list of the Python keywords.  Enter any keyword to get more help.
+
+''')
+        self.list(self.keywords.keys())
+
+    def listsymbols(self):
+        self.output.write('''
+Here is a list of the punctuation symbols which Python assigns special meaning
+to. Enter any symbol to get more help.
+
+''')
+        self.list(self.symbols.keys())
+
+    def listtopics(self):
+        self.output.write('''
+Here is a list of available topics.  Enter any topic name to get more help.
+
+''')
+        self.list(self.topics.keys())
+
+    def showtopic(self, topic, more_xrefs=''):
+        try:
+            import pydoc_data.topics
+        except ImportError:
+            self.output.write('''
+Sorry, topic and keyword documentation is not available because the
+module "pydoc_data.topics" could not be found.
+''')
+            return
+        target = self.topics.get(topic, self.keywords.get(topic))
+        if not target:
+            self.output.write('no documentation found for %s\n' % repr(topic))
+            return
+        if type(target) is type(''):
+            return self.showtopic(target, more_xrefs)
+
+        label, xrefs = target
+        try:
+            doc = pydoc_data.topics.topics[label]
+        except KeyError:
+            self.output.write('no documentation found for %s\n' % repr(topic))
+            return
+        pager(strip(doc) + '\n')
+        if more_xrefs:
+            xrefs = (xrefs or '') + ' ' + more_xrefs
+        if xrefs:
+            import StringIO, formatter
+            buffer = StringIO.StringIO()
+            formatter.DumbWriter(buffer).send_flowing_data(
+                'Related help topics: ' + join(split(xrefs), ', ') + '\n')
+            self.output.write('\n%s\n' % buffer.getvalue())
+
+    def showsymbol(self, symbol):
+        target = self.symbols[symbol]
+        topic, _, xrefs = target.partition(' ')
+        self.showtopic(topic, xrefs)
+
+    def listmodules(self, key=''):
+        if key:
+            self.output.write('''
+Here is a list of matching modules.  Enter any module name to get more help.
+
+''')
+            apropos(key)
+        else:
+            self.output.write('''
+Please wait a moment while I gather a list of all available modules...
+
+''')
+            modules = {}
+            def callback(path, modname, desc, modules=modules):
+                if modname and modname[-9:] == '.__init__':
+                    modname = modname[:-9] + ' (package)'
+                if find(modname, '.') < 0:
+                    modules[modname] = 1
+            def onerror(modname):
+                callback(None, modname, None)
+            ModuleScanner().run(callback, onerror=onerror)
+            self.list(modules.keys())
+            self.output.write('''
+Enter any module name to get more help.  Or, type "modules spam" to search
+for modules whose descriptions contain the word "spam".
+''')
+
+help = Helper()
+
+class Scanner:
+    """A generic tree iterator."""
+    def __init__(self, roots, children, descendp):
+        self.roots = roots[:]
+        self.state = []
+        self.children = children
+        self.descendp = descendp
+
+    def next(self):
+        if not self.state:
+            if not self.roots:
+                return None
+            root = self.roots.pop(0)
+            self.state = [(root, self.children(root))]
+        node, children = self.state[-1]
+        if not children:
+            self.state.pop()
+            return self.next()
+        child = children.pop(0)
+        if self.descendp(child):
+            self.state.append((child, self.children(child)))
+        return child
+
+
+class ModuleScanner:
+    """An interruptible scanner that searches module synopses."""
+
+    def run(self, callback, key=None, completer=None, onerror=None):
+        if key: key = lower(key)
+        self.quit = False
+        seen = {}
+
+        for modname in sys.builtin_module_names:
+            if modname != '__main__':
+                seen[modname] = 1
+                if key is None:
+                    callback(None, modname, '')
+                else:
+                    desc = split(__import__(modname).__doc__ or '', '\n')[0]
+                    if find(lower(modname + ' - ' + desc), key) >= 0:
+                        callback(None, modname, desc)
+
+        for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
+            if self.quit:
+                break
+            if key is None:
+                callback(None, modname, '')
+            else:
+                loader = importer.find_module(modname)
+                if hasattr(loader,'get_source'):
+                    import StringIO
+                    desc = source_synopsis(
+                        StringIO.StringIO(loader.get_source(modname))
+                    ) or ''
+                    if hasattr(loader,'get_filename'):
+                        path = loader.get_filename(modname)
+                    else:
+                        path = None
+                else:
+                    module = loader.load_module(modname)
+                    desc = (module.__doc__ or '').splitlines()[0]
+                    path = getattr(module,'__file__',None)
+                if find(lower(modname + ' - ' + desc), key) >= 0:
+                    callback(path, modname, desc)
+
+        if completer:
+            completer()
+
+def apropos(key):
+    """Print all the one-line module summaries that contain a substring."""
+    def callback(path, modname, desc):
+        if modname[-9:] == '.__init__':
+            modname = modname[:-9] + ' (package)'
+        print modname, desc and '- ' + desc
+    def onerror(modname):
+        pass
+    with warnings.catch_warnings():
+        warnings.filterwarnings('ignore') # ignore problems during import
+        ModuleScanner().run(callback, key, onerror=onerror)
+
+# --------------------------------------------------- web browser interface
+
+def serve(port, callback=None, completer=None):
+    import BaseHTTPServer, mimetools, select
+
+    # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
+    class Message(mimetools.Message):
+        def __init__(self, fp, seekable=1):
+            Message = self.__class__
+            Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
+            self.encodingheader = self.getheader('content-transfer-encoding')
+            self.typeheader = self.getheader('content-type')
+            self.parsetype()
+            self.parseplist()
+
+    class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+        def send_document(self, title, contents):
+            try:
+                self.send_response(200)
+                self.send_header('Content-Type', 'text/html')
+                self.end_headers()
+                self.wfile.write(html.page(title, contents))
+            except IOError: pass
+
+        def do_GET(self):
+            path = self.path
+            if path[-5:] == '.html': path = path[:-5]
+            if path[:1] == '/': path = path[1:]
+            if path and path != '.':
+                try:
+                    obj = locate(path, forceload=1)
+                except ErrorDuringImport, value:
+                    self.send_document(path, html.escape(str(value)))
+                    return
+                if obj:
+                    self.send_document(describe(obj), html.document(obj, path))
+                else:
+                    self.send_document(path,
+'no Python documentation found for %s' % repr(path))
+            else:
+                heading = html.heading(
+'<big><big><strong>Python: Index of Modules</strong></big></big>',
+'#ffffff', '#7799ee')
+                def bltinlink(name):
+                    return '<a href="%s.html">%s</a>' % (name, name)
+                names = filter(lambda x: x != '__main__',
+                               sys.builtin_module_names)
+                contents = html.multicolumn(names, bltinlink)
+                indices = ['<p>' + html.bigsection(
+                    'Built-in Modules', '#ffffff', '#ee77aa', contents)]
+
+                seen = {}
+                for dir in sys.path:
+                    indices.append(html.index(dir, seen))
+                contents = heading + join(indices) + '''<p align=right>
+<font color="#909090" face="helvetica, arial"><strong>
+pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
+                self.send_document('Index of Modules', contents)
+
+        def log_message(self, *args): pass
+
+    class DocServer(BaseHTTPServer.HTTPServer):
+        def __init__(self, port, callback):
+            host = 'localhost'
+            self.address = (host, port)
+            self.url = 'http://%s:%d/' % (host, port)
+            self.callback = callback
+            self.base.__init__(self, self.address, self.handler)
+
+        def serve_until_quit(self):
+            import select
+            self.quit = False
+            while not self.quit:
+                rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
+                if rd: self.handle_request()
+
+        def server_activate(self):
+            self.base.server_activate(self)
+            if self.callback: self.callback(self)
+
+    DocServer.base = BaseHTTPServer.HTTPServer
+    DocServer.handler = DocHandler
+    DocHandler.MessageClass = Message
+    try:
+        try:
+            DocServer(port, callback).serve_until_quit()
+        except (KeyboardInterrupt, select.error):
+            pass
+    finally:
+        if completer: completer()
+
+# ----------------------------------------------------- graphical interface
+
+def gui():
+    """Graphical interface (starts web server and pops up a control window)."""
+    class GUI:
+        def __init__(self, window, port=7464):
+            self.window = window
+            self.server = None
+            self.scanner = None
+
+            import Tkinter
+            self.server_frm = Tkinter.Frame(window)
+            self.title_lbl = Tkinter.Label(self.server_frm,
+                text='Starting server...\n ')
+            self.open_btn = Tkinter.Button(self.server_frm,
+                text='open browser', command=self.open, state='disabled')
+            self.quit_btn = Tkinter.Button(self.server_frm,
+                text='quit serving', command=self.quit, state='disabled')
+
+            self.search_frm = Tkinter.Frame(window)
+            self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
+            self.search_ent = Tkinter.Entry(self.search_frm)
+            self.search_ent.bind('<Return>', self.search)
+            self.stop_btn = Tkinter.Button(self.search_frm,
+                text='stop', pady=0, command=self.stop, state='disabled')
+            if sys.platform == 'win32':
+                # Trying to hide and show this button crashes under Windows.
+                self.stop_btn.pack(side='right')
+
+            self.window.title('pydoc')
+            self.window.protocol('WM_DELETE_WINDOW', self.quit)
+            self.title_lbl.pack(side='top', fill='x')
+            self.open_btn.pack(side='left', fill='x', expand=1)
+            self.quit_btn.pack(side='right', fill='x', expand=1)
+            self.server_frm.pack(side='top', fill='x')
+
+            self.search_lbl.pack(side='left')
+            self.search_ent.pack(side='right', fill='x', expand=1)
+            self.search_frm.pack(side='top', fill='x')
+            self.search_ent.focus_set()
+
+            font = ('helvetica', sys.platform == 'win32' and 8 or 10)
+            self.result_lst = Tkinter.Listbox(window, font=font, height=6)
+            self.result_lst.bind('<Button-1>', self.select)
+            self.result_lst.bind('<Double-Button-1>', self.goto)
+            self.result_scr = Tkinter.Scrollbar(window,
+                orient='vertical', command=self.result_lst.yview)
+            self.result_lst.config(yscrollcommand=self.result_scr.set)
+
+            self.result_frm = Tkinter.Frame(window)
+            self.goto_btn = Tkinter.Button(self.result_frm,
+                text='go to selected', command=self.goto)
+            self.hide_btn = Tkinter.Button(self.result_frm,
+                text='hide results', command=self.hide)
+            self.goto_btn.pack(side='left', fill='x', expand=1)
+            self.hide_btn.pack(side='right', fill='x', expand=1)
+
+            self.window.update()
+            self.minwidth = self.window.winfo_width()
+            self.minheight = self.window.winfo_height()
+            self.bigminheight = (self.server_frm.winfo_reqheight() +
+                                 self.search_frm.winfo_reqheight() +
+                                 self.result_lst.winfo_reqheight() +
+                                 self.result_frm.winfo_reqheight())
+            self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
+            self.expanded = 0
+            self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
+            self.window.wm_minsize(self.minwidth, self.minheight)
+            self.window.tk.willdispatch()
+
+            import threading
+            threading.Thread(
+                target=serve, args=(port, self.ready, self.quit)).start()
+
+        def ready(self, server):
+            self.server = server
+            self.title_lbl.config(
+                text='Python documentation server at\n' + server.url)
+            self.open_btn.config(state='normal')
+            self.quit_btn.config(state='normal')
+
+        def open(self, event=None, url=None):
+            url = url or self.server.url
+            try:
+                import webbrowser
+                webbrowser.open(url)
+            except ImportError: # pre-webbrowser.py compatibility
+                if sys.platform == 'win32':
+                    os.system('start "%s"' % url)
+                else:
+                    rc = os.system('netscape -remote "openURL(%s)" &' % url)
+                    if rc: os.system('netscape "%s" &' % url)
+
+        def quit(self, event=None):
+            if self.server:
+                self.server.quit = 1
+            self.window.quit()
+
+        def search(self, event=None):
+            key = self.search_ent.get()
+            self.stop_btn.pack(side='right')
+            self.stop_btn.config(state='normal')
+            self.search_lbl.config(text='Searching for "%s"...' % key)
+            self.search_ent.forget()
+            self.search_lbl.pack(side='left')
+            self.result_lst.delete(0, 'end')
+            self.goto_btn.config(state='disabled')
+            self.expand()
+
+            import threading
+            if self.scanner:
+                self.scanner.quit = 1
+            self.scanner = ModuleScanner()
+            threading.Thread(target=self.scanner.run,
+                             args=(self.update, key, self.done)).start()
+
+        def update(self, path, modname, desc):
+            if modname[-9:] == '.__init__':
+                modname = modname[:-9] + ' (package)'
+            self.result_lst.insert('end',
+                modname + ' - ' + (desc or '(no description)'))
+
+        def stop(self, event=None):
+            if self.scanner:
+                self.scanner.quit = 1
+                self.scanner = None
+
+        def done(self):
+            self.scanner = None
+            self.search_lbl.config(text='Search for')
+            self.search_lbl.pack(side='left')
+            self.search_ent.pack(side='right', fill='x', expand=1)
+            if sys.platform != 'win32': self.stop_btn.forget()
+            self.stop_btn.config(state='disabled')
+
+        def select(self, event=None):
+            self.goto_btn.config(state='normal')
+
+        def goto(self, event=None):
+            selection = self.result_lst.curselection()
+            if selection:
+                modname = split(self.result_lst.get(selection[0]))[0]
+                self.open(url=self.server.url + modname + '.html')
+
+        def collapse(self):
+            if not self.expanded: return
+            self.result_frm.forget()
+            self.result_scr.forget()
+            self.result_lst.forget()
+            self.bigwidth = self.window.winfo_width()
+            self.bigheight = self.window.winfo_height()
+            self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
+            self.window.wm_minsize(self.minwidth, self.minheight)
+            self.expanded = 0
+
+        def expand(self):
+            if self.expanded: return
+            self.result_frm.pack(side='bottom', fill='x')
+            self.result_scr.pack(side='right', fill='y')
+            self.result_lst.pack(side='top', fill='both', expand=1)
+            self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
+            self.window.wm_minsize(self.minwidth, self.bigminheight)
+            self.expanded = 1
+
+        def hide(self, event=None):
+            self.stop()
+            self.collapse()
+
+    import Tkinter
+    try:
+        root = Tkinter.Tk()
+        # Tk will crash if pythonw.exe has an XP .manifest
+        # file and the root has is not destroyed explicitly.
+        # If the problem is ever fixed in Tk, the explicit
+        # destroy can go.
+        try:
+            gui = GUI(root)
+            root.mainloop()
+        finally:
+            root.destroy()
+    except KeyboardInterrupt:
+        pass
+
+# -------------------------------------------------- command-line interface
+
+def ispath(x):
+    return isinstance(x, str) and find(x, os.sep) >= 0
+
+def cli():
+    """Command-line interface (looks at sys.argv to decide what to do)."""
+    import getopt
+    class BadUsage: pass
+
+    # Scripts don't get the current directory in their path by default
+    # unless they are run with the '-m' switch
+    if '' not in sys.path:
+        scriptdir = os.path.dirname(sys.argv[0])
+        if scriptdir in sys.path:
+            sys.path.remove(scriptdir)
+        sys.path.insert(0, '.')
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
+        writing = 0
+
+        for opt, val in opts:
+            if opt == '-g':
+                gui()
+                return
+            if opt == '-k':
+                apropos(val)
+                return
+            if opt == '-p':
+                try:
+                    port = int(val)
+                except ValueError:
+                    raise BadUsage
+                def ready(server):
+                    print 'pydoc server ready at %s' % server.url
+                def stopped():
+                    print 'pydoc server stopped'
+                serve(port, ready, stopped)
+                return
+            if opt == '-w':
+                writing = 1
+
+        if not args: raise BadUsage
+        for arg in args:
+            if ispath(arg) and not os.path.exists(arg):
+                print 'file %r does not exist' % arg
+                break
+            try:
+                if ispath(arg) and os.path.isfile(arg):
+                    arg = importfile(arg)
+                if writing:
+                    if ispath(arg) and os.path.isdir(arg):
+                        writedocs(arg)
+                    else:
+                        writedoc(arg)
+                else:
+                    help.help(arg)
+            except ErrorDuringImport, value:
+                print value
+
+    except (getopt.error, BadUsage):
+        cmd = os.path.basename(sys.argv[0])
+        print """pydoc - the Python documentation tool
+
+%s <name> ...
+    Show text documentation on something.  <name> may be the name of a
+    Python keyword, topic, function, module, or package, or a dotted
+    reference to a class or function within a module or module in a
+    package.  If <name> contains a '%s', it is used as the path to a
+    Python source file to document. If name is 'keywords', 'topics',
+    or 'modules', a listing of these things is displayed.
+
+%s -k <keyword>
+    Search for a keyword in the synopsis lines of all available modules.
+
+%s -p <port>
+    Start an HTTP server on the given port on the local machine.
+
+%s -g
+    Pop up a graphical interface for finding and serving documentation.
+
+%s -w <name> ...
+    Write out the HTML documentation for a module to a file in the current
+    directory.  If <name> contains a '%s', it is treated as a filename; if
+    it names a directory, documentation is written for all the contents.
+""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
+
+if __name__ == '__main__': cli()
diff --git a/src/main/resources/PythonLibs/pyexpat.py b/src/main/resources/PythonLibs/pyexpat.py
new file mode 100644
index 0000000000000000000000000000000000000000..7d3b815c4b0c114fd6cc5a275a18915aef0080c4
--- /dev/null
+++ b/src/main/resources/PythonLibs/pyexpat.py
@@ -0,0 +1 @@
+from xml.parsers.expat import *
diff --git a/src/main/resources/PythonLibs/quopri.py b/src/main/resources/PythonLibs/quopri.py
new file mode 100644
index 0000000000000000000000000000000000000000..8788afc2f188faeb357442e130431dfa569ff571
--- /dev/null
+++ b/src/main/resources/PythonLibs/quopri.py
@@ -0,0 +1,237 @@
+#! /usr/bin/env python
+
+"""Conversions to/from quoted-printable transport encoding as per RFC 1521."""
+
+# (Dec 1991 version).
+
+__all__ = ["encode", "decode", "encodestring", "decodestring"]
+
+ESCAPE = '='
+MAXLINESIZE = 76
+HEX = '0123456789ABCDEF'
+EMPTYSTRING = ''
+
+try:
+    from binascii import a2b_qp, b2a_qp
+except ImportError:
+    a2b_qp = None
+    b2a_qp = None
+
+
+def needsquoting(c, quotetabs, header):
+    """Decide whether a particular character needs to be quoted.
+
+    The 'quotetabs' flag indicates whether embedded tabs and spaces should be
+    quoted.  Note that line-ending tabs and spaces are always encoded, as per
+    RFC 1521.
+    """
+    if c in ' \t':
+        return quotetabs
+    # if header, we have to escape _ because _ is used to escape space
+    if c == '_':
+        return header
+    return c == ESCAPE or not (' ' <= c <= '~')
+
+def quote(c):
+    """Quote a single character."""
+    i = ord(c)
+    return ESCAPE + HEX[i//16] + HEX[i%16]
+
+
+
+def encode(input, output, quotetabs, header = 0):
+    """Read 'input', apply quoted-printable encoding, and write to 'output'.
+
+    'input' and 'output' are files with readline() and write() methods.
+    The 'quotetabs' flag indicates whether embedded tabs and spaces should be
+    quoted.  Note that line-ending tabs and spaces are always encoded, as per
+    RFC 1521.
+    The 'header' flag indicates whether we are encoding spaces as _ as per
+    RFC 1522.
+    """
+
+    if b2a_qp is not None:
+        data = input.read()
+        odata = b2a_qp(data, quotetabs = quotetabs, header = header)
+        output.write(odata)
+        return
+
+    def write(s, output=output, lineEnd='\n'):
+        # RFC 1521 requires that the line ending in a space or tab must have
+        # that trailing character encoded.
+        if s and s[-1:] in ' \t':
+            output.write(s[:-1] + quote(s[-1]) + lineEnd)
+        elif s == '.':
+            output.write(quote(s) + lineEnd)
+        else:
+            output.write(s + lineEnd)
+
+    prevline = None
+    while 1:
+        line = input.readline()
+        if not line:
+            break
+        outline = []
+        # Strip off any readline induced trailing newline
+        stripped = ''
+        if line[-1:] == '\n':
+            line = line[:-1]
+            stripped = '\n'
+        # Calculate the un-length-limited encoded line
+        for c in line:
+            if needsquoting(c, quotetabs, header):
+                c = quote(c)
+            if header and c == ' ':
+                outline.append('_')
+            else:
+                outline.append(c)
+        # First, write out the previous line
+        if prevline is not None:
+            write(prevline)
+        # Now see if we need any soft line breaks because of RFC-imposed
+        # length limitations.  Then do the thisline->prevline dance.
+        thisline = EMPTYSTRING.join(outline)
+        while len(thisline) > MAXLINESIZE:
+            # Don't forget to include the soft line break `=' sign in the
+            # length calculation!
+            write(thisline[:MAXLINESIZE-1], lineEnd='=\n')
+            thisline = thisline[MAXLINESIZE-1:]
+        # Write out the current line
+        prevline = thisline
+    # Write out the last line, without a trailing newline
+    if prevline is not None:
+        write(prevline, lineEnd=stripped)
+
+def encodestring(s, quotetabs = 0, header = 0):
+    if b2a_qp is not None:
+        return b2a_qp(s, quotetabs = quotetabs, header = header)
+    from cStringIO import StringIO
+    infp = StringIO(s)
+    outfp = StringIO()
+    encode(infp, outfp, quotetabs, header)
+    return outfp.getvalue()
+
+
+
+def decode(input, output, header = 0):
+    """Read 'input', apply quoted-printable decoding, and write to 'output'.
+    'input' and 'output' are files with readline() and write() methods.
+    If 'header' is true, decode underscore as space (per RFC 1522)."""
+
+    if a2b_qp is not None:
+        data = input.read()
+        odata = a2b_qp(data, header = header)
+        output.write(odata)
+        return
+
+    new = ''
+    while 1:
+        line = input.readline()
+        if not line: break
+        i, n = 0, len(line)
+        if n > 0 and line[n-1] == '\n':
+            partial = 0; n = n-1
+            # Strip trailing whitespace
+            while n > 0 and line[n-1] in " \t\r":
+                n = n-1
+        else:
+            partial = 1
+        while i < n:
+            c = line[i]
+            if c == '_' and header:
+                new = new + ' '; i = i+1
+            elif c != ESCAPE:
+                new = new + c; i = i+1
+            elif i+1 == n and not partial:
+                partial = 1; break
+            elif i+1 < n and line[i+1] == ESCAPE:
+                new = new + ESCAPE; i = i+2
+            elif i+2 < n and ishex(line[i+1]) and ishex(line[i+2]):
+                new = new + chr(unhex(line[i+1:i+3])); i = i+3
+            else: # Bad escape sequence -- leave it in
+                new = new + c; i = i+1
+        if not partial:
+            output.write(new + '\n')
+            new = ''
+    if new:
+        output.write(new)
+
+def decodestring(s, header = 0):
+    if a2b_qp is not None:
+        return a2b_qp(s, header = header)
+    from cStringIO import StringIO
+    infp = StringIO(s)
+    outfp = StringIO()
+    decode(infp, outfp, header = header)
+    return outfp.getvalue()
+
+
+
+# Other helper functions
+def ishex(c):
+    """Return true if the character 'c' is a hexadecimal digit."""
+    return '0' <= c <= '9' or 'a' <= c <= 'f' or 'A' <= c <= 'F'
+
+def unhex(s):
+    """Get the integer value of a hexadecimal number."""
+    bits = 0
+    for c in s:
+        if '0' <= c <= '9':
+            i = ord('0')
+        elif 'a' <= c <= 'f':
+            i = ord('a')-10
+        elif 'A' <= c <= 'F':
+            i = ord('A')-10
+        else:
+            break
+        bits = bits*16 + (ord(c) - i)
+    return bits
+
+
+
+def main():
+    import sys
+    import getopt
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'td')
+    except getopt.error, msg:
+        sys.stdout = sys.stderr
+        print msg
+        print "usage: quopri [-t | -d] [file] ..."
+        print "-t: quote tabs"
+        print "-d: decode; default encode"
+        sys.exit(2)
+    deco = 0
+    tabs = 0
+    for o, a in opts:
+        if o == '-t': tabs = 1
+        if o == '-d': deco = 1
+    if tabs and deco:
+        sys.stdout = sys.stderr
+        print "-t and -d are mutually exclusive"
+        sys.exit(2)
+    if not args: args = ['-']
+    sts = 0
+    for file in args:
+        if file == '-':
+            fp = sys.stdin
+        else:
+            try:
+                fp = open(file)
+            except IOError, msg:
+                sys.stderr.write("%s: can't open (%s)\n" % (file, msg))
+                sts = 1
+                continue
+        if deco:
+            decode(fp, sys.stdout)
+        else:
+            encode(fp, sys.stdout, tabs)
+        if fp is not sys.stdin:
+            fp.close()
+    if sts:
+        sys.exit(sts)
+
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/main/resources/PythonLibs/random.py b/src/main/resources/PythonLibs/random.py
new file mode 100644
index 0000000000000000000000000000000000000000..af04ab207d37c098d274caf852d37bdbcfc28198
--- /dev/null
+++ b/src/main/resources/PythonLibs/random.py
@@ -0,0 +1,904 @@
+"""Random variable generators.
+
+    integers
+    --------
+           uniform within range
+
+    sequences
+    ---------
+           pick random element
+           pick random sample
+           generate random permutation
+
+    distributions on the real line:
+    ------------------------------
+           uniform
+           triangular
+           normal (Gaussian)
+           lognormal
+           negative exponential
+           gamma
+           beta
+           pareto
+           Weibull
+
+    distributions on the circle (angles 0 to 2pi)
+    ---------------------------------------------
+           circular uniform
+           von Mises
+
+General notes on the underlying Mersenne Twister core generator:
+
+* The period is 2**19937-1.
+* It is one of the most extensively tested generators in existence.
+* Without a direct way to compute N steps forward, the semantics of
+  jumpahead(n) are weakened to simply jump to another distant state and rely
+  on the large period to avoid overlapping sequences.
+* The random() method is implemented in C, executes in a single Python step,
+  and is, therefore, threadsafe.
+
+"""
+
+from __future__ import division
+from warnings import warn as _warn
+from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType
+from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
+from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
+from os import urandom as _urandom
+from binascii import hexlify as _hexlify
+import hashlib as _hashlib
+
+__all__ = ["Random","seed","random","uniform","randint","choice","sample",
+           "randrange","shuffle","normalvariate","lognormvariate",
+           "expovariate","vonmisesvariate","gammavariate","triangular",
+           "gauss","betavariate","paretovariate","weibullvariate",
+           "getstate","setstate","jumpahead", "WichmannHill", "getrandbits",
+           "SystemRandom"]
+
+NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
+TWOPI = 2.0*_pi
+LOG4 = _log(4.0)
+SG_MAGICCONST = 1.0 + _log(4.5)
+BPF = 53        # Number of bits in a float
+RECIP_BPF = 2**-BPF
+
+
+# Translated by Guido van Rossum from C source provided by
+# Adrian Baddeley.  Adapted by Raymond Hettinger for use with
+# the Mersenne Twister  and os.urandom() core generators.
+
+import _random
+
+class Random(_random.Random):
+    """Random number generator base class used by bound module functions.
+
+    Used to instantiate instances of Random to get generators that don't
+    share state.  Especially useful for multi-threaded programs, creating
+    a different instance of Random for each thread, and using the jumpahead()
+    method to ensure that the generated sequences seen by each thread don't
+    overlap.
+
+    Class Random can also be subclassed if you want to use a different basic
+    generator of your own devising: in that case, override the following
+    methods: random(), seed(), getstate(), setstate() and jumpahead().
+    Optionally, implement a getrandbits() method so that randrange() can cover
+    arbitrarily large ranges.
+
+    """
+
+    VERSION = 3     # used by getstate/setstate
+
+    def __init__(self, x=None):
+        """Initialize an instance.
+
+        Optional argument x controls seeding, as for Random.seed().
+        """
+
+        self.seed(x)
+        self.gauss_next = None
+
+    def seed(self, a=None):
+        """Initialize internal state from hashable object.
+
+        None or no argument seeds from current time or from an operating
+        system specific randomness source if available.
+
+        If a is not None or an int or long, hash(a) is used instead.
+        """
+
+        if a is None:
+            try:
+                a = long(_hexlify(_urandom(16)), 16)
+            except NotImplementedError:
+                import time
+                a = long(time.time() * 256) # use fractional seconds
+
+        super(Random, self).seed(a)
+        self.gauss_next = None
+
+    def getstate(self):
+        """Return internal state; can be passed to setstate() later."""
+        return self.VERSION, super(Random, self).getstate(), self.gauss_next
+
+    def setstate(self, state):
+        """Restore internal state from object returned by getstate()."""
+        version = state[0]
+        if version == 3:
+            version, internalstate, self.gauss_next = state
+            super(Random, self).setstate(internalstate)
+        elif version == 2:
+            version, internalstate, self.gauss_next = state
+            # In version 2, the state was saved as signed ints, which causes
+            #   inconsistencies between 32/64-bit systems. The state is
+            #   really unsigned 32-bit ints, so we convert negative ints from
+            #   version 2 to positive longs for version 3.
+            try:
+                internalstate = tuple( long(x) % (2**32) for x in internalstate )
+            except ValueError, e:
+                raise TypeError, e
+            super(Random, self).setstate(internalstate)
+        else:
+            raise ValueError("state with version %s passed to "
+                             "Random.setstate() of version %s" %
+                             (version, self.VERSION))
+
+    def jumpahead(self, n):
+        """Change the internal state to one that is likely far away
+        from the current state.  This method will not be in Py3.x,
+        so it is better to simply reseed.
+        """
+        # The super.jumpahead() method uses shuffling to change state,
+        # so it needs a large and "interesting" n to work with.  Here,
+        # we use hashing to create a large n for the shuffle.
+        s = repr(n) + repr(self.getstate())
+        n = int(_hashlib.new('sha512', s).hexdigest(), 16)
+        super(Random, self).jumpahead(n)
+
+## ---- Methods below this point do not need to be overridden when
+## ---- subclassing for the purpose of using a different core generator.
+
+## -------------------- pickle support  -------------------
+
+    def __getstate__(self): # for pickle
+        return self.getstate()
+
+    def __setstate__(self, state):  # for pickle
+        self.setstate(state)
+
+    def __reduce__(self):
+        return self.__class__, (), self.getstate()
+
+## -------------------- integer methods  -------------------
+
+    def randrange(self, start, stop=None, step=1, int=int, default=None,
+                  maxwidth=1L<<BPF):
+        """Choose a random item from range(start, stop[, step]).
+
+        This fixes the problem with randint() which includes the
+        endpoint; in Python this is usually not what you want.
+        Do not supply the 'int', 'default', and 'maxwidth' arguments.
+        """
+
+        # This code is a bit messy to make it fast for the
+        # common case while still doing adequate error checking.
+        istart = int(start)
+        if istart != start:
+            raise ValueError, "non-integer arg 1 for randrange()"
+        if stop is default:
+            if istart > 0:
+                if istart >= maxwidth:
+                    return self._randbelow(istart)
+                return int(self.random() * istart)
+            raise ValueError, "empty range for randrange()"
+
+        # stop argument supplied.
+        istop = int(stop)
+        if istop != stop:
+            raise ValueError, "non-integer stop for randrange()"
+        width = istop - istart
+        if step == 1 and width > 0:
+            # Note that
+            #     int(istart + self.random()*width)
+            # instead would be incorrect.  For example, consider istart
+            # = -2 and istop = 0.  Then the guts would be in
+            # -2.0 to 0.0 exclusive on both ends (ignoring that random()
+            # might return 0.0), and because int() truncates toward 0, the
+            # final result would be -1 or 0 (instead of -2 or -1).
+            #     istart + int(self.random()*width)
+            # would also be incorrect, for a subtler reason:  the RHS
+            # can return a long, and then randrange() would also return
+            # a long, but we're supposed to return an int (for backward
+            # compatibility).
+
+            if width >= maxwidth:
+                return int(istart + self._randbelow(width))
+            return int(istart + int(self.random()*width))
+        if step == 1:
+            raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width)
+
+        # Non-unit step argument supplied.
+        istep = int(step)
+        if istep != step:
+            raise ValueError, "non-integer step for randrange()"
+        if istep > 0:
+            n = (width + istep - 1) // istep
+        elif istep < 0:
+            n = (width + istep + 1) // istep
+        else:
+            raise ValueError, "zero step for randrange()"
+
+        if n <= 0:
+            raise ValueError, "empty range for randrange()"
+
+        if n >= maxwidth:
+            return istart + istep*self._randbelow(n)
+        return istart + istep*int(self.random() * n)
+
+    def randint(self, a, b):
+        """Return random integer in range [a, b], including both end points.
+        """
+
+        return self.randrange(a, b+1)
+
+    def _randbelow(self, n, _log=_log, int=int, _maxwidth=1L<<BPF,
+                   _Method=_MethodType, _BuiltinMethod=_BuiltinMethodType):
+        """Return a random int in the range [0,n)
+
+        Handles the case where n has more bits than returned
+        by a single call to the underlying generator.
+        """
+
+        try:
+            getrandbits = self.getrandbits
+        except AttributeError:
+            pass
+        else:
+            # Only call self.getrandbits if the original random() builtin method
+            # has not been overridden or if a new getrandbits() was supplied.
+            # This assures that the two methods correspond.
+            if type(self.random) is _BuiltinMethod or type(getrandbits) is _Method:
+                k = int(1.00001 + _log(n-1, 2.0))   # 2**k > n-1 > 2**(k-2)
+                r = getrandbits(k)
+                while r >= n:
+                    r = getrandbits(k)
+                return r
+        if n >= _maxwidth:
+            _warn("Underlying random() generator does not supply \n"
+                "enough bits to choose from a population range this large")
+        return int(self.random() * n)
+
+## -------------------- sequence methods  -------------------
+
+    def choice(self, seq):
+        """Choose a random element from a non-empty sequence."""
+        return seq[int(self.random() * len(seq))]  # raises IndexError if seq is empty
+
+    def shuffle(self, x, random=None, int=int):
+        """x, random=random.random -> shuffle list x in place; return None.
+
+        Optional arg random is a 0-argument function returning a random
+        float in [0.0, 1.0); by default, the standard random.random.
+        """
+
+        if random is None:
+            random = self.random
+        for i in reversed(xrange(1, len(x))):
+            # pick an element in x[:i+1] with which to exchange x[i]
+            j = int(random() * (i+1))
+            x[i], x[j] = x[j], x[i]
+
+    def sample(self, population, k):
+        """Chooses k unique random elements from a population sequence.
+
+        Returns a new list containing elements from the population while
+        leaving the original population unchanged.  The resulting list is
+        in selection order so that all sub-slices will also be valid random
+        samples.  This allows raffle winners (the sample) to be partitioned
+        into grand prize and second place winners (the subslices).
+
+        Members of the population need not be hashable or unique.  If the
+        population contains repeats, then each occurrence is a possible
+        selection in the sample.
+
+        To choose a sample in a range of integers, use xrange as an argument.
+        This is especially fast and space efficient for sampling from a
+        large population:   sample(xrange(10000000), 60)
+        """
+
+        # Sampling without replacement entails tracking either potential
+        # selections (the pool) in a list or previous selections in a set.
+
+        # When the number of selections is small compared to the
+        # population, then tracking selections is efficient, requiring
+        # only a small set and an occasional reselection.  For
+        # a larger number of selections, the pool tracking method is
+        # preferred since the list takes less space than the
+        # set and it doesn't suffer from frequent reselections.
+
+        n = len(population)
+        if not 0 <= k <= n:
+            raise ValueError("sample larger than population")
+        random = self.random
+        _int = int
+        result = [None] * k
+        setsize = 21        # size of a small set minus size of an empty list
+        if k > 5:
+            setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets
+        if n <= setsize or hasattr(population, "keys"):
+            # An n-length list is smaller than a k-length set, or this is a
+            # mapping type so the other algorithm wouldn't work.
+            pool = list(population)
+            for i in xrange(k):         # invariant:  non-selected at [0,n-i)
+                j = _int(random() * (n-i))
+                result[i] = pool[j]
+                pool[j] = pool[n-i-1]   # move non-selected item into vacancy
+        else:
+            try:
+                selected = set()
+                selected_add = selected.add
+                for i in xrange(k):
+                    j = _int(random() * n)
+                    while j in selected:
+                        j = _int(random() * n)
+                    selected_add(j)
+                    result[i] = population[j]
+            except (TypeError, KeyError):   # handle (at least) sets
+                if isinstance(population, list):
+                    raise
+                return self.sample(tuple(population), k)
+        return result
+
+## -------------------- real-valued distributions  -------------------
+
+## -------------------- uniform distribution -------------------
+
+    def uniform(self, a, b):
+        "Get a random number in the range [a, b) or [a, b] depending on rounding."
+        return a + (b-a) * self.random()
+
+## -------------------- triangular --------------------
+
+    def triangular(self, low=0.0, high=1.0, mode=None):
+        """Triangular distribution.
+
+        Continuous distribution bounded by given lower and upper limits,
+        and having a given mode value in-between.
+
+        http://en.wikipedia.org/wiki/Triangular_distribution
+
+        """
+        u = self.random()
+        c = 0.5 if mode is None else (mode - low) / (high - low)
+        if u > c:
+            u = 1.0 - u
+            c = 1.0 - c
+            low, high = high, low
+        return low + (high - low) * (u * c) ** 0.5
+
+## -------------------- normal distribution --------------------
+
+    def normalvariate(self, mu, sigma):
+        """Normal distribution.
+
+        mu is the mean, and sigma is the standard deviation.
+
+        """
+        # mu = mean, sigma = standard deviation
+
+        # Uses Kinderman and Monahan method. Reference: Kinderman,
+        # A.J. and Monahan, J.F., "Computer generation of random
+        # variables using the ratio of uniform deviates", ACM Trans
+        # Math Software, 3, (1977), pp257-260.
+
+        random = self.random
+        while 1:
+            u1 = random()
+            u2 = 1.0 - random()
+            z = NV_MAGICCONST*(u1-0.5)/u2
+            zz = z*z/4.0
+            if zz <= -_log(u2):
+                break
+        return mu + z*sigma
+
+## -------------------- lognormal distribution --------------------
+
+    def lognormvariate(self, mu, sigma):
+        """Log normal distribution.
+
+        If you take the natural logarithm of this distribution, you'll get a
+        normal distribution with mean mu and standard deviation sigma.
+        mu can have any value, and sigma must be greater than zero.
+
+        """
+        return _exp(self.normalvariate(mu, sigma))
+
+## -------------------- exponential distribution --------------------
+
+    def expovariate(self, lambd):
+        """Exponential distribution.
+
+        lambd is 1.0 divided by the desired mean.  It should be
+        nonzero.  (The parameter would be called "lambda", but that is
+        a reserved word in Python.)  Returned values range from 0 to
+        positive infinity if lambd is positive, and from negative
+        infinity to 0 if lambd is negative.
+
+        """
+        # lambd: rate lambd = 1/mean
+        # ('lambda' is a Python reserved word)
+
+        # we use 1-random() instead of random() to preclude the
+        # possibility of taking the log of zero.
+        return -_log(1.0 - self.random())/lambd
+
+## -------------------- von Mises distribution --------------------
+
+    def vonmisesvariate(self, mu, kappa):
+        """Circular data distribution.
+
+        mu is the mean angle, expressed in radians between 0 and 2*pi, and
+        kappa is the concentration parameter, which must be greater than or
+        equal to zero.  If kappa is equal to zero, this distribution reduces
+        to a uniform random angle over the range 0 to 2*pi.
+
+        """
+        # mu:    mean angle (in radians between 0 and 2*pi)
+        # kappa: concentration parameter kappa (>= 0)
+        # if kappa = 0 generate uniform random angle
+
+        # Based upon an algorithm published in: Fisher, N.I.,
+        # "Statistical Analysis of Circular Data", Cambridge
+        # University Press, 1993.
+
+        # Thanks to Magnus Kessler for a correction to the
+        # implementation of step 4.
+
+        random = self.random
+        if kappa <= 1e-6:
+            return TWOPI * random()
+
+        s = 0.5 / kappa
+        r = s + _sqrt(1.0 + s * s)
+
+        while 1:
+            u1 = random()
+            z = _cos(_pi * u1)
+
+            d = z / (r + z)
+            u2 = random()
+            if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d):
+                break
+
+        q = 1.0 / r
+        f = (q + z) / (1.0 + q * z)
+        u3 = random()
+        if u3 > 0.5:
+            theta = (mu + _acos(f)) % TWOPI
+        else:
+            theta = (mu - _acos(f)) % TWOPI
+
+        return theta
+
+## -------------------- gamma distribution --------------------
+
+    def gammavariate(self, alpha, beta):
+        """Gamma distribution.  Not the gamma function!
+
+        Conditions on the parameters are alpha > 0 and beta > 0.
+
+        The probability distribution function is:
+
+                    x ** (alpha - 1) * math.exp(-x / beta)
+          pdf(x) =  --------------------------------------
+                      math.gamma(alpha) * beta ** alpha
+
+        """
+
+        # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
+
+        # Warning: a few older sources define the gamma distribution in terms
+        # of alpha > -1.0
+        if alpha <= 0.0 or beta <= 0.0:
+            raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
+
+        random = self.random
+        if alpha > 1.0:
+
+            # Uses R.C.H. Cheng, "The generation of Gamma
+            # variables with non-integral shape parameters",
+            # Applied Statistics, (1977), 26, No. 1, p71-74
+
+            ainv = _sqrt(2.0 * alpha - 1.0)
+            bbb = alpha - LOG4
+            ccc = alpha + ainv
+
+            while 1:
+                u1 = random()
+                if not 1e-7 < u1 < .9999999:
+                    continue
+                u2 = 1.0 - random()
+                v = _log(u1/(1.0-u1))/ainv
+                x = alpha*_exp(v)
+                z = u1*u1*u2
+                r = bbb+ccc*v-x
+                if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
+                    return x * beta
+
+        elif alpha == 1.0:
+            # expovariate(1)
+            u = random()
+            while u <= 1e-7:
+                u = random()
+            return -_log(u) * beta
+
+        else:   # alpha is between 0 and 1 (exclusive)
+
+            # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
+
+            while 1:
+                u = random()
+                b = (_e + alpha)/_e
+                p = b*u
+                if p <= 1.0:
+                    x = p ** (1.0/alpha)
+                else:
+                    x = -_log((b-p)/alpha)
+                u1 = random()
+                if p > 1.0:
+                    if u1 <= x ** (alpha - 1.0):
+                        break
+                elif u1 <= _exp(-x):
+                    break
+            return x * beta
+
+## -------------------- Gauss (faster alternative) --------------------
+
+    def gauss(self, mu, sigma):
+        """Gaussian distribution.
+
+        mu is the mean, and sigma is the standard deviation.  This is
+        slightly faster than the normalvariate() function.
+
+        Not thread-safe without a lock around calls.
+
+        """
+
+        # When x and y are two variables from [0, 1), uniformly
+        # distributed, then
+        #
+        #    cos(2*pi*x)*sqrt(-2*log(1-y))
+        #    sin(2*pi*x)*sqrt(-2*log(1-y))
+        #
+        # are two *independent* variables with normal distribution
+        # (mu = 0, sigma = 1).
+        # (Lambert Meertens)
+        # (corrected version; bug discovered by Mike Miller, fixed by LM)
+
+        # Multithreading note: When two threads call this function
+        # simultaneously, it is possible that they will receive the
+        # same return value.  The window is very small though.  To
+        # avoid this, you have to use a lock around all calls.  (I
+        # didn't want to slow this down in the serial case by using a
+        # lock here.)
+
+        random = self.random
+        z = self.gauss_next
+        self.gauss_next = None
+        if z is None:
+            x2pi = random() * TWOPI
+            g2rad = _sqrt(-2.0 * _log(1.0 - random()))
+            z = _cos(x2pi) * g2rad
+            self.gauss_next = _sin(x2pi) * g2rad
+
+        return mu + z*sigma
+
+## -------------------- beta --------------------
+## See
+## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html
+## for Ivan Frohne's insightful analysis of why the original implementation:
+##
+##    def betavariate(self, alpha, beta):
+##        # Discrete Event Simulation in C, pp 87-88.
+##
+##        y = self.expovariate(alpha)
+##        z = self.expovariate(1.0/beta)
+##        return z/(y+z)
+##
+## was dead wrong, and how it probably got that way.
+
+    def betavariate(self, alpha, beta):
+        """Beta distribution.
+
+        Conditions on the parameters are alpha > 0 and beta > 0.
+        Returned values range between 0 and 1.
+
+        """
+
+        # This version due to Janne Sinkkonen, and matches all the std
+        # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
+        y = self.gammavariate(alpha, 1.)
+        if y == 0:
+            return 0.0
+        else:
+            return y / (y + self.gammavariate(beta, 1.))
+
+## -------------------- Pareto --------------------
+
+    def paretovariate(self, alpha):
+        """Pareto distribution.  alpha is the shape parameter."""
+        # Jain, pg. 495
+
+        u = 1.0 - self.random()
+        return 1.0 / pow(u, 1.0/alpha)
+
+## -------------------- Weibull --------------------
+
+    def weibullvariate(self, alpha, beta):
+        """Weibull distribution.
+
+        alpha is the scale parameter and beta is the shape parameter.
+
+        """
+        # Jain, pg. 499; bug fix courtesy Bill Arms
+
+        u = 1.0 - self.random()
+        return alpha * pow(-_log(u), 1.0/beta)
+
+## -------------------- Wichmann-Hill -------------------
+
+class WichmannHill(Random):
+
+    VERSION = 1     # used by getstate/setstate
+
+    def seed(self, a=None):
+        """Initialize internal state from hashable object.
+
+        None or no argument seeds from current time or from an operating
+        system specific randomness source if available.
+
+        If a is not None or an int or long, hash(a) is used instead.
+
+        If a is an int or long, a is used directly.  Distinct values between
+        0 and 27814431486575L inclusive are guaranteed to yield distinct
+        internal states (this guarantee is specific to the default
+        Wichmann-Hill generator).
+        """
+
+        if a is None:
+            try:
+                a = long(_hexlify(_urandom(16)), 16)
+            except NotImplementedError:
+                import time
+                a = long(time.time() * 256) # use fractional seconds
+
+        if not isinstance(a, (int, long)):
+            a = hash(a)
+
+        a, x = divmod(a, 30268)
+        a, y = divmod(a, 30306)
+        a, z = divmod(a, 30322)
+        self._seed = int(x)+1, int(y)+1, int(z)+1
+
+        self.gauss_next = None
+
+    def random(self):
+        """Get the next random number in the range [0.0, 1.0)."""
+
+        # Wichman-Hill random number generator.
+        #
+        # Wichmann, B. A. & Hill, I. D. (1982)
+        # Algorithm AS 183:
+        # An efficient and portable pseudo-random number generator
+        # Applied Statistics 31 (1982) 188-190
+        #
+        # see also:
+        #        Correction to Algorithm AS 183
+        #        Applied Statistics 33 (1984) 123
+        #
+        #        McLeod, A. I. (1985)
+        #        A remark on Algorithm AS 183
+        #        Applied Statistics 34 (1985),198-200
+
+        # This part is thread-unsafe:
+        # BEGIN CRITICAL SECTION
+        x, y, z = self._seed
+        x = (171 * x) % 30269
+        y = (172 * y) % 30307
+        z = (170 * z) % 30323
+        self._seed = x, y, z
+        # END CRITICAL SECTION
+
+        # Note:  on a platform using IEEE-754 double arithmetic, this can
+        # never return 0.0 (asserted by Tim; proof too long for a comment).
+        return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
+
+    def getstate(self):
+        """Return internal state; can be passed to setstate() later."""
+        return self.VERSION, self._seed, self.gauss_next
+
+    def setstate(self, state):
+        """Restore internal state from object returned by getstate()."""
+        version = state[0]
+        if version == 1:
+            version, self._seed, self.gauss_next = state
+        else:
+            raise ValueError("state with version %s passed to "
+                             "Random.setstate() of version %s" %
+                             (version, self.VERSION))
+
+    def jumpahead(self, n):
+        """Act as if n calls to random() were made, but quickly.
+
+        n is an int, greater than or equal to 0.
+
+        Example use:  If you have 2 threads and know that each will
+        consume no more than a million random numbers, create two Random
+        objects r1 and r2, then do
+            r2.setstate(r1.getstate())
+            r2.jumpahead(1000000)
+        Then r1 and r2 will use guaranteed-disjoint segments of the full
+        period.
+        """
+
+        if not n >= 0:
+            raise ValueError("n must be >= 0")
+        x, y, z = self._seed
+        x = int(x * pow(171, n, 30269)) % 30269
+        y = int(y * pow(172, n, 30307)) % 30307
+        z = int(z * pow(170, n, 30323)) % 30323
+        self._seed = x, y, z
+
+    def __whseed(self, x=0, y=0, z=0):
+        """Set the Wichmann-Hill seed from (x, y, z).
+
+        These must be integers in the range [0, 256).
+        """
+
+        if not type(x) == type(y) == type(z) == int:
+            raise TypeError('seeds must be integers')
+        if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
+            raise ValueError('seeds must be in range(0, 256)')
+        if 0 == x == y == z:
+            # Initialize from current time
+            import time
+            t = long(time.time() * 256)
+            t = int((t&0xffffff) ^ (t>>24))
+            t, x = divmod(t, 256)
+            t, y = divmod(t, 256)
+            t, z = divmod(t, 256)
+        # Zero is a poor seed, so substitute 1
+        self._seed = (x or 1, y or 1, z or 1)
+
+        self.gauss_next = None
+
+    def whseed(self, a=None):
+        """Seed from hashable object's hash code.
+
+        None or no argument seeds from current time.  It is not guaranteed
+        that objects with distinct hash codes lead to distinct internal
+        states.
+
+        This is obsolete, provided for compatibility with the seed routine
+        used prior to Python 2.1.  Use the .seed() method instead.
+        """
+
+        if a is None:
+            self.__whseed()
+            return
+        a = hash(a)
+        a, x = divmod(a, 256)
+        a, y = divmod(a, 256)
+        a, z = divmod(a, 256)
+        x = (x + a) % 256 or 1
+        y = (y + a) % 256 or 1
+        z = (z + a) % 256 or 1
+        self.__whseed(x, y, z)
+
+## --------------- Operating System Random Source  ------------------
+
+class SystemRandom(Random):
+    """Alternate random number generator using sources provided
+    by the operating system (such as /dev/urandom on Unix or
+    CryptGenRandom on Windows).
+
+     Not available on all systems (see os.urandom() for details).
+    """
+
+    def random(self):
+        """Get the next random number in the range [0.0, 1.0)."""
+        return (long(_hexlify(_urandom(7)), 16) >> 3) * RECIP_BPF
+
+    def getrandbits(self, k):
+        """getrandbits(k) -> x.  Generates a long int with k random bits."""
+        if k <= 0:
+            raise ValueError('number of bits must be greater than zero')
+        if k != int(k):
+            raise TypeError('number of bits should be an integer')
+        bytes = (k + 7) // 8                    # bits / 8 and rounded up
+        x = long(_hexlify(_urandom(bytes)), 16)
+        return x >> (bytes * 8 - k)             # trim excess bits
+
+    def _stub(self, *args, **kwds):
+        "Stub method.  Not used for a system random number generator."
+        return None
+    seed = jumpahead = _stub
+
+    def _notimplemented(self, *args, **kwds):
+        "Method should not be called for a system random number generator."
+        raise NotImplementedError('System entropy source does not have state.')
+    getstate = setstate = _notimplemented
+
+## -------------------- test program --------------------
+
+def _test_generator(n, func, args):
+    import time
+    print n, 'times', func.__name__
+    total = 0.0
+    sqsum = 0.0
+    smallest = 1e10
+    largest = -1e10
+    t0 = time.time()
+    for i in range(n):
+        x = func(*args)
+        total += x
+        sqsum = sqsum + x*x
+        smallest = min(x, smallest)
+        largest = max(x, largest)
+    t1 = time.time()
+    print round(t1-t0, 3), 'sec,',
+    avg = total/n
+    stddev = _sqrt(sqsum/n - avg*avg)
+    print 'avg %g, stddev %g, min %g, max %g' % \
+              (avg, stddev, smallest, largest)
+
+
+def _test(N=2000):
+    _test_generator(N, random, ())
+    _test_generator(N, normalvariate, (0.0, 1.0))
+    _test_generator(N, lognormvariate, (0.0, 1.0))
+    _test_generator(N, vonmisesvariate, (0.0, 1.0))
+    _test_generator(N, gammavariate, (0.01, 1.0))
+    _test_generator(N, gammavariate, (0.1, 1.0))
+    _test_generator(N, gammavariate, (0.1, 2.0))
+    _test_generator(N, gammavariate, (0.5, 1.0))
+    _test_generator(N, gammavariate, (0.9, 1.0))
+    _test_generator(N, gammavariate, (1.0, 1.0))
+    _test_generator(N, gammavariate, (2.0, 1.0))
+    _test_generator(N, gammavariate, (20.0, 1.0))
+    _test_generator(N, gammavariate, (200.0, 1.0))
+    _test_generator(N, gauss, (0.0, 1.0))
+    _test_generator(N, betavariate, (3.0, 3.0))
+    _test_generator(N, triangular, (0.0, 1.0, 1.0/3.0))
+
+# Create one instance, seeded from current time, and export its methods
+# as module-level functions.  The functions share state across all uses
+#(both in the user's code and in the Python libraries), but that's fine
+# for most programs and is easier for the casual user than making them
+# instantiate their own Random() instance.
+
+_inst = Random()
+seed = _inst.seed
+random = _inst.random
+uniform = _inst.uniform
+triangular = _inst.triangular
+randint = _inst.randint
+choice = _inst.choice
+randrange = _inst.randrange
+sample = _inst.sample
+shuffle = _inst.shuffle
+normalvariate = _inst.normalvariate
+lognormvariate = _inst.lognormvariate
+expovariate = _inst.expovariate
+vonmisesvariate = _inst.vonmisesvariate
+gammavariate = _inst.gammavariate
+gauss = _inst.gauss
+betavariate = _inst.betavariate
+paretovariate = _inst.paretovariate
+weibullvariate = _inst.weibullvariate
+getstate = _inst.getstate
+setstate = _inst.setstate
+jumpahead = _inst.jumpahead
+getrandbits = _inst.getrandbits
+
+if __name__ == '__main__':
+    _test()
diff --git a/src/main/resources/PythonLibs/re.py b/src/main/resources/PythonLibs/re.py
new file mode 100644
index 0000000000000000000000000000000000000000..aab5d37e589252dfe9b06f0ed3e8aa13def49eed
--- /dev/null
+++ b/src/main/resources/PythonLibs/re.py
@@ -0,0 +1,324 @@
+#
+# Secret Labs' Regular Expression Engine
+#
+# re-compatible interface for the sre matching engine
+#
+# Copyright (c) 1998-2001 by Secret Labs AB.  All rights reserved.
+#
+# This version of the SRE library can be redistributed under CNRI's
+# Python 1.6 license.  For any other use, please contact Secret Labs
+# AB (info@pythonware.com).
+#
+# Portions of this engine have been developed in cooperation with
+# CNRI.  Hewlett-Packard provided funding for 1.6 integration and
+# other compatibility work.
+#
+
+r"""Support for regular expressions (RE).
+
+This module provides regular expression matching operations similar to
+those found in Perl.  It supports both 8-bit and Unicode strings; both
+the pattern and the strings being processed can contain null bytes and
+characters outside the US ASCII range.
+
+Regular expressions can contain both special and ordinary characters.
+Most ordinary characters, like "A", "a", or "0", are the simplest
+regular expressions; they simply match themselves.  You can
+concatenate ordinary characters, so last matches the string 'last'.
+
+The special characters are:
+    "."      Matches any character except a newline.
+    "^"      Matches the start of the string.
+    "$"      Matches the end of the string or just before the newline at
+             the end of the string.
+    "*"      Matches 0 or more (greedy) repetitions of the preceding RE.
+             Greedy means that it will match as many repetitions as possible.
+    "+"      Matches 1 or more (greedy) repetitions of the preceding RE.
+    "?"      Matches 0 or 1 (greedy) of the preceding RE.
+    *?,+?,?? Non-greedy versions of the previous three special characters.
+    {m,n}    Matches from m to n repetitions of the preceding RE.
+    {m,n}?   Non-greedy version of the above.
+    "\\"     Either escapes special characters or signals a special sequence.
+    []       Indicates a set of characters.
+             A "^" as the first character indicates a complementing set.
+    "|"      A|B, creates an RE that will match either A or B.
+    (...)    Matches the RE inside the parentheses.
+             The contents can be retrieved or matched later in the string.
+    (?iLmsux) Set the I, L, M, S, U, or X flag for the RE (see below).
+    (?:...)  Non-grouping version of regular parentheses.
+    (?P<name>...) The substring matched by the group is accessible by name.
+    (?P=name)     Matches the text matched earlier by the group named name.
+    (?#...)  A comment; ignored.
+    (?=...)  Matches if ... matches next, but doesn't consume the string.
+    (?!...)  Matches if ... doesn't match next.
+    (?<=...) Matches if preceded by ... (must be fixed length).
+    (?<!...) Matches if not preceded by ... (must be fixed length).
+    (?(id/name)yes|no) Matches yes pattern if the group with id/name matched,
+                       the (optional) no pattern otherwise.
+
+The special sequences consist of "\\" and a character from the list
+below.  If the ordinary character is not on the list, then the
+resulting RE will match the second character.
+    \number  Matches the contents of the group of the same number.
+    \A       Matches only at the start of the string.
+    \Z       Matches only at the end of the string.
+    \b       Matches the empty string, but only at the start or end of a word.
+    \B       Matches the empty string, but not at the start or end of a word.
+    \d       Matches any decimal digit; equivalent to the set [0-9].
+    \D       Matches any non-digit character; equivalent to the set [^0-9].
+    \s       Matches any whitespace character; equivalent to [ \t\n\r\f\v].
+    \S       Matches any non-whitespace character; equiv. to [^ \t\n\r\f\v].
+    \w       Matches any alphanumeric character; equivalent to [a-zA-Z0-9_].
+             With LOCALE, it will match the set [0-9_] plus characters defined
+             as letters for the current locale.
+    \W       Matches the complement of \w.
+    \\       Matches a literal backslash.
+
+This module exports the following functions:
+    match    Match a regular expression pattern to the beginning of a string.
+    search   Search a string for the presence of a pattern.
+    sub      Substitute occurrences of a pattern found in a string.
+    subn     Same as sub, but also return the number of substitutions made.
+    split    Split a string by the occurrences of a pattern.
+    findall  Find all occurrences of a pattern in a string.
+    finditer Return an iterator yielding a match object for each match.
+    compile  Compile a pattern into a RegexObject.
+    purge    Clear the regular expression cache.
+    escape   Backslash all non-alphanumerics in a string.
+
+Some of the functions in this module takes flags as optional parameters:
+    I  IGNORECASE  Perform case-insensitive matching.
+    L  LOCALE      Make \w, \W, \b, \B, dependent on the current locale.
+    M  MULTILINE   "^" matches the beginning of lines (after a newline)
+                   as well as the string.
+                   "$" matches the end of lines (before a newline) as well
+                   as the end of the string.
+    S  DOTALL      "." matches any character at all, including the newline.
+    X  VERBOSE     Ignore whitespace and comments for nicer looking RE's.
+    U  UNICODE     Make \w, \W, \b, \B, dependent on the Unicode locale.
+
+This module also defines an exception 'error'.
+
+"""
+
+import sys
+import sre_compile
+import sre_parse
+
+# public symbols
+__all__ = [ "match", "search", "sub", "subn", "split", "findall",
+    "compile", "purge", "template", "escape", "I", "L", "M", "S", "X",
+    "U", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
+    "UNICODE", "error" ]
+
+__version__ = "2.2.1"
+
+# flags
+I = IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE # ignore case
+L = LOCALE = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale
+U = UNICODE = sre_compile.SRE_FLAG_UNICODE # assume unicode locale
+M = MULTILINE = sre_compile.SRE_FLAG_MULTILINE # make anchors look for newline
+S = DOTALL = sre_compile.SRE_FLAG_DOTALL # make dot match newline
+X = VERBOSE = sre_compile.SRE_FLAG_VERBOSE # ignore whitespace and comments
+
+# sre extensions (experimental, don't rely on these)
+T = TEMPLATE = sre_compile.SRE_FLAG_TEMPLATE # disable backtracking
+DEBUG = sre_compile.SRE_FLAG_DEBUG # dump pattern after compilation
+
+# sre exception
+error = sre_compile.error
+
+# --------------------------------------------------------------------
+# public interface
+
+def match(pattern, string, flags=0):
+    """Try to apply the pattern at the start of the string, returning
+    a match object, or None if no match was found."""
+    return _compile(pattern, flags).match(string)
+
+def search(pattern, string, flags=0):
+    """Scan through string looking for a match to the pattern, returning
+    a match object, or None if no match was found."""
+    return _compile(pattern, flags).search(string)
+
+def sub(pattern, repl, string, count=0, flags=0):
+    """Return the string obtained by replacing the leftmost
+    non-overlapping occurrences of the pattern in string by the
+    replacement repl.  repl can be either a string or a callable;
+    if a string, backslash escapes in it are processed.  If it is
+    a callable, it's passed the match object and must return
+    a replacement string to be used."""
+    return _compile(pattern, flags).sub(repl, string, count)
+
+def subn(pattern, repl, string, count=0, flags=0):
+    """Return a 2-tuple containing (new_string, number).
+    new_string is the string obtained by replacing the leftmost
+    non-overlapping occurrences of the pattern in the source
+    string by the replacement repl.  number is the number of
+    substitutions that were made. repl can be either a string or a
+    callable; if a string, backslash escapes in it are processed.
+    If it is a callable, it's passed the match object and must
+    return a replacement string to be used."""
+    return _compile(pattern, flags).subn(repl, string, count)
+
+def split(pattern, string, maxsplit=0, flags=0):
+    """Split the source string by the occurrences of the pattern,
+    returning a list containing the resulting substrings."""
+    return _compile(pattern, flags).split(string, maxsplit)
+
+def findall(pattern, string, flags=0):
+    """Return a list of all non-overlapping matches in the string.
+
+    If one or more groups are present in the pattern, return a
+    list of groups; this will be a list of tuples if the pattern
+    has more than one group.
+
+    Empty matches are included in the result."""
+    return _compile(pattern, flags).findall(string)
+
+if sys.hexversion >= 0x02020000:
+    __all__.append("finditer")
+    def finditer(pattern, string, flags=0):
+        """Return an iterator over all non-overlapping matches in the
+        string.  For each match, the iterator returns a match object.
+
+        Empty matches are included in the result."""
+        return _compile(pattern, flags).finditer(string)
+
+def compile(pattern, flags=0):
+    "Compile a regular expression pattern, returning a pattern object."
+    return _compile(pattern, flags)
+
+def purge():
+    "Clear the regular expression cache"
+    _cache.clear()
+    _cache_repl.clear()
+
+def template(pattern, flags=0):
+    "Compile a template pattern, returning a pattern object"
+    return _compile(pattern, flags|T)
+
+_alphanum = frozenset(
+    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
+
+def escape(pattern):
+    "Escape all non-alphanumeric characters in pattern."
+    s = list(pattern)
+    alphanum = _alphanum
+    for i, c in enumerate(pattern):
+        if c not in alphanum:
+            if c == "\000":
+                s[i] = "\\000"
+            else:
+                s[i] = "\\" + c
+    return pattern[:0].join(s)
+
+# --------------------------------------------------------------------
+# internals
+
+_cache = {}
+_cache_repl = {}
+
+_pattern_type = type(sre_compile.compile("", 0))
+
+_MAXCACHE = 100
+
+def _compile(*key):
+    # internal: compile pattern
+    cachekey = (type(key[0]),) + key
+    p = _cache.get(cachekey)
+    if p is not None:
+        return p
+    pattern, flags = key
+    if isinstance(pattern, _pattern_type):
+        if flags:
+            raise ValueError('Cannot process flags argument with a compiled pattern')
+        return pattern
+    if not sre_compile.isstring(pattern):
+        raise TypeError, "first argument must be string or compiled pattern"
+    try:
+        p = sre_compile.compile(pattern, flags)
+    except error, v:
+        raise error, v # invalid expression
+    if len(_cache) >= _MAXCACHE:
+        _cache.clear()
+    _cache[cachekey] = p
+    return p
+
+def _compile_repl(*key):
+    # internal: compile replacement pattern
+    p = _cache_repl.get(key)
+    if p is not None:
+        return p
+    repl, pattern = key
+    try:
+        p = sre_parse.parse_template(repl, pattern)
+    except error, v:
+        raise error, v # invalid expression
+    if len(_cache_repl) >= _MAXCACHE:
+        _cache_repl.clear()
+    _cache_repl[key] = p
+    return p
+
+def _expand(pattern, match, template):
+    # internal: match.expand implementation hook
+    template = sre_parse.parse_template(template, pattern)
+    return sre_parse.expand_template(template, match)
+
+def _subx(pattern, template):
+    # internal: pattern.sub/subn implementation helper
+    template = _compile_repl(template, pattern)
+    if not template[0] and len(template[1]) == 1:
+        # literal replacement
+        return template[1][0]
+    def filter(match, template=template):
+        return sre_parse.expand_template(template, match)
+    return filter
+
+# register myself for pickling
+
+import copy_reg
+
+def _pickle(p):
+    return _compile, (p.pattern, p.flags)
+
+copy_reg.pickle(_pattern_type, _pickle, _compile)
+
+# --------------------------------------------------------------------
+# experimental stuff (see python-dev discussions for details)
+
+class Scanner:
+    def __init__(self, lexicon, flags=0):
+        from sre_constants import BRANCH, SUBPATTERN
+        self.lexicon = lexicon
+        # combine phrases into a compound pattern
+        p = []
+        s = sre_parse.Pattern()
+        s.flags = flags
+        for phrase, action in lexicon:
+            p.append(sre_parse.SubPattern(s, [
+                (SUBPATTERN, (len(p)+1, sre_parse.parse(phrase, flags))),
+                ]))
+        s.groups = len(p)+1
+        p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
+        self.scanner = sre_compile.compile(p)
+    def scan(self, string):
+        result = []
+        append = result.append
+        match = self.scanner.scanner(string).match
+        i = 0
+        while 1:
+            m = match()
+            if not m:
+                break
+            j = m.end()
+            if i == j:
+                break
+            action = self.lexicon[m.lastindex-1][1]
+            if hasattr(action, '__call__'):
+                self.match = m
+                action = action(self, m.group())
+            if action is not None:
+                append(action)
+            i = j
+        return result, string[i:]
diff --git a/src/main/resources/PythonLibs/readline.py b/src/main/resources/PythonLibs/readline.py
new file mode 100644
index 0000000000000000000000000000000000000000..2296a5404469beca080ba6b5d0b37cb7e085e9bc
--- /dev/null
+++ b/src/main/resources/PythonLibs/readline.py
@@ -0,0 +1,192 @@
+from __future__ import with_statement
+import os.path
+import sys
+from warnings import warn
+
+import java.lang.reflect.Array
+
+__all__ = ['add_history', 'clear_history', 'get_begidx', 'get_completer',
+           'get_completer_delims', 'get_current_history_length',
+           'get_endidx', 'get_history_item', 'get_history_length',
+           'get_line_buffer', 'insert_text', 'parse_and_bind',
+           'read_history_file', 'read_init_file', 'redisplay',
+           'remove_history_item', 'set_completer', 'set_completer_delims',
+           'set_history_length', 'set_pre_input_hook', 'set_startup_hook',
+           'write_history_file']
+
+try:
+    _console = sys._jy_console
+    _reader = _console.reader
+except AttributeError:
+    raise ImportError("Cannot access JLineConsole reader")
+
+_history_list = None
+
+# The need for the following warnings should go away once we update
+# JLine. Choosing ImportWarning as the closest warning to what is
+# going on here, namely this is functionality not yet available on
+# Jython.
+
+class NotImplementedWarning(ImportWarning):
+    """Not yet implemented by Jython"""
+
+class SecurityWarning(ImportWarning):
+    """Security manager prevents access to private field"""
+
+
+def _setup_history():
+    # This is obviously not desirable, but avoids O(n) workarounds to
+    # modify the history (ipython uses the function
+    # remove_history_item to mutate the history relatively frequently)
+    global _history_list
+
+    history = _reader.history
+    try:
+        history_list_field = history.class.getDeclaredField("history")
+        history_list_field.setAccessible(True)
+        _history_list = history_list_field.get(history)
+    except:
+        pass
+
+_setup_history()
+
+def parse_and_bind(string):
+    if string == "tab: complete":
+        try:
+            keybindings_field = _reader.class.getDeclaredField("keybindings")
+            keybindings_field.setAccessible(True)
+            keybindings = keybindings_field.get(_reader)
+            COMPLETE = _reader.KEYMAP_NAMES.get('COMPLETE')
+            if java.lang.reflect.Array.getShort(keybindings, 9) != COMPLETE:
+                java.lang.reflect.Array.setShort(keybindings, 9, COMPLETE)
+        except:
+            warn("Cannot bind tab key to complete. You need to do this in a .jlinebindings.properties file instead", SecurityWarning, stacklevel=2)
+    else:
+        warn("Cannot bind key %s. You need to do this in a .jlinebindings.properties file instead" % (string,), NotImplementedWarning, stacklevel=2)
+
+def get_line_buffer():
+    return str(_reader.cursorBuffer.buffer)
+
+def insert_text(string):
+    _reader.putString(string)
+
+def read_init_file(filename=None):
+    warn("read_init_file: %s" % (filename,), NotImplementedWarning, "module", 2)
+
+def read_history_file(filename="~/.history"):
+    print "Reading history:", filename
+    expanded = os.path.expanduser(filename)
+    new_history = _reader.getHistory().getClass()()
+    # new_history.clear()
+    with open(expanded) as f:
+        for line in f:
+            new_history.addToHistory(line.rstrip())
+    _reader.history = new_history
+    _setup_history()
+
+def write_history_file(filename="~/.history"):
+    expanded = os.path.expanduser(filename)
+    with open(expanded, 'w') as f:
+        for line in _reader.history.historyList:
+            f.write(line)
+            f.write("\n")
+
+def clear_history():
+    _reader.history.clear()
+
+def add_history(line):
+    _reader.history.addToHistory(line)
+
+def get_history_length():
+    return _reader.history.maxSize
+
+def set_history_length(length):
+    _reader.history.maxSize = length
+
+def get_current_history_length():
+    return len(_reader.history.historyList)
+
+def get_history_item(index):
+    # JLine indexes from 0 while readline indexes from 1 (at least in test_readline)
+    if index>0:
+        return _reader.history.historyList[index-1]
+    else:
+        return None
+
+def remove_history_item(pos):
+    if _history_list:
+        _history_list.remove(pos)
+    else:
+        warn("Cannot remove history item at position: %s" % (pos,), SecurityWarning, stacklevel=2)
+
+def replace_history_item(pos, line):
+    if _history_list:
+        _history_list.set(pos, line)
+    else:
+        warn("Cannot replace history item at position: %s" % (pos,), SecurityWarning, stacklevel=2)
+
+def redisplay():
+    _reader.redrawLine()
+
+def set_startup_hook(function=None):
+    _console.startupHook = function
+
+def set_pre_input_hook(function=None):
+    warn("set_pre_input_hook %s" % (function,), NotImplementedWarning, stacklevel=2)
+
+_completer_function = None
+
+def set_completer(function=None):
+    """set_completer([function]) -> None
+    Set or remove the completer function.
+    The function is called as function(text, state),
+    for state in 0, 1, 2, ..., until it returns a non-string.
+    It should return the next possible completion starting with 'text'."""
+
+    global _completer_function
+    _completer_function = function
+
+    def complete_handler(buffer, cursor, candidates):
+        start = _get_delimited(buffer, cursor)[0]
+        delimited = buffer[start:cursor]
+        for state in xrange(100): # TODO arbitrary, what's the number used by gnu readline?
+            completion = None
+            try:
+                completion = function(delimited, state)
+            except:
+                pass
+            if completion:
+                candidates.add(completion)
+            else:
+                break
+        return start
+
+    _reader.addCompletor(complete_handler)
+
+
+def get_completer():
+    return _completer_function
+
+def _get_delimited(buffer, cursor):
+    start = cursor
+    for i in xrange(cursor-1, -1, -1):
+        if buffer[i] in _completer_delims:
+            break
+        start = i
+    return start, cursor
+
+def get_begidx():
+    return _get_delimited(str(_reader.cursorBuffer.buffer), _reader.cursorBuffer.cursor)[0]
+
+def get_endidx():
+    return _get_delimited(str(_reader.cursorBuffer.buffer), _reader.cursorBuffer.cursor)[1]
+
+def set_completer_delims(string):
+    global _completer_delims, _completer_delims_set
+    _completer_delims = string
+    _completer_delims_set = set(string)
+
+def get_completer_delims():
+    return _completer_delims
+
+set_completer_delims(' \t\n`~!@#$%^&*()-=+[{]}\\|;:\'",<>/?')
diff --git a/src/main/resources/PythonLibs/repr.py b/src/main/resources/PythonLibs/repr.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c26cc39a2190ccdeebd6fb6a93738b6f4a50fdd
--- /dev/null
+++ b/src/main/resources/PythonLibs/repr.py
@@ -0,0 +1,132 @@
+"""Redo the builtin repr() (representation) but with limits on most sizes."""
+
+__all__ = ["Repr","repr"]
+
+import __builtin__
+from itertools import islice
+
+class Repr:
+
+    def __init__(self):
+        self.maxlevel = 6
+        self.maxtuple = 6
+        self.maxlist = 6
+        self.maxarray = 5
+        self.maxdict = 4
+        self.maxset = 6
+        self.maxfrozenset = 6
+        self.maxdeque = 6
+        self.maxstring = 30
+        self.maxlong = 40
+        self.maxother = 20
+
+    def repr(self, x):
+        return self.repr1(x, self.maxlevel)
+
+    def repr1(self, x, level):
+        typename = type(x).__name__
+        if ' ' in typename:
+            parts = typename.split()
+            typename = '_'.join(parts)
+        if hasattr(self, 'repr_' + typename):
+            return getattr(self, 'repr_' + typename)(x, level)
+        else:
+            s = __builtin__.repr(x)
+            if len(s) > self.maxother:
+                i = max(0, (self.maxother-3)//2)
+                j = max(0, self.maxother-3-i)
+                s = s[:i] + '...' + s[len(s)-j:]
+            return s
+
+    def _repr_iterable(self, x, level, left, right, maxiter, trail=''):
+        n = len(x)
+        if level <= 0 and n:
+            s = '...'
+        else:
+            newlevel = level - 1
+            repr1 = self.repr1
+            pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)]
+            if n > maxiter:  pieces.append('...')
+            s = ', '.join(pieces)
+            if n == 1 and trail:  right = trail + right
+        return '%s%s%s' % (left, s, right)
+
+    def repr_tuple(self, x, level):
+        return self._repr_iterable(x, level, '(', ')', self.maxtuple, ',')
+
+    def repr_list(self, x, level):
+        return self._repr_iterable(x, level, '[', ']', self.maxlist)
+
+    def repr_array(self, x, level):
+        header = "array('%s', [" % x.typecode
+        return self._repr_iterable(x, level, header, '])', self.maxarray)
+
+    def repr_set(self, x, level):
+        x = _possibly_sorted(x)
+        return self._repr_iterable(x, level, 'set([', '])', self.maxset)
+
+    def repr_frozenset(self, x, level):
+        x = _possibly_sorted(x)
+        return self._repr_iterable(x, level, 'frozenset([', '])',
+                                   self.maxfrozenset)
+
+    def repr_deque(self, x, level):
+        return self._repr_iterable(x, level, 'deque([', '])', self.maxdeque)
+
+    def repr_dict(self, x, level):
+        n = len(x)
+        if n == 0: return '{}'
+        if level <= 0: return '{...}'
+        newlevel = level - 1
+        repr1 = self.repr1
+        pieces = []
+        for key in islice(_possibly_sorted(x), self.maxdict):
+            keyrepr = repr1(key, newlevel)
+            valrepr = repr1(x[key], newlevel)
+            pieces.append('%s: %s' % (keyrepr, valrepr))
+        if n > self.maxdict: pieces.append('...')
+        s = ', '.join(pieces)
+        return '{%s}' % (s,)
+
+    def repr_str(self, x, level):
+        s = __builtin__.repr(x[:self.maxstring])
+        if len(s) > self.maxstring:
+            i = max(0, (self.maxstring-3)//2)
+            j = max(0, self.maxstring-3-i)
+            s = __builtin__.repr(x[:i] + x[len(x)-j:])
+            s = s[:i] + '...' + s[len(s)-j:]
+        return s
+
+    def repr_long(self, x, level):
+        s = __builtin__.repr(x) # XXX Hope this isn't too slow...
+        if len(s) > self.maxlong:
+            i = max(0, (self.maxlong-3)//2)
+            j = max(0, self.maxlong-3-i)
+            s = s[:i] + '...' + s[len(s)-j:]
+        return s
+
+    def repr_instance(self, x, level):
+        try:
+            s = __builtin__.repr(x)
+            # Bugs in x.__repr__() can cause arbitrary
+            # exceptions -- then make up something
+        except Exception:
+            return '<%s instance at %x>' % (x.__class__.__name__, id(x))
+        if len(s) > self.maxstring:
+            i = max(0, (self.maxstring-3)//2)
+            j = max(0, self.maxstring-3-i)
+            s = s[:i] + '...' + s[len(s)-j:]
+        return s
+
+
+def _possibly_sorted(x):
+    # Since not all sequences of items can be sorted and comparison
+    # functions may raise arbitrary exceptions, return an unsorted
+    # sequence in that case.
+    try:
+        return sorted(x)
+    except Exception:
+        return list(x)
+
+aRepr = Repr()
+repr = aRepr.repr
diff --git a/src/main/resources/PythonLibs/rfc822.py b/src/main/resources/PythonLibs/rfc822.py
new file mode 100644
index 0000000000000000000000000000000000000000..b65d8da0d25babd71cd52720e1e422524e38d921
--- /dev/null
+++ b/src/main/resources/PythonLibs/rfc822.py
@@ -0,0 +1,1011 @@
+"""RFC 2822 message manipulation.
+
+Note: This is only a very rough sketch of a full RFC-822 parser; in particular
+the tokenizing of addresses does not adhere to all the quoting rules.
+
+Note: RFC 2822 is a long awaited update to RFC 822.  This module should
+conform to RFC 2822, and is thus mis-named (it's not worth renaming it).  Some
+effort at RFC 2822 updates have been made, but a thorough audit has not been
+performed.  Consider any RFC 2822 non-conformance to be a bug.
+
+    RFC 2822: http://www.faqs.org/rfcs/rfc2822.html
+    RFC 822 : http://www.faqs.org/rfcs/rfc822.html (obsolete)
+
+Directions for use:
+
+To create a Message object: first open a file, e.g.:
+
+  fp = open(file, 'r')
+
+You can use any other legal way of getting an open file object, e.g. use
+sys.stdin or call os.popen().  Then pass the open file object to the Message()
+constructor:
+
+  m = Message(fp)
+
+This class can work with any input object that supports a readline method.  If
+the input object has seek and tell capability, the rewindbody method will
+work; also illegal lines will be pushed back onto the input stream.  If the
+input object lacks seek but has an `unread' method that can push back a line
+of input, Message will use that to push back illegal lines.  Thus this class
+can be used to parse messages coming from a buffered stream.
+
+The optional `seekable' argument is provided as a workaround for certain stdio
+libraries in which tell() discards buffered data before discovering that the
+lseek() system call doesn't work.  For maximum portability, you should set the
+seekable argument to zero to prevent that initial \code{tell} when passing in
+an unseekable object such as a file object created from a socket object.  If
+it is 1 on entry -- which it is by default -- the tell() method of the open
+file object is called once; if this raises an exception, seekable is reset to
+0.  For other nonzero values of seekable, this test is not made.
+
+To get the text of a particular header there are several methods:
+
+  str = m.getheader(name)
+  str = m.getrawheader(name)
+
+where name is the name of the header, e.g. 'Subject'.  The difference is that
+getheader() strips the leading and trailing whitespace, while getrawheader()
+doesn't.  Both functions retain embedded whitespace (including newlines)
+exactly as they are specified in the header, and leave the case of the text
+unchanged.
+
+For addresses and address lists there are functions
+
+  realname, mailaddress = m.getaddr(name)
+  list = m.getaddrlist(name)
+
+where the latter returns a list of (realname, mailaddr) tuples.
+
+There is also a method
+
+  time = m.getdate(name)
+
+which parses a Date-like field and returns a time-compatible tuple,
+i.e. a tuple such as returned by time.localtime() or accepted by
+time.mktime().
+
+See the class definition for lower level access methods.
+
+There are also some utility functions here.
+"""
+# Cleanup and extensions by Eric S. Raymond <esr@thyrsus.com>
+
+import time
+
+from warnings import warnpy3k
+warnpy3k("in 3.x, rfc822 has been removed in favor of the email package",
+         stacklevel=2)
+
+__all__ = ["Message","AddressList","parsedate","parsedate_tz","mktime_tz"]
+
+_blanklines = ('\r\n', '\n')            # Optimization for islast()
+
+
+class Message:
+    """Represents a single RFC 2822-compliant message."""
+
+    def __init__(self, fp, seekable = 1):
+        """Initialize the class instance and read the headers."""
+        if seekable == 1:
+            # Exercise tell() to make sure it works
+            # (and then assume seek() works, too)
+            try:
+                fp.tell()
+            except (AttributeError, IOError):
+                seekable = 0
+        self.fp = fp
+        self.seekable = seekable
+        self.startofheaders = None
+        self.startofbody = None
+        #
+        if self.seekable:
+            try:
+                self.startofheaders = self.fp.tell()
+            except IOError:
+                self.seekable = 0
+        #
+        self.readheaders()
+        #
+        if self.seekable:
+            try:
+                self.startofbody = self.fp.tell()
+            except IOError:
+                self.seekable = 0
+
+    def rewindbody(self):
+        """Rewind the file to the start of the body (if seekable)."""
+        if not self.seekable:
+            raise IOError, "unseekable file"
+        self.fp.seek(self.startofbody)
+
+    def readheaders(self):
+        """Read header lines.
+
+        Read header lines up to the entirely blank line that terminates them.
+        The (normally blank) line that ends the headers is skipped, but not
+        included in the returned list.  If a non-header line ends the headers,
+        (which is an error), an attempt is made to backspace over it; it is
+        never included in the returned list.
+
+        The variable self.status is set to the empty string if all went well,
+        otherwise it is an error message.  The variable self.headers is a
+        completely uninterpreted list of lines contained in the header (so
+        printing them will reproduce the header exactly as it appears in the
+        file).
+        """
+        self.dict = {}
+        self.unixfrom = ''
+        self.headers = lst = []
+        self.status = ''
+        headerseen = ""
+        firstline = 1
+        startofline = unread = tell = None
+        if hasattr(self.fp, 'unread'):
+            unread = self.fp.unread
+        elif self.seekable:
+            tell = self.fp.tell
+        while 1:
+            if tell:
+                try:
+                    startofline = tell()
+                except IOError:
+                    startofline = tell = None
+                    self.seekable = 0
+            line = self.fp.readline()
+            if not line:
+                self.status = 'EOF in headers'
+                break
+            # Skip unix From name time lines
+            if firstline and line.startswith('From '):
+                self.unixfrom = self.unixfrom + line
+                continue
+            firstline = 0
+            if headerseen and line[0] in ' \t':
+                # It's a continuation line.
+                lst.append(line)
+                x = (self.dict[headerseen] + "\n " + line.strip())
+                self.dict[headerseen] = x.strip()
+                continue
+            elif self.iscomment(line):
+                # It's a comment.  Ignore it.
+                continue
+            elif self.islast(line):
+                # Note! No pushback here!  The delimiter line gets eaten.
+                break
+            headerseen = self.isheader(line)
+            if headerseen:
+                # It's a legal header line, save it.
+                lst.append(line)
+                self.dict[headerseen] = line[len(headerseen)+1:].strip()
+                continue
+            else:
+                # It's not a header line; throw it back and stop here.
+                if not self.dict:
+                    self.status = 'No headers'
+                else:
+                    self.status = 'Non-header line where header expected'
+                # Try to undo the read.
+                if unread:
+                    unread(line)
+                elif tell:
+                    self.fp.seek(startofline)
+                else:
+                    self.status = self.status + '; bad seek'
+                break
+
+    def isheader(self, line):
+        """Determine whether a given line is a legal header.
+
+        This method should return the header name, suitably canonicalized.
+        You may override this method in order to use Message parsing on tagged
+        data in RFC 2822-like formats with special header formats.
+        """
+        i = line.find(':')
+        if i > 0:
+            return line[:i].lower()
+        return None
+
+    def islast(self, line):
+        """Determine whether a line is a legal end of RFC 2822 headers.
+
+        You may override this method if your application wants to bend the
+        rules, e.g. to strip trailing whitespace, or to recognize MH template
+        separators ('--------').  For convenience (e.g. for code reading from
+        sockets) a line consisting of \\r\\n also matches.
+        """
+        return line in _blanklines
+
+    def iscomment(self, line):
+        """Determine whether a line should be skipped entirely.
+
+        You may override this method in order to use Message parsing on tagged
+        data in RFC 2822-like formats that support embedded comments or
+        free-text data.
+        """
+        return False
+
+    def getallmatchingheaders(self, name):
+        """Find all header lines matching a given header name.
+
+        Look through the list of headers and find all lines matching a given
+        header name (and their continuation lines).  A list of the lines is
+        returned, without interpretation.  If the header does not occur, an
+        empty list is returned.  If the header occurs multiple times, all
+        occurrences are returned.  Case is not important in the header name.
+        """
+        name = name.lower() + ':'
+        n = len(name)
+        lst = []
+        hit = 0
+        for line in self.headers:
+            if line[:n].lower() == name:
+                hit = 1
+            elif not line[:1].isspace():
+                hit = 0
+            if hit:
+                lst.append(line)
+        return lst
+
+    def getfirstmatchingheader(self, name):
+        """Get the first header line matching name.
+
+        This is similar to getallmatchingheaders, but it returns only the
+        first matching header (and its continuation lines).
+        """
+        name = name.lower() + ':'
+        n = len(name)
+        lst = []
+        hit = 0
+        for line in self.headers:
+            if hit:
+                if not line[:1].isspace():
+                    break
+            elif line[:n].lower() == name:
+                hit = 1
+            if hit:
+                lst.append(line)
+        return lst
+
+    def getrawheader(self, name):
+        """A higher-level interface to getfirstmatchingheader().
+
+        Return a string containing the literal text of the header but with the
+        keyword stripped.  All leading, trailing and embedded whitespace is
+        kept in the string, however.  Return None if the header does not
+        occur.
+        """
+
+        lst = self.getfirstmatchingheader(name)
+        if not lst:
+            return None
+        lst[0] = lst[0][len(name) + 1:]
+        return ''.join(lst)
+
+    def getheader(self, name, default=None):
+        """Get the header value for a name.
+
+        This is the normal interface: it returns a stripped version of the
+        header value for a given header name, or None if it doesn't exist.
+        This uses the dictionary version which finds the *last* such header.
+        """
+        return self.dict.get(name.lower(), default)
+    get = getheader
+
+    def getheaders(self, name):
+        """Get all values for a header.
+
+        This returns a list of values for headers given more than once; each
+        value in the result list is stripped in the same way as the result of
+        getheader().  If the header is not given, return an empty list.
+        """
+        result = []
+        current = ''
+        have_header = 0
+        for s in self.getallmatchingheaders(name):
+            if s[0].isspace():
+                if current:
+                    current = "%s\n %s" % (current, s.strip())
+                else:
+                    current = s.strip()
+            else:
+                if have_header:
+                    result.append(current)
+                current = s[s.find(":") + 1:].strip()
+                have_header = 1
+        if have_header:
+            result.append(current)
+        return result
+
+    def getaddr(self, name):
+        """Get a single address from a header, as a tuple.
+
+        An example return value:
+        ('Guido van Rossum', 'guido@cwi.nl')
+        """
+        # New, by Ben Escoto
+        alist = self.getaddrlist(name)
+        if alist:
+            return alist[0]
+        else:
+            return (None, None)
+
+    def getaddrlist(self, name):
+        """Get a list of addresses from a header.
+
+        Retrieves a list of addresses from a header, where each address is a
+        tuple as returned by getaddr().  Scans all named headers, so it works
+        properly with multiple To: or Cc: headers for example.
+        """
+        raw = []
+        for h in self.getallmatchingheaders(name):
+            if h[0] in ' \t':
+                raw.append(h)
+            else:
+                if raw:
+                    raw.append(', ')
+                i = h.find(':')
+                if i > 0:
+                    addr = h[i+1:]
+                raw.append(addr)
+        alladdrs = ''.join(raw)
+        a = AddressList(alladdrs)
+        return a.addresslist
+
+    def getdate(self, name):
+        """Retrieve a date field from a header.
+
+        Retrieves a date field from the named header, returning a tuple
+        compatible with time.mktime().
+        """
+        try:
+            data = self[name]
+        except KeyError:
+            return None
+        return parsedate(data)
+
+    def getdate_tz(self, name):
+        """Retrieve a date field from a header as a 10-tuple.
+
+        The first 9 elements make up a tuple compatible with time.mktime(),
+        and the 10th is the offset of the poster's time zone from GMT/UTC.
+        """
+        try:
+            data = self[name]
+        except KeyError:
+            return None
+        return parsedate_tz(data)
+
+
+    # Access as a dictionary (only finds *last* header of each type):
+
+    def __len__(self):
+        """Get the number of headers in a message."""
+        return len(self.dict)
+
+    def __getitem__(self, name):
+        """Get a specific header, as from a dictionary."""
+        return self.dict[name.lower()]
+
+    def __setitem__(self, name, value):
+        """Set the value of a header.
+
+        Note: This is not a perfect inversion of __getitem__, because any
+        changed headers get stuck at the end of the raw-headers list rather
+        than where the altered header was.
+        """
+        del self[name] # Won't fail if it doesn't exist
+        self.dict[name.lower()] = value
+        text = name + ": " + value
+        for line in text.split("\n"):
+            self.headers.append(line + "\n")
+
+    def __delitem__(self, name):
+        """Delete all occurrences of a specific header, if it is present."""
+        name = name.lower()
+        if not name in self.dict:
+            return
+        del self.dict[name]
+        name = name + ':'
+        n = len(name)
+        lst = []
+        hit = 0
+        for i in range(len(self.headers)):
+            line = self.headers[i]
+            if line[:n].lower() == name:
+                hit = 1
+            elif not line[:1].isspace():
+                hit = 0
+            if hit:
+                lst.append(i)
+        for i in reversed(lst):
+            del self.headers[i]
+
+    def setdefault(self, name, default=""):
+        lowername = name.lower()
+        if lowername in self.dict:
+            return self.dict[lowername]
+        else:
+            text = name + ": " + default
+            for line in text.split("\n"):
+                self.headers.append(line + "\n")
+            self.dict[lowername] = default
+            return default
+
+    def has_key(self, name):
+        """Determine whether a message contains the named header."""
+        return name.lower() in self.dict
+
+    def __contains__(self, name):
+        """Determine whether a message contains the named header."""
+        return name.lower() in self.dict
+
+    def __iter__(self):
+        return iter(self.dict)
+
+    def keys(self):
+        """Get all of a message's header field names."""
+        return self.dict.keys()
+
+    def values(self):
+        """Get all of a message's header field values."""
+        return self.dict.values()
+
+    def items(self):
+        """Get all of a message's headers.
+
+        Returns a list of name, value tuples.
+        """
+        return self.dict.items()
+
+    def __str__(self):
+        return ''.join(self.headers)
+
+
+# Utility functions
+# -----------------
+
+# XXX Should fix unquote() and quote() to be really conformant.
+# XXX The inverses of the parse functions may also be useful.
+
+
+def unquote(s):
+    """Remove quotes from a string."""
+    if len(s) > 1:
+        if s.startswith('"') and s.endswith('"'):
+            return s[1:-1].replace('\\\\', '\\').replace('\\"', '"')
+        if s.startswith('<') and s.endswith('>'):
+            return s[1:-1]
+    return s
+
+
+def quote(s):
+    """Add quotes around a string."""
+    return s.replace('\\', '\\\\').replace('"', '\\"')
+
+
+def parseaddr(address):
+    """Parse an address into a (realname, mailaddr) tuple."""
+    a = AddressList(address)
+    lst = a.addresslist
+    if not lst:
+        return (None, None)
+    return lst[0]
+
+
+class AddrlistClass:
+    """Address parser class by Ben Escoto.
+
+    To understand what this class does, it helps to have a copy of
+    RFC 2822 in front of you.
+
+    http://www.faqs.org/rfcs/rfc2822.html
+
+    Note: this class interface is deprecated and may be removed in the future.
+    Use rfc822.AddressList instead.
+    """
+
+    def __init__(self, field):
+        """Initialize a new instance.
+
+        `field' is an unparsed address header field, containing one or more
+        addresses.
+        """
+        self.specials = '()<>@,:;.\"[]'
+        self.pos = 0
+        self.LWS = ' \t'
+        self.CR = '\r\n'
+        self.atomends = self.specials + self.LWS + self.CR
+        # Note that RFC 2822 now specifies `.' as obs-phrase, meaning that it
+        # is obsolete syntax.  RFC 2822 requires that we recognize obsolete
+        # syntax, so allow dots in phrases.
+        self.phraseends = self.atomends.replace('.', '')
+        self.field = field
+        self.commentlist = []
+
+    def gotonext(self):
+        """Parse up to the start of the next address."""
+        while self.pos < len(self.field):
+            if self.field[self.pos] in self.LWS + '\n\r':
+                self.pos = self.pos + 1
+            elif self.field[self.pos] == '(':
+                self.commentlist.append(self.getcomment())
+            else: break
+
+    def getaddrlist(self):
+        """Parse all addresses.
+
+        Returns a list containing all of the addresses.
+        """
+        result = []
+        ad = self.getaddress()
+        while ad:
+            result += ad
+            ad = self.getaddress()
+        return result
+
+    def getaddress(self):
+        """Parse the next address."""
+        self.commentlist = []
+        self.gotonext()
+
+        oldpos = self.pos
+        oldcl = self.commentlist
+        plist = self.getphraselist()
+
+        self.gotonext()
+        returnlist = []
+
+        if self.pos >= len(self.field):
+            # Bad email address technically, no domain.
+            if plist:
+                returnlist = [(' '.join(self.commentlist), plist[0])]
+
+        elif self.field[self.pos] in '.@':
+            # email address is just an addrspec
+            # this isn't very efficient since we start over
+            self.pos = oldpos
+            self.commentlist = oldcl
+            addrspec = self.getaddrspec()
+            returnlist = [(' '.join(self.commentlist), addrspec)]
+
+        elif self.field[self.pos] == ':':
+            # address is a group
+            returnlist = []
+
+            fieldlen = len(self.field)
+            self.pos += 1
+            while self.pos < len(self.field):
+                self.gotonext()
+                if self.pos < fieldlen and self.field[self.pos] == ';':
+                    self.pos += 1
+                    break
+                returnlist = returnlist + self.getaddress()
+
+        elif self.field[self.pos] == '<':
+            # Address is a phrase then a route addr
+            routeaddr = self.getrouteaddr()
+
+            if self.commentlist:
+                returnlist = [(' '.join(plist) + ' (' + \
+                         ' '.join(self.commentlist) + ')', routeaddr)]
+            else: returnlist = [(' '.join(plist), routeaddr)]
+
+        else:
+            if plist:
+                returnlist = [(' '.join(self.commentlist), plist[0])]
+            elif self.field[self.pos] in self.specials:
+                self.pos += 1
+
+        self.gotonext()
+        if self.pos < len(self.field) and self.field[self.pos] == ',':
+            self.pos += 1
+        return returnlist
+
+    def getrouteaddr(self):
+        """Parse a route address (Return-path value).
+
+        This method just skips all the route stuff and returns the addrspec.
+        """
+        if self.field[self.pos] != '<':
+            return
+
+        expectroute = 0
+        self.pos += 1
+        self.gotonext()
+        adlist = ""
+        while self.pos < len(self.field):
+            if expectroute:
+                self.getdomain()
+                expectroute = 0
+            elif self.field[self.pos] == '>':
+                self.pos += 1
+                break
+            elif self.field[self.pos] == '@':
+                self.pos += 1
+                expectroute = 1
+            elif self.field[self.pos] == ':':
+                self.pos += 1
+            else:
+                adlist = self.getaddrspec()
+                self.pos += 1
+                break
+            self.gotonext()
+
+        return adlist
+
+    def getaddrspec(self):
+        """Parse an RFC 2822 addr-spec."""
+        aslist = []
+
+        self.gotonext()
+        while self.pos < len(self.field):
+            if self.field[self.pos] == '.':
+                aslist.append('.')
+                self.pos += 1
+            elif self.field[self.pos] == '"':
+                aslist.append('"%s"' % self.getquote())
+            elif self.field[self.pos] in self.atomends:
+                break
+            else: aslist.append(self.getatom())
+            self.gotonext()
+
+        if self.pos >= len(self.field) or self.field[self.pos] != '@':
+            return ''.join(aslist)
+
+        aslist.append('@')
+        self.pos += 1
+        self.gotonext()
+        return ''.join(aslist) + self.getdomain()
+
+    def getdomain(self):
+        """Get the complete domain name from an address."""
+        sdlist = []
+        while self.pos < len(self.field):
+            if self.field[self.pos] in self.LWS:
+                self.pos += 1
+            elif self.field[self.pos] == '(':
+                self.commentlist.append(self.getcomment())
+            elif self.field[self.pos] == '[':
+                sdlist.append(self.getdomainliteral())
+            elif self.field[self.pos] == '.':
+                self.pos += 1
+                sdlist.append('.')
+            elif self.field[self.pos] in self.atomends:
+                break
+            else: sdlist.append(self.getatom())
+        return ''.join(sdlist)
+
+    def getdelimited(self, beginchar, endchars, allowcomments = 1):
+        """Parse a header fragment delimited by special characters.
+
+        `beginchar' is the start character for the fragment.  If self is not
+        looking at an instance of `beginchar' then getdelimited returns the
+        empty string.
+
+        `endchars' is a sequence of allowable end-delimiting characters.
+        Parsing stops when one of these is encountered.
+
+        If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed
+        within the parsed fragment.
+        """
+        if self.field[self.pos] != beginchar:
+            return ''
+
+        slist = ['']
+        quote = 0
+        self.pos += 1
+        while self.pos < len(self.field):
+            if quote == 1:
+                slist.append(self.field[self.pos])
+                quote = 0
+            elif self.field[self.pos] in endchars:
+                self.pos += 1
+                break
+            elif allowcomments and self.field[self.pos] == '(':
+                slist.append(self.getcomment())
+                continue        # have already advanced pos from getcomment
+            elif self.field[self.pos] == '\\':
+                quote = 1
+            else:
+                slist.append(self.field[self.pos])
+            self.pos += 1
+
+        return ''.join(slist)
+
+    def getquote(self):
+        """Get a quote-delimited fragment from self's field."""
+        return self.getdelimited('"', '"\r', 0)
+
+    def getcomment(self):
+        """Get a parenthesis-delimited fragment from self's field."""
+        return self.getdelimited('(', ')\r', 1)
+
+    def getdomainliteral(self):
+        """Parse an RFC 2822 domain-literal."""
+        return '[%s]' % self.getdelimited('[', ']\r', 0)
+
+    def getatom(self, atomends=None):
+        """Parse an RFC 2822 atom.
+
+        Optional atomends specifies a different set of end token delimiters
+        (the default is to use self.atomends).  This is used e.g. in
+        getphraselist() since phrase endings must not include the `.' (which
+        is legal in phrases)."""
+        atomlist = ['']
+        if atomends is None:
+            atomends = self.atomends
+
+        while self.pos < len(self.field):
+            if self.field[self.pos] in atomends:
+                break
+            else: atomlist.append(self.field[self.pos])
+            self.pos += 1
+
+        return ''.join(atomlist)
+
+    def getphraselist(self):
+        """Parse a sequence of RFC 2822 phrases.
+
+        A phrase is a sequence of words, which are in turn either RFC 2822
+        atoms or quoted-strings.  Phrases are canonicalized by squeezing all
+        runs of continuous whitespace into one space.
+        """
+        plist = []
+
+        while self.pos < len(self.field):
+            if self.field[self.pos] in self.LWS:
+                self.pos += 1
+            elif self.field[self.pos] == '"':
+                plist.append(self.getquote())
+            elif self.field[self.pos] == '(':
+                self.commentlist.append(self.getcomment())
+            elif self.field[self.pos] in self.phraseends:
+                break
+            else:
+                plist.append(self.getatom(self.phraseends))
+
+        return plist
+
+class AddressList(AddrlistClass):
+    """An AddressList encapsulates a list of parsed RFC 2822 addresses."""
+    def __init__(self, field):
+        AddrlistClass.__init__(self, field)
+        if field:
+            self.addresslist = self.getaddrlist()
+        else:
+            self.addresslist = []
+
+    def __len__(self):
+        return len(self.addresslist)
+
+    def __str__(self):
+        return ", ".join(map(dump_address_pair, self.addresslist))
+
+    def __add__(self, other):
+        # Set union
+        newaddr = AddressList(None)
+        newaddr.addresslist = self.addresslist[:]
+        for x in other.addresslist:
+            if not x in self.addresslist:
+                newaddr.addresslist.append(x)
+        return newaddr
+
+    def __iadd__(self, other):
+        # Set union, in-place
+        for x in other.addresslist:
+            if not x in self.addresslist:
+                self.addresslist.append(x)
+        return self
+
+    def __sub__(self, other):
+        # Set difference
+        newaddr = AddressList(None)
+        for x in self.addresslist:
+            if not x in other.addresslist:
+                newaddr.addresslist.append(x)
+        return newaddr
+
+    def __isub__(self, other):
+        # Set difference, in-place
+        for x in other.addresslist:
+            if x in self.addresslist:
+                self.addresslist.remove(x)
+        return self
+
+    def __getitem__(self, index):
+        # Make indexing, slices, and 'in' work
+        return self.addresslist[index]
+
+def dump_address_pair(pair):
+    """Dump a (name, address) pair in a canonicalized form."""
+    if pair[0]:
+        return '"' + pair[0] + '" <' + pair[1] + '>'
+    else:
+        return pair[1]
+
+# Parse a date field
+
+_monthnames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul',
+               'aug', 'sep', 'oct', 'nov', 'dec',
+               'january', 'february', 'march', 'april', 'may', 'june', 'july',
+               'august', 'september', 'october', 'november', 'december']
+_daynames = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
+
+# The timezone table does not include the military time zones defined
+# in RFC822, other than Z.  According to RFC1123, the description in
+# RFC822 gets the signs wrong, so we can't rely on any such time
+# zones.  RFC1123 recommends that numeric timezone indicators be used
+# instead of timezone names.
+
+_timezones = {'UT':0, 'UTC':0, 'GMT':0, 'Z':0,
+              'AST': -400, 'ADT': -300,  # Atlantic (used in Canada)
+              'EST': -500, 'EDT': -400,  # Eastern
+              'CST': -600, 'CDT': -500,  # Central
+              'MST': -700, 'MDT': -600,  # Mountain
+              'PST': -800, 'PDT': -700   # Pacific
+              }
+
+
+def parsedate_tz(data):
+    """Convert a date string to a time tuple.
+
+    Accounts for military timezones.
+    """
+    if not data:
+        return None
+    data = data.split()
+    if data[0][-1] in (',', '.') or data[0].lower() in _daynames:
+        # There's a dayname here. Skip it
+        del data[0]
+    else:
+        # no space after the "weekday,"?
+        i = data[0].rfind(',')
+        if i >= 0:
+            data[0] = data[0][i+1:]
+    if len(data) == 3: # RFC 850 date, deprecated
+        stuff = data[0].split('-')
+        if len(stuff) == 3:
+            data = stuff + data[1:]
+    if len(data) == 4:
+        s = data[3]
+        i = s.find('+')
+        if i > 0:
+            data[3:] = [s[:i], s[i+1:]]
+        else:
+            data.append('') # Dummy tz
+    if len(data) < 5:
+        return None
+    data = data[:5]
+    [dd, mm, yy, tm, tz] = data
+    mm = mm.lower()
+    if not mm in _monthnames:
+        dd, mm = mm, dd.lower()
+        if not mm in _monthnames:
+            return None
+    mm = _monthnames.index(mm)+1
+    if mm > 12: mm = mm - 12
+    if dd[-1] == ',':
+        dd = dd[:-1]
+    i = yy.find(':')
+    if i > 0:
+        yy, tm = tm, yy
+    if yy[-1] == ',':
+        yy = yy[:-1]
+    if not yy[0].isdigit():
+        yy, tz = tz, yy
+    if tm[-1] == ',':
+        tm = tm[:-1]
+    tm = tm.split(':')
+    if len(tm) == 2:
+        [thh, tmm] = tm
+        tss = '0'
+    elif len(tm) == 3:
+        [thh, tmm, tss] = tm
+    else:
+        return None
+    try:
+        yy = int(yy)
+        dd = int(dd)
+        thh = int(thh)
+        tmm = int(tmm)
+        tss = int(tss)
+    except ValueError:
+        return None
+    tzoffset = None
+    tz = tz.upper()
+    if tz in _timezones:
+        tzoffset = _timezones[tz]
+    else:
+        try:
+            tzoffset = int(tz)
+        except ValueError:
+            pass
+    # Convert a timezone offset into seconds ; -0500 -> -18000
+    if tzoffset:
+        if tzoffset < 0:
+            tzsign = -1
+            tzoffset = -tzoffset
+        else:
+            tzsign = 1
+        tzoffset = tzsign * ( (tzoffset//100)*3600 + (tzoffset % 100)*60)
+    return (yy, mm, dd, thh, tmm, tss, 0, 1, 0, tzoffset)
+
+
+def parsedate(data):
+    """Convert a time string to a time tuple."""
+    t = parsedate_tz(data)
+    if t is None:
+        return t
+    return t[:9]
+
+
+def mktime_tz(data):
+    """Turn a 10-tuple as returned by parsedate_tz() into a UTC timestamp."""
+    if data[9] is None:
+        # No zone info, so localtime is better assumption than GMT
+        return time.mktime(data[:8] + (-1,))
+    else:
+        t = time.mktime(data[:8] + (0,))
+        return t - data[9] - time.timezone
+
+def formatdate(timeval=None):
+    """Returns time format preferred for Internet standards.
+
+    Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
+
+    According to RFC 1123, day and month names must always be in
+    English.  If not for that, this code could use strftime().  It
+    can't because strftime() honors the locale and could generated
+    non-English names.
+    """
+    if timeval is None:
+        timeval = time.time()
+    timeval = time.gmtime(timeval)
+    return "%s, %02d %s %04d %02d:%02d:%02d GMT" % (
+            ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")[timeval[6]],
+            timeval[2],
+            ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
+             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")[timeval[1]-1],
+                                timeval[0], timeval[3], timeval[4], timeval[5])
+
+
+# When used as script, run a small test program.
+# The first command line argument must be a filename containing one
+# message in RFC-822 format.
+
+if __name__ == '__main__':
+    import sys, os
+    file = os.path.join(os.environ['HOME'], 'Mail/inbox/1')
+    if sys.argv[1:]: file = sys.argv[1]
+    f = open(file, 'r')
+    m = Message(f)
+    print 'From:', m.getaddr('from')
+    print 'To:', m.getaddrlist('to')
+    print 'Subject:', m.getheader('subject')
+    print 'Date:', m.getheader('date')
+    date = m.getdate_tz('date')
+    tz = date[-1]
+    date = time.localtime(mktime_tz(date))
+    if date:
+        print 'ParsedDate:', time.asctime(date),
+        hhmmss = tz
+        hhmm, ss = divmod(hhmmss, 60)
+        hh, mm = divmod(hhmm, 60)
+        print "%+03d%02d" % (hh, mm),
+        if ss: print ".%02d" % ss,
+        print
+    else:
+        print 'ParsedDate:', None
+    m.rewindbody()
+    n = 0
+    while f.readline():
+        n += 1
+    print 'Lines:', n
+    print '-'*70
+    print 'len =', len(m)
+    if 'Date' in m: print 'Date =', m['Date']
+    if 'X-Nonsense' in m: pass
+    print 'keys =', m.keys()
+    print 'values =', m.values()
+    print 'items =', m.items()
diff --git a/src/main/resources/PythonLibs/rlcompleter.py b/src/main/resources/PythonLibs/rlcompleter.py
new file mode 100644
index 0000000000000000000000000000000000000000..366c59c0cdf04ab9989a43d784341d905cdf11b6
--- /dev/null
+++ b/src/main/resources/PythonLibs/rlcompleter.py
@@ -0,0 +1,166 @@
+"""Word completion for GNU readline.
+
+The completer completes keywords, built-ins and globals in a selectable
+namespace (which defaults to __main__); when completing NAME.NAME..., it
+evaluates (!) the expression up to the last dot and completes its attributes.
+
+It's very cool to do "import sys" type "sys.", hit the completion key (twice),
+and see the list of names defined by the sys module!
+
+Tip: to use the tab key as the completion key, call
+
+    readline.parse_and_bind("tab: complete")
+
+Notes:
+
+- Exceptions raised by the completer function are *ignored* (and generally cause
+  the completion to fail).  This is a feature -- since readline sets the tty
+  device in raw (or cbreak) mode, printing a traceback wouldn't work well
+  without some complicated hoopla to save, reset and restore the tty state.
+
+- The evaluation of the NAME.NAME... form may cause arbitrary application
+  defined code to be executed if an object with a __getattr__ hook is found.
+  Since it is the responsibility of the application (or the user) to enable this
+  feature, I consider this an acceptable risk.  More complicated expressions
+  (e.g. function calls or indexing operations) are *not* evaluated.
+
+- GNU readline is also used by the built-in functions input() and
+raw_input(), and thus these also benefit/suffer from the completer
+features.  Clearly an interactive application can benefit by
+specifying its own completer function and using raw_input() for all
+its input.
+
+- When the original stdin is not a tty device, GNU readline is never
+  used, and this module (and the readline module) are silently inactive.
+
+"""
+
+import __builtin__
+import __main__
+
+__all__ = ["Completer"]
+
+class Completer:
+    def __init__(self, namespace = None):
+        """Create a new completer for the command line.
+
+        Completer([namespace]) -> completer instance.
+
+        If unspecified, the default namespace where completions are performed
+        is __main__ (technically, __main__.__dict__). Namespaces should be
+        given as dictionaries.
+
+        Completer instances should be used as the completion mechanism of
+        readline via the set_completer() call:
+
+        readline.set_completer(Completer(my_namespace).complete)
+        """
+
+        if namespace and not isinstance(namespace, dict):
+            raise TypeError,'namespace must be a dictionary'
+
+        # Don't bind to namespace quite yet, but flag whether the user wants a
+        # specific namespace or to use __main__.__dict__. This will allow us
+        # to bind to __main__.__dict__ at completion time, not now.
+        if namespace is None:
+            self.use_main_ns = 1
+        else:
+            self.use_main_ns = 0
+            self.namespace = namespace
+
+    def complete(self, text, state):
+        """Return the next possible completion for 'text'.
+
+        This is called successively with state == 0, 1, 2, ... until it
+        returns None.  The completion should begin with 'text'.
+
+        """
+        if self.use_main_ns:
+            self.namespace = __main__.__dict__
+
+        if state == 0:
+            if "." in text:
+                self.matches = self.attr_matches(text)
+            else:
+                self.matches = self.global_matches(text)
+        try:
+            return self.matches[state]
+        except IndexError:
+            return None
+
+    def _callable_postfix(self, val, word):
+        if hasattr(val, '__call__'):
+            word = word + "("
+        return word
+
+    def global_matches(self, text):
+        """Compute matches when text is a simple name.
+
+        Return a list of all keywords, built-in functions and names currently
+        defined in self.namespace that match.
+
+        """
+        import keyword
+        matches = []
+        n = len(text)
+        for word in keyword.kwlist:
+            if word[:n] == text:
+                matches.append(word)
+        for nspace in [__builtin__.__dict__, self.namespace]:
+            for word, val in nspace.items():
+                if word[:n] == text and word != "__builtins__":
+                    matches.append(self._callable_postfix(val, word))
+        return matches
+
+    def attr_matches(self, text):
+        """Compute matches when text contains a dot.
+
+        Assuming the text is of the form NAME.NAME....[NAME], and is
+        evaluatable in self.namespace, it will be evaluated and its attributes
+        (as revealed by dir()) are used as possible completions.  (For class
+        instances, class members are also considered.)
+
+        WARNING: this can still invoke arbitrary C code, if an object
+        with a __getattr__ hook is evaluated.
+
+        """
+        import re
+        m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
+        if not m:
+            return []
+        expr, attr = m.group(1, 3)
+        try:
+            thisobject = eval(expr, self.namespace)
+        except Exception:
+            return []
+
+        # get the content of the object, except __builtins__
+        words = dir(thisobject)
+        if "__builtins__" in words:
+            words.remove("__builtins__")
+
+        if hasattr(thisobject, '__class__'):
+            words.append('__class__')
+            words.extend(get_class_members(thisobject.__class__))
+        matches = []
+        n = len(attr)
+        for word in words:
+            if word[:n] == attr and hasattr(thisobject, word):
+                val = getattr(thisobject, word)
+                word = self._callable_postfix(val, "%s.%s" % (expr, word))
+                matches.append(word)
+        return matches
+
+def get_class_members(klass):
+    ret = dir(klass)
+    if hasattr(klass,'__bases__'):
+        for base in klass.__bases__:
+            ret = ret + get_class_members(base)
+    return ret
+
+try:
+    import readline
+except ImportError:
+    pass
+else:
+    readline.set_completer(Completer().complete)
diff --git a/src/main/resources/PythonLibs/robotparser.py b/src/main/resources/PythonLibs/robotparser.py
new file mode 100644
index 0000000000000000000000000000000000000000..1722863d144db7fc1956292892ebf49dc3f0cd3a
--- /dev/null
+++ b/src/main/resources/PythonLibs/robotparser.py
@@ -0,0 +1,222 @@
+""" robotparser.py
+
+    Copyright (C) 2000  Bastian Kleineidam
+
+    You can choose between two licenses when using this package:
+    1) GNU GPLv2
+    2) PSF license for Python 2.2
+
+    The robots.txt Exclusion Protocol is implemented as specified in
+    http://info.webcrawler.com/mak/projects/robots/norobots-rfc.html
+"""
+import urlparse
+import urllib
+
+__all__ = ["RobotFileParser"]
+
+
+class RobotFileParser:
+    """ This class provides a set of methods to read, parse and answer
+    questions about a single robots.txt file.
+
+    """
+
+    def __init__(self, url=''):
+        self.entries = []
+        self.default_entry = None
+        self.disallow_all = False
+        self.allow_all = False
+        self.set_url(url)
+        self.last_checked = 0
+
+    def mtime(self):
+        """Returns the time the robots.txt file was last fetched.
+
+        This is useful for long-running web spiders that need to
+        check for new robots.txt files periodically.
+
+        """
+        return self.last_checked
+
+    def modified(self):
+        """Sets the time the robots.txt file was last fetched to the
+        current time.
+
+        """
+        import time
+        self.last_checked = time.time()
+
+    def set_url(self, url):
+        """Sets the URL referring to a robots.txt file."""
+        self.url = url
+        self.host, self.path = urlparse.urlparse(url)[1:3]
+
+    def read(self):
+        """Reads the robots.txt URL and feeds it to the parser."""
+        opener = URLopener()
+        f = opener.open(self.url)
+        lines = [line.strip() for line in f]
+        f.close()
+        self.errcode = opener.errcode
+        if self.errcode in (401, 403):
+            self.disallow_all = True
+        elif self.errcode >= 400:
+            self.allow_all = True
+        elif self.errcode == 200 and lines:
+            self.parse(lines)
+
+    def _add_entry(self, entry):
+        if "*" in entry.useragents:
+            # the default entry is considered last
+            if self.default_entry is None:
+                # the first default entry wins
+                self.default_entry = entry
+        else:
+            self.entries.append(entry)
+
+    def parse(self, lines):
+        """parse the input lines from a robots.txt file.
+           We allow that a user-agent: line is not preceded by
+           one or more blank lines."""
+        # states:
+        #   0: start state
+        #   1: saw user-agent line
+        #   2: saw an allow or disallow line
+        state = 0
+        linenumber = 0
+        entry = Entry()
+
+        for line in lines:
+            linenumber += 1
+            if not line:
+                if state == 1:
+                    entry = Entry()
+                    state = 0
+                elif state == 2:
+                    self._add_entry(entry)
+                    entry = Entry()
+                    state = 0
+            # remove optional comment and strip line
+            i = line.find('#')
+            if i >= 0:
+                line = line[:i]
+            line = line.strip()
+            if not line:
+                continue
+            line = line.split(':', 1)
+            if len(line) == 2:
+                line[0] = line[0].strip().lower()
+                line[1] = urllib.unquote(line[1].strip())
+                if line[0] == "user-agent":
+                    if state == 2:
+                        self._add_entry(entry)
+                        entry = Entry()
+                    entry.useragents.append(line[1])
+                    state = 1
+                elif line[0] == "disallow":
+                    if state != 0:
+                        entry.rulelines.append(RuleLine(line[1], False))
+                        state = 2
+                elif line[0] == "allow":
+                    if state != 0:
+                        entry.rulelines.append(RuleLine(line[1], True))
+                        state = 2
+        if state == 2:
+            self._add_entry(entry)
+
+
+    def can_fetch(self, useragent, url):
+        """using the parsed robots.txt decide if useragent can fetch url"""
+        if self.disallow_all:
+            return False
+        if self.allow_all:
+            return True
+        # search for given user agent matches
+        # the first match counts
+        parsed_url = urlparse.urlparse(urllib.unquote(url))
+        url = urlparse.urlunparse(('', '', parsed_url.path,
+            parsed_url.params, parsed_url.query, parsed_url.fragment))
+        url = urllib.quote(url)
+        if not url:
+            url = "/"
+        for entry in self.entries:
+            if entry.applies_to(useragent):
+                return entry.allowance(url)
+        # try the default entry last
+        if self.default_entry:
+            return self.default_entry.allowance(url)
+        # agent not found ==> access granted
+        return True
+
+
+    def __str__(self):
+        return ''.join([str(entry) + "\n" for entry in self.entries])
+
+
+class RuleLine:
+    """A rule line is a single "Allow:" (allowance==True) or "Disallow:"
+       (allowance==False) followed by a path."""
+    def __init__(self, path, allowance):
+        if path == '' and not allowance:
+            # an empty value means allow all
+            allowance = True
+        self.path = urllib.quote(path)
+        self.allowance = allowance
+
+    def applies_to(self, filename):
+        return self.path == "*" or filename.startswith(self.path)
+
+    def __str__(self):
+        return (self.allowance and "Allow" or "Disallow") + ": " + self.path
+
+
+class Entry:
+    """An entry has one or more user-agents and zero or more rulelines"""
+    def __init__(self):
+        self.useragents = []
+        self.rulelines = []
+
+    def __str__(self):
+        ret = []
+        for agent in self.useragents:
+            ret.extend(["User-agent: ", agent, "\n"])
+        for line in self.rulelines:
+            ret.extend([str(line), "\n"])
+        return ''.join(ret)
+
+    def applies_to(self, useragent):
+        """check if this entry applies to the specified agent"""
+        # split the name token and make it lower case
+        useragent = useragent.split("/")[0].lower()
+        for agent in self.useragents:
+            if agent == '*':
+                # we have the catch-all agent
+                return True
+            agent = agent.lower()
+            if agent in useragent:
+                return True
+        return False
+
+    def allowance(self, filename):
+        """Preconditions:
+        - our agent applies to this entry
+        - filename is URL decoded"""
+        for line in self.rulelines:
+            if line.applies_to(filename):
+                return line.allowance
+        return True
+
+class URLopener(urllib.FancyURLopener):
+    def __init__(self, *args):
+        urllib.FancyURLopener.__init__(self, *args)
+        self.errcode = 200
+
+    def prompt_user_passwd(self, host, realm):
+        ## If robots.txt file is accessible only with a password,
+        ## we act as if the file wasn't there.
+        return None, None
+
+    def http_error_default(self, url, fp, errcode, errmsg, headers):
+        self.errcode = errcode
+        return urllib.FancyURLopener.http_error_default(self, url, fp, errcode,
+                                                        errmsg, headers)
diff --git a/src/main/resources/PythonLibs/runpy.py b/src/main/resources/PythonLibs/runpy.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4d7cc26a259bb0cc457a79af415435de1f4129f
--- /dev/null
+++ b/src/main/resources/PythonLibs/runpy.py
@@ -0,0 +1,278 @@
+"""runpy.py - locating and running Python code using the module namespace
+
+Provides support for locating and running Python scripts using the Python
+module namespace instead of the native filesystem.
+
+This allows Python code to play nicely with non-filesystem based PEP 302
+importers when locating support scripts as well as when importing modules.
+"""
+# Written by Nick Coghlan <ncoghlan at gmail.com>
+#    to implement PEP 338 (Executing Modules as Scripts)
+
+import sys
+import imp
+from pkgutil import read_code
+try:
+    from imp import get_loader
+except ImportError:
+    from pkgutil import get_loader
+
+__all__ = [
+    "run_module", "run_path",
+]
+
+class _TempModule(object):
+    """Temporarily replace a module in sys.modules with an empty namespace"""
+    def __init__(self, mod_name):
+        self.mod_name = mod_name
+        self.module = imp.new_module(mod_name)
+        self._saved_module = []
+
+    def __enter__(self):
+        mod_name = self.mod_name
+        try:
+            self._saved_module.append(sys.modules[mod_name])
+        except KeyError:
+            pass
+        sys.modules[mod_name] = self.module
+        return self
+
+    def __exit__(self, *args):
+        if self._saved_module:
+            sys.modules[self.mod_name] = self._saved_module[0]
+        else:
+            del sys.modules[self.mod_name]
+        self._saved_module = []
+
+class _ModifiedArgv0(object):
+    def __init__(self, value):
+        self.value = value
+        self._saved_value = self._sentinel = object()
+
+    def __enter__(self):
+        if self._saved_value is not self._sentinel:
+            raise RuntimeError("Already preserving saved value")
+        self._saved_value = sys.argv[0]
+        sys.argv[0] = self.value
+
+    def __exit__(self, *args):
+        self.value = self._sentinel
+        sys.argv[0] = self._saved_value
+
+def _run_code(code, run_globals, init_globals=None,
+              mod_name=None, mod_fname=None,
+              mod_loader=None, pkg_name=None):
+    """Helper to run code in nominated namespace"""
+    if init_globals is not None:
+        run_globals.update(init_globals)
+    run_globals.update(__name__ = mod_name,
+                       __file__ = mod_fname,
+                       __loader__ = mod_loader,
+                       __package__ = pkg_name)
+    exec code in run_globals
+    return run_globals
+
+def _run_module_code(code, init_globals=None,
+                    mod_name=None, mod_fname=None,
+                    mod_loader=None, pkg_name=None):
+    """Helper to run code in new namespace with sys modified"""
+    with _TempModule(mod_name) as temp_module, _ModifiedArgv0(mod_fname):
+        mod_globals = temp_module.module.__dict__
+        _run_code(code, mod_globals, init_globals,
+                  mod_name, mod_fname, mod_loader, pkg_name)
+    # Copy the globals of the temporary module, as they
+    # may be cleared when the temporary module goes away
+    return mod_globals.copy()
+
+
+# This helper is needed due to a missing component in the PEP 302
+# loader protocol (specifically, "get_filename" is non-standard)
+# Since we can't introduce new features in maintenance releases,
+# support was added to zipimporter under the name '_get_filename'
+def _get_filename(loader, mod_name):
+    for attr in ("get_filename", "_get_filename"):
+        meth = getattr(loader, attr, None)
+        if meth is not None:
+            return meth(mod_name)
+    return None
+
+# Helper to get the loader, code and filename for a module
+def _get_module_details(mod_name):
+    loader = get_loader(mod_name)
+    if loader is None:
+        raise ImportError("No module named %s" % mod_name)
+    if loader.is_package(mod_name):
+        if mod_name == "__main__" or mod_name.endswith(".__main__"):
+            raise ImportError("Cannot use package as __main__ module")
+        try:
+            pkg_main_name = mod_name + ".__main__"
+            return _get_module_details(pkg_main_name)
+        except ImportError, e:
+            raise ImportError(("%s; %r is a package and cannot " +
+                               "be directly executed") %(e, mod_name))
+    code = loader.get_code(mod_name)
+    if code is None:
+        raise ImportError("No code object available for %s" % mod_name)
+    filename = _get_filename(loader, mod_name)
+    return mod_name, loader, code, filename
+
+
+def _get_main_module_details():
+    # Helper that gives a nicer error message when attempting to
+    # execute a zipfile or directory by invoking __main__.py
+    main_name = "__main__"
+    try:
+        return _get_module_details(main_name)
+    except ImportError as exc:
+        if main_name in str(exc):
+            raise ImportError("can't find %r module in %r" %
+                              (main_name, sys.path[0]))
+        raise
+
+# This function is the actual implementation of the -m switch and direct
+# execution of zipfiles and directories and is deliberately kept private.
+# This avoids a repeat of the situation where run_module() no longer met the
+# needs of mainmodule.c, but couldn't be changed because it was public
+def _run_module_as_main(mod_name, alter_argv=True):
+    """Runs the designated module in the __main__ namespace
+
+       Note that the executed module will have full access to the
+       __main__ namespace. If this is not desirable, the run_module()
+       function should be used to run the module code in a fresh namespace.
+
+       At the very least, these variables in __main__ will be overwritten:
+           __name__
+           __file__
+           __loader__
+           __package__
+    """
+    try:
+        if alter_argv or mod_name != "__main__": # i.e. -m switch
+            mod_name, loader, code, fname = _get_module_details(mod_name)
+        else:          # i.e. directory or zipfile execution
+            mod_name, loader, code, fname = _get_main_module_details()
+    except ImportError as exc:
+        msg = "%s: %s" % (sys.executable, str(exc))
+        sys.exit(msg)
+    pkg_name = mod_name.rpartition('.')[0]
+    main_globals = sys.modules["__main__"].__dict__
+    if alter_argv:
+        sys.argv[0] = fname
+    return _run_code(code, main_globals, None,
+                     "__main__", fname, loader, pkg_name)
+
+def run_module(mod_name, init_globals=None,
+               run_name=None, alter_sys=False):
+    """Execute a module's code without importing it
+
+       Returns the resulting top level namespace dictionary
+    """
+    mod_name, loader, code, fname = _get_module_details(mod_name)
+    if run_name is None:
+        run_name = mod_name
+    pkg_name = mod_name.rpartition('.')[0]
+    if alter_sys:
+        return _run_module_code(code, init_globals, run_name,
+                                fname, loader, pkg_name)
+    else:
+        # Leave the sys module alone
+        return _run_code(code, {}, init_globals, run_name,
+                         fname, loader, pkg_name)
+
+
+# XXX (ncoghlan): Perhaps expose the C API function
+# as imp.get_importer instead of reimplementing it in Python?
+def _get_importer(path_name):
+    """Python version of PyImport_GetImporter C API function"""
+    cache = sys.path_importer_cache
+    try:
+        importer = cache[path_name]
+    except KeyError:
+        # Not yet cached. Flag as using the
+        # standard machinery until we finish
+        # checking the hooks
+        cache[path_name] = None
+        for hook in sys.path_hooks:
+            try:
+                importer = hook(path_name)
+                break
+            except ImportError:
+                pass
+        else:
+            # The following check looks a bit odd. The trick is that
+            # NullImporter raises ImportError if the supplied path is a
+            # *valid* directory entry (and hence able to be handled
+            # by the standard import machinery)
+            try:
+                importer = imp.NullImporter(path_name)
+            except ImportError:
+                return None
+        cache[path_name] = importer
+    return importer
+
+def _get_code_from_file(fname):
+    # Check for a compiled file first
+    with open(fname, "rb") as f:
+        code = read_code(f)
+    if code is None:
+        # That didn't work, so try it as normal source code
+        with open(fname, "rU") as f:
+            code = compile(f.read(), fname, 'exec')
+    return code
+
+def run_path(path_name, init_globals=None, run_name=None):
+    """Execute code located at the specified filesystem location
+
+       Returns the resulting top level namespace dictionary
+
+       The file path may refer directly to a Python script (i.e.
+       one that could be directly executed with execfile) or else
+       it may refer to a zipfile or directory containing a top
+       level __main__.py script.
+    """
+    if run_name is None:
+        run_name = "<run_path>"
+    importer = _get_importer(path_name)
+    if isinstance(importer, imp.NullImporter):
+        # Not a valid sys.path entry, so run the code directly
+        # execfile() doesn't help as we want to allow compiled files
+        code = _get_code_from_file(path_name)
+        return _run_module_code(code, init_globals, run_name, path_name)
+    else:
+        # Importer is defined for path, so add it to
+        # the start of sys.path
+        sys.path.insert(0, path_name)
+        try:
+            # Here's where things are a little different from the run_module
+            # case. There, we only had to replace the module in sys while the
+            # code was running and doing so was somewhat optional. Here, we
+            # have no choice and we have to remove it even while we read the
+            # code. If we don't do this, a __loader__ attribute in the
+            # existing __main__ module may prevent location of the new module.
+            main_name = "__main__"
+            saved_main = sys.modules[main_name]
+            del sys.modules[main_name]
+            try:
+                mod_name, loader, code, fname = _get_main_module_details()
+            finally:
+                sys.modules[main_name] = saved_main
+            pkg_name = ""
+            with _TempModule(run_name) as temp_module, \
+                 _ModifiedArgv0(path_name):
+                mod_globals = temp_module.module.__dict__
+                return _run_code(code, mod_globals, init_globals,
+                                    run_name, fname, loader, pkg_name).copy()
+        finally:
+            try:
+                sys.path.remove(path_name)
+            except ValueError:
+                pass
+
+
+if __name__ == "__main__":
+    # Run the module specified as the next command line argument
+    if len(sys.argv) < 2:
+        print >> sys.stderr, "No module specified for execution"
+    else:
+        del sys.argv[0] # Make the requested module sys.argv[0]
+        _run_module_as_main(sys.argv[0])
diff --git a/src/main/resources/PythonLibs/sched.py b/src/main/resources/PythonLibs/sched.py
new file mode 100644
index 0000000000000000000000000000000000000000..47646a10081143103f6a4070321207d7848d5435
--- /dev/null
+++ b/src/main/resources/PythonLibs/sched.py
@@ -0,0 +1,134 @@
+"""A generally useful event scheduler class.
+
+Each instance of this class manages its own queue.
+No multi-threading is implied; you are supposed to hack that
+yourself, or use a single instance per application.
+
+Each instance is parametrized with two functions, one that is
+supposed to return the current time, one that is supposed to
+implement a delay.  You can implement real-time scheduling by
+substituting time and sleep from built-in module time, or you can
+implement simulated time by writing your own functions.  This can
+also be used to integrate scheduling with STDWIN events; the delay
+function is allowed to modify the queue.  Time can be expressed as
+integers or floating point numbers, as long as it is consistent.
+
+Events are specified by tuples (time, priority, action, argument).
+As in UNIX, lower priority numbers mean higher priority; in this
+way the queue can be maintained as a priority queue.  Execution of the
+event means calling the action function, passing it the argument
+sequence in "argument" (remember that in Python, multiple function
+arguments are be packed in a sequence).
+The action function may be an instance method so it
+has another way to reference private data (besides global variables).
+"""
+
+# XXX The timefunc and delayfunc should have been defined as methods
+# XXX so you can define new kinds of schedulers using subclassing
+# XXX instead of having to define a module or class just to hold
+# XXX the global state of your particular time and delay functions.
+
+import heapq
+from collections import namedtuple
+
+__all__ = ["scheduler"]
+
+Event = namedtuple('Event', 'time, priority, action, argument')
+
+class scheduler:
+    def __init__(self, timefunc, delayfunc):
+        """Initialize a new instance, passing the time and delay
+        functions"""
+        self._queue = []
+        self.timefunc = timefunc
+        self.delayfunc = delayfunc
+
+    def enterabs(self, time, priority, action, argument):
+        """Enter a new event in the queue at an absolute time.
+
+        Returns an ID for the event which can be used to remove it,
+        if necessary.
+
+        """
+        event = Event(time, priority, action, argument)
+        heapq.heappush(self._queue, event)
+        return event # The ID
+
+    def enter(self, delay, priority, action, argument):
+        """A variant that specifies the time as a relative time.
+
+        This is actually the more commonly used interface.
+
+        """
+        time = self.timefunc() + delay
+        return self.enterabs(time, priority, action, argument)
+
+    def cancel(self, event):
+        """Remove an event from the queue.
+
+        This must be presented the ID as returned by enter().
+        If the event is not in the queue, this raises ValueError.
+
+        """
+        self._queue.remove(event)
+        heapq.heapify(self._queue)
+
+    def empty(self):
+        """Check whether the queue is empty."""
+        return not self._queue
+
+    def run(self):
+        """Execute events until the queue is empty.
+
+        When there is a positive delay until the first event, the
+        delay function is called and the event is left in the queue;
+        otherwise, the event is removed from the queue and executed
+        (its action function is called, passing it the argument).  If
+        the delay function returns prematurely, it is simply
+        restarted.
+
+        It is legal for both the delay function and the action
+        function to modify the queue or to raise an exception;
+        exceptions are not caught but the scheduler's state remains
+        well-defined so run() may be called again.
+
+        A questionable hack is added to allow other threads to run:
+        just after an event is executed, a delay of 0 is executed, to
+        avoid monopolizing the CPU when other threads are also
+        runnable.
+
+        """
+        # localize variable access to minimize overhead
+        # and to improve thread safety
+        q = self._queue
+        delayfunc = self.delayfunc
+        timefunc = self.timefunc
+        pop = heapq.heappop
+        while q:
+            time, priority, action, argument = checked_event = q[0]
+            now = timefunc()
+            if now < time:
+                delayfunc(time - now)
+            else:
+                event = pop(q)
+                # Verify that the event was not removed or altered
+                # by another thread after we last looked at q[0].
+                if event is checked_event:
+                    action(*argument)
+                    delayfunc(0)   # Let other threads run
+                else:
+                    heapq.heappush(q, event)
+
+    @property
+    def queue(self):
+        """An ordered list of upcoming events.
+
+        Events are named tuples with fields for:
+            time, priority, action, arguments
+
+        """
+        # Use heapq to sort the queue rather than using 'sorted(self._queue)'.
+        # With heapq, two events scheduled at the same time will show in
+        # the actual order they would be retrieved.
+        events = self._queue[:]
+        return map(heapq.heappop, [events]*len(events))
diff --git a/src/main/resources/PythonLibs/select.py b/src/main/resources/PythonLibs/select.py
new file mode 100644
index 0000000000000000000000000000000000000000..846b86c23173cc9df3922f397449233fceb25019
--- /dev/null
+++ b/src/main/resources/PythonLibs/select.py
@@ -0,0 +1,264 @@
+"""
+This is an select module for use on JVMs >= 1.5.
+It is documented, along with known issues and workarounds, on the jython wiki.
+http://wiki.python.org/jython/SelectModule
+"""
+
+import java.nio.channels.SelectableChannel
+import java.nio.channels.SelectionKey
+import java.nio.channels.Selector
+from java.nio.channels.SelectionKey import OP_ACCEPT, OP_CONNECT, OP_WRITE, OP_READ
+
+import errno
+import os
+import Queue
+import socket
+
+class error(Exception): pass
+
+ALL = None
+
+_exception_map = {
+
+# (<javaexception>, <circumstance>) : lambda: <code that raises the python equivalent>
+
+(java.nio.channels.ClosedChannelException, ALL) : error(errno.ENOTCONN, 'Socket is not connected'),
+(java.nio.channels.CancelledKeyException, ALL) : error(errno.ENOTCONN, 'Socket is not connected'),
+(java.nio.channels.IllegalBlockingModeException, ALL) : error(errno.ESOCKISBLOCKING, 'socket must be in non-blocking mode'),
+}
+
+def _map_exception(exc, circumstance=ALL):
+    try:
+        mapped_exception = _exception_map[(exc.__class__, circumstance)]
+        mapped_exception.java_exception = exc
+        return mapped_exception
+    except KeyError:
+        return error(-1, 'Unmapped java exception: <%s:%s>' % (exc.toString(), circumstance))
+
+POLLIN   = 1
+POLLOUT  = 2
+
+# The following event types are completely ignored on jython
+# Java does not support them, AFAICT
+# They are declared only to support code compatibility with cpython
+
+POLLPRI  = 4
+POLLERR  = 8
+POLLHUP  = 16
+POLLNVAL = 32
+
+def _getselectable(selectable_object):
+    try:
+        channel = selectable_object.getchannel()
+    except:
+        try:
+            channel = selectable_object.fileno().getChannel()
+        except:
+            raise TypeError("Object '%s' is not watchable" % selectable_object,
+                            errno.ENOTSOCK)
+    
+    if channel and not isinstance(channel, java.nio.channels.SelectableChannel):
+        raise TypeError("Object '%s' is not watchable" % selectable_object,
+                        errno.ENOTSOCK)
+    return channel
+
+class poll:
+
+    def __init__(self):
+        self.selector = java.nio.channels.Selector.open()
+        self.chanmap = {}
+        self.unconnected_sockets = []
+
+    def _register_channel(self, socket_object, channel, mask):
+        jmask = 0
+        if mask & POLLIN:
+            # Note that OP_READ is NOT a valid event on server socket channels.
+            if channel.validOps() & OP_ACCEPT:
+                jmask = OP_ACCEPT
+            else:
+                jmask = OP_READ
+        if mask & POLLOUT:
+            if channel.validOps() & OP_WRITE:
+                jmask |= OP_WRITE
+            if channel.validOps() & OP_CONNECT:
+                jmask |= OP_CONNECT
+        selectionkey = channel.register(self.selector, jmask)
+        self.chanmap[channel] = (socket_object, selectionkey)
+
+    def _check_unconnected_sockets(self):
+        temp_list = []
+        for socket_object, mask in self.unconnected_sockets:
+            channel = _getselectable(socket_object)
+            if channel is not None:
+                self._register_channel(socket_object, channel, mask)
+            else:
+                temp_list.append( (socket_object, mask) )
+        self.unconnected_sockets = temp_list
+
+    def register(self, socket_object, mask = POLLIN|POLLOUT|POLLPRI):
+        try:
+            channel = _getselectable(socket_object)
+            if channel is None:
+                # The socket is not yet connected, and thus has no channel
+                # Add it to a pending list, and return
+                self.unconnected_sockets.append( (socket_object, mask) )
+                return
+            self._register_channel(socket_object, channel, mask)
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+    def unregister(self, socket_object):
+        try:
+            channel = _getselectable(socket_object)
+            self.chanmap[channel][1].cancel()
+            del self.chanmap[channel]
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+    def _dopoll(self, timeout):
+        if timeout is None or timeout < 0:
+            self.selector.select()
+        else:
+            try:
+                timeout = int(timeout)
+                if not timeout:
+                    self.selector.selectNow()
+                else:
+                    # No multiplication required: both cpython and java use millisecond timeouts
+                    self.selector.select(timeout)
+            except ValueError, vx:
+                raise error("poll timeout must be a number of milliseconds or None", errno.EINVAL)
+        # The returned selectedKeys cannot be used from multiple threads!
+        return self.selector.selectedKeys()
+
+    def poll(self, timeout=None):
+        try:
+            self._check_unconnected_sockets()
+            selectedkeys = self._dopoll(timeout)
+            results = []
+            for k in selectedkeys.iterator():
+                jmask = k.readyOps()
+                pymask = 0
+                if jmask & OP_READ: pymask |= POLLIN
+                if jmask & OP_WRITE: pymask |= POLLOUT
+                if jmask & OP_ACCEPT: pymask |= POLLIN
+                if jmask & OP_CONNECT: pymask |= POLLOUT
+                # Now return the original userobject, and the return event mask
+                results.append( (self.chanmap[k.channel()][0], pymask) )
+            return results
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+    def _deregister_all(self):
+        try:
+            for k in self.selector.keys():
+                k.cancel()
+            # Keys are not actually removed from the selector until the next select operation.
+            self.selector.selectNow()
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+    def close(self):
+        try:
+            self._deregister_all()
+            self.selector.close()
+        except java.lang.Exception, jlx:
+            raise _map_exception(jlx)
+
+def _calcselecttimeoutvalue(value):
+    if value is None:
+        return None
+    try:
+        floatvalue = float(value)
+    except Exception, x:
+        raise TypeError("Select timeout value must be a number or None")
+    if value < 0:
+        raise error("Select timeout value cannot be negative", errno.EINVAL)
+    if floatvalue < 0.000001:
+        return 0
+    return int(floatvalue * 1000) # Convert to milliseconds
+
+# This cache for poll objects is required because of a bug in java on MS Windows
+# http://bugs.jython.org/issue1291
+
+class poll_object_cache:
+
+    def __init__(self):
+        self.is_windows = os._name == 'nt'
+        if self.is_windows:
+            self.poll_object_queue = Queue.Queue()
+        import atexit
+        atexit.register(self.finalize)
+
+    def get_poll_object(self):
+        if not self.is_windows:
+            return poll()
+        try:
+            return self.poll_object_queue.get(False)
+        except Queue.Empty:
+            return poll()
+
+    def release_poll_object(self, pobj):
+        if self.is_windows:
+            pobj._deregister_all()
+            self.poll_object_queue.put(pobj)
+        else:
+            pobj.close()
+
+    def finalize(self):
+        if self.is_windows:
+            while True:
+                try:
+                    p = self.poll_object_queue.get(False)
+                    p.close()
+                except Queue.Empty:
+                    return
+
+_poll_object_cache = poll_object_cache()
+
+def native_select(read_fd_list, write_fd_list, outofband_fd_list, timeout=None):
+    timeout = _calcselecttimeoutvalue(timeout)
+    # First create a poll object to do the actual watching.
+    pobj = _poll_object_cache.get_poll_object()
+    try:
+        registered_for_read = {}
+        # Check the read list
+        for fd in read_fd_list:
+            pobj.register(fd, POLLIN)
+            registered_for_read[fd] = 1
+        # And now the write list
+        for fd in write_fd_list:
+            if fd in registered_for_read:
+                # registering a second time overwrites the first
+                pobj.register(fd, POLLIN|POLLOUT)
+            else:
+                pobj.register(fd, POLLOUT)
+        results = pobj.poll(timeout)
+        # Now start preparing the results
+        read_ready_list, write_ready_list, oob_ready_list = [], [], []
+        for fd, mask in results:
+            if mask & POLLIN:
+                read_ready_list.append(fd)
+            if mask & POLLOUT:
+                write_ready_list.append(fd)
+        return read_ready_list, write_ready_list, oob_ready_list
+    finally:
+        _poll_object_cache.release_poll_object(pobj)
+
+select = native_select
+
+def cpython_compatible_select(read_fd_list, write_fd_list, outofband_fd_list, timeout=None):
+    # First turn all sockets to non-blocking
+    # keeping track of which ones have changed
+    modified_channels = []
+    try:
+        for socket_list in [read_fd_list, write_fd_list, outofband_fd_list]:
+            for s in socket_list:
+                channel = _getselectable(s)
+                if channel.isBlocking():
+                    modified_channels.append(channel)
+                    channel.configureBlocking(0)
+        return native_select(read_fd_list, write_fd_list, outofband_fd_list, timeout)
+    finally:
+        for channel in modified_channels:
+            channel.configureBlocking(1)
diff --git a/src/main/resources/PythonLibs/sets.py b/src/main/resources/PythonLibs/sets.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe31a0b7e979ca8aa67a4ca7c41b04318b5e69df
--- /dev/null
+++ b/src/main/resources/PythonLibs/sets.py
@@ -0,0 +1,557 @@
+"""Classes to represent arbitrary sets (including sets of sets).
+
+This module implements sets using dictionaries whose values are
+ignored.  The usual operations (union, intersection, deletion, etc.)
+are provided as both methods and operators.
+
+Important: sets are not sequences!  While they support 'x in s',
+'len(s)', and 'for x in s', none of those operations are unique for
+sequences; for example, mappings support all three as well.  The
+characteristic operation for sequences is subscripting with small
+integers: s[i], for i in range(len(s)).  Sets don't support
+subscripting at all.  Also, sequences allow multiple occurrences and
+their elements have a definite order; sets on the other hand don't
+record multiple occurrences and don't remember the order of element
+insertion (which is why they don't support s[i]).
+
+The following classes are provided:
+
+BaseSet -- All the operations common to both mutable and immutable
+    sets. This is an abstract class, not meant to be directly
+    instantiated.
+
+Set -- Mutable sets, subclass of BaseSet; not hashable.
+
+ImmutableSet -- Immutable sets, subclass of BaseSet; hashable.
+    An iterable argument is mandatory to create an ImmutableSet.
+
+_TemporarilyImmutableSet -- A wrapper around a Set, hashable,
+    giving the same hash value as the immutable set equivalent
+    would have.  Do not use this class directly.
+
+Only hashable objects can be added to a Set. In particular, you cannot
+really add a Set as an element to another Set; if you try, what is
+actually added is an ImmutableSet built from it (it compares equal to
+the one you tried adding).
+
+When you ask if `x in y' where x is a Set and y is a Set or
+ImmutableSet, x is wrapped into a _TemporarilyImmutableSet z, and
+what's tested is actually `z in y'.
+
+"""
+
+# Code history:
+#
+# - Greg V. Wilson wrote the first version, using a different approach
+#   to the mutable/immutable problem, and inheriting from dict.
+#
+# - Alex Martelli modified Greg's version to implement the current
+#   Set/ImmutableSet approach, and make the data an attribute.
+#
+# - Guido van Rossum rewrote much of the code, made some API changes,
+#   and cleaned up the docstrings.
+#
+# - Raymond Hettinger added a number of speedups and other
+#   improvements.
+
+from itertools import ifilter, ifilterfalse
+
+__all__ = ['BaseSet', 'Set', 'ImmutableSet']
+
+import warnings
+warnings.warn("the sets module is deprecated", DeprecationWarning,
+                stacklevel=2)
+
+class BaseSet(object):
+    """Common base class for mutable and immutable sets."""
+
+    __slots__ = ['_data']
+
+    # Constructor
+
+    def __init__(self):
+        """This is an abstract class."""
+        # Don't call this from a concrete subclass!
+        if self.__class__ is BaseSet:
+            raise TypeError, ("BaseSet is an abstract class.  "
+                              "Use Set or ImmutableSet.")
+
+    # Standard protocols: __len__, __repr__, __str__, __iter__
+
+    def __len__(self):
+        """Return the number of elements of a set."""
+        return len(self._data)
+
+    def __repr__(self):
+        """Return string representation of a set.
+
+        This looks like 'Set([<list of elements>])'.
+        """
+        return self._repr()
+
+    # __str__ is the same as __repr__
+    __str__ = __repr__
+
+    def _repr(self, sorted=False):
+        elements = self._data.keys()
+        if sorted:
+            elements.sort()
+        return '%s(%r)' % (self.__class__.__name__, elements)
+
+    def __iter__(self):
+        """Return an iterator over the elements or a set.
+
+        This is the keys iterator for the underlying dict.
+        """
+        return self._data.iterkeys()
+
+    # Three-way comparison is not supported.  However, because __eq__ is
+    # tried before __cmp__, if Set x == Set y, x.__eq__(y) returns True and
+    # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this
+    # case).
+
+    def __cmp__(self, other):
+        raise TypeError, "can't compare sets using cmp()"
+
+    # Equality comparisons using the underlying dicts.  Mixed-type comparisons
+    # are allowed here, where Set == z for non-Set z always returns False,
+    # and Set != z always True.  This allows expressions like "x in y" to
+    # give the expected result when y is a sequence of mixed types, not
+    # raising a pointless TypeError just because y contains a Set, or x is
+    # a Set and y contain's a non-set ("in" invokes only __eq__).
+    # Subtle:  it would be nicer if __eq__ and __ne__ could return
+    # NotImplemented instead of True or False.  Then the other comparand
+    # would get a chance to determine the result, and if the other comparand
+    # also returned NotImplemented then it would fall back to object address
+    # comparison (which would always return False for __eq__ and always
+    # True for __ne__).  However, that doesn't work, because this type
+    # *also* implements __cmp__:  if, e.g., __eq__ returns NotImplemented,
+    # Python tries __cmp__ next, and the __cmp__ here then raises TypeError.
+
+    def __eq__(self, other):
+        if isinstance(other, BaseSet):
+            return self._data == other._data
+        else:
+            return False
+
+    def __ne__(self, other):
+        if isinstance(other, BaseSet):
+            return self._data != other._data
+        else:
+            return True
+
+    # Copying operations
+
+    def copy(self):
+        """Return a shallow copy of a set."""
+        result = self.__class__()
+        result._data.update(self._data)
+        return result
+
+    __copy__ = copy # For the copy module
+
+    def __deepcopy__(self, memo):
+        """Return a deep copy of a set; used by copy module."""
+        # This pre-creates the result and inserts it in the memo
+        # early, in case the deep copy recurses into another reference
+        # to this same set.  A set can't be an element of itself, but
+        # it can certainly contain an object that has a reference to
+        # itself.
+        from copy import deepcopy
+        result = self.__class__()
+        memo[id(self)] = result
+        data = result._data
+        value = True
+        for elt in self:
+            data[deepcopy(elt, memo)] = value
+        return result
+
+    # Standard set operations: union, intersection, both differences.
+    # Each has an operator version (e.g. __or__, invoked with |) and a
+    # method version (e.g. union).
+    # Subtle:  Each pair requires distinct code so that the outcome is
+    # correct when the type of other isn't suitable.  For example, if
+    # we did "union = __or__" instead, then Set().union(3) would return
+    # NotImplemented instead of raising TypeError (albeit that *why* it
+    # raises TypeError as-is is also a bit subtle).
+
+    def __or__(self, other):
+        """Return the union of two sets as a new set.
+
+        (I.e. all elements that are in either set.)
+        """
+        if not isinstance(other, BaseSet):
+            return NotImplemented
+        return self.union(other)
+
+    def union(self, other):
+        """Return the union of two sets as a new set.
+
+        (I.e. all elements that are in either set.)
+        """
+        result = self.__class__(self)
+        result._update(other)
+        return result
+
+    def __and__(self, other):
+        """Return the intersection of two sets as a new set.
+
+        (I.e. all elements that are in both sets.)
+        """
+        if not isinstance(other, BaseSet):
+            return NotImplemented
+        return self.intersection(other)
+
+    def intersection(self, other):
+        """Return the intersection of two sets as a new set.
+
+        (I.e. all elements that are in both sets.)
+        """
+        if not isinstance(other, BaseSet):
+            other = Set(other)
+        if len(self) <= len(other):
+            little, big = self, other
+        else:
+            little, big = other, self
+        common = ifilter(big._data.__contains__, little)
+        return self.__class__(common)
+
+    def __xor__(self, other):
+        """Return the symmetric difference of two sets as a new set.
+
+        (I.e. all elements that are in exactly one of the sets.)
+        """
+        if not isinstance(other, BaseSet):
+            return NotImplemented
+        return self.symmetric_difference(other)
+
+    def symmetric_difference(self, other):
+        """Return the symmetric difference of two sets as a new set.
+
+        (I.e. all elements that are in exactly one of the sets.)
+        """
+        result = self.__class__()
+        data = result._data
+        value = True
+        selfdata = self._data
+        try:
+            otherdata = other._data
+        except AttributeError:
+            otherdata = Set(other)._data
+        for elt in ifilterfalse(otherdata.__contains__, selfdata):
+            data[elt] = value
+        for elt in ifilterfalse(selfdata.__contains__, otherdata):
+            data[elt] = value
+        return result
+
+    def  __sub__(self, other):
+        """Return the difference of two sets as a new Set.
+
+        (I.e. all elements that are in this set and not in the other.)
+        """
+        if not isinstance(other, BaseSet):
+            return NotImplemented
+        return self.difference(other)
+
+    def difference(self, other):
+        """Return the difference of two sets as a new Set.
+
+        (I.e. all elements that are in this set and not in the other.)
+        """
+        result = self.__class__()
+        data = result._data
+        try:
+            otherdata = other._data
+        except AttributeError:
+            otherdata = Set(other)._data
+        value = True
+        for elt in ifilterfalse(otherdata.__contains__, self):
+            data[elt] = value
+        return result
+
+    # Membership test
+
+    def __contains__(self, element):
+        """Report whether an element is a member of a set.
+
+        (Called in response to the expression `element in self'.)
+        """
+        try:
+            return element in self._data
+        except TypeError:
+            transform = getattr(element, "__as_temporarily_immutable__", None)
+            if transform is None:
+                raise # re-raise the TypeError exception we caught
+            return transform() in self._data
+
+    # Subset and superset test
+
+    def issubset(self, other):
+        """Report whether another set contains this set."""
+        self._binary_sanity_check(other)
+        if len(self) > len(other):  # Fast check for obvious cases
+            return False
+        for elt in ifilterfalse(other._data.__contains__, self):
+            return False
+        return True
+
+    def issuperset(self, other):
+        """Report whether this set contains another set."""
+        self._binary_sanity_check(other)
+        if len(self) < len(other):  # Fast check for obvious cases
+            return False
+        for elt in ifilterfalse(self._data.__contains__, other):
+            return False
+        return True
+
+    # Inequality comparisons using the is-subset relation.
+    __le__ = issubset
+    __ge__ = issuperset
+
+    def __lt__(self, other):
+        self._binary_sanity_check(other)
+        return len(self) < len(other) and self.issubset(other)
+
+    def __gt__(self, other):
+        self._binary_sanity_check(other)
+        return len(self) > len(other) and self.issuperset(other)
+
+    # We inherit object.__hash__, so we must deny this explicitly
+    __hash__ = None
+
+    # Assorted helpers
+
+    def _binary_sanity_check(self, other):
+        # Check that the other argument to a binary operation is also
+        # a set, raising a TypeError otherwise.
+        if not isinstance(other, BaseSet):
+            raise TypeError, "Binary operation only permitted between sets"
+
+    def _compute_hash(self):
+        # Calculate hash code for a set by xor'ing the hash codes of
+        # the elements.  This ensures that the hash code does not depend
+        # on the order in which elements are added to the set.  This is
+        # not called __hash__ because a BaseSet should not be hashable;
+        # only an ImmutableSet is hashable.
+        result = 0
+        for elt in self:
+            result ^= hash(elt)
+        return result
+
+    def _update(self, iterable):
+        # The main loop for update() and the subclass __init__() methods.
+        data = self._data
+
+        # Use the fast update() method when a dictionary is available.
+        if isinstance(iterable, BaseSet):
+            data.update(iterable._data)
+            return
+
+        value = True
+
+        if type(iterable) in (list, tuple, xrange):
+            # Optimized: we know that __iter__() and next() can't
+            # raise TypeError, so we can move 'try:' out of the loop.
+            it = iter(iterable)
+            while True:
+                try:
+                    for element in it:
+                        data[element] = value
+                    return
+                except TypeError:
+                    transform = getattr(element, "__as_immutable__", None)
+                    if transform is None:
+                        raise # re-raise the TypeError exception we caught
+                    data[transform()] = value
+        else:
+            # Safe: only catch TypeError where intended
+            for element in iterable:
+                try:
+                    data[element] = value
+                except TypeError:
+                    transform = getattr(element, "__as_immutable__", None)
+                    if transform is None:
+                        raise # re-raise the TypeError exception we caught
+                    data[transform()] = value
+
+
+class ImmutableSet(BaseSet):
+    """Immutable set class."""
+
+    __slots__ = ['_hashcode']
+
+    # BaseSet + hashing
+
+    def __init__(self, iterable=None):
+        """Construct an immutable set from an optional iterable."""
+        self._hashcode = None
+        self._data = {}
+        if iterable is not None:
+            self._update(iterable)
+
+    def __hash__(self):
+        if self._hashcode is None:
+            self._hashcode = self._compute_hash()
+        return self._hashcode
+
+    def __getstate__(self):
+        return self._data, self._hashcode
+
+    def __setstate__(self, state):
+        self._data, self._hashcode = state
+
+class Set(BaseSet):
+    """ Mutable set class."""
+
+    __slots__ = []
+
+    # BaseSet + operations requiring mutability; no hashing
+
+    def __init__(self, iterable=None):
+        """Construct a set from an optional iterable."""
+        self._data = {}
+        if iterable is not None:
+            self._update(iterable)
+
+    def __getstate__(self):
+        # getstate's results are ignored if it is not
+        return self._data,
+
+    def __setstate__(self, data):
+        self._data, = data
+
+    # In-place union, intersection, differences.
+    # Subtle:  The xyz_update() functions deliberately return None,
+    # as do all mutating operations on built-in container types.
+    # The __xyz__ spellings have to return self, though.
+
+    def __ior__(self, other):
+        """Update a set with the union of itself and another."""
+        self._binary_sanity_check(other)
+        self._data.update(other._data)
+        return self
+
+    def union_update(self, other):
+        """Update a set with the union of itself and another."""
+        self._update(other)
+
+    def __iand__(self, other):
+        """Update a set with the intersection of itself and another."""
+        self._binary_sanity_check(other)
+        self._data = (self & other)._data
+        return self
+
+    def intersection_update(self, other):
+        """Update a set with the intersection of itself and another."""
+        if isinstance(other, BaseSet):
+            self &= other
+        else:
+            self._data = (self.intersection(other))._data
+
+    def __ixor__(self, other):
+        """Update a set with the symmetric difference of itself and another."""
+        self._binary_sanity_check(other)
+        self.symmetric_difference_update(other)
+        return self
+
+    def symmetric_difference_update(self, other):
+        """Update a set with the symmetric difference of itself and another."""
+        data = self._data
+        value = True
+        if not isinstance(other, BaseSet):
+            other = Set(other)
+        if self is other:
+            self.clear()
+        for elt in other:
+            if elt in data:
+                del data[elt]
+            else:
+                data[elt] = value
+
+    def __isub__(self, other):
+        """Remove all elements of another set from this set."""
+        self._binary_sanity_check(other)
+        self.difference_update(other)
+        return self
+
+    def difference_update(self, other):
+        """Remove all elements of another set from this set."""
+        data = self._data
+        if not isinstance(other, BaseSet):
+            other = Set(other)
+        if self is other:
+            self.clear()
+        for elt in ifilter(data.__contains__, other):
+            del data[elt]
+
+    # Python dict-like mass mutations: update, clear
+
+    def update(self, iterable):
+        """Add all values from an iterable (such as a list or file)."""
+        self._update(iterable)
+
+    def clear(self):
+        """Remove all elements from this set."""
+        self._data.clear()
+
+    # Single-element mutations: add, remove, discard
+
+    def add(self, element):
+        """Add an element to a set.
+
+        This has no effect if the element is already present.
+        """
+        try:
+            self._data[element] = True
+        except TypeError:
+            transform = getattr(element, "__as_immutable__", None)
+            if transform is None:
+                raise # re-raise the TypeError exception we caught
+            self._data[transform()] = True
+
+    def remove(self, element):
+        """Remove an element from a set; it must be a member.
+
+        If the element is not a member, raise a KeyError.
+        """
+        try:
+            del self._data[element]
+        except TypeError:
+            transform = getattr(element, "__as_temporarily_immutable__", None)
+            if transform is None:
+                raise # re-raise the TypeError exception we caught
+            del self._data[transform()]
+
+    def discard(self, element):
+        """Remove an element from a set if it is a member.
+
+        If the element is not a member, do nothing.
+        """
+        try:
+            self.remove(element)
+        except KeyError:
+            pass
+
+    def pop(self):
+        """Remove and return an arbitrary set element."""
+        return self._data.popitem()[0]
+
+    def __as_immutable__(self):
+        # Return a copy of self as an immutable set
+        return ImmutableSet(self)
+
+    def __as_temporarily_immutable__(self):
+        # Return self wrapped in a temporarily immutable set
+        return _TemporarilyImmutableSet(self)
+
+
+class _TemporarilyImmutableSet(BaseSet):
+    # Wrap a mutable set as if it was temporarily immutable.
+    # This only supplies hashing and equality comparisons.
+
+    def __init__(self, set):
+        self._set = set
+        self._data = set._data  # Needed by ImmutableSet.__eq__()
+
+    def __hash__(self):
+        return self._set._compute_hash()
diff --git a/src/main/resources/PythonLibs/sgmllib.py b/src/main/resources/PythonLibs/sgmllib.py
new file mode 100644
index 0000000000000000000000000000000000000000..104b25f2a07b0e716c40328d1878f56e774d8169
--- /dev/null
+++ b/src/main/resources/PythonLibs/sgmllib.py
@@ -0,0 +1,553 @@
+"""A parser for SGML, using the derived class as a static DTD."""
+
+# XXX This only supports those SGML features used by HTML.
+
+# XXX There should be a way to distinguish between PCDATA (parsed
+# character data -- the normal case), RCDATA (replaceable character
+# data -- only char and entity references and end tags are special)
+# and CDATA (character data -- only end tags are special).  RCDATA is
+# not supported at all.
+
+
+from warnings import warnpy3k
+warnpy3k("the sgmllib module has been removed in Python 3.0",
+         stacklevel=2)
+del warnpy3k
+
+import markupbase
+import re
+
+__all__ = ["SGMLParser", "SGMLParseError"]
+
+# Regular expressions used for parsing
+
+interesting = re.compile('[&<]')
+incomplete = re.compile('&([a-zA-Z][a-zA-Z0-9]*|#[0-9]*)?|'
+                           '<([a-zA-Z][^<>]*|'
+                              '/([a-zA-Z][^<>]*)?|'
+                              '![^<>]*)?')
+
+entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
+charref = re.compile('&#([0-9]+)[^0-9]')
+
+starttagopen = re.compile('<[>a-zA-Z]')
+shorttagopen = re.compile('<[a-zA-Z][-.a-zA-Z0-9]*/')
+shorttag = re.compile('<([a-zA-Z][-.a-zA-Z0-9]*)/([^/]*)/')
+piclose = re.compile('>')
+endbracket = re.compile('[<>]')
+tagfind = re.compile('[a-zA-Z][-_.a-zA-Z0-9]*')
+attrfind = re.compile(
+    r'\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)(\s*=\s*'
+    r'(\'[^\']*\'|"[^"]*"|[][\-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?')
+
+
+class SGMLParseError(RuntimeError):
+    """Exception raised for all parse errors."""
+    pass
+
+
+# SGML parser base class -- find tags and call handler functions.
+# Usage: p = SGMLParser(); p.feed(data); ...; p.close().
+# The dtd is defined by deriving a class which defines methods
+# with special names to handle tags: start_foo and end_foo to handle
+# <foo> and </foo>, respectively, or do_foo to handle <foo> by itself.
+# (Tags are converted to lower case for this purpose.)  The data
+# between tags is passed to the parser by calling self.handle_data()
+# with some data as argument (the data may be split up in arbitrary
+# chunks).  Entity references are passed by calling
+# self.handle_entityref() with the entity reference as argument.
+
+class SGMLParser(markupbase.ParserBase):
+    # Definition of entities -- derived classes may override
+    entity_or_charref = re.compile('&(?:'
+      '([a-zA-Z][-.a-zA-Z0-9]*)|#([0-9]+)'
+      ')(;?)')
+
+    def __init__(self, verbose=0):
+        """Initialize and reset this instance."""
+        self.verbose = verbose
+        self.reset()
+
+    def reset(self):
+        """Reset this instance. Loses all unprocessed data."""
+        self.__starttag_text = None
+        self.rawdata = ''
+        self.stack = []
+        self.lasttag = '???'
+        self.nomoretags = 0
+        self.literal = 0
+        markupbase.ParserBase.reset(self)
+
+    def setnomoretags(self):
+        """Enter literal mode (CDATA) till EOF.
+
+        Intended for derived classes only.
+        """
+        self.nomoretags = self.literal = 1
+
+    def setliteral(self, *args):
+        """Enter literal mode (CDATA).
+
+        Intended for derived classes only.
+        """
+        self.literal = 1
+
+    def feed(self, data):
+        """Feed some data to the parser.
+
+        Call this as often as you want, with as little or as much text
+        as you want (may include '\n').  (This just saves the text,
+        all the processing is done by goahead().)
+        """
+
+        self.rawdata = self.rawdata + data
+        self.goahead(0)
+
+    def close(self):
+        """Handle the remaining data."""
+        self.goahead(1)
+
+    def error(self, message):
+        raise SGMLParseError(message)
+
+    # Internal -- handle data as far as reasonable.  May leave state
+    # and data to be processed by a subsequent call.  If 'end' is
+    # true, force handling all data as if followed by EOF marker.
+    def goahead(self, end):
+        rawdata = self.rawdata
+        i = 0
+        n = len(rawdata)
+        while i < n:
+            if self.nomoretags:
+                self.handle_data(rawdata[i:n])
+                i = n
+                break
+            match = interesting.search(rawdata, i)
+            if match: j = match.start()
+            else: j = n
+            if i < j:
+                self.handle_data(rawdata[i:j])
+            i = j
+            if i == n: break
+            if rawdata[i] == '<':
+                if starttagopen.match(rawdata, i):
+                    if self.literal:
+                        self.handle_data(rawdata[i])
+                        i = i+1
+                        continue
+                    k = self.parse_starttag(i)
+                    if k < 0: break
+                    i = k
+                    continue
+                if rawdata.startswith("</", i):
+                    k = self.parse_endtag(i)
+                    if k < 0: break
+                    i = k
+                    self.literal = 0
+                    continue
+                if self.literal:
+                    if n > (i + 1):
+                        self.handle_data("<")
+                        i = i+1
+                    else:
+                        # incomplete
+                        break
+                    continue
+                if rawdata.startswith("<!--", i):
+                        # Strictly speaking, a comment is --.*--
+                        # within a declaration tag <!...>.
+                        # This should be removed,
+                        # and comments handled only in parse_declaration.
+                    k = self.parse_comment(i)
+                    if k < 0: break
+                    i = k
+                    continue
+                if rawdata.startswith("<?", i):
+                    k = self.parse_pi(i)
+                    if k < 0: break
+                    i = i+k
+                    continue
+                if rawdata.startswith("<!", i):
+                    # This is some sort of declaration; in "HTML as
+                    # deployed," this should only be the document type
+                    # declaration ("<!DOCTYPE html...>").
+                    k = self.parse_declaration(i)
+                    if k < 0: break
+                    i = k
+                    continue
+            elif rawdata[i] == '&':
+                if self.literal:
+                    self.handle_data(rawdata[i])
+                    i = i+1
+                    continue
+                match = charref.match(rawdata, i)
+                if match:
+                    name = match.group(1)
+                    self.handle_charref(name)
+                    i = match.end(0)
+                    if rawdata[i-1] != ';': i = i-1
+                    continue
+                match = entityref.match(rawdata, i)
+                if match:
+                    name = match.group(1)
+                    self.handle_entityref(name)
+                    i = match.end(0)
+                    if rawdata[i-1] != ';': i = i-1
+                    continue
+            else:
+                self.error('neither < nor & ??')
+            # We get here only if incomplete matches but
+            # nothing else
+            match = incomplete.match(rawdata, i)
+            if not match:
+                self.handle_data(rawdata[i])
+                i = i+1
+                continue
+            j = match.end(0)
+            if j == n:
+                break # Really incomplete
+            self.handle_data(rawdata[i:j])
+            i = j
+        # end while
+        if end and i < n:
+            self.handle_data(rawdata[i:n])
+            i = n
+        self.rawdata = rawdata[i:]
+        # XXX if end: check for empty stack
+
+    # Extensions for the DOCTYPE scanner:
+    _decl_otherchars = '='
+
+    # Internal -- parse processing instr, return length or -1 if not terminated
+    def parse_pi(self, i):
+        rawdata = self.rawdata
+        if rawdata[i:i+2] != '<?':
+            self.error('unexpected call to parse_pi()')
+        match = piclose.search(rawdata, i+2)
+        if not match:
+            return -1
+        j = match.start(0)
+        self.handle_pi(rawdata[i+2: j])
+        j = match.end(0)
+        return j-i
+
+    def get_starttag_text(self):
+        return self.__starttag_text
+
+    # Internal -- handle starttag, return length or -1 if not terminated
+    def parse_starttag(self, i):
+        self.__starttag_text = None
+        start_pos = i
+        rawdata = self.rawdata
+        if shorttagopen.match(rawdata, i):
+            # SGML shorthand: <tag/data/ == <tag>data</tag>
+            # XXX Can data contain &... (entity or char refs)?
+            # XXX Can data contain < or > (tag characters)?
+            # XXX Can there be whitespace before the first /?
+            match = shorttag.match(rawdata, i)
+            if not match:
+                return -1
+            tag, data = match.group(1, 2)
+            self.__starttag_text = '<%s/' % tag
+            tag = tag.lower()
+            k = match.end(0)
+            self.finish_shorttag(tag, data)
+            self.__starttag_text = rawdata[start_pos:match.end(1) + 1]
+            return k
+        # XXX The following should skip matching quotes (' or ")
+        # As a shortcut way to exit, this isn't so bad, but shouldn't
+        # be used to locate the actual end of the start tag since the
+        # < or > characters may be embedded in an attribute value.
+        match = endbracket.search(rawdata, i+1)
+        if not match:
+            return -1
+        j = match.start(0)
+        # Now parse the data between i+1 and j into a tag and attrs
+        attrs = []
+        if rawdata[i:i+2] == '<>':
+            # SGML shorthand: <> == <last open tag seen>
+            k = j
+            tag = self.lasttag
+        else:
+            match = tagfind.match(rawdata, i+1)
+            if not match:
+                self.error('unexpected call to parse_starttag')
+            k = match.end(0)
+            tag = rawdata[i+1:k].lower()
+            self.lasttag = tag
+        while k < j:
+            match = attrfind.match(rawdata, k)
+            if not match: break
+            attrname, rest, attrvalue = match.group(1, 2, 3)
+            if not rest:
+                attrvalue = attrname
+            else:
+                if (attrvalue[:1] == "'" == attrvalue[-1:] or
+                    attrvalue[:1] == '"' == attrvalue[-1:]):
+                    # strip quotes
+                    attrvalue = attrvalue[1:-1]
+                attrvalue = self.entity_or_charref.sub(
+                    self._convert_ref, attrvalue)
+            attrs.append((attrname.lower(), attrvalue))
+            k = match.end(0)
+        if rawdata[j] == '>':
+            j = j+1
+        self.__starttag_text = rawdata[start_pos:j]
+        self.finish_starttag(tag, attrs)
+        return j
+
+    # Internal -- convert entity or character reference
+    def _convert_ref(self, match):
+        if match.group(2):
+            return self.convert_charref(match.group(2)) or \
+                '&#%s%s' % match.groups()[1:]
+        elif match.group(3):
+            return self.convert_entityref(match.group(1)) or \
+                '&%s;' % match.group(1)
+        else:
+            return '&%s' % match.group(1)
+
+    # Internal -- parse endtag
+    def parse_endtag(self, i):
+        rawdata = self.rawdata
+        match = endbracket.search(rawdata, i+1)
+        if not match:
+            return -1
+        j = match.start(0)
+        tag = rawdata[i+2:j].strip().lower()
+        if rawdata[j] == '>':
+            j = j+1
+        self.finish_endtag(tag)
+        return j
+
+    # Internal -- finish parsing of <tag/data/ (same as <tag>data</tag>)
+    def finish_shorttag(self, tag, data):
+        self.finish_starttag(tag, [])
+        self.handle_data(data)
+        self.finish_endtag(tag)
+
+    # Internal -- finish processing of start tag
+    # Return -1 for unknown tag, 0 for open-only tag, 1 for balanced tag
+    def finish_starttag(self, tag, attrs):
+        try:
+            method = getattr(self, 'start_' + tag)
+        except AttributeError:
+            try:
+                method = getattr(self, 'do_' + tag)
+            except AttributeError:
+                self.unknown_starttag(tag, attrs)
+                return -1
+            else:
+                self.handle_starttag(tag, method, attrs)
+                return 0
+        else:
+            self.stack.append(tag)
+            self.handle_starttag(tag, method, attrs)
+            return 1
+
+    # Internal -- finish processing of end tag
+    def finish_endtag(self, tag):
+        if not tag:
+            found = len(self.stack) - 1
+            if found < 0:
+                self.unknown_endtag(tag)
+                return
+        else:
+            if tag not in self.stack:
+                try:
+                    method = getattr(self, 'end_' + tag)
+                except AttributeError:
+                    self.unknown_endtag(tag)
+                else:
+                    self.report_unbalanced(tag)
+                return
+            found = len(self.stack)
+            for i in range(found):
+                if self.stack[i] == tag: found = i
+        while len(self.stack) > found:
+            tag = self.stack[-1]
+            try:
+                method = getattr(self, 'end_' + tag)
+            except AttributeError:
+                method = None
+            if method:
+                self.handle_endtag(tag, method)
+            else:
+                self.unknown_endtag(tag)
+            del self.stack[-1]
+
+    # Overridable -- handle start tag
+    def handle_starttag(self, tag, method, attrs):
+        method(attrs)
+
+    # Overridable -- handle end tag
+    def handle_endtag(self, tag, method):
+        method()
+
+    # Example -- report an unbalanced </...> tag.
+    def report_unbalanced(self, tag):
+        if self.verbose:
+            print '*** Unbalanced </' + tag + '>'
+            print '*** Stack:', self.stack
+
+    def convert_charref(self, name):
+        """Convert character reference, may be overridden."""
+        try:
+            n = int(name)
+        except ValueError:
+            return
+        if not 0 <= n <= 127:
+            return
+        return self.convert_codepoint(n)
+
+    def convert_codepoint(self, codepoint):
+        return chr(codepoint)
+
+    def handle_charref(self, name):
+        """Handle character reference, no need to override."""
+        replacement = self.convert_charref(name)
+        if replacement is None:
+            self.unknown_charref(name)
+        else:
+            self.handle_data(replacement)
+
+    # Definition of entities -- derived classes may override
+    entitydefs = \
+            {'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"', 'apos': '\''}
+
+    def convert_entityref(self, name):
+        """Convert entity references.
+
+        As an alternative to overriding this method; one can tailor the
+        results by setting up the self.entitydefs mapping appropriately.
+        """
+        table = self.entitydefs
+        if name in table:
+            return table[name]
+        else:
+            return
+
+    def handle_entityref(self, name):
+        """Handle entity references, no need to override."""
+        replacement = self.convert_entityref(name)
+        if replacement is None:
+            self.unknown_entityref(name)
+        else:
+            self.handle_data(replacement)
+
+    # Example -- handle data, should be overridden
+    def handle_data(self, data):
+        pass
+
+    # Example -- handle comment, could be overridden
+    def handle_comment(self, data):
+        pass
+
+    # Example -- handle declaration, could be overridden
+    def handle_decl(self, decl):
+        pass
+
+    # Example -- handle processing instruction, could be overridden
+    def handle_pi(self, data):
+        pass
+
+    # To be overridden -- handlers for unknown objects
+    def unknown_starttag(self, tag, attrs): pass
+    def unknown_endtag(self, tag): pass
+    def unknown_charref(self, ref): pass
+    def unknown_entityref(self, ref): pass
+
+
+class TestSGMLParser(SGMLParser):
+
+    def __init__(self, verbose=0):
+        self.testdata = ""
+        SGMLParser.__init__(self, verbose)
+
+    def handle_data(self, data):
+        self.testdata = self.testdata + data
+        if len(repr(self.testdata)) >= 70:
+            self.flush()
+
+    def flush(self):
+        data = self.testdata
+        if data:
+            self.testdata = ""
+            print 'data:', repr(data)
+
+    def handle_comment(self, data):
+        self.flush()
+        r = repr(data)
+        if len(r) > 68:
+            r = r[:32] + '...' + r[-32:]
+        print 'comment:', r
+
+    def unknown_starttag(self, tag, attrs):
+        self.flush()
+        if not attrs:
+            print 'start tag: <' + tag + '>'
+        else:
+            print 'start tag: <' + tag,
+            for name, value in attrs:
+                print name + '=' + '"' + value + '"',
+            print '>'
+
+    def unknown_endtag(self, tag):
+        self.flush()
+        print 'end tag: </' + tag + '>'
+
+    def unknown_entityref(self, ref):
+        self.flush()
+        print '*** unknown entity ref: &' + ref + ';'
+
+    def unknown_charref(self, ref):
+        self.flush()
+        print '*** unknown char ref: &#' + ref + ';'
+
+    def unknown_decl(self, data):
+        self.flush()
+        print '*** unknown decl: [' + data + ']'
+
+    def close(self):
+        SGMLParser.close(self)
+        self.flush()
+
+
+def test(args = None):
+    import sys
+
+    if args is None:
+        args = sys.argv[1:]
+
+    if args and args[0] == '-s':
+        args = args[1:]
+        klass = SGMLParser
+    else:
+        klass = TestSGMLParser
+
+    if args:
+        file = args[0]
+    else:
+        file = 'test.html'
+
+    if file == '-':
+        f = sys.stdin
+    else:
+        try:
+            f = open(file, 'r')
+        except IOError, msg:
+            print file, ":", msg
+            sys.exit(1)
+
+    data = f.read()
+    if f is not sys.stdin:
+        f.close()
+
+    x = klass()
+    for c in data:
+        x.feed(c)
+    x.close()
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/sha.py b/src/main/resources/PythonLibs/sha.py
new file mode 100644
index 0000000000000000000000000000000000000000..41dde8dde27b57c8d1fe9a3b06ee13b8aa9af5d7
--- /dev/null
+++ b/src/main/resources/PythonLibs/sha.py
@@ -0,0 +1,15 @@
+# $Id$
+#
+#  Copyright (C) 2005   Gregory P. Smith (greg@krypto.org)
+#  Licensed to PSF under a Contributor Agreement.
+
+import warnings
+warnings.warn("the sha module is deprecated; use the hashlib module instead",
+                DeprecationWarning, 2)
+
+from hashlib import sha1 as sha
+new = sha
+
+blocksize = 1        # legacy value (wrong in any useful sense)
+digest_size = 20
+digestsize = 20
diff --git a/src/main/resources/PythonLibs/shelve.py b/src/main/resources/PythonLibs/shelve.py
new file mode 100644
index 0000000000000000000000000000000000000000..c8cba8582d6ff1ed7a4c7af6e42492fdfca3d13d
--- /dev/null
+++ b/src/main/resources/PythonLibs/shelve.py
@@ -0,0 +1,239 @@
+"""Manage shelves of pickled objects.
+
+A "shelf" is a persistent, dictionary-like object.  The difference
+with dbm databases is that the values (not the keys!) in a shelf can
+be essentially arbitrary Python objects -- anything that the "pickle"
+module can handle.  This includes most class instances, recursive data
+types, and objects containing lots of shared sub-objects.  The keys
+are ordinary strings.
+
+To summarize the interface (key is a string, data is an arbitrary
+object):
+
+        import shelve
+        d = shelve.open(filename) # open, with (g)dbm filename -- no suffix
+
+        d[key] = data   # store data at key (overwrites old data if
+                        # using an existing key)
+        data = d[key]   # retrieve a COPY of the data at key (raise
+                        # KeyError if no such key) -- NOTE that this
+                        # access returns a *copy* of the entry!
+        del d[key]      # delete data stored at key (raises KeyError
+                        # if no such key)
+        flag = d.has_key(key)   # true if the key exists; same as "key in d"
+        list = d.keys() # a list of all existing keys (slow!)
+
+        d.close()       # close it
+
+Dependent on the implementation, closing a persistent dictionary may
+or may not be necessary to flush changes to disk.
+
+Normally, d[key] returns a COPY of the entry.  This needs care when
+mutable entries are mutated: for example, if d[key] is a list,
+        d[key].append(anitem)
+does NOT modify the entry d[key] itself, as stored in the persistent
+mapping -- it only modifies the copy, which is then immediately
+discarded, so that the append has NO effect whatsoever.  To append an
+item to d[key] in a way that will affect the persistent mapping, use:
+        data = d[key]
+        data.append(anitem)
+        d[key] = data
+
+To avoid the problem with mutable entries, you may pass the keyword
+argument writeback=True in the call to shelve.open.  When you use:
+        d = shelve.open(filename, writeback=True)
+then d keeps a cache of all entries you access, and writes them all back
+to the persistent mapping when you call d.close().  This ensures that
+such usage as d[key].append(anitem) works as intended.
+
+However, using keyword argument writeback=True may consume vast amount
+of memory for the cache, and it may make d.close() very slow, if you
+access many of d's entries after opening it in this way: d has no way to
+check which of the entries you access are mutable and/or which ones you
+actually mutate, so it must cache, and write back at close, all of the
+entries that you access.  You can call d.sync() to write back all the
+entries in the cache, and empty the cache (d.sync() also synchronizes
+the persistent dictionary on disk, if feasible).
+"""
+
+# Try using cPickle and cStringIO if available.
+
+try:
+    from cPickle import Pickler, Unpickler
+except ImportError:
+    from pickle import Pickler, Unpickler
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+import UserDict
+
+__all__ = ["Shelf","BsdDbShelf","DbfilenameShelf","open"]
+
+class _ClosedDict(UserDict.DictMixin):
+    'Marker for a closed dict.  Access attempts raise a ValueError.'
+
+    def closed(self, *args):
+        raise ValueError('invalid operation on closed shelf')
+    __getitem__ = __setitem__ = __delitem__ = keys = closed
+
+    def __repr__(self):
+        return '<Closed Dictionary>'
+
+class Shelf(UserDict.DictMixin):
+    """Base class for shelf implementations.
+
+    This is initialized with a dictionary-like object.
+    See the module's __doc__ string for an overview of the interface.
+    """
+
+    def __init__(self, dict, protocol=None, writeback=False):
+        self.dict = dict
+        if protocol is None:
+            protocol = 0
+        self._protocol = protocol
+        self.writeback = writeback
+        self.cache = {}
+
+    def keys(self):
+        return self.dict.keys()
+
+    def __len__(self):
+        return len(self.dict)
+
+    def has_key(self, key):
+        return key in self.dict
+
+    def __contains__(self, key):
+        return key in self.dict
+
+    def get(self, key, default=None):
+        if key in self.dict:
+            return self[key]
+        return default
+
+    def __getitem__(self, key):
+        try:
+            value = self.cache[key]
+        except KeyError:
+            f = StringIO(self.dict[key])
+            value = Unpickler(f).load()
+            if self.writeback:
+                self.cache[key] = value
+        return value
+
+    def __setitem__(self, key, value):
+        if self.writeback:
+            self.cache[key] = value
+        f = StringIO()
+        p = Pickler(f, self._protocol)
+        p.dump(value)
+        self.dict[key] = f.getvalue()
+
+    def __delitem__(self, key):
+        del self.dict[key]
+        try:
+            del self.cache[key]
+        except KeyError:
+            pass
+
+    def close(self):
+        self.sync()
+        try:
+            self.dict.close()
+        except AttributeError:
+            pass
+        # Catch errors that may happen when close is called from __del__
+        # because CPython is in interpreter shutdown.
+        try:
+            self.dict = _ClosedDict()
+        except (NameError, TypeError):
+            self.dict = None
+
+    def __del__(self):
+        if not hasattr(self, 'writeback'):
+            # __init__ didn't succeed, so don't bother closing
+            return
+        self.close()
+
+    def sync(self):
+        if self.writeback and self.cache:
+            self.writeback = False
+            for key, entry in self.cache.iteritems():
+                self[key] = entry
+            self.writeback = True
+            self.cache = {}
+        if hasattr(self.dict, 'sync'):
+            self.dict.sync()
+
+
+class BsdDbShelf(Shelf):
+    """Shelf implementation using the "BSD" db interface.
+
+    This adds methods first(), next(), previous(), last() and
+    set_location() that have no counterpart in [g]dbm databases.
+
+    The actual database must be opened using one of the "bsddb"
+    modules "open" routines (i.e. bsddb.hashopen, bsddb.btopen or
+    bsddb.rnopen) and passed to the constructor.
+
+    See the module's __doc__ string for an overview of the interface.
+    """
+
+    def __init__(self, dict, protocol=None, writeback=False):
+        Shelf.__init__(self, dict, protocol, writeback)
+
+    def set_location(self, key):
+        (key, value) = self.dict.set_location(key)
+        f = StringIO(value)
+        return (key, Unpickler(f).load())
+
+    def next(self):
+        (key, value) = self.dict.next()
+        f = StringIO(value)
+        return (key, Unpickler(f).load())
+
+    def previous(self):
+        (key, value) = self.dict.previous()
+        f = StringIO(value)
+        return (key, Unpickler(f).load())
+
+    def first(self):
+        (key, value) = self.dict.first()
+        f = StringIO(value)
+        return (key, Unpickler(f).load())
+
+    def last(self):
+        (key, value) = self.dict.last()
+        f = StringIO(value)
+        return (key, Unpickler(f).load())
+
+
+class DbfilenameShelf(Shelf):
+    """Shelf implementation using the "anydbm" generic dbm interface.
+
+    This is initialized with the filename for the dbm database.
+    See the module's __doc__ string for an overview of the interface.
+    """
+
+    def __init__(self, filename, flag='c', protocol=None, writeback=False):
+        import anydbm
+        Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback)
+
+
+def open(filename, flag='c', protocol=None, writeback=False):
+    """Open a persistent dictionary for reading and writing.
+
+    The filename parameter is the base filename for the underlying
+    database.  As a side-effect, an extension may be added to the
+    filename and more than one file may be created.  The optional flag
+    parameter has the same interpretation as the flag parameter of
+    anydbm.open(). The optional protocol parameter specifies the
+    version of the pickle protocol (0, 1, or 2).
+
+    See the module's __doc__ string for an overview of the interface.
+    """
+
+    return DbfilenameShelf(filename, flag, protocol, writeback)
diff --git a/src/main/resources/PythonLibs/shlex.py b/src/main/resources/PythonLibs/shlex.py
new file mode 100644
index 0000000000000000000000000000000000000000..e7c8accd427590b035bdf47f82d005daec879c63
--- /dev/null
+++ b/src/main/resources/PythonLibs/shlex.py
@@ -0,0 +1,292 @@
+# -*- coding: iso-8859-1 -*-
+"""A lexical analyzer class for simple shell-like syntaxes."""
+
+# Module and documentation by Eric S. Raymond, 21 Dec 1998
+# Input stacking and error message cleanup added by ESR, March 2000
+# push_source() and pop_source() made explicit by ESR, January 2001.
+# Posix compliance, split(), string arguments, and
+# iterator interface by Gustavo Niemeyer, April 2003.
+
+import os.path
+import sys
+from collections import deque
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+__all__ = ["shlex", "split"]
+
+class shlex:
+    "A lexical analyzer class for simple shell-like syntaxes."
+    def __init__(self, instream=None, infile=None, posix=False):
+        if isinstance(instream, basestring):
+            instream = StringIO(instream)
+        if instream is not None:
+            self.instream = instream
+            self.infile = infile
+        else:
+            self.instream = sys.stdin
+            self.infile = None
+        self.posix = posix
+        if posix:
+            self.eof = None
+        else:
+            self.eof = ''
+        self.commenters = '#'
+        self.wordchars = ('abcdfeghijklmnopqrstuvwxyz'
+                          'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_')
+        if self.posix:
+            self.wordchars += ('ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ'
+                               'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ')
+        self.whitespace = ' \t\r\n'
+        self.whitespace_split = False
+        self.quotes = '\'"'
+        self.escape = '\\'
+        self.escapedquotes = '"'
+        self.state = ' '
+        self.pushback = deque()
+        self.lineno = 1
+        self.debug = 0
+        self.token = ''
+        self.filestack = deque()
+        self.source = None
+        if self.debug:
+            print 'shlex: reading from %s, line %d' \
+                  % (self.instream, self.lineno)
+
+    def push_token(self, tok):
+        "Push a token onto the stack popped by the get_token method"
+        if self.debug >= 1:
+            print "shlex: pushing token " + repr(tok)
+        self.pushback.appendleft(tok)
+
+    def push_source(self, newstream, newfile=None):
+        "Push an input source onto the lexer's input source stack."
+        if isinstance(newstream, basestring):
+            newstream = StringIO(newstream)
+        self.filestack.appendleft((self.infile, self.instream, self.lineno))
+        self.infile = newfile
+        self.instream = newstream
+        self.lineno = 1
+        if self.debug:
+            if newfile is not None:
+                print 'shlex: pushing to file %s' % (self.infile,)
+            else:
+                print 'shlex: pushing to stream %s' % (self.instream,)
+
+    def pop_source(self):
+        "Pop the input source stack."
+        self.instream.close()
+        (self.infile, self.instream, self.lineno) = self.filestack.popleft()
+        if self.debug:
+            print 'shlex: popping to %s, line %d' \
+                  % (self.instream, self.lineno)
+        self.state = ' '
+
+    def get_token(self):
+        "Get a token from the input stream (or from stack if it's nonempty)"
+        if self.pushback:
+            tok = self.pushback.popleft()
+            if self.debug >= 1:
+                print "shlex: popping token " + repr(tok)
+            return tok
+        # No pushback.  Get a token.
+        raw = self.read_token()
+        # Handle inclusions
+        if self.source is not None:
+            while raw == self.source:
+                spec = self.sourcehook(self.read_token())
+                if spec:
+                    (newfile, newstream) = spec
+                    self.push_source(newstream, newfile)
+                raw = self.get_token()
+        # Maybe we got EOF instead?
+        while raw == self.eof:
+            if not self.filestack:
+                return self.eof
+            else:
+                self.pop_source()
+                raw = self.get_token()
+        # Neither inclusion nor EOF
+        if self.debug >= 1:
+            if raw != self.eof:
+                print "shlex: token=" + repr(raw)
+            else:
+                print "shlex: token=EOF"
+        return raw
+
+    def read_token(self):
+        quoted = False
+        escapedstate = ' '
+        while True:
+            nextchar = self.instream.read(1)
+            if nextchar == '\n':
+                self.lineno = self.lineno + 1
+            if self.debug >= 3:
+                print "shlex: in state", repr(self.state), \
+                      "I see character:", repr(nextchar)
+            if self.state is None:
+                self.token = ''        # past end of file
+                break
+            elif self.state == ' ':
+                if not nextchar:
+                    self.state = None  # end of file
+                    break
+                elif nextchar in self.whitespace:
+                    if self.debug >= 2:
+                        print "shlex: I see whitespace in whitespace state"
+                    if self.token or (self.posix and quoted):
+                        break   # emit current token
+                    else:
+                        continue
+                elif nextchar in self.commenters:
+                    self.instream.readline()
+                    self.lineno = self.lineno + 1
+                elif self.posix and nextchar in self.escape:
+                    escapedstate = 'a'
+                    self.state = nextchar
+                elif nextchar in self.wordchars:
+                    self.token = nextchar
+                    self.state = 'a'
+                elif nextchar in self.quotes:
+                    if not self.posix:
+                        self.token = nextchar
+                    self.state = nextchar
+                elif self.whitespace_split:
+                    self.token = nextchar
+                    self.state = 'a'
+                else:
+                    self.token = nextchar
+                    if self.token or (self.posix and quoted):
+                        break   # emit current token
+                    else:
+                        continue
+            elif self.state in self.quotes:
+                quoted = True
+                if not nextchar:      # end of file
+                    if self.debug >= 2:
+                        print "shlex: I see EOF in quotes state"
+                    # XXX what error should be raised here?
+                    raise ValueError, "No closing quotation"
+                if nextchar == self.state:
+                    if not self.posix:
+                        self.token = self.token + nextchar
+                        self.state = ' '
+                        break
+                    else:
+                        self.state = 'a'
+                elif self.posix and nextchar in self.escape and \
+                     self.state in self.escapedquotes:
+                    escapedstate = self.state
+                    self.state = nextchar
+                else:
+                    self.token = self.token + nextchar
+            elif self.state in self.escape:
+                if not nextchar:      # end of file
+                    if self.debug >= 2:
+                        print "shlex: I see EOF in escape state"
+                    # XXX what error should be raised here?
+                    raise ValueError, "No escaped character"
+                # In posix shells, only the quote itself or the escape
+                # character may be escaped within quotes.
+                if escapedstate in self.quotes and \
+                   nextchar != self.state and nextchar != escapedstate:
+                    self.token = self.token + self.state
+                self.token = self.token + nextchar
+                self.state = escapedstate
+            elif self.state == 'a':
+                if not nextchar:
+                    self.state = None   # end of file
+                    break
+                elif nextchar in self.whitespace:
+                    if self.debug >= 2:
+                        print "shlex: I see whitespace in word state"
+                    self.state = ' '
+                    if self.token or (self.posix and quoted):
+                        break   # emit current token
+                    else:
+                        continue
+                elif nextchar in self.commenters:
+                    self.instream.readline()
+                    self.lineno = self.lineno + 1
+                    if self.posix:
+                        self.state = ' '
+                        if self.token or (self.posix and quoted):
+                            break   # emit current token
+                        else:
+                            continue
+                elif self.posix and nextchar in self.quotes:
+                    self.state = nextchar
+                elif self.posix and nextchar in self.escape:
+                    escapedstate = 'a'
+                    self.state = nextchar
+                elif nextchar in self.wordchars or nextchar in self.quotes \
+                    or self.whitespace_split:
+                    self.token = self.token + nextchar
+                else:
+                    self.pushback.appendleft(nextchar)
+                    if self.debug >= 2:
+                        print "shlex: I see punctuation in word state"
+                    self.state = ' '
+                    if self.token:
+                        break   # emit current token
+                    else:
+                        continue
+        result = self.token
+        self.token = ''
+        if self.posix and not quoted and result == '':
+            result = None
+        if self.debug > 1:
+            if result:
+                print "shlex: raw token=" + repr(result)
+            else:
+                print "shlex: raw token=EOF"
+        return result
+
+    def sourcehook(self, newfile):
+        "Hook called on a filename to be sourced."
+        if newfile[0] == '"':
+            newfile = newfile[1:-1]
+        # This implements cpp-like semantics for relative-path inclusion.
+        if isinstance(self.infile, basestring) and not os.path.isabs(newfile):
+            newfile = os.path.join(os.path.dirname(self.infile), newfile)
+        return (newfile, open(newfile, "r"))
+
+    def error_leader(self, infile=None, lineno=None):
+        "Emit a C-compiler-like, Emacs-friendly error-message leader."
+        if infile is None:
+            infile = self.infile
+        if lineno is None:
+            lineno = self.lineno
+        return "\"%s\", line %d: " % (infile, lineno)
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        token = self.get_token()
+        if token == self.eof:
+            raise StopIteration
+        return token
+
+def split(s, comments=False, posix=True):
+    lex = shlex(s, posix=posix)
+    lex.whitespace_split = True
+    if not comments:
+        lex.commenters = ''
+    return list(lex)
+
+if __name__ == '__main__':
+    if len(sys.argv) == 1:
+        lexer = shlex()
+    else:
+        file = sys.argv[1]
+        lexer = shlex(open(file), file)
+    while 1:
+        tt = lexer.get_token()
+        if tt:
+            print "Token: " + repr(tt)
+        else:
+            break
diff --git a/src/main/resources/PythonLibs/shutil.py b/src/main/resources/PythonLibs/shutil.py
new file mode 100644
index 0000000000000000000000000000000000000000..420802fafdff81fcd78b886b7474dd5322b444ae
--- /dev/null
+++ b/src/main/resources/PythonLibs/shutil.py
@@ -0,0 +1,556 @@
+"""Utility functions for copying and archiving files and directory trees.
+
+XXX The functions here don't copy the resource fork or other metadata on Mac.
+
+"""
+
+import os
+import sys
+import stat
+from os.path import abspath
+import fnmatch
+import collections
+import errno
+
+try:
+    from pwd import getpwnam
+except ImportError:
+    getpwnam = None
+
+try:
+    from grp import getgrnam
+except ImportError:
+    getgrnam = None
+
+__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
+           "copytree", "move", "rmtree", "Error", "SpecialFileError",
+           "ExecError", "make_archive", "get_archive_formats",
+           "register_archive_format", "unregister_archive_format",
+           "ignore_patterns"]
+
+class Error(EnvironmentError):
+    pass
+
+class SpecialFileError(EnvironmentError):
+    """Raised when trying to do a kind of operation (e.g. copying) which is
+    not supported on a special file (e.g. a named pipe)"""
+
+class ExecError(EnvironmentError):
+    """Raised when a command could not be executed"""
+
+try:
+    WindowsError
+except NameError:
+    WindowsError = None
+
+def copyfileobj(fsrc, fdst, length=16*1024):
+    """copy data from file-like object fsrc to file-like object fdst"""
+    while 1:
+        buf = fsrc.read(length)
+        if not buf:
+            break
+        fdst.write(buf)
+
+def _samefile(src, dst):
+    # Macintosh, Unix.
+    if hasattr(os.path, 'samefile'):
+        try:
+            return os.path.samefile(src, dst)
+        except OSError:
+            return False
+
+    # All other platforms: check for same pathname.
+    return (os.path.normcase(os.path.abspath(src)) ==
+            os.path.normcase(os.path.abspath(dst)))
+
+def copyfile(src, dst):
+    """Copy data from src to dst"""
+    if _samefile(src, dst):
+        raise Error("`%s` and `%s` are the same file" % (src, dst))
+
+    for fn in [src, dst]:
+        try:
+            st = os.stat(fn)
+        except OSError:
+            # File most likely does not exist
+            pass
+        else:
+            # XXX What about other special files? (sockets, devices...)
+            if stat.S_ISFIFO(st.st_mode):
+                raise SpecialFileError("`%s` is a named pipe" % fn)
+
+    with open(src, 'rb') as fsrc:
+        with open(dst, 'wb') as fdst:
+            copyfileobj(fsrc, fdst)
+
+def copymode(src, dst):
+    """Copy mode bits from src to dst"""
+    if hasattr(os, 'chmod'):
+        st = os.stat(src)
+        mode = stat.S_IMODE(st.st_mode)
+        os.chmod(dst, mode)
+
+def copystat(src, dst):
+    """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
+    st = os.stat(src)
+    mode = stat.S_IMODE(st.st_mode)
+    if hasattr(os, 'utime'):
+        os.utime(dst, (st.st_atime, st.st_mtime))
+    if hasattr(os, 'chmod'):
+        os.chmod(dst, mode)
+    if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
+        try:
+            os.chflags(dst, st.st_flags)
+        except OSError, why:
+            for err in 'EOPNOTSUPP', 'ENOTSUP':
+                if hasattr(errno, err) and why.errno == getattr(errno, err):
+                    break
+            else:
+                raise
+
+def copy(src, dst):
+    """Copy data and mode bits ("cp src dst").
+
+    The destination may be a directory.
+
+    """
+    if os.path.isdir(dst):
+        dst = os.path.join(dst, os.path.basename(src))
+    copyfile(src, dst)
+    copymode(src, dst)
+
+def copy2(src, dst):
+    """Copy data and all stat info ("cp -p src dst").
+
+    The destination may be a directory.
+
+    """
+    if os.path.isdir(dst):
+        dst = os.path.join(dst, os.path.basename(src))
+    copyfile(src, dst)
+    copystat(src, dst)
+
+def ignore_patterns(*patterns):
+    """Function that can be used as copytree() ignore parameter.
+
+    Patterns is a sequence of glob-style patterns
+    that are used to exclude files"""
+    def _ignore_patterns(path, names):
+        ignored_names = []
+        for pattern in patterns:
+            ignored_names.extend(fnmatch.filter(names, pattern))
+        return set(ignored_names)
+    return _ignore_patterns
+
+def copytree(src, dst, symlinks=False, ignore=None):
+    """Recursively copy a directory tree using copy2().
+
+    The destination directory must not already exist.
+    If exception(s) occur, an Error is raised with a list of reasons.
+
+    If the optional symlinks flag is true, symbolic links in the
+    source tree result in symbolic links in the destination tree; if
+    it is false, the contents of the files pointed to by symbolic
+    links are copied.
+
+    The optional ignore argument is a callable. If given, it
+    is called with the `src` parameter, which is the directory
+    being visited by copytree(), and `names` which is the list of
+    `src` contents, as returned by os.listdir():
+
+        callable(src, names) -> ignored_names
+
+    Since copytree() is called recursively, the callable will be
+    called once for each directory that is copied. It returns a
+    list of names relative to the `src` directory that should
+    not be copied.
+
+    XXX Consider this example code rather than the ultimate tool.
+
+    """
+    names = os.listdir(src)
+    if ignore is not None:
+        ignored_names = ignore(src, names)
+    else:
+        ignored_names = set()
+
+    os.makedirs(dst)
+    errors = []
+    for name in names:
+        if name in ignored_names:
+            continue
+        srcname = os.path.join(src, name)
+        dstname = os.path.join(dst, name)
+        try:
+            if symlinks and os.path.islink(srcname):
+                linkto = os.readlink(srcname)
+                os.symlink(linkto, dstname)
+            elif os.path.isdir(srcname):
+                copytree(srcname, dstname, symlinks, ignore)
+            else:
+                # Will raise a SpecialFileError for unsupported file types
+                copy2(srcname, dstname)
+        # catch the Error from the recursive copytree so that we can
+        # continue with other files
+        except Error, err:
+            errors.extend(err.args[0])
+        except EnvironmentError, why:
+            errors.append((srcname, dstname, str(why)))
+    try:
+        copystat(src, dst)
+    except OSError, why:
+        if WindowsError is not None and isinstance(why, WindowsError):
+            # Copying file access times may fail on Windows
+            pass
+        else:
+            errors.append((src, dst, str(why)))
+    if errors:
+        raise Error, errors
+
+def rmtree(path, ignore_errors=False, onerror=None):
+    """Recursively delete a directory tree.
+
+    If ignore_errors is set, errors are ignored; otherwise, if onerror
+    is set, it is called to handle the error with arguments (func,
+    path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
+    path is the argument to that function that caused it to fail; and
+    exc_info is a tuple returned by sys.exc_info().  If ignore_errors
+    is false and onerror is None, an exception is raised.
+
+    """
+    if ignore_errors:
+        def onerror(*args):
+            pass
+    elif onerror is None:
+        def onerror(*args):
+            raise
+    try:
+        if os.path.islink(path):
+            # symlinks to directories are forbidden, see bug #1669
+            raise OSError("Cannot call rmtree on a symbolic link")
+    except OSError:
+        onerror(os.path.islink, path, sys.exc_info())
+        # can't continue even if onerror hook returns
+        return
+    names = []
+    try:
+        names = os.listdir(path)
+    except os.error, err:
+        onerror(os.listdir, path, sys.exc_info())
+    for name in names:
+        fullname = os.path.join(path, name)
+        try:
+            mode = os.lstat(fullname).st_mode
+        except os.error:
+            mode = 0
+        if stat.S_ISDIR(mode):
+            rmtree(fullname, ignore_errors, onerror)
+        else:
+            try:
+                os.remove(fullname)
+            except os.error, err:
+                onerror(os.remove, fullname, sys.exc_info())
+    try:
+        os.rmdir(path)
+    except os.error:
+        onerror(os.rmdir, path, sys.exc_info())
+
+
+def _basename(path):
+    # A basename() variant which first strips the trailing slash, if present.
+    # Thus we always get the last component of the path, even for directories.
+    return os.path.basename(path.rstrip(os.path.sep))
+
+def move(src, dst):
+    """Recursively move a file or directory to another location. This is
+    similar to the Unix "mv" command.
+
+    If the destination is a directory or a symlink to a directory, the source
+    is moved inside the directory. The destination path must not already
+    exist.
+
+    If the destination already exists but is not a directory, it may be
+    overwritten depending on os.rename() semantics.
+
+    If the destination is on our current filesystem, then rename() is used.
+    Otherwise, src is copied to the destination and then removed.
+    A lot more could be done here...  A look at a mv.c shows a lot of
+    the issues this implementation glosses over.
+
+    """
+    real_dst = dst
+    if os.path.isdir(dst):
+        if _samefile(src, dst):
+            # We might be on a case insensitive filesystem,
+            # perform the rename anyway.
+            os.rename(src, dst)
+            return
+
+        real_dst = os.path.join(dst, _basename(src))
+        if os.path.exists(real_dst):
+            raise Error, "Destination path '%s' already exists" % real_dst
+    try:
+        os.rename(src, real_dst)
+    except OSError:
+        if os.path.isdir(src):
+            if _destinsrc(src, dst):
+                raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
+            copytree(src, real_dst, symlinks=True)
+            rmtree(src)
+        else:
+            copy2(src, real_dst)
+            os.unlink(src)
+
+def _destinsrc(src, dst):
+    src = abspath(src)
+    dst = abspath(dst)
+    if not src.endswith(os.path.sep):
+        src += os.path.sep
+    if not dst.endswith(os.path.sep):
+        dst += os.path.sep
+    return dst.startswith(src)
+
+def _get_gid(name):
+    """Returns a gid, given a group name."""
+    if getgrnam is None or name is None:
+        return None
+    try:
+        result = getgrnam(name)
+    except KeyError:
+        result = None
+    if result is not None:
+        return result[2]
+    return None
+
+def _get_uid(name):
+    """Returns an uid, given a user name."""
+    if getpwnam is None or name is None:
+        return None
+    try:
+        result = getpwnam(name)
+    except KeyError:
+        result = None
+    if result is not None:
+        return result[2]
+    return None
+
+def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
+                  owner=None, group=None, logger=None):
+    """Create a (possibly compressed) tar file from all the files under
+    'base_dir'.
+
+    'compress' must be "gzip" (the default), "bzip2", or None.
+
+    'owner' and 'group' can be used to define an owner and a group for the
+    archive that is being built. If not provided, the current owner and group
+    will be used.
+
+    The output tar file will be named 'base_name' +  ".tar", possibly plus
+    the appropriate compression extension (".gz", or ".bz2").
+
+    Returns the output filename.
+    """
+    tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: ''}
+    compress_ext = {'gzip': '.gz', 'bzip2': '.bz2'}
+
+    # flags for compression program, each element of list will be an argument
+    if compress is not None and compress not in compress_ext.keys():
+        raise ValueError, \
+              ("bad value for 'compress': must be None, 'gzip' or 'bzip2'")
+
+    archive_name = base_name + '.tar' + compress_ext.get(compress, '')
+    archive_dir = os.path.dirname(archive_name)
+
+    if not os.path.exists(archive_dir):
+        if logger is not None:
+            logger.info("creating %s", archive_dir)
+        if not dry_run:
+            os.makedirs(archive_dir)
+
+
+    # creating the tarball
+    import tarfile  # late import so Python build itself doesn't break
+
+    if logger is not None:
+        logger.info('Creating tar archive')
+
+    uid = _get_uid(owner)
+    gid = _get_gid(group)
+
+    def _set_uid_gid(tarinfo):
+        if gid is not None:
+            tarinfo.gid = gid
+            tarinfo.gname = group
+        if uid is not None:
+            tarinfo.uid = uid
+            tarinfo.uname = owner
+        return tarinfo
+
+    if not dry_run:
+        tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
+        try:
+            tar.add(base_dir, filter=_set_uid_gid)
+        finally:
+            tar.close()
+
+    return archive_name
+
+def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
+    # XXX see if we want to keep an external call here
+    if verbose:
+        zipoptions = "-r"
+    else:
+        zipoptions = "-rq"
+    from distutils.errors import DistutilsExecError
+    from distutils.spawn import spawn
+    try:
+        spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
+    except DistutilsExecError:
+        # XXX really should distinguish between "couldn't find
+        # external 'zip' command" and "zip failed".
+        raise ExecError, \
+            ("unable to create zip file '%s': "
+            "could neither import the 'zipfile' module nor "
+            "find a standalone zip utility") % zip_filename
+
+def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
+    """Create a zip file from all the files under 'base_dir'.
+
+    The output zip file will be named 'base_name' + ".zip".  Uses either the
+    "zipfile" Python module (if available) or the InfoZIP "zip" utility
+    (if installed and found on the default search path).  If neither tool is
+    available, raises ExecError.  Returns the name of the output zip
+    file.
+    """
+    zip_filename = base_name + ".zip"
+    archive_dir = os.path.dirname(base_name)
+
+    if not os.path.exists(archive_dir):
+        if logger is not None:
+            logger.info("creating %s", archive_dir)
+        if not dry_run:
+            os.makedirs(archive_dir)
+
+    # If zipfile module is not available, try spawning an external 'zip'
+    # command.
+    try:
+        import zipfile
+    except ImportError:
+        zipfile = None
+
+    if zipfile is None:
+        _call_external_zip(base_dir, zip_filename, verbose, dry_run)
+    else:
+        if logger is not None:
+            logger.info("creating '%s' and adding '%s' to it",
+                        zip_filename, base_dir)
+
+        if not dry_run:
+            zip = zipfile.ZipFile(zip_filename, "w",
+                                  compression=zipfile.ZIP_DEFLATED)
+
+            for dirpath, dirnames, filenames in os.walk(base_dir):
+                for name in filenames:
+                    path = os.path.normpath(os.path.join(dirpath, name))
+                    if os.path.isfile(path):
+                        zip.write(path, path)
+                        if logger is not None:
+                            logger.info("adding '%s'", path)
+            zip.close()
+
+    return zip_filename
+
+_ARCHIVE_FORMATS = {
+    'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
+    'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
+    'tar':   (_make_tarball, [('compress', None)], "uncompressed tar file"),
+    'zip':   (_make_zipfile, [],"ZIP file")
+    }
+
+def get_archive_formats():
+    """Returns a list of supported formats for archiving and unarchiving.
+
+    Each element of the returned sequence is a tuple (name, description)
+    """
+    formats = [(name, registry[2]) for name, registry in
+               _ARCHIVE_FORMATS.items()]
+    formats.sort()
+    return formats
+
+def register_archive_format(name, function, extra_args=None, description=''):
+    """Registers an archive format.
+
+    name is the name of the format. function is the callable that will be
+    used to create archives. If provided, extra_args is a sequence of
+    (name, value) tuples that will be passed as arguments to the callable.
+    description can be provided to describe the format, and will be returned
+    by the get_archive_formats() function.
+    """
+    if extra_args is None:
+        extra_args = []
+    if not isinstance(function, collections.Callable):
+        raise TypeError('The %s object is not callable' % function)
+    if not isinstance(extra_args, (tuple, list)):
+        raise TypeError('extra_args needs to be a sequence')
+    for element in extra_args:
+        if not isinstance(element, (tuple, list)) or len(element) !=2 :
+            raise TypeError('extra_args elements are : (arg_name, value)')
+
+    _ARCHIVE_FORMATS[name] = (function, extra_args, description)
+
+def unregister_archive_format(name):
+    del _ARCHIVE_FORMATS[name]
+
+def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
+                 dry_run=0, owner=None, group=None, logger=None):
+    """Create an archive file (eg. zip or tar).
+
+    'base_name' is the name of the file to create, minus any format-specific
+    extension; 'format' is the archive format: one of "zip", "tar", "bztar"
+    or "gztar".
+
+    'root_dir' is a directory that will be the root directory of the
+    archive; ie. we typically chdir into 'root_dir' before creating the
+    archive.  'base_dir' is the directory where we start archiving from;
+    ie. 'base_dir' will be the common prefix of all files and
+    directories in the archive.  'root_dir' and 'base_dir' both default
+    to the current directory.  Returns the name of the archive file.
+
+    'owner' and 'group' are used when creating a tar archive. By default,
+    uses the current owner and group.
+    """
+    save_cwd = os.getcwd()
+    if root_dir is not None:
+        if logger is not None:
+            logger.debug("changing into '%s'", root_dir)
+        base_name = os.path.abspath(base_name)
+        if not dry_run:
+            os.chdir(root_dir)
+
+    if base_dir is None:
+        base_dir = os.curdir
+
+    kwargs = {'dry_run': dry_run, 'logger': logger}
+
+    try:
+        format_info = _ARCHIVE_FORMATS[format]
+    except KeyError:
+        raise ValueError, "unknown archive format '%s'" % format
+
+    func = format_info[0]
+    for arg, val in format_info[1]:
+        kwargs[arg] = val
+
+    if format != 'zip':
+        kwargs['owner'] = owner
+        kwargs['group'] = group
+
+    try:
+        filename = func(base_name, base_dir, **kwargs)
+    finally:
+        if root_dir is not None:
+            if logger is not None:
+                logger.debug("changing back to '%s'", save_cwd)
+            os.chdir(save_cwd)
+
+    return filename
diff --git a/src/main/resources/PythonLibs/signal.py b/src/main/resources/PythonLibs/signal.py
new file mode 100644
index 0000000000000000000000000000000000000000..f7a8cc00bdc08653ccfaa86f9ec9871b246e9a8f
--- /dev/null
+++ b/src/main/resources/PythonLibs/signal.py
@@ -0,0 +1,239 @@
+"""
+    This module provides mechanisms to use signal handlers in Python.
+
+    Functions:
+
+    signal(sig,action) -- set the action for a given signal (done)
+    pause(sig) -- wait until a signal arrives [Unix only]
+    alarm(seconds) -- cause SIGALRM after a specified time [Unix only]
+    getsignal(sig) -- get the signal action for a given signal
+    default_int_handler(action) -- default SIGINT handler (done, but acts string)
+
+    Constants:
+
+    SIG_DFL -- used to refer to the system default handler
+    SIG_IGN -- used to ignore the signal
+    NSIG -- number of defined signals
+
+    SIGINT, SIGTERM, etc. -- signal numbers
+
+    *** IMPORTANT NOTICES ***
+    A signal handler function is called with two arguments:
+    the first is the signal number, the second is the interrupted stack frame.
+
+    According to http://java.sun.com/products/jdk/faq/faq-sun-packages.html
+    'writing java programs that rely on sun.* is risky: they are not portable, and are not supported.'
+
+    However, in Jython, like Python, we let you decide what makes
+    sense for your application. If sun.misc.Signal is not available,
+    an ImportError is raised.
+"""
+
+
+try:
+    import sun.misc.Signal
+except ImportError:
+    raise ImportError("signal module requires sun.misc.Signal, which is not available on this platform")
+
+import os
+import sun.misc.SignalHandler
+import sys
+import threading
+import time
+from java.lang import IllegalArgumentException
+from java.util.concurrent.atomic import AtomicReference
+
+debug = 0
+
+def _init_signals():
+    # install signals by checking for standard names
+    # using IllegalArgumentException to diagnose
+
+    possible_signals = """
+        SIGABRT
+        SIGALRM
+        SIGBUS
+        SIGCHLD
+        SIGCONT
+        SIGFPE
+        SIGHUP
+        SIGILL
+        SIGINFO
+        SIGINT
+        SIGIOT
+        SIGKILL
+        SIGPIPE
+        SIGPOLL
+        SIGPROF
+        SIGQUIT
+        SIGSEGV
+        SIGSTOP
+        SIGSYS
+        SIGTERM
+        SIGTRAP
+        SIGTSTP
+        SIGTTIN
+        SIGTTOU
+        SIGURG
+        SIGUSR1
+        SIGUSR2
+        SIGVTALRM
+        SIGWINCH
+        SIGXCPU
+        SIGXFSZ
+    """.split()
+
+    _module = __import__(__name__)
+    signals = {}
+    signals_by_name = {}
+    for signal_name in possible_signals:
+        try:
+            java_signal = sun.misc.Signal(signal_name[3:])
+        except IllegalArgumentException:
+            continue
+
+        signal_number = java_signal.getNumber()
+        signals[signal_number] = java_signal
+        signals_by_name[signal_name] = java_signal
+        setattr(_module, signal_name, signal_number) # install as a module constant
+    return signals
+
+_signals = _init_signals()
+NSIG = max(_signals.iterkeys()) + 1
+SIG_DFL = sun.misc.SignalHandler.SIG_DFL # default system handler
+SIG_IGN = sun.misc.SignalHandler.SIG_IGN # handler to ignore a signal
+
+class JythonSignalHandler(sun.misc.SignalHandler):
+    def __init__(self, action):
+        self.action = action
+
+    def handle(self, signal):
+        # passing a frame here probably don't make sense in a threaded system,
+        # but perhaps revisit
+        self.action(signal.getNumber(), None)
+
+def signal(sig, action):
+    """
+    signal(sig, action) -> action
+
+    Set the action for the given signal.  The action can be SIG_DFL,
+    SIG_IGN, or a callable Python object.  The previous action is
+    returned.  See getsignal() for possible return values.
+
+    *** IMPORTANT NOTICE ***
+    A signal handler function is called with two arguments:
+    the first is the signal number, the second is the interrupted stack frame.
+    """
+    # maybe keep a weak ref map of handlers we have returned?
+
+    try:
+        signal = _signals[sig]
+    except KeyError:
+        raise ValueError("signal number out of range")
+
+    if callable(action):
+        prev = sun.misc.Signal.handle(signal, JythonSignalHandler(action))
+    elif action in (SIG_IGN, SIG_DFL) or isinstance(action, sun.misc.SignalHandler):
+        prev = sun.misc.Signal.handle(signal, action)
+    else:
+        raise TypeError("signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object")
+
+    if isinstance(prev, JythonSignalHandler):
+        return prev.action
+    else:
+        return prev
+
+
+# dangerous! don't use!
+def getsignal(sig):
+    """getsignal(sig) -> action
+
+    Return the current action for the given signal.  The return value can be:
+    SIG_IGN -- if the signal is being ignored
+    SIG_DFL -- if the default action for the signal is in effect
+    None -- if an unknown handler is in effect
+    anything else -- the callable Python object used as a handler
+
+    Note for Jython: this function is NOT threadsafe. The underlying
+    Java support only enables getting the current signal handler by
+    setting a new one. So this is completely prone to race conditions.
+    """
+    try:
+        signal = _signals[sig]
+    except KeyError:
+        raise ValueError("signal number out of range")
+    current = sun.misc.Signal.handle(signal, SIG_DFL)
+    sun.misc.Signal.handle(signal, current) # and reinstall
+
+    if isinstance(current, JythonSignalHandler):
+        return current.action
+    else:
+        return current
+
+def default_int_handler(sig, frame):
+    """
+    default_int_handler(...)
+
+    The default handler for SIGINT installed by Python.
+    It raises KeyboardInterrupt.
+    """
+    raise KeyboardInterrupt
+
+def pause():
+    raise NotImplementedError
+
+_alarm_timer_holder = AtomicReference()
+
+def _alarm_handler(sig, frame):
+    print "Alarm clock"
+    os._exit(0)
+
+# install a default alarm handler, the one we get by default doesn't
+# work terribly well since it throws a bus error (at least on OS X)!
+try:
+    SIGALRM
+    signal(SIGALRM, _alarm_handler)
+except NameError:
+    pass
+
+class _Alarm(object):
+    def __init__(self, interval, task):
+        self.interval = interval
+        self.task = task
+        self.scheduled = None
+        self.timer = threading.Timer(self.interval, self.task)
+
+    def start(self):
+        self.timer.start()
+        self.scheduled = time.time() + self.interval
+
+    def cancel(self):
+        self.timer.cancel()
+        now = time.time()
+        if self.scheduled and self.scheduled > now:
+            return self.scheduled - now
+        else:
+            return 0
+
+def alarm(time):
+    try:
+        SIGALRM
+    except NameError:
+        raise NotImplementedError("alarm not implemented on this platform")
+
+    def raise_alarm():
+        sun.misc.Signal.raise(_signals[SIGALRM])
+
+    if time > 0:
+        new_alarm_timer = _Alarm(time, raise_alarm)
+    else:
+        new_alarm_timer = None
+    old_alarm_timer = _alarm_timer_holder.getAndSet(new_alarm_timer)
+    if old_alarm_timer:
+        scheduled = int(old_alarm_timer.cancel())
+    else:
+        scheduled = 0
+
+    if new_alarm_timer:
+        new_alarm_timer.start()
+    return scheduled
diff --git a/src/main/resources/PythonLibs/site-packages/README b/src/main/resources/PythonLibs/site-packages/README
new file mode 100644
index 0000000000000000000000000000000000000000..273f6251a7f9d9c4142522e9ab1d699a8ab1bad6
--- /dev/null
+++ b/src/main/resources/PythonLibs/site-packages/README
@@ -0,0 +1,2 @@
+This directory exists so that 3rd party packages can be installed
+here.  Read the source for site.py for more details.
diff --git a/src/main/resources/PythonLibs/site.py b/src/main/resources/PythonLibs/site.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c4f52076c8ac7c5d98d62fb1ed4b7b28db25f7e
--- /dev/null
+++ b/src/main/resources/PythonLibs/site.py
@@ -0,0 +1,623 @@
+"""Append module search paths for third-party packages to sys.path.
+
+****************************************************************
+* This module is automatically imported during initialization. *
+****************************************************************
+
+In earlier versions of Python (up to 1.5a3), scripts or modules that
+needed to use site-specific modules would place ``import site''
+somewhere near the top of their code.  Because of the automatic
+import, this is no longer necessary (but code that does it still
+works).
+
+This will append site-specific paths to the module search path.  On
+Unix (including Mac OSX), it starts with sys.prefix and
+sys.exec_prefix (if different) and appends
+lib/python<version>/site-packages as well as lib/site-python.
+On other platforms (such as Windows), it tries each of the
+prefixes directly, as well as with lib/site-packages appended.  The
+resulting directories, if they exist, are appended to sys.path, and
+also inspected for path configuration files.
+
+A path configuration file is a file whose name has the form
+<package>.pth; its contents are additional directories (one per line)
+to be added to sys.path.  Non-existing directories (or
+non-directories) are never added to sys.path; no directory is added to
+sys.path more than once.  Blank lines and lines beginning with
+'#' are skipped. Lines starting with 'import' are executed.
+
+For example, suppose sys.prefix and sys.exec_prefix are set to
+/usr/local and there is a directory /usr/local/lib/python2.5/site-packages
+with three subdirectories, foo, bar and spam, and two path
+configuration files, foo.pth and bar.pth.  Assume foo.pth contains the
+following:
+
+  # foo package configuration
+  foo
+  bar
+  bletch
+
+and bar.pth contains:
+
+  # bar package configuration
+  bar
+
+Then the following directories are added to sys.path, in this order:
+
+  /usr/local/lib/python2.5/site-packages/bar
+  /usr/local/lib/python2.5/site-packages/foo
+
+Note that bletch is omitted because it doesn't exist; bar precedes foo
+because bar.pth comes alphabetically before foo.pth; and spam is
+omitted because it is not mentioned in either path configuration file.
+
+After these path manipulations, an attempt is made to import a module
+named sitecustomize, which can perform arbitrary additional
+site-specific customizations.  If this import fails with an
+ImportError exception, it is silently ignored.
+
+"""
+
+import sys
+import os
+import __builtin__
+import traceback
+
+_is_jython = sys.platform.startswith("java")
+if _is_jython:
+    _ModuleType = type(os)
+
+# Prefixes for site-packages; add additional prefixes like /usr/local here
+PREFIXES = [sys.prefix, sys.exec_prefix]
+# Enable per user site-packages directory
+# set it to False to disable the feature or True to force the feature
+ENABLE_USER_SITE = None
+
+# for distutils.commands.install
+# These values are initialized by the getuserbase() and getusersitepackages()
+# functions, through the main() function when Python starts.
+USER_SITE = None
+USER_BASE = None
+
+
+def makepath(*paths):
+    dir = os.path.join(*paths)
+    if _is_jython and (dir == '__classpath__' or
+                       dir.startswith('__pyclasspath__')):
+            return dir, dir
+    try:
+        dir = os.path.abspath(dir)
+    except OSError:
+        pass
+    return dir, os.path.normcase(dir)
+
+
+def abs__file__():
+    """Set all module' __file__ attribute to an absolute path"""
+    for m in sys.modules.values():
+        if hasattr(m, '__loader__') or (
+            _is_jython and not isinstance(m, _ModuleType)):
+                continue   # don't mess with a PEP 302-supplied __file__
+        f = getattr(m, '__file__', None)
+        if f is None:
+            continue
+        m.__file__ = os.path.abspath(f)
+
+
+def removeduppaths():
+    """ Remove duplicate entries from sys.path along with making them
+    absolute"""
+    # This ensures that the initial path provided by the interpreter contains
+    # only absolute pathnames, even if we're running from the build directory.
+    L = []
+    known_paths = set()
+    for dir in sys.path:
+        # Filter out duplicate paths (on case-insensitive file systems also
+        # if they only differ in case); turn relative paths into absolute
+        # paths.
+        dir, dircase = makepath(dir)
+        if not dircase in known_paths:
+            L.append(dir)
+            known_paths.add(dircase)
+    sys.path[:] = L
+    return known_paths
+
+# XXX This should not be part of site.py, since it is needed even when
+# using the -S option for Python.  See http://www.python.org/sf/586680
+def addbuilddir():
+    """Append ./build/lib.<platform> in case we're running in the build dir
+    (especially for Guido :-)"""
+    from sysconfig import get_platform
+    s = "build/lib.%s-%.3s" % (get_platform(), sys.version)
+    if hasattr(sys, 'gettotalrefcount'):
+        s += '-pydebug'
+    s = os.path.join(os.path.dirname(sys.path.pop()), s)
+    sys.path.append(s)
+
+
+def _init_pathinfo():
+    """Return a set containing all existing directory entries from sys.path"""
+    d = set()
+    for dir in sys.path:
+        try:
+            if os.path.isdir(dir):
+                dir, dircase = makepath(dir)
+                d.add(dircase)
+        except TypeError:
+            continue
+    return d
+
+
+def addpackage(sitedir, name, known_paths):
+    """Process a .pth file within the site-packages directory:
+       For each line in the file, either combine it with sitedir to a path
+       and add that to known_paths, or execute it if it starts with 'import '.
+    """
+    if known_paths is None:
+        _init_pathinfo()
+        reset = 1
+    else:
+        reset = 0
+    fullname = os.path.join(sitedir, name)
+    try:
+        f = open(fullname, "rU")
+    except IOError:
+        return
+    with f:
+        for n, line in enumerate(f):
+            if line.startswith("#"):
+                continue
+            try:
+                if line.startswith(("import ", "import\t")):
+                    exec line
+                    continue
+                line = line.rstrip()
+                dir, dircase = makepath(sitedir, line)
+                if not dircase in known_paths and os.path.exists(dir):
+                    sys.path.append(dir)
+                    known_paths.add(dircase)
+            except Exception as err:
+                print >>sys.stderr, "Error processing line {:d} of {}:\n".format(
+                    n+1, fullname)
+                for record in traceback.format_exception(*sys.exc_info()):
+                    for line in record.splitlines():
+                        print >>sys.stderr, '  '+line
+                print >>sys.stderr, "\nRemainder of file ignored"
+                break
+    if reset:
+        known_paths = None
+    return known_paths
+
+
+def addsitedir(sitedir, known_paths=None):
+    """Add 'sitedir' argument to sys.path if missing and handle .pth files in
+    'sitedir'"""
+    if known_paths is None:
+        known_paths = _init_pathinfo()
+        reset = 1
+    else:
+        reset = 0
+    sitedir, sitedircase = makepath(sitedir)
+    if not sitedircase in known_paths:
+        sys.path.append(sitedir)        # Add path component
+    try:
+        names = os.listdir(sitedir)
+    except os.error:
+        return
+    dotpth = os.extsep + "pth"
+    names = [name for name in names if name.endswith(dotpth)]
+    for name in sorted(names):
+        addpackage(sitedir, name, known_paths)
+    if reset:
+        known_paths = None
+    return known_paths
+
+
+def check_enableusersite():
+    """Check if user site directory is safe for inclusion
+
+    The function tests for the command line flag (including environment var),
+    process uid/gid equal to effective uid/gid.
+
+    None: Disabled for security reasons
+    False: Disabled by user (command line option)
+    True: Safe and enabled
+    """
+    if sys.flags.no_user_site:
+        return False
+
+    if hasattr(os, "getuid") and hasattr(os, "geteuid"):
+        # check process uid == effective uid
+        if os.geteuid() != os.getuid():
+            return None
+    if hasattr(os, "getgid") and hasattr(os, "getegid"):
+        # check process gid == effective gid
+        if os.getegid() != os.getgid():
+            return None
+
+    return True
+
+def getuserbase():
+    """Returns the `user base` directory path.
+
+    The `user base` directory can be used to store data. If the global
+    variable ``USER_BASE`` is not initialized yet, this function will also set
+    it.
+    """
+    global USER_BASE
+    if USER_BASE is not None:
+        return USER_BASE
+    from sysconfig import get_config_var
+    USER_BASE = get_config_var('userbase')
+    return USER_BASE
+
+def getusersitepackages():
+    """Returns the user-specific site-packages directory path.
+
+    If the global variable ``USER_SITE`` is not initialized yet, this
+    function will also set it.
+    """
+    global USER_SITE
+    user_base = getuserbase() # this will also set USER_BASE
+
+    if USER_SITE is not None:
+        return USER_SITE
+
+    from sysconfig import get_path
+    import os
+
+    if sys.platform == 'darwin':
+        from sysconfig import get_config_var
+        if get_config_var('PYTHONFRAMEWORK'):
+            USER_SITE = get_path('purelib', 'osx_framework_user')
+            return USER_SITE
+
+    USER_SITE = get_path('purelib', '%s_user' % os.name)
+    return USER_SITE
+
+def addusersitepackages(known_paths):
+    """Add a per user site-package to sys.path
+
+    Each user has its own python directory with site-packages in the
+    home directory.
+    """
+    # get the per user site-package path
+    # this call will also make sure USER_BASE and USER_SITE are set
+    user_site = getusersitepackages()
+
+    if ENABLE_USER_SITE and os.path.isdir(user_site):
+        addsitedir(user_site, known_paths)
+    return known_paths
+
+def getsitepackages():
+    """Returns a list containing all global site-packages directories
+    (and possibly site-python).
+
+    For each directory present in the global ``PREFIXES``, this function
+    will find its `site-packages` subdirectory depending on the system
+    environment, and will return a list of full paths.
+    """
+    sitepackages = []
+    seen = set()
+
+    for prefix in PREFIXES:
+        if not prefix or prefix in seen:
+            continue
+        seen.add(prefix)
+
+        if sys.platform in ('os2emx', 'riscos') or _is_jython:
+            sitepackages.append(os.path.join(prefix, "Lib", "site-packages"))
+        elif os.sep == '/':
+            sitepackages.append(os.path.join(prefix, "lib",
+                                        "python" + sys.version[:3],
+                                        "site-packages"))
+            sitepackages.append(os.path.join(prefix, "lib", "site-python"))
+        else:
+            sitepackages.append(prefix)
+            sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
+        if sys.platform == "darwin":
+            # for framework builds *only* we add the standard Apple
+            # locations.
+            from sysconfig import get_config_var
+            framework = get_config_var("PYTHONFRAMEWORK")
+            if framework:
+                sitepackages.append(
+                        os.path.join("/Library", framework,
+                            sys.version[:3], "site-packages"))
+    return sitepackages
+
+def addsitepackages(known_paths):
+    """Add site-packages (and possibly site-python) to sys.path"""
+    for sitedir in getsitepackages():
+        if os.path.isdir(sitedir):
+            addsitedir(sitedir, known_paths)
+
+    return known_paths
+
+def setBEGINLIBPATH():
+    """The OS/2 EMX port has optional extension modules that do double duty
+    as DLLs (and must use the .DLL file extension) for other extensions.
+    The library search path needs to be amended so these will be found
+    during module import.  Use BEGINLIBPATH so that these are at the start
+    of the library search path.
+
+    """
+    dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
+    libpath = os.environ['BEGINLIBPATH'].split(';')
+    if libpath[-1]:
+        libpath.append(dllpath)
+    else:
+        libpath[-1] = dllpath
+    os.environ['BEGINLIBPATH'] = ';'.join(libpath)
+
+
+def setquit():
+    """Define new builtins 'quit' and 'exit'.
+
+    These are objects which make the interpreter exit when called.
+    The repr of each object contains a hint at how it works.
+
+    """
+    if os.sep == ':':
+        eof = 'Cmd-Q'
+    elif os.sep == '\\':
+        eof = 'Ctrl-Z plus Return'
+    else:
+        eof = 'Ctrl-D (i.e. EOF)'
+
+    class Quitter(object):
+        def __init__(self, name):
+            self.name = name
+        def __repr__(self):
+            return 'Use %s() or %s to exit' % (self.name, eof)
+        def __call__(self, code=None):
+            # Shells like IDLE catch the SystemExit, but listen when their
+            # stdin wrapper is closed.
+            try:
+                sys.stdin.close()
+            except:
+                pass
+            raise SystemExit(code)
+    __builtin__.quit = Quitter('quit')
+    __builtin__.exit = Quitter('exit')
+
+
+class _Printer(object):
+    """interactive prompt objects for printing the license text, a list of
+    contributors and the copyright notice."""
+
+    MAXLINES = 23
+
+    def __init__(self, name, data, files=(), dirs=()):
+        self.__name = name
+        self.__data = data
+        self.__files = files
+        self.__dirs = dirs
+        self.__lines = None
+
+    def __setup(self):
+        if self.__lines:
+            return
+        data = None
+        for dir in self.__dirs:
+            for filename in self.__files:
+                filename = os.path.join(dir, filename)
+                try:
+                    fp = file(filename, "rU")
+                    data = fp.read()
+                    fp.close()
+                    break
+                except IOError:
+                    pass
+            if data:
+                break
+        if not data:
+            data = self.__data
+        self.__lines = data.split('\n')
+        self.__linecnt = len(self.__lines)
+
+    def __repr__(self):
+        self.__setup()
+        if len(self.__lines) <= self.MAXLINES:
+            return "\n".join(self.__lines)
+        else:
+            return "Type %s() to see the full %s text" % ((self.__name,)*2)
+
+    def __call__(self):
+        self.__setup()
+        prompt = 'Hit Return for more, or q (and Return) to quit: '
+        lineno = 0
+        while 1:
+            try:
+                for i in range(lineno, lineno + self.MAXLINES):
+                    print self.__lines[i]
+            except IndexError:
+                break
+            else:
+                lineno += self.MAXLINES
+                key = None
+                while key is None:
+                    key = raw_input(prompt)
+                    if key not in ('', 'q'):
+                        key = None
+                if key == 'q':
+                    break
+
+def setcopyright():
+    """Set 'copyright' and 'credits' in __builtin__"""
+    __builtin__.copyright = _Printer("copyright", sys.copyright)
+    if sys.platform[:4] == 'java':
+        __builtin__.credits = _Printer(
+            "credits",
+            "Jython is maintained by the Jython developers (www.jython.org).")
+    else:
+        __builtin__.credits = _Printer("credits", """\
+    Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
+    for supporting Python development.  See www.python.org for more information.""")
+    here = os.path.dirname(os.__file__)
+    __builtin__.license = _Printer(
+        "license", "See http://www.python.org/%.3s/license.html" % sys.version,
+        ["LICENSE.txt", "LICENSE"],
+        [os.path.join(here, os.pardir), here, os.curdir])
+
+
+class _Helper(object):
+    """Define the builtin 'help'.
+    This is a wrapper around pydoc.help (with a twist).
+
+    """
+
+    def __repr__(self):
+        return "Type help() for interactive help, " \
+               "or help(object) for help about object."
+    def __call__(self, *args, **kwds):
+        import pydoc
+        return pydoc.help(*args, **kwds)
+
+def sethelper():
+    __builtin__.help = _Helper()
+
+def aliasmbcs():
+    """On Windows, some default encodings are not provided by Python,
+    while they are always available as "mbcs" in each locale. Make
+    them usable by aliasing to "mbcs" in such a case."""
+    if sys.platform == 'win32':
+        import locale, codecs
+        enc = locale.getdefaultlocale()[1]
+        if enc.startswith('cp'):            # "cp***" ?
+            try:
+                codecs.lookup(enc)
+            except LookupError:
+                import encodings
+                encodings._cache[enc] = encodings._unknown
+                encodings.aliases.aliases[enc] = 'mbcs'
+
+def setencoding():
+    """Set the string encoding used by the Unicode implementation.  The
+    default is 'ascii', but if you're willing to experiment, you can
+    change this."""
+    encoding = "ascii" # Default value set by _PyUnicode_Init()
+    if 0:
+        # Enable to support locale aware default string encodings.
+        import locale
+        loc = locale.getdefaultlocale()
+        if loc[1]:
+            encoding = loc[1]
+    if 0:
+        # Enable to switch off string to Unicode coercion and implicit
+        # Unicode to string conversion.
+        encoding = "undefined"
+    if encoding != "ascii":
+        # On Non-Unicode builds this will raise an AttributeError...
+        sys.setdefaultencoding(encoding) # Needs Python Unicode build !
+
+
+def execsitecustomize():
+    """Run custom site specific code, if available."""
+    try:
+        import sitecustomize
+    except ImportError:
+        pass
+    except Exception:
+        if sys.flags.verbose:
+            sys.excepthook(*sys.exc_info())
+        else:
+            print >>sys.stderr, \
+                "'import sitecustomize' failed; use -v for traceback"
+
+
+def execusercustomize():
+    """Run custom user specific code, if available."""
+    try:
+        import usercustomize
+    except ImportError:
+        pass
+    except Exception:
+        if sys.flags.verbose:
+            sys.excepthook(*sys.exc_info())
+        else:
+            print>>sys.stderr, \
+                "'import usercustomize' failed; use -v for traceback"
+
+
+def main():
+    global ENABLE_USER_SITE
+
+    abs__file__()
+    known_paths = removeduppaths()
+    if (os.name == "posix" and sys.path and
+        os.path.basename(sys.path[-1]) == "Modules"):
+        addbuilddir()
+    if ENABLE_USER_SITE is None:
+        ENABLE_USER_SITE = check_enableusersite()
+    known_paths = addusersitepackages(known_paths)
+    known_paths = addsitepackages(known_paths)
+    if sys.platform == 'os2emx':
+        setBEGINLIBPATH()
+    setquit()
+    setcopyright()
+    sethelper()
+    aliasmbcs()
+    setencoding()
+    execsitecustomize()
+    if ENABLE_USER_SITE:
+        execusercustomize()
+    # Remove sys.setdefaultencoding() so that users cannot change the
+    # encoding after initialization.  The test for presence is needed when
+    # this module is run as a script, because this code is executed twice.
+    if hasattr(sys, "setdefaultencoding"):
+        del sys.setdefaultencoding
+
+main()
+
+def _script():
+    help = """\
+    %s [--user-base] [--user-site]
+
+    Without arguments print some useful information
+    With arguments print the value of USER_BASE and/or USER_SITE separated
+    by '%s'.
+
+    Exit codes with --user-base or --user-site:
+      0 - user site directory is enabled
+      1 - user site directory is disabled by user
+      2 - uses site directory is disabled by super user
+          or for security reasons
+     >2 - unknown error
+    """
+    args = sys.argv[1:]
+    if not args:
+        print "sys.path = ["
+        for dir in sys.path:
+            print "    %r," % (dir,)
+        print "]"
+        print "USER_BASE: %r (%s)" % (USER_BASE,
+            "exists" if os.path.isdir(USER_BASE) else "doesn't exist")
+        print "USER_SITE: %r (%s)" % (USER_SITE,
+            "exists" if os.path.isdir(USER_SITE) else "doesn't exist")
+        print "ENABLE_USER_SITE: %r" %  ENABLE_USER_SITE
+        sys.exit(0)
+
+    buffer = []
+    if '--user-base' in args:
+        buffer.append(USER_BASE)
+    if '--user-site' in args:
+        buffer.append(USER_SITE)
+
+    if buffer:
+        print os.pathsep.join(buffer)
+        if ENABLE_USER_SITE:
+            sys.exit(0)
+        elif ENABLE_USER_SITE is False:
+            sys.exit(1)
+        elif ENABLE_USER_SITE is None:
+            sys.exit(2)
+        else:
+            sys.exit(3)
+    else:
+        import textwrap
+        print textwrap.dedent(help % (sys.argv[0], os.pathsep))
+        sys.exit(10)
+
+if __name__ == '__main__':
+    _script()
diff --git a/src/main/resources/PythonLibs/smtpd.py b/src/main/resources/PythonLibs/smtpd.py
new file mode 100644
index 0000000000000000000000000000000000000000..b4d208b2eeb9857e89fcc9df8ffdb6a0233e429f
--- /dev/null
+++ b/src/main/resources/PythonLibs/smtpd.py
@@ -0,0 +1,555 @@
+#! /usr/bin/env python
+"""An RFC 2821 smtp proxy.
+
+Usage: %(program)s [options] [localhost:localport [remotehost:remoteport]]
+
+Options:
+
+    --nosetuid
+    -n
+        This program generally tries to setuid `nobody', unless this flag is
+        set.  The setuid call will fail if this program is not run as root (in
+        which case, use this flag).
+
+    --version
+    -V
+        Print the version number and exit.
+
+    --class classname
+    -c classname
+        Use `classname' as the concrete SMTP proxy class.  Uses `PureProxy' by
+        default.
+
+    --debug
+    -d
+        Turn on debugging prints.
+
+    --help
+    -h
+        Print this message and exit.
+
+Version: %(__version__)s
+
+If localhost is not given then `localhost' is used, and if localport is not
+given then 8025 is used.  If remotehost is not given then `localhost' is used,
+and if remoteport is not given, then 25 is used.
+"""
+
+# Overview:
+#
+# This file implements the minimal SMTP protocol as defined in RFC 821.  It
+# has a hierarchy of classes which implement the backend functionality for the
+# smtpd.  A number of classes are provided:
+#
+#   SMTPServer - the base class for the backend.  Raises NotImplementedError
+#   if you try to use it.
+#
+#   DebuggingServer - simply prints each message it receives on stdout.
+#
+#   PureProxy - Proxies all messages to a real smtpd which does final
+#   delivery.  One known problem with this class is that it doesn't handle
+#   SMTP errors from the backend server at all.  This should be fixed
+#   (contributions are welcome!).
+#
+#   MailmanProxy - An experimental hack to work with GNU Mailman
+#   <www.list.org>.  Using this server as your real incoming smtpd, your
+#   mailhost will automatically recognize and accept mail destined to Mailman
+#   lists when those lists are created.  Every message not destined for a list
+#   gets forwarded to a real backend smtpd, as with PureProxy.  Again, errors
+#   are not handled correctly yet.
+#
+# Please note that this script requires Python 2.0
+#
+# Author: Barry Warsaw <barry@python.org>
+#
+# TODO:
+#
+# - support mailbox delivery
+# - alias files
+# - ESMTP
+# - handle error codes from the backend smtpd
+
+import sys
+import os
+import errno
+import getopt
+import time
+import socket
+import asyncore
+import asynchat
+
+__all__ = ["SMTPServer","DebuggingServer","PureProxy","MailmanProxy"]
+
+program = sys.argv[0]
+__version__ = 'Python SMTP proxy version 0.2'
+
+
+class Devnull:
+    def write(self, msg): pass
+    def flush(self): pass
+
+
+DEBUGSTREAM = Devnull()
+NEWLINE = '\n'
+EMPTYSTRING = ''
+COMMASPACE = ', '
+
+
+def usage(code, msg=''):
+    print >> sys.stderr, __doc__ % globals()
+    if msg:
+        print >> sys.stderr, msg
+    sys.exit(code)
+
+
+class SMTPChannel(asynchat.async_chat):
+    COMMAND = 0
+    DATA = 1
+
+    def __init__(self, server, conn, addr):
+        asynchat.async_chat.__init__(self, conn)
+        self.__server = server
+        self.__conn = conn
+        self.__addr = addr
+        self.__line = []
+        self.__state = self.COMMAND
+        self.__greeting = 0
+        self.__mailfrom = None
+        self.__rcpttos = []
+        self.__data = ''
+        self.__fqdn = socket.getfqdn()
+        try:
+            self.__peer = conn.getpeername()
+        except socket.error, err:
+            # a race condition  may occur if the other end is closing
+            # before we can get the peername
+            self.close()
+            if err[0] != errno.ENOTCONN:
+                raise
+            return
+        print >> DEBUGSTREAM, 'Peer:', repr(self.__peer)
+        self.push('220 %s %s' % (self.__fqdn, __version__))
+        self.set_terminator('\r\n')
+
+    # Overrides base class for convenience
+    def push(self, msg):
+        asynchat.async_chat.push(self, msg + '\r\n')
+
+    # Implementation of base class abstract method
+    def collect_incoming_data(self, data):
+        self.__line.append(data)
+
+    # Implementation of base class abstract method
+    def found_terminator(self):
+        line = EMPTYSTRING.join(self.__line)
+        print >> DEBUGSTREAM, 'Data:', repr(line)
+        self.__line = []
+        if self.__state == self.COMMAND:
+            if not line:
+                self.push('500 Error: bad syntax')
+                return
+            method = None
+            i = line.find(' ')
+            if i < 0:
+                command = line.upper()
+                arg = None
+            else:
+                command = line[:i].upper()
+                arg = line[i+1:].strip()
+            method = getattr(self, 'smtp_' + command, None)
+            if not method:
+                self.push('502 Error: command "%s" not implemented' % command)
+                return
+            method(arg)
+            return
+        else:
+            if self.__state != self.DATA:
+                self.push('451 Internal confusion')
+                return
+            # Remove extraneous carriage returns and de-transparency according
+            # to RFC 821, Section 4.5.2.
+            data = []
+            for text in line.split('\r\n'):
+                if text and text[0] == '.':
+                    data.append(text[1:])
+                else:
+                    data.append(text)
+            self.__data = NEWLINE.join(data)
+            status = self.__server.process_message(self.__peer,
+                                                   self.__mailfrom,
+                                                   self.__rcpttos,
+                                                   self.__data)
+            self.__rcpttos = []
+            self.__mailfrom = None
+            self.__state = self.COMMAND
+            self.set_terminator('\r\n')
+            if not status:
+                self.push('250 Ok')
+            else:
+                self.push(status)
+
+    # SMTP and ESMTP commands
+    def smtp_HELO(self, arg):
+        if not arg:
+            self.push('501 Syntax: HELO hostname')
+            return
+        if self.__greeting:
+            self.push('503 Duplicate HELO/EHLO')
+        else:
+            self.__greeting = arg
+            self.push('250 %s' % self.__fqdn)
+
+    def smtp_NOOP(self, arg):
+        if arg:
+            self.push('501 Syntax: NOOP')
+        else:
+            self.push('250 Ok')
+
+    def smtp_QUIT(self, arg):
+        # args is ignored
+        self.push('221 Bye')
+        self.close_when_done()
+
+    # factored
+    def __getaddr(self, keyword, arg):
+        address = None
+        keylen = len(keyword)
+        if arg[:keylen].upper() == keyword:
+            address = arg[keylen:].strip()
+            if not address:
+                pass
+            elif address[0] == '<' and address[-1] == '>' and address != '<>':
+                # Addresses can be in the form <person@dom.com> but watch out
+                # for null address, e.g. <>
+                address = address[1:-1]
+        return address
+
+    def smtp_MAIL(self, arg):
+        print >> DEBUGSTREAM, '===> MAIL', arg
+        address = self.__getaddr('FROM:', arg) if arg else None
+        if not address:
+            self.push('501 Syntax: MAIL FROM:<address>')
+            return
+        if self.__mailfrom:
+            self.push('503 Error: nested MAIL command')
+            return
+        self.__mailfrom = address
+        print >> DEBUGSTREAM, 'sender:', self.__mailfrom
+        self.push('250 Ok')
+
+    def smtp_RCPT(self, arg):
+        print >> DEBUGSTREAM, '===> RCPT', arg
+        if not self.__mailfrom:
+            self.push('503 Error: need MAIL command')
+            return
+        address = self.__getaddr('TO:', arg) if arg else None
+        if not address:
+            self.push('501 Syntax: RCPT TO: <address>')
+            return
+        self.__rcpttos.append(address)
+        print >> DEBUGSTREAM, 'recips:', self.__rcpttos
+        self.push('250 Ok')
+
+    def smtp_RSET(self, arg):
+        if arg:
+            self.push('501 Syntax: RSET')
+            return
+        # Resets the sender, recipients, and data, but not the greeting
+        self.__mailfrom = None
+        self.__rcpttos = []
+        self.__data = ''
+        self.__state = self.COMMAND
+        self.push('250 Ok')
+
+    def smtp_DATA(self, arg):
+        if not self.__rcpttos:
+            self.push('503 Error: need RCPT command')
+            return
+        if arg:
+            self.push('501 Syntax: DATA')
+            return
+        self.__state = self.DATA
+        self.set_terminator('\r\n.\r\n')
+        self.push('354 End data with <CR><LF>.<CR><LF>')
+
+
+class SMTPServer(asyncore.dispatcher):
+    def __init__(self, localaddr, remoteaddr):
+        self._localaddr = localaddr
+        self._remoteaddr = remoteaddr
+        asyncore.dispatcher.__init__(self)
+        try:
+            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+            # try to re-use a server port if possible
+            self.set_reuse_addr()
+            self.bind(localaddr)
+            self.listen(5)
+        except:
+            # cleanup asyncore.socket_map before raising
+            self.close()
+            raise
+        else:
+            print >> DEBUGSTREAM, \
+                  '%s started at %s\n\tLocal addr: %s\n\tRemote addr:%s' % (
+                self.__class__.__name__, time.ctime(time.time()),
+                localaddr, remoteaddr)
+
+    def handle_accept(self):
+        pair = self.accept()
+        if pair is not None:
+            conn, addr = pair
+            print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
+            channel = SMTPChannel(self, conn, addr)
+
+    # API for "doing something useful with the message"
+    def process_message(self, peer, mailfrom, rcpttos, data):
+        """Override this abstract method to handle messages from the client.
+
+        peer is a tuple containing (ipaddr, port) of the client that made the
+        socket connection to our smtp port.
+
+        mailfrom is the raw address the client claims the message is coming
+        from.
+
+        rcpttos is a list of raw addresses the client wishes to deliver the
+        message to.
+
+        data is a string containing the entire full text of the message,
+        headers (if supplied) and all.  It has been `de-transparencied'
+        according to RFC 821, Section 4.5.2.  In other words, a line
+        containing a `.' followed by other text has had the leading dot
+        removed.
+
+        This function should return None, for a normal `250 Ok' response;
+        otherwise it returns the desired response string in RFC 821 format.
+
+        """
+        raise NotImplementedError
+
+
+class DebuggingServer(SMTPServer):
+    # Do something with the gathered message
+    def process_message(self, peer, mailfrom, rcpttos, data):
+        inheaders = 1
+        lines = data.split('\n')
+        print '---------- MESSAGE FOLLOWS ----------'
+        for line in lines:
+            # headers first
+            if inheaders and not line:
+                print 'X-Peer:', peer[0]
+                inheaders = 0
+            print line
+        print '------------ END MESSAGE ------------'
+
+
+class PureProxy(SMTPServer):
+    def process_message(self, peer, mailfrom, rcpttos, data):
+        lines = data.split('\n')
+        # Look for the last header
+        i = 0
+        for line in lines:
+            if not line:
+                break
+            i += 1
+        lines.insert(i, 'X-Peer: %s' % peer[0])
+        data = NEWLINE.join(lines)
+        refused = self._deliver(mailfrom, rcpttos, data)
+        # TBD: what to do with refused addresses?
+        print >> DEBUGSTREAM, 'we got some refusals:', refused
+
+    def _deliver(self, mailfrom, rcpttos, data):
+        import smtplib
+        refused = {}
+        try:
+            s = smtplib.SMTP()
+            s.connect(self._remoteaddr[0], self._remoteaddr[1])
+            try:
+                refused = s.sendmail(mailfrom, rcpttos, data)
+            finally:
+                s.quit()
+        except smtplib.SMTPRecipientsRefused, e:
+            print >> DEBUGSTREAM, 'got SMTPRecipientsRefused'
+            refused = e.recipients
+        except (socket.error, smtplib.SMTPException), e:
+            print >> DEBUGSTREAM, 'got', e.__class__
+            # All recipients were refused.  If the exception had an associated
+            # error code, use it.  Otherwise,fake it with a non-triggering
+            # exception code.
+            errcode = getattr(e, 'smtp_code', -1)
+            errmsg = getattr(e, 'smtp_error', 'ignore')
+            for r in rcpttos:
+                refused[r] = (errcode, errmsg)
+        return refused
+
+
+class MailmanProxy(PureProxy):
+    def process_message(self, peer, mailfrom, rcpttos, data):
+        from cStringIO import StringIO
+        from Mailman import Utils
+        from Mailman import Message
+        from Mailman import MailList
+        # If the message is to a Mailman mailing list, then we'll invoke the
+        # Mailman script directly, without going through the real smtpd.
+        # Otherwise we'll forward it to the local proxy for disposition.
+        listnames = []
+        for rcpt in rcpttos:
+            local = rcpt.lower().split('@')[0]
+            # We allow the following variations on the theme
+            #   listname
+            #   listname-admin
+            #   listname-owner
+            #   listname-request
+            #   listname-join
+            #   listname-leave
+            parts = local.split('-')
+            if len(parts) > 2:
+                continue
+            listname = parts[0]
+            if len(parts) == 2:
+                command = parts[1]
+            else:
+                command = ''
+            if not Utils.list_exists(listname) or command not in (
+                    '', 'admin', 'owner', 'request', 'join', 'leave'):
+                continue
+            listnames.append((rcpt, listname, command))
+        # Remove all list recipients from rcpttos and forward what we're not
+        # going to take care of ourselves.  Linear removal should be fine
+        # since we don't expect a large number of recipients.
+        for rcpt, listname, command in listnames:
+            rcpttos.remove(rcpt)
+        # If there's any non-list destined recipients left,
+        print >> DEBUGSTREAM, 'forwarding recips:', ' '.join(rcpttos)
+        if rcpttos:
+            refused = self._deliver(mailfrom, rcpttos, data)
+            # TBD: what to do with refused addresses?
+            print >> DEBUGSTREAM, 'we got refusals:', refused
+        # Now deliver directly to the list commands
+        mlists = {}
+        s = StringIO(data)
+        msg = Message.Message(s)
+        # These headers are required for the proper execution of Mailman.  All
+        # MTAs in existence seem to add these if the original message doesn't
+        # have them.
+        if not msg.getheader('from'):
+            msg['From'] = mailfrom
+        if not msg.getheader('date'):
+            msg['Date'] = time.ctime(time.time())
+        for rcpt, listname, command in listnames:
+            print >> DEBUGSTREAM, 'sending message to', rcpt
+            mlist = mlists.get(listname)
+            if not mlist:
+                mlist = MailList.MailList(listname, lock=0)
+                mlists[listname] = mlist
+            # dispatch on the type of command
+            if command == '':
+                # post
+                msg.Enqueue(mlist, tolist=1)
+            elif command == 'admin':
+                msg.Enqueue(mlist, toadmin=1)
+            elif command == 'owner':
+                msg.Enqueue(mlist, toowner=1)
+            elif command == 'request':
+                msg.Enqueue(mlist, torequest=1)
+            elif command in ('join', 'leave'):
+                # TBD: this is a hack!
+                if command == 'join':
+                    msg['Subject'] = 'subscribe'
+                else:
+                    msg['Subject'] = 'unsubscribe'
+                msg.Enqueue(mlist, torequest=1)
+
+
+class Options:
+    setuid = 1
+    classname = 'PureProxy'
+
+
+def parseargs():
+    global DEBUGSTREAM
+    try:
+        opts, args = getopt.getopt(
+            sys.argv[1:], 'nVhc:d',
+            ['class=', 'nosetuid', 'version', 'help', 'debug'])
+    except getopt.error, e:
+        usage(1, e)
+
+    options = Options()
+    for opt, arg in opts:
+        if opt in ('-h', '--help'):
+            usage(0)
+        elif opt in ('-V', '--version'):
+            print >> sys.stderr, __version__
+            sys.exit(0)
+        elif opt in ('-n', '--nosetuid'):
+            options.setuid = 0
+        elif opt in ('-c', '--class'):
+            options.classname = arg
+        elif opt in ('-d', '--debug'):
+            DEBUGSTREAM = sys.stderr
+
+    # parse the rest of the arguments
+    if len(args) < 1:
+        localspec = 'localhost:8025'
+        remotespec = 'localhost:25'
+    elif len(args) < 2:
+        localspec = args[0]
+        remotespec = 'localhost:25'
+    elif len(args) < 3:
+        localspec = args[0]
+        remotespec = args[1]
+    else:
+        usage(1, 'Invalid arguments: %s' % COMMASPACE.join(args))
+
+    # split into host/port pairs
+    i = localspec.find(':')
+    if i < 0:
+        usage(1, 'Bad local spec: %s' % localspec)
+    options.localhost = localspec[:i]
+    try:
+        options.localport = int(localspec[i+1:])
+    except ValueError:
+        usage(1, 'Bad local port: %s' % localspec)
+    i = remotespec.find(':')
+    if i < 0:
+        usage(1, 'Bad remote spec: %s' % remotespec)
+    options.remotehost = remotespec[:i]
+    try:
+        options.remoteport = int(remotespec[i+1:])
+    except ValueError:
+        usage(1, 'Bad remote port: %s' % remotespec)
+    return options
+
+
+if __name__ == '__main__':
+    options = parseargs()
+    # Become nobody
+    classname = options.classname
+    if "." in classname:
+        lastdot = classname.rfind(".")
+        mod = __import__(classname[:lastdot], globals(), locals(), [""])
+        classname = classname[lastdot+1:]
+    else:
+        import __main__ as mod
+    class_ = getattr(mod, classname)
+    proxy = class_((options.localhost, options.localport),
+                   (options.remotehost, options.remoteport))
+    if options.setuid:
+        try:
+            import pwd
+        except ImportError:
+            print >> sys.stderr, \
+                  'Cannot import module "pwd"; try running with -n option.'
+            sys.exit(1)
+        nobody = pwd.getpwnam('nobody')[2]
+        try:
+            os.setuid(nobody)
+        except OSError, e:
+            if e.errno != errno.EPERM: raise
+            print >> sys.stderr, \
+                  'Cannot setuid "nobody"; try running with -n option.'
+            sys.exit(1)
+    try:
+        asyncore.loop()
+    except KeyboardInterrupt:
+        pass
diff --git a/src/main/resources/PythonLibs/smtplib.py b/src/main/resources/PythonLibs/smtplib.py
new file mode 100644
index 0000000000000000000000000000000000000000..099e54a4fa1e3ccbd43a235a502e4fef7f5b2683
--- /dev/null
+++ b/src/main/resources/PythonLibs/smtplib.py
@@ -0,0 +1,857 @@
+#! /usr/bin/env python
+
+'''SMTP/ESMTP client class.
+
+This should follow RFC 821 (SMTP), RFC 1869 (ESMTP), RFC 2554 (SMTP
+Authentication) and RFC 2487 (Secure SMTP over TLS).
+
+Notes:
+
+Please remember, when doing ESMTP, that the names of the SMTP service
+extensions are NOT the same thing as the option keywords for the RCPT
+and MAIL commands!
+
+Example:
+
+  >>> import smtplib
+  >>> s=smtplib.SMTP("localhost")
+  >>> print s.help()
+  This is Sendmail version 8.8.4
+  Topics:
+      HELO    EHLO    MAIL    RCPT    DATA
+      RSET    NOOP    QUIT    HELP    VRFY
+      EXPN    VERB    ETRN    DSN
+  For more info use "HELP <topic>".
+  To report bugs in the implementation send email to
+      sendmail-bugs@sendmail.org.
+  For local information send email to Postmaster at your site.
+  End of HELP info
+  >>> s.putcmd("vrfy","someone@here")
+  >>> s.getreply()
+  (250, "Somebody OverHere <somebody@here.my.org>")
+  >>> s.quit()
+'''
+
+# Author: The Dragon De Monsyne <dragondm@integral.org>
+# ESMTP support, test code and doc fixes added by
+#     Eric S. Raymond <esr@thyrsus.com>
+# Better RFC 821 compliance (MAIL and RCPT, and CRLF in data)
+#     by Carey Evans <c.evans@clear.net.nz>, for picky mail servers.
+# RFC 2554 (authentication) support by Gerhard Haering <gerhard@bigfoot.de>.
+#
+# This was modified from the Python 1.5 library HTTP lib.
+
+import socket
+import re
+import email.utils
+import base64
+import hmac
+from email.base64mime import encode as encode_base64
+from sys import stderr
+
+__all__ = ["SMTPException", "SMTPServerDisconnected", "SMTPResponseException",
+           "SMTPSenderRefused", "SMTPRecipientsRefused", "SMTPDataError",
+           "SMTPConnectError", "SMTPHeloError", "SMTPAuthenticationError",
+           "quoteaddr", "quotedata", "SMTP"]
+
+SMTP_PORT = 25
+SMTP_SSL_PORT = 465
+CRLF = "\r\n"
+
+OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I)
+
+
+# Exception classes used by this module.
+class SMTPException(Exception):
+    """Base class for all exceptions raised by this module."""
+
+class SMTPServerDisconnected(SMTPException):
+    """Not connected to any SMTP server.
+
+    This exception is raised when the server unexpectedly disconnects,
+    or when an attempt is made to use the SMTP instance before
+    connecting it to a server.
+    """
+
+class SMTPResponseException(SMTPException):
+    """Base class for all exceptions that include an SMTP error code.
+
+    These exceptions are generated in some instances when the SMTP
+    server returns an error code.  The error code is stored in the
+    `smtp_code' attribute of the error, and the `smtp_error' attribute
+    is set to the error message.
+    """
+
+    def __init__(self, code, msg):
+        self.smtp_code = code
+        self.smtp_error = msg
+        self.args = (code, msg)
+
+class SMTPSenderRefused(SMTPResponseException):
+    """Sender address refused.
+
+    In addition to the attributes set by on all SMTPResponseException
+    exceptions, this sets `sender' to the string that the SMTP refused.
+    """
+
+    def __init__(self, code, msg, sender):
+        self.smtp_code = code
+        self.smtp_error = msg
+        self.sender = sender
+        self.args = (code, msg, sender)
+
+class SMTPRecipientsRefused(SMTPException):
+    """All recipient addresses refused.
+
+    The errors for each recipient are accessible through the attribute
+    'recipients', which is a dictionary of exactly the same sort as
+    SMTP.sendmail() returns.
+    """
+
+    def __init__(self, recipients):
+        self.recipients = recipients
+        self.args = (recipients,)
+
+
+class SMTPDataError(SMTPResponseException):
+    """The SMTP server didn't accept the data."""
+
+class SMTPConnectError(SMTPResponseException):
+    """Error during connection establishment."""
+
+class SMTPHeloError(SMTPResponseException):
+    """The server refused our HELO reply."""
+
+class SMTPAuthenticationError(SMTPResponseException):
+    """Authentication error.
+
+    Most probably the server didn't accept the username/password
+    combination provided.
+    """
+
+
+def quoteaddr(addr):
+    """Quote a subset of the email addresses defined by RFC 821.
+
+    Should be able to handle anything rfc822.parseaddr can handle.
+    """
+    m = (None, None)
+    try:
+        m = email.utils.parseaddr(addr)[1]
+    except AttributeError:
+        pass
+    if m == (None, None):  # Indicates parse failure or AttributeError
+        # something weird here.. punt -ddm
+        return "<%s>" % addr
+    elif m is None:
+        # the sender wants an empty return address
+        return "<>"
+    else:
+        return "<%s>" % m
+
+def _addr_only(addrstring):
+    displayname, addr = email.utils.parseaddr(addrstring)
+    if (displayname, addr) == ('', ''):
+        # parseaddr couldn't parse it, so use it as is.
+        return addrstring
+    return addr
+
+def quotedata(data):
+    """Quote data for email.
+
+    Double leading '.', and change Unix newline '\\n', or Mac '\\r' into
+    Internet CRLF end-of-line.
+    """
+    return re.sub(r'(?m)^\.', '..',
+        re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))
+
+
+try:
+    import ssl
+except ImportError:
+    _have_ssl = False
+else:
+    class SSLFakeFile:
+        """A fake file like object that really wraps a SSLObject.
+
+        It only supports what is needed in smtplib.
+        """
+        def __init__(self, sslobj):
+            self.sslobj = sslobj
+
+        def readline(self):
+            str = ""
+            chr = None
+            while chr != "\n":
+                chr = self.sslobj.read(1)
+                if not chr:
+                    break
+                str += chr
+            return str
+
+        def close(self):
+            pass
+
+    _have_ssl = True
+
+class SMTP:
+    """This class manages a connection to an SMTP or ESMTP server.
+    SMTP Objects:
+        SMTP objects have the following attributes:
+            helo_resp
+                This is the message given by the server in response to the
+                most recent HELO command.
+
+            ehlo_resp
+                This is the message given by the server in response to the
+                most recent EHLO command. This is usually multiline.
+
+            does_esmtp
+                This is a True value _after you do an EHLO command_, if the
+                server supports ESMTP.
+
+            esmtp_features
+                This is a dictionary, which, if the server supports ESMTP,
+                will _after you do an EHLO command_, contain the names of the
+                SMTP service extensions this server supports, and their
+                parameters (if any).
+
+                Note, all extension names are mapped to lower case in the
+                dictionary.
+
+        See each method's docstrings for details.  In general, there is a
+        method of the same name to perform each SMTP command.  There is also a
+        method called 'sendmail' that will do an entire mail transaction.
+        """
+    debuglevel = 0
+    file = None
+    helo_resp = None
+    ehlo_msg = "ehlo"
+    ehlo_resp = None
+    does_esmtp = 0
+    default_port = SMTP_PORT
+
+    def __init__(self, host='', port=0, local_hostname=None,
+                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
+        """Initialize a new instance.
+
+        If specified, `host' is the name of the remote host to which to
+        connect.  If specified, `port' specifies the port to which to connect.
+        By default, smtplib.SMTP_PORT is used.  An SMTPConnectError is raised
+        if the specified `host' doesn't respond correctly.  If specified,
+        `local_hostname` is used as the FQDN of the local host.  By default,
+        the local hostname is found using socket.getfqdn().
+
+        """
+        self.timeout = timeout
+        self.esmtp_features = {}
+        if host:
+            (code, msg) = self.connect(host, port)
+            if code != 220:
+                raise SMTPConnectError(code, msg)
+        if local_hostname is not None:
+            self.local_hostname = local_hostname
+        else:
+            # RFC 2821 says we should use the fqdn in the EHLO/HELO verb, and
+            # if that can't be calculated, that we should use a domain literal
+            # instead (essentially an encoded IP address like [A.B.C.D]).
+            fqdn = socket.getfqdn()
+            if '.' in fqdn:
+                self.local_hostname = fqdn
+            else:
+                # We can't find an fqdn hostname, so use a domain literal
+                addr = '127.0.0.1'
+                try:
+                    addr = socket.gethostbyname(socket.gethostname())
+                except socket.gaierror:
+                    pass
+                self.local_hostname = '[%s]' % addr
+
+    def set_debuglevel(self, debuglevel):
+        """Set the debug output level.
+
+        A non-false value results in debug messages for connection and for all
+        messages sent to and received from the server.
+
+        """
+        self.debuglevel = debuglevel
+
+    def _get_socket(self, port, host, timeout):
+        # This makes it simpler for SMTP_SSL to use the SMTP connect code
+        # and just alter the socket connection bit.
+        if self.debuglevel > 0:
+            print>>stderr, 'connect:', (host, port)
+        return socket.create_connection((port, host), timeout)
+
+    def connect(self, host='localhost', port=0):
+        """Connect to a host on a given port.
+
+        If the hostname ends with a colon (`:') followed by a number, and
+        there is no port specified, that suffix will be stripped off and the
+        number interpreted as the port number to use.
+
+        Note: This method is automatically invoked by __init__, if a host is
+        specified during instantiation.
+
+        """
+        if not port and (host.find(':') == host.rfind(':')):
+            i = host.rfind(':')
+            if i >= 0:
+                host, port = host[:i], host[i + 1:]
+                try:
+                    port = int(port)
+                except ValueError:
+                    raise socket.error, "nonnumeric port"
+        if not port:
+            port = self.default_port
+        if self.debuglevel > 0:
+            print>>stderr, 'connect:', (host, port)
+        self.sock = self._get_socket(host, port, self.timeout)
+        (code, msg) = self.getreply()
+        if self.debuglevel > 0:
+            print>>stderr, "connect:", msg
+        return (code, msg)
+
+    def send(self, str):
+        """Send `str' to the server."""
+        if self.debuglevel > 0:
+            print>>stderr, 'send:', repr(str)
+        if hasattr(self, 'sock') and self.sock:
+            try:
+                self.sock.sendall(str)
+            except socket.error:
+                self.close()
+                raise SMTPServerDisconnected('Server not connected')
+        else:
+            raise SMTPServerDisconnected('please run connect() first')
+
+    def putcmd(self, cmd, args=""):
+        """Send a command to the server."""
+        if args == "":
+            str = '%s%s' % (cmd, CRLF)
+        else:
+            str = '%s %s%s' % (cmd, args, CRLF)
+        self.send(str)
+
+    def getreply(self):
+        """Get a reply from the server.
+
+        Returns a tuple consisting of:
+
+          - server response code (e.g. '250', or such, if all goes well)
+            Note: returns -1 if it can't read response code.
+
+          - server response string corresponding to response code (multiline
+            responses are converted to a single, multiline string).
+
+        Raises SMTPServerDisconnected if end-of-file is reached.
+        """
+        resp = []
+        if self.file is None:
+            self.file = self.sock.makefile('rb')
+        while 1:
+            try:
+                line = self.file.readline()
+            except socket.error as e:
+                self.close()
+                raise SMTPServerDisconnected("Connection unexpectedly closed: "
+                                             + str(e))
+            if line == '':
+                self.close()
+                raise SMTPServerDisconnected("Connection unexpectedly closed")
+            if self.debuglevel > 0:
+                print>>stderr, 'reply:', repr(line)
+            resp.append(line[4:].strip())
+            code = line[:3]
+            # Check that the error code is syntactically correct.
+            # Don't attempt to read a continuation line if it is broken.
+            try:
+                errcode = int(code)
+            except ValueError:
+                errcode = -1
+                break
+            # Check if multiline response.
+            if line[3:4] != "-":
+                break
+
+        errmsg = "\n".join(resp)
+        if self.debuglevel > 0:
+            print>>stderr, 'reply: retcode (%s); Msg: %s' % (errcode, errmsg)
+        return errcode, errmsg
+
+    def docmd(self, cmd, args=""):
+        """Send a command, and return its response code."""
+        self.putcmd(cmd, args)
+        return self.getreply()
+
+    # std smtp commands
+    def helo(self, name=''):
+        """SMTP 'helo' command.
+        Hostname to send for this command defaults to the FQDN of the local
+        host.
+        """
+        self.putcmd("helo", name or self.local_hostname)
+        (code, msg) = self.getreply()
+        self.helo_resp = msg
+        return (code, msg)
+
+    def ehlo(self, name=''):
+        """ SMTP 'ehlo' command.
+        Hostname to send for this command defaults to the FQDN of the local
+        host.
+        """
+        self.esmtp_features = {}
+        self.putcmd(self.ehlo_msg, name or self.local_hostname)
+        (code, msg) = self.getreply()
+        # According to RFC1869 some (badly written)
+        # MTA's will disconnect on an ehlo. Toss an exception if
+        # that happens -ddm
+        if code == -1 and len(msg) == 0:
+            self.close()
+            raise SMTPServerDisconnected("Server not connected")
+        self.ehlo_resp = msg
+        if code != 250:
+            return (code, msg)
+        self.does_esmtp = 1
+        #parse the ehlo response -ddm
+        resp = self.ehlo_resp.split('\n')
+        del resp[0]
+        for each in resp:
+            # To be able to communicate with as many SMTP servers as possible,
+            # we have to take the old-style auth advertisement into account,
+            # because:
+            # 1) Else our SMTP feature parser gets confused.
+            # 2) There are some servers that only advertise the auth methods we
+            #    support using the old style.
+            auth_match = OLDSTYLE_AUTH.match(each)
+            if auth_match:
+                # This doesn't remove duplicates, but that's no problem
+                self.esmtp_features["auth"] = self.esmtp_features.get("auth", "") \
+                        + " " + auth_match.groups(0)[0]
+                continue
+
+            # RFC 1869 requires a space between ehlo keyword and parameters.
+            # It's actually stricter, in that only spaces are allowed between
+            # parameters, but were not going to check for that here.  Note
+            # that the space isn't present if there are no parameters.
+            m = re.match(r'(?P<feature>[A-Za-z0-9][A-Za-z0-9\-]*) ?', each)
+            if m:
+                feature = m.group("feature").lower()
+                params = m.string[m.end("feature"):].strip()
+                if feature == "auth":
+                    self.esmtp_features[feature] = self.esmtp_features.get(feature, "") \
+                            + " " + params
+                else:
+                    self.esmtp_features[feature] = params
+        return (code, msg)
+
+    def has_extn(self, opt):
+        """Does the server support a given SMTP service extension?"""
+        return opt.lower() in self.esmtp_features
+
+    def help(self, args=''):
+        """SMTP 'help' command.
+        Returns help text from server."""
+        self.putcmd("help", args)
+        return self.getreply()[1]
+
+    def rset(self):
+        """SMTP 'rset' command -- resets session."""
+        return self.docmd("rset")
+
+    def noop(self):
+        """SMTP 'noop' command -- doesn't do anything :>"""
+        return self.docmd("noop")
+
+    def mail(self, sender, options=[]):
+        """SMTP 'mail' command -- begins mail xfer session."""
+        optionlist = ''
+        if options and self.does_esmtp:
+            optionlist = ' ' + ' '.join(options)
+        self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist))
+        return self.getreply()
+
+    def rcpt(self, recip, options=[]):
+        """SMTP 'rcpt' command -- indicates 1 recipient for this mail."""
+        optionlist = ''
+        if options and self.does_esmtp:
+            optionlist = ' ' + ' '.join(options)
+        self.putcmd("rcpt", "TO:%s%s" % (quoteaddr(recip), optionlist))
+        return self.getreply()
+
+    def data(self, msg):
+        """SMTP 'DATA' command -- sends message data to server.
+
+        Automatically quotes lines beginning with a period per rfc821.
+        Raises SMTPDataError if there is an unexpected reply to the
+        DATA command; the return value from this method is the final
+        response code received when the all data is sent.
+        """
+        self.putcmd("data")
+        (code, repl) = self.getreply()
+        if self.debuglevel > 0:
+            print>>stderr, "data:", (code, repl)
+        if code != 354:
+            raise SMTPDataError(code, repl)
+        else:
+            q = quotedata(msg)
+            if q[-2:] != CRLF:
+                q = q + CRLF
+            q = q + "." + CRLF
+            self.send(q)
+            (code, msg) = self.getreply()
+            if self.debuglevel > 0:
+                print>>stderr, "data:", (code, msg)
+            return (code, msg)
+
+    def verify(self, address):
+        """SMTP 'verify' command -- checks for address validity."""
+        self.putcmd("vrfy", _addr_only(address))
+        return self.getreply()
+    # a.k.a.
+    vrfy = verify
+
+    def expn(self, address):
+        """SMTP 'expn' command -- expands a mailing list."""
+        self.putcmd("expn", _addr_only(address))
+        return self.getreply()
+
+    # some useful methods
+
+    def ehlo_or_helo_if_needed(self):
+        """Call self.ehlo() and/or self.helo() if needed.
+
+        If there has been no previous EHLO or HELO command this session, this
+        method tries ESMTP EHLO first.
+
+        This method may raise the following exceptions:
+
+         SMTPHeloError            The server didn't reply properly to
+                                  the helo greeting.
+        """
+        if self.helo_resp is None and self.ehlo_resp is None:
+            if not (200 <= self.ehlo()[0] <= 299):
+                (code, resp) = self.helo()
+                if not (200 <= code <= 299):
+                    raise SMTPHeloError(code, resp)
+
+    def login(self, user, password):
+        """Log in on an SMTP server that requires authentication.
+
+        The arguments are:
+            - user:     The user name to authenticate with.
+            - password: The password for the authentication.
+
+        If there has been no previous EHLO or HELO command this session, this
+        method tries ESMTP EHLO first.
+
+        This method will return normally if the authentication was successful.
+
+        This method may raise the following exceptions:
+
+         SMTPHeloError            The server didn't reply properly to
+                                  the helo greeting.
+         SMTPAuthenticationError  The server didn't accept the username/
+                                  password combination.
+         SMTPException            No suitable authentication method was
+                                  found.
+        """
+
+        def encode_cram_md5(challenge, user, password):
+            challenge = base64.decodestring(challenge)
+            response = user + " " + hmac.HMAC(password, challenge).hexdigest()
+            return encode_base64(response, eol="")
+
+        def encode_plain(user, password):
+            return encode_base64("\0%s\0%s" % (user, password), eol="")
+
+
+        AUTH_PLAIN = "PLAIN"
+        AUTH_CRAM_MD5 = "CRAM-MD5"
+        AUTH_LOGIN = "LOGIN"
+
+        self.ehlo_or_helo_if_needed()
+
+        if not self.has_extn("auth"):
+            raise SMTPException("SMTP AUTH extension not supported by server.")
+
+        # Authentication methods the server supports:
+        authlist = self.esmtp_features["auth"].split()
+
+        # List of authentication methods we support: from preferred to
+        # less preferred methods. Except for the purpose of testing the weaker
+        # ones, we prefer stronger methods like CRAM-MD5:
+        preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN, AUTH_LOGIN]
+
+        # Determine the authentication method we'll use
+        authmethod = None
+        for method in preferred_auths:
+            if method in authlist:
+                authmethod = method
+                break
+
+        if authmethod == AUTH_CRAM_MD5:
+            (code, resp) = self.docmd("AUTH", AUTH_CRAM_MD5)
+            if code == 503:
+                # 503 == 'Error: already authenticated'
+                return (code, resp)
+            (code, resp) = self.docmd(encode_cram_md5(resp, user, password))
+        elif authmethod == AUTH_PLAIN:
+            (code, resp) = self.docmd("AUTH",
+                AUTH_PLAIN + " " + encode_plain(user, password))
+        elif authmethod == AUTH_LOGIN:
+            (code, resp) = self.docmd("AUTH",
+                "%s %s" % (AUTH_LOGIN, encode_base64(user, eol="")))
+            if code != 334:
+                raise SMTPAuthenticationError(code, resp)
+            (code, resp) = self.docmd(encode_base64(password, eol=""))
+        elif authmethod is None:
+            raise SMTPException("No suitable authentication method found.")
+        if code not in (235, 503):
+            # 235 == 'Authentication successful'
+            # 503 == 'Error: already authenticated'
+            raise SMTPAuthenticationError(code, resp)
+        return (code, resp)
+
+    def starttls(self, keyfile=None, certfile=None):
+        """Puts the connection to the SMTP server into TLS mode.
+
+        If there has been no previous EHLO or HELO command this session, this
+        method tries ESMTP EHLO first.
+
+        If the server supports TLS, this will encrypt the rest of the SMTP
+        session. If you provide the keyfile and certfile parameters,
+        the identity of the SMTP server and client can be checked. This,
+        however, depends on whether the socket module really checks the
+        certificates.
+
+        This method may raise the following exceptions:
+
+         SMTPHeloError            The server didn't reply properly to
+                                  the helo greeting.
+        """
+        self.ehlo_or_helo_if_needed()
+        if not self.has_extn("starttls"):
+            raise SMTPException("STARTTLS extension not supported by server.")
+        (resp, reply) = self.docmd("STARTTLS")
+        if resp == 220:
+            if not _have_ssl:
+                raise RuntimeError("No SSL support included in this Python")
+            self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
+            self.file = SSLFakeFile(self.sock)
+            # RFC 3207:
+            # The client MUST discard any knowledge obtained from
+            # the server, such as the list of SMTP service extensions,
+            # which was not obtained from the TLS negotiation itself.
+            self.helo_resp = None
+            self.ehlo_resp = None
+            self.esmtp_features = {}
+            self.does_esmtp = 0
+        return (resp, reply)
+
+    def sendmail(self, from_addr, to_addrs, msg, mail_options=[],
+                 rcpt_options=[]):
+        """This command performs an entire mail transaction.
+
+        The arguments are:
+            - from_addr    : The address sending this mail.
+            - to_addrs     : A list of addresses to send this mail to.  A bare
+                             string will be treated as a list with 1 address.
+            - msg          : The message to send.
+            - mail_options : List of ESMTP options (such as 8bitmime) for the
+                             mail command.
+            - rcpt_options : List of ESMTP options (such as DSN commands) for
+                             all the rcpt commands.
+
+        If there has been no previous EHLO or HELO command this session, this
+        method tries ESMTP EHLO first.  If the server does ESMTP, message size
+        and each of the specified options will be passed to it.  If EHLO
+        fails, HELO will be tried and ESMTP options suppressed.
+
+        This method will return normally if the mail is accepted for at least
+        one recipient.  It returns a dictionary, with one entry for each
+        recipient that was refused.  Each entry contains a tuple of the SMTP
+        error code and the accompanying error message sent by the server.
+
+        This method may raise the following exceptions:
+
+         SMTPHeloError          The server didn't reply properly to
+                                the helo greeting.
+         SMTPRecipientsRefused  The server rejected ALL recipients
+                                (no mail was sent).
+         SMTPSenderRefused      The server didn't accept the from_addr.
+         SMTPDataError          The server replied with an unexpected
+                                error code (other than a refusal of
+                                a recipient).
+
+        Note: the connection will be open even after an exception is raised.
+
+        Example:
+
+         >>> import smtplib
+         >>> s=smtplib.SMTP("localhost")
+         >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"]
+         >>> msg = '''\\
+         ... From: Me@my.org
+         ... Subject: testin'...
+         ...
+         ... This is a test '''
+         >>> s.sendmail("me@my.org",tolist,msg)
+         { "three@three.org" : ( 550 ,"User unknown" ) }
+         >>> s.quit()
+
+        In the above example, the message was accepted for delivery to three
+        of the four addresses, and one was rejected, with the error code
+        550.  If all addresses are accepted, then the method will return an
+        empty dictionary.
+
+        """
+        self.ehlo_or_helo_if_needed()
+        esmtp_opts = []
+        if self.does_esmtp:
+            # Hmmm? what's this? -ddm
+            # self.esmtp_features['7bit']=""
+            if self.has_extn('size'):
+                esmtp_opts.append("size=%d" % len(msg))
+            for option in mail_options:
+                esmtp_opts.append(option)
+
+        (code, resp) = self.mail(from_addr, esmtp_opts)
+        if code != 250:
+            self.rset()
+            raise SMTPSenderRefused(code, resp, from_addr)
+        senderrs = {}
+        if isinstance(to_addrs, basestring):
+            to_addrs = [to_addrs]
+        for each in to_addrs:
+            (code, resp) = self.rcpt(each, rcpt_options)
+            if (code != 250) and (code != 251):
+                senderrs[each] = (code, resp)
+        if len(senderrs) == len(to_addrs):
+            # the server refused all our recipients
+            self.rset()
+            raise SMTPRecipientsRefused(senderrs)
+        (code, resp) = self.data(msg)
+        if code != 250:
+            self.rset()
+            raise SMTPDataError(code, resp)
+        #if we got here then somebody got our mail
+        return senderrs
+
+
+    def close(self):
+        """Close the connection to the SMTP server."""
+        if self.file:
+            self.file.close()
+        self.file = None
+        if self.sock:
+            self.sock.close()
+        self.sock = None
+
+
+    def quit(self):
+        """Terminate the SMTP session."""
+        res = self.docmd("quit")
+        self.close()
+        return res
+
+if _have_ssl:
+
+    class SMTP_SSL(SMTP):
+        """ This is a subclass derived from SMTP that connects over an SSL encrypted
+        socket (to use this class you need a socket module that was compiled with SSL
+        support). If host is not specified, '' (the local host) is used. If port is
+        omitted, the standard SMTP-over-SSL port (465) is used. keyfile and certfile
+        are also optional - they can contain a PEM formatted private key and
+        certificate chain file for the SSL connection.
+        """
+
+        default_port = SMTP_SSL_PORT
+
+        def __init__(self, host='', port=0, local_hostname=None,
+                     keyfile=None, certfile=None,
+                     timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
+            self.keyfile = keyfile
+            self.certfile = certfile
+            SMTP.__init__(self, host, port, local_hostname, timeout)
+
+        def _get_socket(self, host, port, timeout):
+            if self.debuglevel > 0:
+                print>>stderr, 'connect:', (host, port)
+            new_socket = socket.create_connection((host, port), timeout)
+            new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
+            self.file = SSLFakeFile(new_socket)
+            return new_socket
+
+    __all__.append("SMTP_SSL")
+
+#
+# LMTP extension
+#
+LMTP_PORT = 2003
+
+class LMTP(SMTP):
+    """LMTP - Local Mail Transfer Protocol
+
+    The LMTP protocol, which is very similar to ESMTP, is heavily based
+    on the standard SMTP client. It's common to use Unix sockets for LMTP,
+    so our connect() method must support that as well as a regular
+    host:port server. To specify a Unix socket, you must use an absolute
+    path as the host, starting with a '/'.
+
+    Authentication is supported, using the regular SMTP mechanism. When
+    using a Unix socket, LMTP generally don't support or require any
+    authentication, but your mileage might vary."""
+
+    ehlo_msg = "lhlo"
+
+    def __init__(self, host='', port=LMTP_PORT, local_hostname=None):
+        """Initialize a new instance."""
+        SMTP.__init__(self, host, port, local_hostname)
+
+    def connect(self, host='localhost', port=0):
+        """Connect to the LMTP daemon, on either a Unix or a TCP socket."""
+        if host[0] != '/':
+            return SMTP.connect(self, host, port)
+
+        # Handle Unix-domain sockets.
+        try:
+            self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            self.sock.connect(host)
+        except socket.error:
+            if self.debuglevel > 0:
+                print>>stderr, 'connect fail:', host
+            if self.sock:
+                self.sock.close()
+            self.sock = None
+            raise
+        (code, msg) = self.getreply()
+        if self.debuglevel > 0:
+            print>>stderr, "connect:", msg
+        return (code, msg)
+
+
+# Test the sendmail method, which tests most of the others.
+# Note: This always sends to localhost.
+if __name__ == '__main__':
+    import sys
+
+    def prompt(prompt):
+        sys.stdout.write(prompt + ": ")
+        return sys.stdin.readline().strip()
+
+    fromaddr = prompt("From")
+    toaddrs = prompt("To").split(',')
+    print "Enter message, end with ^D:"
+    msg = ''
+    while 1:
+        line = sys.stdin.readline()
+        if not line:
+            break
+        msg = msg + line
+    print "Message length is %d" % len(msg)
+
+    server = SMTP('localhost')
+    server.set_debuglevel(1)
+    server.sendmail(fromaddr, toaddrs, msg)
+    server.quit()
diff --git a/src/main/resources/PythonLibs/sndhdr.py b/src/main/resources/PythonLibs/sndhdr.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc2d6b8b197b704782be0c35abecb262ae5c69ae
--- /dev/null
+++ b/src/main/resources/PythonLibs/sndhdr.py
@@ -0,0 +1,228 @@
+"""Routines to help recognizing sound files.
+
+Function whathdr() recognizes various types of sound file headers.
+It understands almost all headers that SOX can decode.
+
+The return tuple contains the following items, in this order:
+- file type (as SOX understands it)
+- sampling rate (0 if unknown or hard to decode)
+- number of channels (0 if unknown or hard to decode)
+- number of frames in the file (-1 if unknown or hard to decode)
+- number of bits/sample, or 'U' for U-LAW, or 'A' for A-LAW
+
+If the file doesn't have a recognizable type, it returns None.
+If the file can't be opened, IOError is raised.
+
+To compute the total time, divide the number of frames by the
+sampling rate (a frame contains a sample for each channel).
+
+Function what() calls whathdr().  (It used to also use some
+heuristics for raw data, but this doesn't work very well.)
+
+Finally, the function test() is a simple main program that calls
+what() for all files mentioned on the argument list.  For directory
+arguments it calls what() for all files in that directory.  Default
+argument is "." (testing all files in the current directory).  The
+option -r tells it to recurse down directories found inside
+explicitly given directories.
+"""
+
+# The file structure is top-down except that the test program and its
+# subroutine come last.
+
+__all__ = ["what","whathdr"]
+
+def what(filename):
+    """Guess the type of a sound file"""
+    res = whathdr(filename)
+    return res
+
+
+def whathdr(filename):
+    """Recognize sound headers"""
+    f = open(filename, 'rb')
+    h = f.read(512)
+    for tf in tests:
+        res = tf(h, f)
+        if res:
+            return res
+    return None
+
+
+#-----------------------------------#
+# Subroutines per sound header type #
+#-----------------------------------#
+
+tests = []
+
+def test_aifc(h, f):
+    import aifc
+    if h[:4] != 'FORM':
+        return None
+    if h[8:12] == 'AIFC':
+        fmt = 'aifc'
+    elif h[8:12] == 'AIFF':
+        fmt = 'aiff'
+    else:
+        return None
+    f.seek(0)
+    try:
+        a = aifc.openfp(f, 'r')
+    except (EOFError, aifc.Error):
+        return None
+    return (fmt, a.getframerate(), a.getnchannels(), \
+            a.getnframes(), 8*a.getsampwidth())
+
+tests.append(test_aifc)
+
+
+def test_au(h, f):
+    if h[:4] == '.snd':
+        f = get_long_be
+    elif h[:4] in ('\0ds.', 'dns.'):
+        f = get_long_le
+    else:
+        return None
+    type = 'au'
+    hdr_size = f(h[4:8])
+    data_size = f(h[8:12])
+    encoding = f(h[12:16])
+    rate = f(h[16:20])
+    nchannels = f(h[20:24])
+    sample_size = 1 # default
+    if encoding == 1:
+        sample_bits = 'U'
+    elif encoding == 2:
+        sample_bits = 8
+    elif encoding == 3:
+        sample_bits = 16
+        sample_size = 2
+    else:
+        sample_bits = '?'
+    frame_size = sample_size * nchannels
+    return type, rate, nchannels, data_size//frame_size, sample_bits
+
+tests.append(test_au)
+
+
+def test_hcom(h, f):
+    if h[65:69] != 'FSSD' or h[128:132] != 'HCOM':
+        return None
+    divisor = get_long_be(h[128+16:128+20])
+    return 'hcom', 22050//divisor, 1, -1, 8
+
+tests.append(test_hcom)
+
+
+def test_voc(h, f):
+    if h[:20] != 'Creative Voice File\032':
+        return None
+    sbseek = get_short_le(h[20:22])
+    rate = 0
+    if 0 <= sbseek < 500 and h[sbseek] == '\1':
+        ratecode = ord(h[sbseek+4])
+        rate = int(1000000.0 / (256 - ratecode))
+    return 'voc', rate, 1, -1, 8
+
+tests.append(test_voc)
+
+
+def test_wav(h, f):
+    # 'RIFF' <len> 'WAVE' 'fmt ' <len>
+    if h[:4] != 'RIFF' or h[8:12] != 'WAVE' or h[12:16] != 'fmt ':
+        return None
+    style = get_short_le(h[20:22])
+    nchannels = get_short_le(h[22:24])
+    rate = get_long_le(h[24:28])
+    sample_bits = get_short_le(h[34:36])
+    return 'wav', rate, nchannels, -1, sample_bits
+
+tests.append(test_wav)
+
+
+def test_8svx(h, f):
+    if h[:4] != 'FORM' or h[8:12] != '8SVX':
+        return None
+    # Should decode it to get #channels -- assume always 1
+    return '8svx', 0, 1, 0, 8
+
+tests.append(test_8svx)
+
+
+def test_sndt(h, f):
+    if h[:5] == 'SOUND':
+        nsamples = get_long_le(h[8:12])
+        rate = get_short_le(h[20:22])
+        return 'sndt', rate, 1, nsamples, 8
+
+tests.append(test_sndt)
+
+
+def test_sndr(h, f):
+    if h[:2] == '\0\0':
+        rate = get_short_le(h[2:4])
+        if 4000 <= rate <= 25000:
+            return 'sndr', rate, 1, -1, 8
+
+tests.append(test_sndr)
+
+
+#---------------------------------------------#
+# Subroutines to extract numbers from strings #
+#---------------------------------------------#
+
+def get_long_be(s):
+    return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
+
+def get_long_le(s):
+    return (ord(s[3])<<24) | (ord(s[2])<<16) | (ord(s[1])<<8) | ord(s[0])
+
+def get_short_be(s):
+    return (ord(s[0])<<8) | ord(s[1])
+
+def get_short_le(s):
+    return (ord(s[1])<<8) | ord(s[0])
+
+
+#--------------------#
+# Small test program #
+#--------------------#
+
+def test():
+    import sys
+    recursive = 0
+    if sys.argv[1:] and sys.argv[1] == '-r':
+        del sys.argv[1:2]
+        recursive = 1
+    try:
+        if sys.argv[1:]:
+            testall(sys.argv[1:], recursive, 1)
+        else:
+            testall(['.'], recursive, 1)
+    except KeyboardInterrupt:
+        sys.stderr.write('\n[Interrupted]\n')
+        sys.exit(1)
+
+def testall(list, recursive, toplevel):
+    import sys
+    import os
+    for filename in list:
+        if os.path.isdir(filename):
+            print filename + '/:',
+            if recursive or toplevel:
+                print 'recursing down:'
+                import glob
+                names = glob.glob(os.path.join(filename, '*'))
+                testall(names, recursive, 0)
+            else:
+                print '*** directory (use -r) ***'
+        else:
+            print filename + ':',
+            sys.stdout.flush()
+            try:
+                print what(filename)
+            except IOError:
+                print '*** not found ***'
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/socket.py b/src/main/resources/PythonLibs/socket.py
new file mode 100644
index 0000000000000000000000000000000000000000..25c779a3555f61a15b6f92fdcbde7d019315e96a
--- /dev/null
+++ b/src/main/resources/PythonLibs/socket.py
@@ -0,0 +1,1889 @@
+"""
+This is an updated socket module for use on JVMs >= 1.5; it is derived from the old jython socket module.
+It is documented, along with known issues and workarounds, on the jython wiki.
+http://wiki.python.org/jython/NewSocketModule
+"""
+
+_defaulttimeout = None
+
+import errno
+import jarray
+import string
+import struct
+import sys
+import threading
+import time
+import types
+
+# Java.io classes
+import java.io.BufferedInputStream
+import java.io.BufferedOutputStream
+# Java.io exceptions
+import java.io.InterruptedIOException
+import java.io.IOException
+
+# Java.lang classes
+import java.lang.String
+# Java.lang exceptions
+import java.lang.Exception
+
+# Java.net classes
+import java.net.DatagramPacket
+import java.net.InetAddress
+import java.net.InetSocketAddress
+import java.net.Socket
+# Java.net exceptions
+import java.net.BindException
+import java.net.ConnectException
+import java.net.NoRouteToHostException
+import java.net.PortUnreachableException
+import java.net.ProtocolException
+import java.net.SocketException
+import java.net.SocketTimeoutException
+import java.net.UnknownHostException
+
+# Java.nio classes
+import java.nio.ByteBuffer
+import java.nio.channels.DatagramChannel
+import java.nio.channels.ServerSocketChannel
+import java.nio.channels.SocketChannel
+# Java.nio exceptions
+import java.nio.channels.AlreadyConnectedException
+import java.nio.channels.AsynchronousCloseException
+import java.nio.channels.CancelledKeyException
+import java.nio.channels.ClosedByInterruptException
+import java.nio.channels.ClosedChannelException
+import java.nio.channels.ClosedSelectorException
+import java.nio.channels.ConnectionPendingException
+import java.nio.channels.IllegalBlockingModeException
+import java.nio.channels.IllegalSelectorException
+import java.nio.channels.NoConnectionPendingException
+import java.nio.channels.NonReadableChannelException
+import java.nio.channels.NonWritableChannelException
+import java.nio.channels.NotYetBoundException
+import java.nio.channels.NotYetConnectedException
+import java.nio.channels.UnresolvedAddressException
+import java.nio.channels.UnsupportedAddressTypeException
+
+# Javax.net.ssl classes
+import javax.net.ssl.SSLSocketFactory
+# Javax.net.ssl exceptions
+javax.net.ssl.SSLException
+javax.net.ssl.SSLHandshakeException
+javax.net.ssl.SSLKeyException
+javax.net.ssl.SSLPeerUnverifiedException
+javax.net.ssl.SSLProtocolException
+
+import org.python.core.io.DatagramSocketIO
+import org.python.core.io.ServerSocketIO
+import org.python.core.io.SocketIO
+from org.python.core.Py import newString as asPyString
+
+class error(IOError): pass
+class herror(error): pass
+class gaierror(error): pass
+class timeout(error): pass
+class sslerror(error): pass
+
+def _add_exception_attrs(exc):
+    setattr(exc, 'errno', exc[0])
+    setattr(exc, 'strerror', exc[1])
+    return exc
+
+def _unmapped_exception(exc):
+    return _add_exception_attrs(error(-1, 'Unmapped exception: %s' % exc))
+
+def java_net_socketexception_handler(exc):
+    if exc.message.startswith("Address family not supported by protocol family"):
+        return _add_exception_attrs(error(errno.EAFNOSUPPORT, 
+                'Address family not supported by protocol family: See http://wiki.python.org/jython/NewSocketModule#IPV6_address_support'))
+    return _unmapped_exception(exc)
+
+def would_block_error(exc=None):
+    return _add_exception_attrs(error(errno.EWOULDBLOCK, 'The socket operation could not complete without blocking'))
+
+ALL = None
+
+_ssl_message = ": Differences between the SSL socket behaviour of cpython vs. jython are explained on the wiki:  http://wiki.python.org/jython/NewSocketModule#SSL_Support"
+
+_exception_map = {
+
+# (<javaexception>, <circumstance>) : callable that raises the python equivalent exception, or None to stub out as unmapped
+
+(java.io.IOException, ALL)            : lambda x: error(errno.ECONNRESET, 'Software caused connection abort'),
+(java.io.InterruptedIOException, ALL) : lambda x: timeout(None, 'timed out'),
+
+(java.net.BindException, ALL)            : lambda x: error(errno.EADDRINUSE, 'Address already in use'),
+(java.net.ConnectException, ALL)         : lambda x: error(errno.ECONNREFUSED, 'Connection refused'),
+(java.net.NoRouteToHostException, ALL)   : lambda x: error(errno.EHOSTUNREACH, 'No route to host'),
+(java.net.PortUnreachableException, ALL) : None,
+(java.net.ProtocolException, ALL)        : None,
+(java.net.SocketException, ALL)          : java_net_socketexception_handler,
+(java.net.SocketTimeoutException, ALL)   : lambda x: timeout(None, 'timed out'),
+(java.net.UnknownHostException, ALL)     : lambda x: gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed'),
+
+(java.nio.channels.AlreadyConnectedException, ALL)       : lambda x: error(errno.EISCONN, 'Socket is already connected'),
+(java.nio.channels.AsynchronousCloseException, ALL)      : None,
+(java.nio.channels.CancelledKeyException, ALL)           : None,
+(java.nio.channels.ClosedByInterruptException, ALL)      : None,
+(java.nio.channels.ClosedChannelException, ALL)          : lambda x: error(errno.EPIPE, 'Socket closed'),
+(java.nio.channels.ClosedSelectorException, ALL)         : None,
+(java.nio.channels.ConnectionPendingException, ALL)      : None,
+(java.nio.channels.IllegalBlockingModeException, ALL)    : None,
+(java.nio.channels.IllegalSelectorException, ALL)        : None,
+(java.nio.channels.NoConnectionPendingException, ALL)    : None,
+(java.nio.channels.NonReadableChannelException, ALL)     : None,
+(java.nio.channels.NonWritableChannelException, ALL)     : None,
+(java.nio.channels.NotYetBoundException, ALL)            : None,
+(java.nio.channels.NotYetConnectedException, ALL)        : None,
+(java.nio.channels.UnresolvedAddressException, ALL)      : lambda x: gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed'),
+(java.nio.channels.UnsupportedAddressTypeException, ALL) : None,
+
+# These error codes are currently wrong: getting them correct is going to require
+# some investigation. Cpython 2.6 introduced extensive SSL support.
+
+(javax.net.ssl.SSLException, ALL)                        : lambda x: sslerror(-1, 'SSL exception'+_ssl_message),
+(javax.net.ssl.SSLHandshakeException, ALL)               : lambda x: sslerror(-1, 'SSL handshake exception'+_ssl_message),
+(javax.net.ssl.SSLKeyException, ALL)                     : lambda x: sslerror(-1, 'SSL key exception'+_ssl_message),
+(javax.net.ssl.SSLPeerUnverifiedException, ALL)          : lambda x: sslerror(-1, 'SSL peer unverified exception'+_ssl_message),
+(javax.net.ssl.SSLProtocolException, ALL)                : lambda x: sslerror(-1, 'SSL protocol exception'+_ssl_message),
+
+}
+
+def _map_exception(java_exception, circumstance=ALL):
+    mapped_exception = _exception_map.get((java_exception.__class__, circumstance))
+    if mapped_exception:
+        py_exception = mapped_exception(java_exception)
+    else:
+        py_exception = error(-1, 'Unmapped exception: %s' % java_exception)
+    setattr(py_exception, 'java_exception', java_exception)
+    return _add_exception_attrs(py_exception)
+
+from functools import wraps
+
+# Used to map java exceptions to the equivalent python exception
+# And to set the _last_error attribute on socket objects, to support SO_ERROR
+def raises_java_exception(method_or_function):
+    @wraps(method_or_function)
+    def handle_exception(*args, **kwargs):
+        is_socket = (len(args) > 0 and isinstance(args[0], _nonblocking_api_mixin))
+        try:
+            try:
+                return method_or_function(*args, **kwargs)
+            except java.lang.Exception, jlx:
+                raise _map_exception(jlx)
+        except error, e:
+            if is_socket:
+                setattr(args[0], '_last_error', e[0])
+            raise
+        else:
+            if is_socket:
+                setattr(args[0], '_last_error', 0)
+    return handle_exception
+
+_feature_support_map = {
+    'ipv6': True,
+    'idna': False,
+    'tipc': False,
+}
+
+def supports(feature, *args):
+    if len(args) == 1:
+        _feature_support_map[feature] = args[0]
+    return _feature_support_map.get(feature, False)
+
+MODE_BLOCKING    = 'block'
+MODE_NONBLOCKING = 'nonblock'
+MODE_TIMEOUT     = 'timeout'
+
+_permitted_modes = (MODE_BLOCKING, MODE_NONBLOCKING, MODE_TIMEOUT)
+
+SHUT_RD   = 0
+SHUT_WR   = 1
+SHUT_RDWR = 2
+
+AF_UNSPEC = 0
+AF_INET   = 2
+AF_INET6  = 23
+
+AI_PASSIVE     = 1
+AI_CANONNAME   = 2
+AI_NUMERICHOST = 4
+AI_V4MAPPED    = 8
+AI_ALL         = 16
+AI_ADDRCONFIG  = 32
+AI_NUMERICSERV = 1024
+
+EAI_NONAME     = -2
+EAI_SERVICE    = -8
+EAI_ADDRFAMILY = -9
+
+NI_NUMERICHOST              = 1
+NI_NUMERICSERV              = 2
+NI_NOFQDN                   = 4
+NI_NAMEREQD                 = 8
+NI_DGRAM                    = 16
+NI_MAXSERV                  = 32
+NI_IDN                      = 64
+NI_IDN_ALLOW_UNASSIGNED     = 128
+NI_IDN_USE_STD3_ASCII_RULES = 256
+NI_MAXHOST                  = 1025
+
+# For some reason, probably historical, SOCK_DGRAM and SOCK_STREAM are opposite values of what they are on cpython.
+# I.E. The following is the way they are on cpython
+# SOCK_STREAM    = 1
+# SOCK_DGRAM     = 2
+# At some point, we should probably switch them around, which *should* not affect anybody
+
+SOCK_DGRAM     = 1
+SOCK_STREAM    = 2
+SOCK_RAW       = 3 # not supported
+SOCK_RDM       = 4 # not supported
+SOCK_SEQPACKET = 5 # not supported
+
+SOL_SOCKET = 0xFFFF
+
+IPPROTO_AH       =  51 # not supported
+IPPROTO_DSTOPTS  =  60 # not supported
+IPPROTO_ESP      =  50 # not supported
+IPPROTO_FRAGMENT =  44 # not supported
+IPPROTO_GGP      =   3 # not supported
+IPPROTO_HOPOPTS  =   0 # not supported
+IPPROTO_ICMP     =   1 # not supported
+IPPROTO_ICMPV6   =  58 # not supported
+IPPROTO_IDP      =  22 # not supported
+IPPROTO_IGMP     =   2 # not supported
+IPPROTO_IP       =   0
+IPPROTO_IPV4     =   4 # not supported
+IPPROTO_IPV6     =  41 # not supported
+IPPROTO_MAX      = 256 # not supported
+IPPROTO_ND       =  77 # not supported
+IPPROTO_NONE     =  59 # not supported
+IPPROTO_PUP      =  12 # not supported
+IPPROTO_RAW      = 255 # not supported
+IPPROTO_ROUTING  =  43 # not supported
+IPPROTO_TCP      =   6
+IPPROTO_UDP      =  17
+
+SO_ACCEPTCONN  = 1
+SO_BROADCAST   = 2
+SO_ERROR       = 4
+SO_KEEPALIVE   = 8
+SO_LINGER      = 16
+SO_OOBINLINE   = 32
+SO_RCVBUF      = 64
+SO_REUSEADDR   = 128
+SO_SNDBUF      = 256
+SO_TIMEOUT     = 512
+SO_TYPE        = 1024
+
+TCP_NODELAY    = 2048
+
+INADDR_ANY = "0.0.0.0"
+INADDR_BROADCAST = "255.255.255.255"
+
+IN6ADDR_ANY_INIT = "::"
+
+# Options with negative constants are not supported
+# They are being added here so that code that refers to them
+# will not break with an AttributeError
+
+SO_DEBUG            = -1
+SO_DONTROUTE        = -1
+SO_EXCLUSIVEADDRUSE = -8
+SO_RCVLOWAT         = -16
+SO_RCVTIMEO         = -32
+SO_REUSEPORT        = -64
+SO_SNDLOWAT         = -128
+SO_SNDTIMEO         = -256
+SO_USELOOPBACK      = -512
+
+__all__ = [
+    # Families
+    'AF_UNSPEC', 'AF_INET', 'AF_INET6', 
+    # getaddrinfo and getnameinfo flags
+    'AI_PASSIVE', 'AI_CANONNAME', 'AI_NUMERICHOST', 'AI_V4MAPPED',
+    'AI_ALL', 'AI_ADDRCONFIG', 'AI_NUMERICSERV', 'EAI_NONAME', 
+    'EAI_SERVICE', 'EAI_ADDRFAMILY',
+    'NI_NUMERICHOST', 'NI_NUMERICSERV', 'NI_NOFQDN', 'NI_NAMEREQD',
+    'NI_DGRAM', 'NI_MAXSERV', 'NI_IDN', 'NI_IDN_ALLOW_UNASSIGNED',
+    'NI_IDN_USE_STD3_ASCII_RULES', 'NI_MAXHOST',
+    # socket types
+    'SOCK_DGRAM', 'SOCK_STREAM', 'SOCK_RAW', 'SOCK_RDM', 'SOCK_SEQPACKET',
+    # levels
+    'SOL_SOCKET',
+    # protocols
+    'IPPROTO_AH', 'IPPROTO_DSTOPTS', 'IPPROTO_ESP', 'IPPROTO_FRAGMENT',
+    'IPPROTO_GGP', 'IPPROTO_HOPOPTS', 'IPPROTO_ICMP', 'IPPROTO_ICMPV6',
+    'IPPROTO_IDP', 'IPPROTO_IGMP', 'IPPROTO_IP', 'IPPROTO_IPV4',
+    'IPPROTO_IPV6', 'IPPROTO_MAX', 'IPPROTO_ND', 'IPPROTO_NONE',
+    'IPPROTO_PUP', 'IPPROTO_RAW', 'IPPROTO_ROUTING', 'IPPROTO_TCP', 
+    'IPPROTO_UDP',
+    # Special hostnames
+    'INADDR_ANY', 'INADDR_BROADCAST', 'IN6ADDR_ANY_INIT',
+    # support socket options
+    'SO_BROADCAST', 'SO_KEEPALIVE', 'SO_LINGER', 'SO_OOBINLINE',
+    'SO_RCVBUF', 'SO_REUSEADDR', 'SO_SNDBUF', 'SO_TIMEOUT', 'TCP_NODELAY',
+    # unsupported socket options
+    'SO_ACCEPTCONN', 'SO_DEBUG', 'SO_DONTROUTE', 'SO_ERROR',
+    'SO_EXCLUSIVEADDRUSE', 'SO_RCVLOWAT', 'SO_RCVTIMEO', 'SO_REUSEPORT',
+    'SO_SNDLOWAT', 'SO_SNDTIMEO', 'SO_TYPE', 'SO_USELOOPBACK',
+    # functions
+    'getfqdn', 'gethostname', 'gethostbyname', 'gethostbyaddr',
+    'getservbyname', 'getservbyport', 'getprotobyname', 'getaddrinfo',
+    'getnameinfo', 'getdefaulttimeout', 'setdefaulttimeout', 'htons',
+    'htonl', 'ntohs', 'ntohl', 'inet_pton', 'inet_ntop', 'inet_aton',
+    'inet_ntoa', 'create_connection', 'socket', 'ssl',
+    # exceptions
+    'error', 'herror', 'gaierror', 'timeout', 'sslerror',
+    # classes
+    'SocketType', 
+    # Misc flags     
+    'has_ipv6', 'SHUT_RD', 'SHUT_WR', 'SHUT_RDWR',
+]
+
+def _constant_to_name(const_value, expected_name_starts):
+    sock_module = sys.modules['socket']
+    try:
+        for name in dir(sock_module):
+            if getattr(sock_module, name) is const_value:
+                for name_start in expected_name_starts:
+                    if name.startswith(name_start):
+                        return name
+        return "Unknown"
+    finally:
+        sock_module = None
+
+import _google_ipaddr_r234
+
+def _is_ip_address(addr, version=None):
+    try:
+        _google_ipaddr_r234.IPAddress(addr, version)
+        return True
+    except ValueError:
+        return False
+
+def is_ipv4_address(addr):
+    return _is_ip_address(addr, 4)
+
+def is_ipv6_address(addr):
+    return _is_ip_address(addr, 6)
+
+def is_ip_address(addr):
+    return _is_ip_address(addr)
+
+class _nio_impl:
+
+    timeout = None
+    mode = MODE_BLOCKING
+
+    def config(self, mode, timeout):
+        self.mode = mode
+        if self.mode == MODE_BLOCKING:
+            self.jchannel.configureBlocking(1)
+        if self.mode == MODE_NONBLOCKING:
+            self.jchannel.configureBlocking(0)
+        if self.mode == MODE_TIMEOUT:
+            self.jchannel.configureBlocking(1)
+            self._timeout_millis = int(timeout*1000)
+            self.jsocket.setSoTimeout(self._timeout_millis)
+
+    def getsockopt(self, level, option):
+        if (level, option) in self.options:
+            result = getattr(self.jsocket, "get%s" % self.options[ (level, option) ])()
+            if option == SO_LINGER:
+                if result == -1:
+                    enabled, linger_time = 0, 0
+                else:
+                    enabled, linger_time = 1, result
+                return struct.pack('ii', enabled, linger_time)
+            return result
+        else:
+            raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % \
+                (_constant_to_name(option, ['SO_', 'TCP_']), _constant_to_name(level, ['SOL_', 'IPPROTO_']), str(self.jsocket)))
+
+    def setsockopt(self, level, option, value):
+        if (level, option) in self.options:
+            if option == SO_LINGER:
+                values = struct.unpack('ii', value)
+                self.jsocket.setSoLinger(*values)
+            else:
+                getattr(self.jsocket, "set%s" % self.options[ (level, option) ])(value)
+        else:
+            raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % \
+                (_constant_to_name(option, ['SO_', 'TCP_']), _constant_to_name(level,  ['SOL_', 'IPPROTO_']), str(self.jsocket)))
+
+    def close(self):
+        self.jsocket.close()
+
+    def getchannel(self):
+        return self.jchannel
+
+    def fileno(self):
+        return self.socketio
+
+class _client_socket_impl(_nio_impl):
+
+    options = {
+        (SOL_SOCKET,  SO_KEEPALIVE):   'KeepAlive',
+        (SOL_SOCKET,  SO_LINGER):      'SoLinger',
+        (SOL_SOCKET,  SO_OOBINLINE):   'OOBInline',
+        (SOL_SOCKET,  SO_RCVBUF):      'ReceiveBufferSize',
+        (SOL_SOCKET,  SO_REUSEADDR):   'ReuseAddress',
+        (SOL_SOCKET,  SO_SNDBUF):      'SendBufferSize',
+        (SOL_SOCKET,  SO_TIMEOUT):     'SoTimeout',
+        (IPPROTO_TCP, TCP_NODELAY):    'TcpNoDelay',
+    }
+
+    def __init__(self, socket=None, pending_options=None):
+        if socket:
+            self.jchannel = socket.getChannel()
+        else:
+            self.jchannel = java.nio.channels.SocketChannel.open()
+        self.jsocket = self.jchannel.socket()
+        self.socketio = org.python.core.io.SocketIO(self.jchannel, 'rw')
+        if pending_options:
+            for level, optname in pending_options.keys():
+                self.setsockopt(level, optname, pending_options[ (level, optname) ])
+
+    def bind(self, jsockaddr, reuse_addr):
+        self.jsocket.setReuseAddress(reuse_addr)
+        self.jsocket.bind(jsockaddr)
+
+    def connect(self, jsockaddr):
+        if self.mode == MODE_TIMEOUT:
+            self.jsocket.connect (jsockaddr, self._timeout_millis)
+        else:
+            self.jchannel.connect(jsockaddr)
+
+    def finish_connect(self):
+        return self.jchannel.finishConnect()
+
+    def _do_read_net(self, buf):
+        # Need two separate implementations because the java.nio APIs do not support timeouts
+        return self.jsocket.getInputStream().read(buf)
+
+    def _do_read_nio(self, buf):
+        bytebuf = java.nio.ByteBuffer.wrap(buf)
+        count = self.jchannel.read(bytebuf)
+        return count
+
+    def _do_write_net(self, buf):
+        self.jsocket.getOutputStream().write(buf)
+        return len(buf)
+
+    def _do_write_nio(self, buf):
+        bytebuf = java.nio.ByteBuffer.wrap(buf)
+        count = self.jchannel.write(bytebuf)
+        return count
+
+    def read(self, buf):
+        if self.mode == MODE_TIMEOUT:
+            return self._do_read_net(buf)
+        else:
+            return self._do_read_nio(buf)
+
+    def write(self, buf):
+        if self.mode == MODE_TIMEOUT:
+            return self._do_write_net(buf)
+        else:
+            return self._do_write_nio(buf)
+
+    def shutdown(self, how):
+        if how in (SHUT_RD, SHUT_RDWR):
+            self.jsocket.shutdownInput()
+        if how in (SHUT_WR, SHUT_RDWR):
+            self.jsocket.shutdownOutput()
+
+    def getsockname(self):
+        return (self.jsocket.getLocalAddress().getHostAddress(), self.jsocket.getLocalPort())
+
+    def getpeername(self):
+        return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getPort() )
+
+class _server_socket_impl(_nio_impl):
+
+    options = {
+        (SOL_SOCKET, SO_RCVBUF):      'ReceiveBufferSize',
+        (SOL_SOCKET, SO_REUSEADDR):   'ReuseAddress',
+        (SOL_SOCKET, SO_TIMEOUT):     'SoTimeout',
+    }
+
+    def __init__(self, jsockaddr, backlog, reuse_addr):
+        self.pending_client_options = {}
+        self.jchannel = java.nio.channels.ServerSocketChannel.open()
+        self.jsocket = self.jchannel.socket()
+        self.jsocket.setReuseAddress(reuse_addr)
+        self.jsocket.bind(jsockaddr, backlog)
+        self.socketio = org.python.core.io.ServerSocketIO(self.jchannel, 'rw')
+
+    def accept(self):
+        if self.mode in (MODE_BLOCKING, MODE_NONBLOCKING):
+            new_cli_chan = self.jchannel.accept()
+            if new_cli_chan is not None:
+                return _client_socket_impl(new_cli_chan.socket(), self.pending_client_options)
+            else:
+                return None
+        else:
+            # In timeout mode now
+            new_cli_sock = self.jsocket.accept()
+            return _client_socket_impl(new_cli_sock, self.pending_client_options)
+
+    def shutdown(self, how):
+        # This is no-op on java, for server sockets.
+        # What the user wants to achieve is achieved by calling close() on
+        # java/jython. But we can't call that here because that would then
+        # later cause the user explicit close() call to fail
+        pass
+
+    def getsockopt(self, level, option):
+        if self.options.has_key( (level, option) ):
+            return _nio_impl.getsockopt(self, level, option)
+        elif _client_socket_impl.options.has_key( (level, option) ):
+            return self.pending_client_options.get( (level, option), None)
+        else:
+            raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % \
+                (_constant_to_name(option, ['SO_', 'TCP_']), _constant_to_name(level,  ['SOL_', 'IPPROTO_']), str(self.jsocket)))
+
+    def setsockopt(self, level, option, value):
+        if self.options.has_key( (level, option) ):
+            _nio_impl.setsockopt(self, level, option, value)
+        elif _client_socket_impl.options.has_key( (level, option) ):
+            self.pending_client_options[ (level, option) ] = value
+        else:
+            raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % \
+                (_constant_to_name(option, ['SO_', 'TCP_']), _constant_to_name(level,  ['SOL_', 'IPPROTO_']), str(self.jsocket)))
+
+    def getsockname(self):
+        return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getLocalPort())
+
+    def getpeername(self):
+        # Not a meaningful operation for server sockets.
+        raise error(errno.ENOTCONN, "Socket is not connected")
+
+class _datagram_socket_impl(_nio_impl):
+
+    options = {
+        (SOL_SOCKET, SO_BROADCAST):   'Broadcast',
+        (SOL_SOCKET, SO_RCVBUF):      'ReceiveBufferSize',
+        (SOL_SOCKET, SO_REUSEADDR):   'ReuseAddress',
+        (SOL_SOCKET, SO_SNDBUF):      'SendBufferSize',
+        (SOL_SOCKET, SO_TIMEOUT):     'SoTimeout',
+    }
+
+    def __init__(self, jsockaddr=None, reuse_addr=0):
+        self.jchannel = java.nio.channels.DatagramChannel.open()
+        self.jsocket = self.jchannel.socket()
+        if jsockaddr is not None:
+            self.jsocket.setReuseAddress(reuse_addr)
+            self.jsocket.bind(jsockaddr)
+        self.socketio = org.python.core.io.DatagramSocketIO(self.jchannel, 'rw')
+
+    def connect(self, jsockaddr):
+        self.jchannel.connect(jsockaddr)
+
+    def disconnect(self):
+        """
+            Disconnect the datagram socket.
+            cpython appears not to have this operation
+        """
+        self.jchannel.disconnect()
+
+    def shutdown(self, how):
+        # This is no-op on java, for datagram sockets.
+        # What the user wants to achieve is achieved by calling close() on
+        # java/jython. But we can't call that here because that would then
+        # later cause the user explicit close() call to fail
+        pass
+
+    def _do_send_net(self, byte_array, socket_address, flags):
+        # Need two separate implementations because the java.nio APIs do not support timeouts
+        num_bytes = len(byte_array)
+        if self.jsocket.isConnected() and socket_address is None:
+            packet = java.net.DatagramPacket(byte_array, num_bytes)
+        else:
+            packet = java.net.DatagramPacket(byte_array, num_bytes, socket_address)
+        self.jsocket.send(packet)
+        return num_bytes
+
+    def _do_send_nio(self, byte_array, socket_address, flags):
+        byte_buf = java.nio.ByteBuffer.wrap(byte_array)
+        if self.jchannel.isConnected() and socket_address is None:
+            bytes_sent = self.jchannel.write(byte_buf)
+        else:
+            bytes_sent = self.jchannel.send(byte_buf, socket_address)
+        return bytes_sent
+
+    def sendto(self, byte_array, jsockaddr, flags):
+        if self.mode == MODE_TIMEOUT:
+            return self._do_send_net(byte_array, jsockaddr, flags)
+        else:
+            return self._do_send_nio(byte_array, jsockaddr, flags)
+
+    def send(self, byte_array, flags):
+        if self.mode == MODE_TIMEOUT:
+            return self._do_send_net(byte_array, None, flags)
+        else:
+            return self._do_send_nio(byte_array, None, flags)
+
+    def _do_receive_net(self, return_source_address, num_bytes, flags):
+        byte_array = jarray.zeros(num_bytes, 'b')
+        packet = java.net.DatagramPacket(byte_array, num_bytes)
+        self.jsocket.receive(packet)
+        bytes_rcvd = packet.getLength()
+        if bytes_rcvd < num_bytes:
+            byte_array = byte_array[:bytes_rcvd]
+        return_data = byte_array.tostring()
+        if return_source_address:
+            host = None
+            if packet.getAddress():
+                host = packet.getAddress().getHostAddress()
+            port = packet.getPort()
+            return return_data, (host, port)
+        else:
+            return return_data
+
+    def _do_receive_nio(self, return_source_address, num_bytes, flags):
+        byte_array = jarray.zeros(num_bytes, 'b')
+        byte_buf = java.nio.ByteBuffer.wrap(byte_array)
+        source_address = self.jchannel.receive(byte_buf)
+        if source_address is None and not self.jchannel.isBlocking():
+            raise would_block_error()
+        byte_buf.flip() ; bytes_read = byte_buf.remaining()
+        if bytes_read < num_bytes:
+            byte_array = byte_array[:bytes_read]
+        return_data = byte_array.tostring()
+        if return_source_address:
+            return return_data, (source_address.getAddress().getHostAddress(), source_address.getPort())
+        else:
+            return return_data
+
+    def recvfrom(self, num_bytes, flags):
+        if self.mode == MODE_TIMEOUT:
+            return self._do_receive_net(1, num_bytes, flags)
+        else:
+            return self._do_receive_nio(1, num_bytes, flags)
+
+    def recv(self, num_bytes, flags):
+        if self.mode == MODE_TIMEOUT:
+            return self._do_receive_net(0, num_bytes, flags)
+        else:
+            return self._do_receive_nio(0, num_bytes, flags)
+
+    def getsockname(self):
+        return (self.jsocket.getLocalAddress().getHostAddress(), self.jsocket.getLocalPort())
+
+    def getpeername(self):
+        peer_address = self.jsocket.getInetAddress()
+        if peer_address is None:
+            raise error(errno.ENOTCONN, "Socket is not connected")
+        return (peer_address.getHostAddress(), self.jsocket.getPort() )
+
+has_ipv6 = True # IPV6 FTW!
+
+# Name and address functions
+
+def _gethostbyaddr(name):
+    # This is as close as I can get; at least the types are correct...
+    addresses = java.net.InetAddress.getAllByName(gethostbyname(name))
+    names = []
+    addrs = []
+    for addr in addresses:
+        names.append(asPyString(addr.getHostName()))
+        addrs.append(asPyString(addr.getHostAddress()))
+    return (names, addrs)
+
+@raises_java_exception
+def getfqdn(name=None):
+    """
+    Return a fully qualified domain name for name. If name is omitted or empty
+    it is interpreted as the local host.  To find the fully qualified name,
+    the hostname returned by gethostbyaddr() is checked, then aliases for the
+    host, if available. The first name which includes a period is selected.
+    In case no fully qualified domain name is available, the hostname is retur
+    New in version 2.0.
+    """
+    if not name:
+        name = gethostname()
+    names, addrs = _gethostbyaddr(name)
+    for a in names:
+        if a.find(".") >= 0:
+            return a
+    return name
+
+@raises_java_exception
+def gethostname():
+    return asPyString(java.net.InetAddress.getLocalHost().getHostName())
+
+@raises_java_exception
+def gethostbyname(name):
+    return asPyString(java.net.InetAddress.getByName(name).getHostAddress())
+
+#
+# Skeleton implementation of gethostbyname_ex
+# Needed because urllib2 refers to it
+#
+
+@raises_java_exception
+def gethostbyname_ex(name):
+    return (name, [], gethostbyname(name))
+
+@raises_java_exception
+def gethostbyaddr(name):
+    names, addrs = _gethostbyaddr(name)
+    return (names[0], names, addrs)
+
+def getservbyname(service_name, protocol_name=None):
+    try:
+        from jnr.netdb import Service
+    except ImportError:
+        return None
+    service = Service.getServiceByName(service_name, protocol_name)
+    if service is None:
+        raise error('service/proto not found')
+    return service.getPort()
+
+def getservbyport(port, protocol_name=None):
+    try:
+        from jnr.netdb import Service
+    except ImportError:
+        return None
+    service = Service.getServiceByPort(port, protocol_name)
+    if service is None:
+        raise error('port/proto not found')
+    return service.getName()
+
+def getprotobyname(protocol_name=None):
+    try:
+        from jnr.netdb import Protocol
+    except ImportError:
+        return None
+    proto = Protocol.getProtocolByName(protocol_name)
+    if proto is None:
+        raise error('protocol not found')
+    return proto.getProto()
+
+def _realsocket(family = AF_INET, sock_type = SOCK_STREAM, protocol=0):
+    assert family in (AF_INET, AF_INET6), "Only AF_INET and AF_INET6 sockets are currently supported on jython"
+    assert sock_type in (SOCK_DGRAM, SOCK_STREAM), "Only SOCK_STREAM and SOCK_DGRAM sockets are currently supported on jython"
+    if sock_type == SOCK_STREAM:
+        if protocol != 0:
+            assert protocol == IPPROTO_TCP, "Only IPPROTO_TCP supported on SOCK_STREAM sockets"
+        else:
+            protocol = IPPROTO_TCP
+        result = _tcpsocket()
+    else:
+        if protocol != 0:
+            assert protocol == IPPROTO_UDP, "Only IPPROTO_UDP supported on SOCK_DGRAM sockets"
+        else:
+            protocol = IPPROTO_UDP
+        result = _udpsocket()
+    setattr(result, "family", family)
+    setattr(result, "type",   sock_type)
+    setattr(result, "proto",  protocol)
+    return result
+
+#
+# Attempt to provide IDNA (RFC 3490) support.
+#
+# Try java.net.IDN, built into java 6
+#
+
+idna_libraries = [
+    ('java.net.IDN', 'toASCII', 'toUnicode', 
+        'ALLOW_UNASSIGNED', 'USE_STD3_ASCII_RULES', 
+        java.lang.IllegalArgumentException)
+]
+  
+for idna_lib, efn, dfn, au, usar, exc in idna_libraries:
+    try:
+        m = __import__(idna_lib, globals(), locals(), [efn, dfn, au, usar])
+        encode_fn = getattr(m, efn)
+        def _encode_idna(name):
+            try:
+                return encode_fn(name)
+            except exc:
+                raise UnicodeEncodeError(name)
+        decode_fn = getattr(m, dfn)
+        def _decode_idna(name, flags=0):
+            try:
+                jflags = 0
+                if flags & NI_IDN_ALLOW_UNASSIGNED:
+                    jflags |= au
+                if flags & NI_IDN_USE_STD3_ASCII_RULES:
+                    jflags |= usar
+                return decode_fn(name, jflags)
+            except Exception, x:
+                raise UnicodeDecodeError(name)
+        supports('idna', True)
+        break
+    except (AttributeError, ImportError), e:
+        pass
+else:
+    _encode_idna = lambda x: x.encode("ascii")
+    _decode_idna = lambda x, y=0: x.decode("ascii")
+
+#
+# Define data structures to support IPV4 and IPV6.
+#
+
+class _ip_address_t: pass
+
+class _ipv4_address_t(_ip_address_t):
+
+    def __init__(self, sockaddr, port, jaddress):
+        self.sockaddr = sockaddr
+        self.port     = port
+        self.jaddress = jaddress
+
+    def __getitem__(self, index):
+        if   0 == index:
+            return self.sockaddr
+        elif 1 == index:
+            return self.port
+        else:
+            raise IndexError()
+
+    def __len__(self):
+        return 2
+
+    def __str__(self):
+        return "('%s', %d)" % (self.sockaddr, self.port)
+
+    __repr__ = __str__
+
+class _ipv6_address_t(_ip_address_t):
+
+    def __init__(self, sockaddr, port, jaddress):
+        self.sockaddr = sockaddr
+        self.port     = port
+        self.jaddress = jaddress
+
+    def __getitem__(self, index):
+        if   0 == index:
+            return self.sockaddr
+        elif 1 == index:
+            return self.port
+        elif 2 == index:
+            return 0
+        elif 3 == index:
+            return self.jaddress.scopeId
+        else:
+            raise IndexError()
+
+    def __len__(self):
+        return 4
+
+    def __str__(self):
+        return "('%s', %d, 0, %d)" % (self.sockaddr, self.port, self.jaddress.scopeId)
+
+    __repr__ = __str__
+
+def _get_jsockaddr(address_object, family, sock_type, proto, flags):
+    # Is this an object that was returned from getaddrinfo? If so, it already contains an InetAddress
+    if isinstance(address_object, _ip_address_t):
+        return java.net.InetSocketAddress(address_object.jaddress, address_object[1]) 
+    # The user passed an address tuple, not an object returned from getaddrinfo
+    # So we must call getaddrinfo, after some translations and checking
+    if address_object is None:
+        address_object = ("", 0)
+    error_message = "Address must be a 2-tuple (ipv4: (host, port)) or a 4-tuple (ipv6: (host, port, flow, scope))"
+    if not isinstance(address_object, tuple) or \
+            ((family == AF_INET and len(address_object) != 2) or (family == AF_INET6 and len(address_object) not in [2,4] )) or \
+            not isinstance(address_object[0], (basestring, types.NoneType)) or \
+            not isinstance(address_object[1], (int, long)):
+        raise TypeError(error_message)
+    if len(address_object) == 4 and not isinstance(address_object[3], (int, long)):
+        raise TypeError(error_message)
+    hostname = address_object[0]
+    if hostname is not None:
+        hostname = hostname.strip()
+    port = address_object[1]
+    if family == AF_INET and sock_type == SOCK_DGRAM and hostname == "<broadcast>":
+        hostname = INADDR_BROADCAST
+    if hostname in ["", None]:
+        if flags & AI_PASSIVE:
+            hostname = {AF_INET: INADDR_ANY, AF_INET6: IN6ADDR_ANY_INIT}[family]
+        else:
+            hostname = "localhost"
+    if isinstance(hostname, unicode):
+        hostname = _encode_idna(hostname)
+    addresses = getaddrinfo(hostname, port, family, sock_type, proto, flags)
+    if len(addresses) == 0:
+        raise gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed')
+    return java.net.InetSocketAddress(addresses[0][4].jaddress, port)
+
+# Workaround for this (predominantly windows) issue
+# http://wiki.python.org/jython/NewSocketModule#IPV6_address_support
+
+_ipv4_addresses_only = False
+
+def _use_ipv4_addresses_only(value):
+    global _ipv4_addresses_only
+    _ipv4_addresses_only = value
+
+def _getaddrinfo_get_host(host, family, flags):
+    if not isinstance(host, basestring) and host is not None:
+        raise TypeError("getaddrinfo() argument 1 must be string or None")
+    if flags & AI_NUMERICHOST:
+        if not is_ip_address(host):
+            raise gaierror(EAI_NONAME, "Name or service not known")
+        if family == AF_INET and not is_ipv4_address(host):
+            raise gaierror(EAI_ADDRFAMILY, "Address family for hostname not supported")
+        if family == AF_INET6 and not is_ipv6_address(host):
+            raise gaierror(EAI_ADDRFAMILY, "Address family for hostname not supported")
+    if isinstance(host, unicode):
+        host = _encode_idna(host)
+    return host
+
+def _getaddrinfo_get_port(port, flags):
+    if isinstance(port, basestring):
+        try:
+            int_port = int(port)
+        except ValueError:
+            if flags & AI_NUMERICSERV:
+                raise gaierror(EAI_NONAME, "Name or service not known")
+            # Lookup the service by name
+            try:
+                int_port = getservbyname(port)
+            except error:
+                raise gaierror(EAI_SERVICE, "Servname not supported for ai_socktype")
+    elif port is None:
+        int_port = 0
+    elif not isinstance(port, (int, long)):
+        raise error("Int or String expected")
+    else:
+        int_port = int(port)
+    return int_port % 65536
+
+@raises_java_exception
+def getaddrinfo(host, port, family=AF_UNSPEC, socktype=0, proto=0, flags=0):
+    if _ipv4_addresses_only:
+        family = AF_INET
+    if not family in [AF_INET, AF_INET6, AF_UNSPEC]:
+        raise gaierror(errno.EIO, 'ai_family not supported')
+    host = _getaddrinfo_get_host(host, family, flags)
+    port = _getaddrinfo_get_port(port, flags)
+    if socktype not in [0, SOCK_DGRAM, SOCK_STREAM]:
+        raise error(errno.ESOCKTNOSUPPORT, "Socket type %s is not supported" % _constant_to_name(socktype, ['SOCK_']))
+    filter_fns = []
+    filter_fns.append({
+        AF_INET:   lambda x: isinstance(x, java.net.Inet4Address),
+        AF_INET6:  lambda x: isinstance(x, java.net.Inet6Address),
+        AF_UNSPEC: lambda x: isinstance(x, java.net.InetAddress),
+    }[family])
+    if host in [None, ""]:
+        if flags & AI_PASSIVE:
+             hosts = {AF_INET: [INADDR_ANY], AF_INET6: [IN6ADDR_ANY_INIT], AF_UNSPEC: [INADDR_ANY, IN6ADDR_ANY_INIT]}[family]
+        else:
+             hosts = ["localhost"]
+    else:
+        hosts = [host]
+    results = []
+    for h in hosts:
+        for a in java.net.InetAddress.getAllByName(h):
+            if len([f for f in filter_fns if f(a)]):
+                family = {java.net.Inet4Address: AF_INET, java.net.Inet6Address: AF_INET6}[a.getClass()]
+                if flags & AI_CANONNAME:
+                    canonname = asPyString(a.getCanonicalHostName())
+                else:
+                    canonname = ""
+                sockaddr = asPyString(a.getHostAddress())
+                # TODO: Include flowinfo and scopeid in a 4-tuple for IPv6 addresses
+                sock_tuple = {AF_INET : _ipv4_address_t, AF_INET6 : _ipv6_address_t}[family](sockaddr, port, a)
+                if socktype == 0:
+                    socktypes = [SOCK_DGRAM, SOCK_STREAM]
+                else:
+                    socktypes = [socktype]
+                for result_socktype in socktypes:
+                    result_proto = {SOCK_DGRAM: IPPROTO_UDP, SOCK_STREAM: IPPROTO_TCP}[result_socktype]
+                    if proto in [0, result_proto]:
+                        # The returned socket will only support the result_proto
+                        # If this does not match the requested proto, don't return it
+                        results.append((family, result_socktype, result_proto, canonname, sock_tuple))
+    return results
+
+def _getnameinfo_get_host(address, flags):
+    if not isinstance(address, basestring):
+        raise TypeError("getnameinfo() address 1 must be string, not None")
+    if isinstance(address, unicode):
+        address = _encode_idna(address)
+    jia = java.net.InetAddress.getByName(address)
+    result = jia.getCanonicalHostName()
+    if flags & NI_NAMEREQD:
+        if is_ip_address(result):
+            raise gaierror(EAI_NONAME, "Name or service not known")
+    elif flags & NI_NUMERICHOST:
+        result = jia.getHostAddress()
+    # Ignoring NI_NOFQDN for now
+    if flags & NI_IDN:
+        result = _decode_idna(result, flags)
+    return result
+
+def _getnameinfo_get_port(port, flags):
+    if not isinstance(port, (int, long)):
+        raise TypeError("getnameinfo() port number must be an integer")
+    if flags & NI_NUMERICSERV:
+        return port
+    proto = None
+    if flags & NI_DGRAM:
+        proto = "udp"
+    return getservbyport(port, proto)
+
+@raises_java_exception
+def getnameinfo(sock_addr, flags):
+    if not isinstance(sock_addr, tuple) or len(sock_addr) < 2:
+        raise TypeError("getnameinfo() argument 1 must be a tuple")
+    host = _getnameinfo_get_host(sock_addr[0], flags)
+    port = _getnameinfo_get_port(sock_addr[1], flags)
+    return (host, port)
+
+def getdefaulttimeout():
+    return _defaulttimeout
+
+def _calctimeoutvalue(value):
+    if value is None:
+        return None
+    try:
+        floatvalue = float(value)
+    except:
+        raise TypeError('Socket timeout value must be a number or None')
+    if floatvalue < 0.0:
+        raise ValueError("Socket timeout value cannot be negative")
+    if floatvalue < 0.000001:
+        return 0.0
+    return floatvalue
+
+def setdefaulttimeout(timeout):
+    global _defaulttimeout
+    try:
+        _defaulttimeout = _calctimeoutvalue(timeout)
+    finally:
+        _nonblocking_api_mixin.timeout = _defaulttimeout
+
+def htons(x): return x
+def htonl(x): return x
+def ntohs(x): return x
+def ntohl(x): return x
+
+@raises_java_exception
+def inet_pton(family, ip_string):
+    if family == AF_INET:
+        if not is_ipv4_address(ip_string):
+            raise error("illegal IP address string passed to inet_pton")
+    elif family == AF_INET6:
+        if not is_ipv6_address(ip_string):
+            raise error("illegal IP address string passed to inet_pton")
+    else:
+        raise error(errno.EAFNOSUPPORT, "Address family not supported by protocol")
+    ia = java.net.InetAddress.getByName(ip_string)
+    bytes = []
+    for byte in ia.getAddress():
+        if byte < 0:
+            bytes.append(byte+256)
+        else:
+            bytes.append(byte)
+    return "".join([chr(byte) for byte in bytes])
+
+@raises_java_exception
+def inet_ntop(family, packed_ip):
+    jByteArray = jarray.array(packed_ip, 'b')
+    if family == AF_INET:
+        if len(jByteArray) != 4:
+            raise ValueError("invalid length of packed IP address string")
+    elif family == AF_INET6:
+        if len(jByteArray) != 16:
+            raise ValueError("invalid length of packed IP address string")
+    else:
+        raise ValueError("unknown address family %s" % family)
+    ia = java.net.InetAddress.getByAddress(jByteArray)
+    return ia.getHostAddress()
+
+def inet_aton(ip_string):
+    return inet_pton(AF_INET, ip_string)
+
+def inet_ntoa(packed_ip):
+    return inet_ntop(AF_INET, packed_ip)
+
+class _nonblocking_api_mixin:
+
+    mode            = MODE_BLOCKING
+    reference_count = 0
+    close_lock      = threading.Lock()
+
+    def __init__(self):
+        self.timeout = _defaulttimeout
+        if self.timeout is not None:
+            self.mode = MODE_TIMEOUT
+        self.pending_options = {
+            (SOL_SOCKET, SO_REUSEADDR):  0,
+        }
+
+    def gettimeout(self):
+        return self.timeout
+
+    def settimeout(self, timeout):
+        self.timeout = _calctimeoutvalue(timeout)
+        if self.timeout is None:
+            self.mode = MODE_BLOCKING
+        elif self.timeout < 0.000001:
+            self.mode = MODE_NONBLOCKING
+        else:
+            self.mode = MODE_TIMEOUT
+        self._config()
+
+    def setblocking(self, flag):
+        if flag:
+            self.mode = MODE_BLOCKING
+            self.timeout = None
+        else:
+            self.mode = MODE_NONBLOCKING
+            self.timeout = 0.0
+        self._config()
+
+    def getblocking(self):
+        return self.mode == MODE_BLOCKING
+
+    @raises_java_exception
+    def setsockopt(self, level, optname, value):
+        if self.sock_impl:
+            self.sock_impl.setsockopt(level, optname, value)
+        else:
+            self.pending_options[ (level, optname) ] = value
+
+    @raises_java_exception
+    def getsockopt(self, level, optname):
+        # Handle "pseudo" options first
+        if level == SOL_SOCKET and optname == SO_TYPE:
+            return getattr(self, "type")
+        if level == SOL_SOCKET and optname == SO_ERROR:
+            return_value = self._last_error
+            self._last_error = 0
+            return return_value
+        # Now handle "real" options
+        if self.sock_impl:
+            return self.sock_impl.getsockopt(level, optname)
+        else:
+            return self.pending_options.get( (level, optname), None)
+
+    @raises_java_exception
+    def shutdown(self, how):
+        assert how in (SHUT_RD, SHUT_WR, SHUT_RDWR)
+        if not self.sock_impl:
+            raise error(errno.ENOTCONN, "Transport endpoint is not connected")
+        self.sock_impl.shutdown(how)
+
+    @raises_java_exception
+    def close(self):
+        if self.sock_impl:
+            self.sock_impl.close()
+
+    @raises_java_exception
+    def getsockname(self):
+        if self.sock_impl is None:
+            # If the user has already bound an address, return that
+            if self.local_addr:
+                return self.local_addr
+            # The user has not bound, connected or listened
+            # This is what cpython raises in this scenario
+            raise error(errno.EINVAL, "Invalid argument")
+        return self.sock_impl.getsockname()
+
+    @raises_java_exception
+    def getpeername(self):
+        if self.sock_impl is None:
+            raise error(errno.ENOTCONN, "Socket is not connected")
+        return self.sock_impl.getpeername()
+
+    def _config(self):
+        assert self.mode in _permitted_modes
+        if self.sock_impl:
+            self.sock_impl.config(self.mode, self.timeout)
+            for level, optname in self.pending_options.keys():
+                if optname != SO_REUSEADDR:
+                    self.sock_impl.setsockopt(level, optname, self.pending_options[ (level, optname) ])
+
+    def getchannel(self):
+        if not self.sock_impl:
+            return None
+        return self.sock_impl.getchannel()
+
+    def fileno(self):
+        if not self.sock_impl:
+            return None
+        return self.sock_impl.fileno()
+
+    def _get_jsocket(self):
+        return self.sock_impl.jsocket
+
+class _tcpsocket(_nonblocking_api_mixin):
+
+    sock_impl   = None
+    istream     = None
+    ostream     = None
+    local_addr  = None
+    server      = 0
+    _last_error = 0
+
+    def __init__(self):
+        _nonblocking_api_mixin.__init__(self)
+
+    def getsockopt(self, level, optname):
+        if level == SOL_SOCKET and optname == SO_ACCEPTCONN:
+            return self.server
+        return _nonblocking_api_mixin.getsockopt(self, level, optname)
+
+    @raises_java_exception
+    def bind(self, addr):
+        assert not self.sock_impl
+        assert not self.local_addr
+        # Do the address format check
+        _get_jsockaddr(addr, self.family, self.type, self.proto, AI_PASSIVE)
+        self.local_addr = addr
+
+    @raises_java_exception
+    def listen(self, backlog):
+        "This signifies a server socket"
+        assert not self.sock_impl
+        self.server = 1
+        self.sock_impl = _server_socket_impl(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, AI_PASSIVE), 
+                              backlog, self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
+        self._config()
+
+    @raises_java_exception
+    def accept(self):
+        "This signifies a server socket"
+        if not self.sock_impl:
+            self.listen()
+        assert self.server
+        new_sock = self.sock_impl.accept()
+        if not new_sock:
+            raise would_block_error()
+        cliconn = _tcpsocket()
+        cliconn.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ] = new_sock.jsocket.getReuseAddress()
+        cliconn.sock_impl = new_sock
+        cliconn._setup()
+        return cliconn, new_sock.getpeername()
+
+    def _do_connect(self, addr):
+        assert not self.sock_impl
+        self.sock_impl = _client_socket_impl()
+        if self.local_addr: # Has the socket been bound to a local address?
+            self.sock_impl.bind(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, 0), 
+                                 self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
+        self._config() # Configure timeouts, etc, now that the socket exists
+        self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0))
+
+    @raises_java_exception
+    def connect(self, addr):
+        "This signifies a client socket"
+        self._do_connect(addr)
+        self._setup()
+
+    @raises_java_exception
+    def connect_ex(self, addr):
+        "This signifies a client socket"
+        if not self.sock_impl:
+            self._do_connect(addr)
+        if self.sock_impl.finish_connect():
+            self._setup()
+            if self.mode == MODE_NONBLOCKING:
+                return errno.EISCONN
+            return 0
+        return errno.EINPROGRESS
+
+    def _setup(self):
+        if self.mode != MODE_NONBLOCKING:
+            self.istream = self.sock_impl.jsocket.getInputStream()
+            self.ostream = self.sock_impl.jsocket.getOutputStream()
+
+    @raises_java_exception
+    def recv(self, n):
+        if not self.sock_impl: raise error(errno.ENOTCONN, 'Socket is not connected')
+        if self.sock_impl.jchannel.isConnectionPending():
+            self.sock_impl.jchannel.finishConnect()
+        data = jarray.zeros(n, 'b')
+        m = self.sock_impl.read(data)
+        if m == -1:#indicates EOF has been reached, so we just return the empty string
+            return ""
+        elif m <= 0:
+            if self.mode == MODE_NONBLOCKING:
+                raise would_block_error()
+            return ""
+        if m < n:
+            data = data[:m]
+        return data.tostring()
+
+    @raises_java_exception
+    def recvfrom(self, n):
+        return self.recv(n), self.getpeername()
+
+    @raises_java_exception
+    def send(self, s):
+        if not self.sock_impl: raise error(errno.ENOTCONN, 'Socket is not connected')
+        if self.sock_impl.jchannel.isConnectionPending():
+            self.sock_impl.jchannel.finishConnect()
+        numwritten = self.sock_impl.write(s)
+        if numwritten == 0 and self.mode == MODE_NONBLOCKING:
+            raise would_block_error()
+        return numwritten
+
+    sendall = send
+
+    @raises_java_exception
+    def close(self):
+        if self.istream:
+            self.istream.close()
+        if self.ostream:
+            self.ostream.close()
+        if self.sock_impl:
+            self.sock_impl.close()
+
+
+class _udpsocket(_nonblocking_api_mixin):
+
+    sock_impl   = None
+    connected   = False
+    local_addr  = None
+    _last_error = 0
+
+    def __init__(self):
+        _nonblocking_api_mixin.__init__(self)
+
+    @raises_java_exception
+    def bind(self, addr):
+        assert not self.sock_impl
+        assert not self.local_addr
+        # Do the address format check
+        _get_jsockaddr(addr, self.family, self.type, self.proto, AI_PASSIVE)
+        self.local_addr = addr
+        self.sock_impl = _datagram_socket_impl(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, AI_PASSIVE), 
+                                                self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
+        self._config()
+
+    def _do_connect(self, addr):
+        assert not self.connected, "Datagram Socket is already connected"
+        if not self.sock_impl:
+            self.sock_impl = _datagram_socket_impl()
+            self._config()
+        self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0))
+        self.connected = True
+
+    @raises_java_exception
+    def connect(self, addr):
+        self._do_connect(addr)
+
+    @raises_java_exception
+    def connect_ex(self, addr):
+        if not self.sock_impl:
+            self._do_connect(addr)
+        return 0
+
+    @raises_java_exception
+    def sendto(self, data, p1, p2=None):
+        if not p2:
+            flags, addr = 0, p1
+        else:
+            flags, addr = 0, p2
+        if not self.sock_impl:
+            self.sock_impl = _datagram_socket_impl()
+            self._config()
+        byte_array = java.lang.String(data).getBytes('iso-8859-1')
+        result = self.sock_impl.sendto(byte_array, _get_jsockaddr(addr, self.family, self.type, self.proto, 0), flags)
+        return result
+
+    @raises_java_exception
+    def send(self, data, flags=None):
+        if not self.connected: raise error(errno.ENOTCONN, "Socket is not connected")
+        byte_array = java.lang.String(data).getBytes('iso-8859-1')
+        return self.sock_impl.send(byte_array, flags)
+
+    @raises_java_exception
+    def recvfrom(self, num_bytes, flags=None):
+        """
+        There is some disagreement as to what the behaviour should be if
+        a recvfrom operation is requested on an unbound socket.
+        See the following links for more information
+        http://bugs.jython.org/issue1005
+        http://bugs.sun.com/view_bug.do?bug_id=6621689
+        """
+        # This is the old 2.1 behaviour
+        #assert self.sock_impl
+        # This is amak's preferred interpretation
+        #raise error(errno.ENOTCONN, "Recvfrom on unbound udp socket meaningless operation")
+        # And this is the option for cpython compatibility
+        if not self.sock_impl:
+            self.sock_impl = _datagram_socket_impl()
+            self._config()
+        return self.sock_impl.recvfrom(num_bytes, flags)
+
+    @raises_java_exception
+    def recv(self, num_bytes, flags=None):
+        if not self.sock_impl:
+            raise error(errno.ENOTCONN, "Socket is not connected")
+        return self.sock_impl.recv(num_bytes, flags)
+
+    def __del__(self):
+        self.close()
+
+_socketmethods = (
+    'bind', 'connect', 'connect_ex', 'fileno', 'listen',
+    'getpeername', 'getsockname', 'getsockopt', 'setsockopt',
+    'sendall', 'setblocking',
+    'settimeout', 'gettimeout', 'shutdown', 'getchannel')
+
+# All the method names that must be delegated to either the real socket
+# object or the _closedsocket object.
+_delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into",
+                     "send", "sendto")
+
+class _closedsocket(object):
+    __slots__ = []
+    def _dummy(*args):
+        raise error(errno.EBADF, 'Bad file descriptor')
+    # All _delegate_methods must also be initialized here.
+    send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
+    __getattr__ = _dummy
+
+_active_sockets = set()
+
+def _closeActiveSockets():
+    for socket in _active_sockets.copy():
+        try:
+            socket.close()
+        except error:
+            msg = 'Problem closing socket: %s: %r' % (socket, sys.exc_info())
+            print >> sys.stderr, msg
+
+class _socketobject(object):
+
+    __doc__ = _realsocket.__doc__
+
+    __slots__ = ["_sock", "__weakref__"] + list(_delegate_methods)
+
+    def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
+        if _sock is None:
+            _sock = _realsocket(family, type, proto)
+            _sock.reference_count += 1
+        elif isinstance(_sock, _nonblocking_api_mixin):
+            _sock.reference_count += 1
+        self._sock = _sock
+        for method in _delegate_methods:
+            meth = getattr(_sock, method, None)
+            if meth:
+                setattr(self, method, meth)
+        _active_sockets.add(self)
+
+    def close(self):
+        try:
+            _active_sockets.remove(self)
+        except KeyError:
+            pass
+        _sock = self._sock
+        if isinstance(_sock, _nonblocking_api_mixin):
+            _sock.close_lock.acquire()
+            try:
+                _sock.reference_count -=1
+                if not _sock.reference_count:
+                    _sock.close()
+                self._sock = _closedsocket()
+                dummy = self._sock._dummy
+                for method in _delegate_methods:
+                    setattr(self, method, dummy)
+                self.send = self.recv = self.sendto = self.recvfrom = \
+                    self._sock._dummy
+            finally:
+                _sock.close_lock.release()
+    #close.__doc__ = _realsocket.close.__doc__
+
+    def accept(self):
+        sock, addr = self._sock.accept()
+        return _socketobject(_sock=sock), addr
+    #accept.__doc__ = _realsocket.accept.__doc__
+
+    def dup(self):
+        """dup() -> socket object
+
+        Return a new socket object connected to the same system resource."""
+        _sock = self._sock
+        if not isinstance(_sock, _nonblocking_api_mixin):
+            return _socketobject(_sock=_sock)
+
+        _sock.close_lock.acquire()
+        try:
+            duped = _socketobject(_sock=_sock)
+        finally:
+            _sock.close_lock.release()
+        return duped
+
+    def makefile(self, mode='r', bufsize=-1):
+        """makefile([mode[, bufsize]]) -> file object
+
+        Return a regular file object corresponding to the socket.  The mode
+        and bufsize arguments are as for the built-in open() function."""
+        _sock = self._sock
+        if not isinstance(_sock, _nonblocking_api_mixin):
+            return _fileobject(_sock, mode, bufsize)
+
+        _sock.close_lock.acquire()
+        try:
+            fileobject = _fileobject(_sock, mode, bufsize)
+        finally:
+            _sock.close_lock.release()
+        return fileobject
+
+    family = property(lambda self: self._sock.family, doc="the socket family")
+    type = property(lambda self: self._sock.type, doc="the socket type")
+    proto = property(lambda self: self._sock.proto, doc="the socket protocol")
+
+    _s = ("def %s(self, *args): return self._sock.%s(*args)\n\n"
+          #"%s.__doc__ = _realsocket.%s.__doc__\n")
+          )
+    for _m in _socketmethods:
+        #exec _s % (_m, _m, _m, _m)
+        exec _s % (_m, _m)
+    del _m, _s
+
+socket = SocketType = _socketobject
+
+class _fileobject(object):
+    """Faux file object attached to a socket object."""
+
+    default_bufsize = 8192
+    name = "<socket>"
+
+    __slots__ = ["mode", "bufsize", "softspace",
+                 # "closed" is a property, see below
+                 "_sock", "_rbufsize", "_wbufsize", "_rbuf", "_wbuf",
+                 "_close"]
+
+    def __init__(self, sock, mode='rb', bufsize=-1, close=False):
+        self._sock = sock
+        if isinstance(sock, _nonblocking_api_mixin):
+            sock.reference_count += 1
+        self.mode = mode # Not actually used in this version
+        if bufsize < 0:
+            bufsize = self.default_bufsize
+        self.bufsize = bufsize
+        self.softspace = False
+        if bufsize == 0:
+            self._rbufsize = 1
+        elif bufsize == 1:
+            self._rbufsize = self.default_bufsize
+        else:
+            self._rbufsize = bufsize
+        self._wbufsize = bufsize
+        self._rbuf = "" # A string
+        self._wbuf = [] # A list of strings
+        self._close = close
+
+    def _getclosed(self):
+        return self._sock is None
+    closed = property(_getclosed, doc="True if the file is closed")
+
+    def close(self):
+        try:
+            if self._sock:
+                self.flush()
+        finally:
+            if self._sock:
+                if isinstance(self._sock, _nonblocking_api_mixin):
+                    self._sock.reference_count -= 1
+                    if not self._sock.reference_count or self._close:
+                        self._sock.close()
+                elif self._close:
+                    self._sock.close()
+            self._sock = None
+
+    def __del__(self):
+        try:
+            self.close()
+        except:
+            # close() may fail if __init__ didn't complete
+            pass
+
+    def flush(self):
+        if self._wbuf:
+            buffer = "".join(self._wbuf)
+            self._wbuf = []
+            self._sock.sendall(buffer)
+
+    def fileno(self):
+        return self._sock.fileno()
+
+    def write(self, data):
+        data = str(data) # XXX Should really reject non-string non-buffers
+        if not data:
+            return
+        self._wbuf.append(data)
+        if (self._wbufsize == 0 or
+            self._wbufsize == 1 and '\n' in data or
+            self._get_wbuf_len() >= self._wbufsize):
+            self.flush()
+
+    def writelines(self, list):
+        # XXX We could do better here for very long lists
+        # XXX Should really reject non-string non-buffers
+        self._wbuf.extend(filter(None, map(str, list)))
+        if (self._wbufsize <= 1 or
+            self._get_wbuf_len() >= self._wbufsize):
+            self.flush()
+
+    def _get_wbuf_len(self):
+        buf_len = 0
+        for x in self._wbuf:
+            buf_len += len(x)
+        return buf_len
+
+    def read(self, size=-1):
+        data = self._rbuf
+        if size < 0:
+            # Read until EOF
+            buffers = []
+            if data:
+                buffers.append(data)
+            self._rbuf = ""
+            if self._rbufsize <= 1:
+                recv_size = self.default_bufsize
+            else:
+                recv_size = self._rbufsize
+            while True:
+                data = self._sock.recv(recv_size)
+                if not data:
+                    break
+                buffers.append(data)
+            return "".join(buffers)
+        else:
+            # Read until size bytes or EOF seen, whichever comes first
+            buf_len = len(data)
+            if buf_len >= size:
+                self._rbuf = data[size:]
+                return data[:size]
+            buffers = []
+            if data:
+                buffers.append(data)
+            self._rbuf = ""
+            while True:
+                left = size - buf_len
+                recv_size = max(self._rbufsize, left)
+                data = self._sock.recv(recv_size)
+                if not data:
+                    break
+                buffers.append(data)
+                n = len(data)
+                if n >= left:
+                    self._rbuf = data[left:]
+                    buffers[-1] = data[:left]
+                    break
+                buf_len += n
+            return "".join(buffers)
+
+    def readline(self, size=-1):
+        data = self._rbuf
+        if size < 0:
+            # Read until \n or EOF, whichever comes first
+            if self._rbufsize <= 1:
+                # Speed up unbuffered case
+                assert data == ""
+                buffers = []
+                recv = self._sock.recv
+                while data != "\n":
+                    data = recv(1)
+                    if not data:
+                        break
+                    buffers.append(data)
+                return "".join(buffers)
+            nl = data.find('\n')
+            if nl >= 0:
+                nl += 1
+                self._rbuf = data[nl:]
+                return data[:nl]
+            buffers = []
+            if data:
+                buffers.append(data)
+            self._rbuf = ""
+            while True:
+                data = self._sock.recv(self._rbufsize)
+                if not data:
+                    break
+                buffers.append(data)
+                nl = data.find('\n')
+                if nl >= 0:
+                    nl += 1
+                    self._rbuf = data[nl:]
+                    buffers[-1] = data[:nl]
+                    break
+            return "".join(buffers)
+        else:
+            # Read until size bytes or \n or EOF seen, whichever comes first
+            nl = data.find('\n', 0, size)
+            if nl >= 0:
+                nl += 1
+                self._rbuf = data[nl:]
+                return data[:nl]
+            buf_len = len(data)
+            if buf_len >= size:
+                self._rbuf = data[size:]
+                return data[:size]
+            buffers = []
+            if data:
+                buffers.append(data)
+            self._rbuf = ""
+            while True:
+                data = self._sock.recv(self._rbufsize)
+                if not data:
+                    break
+                buffers.append(data)
+                left = size - buf_len
+                nl = data.find('\n', 0, left)
+                if nl >= 0:
+                    nl += 1
+                    self._rbuf = data[nl:]
+                    buffers[-1] = data[:nl]
+                    break
+                n = len(data)
+                if n >= left:
+                    self._rbuf = data[left:]
+                    buffers[-1] = data[:left]
+                    break
+                buf_len += n
+            return "".join(buffers)
+
+    def readlines(self, sizehint=0):
+        total = 0
+        list = []
+        while True:
+            line = self.readline()
+            if not line:
+                break
+            list.append(line)
+            total += len(line)
+            if sizehint and total >= sizehint:
+                break
+        return list
+
+    # Iterator protocols
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        line = self.readline()
+        if not line:
+            raise StopIteration
+        return line
+
+_GLOBAL_DEFAULT_TIMEOUT = object()
+
+def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
+                      source_address=None):
+    """Connect to *address* and return the socket object.
+
+    Convenience function.  Connect to *address* (a 2-tuple ``(host,
+    port)``) and return the socket object.  Passing the optional
+    *timeout* parameter will set the timeout on the socket instance
+    before attempting to connect.  If no *timeout* is supplied, the
+    global default timeout setting returned by :func:`getdefaulttimeout`
+    is used.  If *source_address* is set it must be a tuple of (host, port)
+    for the socket to bind as a source address before making the connection.
+    An host of '' or port 0 tells the OS to use the default.
+    """
+
+    host, port = address
+    err = None
+    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
+        af, socktype, proto, canonname, sa = res
+        sock = None
+        try:
+            sock = socket(af, socktype, proto)
+            if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
+                sock.settimeout(timeout)
+            if source_address:
+                sock.bind(source_address)
+            sock.connect(sa)
+            return sock
+
+        except error as _:
+            err = _
+            if sock is not None:
+                sock.close()
+
+    if err is not None:
+        raise err
+    else:
+        raise error("getaddrinfo returns an empty list")
+
+# Define the SSL support
+
+class ssl:
+
+    @raises_java_exception
+    def __init__(self, jython_socket_wrapper, keyfile=None, certfile=None):
+        self.jython_socket_wrapper = jython_socket_wrapper
+        jython_socket = self.jython_socket_wrapper._sock
+        self.java_ssl_socket = self._make_ssl_socket(jython_socket)
+        self._in_buf = java.io.BufferedInputStream(self.java_ssl_socket.getInputStream())
+        self._out_buf = java.io.BufferedOutputStream(self.java_ssl_socket.getOutputStream())
+
+    def _make_ssl_socket(self, jython_socket, auto_close=0):
+        java_net_socket = jython_socket._get_jsocket()
+        assert isinstance(java_net_socket, java.net.Socket)
+        host = java_net_socket.getInetAddress().getHostAddress()
+        port = java_net_socket.getPort()
+        factory = javax.net.ssl.SSLSocketFactory.getDefault();
+        java_ssl_socket = factory.createSocket(java_net_socket, host, port, auto_close)
+        java_ssl_socket.setEnabledCipherSuites(java_ssl_socket.getSupportedCipherSuites())
+        java_ssl_socket.startHandshake()
+        return java_ssl_socket
+
+    @raises_java_exception
+    def read(self, n=4096):
+        data = jarray.zeros(n, 'b')
+        m = self._in_buf.read(data, 0, n)
+        if m <= 0:
+            return ""
+        if m < n:
+            data = data[:m]
+        return data.tostring()
+
+    recv = read
+
+    @raises_java_exception
+    def write(self, s):
+        self._out_buf.write(s)
+        self._out_buf.flush()
+        return len(s)
+
+    send = sendall = write
+
+    def makefile(self, mode='r', bufsize=-1):
+        return _fileobject(self, mode, bufsize)
+
+    def _get_server_cert(self):
+        return self.java_ssl_socket.getSession().getPeerCertificates()[0]
+
+    @raises_java_exception
+    def server(self):
+        cert = self._get_server_cert()
+        return cert.getSubjectDN().toString()
+
+    @raises_java_exception
+    def issuer(self):
+        cert = self._get_server_cert()
+        return cert.getIssuerDN().toString()
+
+    def close(self):
+        self.jython_socket_wrapper.close()
+
+def test():
+    s = socket(AF_INET, SOCK_STREAM)
+    s.connect(("", 80))
+    s.send("GET / HTTP/1.0\r\n\r\n")
+    while 1:
+        data = s.recv(2000)
+        print data
+        if not data:
+            break
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/sre.py b/src/main/resources/PythonLibs/sre.py
new file mode 100644
index 0000000000000000000000000000000000000000..c04576bafa58871e84333c0da2a074614c01e97b
--- /dev/null
+++ b/src/main/resources/PythonLibs/sre.py
@@ -0,0 +1,13 @@
+"""This file is only retained for backwards compatibility.
+It will be removed in the future.  sre was moved to re in version 2.5.
+"""
+
+import warnings
+warnings.warn("The sre module is deprecated, please import re.",
+              DeprecationWarning, 2)
+
+from re import *
+from re import __all__
+
+# old pickles expect the _compile() reconstructor in this module
+from re import _compile
diff --git a/src/main/resources/PythonLibs/sre_compile.py b/src/main/resources/PythonLibs/sre_compile.py
new file mode 100644
index 0000000000000000000000000000000000000000..a2279de8190c79fd9c74c38b58f0f37033ff3ed4
--- /dev/null
+++ b/src/main/resources/PythonLibs/sre_compile.py
@@ -0,0 +1,536 @@
+#
+# Secret Labs' Regular Expression Engine
+#
+# convert template to internal format
+#
+# Copyright (c) 1997-2001 by Secret Labs AB.  All rights reserved.
+#
+# See the sre.py file for information on usage and redistribution.
+#
+
+"""Internal support module for sre"""
+
+import _sre, sys
+
+from sre_constants import *
+
+assert _sre.MAGIC == MAGIC, "SRE module mismatch"
+
+if _sre.CODESIZE == 2:
+    MAXCODE = 65535
+else:
+    MAXCODE = 0xFFFFFFFFL
+
+def _identityfunction(x):
+    return x
+
+def set(seq):
+    s = {}
+    for elem in seq:
+        s[elem] = 1
+    return s
+
+_LITERAL_CODES = set([LITERAL, NOT_LITERAL])
+_REPEATING_CODES = set([REPEAT, MIN_REPEAT, MAX_REPEAT])
+_SUCCESS_CODES = set([SUCCESS, FAILURE])
+_ASSERT_CODES = set([ASSERT, ASSERT_NOT])
+
+def _compile(code, pattern, flags):
+    # internal: compile a (sub)pattern
+    emit = code.append
+    _len = len
+    LITERAL_CODES = _LITERAL_CODES
+    REPEATING_CODES = _REPEATING_CODES
+    SUCCESS_CODES = _SUCCESS_CODES
+    ASSERT_CODES = _ASSERT_CODES
+    for op, av in pattern:
+        if op in LITERAL_CODES:
+            if flags & SRE_FLAG_IGNORECASE:
+                emit(OPCODES[OP_IGNORE[op]])
+                emit(_sre.getlower(av, flags))
+            else:
+                emit(OPCODES[op])
+                emit(av)
+        elif op is IN:
+            if flags & SRE_FLAG_IGNORECASE:
+                emit(OPCODES[OP_IGNORE[op]])
+                def fixup(literal, flags=flags):
+                    return _sre.getlower(literal, flags)
+            else:
+                emit(OPCODES[op])
+                fixup = _identityfunction
+            skip = _len(code); emit(0)
+            _compile_charset(av, flags, code, fixup)
+            code[skip] = _len(code) - skip
+        elif op is ANY:
+            if flags & SRE_FLAG_DOTALL:
+                emit(OPCODES[ANY_ALL])
+            else:
+                emit(OPCODES[ANY])
+        elif op in REPEATING_CODES:
+            if flags & SRE_FLAG_TEMPLATE:
+                raise error, "internal: unsupported template operator"
+                emit(OPCODES[REPEAT])
+                skip = _len(code); emit(0)
+                emit(av[0])
+                emit(av[1])
+                _compile(code, av[2], flags)
+                emit(OPCODES[SUCCESS])
+                code[skip] = _len(code) - skip
+            elif _simple(av) and op is not REPEAT:
+                if op is MAX_REPEAT:
+                    emit(OPCODES[REPEAT_ONE])
+                else:
+                    emit(OPCODES[MIN_REPEAT_ONE])
+                skip = _len(code); emit(0)
+                emit(av[0])
+                emit(av[1])
+                _compile(code, av[2], flags)
+                emit(OPCODES[SUCCESS])
+                code[skip] = _len(code) - skip
+            else:
+                emit(OPCODES[REPEAT])
+                skip = _len(code); emit(0)
+                emit(av[0])
+                emit(av[1])
+                _compile(code, av[2], flags)
+                code[skip] = _len(code) - skip
+                if op is MAX_REPEAT:
+                    emit(OPCODES[MAX_UNTIL])
+                else:
+                    emit(OPCODES[MIN_UNTIL])
+        elif op is SUBPATTERN:
+            if av[0]:
+                emit(OPCODES[MARK])
+                emit((av[0]-1)*2)
+            # _compile_info(code, av[1], flags)
+            _compile(code, av[1], flags)
+            if av[0]:
+                emit(OPCODES[MARK])
+                emit((av[0]-1)*2+1)
+        elif op in SUCCESS_CODES:
+            emit(OPCODES[op])
+        elif op in ASSERT_CODES:
+            emit(OPCODES[op])
+            skip = _len(code); emit(0)
+            if av[0] >= 0:
+                emit(0) # look ahead
+            else:
+                lo, hi = av[1].getwidth()
+                if lo != hi:
+                    raise error, "look-behind requires fixed-width pattern"
+                emit(lo) # look behind
+            _compile(code, av[1], flags)
+            emit(OPCODES[SUCCESS])
+            code[skip] = _len(code) - skip
+        elif op is CALL:
+            emit(OPCODES[op])
+            skip = _len(code); emit(0)
+            _compile(code, av, flags)
+            emit(OPCODES[SUCCESS])
+            code[skip] = _len(code) - skip
+        elif op is AT:
+            emit(OPCODES[op])
+            if flags & SRE_FLAG_MULTILINE:
+                av = AT_MULTILINE.get(av, av)
+            if flags & SRE_FLAG_LOCALE:
+                av = AT_LOCALE.get(av, av)
+            elif flags & SRE_FLAG_UNICODE:
+                av = AT_UNICODE.get(av, av)
+            emit(ATCODES[av])
+        elif op is BRANCH:
+            emit(OPCODES[op])
+            tail = []
+            tailappend = tail.append
+            for av in av[1]:
+                skip = _len(code); emit(0)
+                # _compile_info(code, av, flags)
+                _compile(code, av, flags)
+                emit(OPCODES[JUMP])
+                tailappend(_len(code)); emit(0)
+                code[skip] = _len(code) - skip
+            emit(0) # end of branch
+            for tail in tail:
+                code[tail] = _len(code) - tail
+        elif op is CATEGORY:
+            emit(OPCODES[op])
+            if flags & SRE_FLAG_LOCALE:
+                av = CH_LOCALE[av]
+            elif flags & SRE_FLAG_UNICODE:
+                av = CH_UNICODE[av]
+            emit(CHCODES[av])
+        elif op is GROUPREF:
+            if flags & SRE_FLAG_IGNORECASE:
+                emit(OPCODES[OP_IGNORE[op]])
+            else:
+                emit(OPCODES[op])
+            emit(av-1)
+        elif op is GROUPREF_EXISTS:
+            emit(OPCODES[op])
+            emit(av[0]-1)
+            skipyes = _len(code); emit(0)
+            _compile(code, av[1], flags)
+            if av[2]:
+                emit(OPCODES[JUMP])
+                skipno = _len(code); emit(0)
+                code[skipyes] = _len(code) - skipyes + 1
+                _compile(code, av[2], flags)
+                code[skipno] = _len(code) - skipno
+            else:
+                code[skipyes] = _len(code) - skipyes + 1
+        else:
+            raise ValueError, ("unsupported operand type", op)
+
+def _compile_charset(charset, flags, code, fixup=None):
+    # compile charset subprogram
+    emit = code.append
+    if fixup is None:
+        fixup = _identityfunction
+    for op, av in _optimize_charset(charset, fixup):
+        emit(OPCODES[op])
+        if op is NEGATE:
+            pass
+        elif op is LITERAL:
+            emit(fixup(av))
+        elif op is RANGE:
+            emit(fixup(av[0]))
+            emit(fixup(av[1]))
+        elif op is CHARSET:
+            code.extend(av)
+        elif op is BIGCHARSET:
+            code.extend(av)
+        elif op is CATEGORY:
+            if flags & SRE_FLAG_LOCALE:
+                emit(CHCODES[CH_LOCALE[av]])
+            elif flags & SRE_FLAG_UNICODE:
+                emit(CHCODES[CH_UNICODE[av]])
+            else:
+                emit(CHCODES[av])
+        else:
+            raise error, "internal: unsupported set operator"
+    emit(OPCODES[FAILURE])
+
+def _optimize_charset(charset, fixup):
+    # internal: optimize character set
+    out = []
+    outappend = out.append
+    charmap = [0]*256
+    try:
+        for op, av in charset:
+            if op is NEGATE:
+                outappend((op, av))
+            elif op is LITERAL:
+                charmap[fixup(av)] = 1
+            elif op is RANGE:
+                for i in range(fixup(av[0]), fixup(av[1])+1):
+                    charmap[i] = 1
+            elif op is CATEGORY:
+                # XXX: could append to charmap tail
+                return charset # cannot compress
+    except IndexError:
+        # character set contains unicode characters
+        return _optimize_unicode(charset, fixup)
+    # compress character map
+    i = p = n = 0
+    runs = []
+    runsappend = runs.append
+    for c in charmap:
+        if c:
+            if n == 0:
+                p = i
+            n = n + 1
+        elif n:
+            runsappend((p, n))
+            n = 0
+        i = i + 1
+    if n:
+        runsappend((p, n))
+    if len(runs) <= 2:
+        # use literal/range
+        for p, n in runs:
+            if n == 1:
+                outappend((LITERAL, p))
+            else:
+                outappend((RANGE, (p, p+n-1)))
+        if len(out) < len(charset):
+            return out
+    else:
+        # use bitmap
+        data = _mk_bitmap(charmap)
+        outappend((CHARSET, data))
+        return out
+    return charset
+
+def _mk_bitmap(bits):
+    data = []
+    dataappend = data.append
+    if _sre.CODESIZE == 2:
+        start = (1, 0)
+    else:
+        start = (1L, 0L)
+    m, v = start
+    for c in bits:
+        if c:
+            v = v + m
+        m = m + m
+        if m > MAXCODE:
+            dataappend(v)
+            m, v = start
+    return data
+
+# To represent a big charset, first a bitmap of all characters in the
+# set is constructed. Then, this bitmap is sliced into chunks of 256
+# characters, duplicate chunks are eliminated, and each chunk is
+# given a number. In the compiled expression, the charset is
+# represented by a 16-bit word sequence, consisting of one word for
+# the number of different chunks, a sequence of 256 bytes (128 words)
+# of chunk numbers indexed by their original chunk position, and a
+# sequence of chunks (16 words each).
+
+# Compression is normally good: in a typical charset, large ranges of
+# Unicode will be either completely excluded (e.g. if only cyrillic
+# letters are to be matched), or completely included (e.g. if large
+# subranges of Kanji match). These ranges will be represented by
+# chunks of all one-bits or all zero-bits.
+
+# Matching can be also done efficiently: the more significant byte of
+# the Unicode character is an index into the chunk number, and the
+# less significant byte is a bit index in the chunk (just like the
+# CHARSET matching).
+
+# In UCS-4 mode, the BIGCHARSET opcode still supports only subsets
+# of the basic multilingual plane; an efficient representation
+# for all of UTF-16 has not yet been developed. This means,
+# in particular, that negated charsets cannot be represented as
+# bigcharsets.
+
+def _optimize_unicode(charset, fixup):
+    # problems with optimization in Jython, forget about it for now
+    return charset
+
+    try:
+        import array
+    except ImportError:
+        return charset
+    charmap = [0]*65536
+    negate = 0
+    try:
+        for op, av in charset:
+            if op is NEGATE:
+                negate = 1
+            elif op is LITERAL:
+                charmap[fixup(av)] = 1
+            elif op is RANGE:
+                for i in xrange(fixup(av[0]), fixup(av[1])+1):
+                    charmap[i] = 1
+            elif op is CATEGORY:
+                # XXX: could expand category
+                return charset # cannot compress
+    except IndexError:
+        # non-BMP characters
+        return charset
+    if negate:
+        if sys.maxunicode != 65535:
+            # XXX: negation does not work with big charsets
+            return charset
+        for i in xrange(65536):
+            charmap[i] = not charmap[i]
+    comps = {}
+    mapping = [0]*256
+    block = 0
+    data = []
+    for i in xrange(256):
+        chunk = tuple(charmap[i*256:(i+1)*256])
+        new = comps.setdefault(chunk, block)
+        mapping[i] = new
+        if new == block:
+            block = block + 1
+            data = data + _mk_bitmap(chunk)
+    header = [block]
+    if _sre.CODESIZE == 2:
+        code = 'H'
+    else:
+        # change this for Jython from 'I', since that will expand to
+        # long, and cause needless complexity (or so it seems)
+        code = 'i'
+    # Convert block indices to byte array of 256 bytes
+    mapping = array.array('b', mapping).tostring()
+    # Convert byte array to word array
+    mapping = array.array(code, mapping)
+    assert mapping.itemsize == _sre.CODESIZE
+    header = header + mapping.tolist()
+    data[0:0] = header
+    return [(BIGCHARSET, data)]
+
+def _simple(av):
+    # check if av is a "simple" operator
+    lo, hi = av[2].getwidth()
+    if lo == 0 and hi == MAXREPEAT:
+        raise error, "nothing to repeat"
+    return lo == hi == 1 and av[2][0][0] != SUBPATTERN
+
+def _compile_info(code, pattern, flags):
+    # internal: compile an info block.  in the current version,
+    # this contains min/max pattern width, and an optional literal
+    # prefix or a character map
+    lo, hi = pattern.getwidth()
+    if lo == 0:
+        return # not worth it
+    # look for a literal prefix
+    prefix = []
+    prefixappend = prefix.append
+    prefix_skip = 0
+    charset = [] # not used
+    charsetappend = charset.append
+    if not (flags & SRE_FLAG_IGNORECASE):
+        # look for literal prefix
+        for op, av in pattern.data:
+            if op is LITERAL:
+                if len(prefix) == prefix_skip:
+                    prefix_skip = prefix_skip + 1
+                prefixappend(av)
+            elif op is SUBPATTERN and len(av[1]) == 1:
+                op, av = av[1][0]
+                if op is LITERAL:
+                    prefixappend(av)
+                else:
+                    break
+            else:
+                break
+        # if no prefix, look for charset prefix
+        if not prefix and pattern.data:
+            op, av = pattern.data[0]
+            if op is SUBPATTERN and av[1]:
+                op, av = av[1][0]
+                if op is LITERAL:
+                    charsetappend((op, av))
+                elif op is BRANCH:
+                    c = []
+                    cappend = c.append
+                    for p in av[1]:
+                        if not p:
+                            break
+                        op, av = p[0]
+                        if op is LITERAL:
+                            cappend((op, av))
+                        else:
+                            break
+                    else:
+                        charset = c
+            elif op is BRANCH:
+                c = []
+                cappend = c.append
+                for p in av[1]:
+                    if not p:
+                        break
+                    op, av = p[0]
+                    if op is LITERAL:
+                        cappend((op, av))
+                    else:
+                        break
+                else:
+                    charset = c
+            elif op is IN:
+                charset = av
+##     if prefix:
+##         print "*** PREFIX", prefix, prefix_skip
+##     if charset:
+##         print "*** CHARSET", charset
+    # add an info block
+    emit = code.append
+    emit(OPCODES[INFO])
+    skip = len(code); emit(0)
+    # literal flag
+    mask = 0
+    if prefix:
+        mask = SRE_INFO_PREFIX
+        if len(prefix) == prefix_skip == len(pattern.data):
+            mask = mask + SRE_INFO_LITERAL
+    elif charset:
+        mask = mask + SRE_INFO_CHARSET
+    emit(mask)
+    # pattern length
+    if lo < MAXCODE:
+        emit(lo)
+    else:
+        emit(MAXCODE)
+        prefix = prefix[:MAXCODE]
+    if hi < MAXCODE:
+        emit(hi)
+    else:
+        emit(0)
+    # add literal prefix
+    if prefix:
+        emit(len(prefix)) # length
+        emit(prefix_skip) # skip
+        code.extend(prefix)
+        # generate overlap table
+        table = [-1] + ([0]*len(prefix))
+        for i in xrange(len(prefix)):
+            table[i+1] = table[i]+1
+            while table[i+1] > 0 and prefix[i] != prefix[table[i+1]-1]:
+                table[i+1] = table[table[i+1]-1]+1
+        code.extend(table[1:]) # don't store first entry
+    elif charset:
+        _compile_charset(charset, flags, code)
+    code[skip] = len(code) - skip
+
+try:
+    unicode
+except NameError:
+    STRING_TYPES = (type(""),)
+else:
+    STRING_TYPES = (type(""), type(unicode("")))
+
+def isstring(obj):
+    for tp in STRING_TYPES:
+        if isinstance(obj, tp):
+            return 1
+    return 0
+
+def _code(p, flags):
+
+    flags = p.pattern.flags | flags
+    code = []
+
+    # compile info block
+    _compile_info(code, p, flags)
+
+    # compile the pattern
+    _compile(code, p.data, flags)
+
+    code.append(OPCODES[SUCCESS])
+
+    return code
+
+def compile(p, flags=0):
+    # internal: convert pattern list to internal format
+
+    if isstring(p):
+        import sre_parse
+        pattern = p
+        p = sre_parse.parse(p, flags)
+    else:
+        pattern = None
+
+    code = _code(p, flags)
+
+    # print code
+
+    # XXX: <fl> get rid of this limitation!
+    if p.pattern.groups > 100:
+        raise AssertionError(
+            "sorry, but this version only supports 100 named groups"
+            )
+
+    # map in either direction
+    groupindex = p.pattern.groupdict
+    indexgroup = [None] * p.pattern.groups
+    for k, i in groupindex.items():
+        indexgroup[i] = k
+
+    return _sre.compile(
+        pattern, flags | p.pattern.flags, code,
+        p.pattern.groups-1,
+        groupindex, indexgroup
+        )
diff --git a/src/main/resources/PythonLibs/sre_constants.py b/src/main/resources/PythonLibs/sre_constants.py
new file mode 100644
index 0000000000000000000000000000000000000000..b0175e71be6597717244555654e3a9268bb6b439
--- /dev/null
+++ b/src/main/resources/PythonLibs/sre_constants.py
@@ -0,0 +1,259 @@
+#
+# Secret Labs' Regular Expression Engine
+#
+# various symbols used by the regular expression engine.
+# run this script to update the _sre include files!
+#
+# Copyright (c) 1998-2001 by Secret Labs AB.  All rights reserved.
+#
+# See the sre.py file for information on usage and redistribution.
+#
+
+"""Internal support module for sre"""
+
+# update when constants are added or removed
+
+MAGIC = 20031017
+
+from _sre import MAXREPEAT
+
+# SRE standard exception (access as sre.error)
+# should this really be here?
+
+class error(Exception):
+    pass
+
+# operators
+
+FAILURE = "failure"
+SUCCESS = "success"
+
+ANY = "any"
+ANY_ALL = "any_all"
+ASSERT = "assert"
+ASSERT_NOT = "assert_not"
+AT = "at"
+BIGCHARSET = "bigcharset"
+BRANCH = "branch"
+CALL = "call"
+CATEGORY = "category"
+CHARSET = "charset"
+GROUPREF = "groupref"
+GROUPREF_IGNORE = "groupref_ignore"
+GROUPREF_EXISTS = "groupref_exists"
+IN = "in"
+IN_IGNORE = "in_ignore"
+INFO = "info"
+JUMP = "jump"
+LITERAL = "literal"
+LITERAL_IGNORE = "literal_ignore"
+MARK = "mark"
+MAX_REPEAT = "max_repeat"
+MAX_UNTIL = "max_until"
+MIN_REPEAT = "min_repeat"
+MIN_UNTIL = "min_until"
+NEGATE = "negate"
+NOT_LITERAL = "not_literal"
+NOT_LITERAL_IGNORE = "not_literal_ignore"
+RANGE = "range"
+REPEAT = "repeat"
+REPEAT_ONE = "repeat_one"
+SUBPATTERN = "subpattern"
+MIN_REPEAT_ONE = "min_repeat_one"
+
+# positions
+AT_BEGINNING = "at_beginning"
+AT_BEGINNING_LINE = "at_beginning_line"
+AT_BEGINNING_STRING = "at_beginning_string"
+AT_BOUNDARY = "at_boundary"
+AT_NON_BOUNDARY = "at_non_boundary"
+AT_END = "at_end"
+AT_END_LINE = "at_end_line"
+AT_END_STRING = "at_end_string"
+AT_LOC_BOUNDARY = "at_loc_boundary"
+AT_LOC_NON_BOUNDARY = "at_loc_non_boundary"
+AT_UNI_BOUNDARY = "at_uni_boundary"
+AT_UNI_NON_BOUNDARY = "at_uni_non_boundary"
+
+# categories
+CATEGORY_DIGIT = "category_digit"
+CATEGORY_NOT_DIGIT = "category_not_digit"
+CATEGORY_SPACE = "category_space"
+CATEGORY_NOT_SPACE = "category_not_space"
+CATEGORY_WORD = "category_word"
+CATEGORY_NOT_WORD = "category_not_word"
+CATEGORY_LINEBREAK = "category_linebreak"
+CATEGORY_NOT_LINEBREAK = "category_not_linebreak"
+CATEGORY_LOC_WORD = "category_loc_word"
+CATEGORY_LOC_NOT_WORD = "category_loc_not_word"
+CATEGORY_UNI_DIGIT = "category_uni_digit"
+CATEGORY_UNI_NOT_DIGIT = "category_uni_not_digit"
+CATEGORY_UNI_SPACE = "category_uni_space"
+CATEGORY_UNI_NOT_SPACE = "category_uni_not_space"
+CATEGORY_UNI_WORD = "category_uni_word"
+CATEGORY_UNI_NOT_WORD = "category_uni_not_word"
+CATEGORY_UNI_LINEBREAK = "category_uni_linebreak"
+CATEGORY_UNI_NOT_LINEBREAK = "category_uni_not_linebreak"
+
+OPCODES = [
+
+    # failure=0 success=1 (just because it looks better that way :-)
+    FAILURE, SUCCESS,
+
+    ANY, ANY_ALL,
+    ASSERT, ASSERT_NOT,
+    AT,
+    BRANCH,
+    CALL,
+    CATEGORY,
+    CHARSET, BIGCHARSET,
+    GROUPREF, GROUPREF_EXISTS, GROUPREF_IGNORE,
+    IN, IN_IGNORE,
+    INFO,
+    JUMP,
+    LITERAL, LITERAL_IGNORE,
+    MARK,
+    MAX_UNTIL,
+    MIN_UNTIL,
+    NOT_LITERAL, NOT_LITERAL_IGNORE,
+    NEGATE,
+    RANGE,
+    REPEAT,
+    REPEAT_ONE,
+    SUBPATTERN,
+    MIN_REPEAT_ONE
+
+]
+
+ATCODES = [
+    AT_BEGINNING, AT_BEGINNING_LINE, AT_BEGINNING_STRING, AT_BOUNDARY,
+    AT_NON_BOUNDARY, AT_END, AT_END_LINE, AT_END_STRING,
+    AT_LOC_BOUNDARY, AT_LOC_NON_BOUNDARY, AT_UNI_BOUNDARY,
+    AT_UNI_NON_BOUNDARY
+]
+
+CHCODES = [
+    CATEGORY_DIGIT, CATEGORY_NOT_DIGIT, CATEGORY_SPACE,
+    CATEGORY_NOT_SPACE, CATEGORY_WORD, CATEGORY_NOT_WORD,
+    CATEGORY_LINEBREAK, CATEGORY_NOT_LINEBREAK, CATEGORY_LOC_WORD,
+    CATEGORY_LOC_NOT_WORD, CATEGORY_UNI_DIGIT, CATEGORY_UNI_NOT_DIGIT,
+    CATEGORY_UNI_SPACE, CATEGORY_UNI_NOT_SPACE, CATEGORY_UNI_WORD,
+    CATEGORY_UNI_NOT_WORD, CATEGORY_UNI_LINEBREAK,
+    CATEGORY_UNI_NOT_LINEBREAK
+]
+
+def makedict(list):
+    d = {}
+    i = 0
+    for item in list:
+        d[item] = i
+        i = i + 1
+    return d
+
+OPCODES = makedict(OPCODES)
+ATCODES = makedict(ATCODES)
+CHCODES = makedict(CHCODES)
+
+# replacement operations for "ignore case" mode
+OP_IGNORE = {
+    GROUPREF: GROUPREF_IGNORE,
+    IN: IN_IGNORE,
+    LITERAL: LITERAL_IGNORE,
+    NOT_LITERAL: NOT_LITERAL_IGNORE
+}
+
+AT_MULTILINE = {
+    AT_BEGINNING: AT_BEGINNING_LINE,
+    AT_END: AT_END_LINE
+}
+
+AT_LOCALE = {
+    AT_BOUNDARY: AT_LOC_BOUNDARY,
+    AT_NON_BOUNDARY: AT_LOC_NON_BOUNDARY
+}
+
+AT_UNICODE = {
+    AT_BOUNDARY: AT_UNI_BOUNDARY,
+    AT_NON_BOUNDARY: AT_UNI_NON_BOUNDARY
+}
+
+CH_LOCALE = {
+    CATEGORY_DIGIT: CATEGORY_DIGIT,
+    CATEGORY_NOT_DIGIT: CATEGORY_NOT_DIGIT,
+    CATEGORY_SPACE: CATEGORY_SPACE,
+    CATEGORY_NOT_SPACE: CATEGORY_NOT_SPACE,
+    CATEGORY_WORD: CATEGORY_LOC_WORD,
+    CATEGORY_NOT_WORD: CATEGORY_LOC_NOT_WORD,
+    CATEGORY_LINEBREAK: CATEGORY_LINEBREAK,
+    CATEGORY_NOT_LINEBREAK: CATEGORY_NOT_LINEBREAK
+}
+
+CH_UNICODE = {
+    CATEGORY_DIGIT: CATEGORY_UNI_DIGIT,
+    CATEGORY_NOT_DIGIT: CATEGORY_UNI_NOT_DIGIT,
+    CATEGORY_SPACE: CATEGORY_UNI_SPACE,
+    CATEGORY_NOT_SPACE: CATEGORY_UNI_NOT_SPACE,
+    CATEGORY_WORD: CATEGORY_UNI_WORD,
+    CATEGORY_NOT_WORD: CATEGORY_UNI_NOT_WORD,
+    CATEGORY_LINEBREAK: CATEGORY_UNI_LINEBREAK,
+    CATEGORY_NOT_LINEBREAK: CATEGORY_UNI_NOT_LINEBREAK
+}
+
+# flags
+SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking)
+SRE_FLAG_IGNORECASE = 2 # case insensitive
+SRE_FLAG_LOCALE = 4 # honour system locale
+SRE_FLAG_MULTILINE = 8 # treat target as multiline string
+SRE_FLAG_DOTALL = 16 # treat target as a single string
+SRE_FLAG_UNICODE = 32 # use unicode locale
+SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments
+SRE_FLAG_DEBUG = 128 # debugging
+
+# flags for INFO primitive
+SRE_INFO_PREFIX = 1 # has prefix
+SRE_INFO_LITERAL = 2 # entire pattern is literal (given by prefix)
+SRE_INFO_CHARSET = 4 # pattern starts with character from given set
+
+if __name__ == "__main__":
+    def dump(f, d, prefix):
+        items = d.items()
+        items.sort(key=lambda a: a[1])
+        for k, v in items:
+            f.write("#define %s_%s %s\n" % (prefix, k.upper(), v))
+    f = open("sre_constants.h", "w")
+    f.write("""\
+/*
+ * Secret Labs' Regular Expression Engine
+ *
+ * regular expression matching engine
+ *
+ * NOTE: This file is generated by sre_constants.py.  If you need
+ * to change anything in here, edit sre_constants.py and run it.
+ *
+ * Copyright (c) 1997-2001 by Secret Labs AB.  All rights reserved.
+ *
+ * See the _sre.c file for information on usage and redistribution.
+ */
+
+""")
+
+    f.write("#define SRE_MAGIC %d\n" % MAGIC)
+
+    dump(f, OPCODES, "SRE_OP")
+    dump(f, ATCODES, "SRE")
+    dump(f, CHCODES, "SRE")
+
+    f.write("#define SRE_FLAG_TEMPLATE %d\n" % SRE_FLAG_TEMPLATE)
+    f.write("#define SRE_FLAG_IGNORECASE %d\n" % SRE_FLAG_IGNORECASE)
+    f.write("#define SRE_FLAG_LOCALE %d\n" % SRE_FLAG_LOCALE)
+    f.write("#define SRE_FLAG_MULTILINE %d\n" % SRE_FLAG_MULTILINE)
+    f.write("#define SRE_FLAG_DOTALL %d\n" % SRE_FLAG_DOTALL)
+    f.write("#define SRE_FLAG_UNICODE %d\n" % SRE_FLAG_UNICODE)
+    f.write("#define SRE_FLAG_VERBOSE %d\n" % SRE_FLAG_VERBOSE)
+
+    f.write("#define SRE_INFO_PREFIX %d\n" % SRE_INFO_PREFIX)
+    f.write("#define SRE_INFO_LITERAL %d\n" % SRE_INFO_LITERAL)
+    f.write("#define SRE_INFO_CHARSET %d\n" % SRE_INFO_CHARSET)
+
+    f.close()
+    print "done"
diff --git a/src/main/resources/PythonLibs/sre_parse.py b/src/main/resources/PythonLibs/sre_parse.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0cf34414b6335d2747bcc319a410bce1d18a702
--- /dev/null
+++ b/src/main/resources/PythonLibs/sre_parse.py
@@ -0,0 +1,801 @@
+#
+# Secret Labs' Regular Expression Engine
+#
+# convert re-style regular expression to sre pattern
+#
+# Copyright (c) 1998-2001 by Secret Labs AB.  All rights reserved.
+#
+# See the sre.py file for information on usage and redistribution.
+#
+
+"""Internal support module for sre"""
+
+# XXX: show string offset and offending character for all errors
+
+import sys
+
+from sre_constants import *
+from _sre import MAXREPEAT
+
+SPECIAL_CHARS = ".\\[{()*+?^$|"
+REPEAT_CHARS = "*+?{"
+
+DIGITS = set("0123456789")
+
+OCTDIGITS = set("01234567")
+HEXDIGITS = set("0123456789abcdefABCDEF")
+
+WHITESPACE = set(" \t\n\r\v\f")
+
+ESCAPES = {
+    r"\a": (LITERAL, ord("\a")),
+    r"\b": (LITERAL, ord("\b")),
+    r"\f": (LITERAL, ord("\f")),
+    r"\n": (LITERAL, ord("\n")),
+    r"\r": (LITERAL, ord("\r")),
+    r"\t": (LITERAL, ord("\t")),
+    r"\v": (LITERAL, ord("\v")),
+    r"\\": (LITERAL, ord("\\"))
+}
+
+CATEGORIES = {
+    r"\A": (AT, AT_BEGINNING_STRING), # start of string
+    r"\b": (AT, AT_BOUNDARY),
+    r"\B": (AT, AT_NON_BOUNDARY),
+    r"\d": (IN, [(CATEGORY, CATEGORY_DIGIT)]),
+    r"\D": (IN, [(CATEGORY, CATEGORY_NOT_DIGIT)]),
+    r"\s": (IN, [(CATEGORY, CATEGORY_SPACE)]),
+    r"\S": (IN, [(CATEGORY, CATEGORY_NOT_SPACE)]),
+    r"\w": (IN, [(CATEGORY, CATEGORY_WORD)]),
+    r"\W": (IN, [(CATEGORY, CATEGORY_NOT_WORD)]),
+    r"\Z": (AT, AT_END_STRING), # end of string
+}
+
+FLAGS = {
+    # standard flags
+    "i": SRE_FLAG_IGNORECASE,
+    "L": SRE_FLAG_LOCALE,
+    "m": SRE_FLAG_MULTILINE,
+    "s": SRE_FLAG_DOTALL,
+    "x": SRE_FLAG_VERBOSE,
+    # extensions
+    "t": SRE_FLAG_TEMPLATE,
+    "u": SRE_FLAG_UNICODE,
+}
+
+class Pattern:
+    # master pattern object.  keeps track of global attributes
+    def __init__(self):
+        self.flags = 0
+        self.open = []
+        self.groups = 1
+        self.groupdict = {}
+    def opengroup(self, name=None):
+        gid = self.groups
+        self.groups = gid + 1
+        if name is not None:
+            ogid = self.groupdict.get(name, None)
+            if ogid is not None:
+                raise error, ("redefinition of group name %s as group %d; "
+                              "was group %d" % (repr(name), gid,  ogid))
+            self.groupdict[name] = gid
+        self.open.append(gid)
+        return gid
+    def closegroup(self, gid):
+        self.open.remove(gid)
+    def checkgroup(self, gid):
+        return gid < self.groups and gid not in self.open
+
+class SubPattern:
+    # a subpattern, in intermediate form
+    def __init__(self, pattern, data=None):
+        self.pattern = pattern
+        if data is None:
+            data = []
+        self.data = data
+        self.width = None
+    def dump(self, level=0):
+        nl = 1
+        seqtypes = type(()), type([])
+        for op, av in self.data:
+            print level*"  " + op,; nl = 0
+            if op == "in":
+                # member sublanguage
+                print; nl = 1
+                for op, a in av:
+                    print (level+1)*"  " + op, a
+            elif op == "branch":
+                print; nl = 1
+                i = 0
+                for a in av[1]:
+                    if i > 0:
+                        print level*"  " + "or"
+                    a.dump(level+1); nl = 1
+                    i = i + 1
+            elif type(av) in seqtypes:
+                for a in av:
+                    if isinstance(a, SubPattern):
+                        if not nl: print
+                        a.dump(level+1); nl = 1
+                    else:
+                        print a, ; nl = 0
+            else:
+                print av, ; nl = 0
+            if not nl: print
+    def __repr__(self):
+        return repr(self.data)
+    def __len__(self):
+        return len(self.data)
+    def __delitem__(self, index):
+        del self.data[index]
+    def __getitem__(self, index):
+        if isinstance(index, slice):
+            return SubPattern(self.pattern, self.data[index])
+        return self.data[index]
+    def __setitem__(self, index, code):
+        self.data[index] = code
+    def insert(self, index, code):
+        self.data.insert(index, code)
+    def append(self, code):
+        self.data.append(code)
+    def getwidth(self):
+        # determine the width (min, max) for this subpattern
+        if self.width:
+            return self.width
+        lo = hi = 0L
+        UNITCODES = (ANY, RANGE, IN, LITERAL, NOT_LITERAL, CATEGORY)
+        REPEATCODES = (MIN_REPEAT, MAX_REPEAT)
+        for op, av in self.data:
+            if op is BRANCH:
+                i = sys.maxint
+                j = 0
+                for av in av[1]:
+                    l, h = av.getwidth()
+                    i = min(i, l)
+                    j = max(j, h)
+                lo = lo + i
+                hi = hi + j
+            elif op is CALL:
+                i, j = av.getwidth()
+                lo = lo + i
+                hi = hi + j
+            elif op is SUBPATTERN:
+                i, j = av[1].getwidth()
+                lo = lo + i
+                hi = hi + j
+            elif op in REPEATCODES:
+                i, j = av[2].getwidth()
+                lo = lo + long(i) * av[0]
+                hi = hi + long(j) * av[1]
+            elif op in UNITCODES:
+                lo = lo + 1
+                hi = hi + 1
+            elif op == SUCCESS:
+                break
+        self.width = int(min(lo, sys.maxint)), int(min(hi, sys.maxint))
+        return self.width
+
+class Tokenizer:
+    def __init__(self, string):
+        self.string = string
+        self.index = 0
+        self.__next()
+    def __next(self):
+        if self.index >= len(self.string):
+            self.next = None
+            return
+        char = self.string[self.index]
+        if char[0] == "\\":
+            try:
+                c = self.string[self.index + 1]
+            except IndexError:
+                raise error, "bogus escape (end of line)"
+            char = char + c
+        self.index = self.index + len(char)
+        self.next = char
+    def match(self, char, skip=1):
+        if char == self.next:
+            if skip:
+                self.__next()
+            return 1
+        return 0
+    def get(self):
+        this = self.next
+        self.__next()
+        return this
+    def tell(self):
+        return self.index, self.next
+    def seek(self, index):
+        self.index, self.next = index
+
+def isident(char):
+    return "a" <= char <= "z" or "A" <= char <= "Z" or char == "_"
+
+def isdigit(char):
+    return "0" <= char <= "9"
+
+def isname(name):
+    # check that group name is a valid string
+    if not isident(name[0]):
+        return False
+    for char in name[1:]:
+        if not isident(char) and not isdigit(char):
+            return False
+    return True
+
+def _class_escape(source, escape):
+    # handle escape code inside character class
+    code = ESCAPES.get(escape)
+    if code:
+        return code
+    code = CATEGORIES.get(escape)
+    if code and code[0] == IN:
+        return code
+    try:
+        c = escape[1:2]
+        if c == "x":
+            # hexadecimal escape (exactly two digits)
+            while source.next in HEXDIGITS and len(escape) < 4:
+                escape = escape + source.get()
+            escape = escape[2:]
+            if len(escape) != 2:
+                raise error, "bogus escape: %s" % repr("\\" + escape)
+            return LITERAL, int(escape, 16) & 0xff
+        elif c in OCTDIGITS:
+            # octal escape (up to three digits)
+            while source.next in OCTDIGITS and len(escape) < 4:
+                escape = escape + source.get()
+            escape = escape[1:]
+            return LITERAL, int(escape, 8) & 0xff
+        elif c in DIGITS:
+            raise error, "bogus escape: %s" % repr(escape)
+        if len(escape) == 2:
+            return LITERAL, ord(escape[1])
+    except ValueError:
+        pass
+    raise error, "bogus escape: %s" % repr(escape)
+
+def _escape(source, escape, state):
+    # handle escape code in expression
+    code = CATEGORIES.get(escape)
+    if code:
+        return code
+    code = ESCAPES.get(escape)
+    if code:
+        return code
+    try:
+        c = escape[1:2]
+        if c == "x":
+            # hexadecimal escape
+            while source.next in HEXDIGITS and len(escape) < 4:
+                escape = escape + source.get()
+            if len(escape) != 4:
+                raise ValueError
+            return LITERAL, int(escape[2:], 16) & 0xff
+        elif c == "0":
+            # octal escape
+            while source.next in OCTDIGITS and len(escape) < 4:
+                escape = escape + source.get()
+            return LITERAL, int(escape[1:], 8) & 0xff
+        elif c in DIGITS:
+            # octal escape *or* decimal group reference (sigh)
+            if source.next in DIGITS:
+                escape = escape + source.get()
+                if (escape[1] in OCTDIGITS and escape[2] in OCTDIGITS and
+                    source.next in OCTDIGITS):
+                    # got three octal digits; this is an octal escape
+                    escape = escape + source.get()
+                    return LITERAL, int(escape[1:], 8) & 0xff
+            # not an octal escape, so this is a group reference
+            group = int(escape[1:])
+            if group < state.groups:
+                if not state.checkgroup(group):
+                    raise error, "cannot refer to open group"
+                return GROUPREF, group
+            raise ValueError
+        if len(escape) == 2:
+            return LITERAL, ord(escape[1])
+    except ValueError:
+        pass
+    raise error, "bogus escape: %s" % repr(escape)
+
+def _parse_sub(source, state, nested=1):
+    # parse an alternation: a|b|c
+
+    items = []
+    itemsappend = items.append
+    sourcematch = source.match
+    while 1:
+        itemsappend(_parse(source, state))
+        if sourcematch("|"):
+            continue
+        if not nested:
+            break
+        if not source.next or sourcematch(")", 0):
+            break
+        else:
+            raise error, "pattern not properly closed"
+
+    if len(items) == 1:
+        return items[0]
+
+    subpattern = SubPattern(state)
+    subpatternappend = subpattern.append
+
+    # check if all items share a common prefix
+    while 1:
+        prefix = None
+        for item in items:
+            if not item:
+                break
+            if prefix is None:
+                prefix = item[0]
+            elif item[0] != prefix:
+                break
+        else:
+            # all subitems start with a common "prefix".
+            # move it out of the branch
+            for item in items:
+                del item[0]
+            subpatternappend(prefix)
+            continue # check next one
+        break
+
+    # check if the branch can be replaced by a character set
+    for item in items:
+        if len(item) != 1 or item[0][0] != LITERAL:
+            break
+    else:
+        # we can store this as a character set instead of a
+        # branch (the compiler may optimize this even more)
+        set = []
+        setappend = set.append
+        for item in items:
+            setappend(item[0])
+        subpatternappend((IN, set))
+        return subpattern
+
+    subpattern.append((BRANCH, (None, items)))
+    return subpattern
+
+def _parse_sub_cond(source, state, condgroup):
+    item_yes = _parse(source, state)
+    if source.match("|"):
+        item_no = _parse(source, state)
+        if source.match("|"):
+            raise error, "conditional backref with more than two branches"
+    else:
+        item_no = None
+    if source.next and not source.match(")", 0):
+        raise error, "pattern not properly closed"
+    subpattern = SubPattern(state)
+    subpattern.append((GROUPREF_EXISTS, (condgroup, item_yes, item_no)))
+    return subpattern
+
+_PATTERNENDERS = set("|)")
+_ASSERTCHARS = set("=!<")
+_LOOKBEHINDASSERTCHARS = set("=!")
+_REPEATCODES = set([MIN_REPEAT, MAX_REPEAT])
+
+def _parse(source, state):
+    # parse a simple pattern
+    subpattern = SubPattern(state)
+
+    # precompute constants into local variables
+    subpatternappend = subpattern.append
+    sourceget = source.get
+    sourcematch = source.match
+    _len = len
+    PATTERNENDERS = _PATTERNENDERS
+    ASSERTCHARS = _ASSERTCHARS
+    LOOKBEHINDASSERTCHARS = _LOOKBEHINDASSERTCHARS
+    REPEATCODES = _REPEATCODES
+
+    while 1:
+
+        if source.next in PATTERNENDERS:
+            break # end of subpattern
+        this = sourceget()
+        if this is None:
+            break # end of pattern
+
+        if state.flags & SRE_FLAG_VERBOSE:
+            # skip whitespace and comments
+            if this in WHITESPACE:
+                continue
+            if this == "#":
+                while 1:
+                    this = sourceget()
+                    if this in (None, "\n"):
+                        break
+                continue
+
+        if this and this[0] not in SPECIAL_CHARS:
+            subpatternappend((LITERAL, ord(this)))
+
+        elif this == "[":
+            # character set
+            set = []
+            setappend = set.append
+##          if sourcematch(":"):
+##              pass # handle character classes
+            if sourcematch("^"):
+                setappend((NEGATE, None))
+            # check remaining characters
+            start = set[:]
+            while 1:
+                this = sourceget()
+                if this == "]" and set != start:
+                    break
+                elif this and this[0] == "\\":
+                    code1 = _class_escape(source, this)
+                elif this:
+                    code1 = LITERAL, ord(this)
+                else:
+                    raise error, "unexpected end of regular expression"
+                if sourcematch("-"):
+                    # potential range
+                    this = sourceget()
+                    if this == "]":
+                        if code1[0] is IN:
+                            code1 = code1[1][0]
+                        setappend(code1)
+                        setappend((LITERAL, ord("-")))
+                        break
+                    elif this:
+                        if this[0] == "\\":
+                            code2 = _class_escape(source, this)
+                        else:
+                            code2 = LITERAL, ord(this)
+                        if code1[0] != LITERAL or code2[0] != LITERAL:
+                            raise error, "bad character range"
+                        lo = code1[1]
+                        hi = code2[1]
+                        if hi < lo:
+                            raise error, "bad character range"
+                        setappend((RANGE, (lo, hi)))
+                    else:
+                        raise error, "unexpected end of regular expression"
+                else:
+                    if code1[0] is IN:
+                        code1 = code1[1][0]
+                    setappend(code1)
+
+            # XXX: <fl> should move set optimization to compiler!
+            if _len(set)==1 and set[0][0] is LITERAL:
+                subpatternappend(set[0]) # optimization
+            elif _len(set)==2 and set[0][0] is NEGATE and set[1][0] is LITERAL:
+                subpatternappend((NOT_LITERAL, set[1][1])) # optimization
+            else:
+                # XXX: <fl> should add charmap optimization here
+                subpatternappend((IN, set))
+
+        elif this and this[0] in REPEAT_CHARS:
+            # repeat previous item
+            if this == "?":
+                min, max = 0, 1
+            elif this == "*":
+                min, max = 0, MAXREPEAT
+
+            elif this == "+":
+                min, max = 1, MAXREPEAT
+            elif this == "{":
+                if source.next == "}":
+                    subpatternappend((LITERAL, ord(this)))
+                    continue
+                here = source.tell()
+                min, max = 0, MAXREPEAT
+                lo = hi = ""
+                while source.next in DIGITS:
+                    lo = lo + source.get()
+                if sourcematch(","):
+                    while source.next in DIGITS:
+                        hi = hi + sourceget()
+                else:
+                    hi = lo
+                if not sourcematch("}"):
+                    subpatternappend((LITERAL, ord(this)))
+                    source.seek(here)
+                    continue
+                if lo:
+                    min = int(lo)
+                    if min >= MAXREPEAT:
+                        raise OverflowError("the repetition number is too large")
+                if hi:
+                    max = int(hi)
+                    if max >= MAXREPEAT:
+                        raise OverflowError("the repetition number is too large")
+                    if max < min:
+                        raise error("bad repeat interval")
+            else:
+                raise error, "not supported"
+            # figure out which item to repeat
+            if subpattern:
+                item = subpattern[-1:]
+            else:
+                item = None
+            if not item or (_len(item) == 1 and item[0][0] == AT):
+                raise error, "nothing to repeat"
+            if item[0][0] in REPEATCODES:
+                raise error, "multiple repeat"
+            if sourcematch("?"):
+                subpattern[-1] = (MIN_REPEAT, (min, max, item))
+            else:
+                subpattern[-1] = (MAX_REPEAT, (min, max, item))
+
+        elif this == ".":
+            subpatternappend((ANY, None))
+
+        elif this == "(":
+            group = 1
+            name = None
+            condgroup = None
+            if sourcematch("?"):
+                group = 0
+                # options
+                if sourcematch("P"):
+                    # python extensions
+                    if sourcematch("<"):
+                        # named group: skip forward to end of name
+                        name = ""
+                        while 1:
+                            char = sourceget()
+                            if char is None:
+                                raise error, "unterminated name"
+                            if char == ">":
+                                break
+                            name = name + char
+                        group = 1
+                        if not name:
+                            raise error("missing group name")
+                        if not isname(name):
+                            raise error, "bad character in group name"
+                    elif sourcematch("="):
+                        # named backreference
+                        name = ""
+                        while 1:
+                            char = sourceget()
+                            if char is None:
+                                raise error, "unterminated name"
+                            if char == ")":
+                                break
+                            name = name + char
+                        if not name:
+                            raise error("missing group name")
+                        if not isname(name):
+                            raise error, "bad character in group name"
+                        gid = state.groupdict.get(name)
+                        if gid is None:
+                            raise error, "unknown group name"
+                        subpatternappend((GROUPREF, gid))
+                        continue
+                    else:
+                        char = sourceget()
+                        if char is None:
+                            raise error, "unexpected end of pattern"
+                        raise error, "unknown specifier: ?P%s" % char
+                elif sourcematch(":"):
+                    # non-capturing group
+                    group = 2
+                elif sourcematch("#"):
+                    # comment
+                    while 1:
+                        if source.next is None or source.next == ")":
+                            break
+                        sourceget()
+                    if not sourcematch(")"):
+                        raise error, "unbalanced parenthesis"
+                    continue
+                elif source.next in ASSERTCHARS:
+                    # lookahead assertions
+                    char = sourceget()
+                    dir = 1
+                    if char == "<":
+                        if source.next not in LOOKBEHINDASSERTCHARS:
+                            raise error, "syntax error"
+                        dir = -1 # lookbehind
+                        char = sourceget()
+                    p = _parse_sub(source, state)
+                    if not sourcematch(")"):
+                        raise error, "unbalanced parenthesis"
+                    if char == "=":
+                        subpatternappend((ASSERT, (dir, p)))
+                    else:
+                        subpatternappend((ASSERT_NOT, (dir, p)))
+                    continue
+                elif sourcematch("("):
+                    # conditional backreference group
+                    condname = ""
+                    while 1:
+                        char = sourceget()
+                        if char is None:
+                            raise error, "unterminated name"
+                        if char == ")":
+                            break
+                        condname = condname + char
+                    group = 2
+                    if not condname:
+                        raise error("missing group name")
+                    if isname(condname):
+                        condgroup = state.groupdict.get(condname)
+                        if condgroup is None:
+                            raise error, "unknown group name"
+                    else:
+                        try:
+                            condgroup = int(condname)
+                        except ValueError:
+                            raise error, "bad character in group name"
+                else:
+                    # flags
+                    if not source.next in FLAGS:
+                        raise error, "unexpected end of pattern"
+                    while source.next in FLAGS:
+                        state.flags = state.flags | FLAGS[sourceget()]
+            if group:
+                # parse group contents
+                if group == 2:
+                    # anonymous group
+                    group = None
+                else:
+                    group = state.opengroup(name)
+                if condgroup:
+                    p = _parse_sub_cond(source, state, condgroup)
+                else:
+                    p = _parse_sub(source, state)
+                if not sourcematch(")"):
+                    raise error, "unbalanced parenthesis"
+                if group is not None:
+                    state.closegroup(group)
+                subpatternappend((SUBPATTERN, (group, p)))
+            else:
+                while 1:
+                    char = sourceget()
+                    if char is None:
+                        raise error, "unexpected end of pattern"
+                    if char == ")":
+                        break
+                    raise error, "unknown extension"
+
+        elif this == "^":
+            subpatternappend((AT, AT_BEGINNING))
+
+        elif this == "$":
+            subpattern.append((AT, AT_END))
+
+        elif this and this[0] == "\\":
+            code = _escape(source, this, state)
+            subpatternappend(code)
+
+        else:
+            raise error, "parser error"
+
+    return subpattern
+
+def parse(str, flags=0, pattern=None):
+    # parse 're' pattern into list of (opcode, argument) tuples
+
+    source = Tokenizer(str)
+
+    if pattern is None:
+        pattern = Pattern()
+    pattern.flags = flags
+    pattern.str = str
+
+    p = _parse_sub(source, pattern, 0)
+
+    tail = source.get()
+    if tail == ")":
+        raise error, "unbalanced parenthesis"
+    elif tail:
+        raise error, "bogus characters at end of regular expression"
+
+    if flags & SRE_FLAG_DEBUG:
+        p.dump()
+
+    if not (flags & SRE_FLAG_VERBOSE) and p.pattern.flags & SRE_FLAG_VERBOSE:
+        # the VERBOSE flag was switched on inside the pattern.  to be
+        # on the safe side, we'll parse the whole thing again...
+        return parse(str, p.pattern.flags)
+
+    return p
+
+def parse_template(source, pattern):
+    # parse 're' replacement string into list of literals and
+    # group references
+    s = Tokenizer(source)
+    sget = s.get
+    p = []
+    a = p.append
+    def literal(literal, p=p, pappend=a):
+        if p and p[-1][0] is LITERAL:
+            p[-1] = LITERAL, p[-1][1] + literal
+        else:
+            pappend((LITERAL, literal))
+    sep = source[:0]
+    if type(sep) is type(""):
+        makechar = chr
+    else:
+        makechar = unichr
+    while 1:
+        this = sget()
+        if this is None:
+            break # end of replacement string
+        if this and this[0] == "\\":
+            # group
+            c = this[1:2]
+            if c == "g":
+                name = ""
+                if s.match("<"):
+                    while 1:
+                        char = sget()
+                        if char is None:
+                            raise error, "unterminated group name"
+                        if char == ">":
+                            break
+                        name = name + char
+                if not name:
+                    raise error, "missing group name"
+                try:
+                    index = int(name)
+                    if index < 0:
+                        raise error, "negative group number"
+                except ValueError:
+                    if not isname(name):
+                        raise error, "bad character in group name"
+                    try:
+                        index = pattern.groupindex[name]
+                    except KeyError:
+                        raise IndexError, "unknown group name"
+                a((MARK, index))
+            elif c == "0":
+                if s.next in OCTDIGITS:
+                    this = this + sget()
+                    if s.next in OCTDIGITS:
+                        this = this + sget()
+                literal(makechar(int(this[1:], 8) & 0xff))
+            elif c in DIGITS:
+                isoctal = False
+                if s.next in DIGITS:
+                    this = this + sget()
+                    if (c in OCTDIGITS and this[2] in OCTDIGITS and
+                        s.next in OCTDIGITS):
+                        this = this + sget()
+                        isoctal = True
+                        literal(makechar(int(this[1:], 8) & 0xff))
+                if not isoctal:
+                    a((MARK, int(this[1:])))
+            else:
+                try:
+                    this = makechar(ESCAPES[this][1])
+                except KeyError:
+                    pass
+                literal(this)
+        else:
+            literal(this)
+    # convert template to groups and literals lists
+    i = 0
+    groups = []
+    groupsappend = groups.append
+    literals = [None] * len(p)
+    for c, s in p:
+        if c is MARK:
+            groupsappend((i, s))
+            # literal[i] is already None
+        else:
+            literals[i] = s
+        i = i + 1
+    return groups, literals
+
+def expand_template(template, match):
+    g = match.group
+    sep = match.string[:0]
+    groups, literals = template
+    literals = literals[:]
+    try:
+        for index, group in groups:
+            literals[index] = s = g(group)
+            if s is None:
+                raise error, "unmatched group"
+    except IndexError:
+        raise error, "invalid group reference"
+    return sep.join(literals)
diff --git a/src/main/resources/PythonLibs/ssl.py b/src/main/resources/PythonLibs/ssl.py
new file mode 100644
index 0000000000000000000000000000000000000000..f4dce4dfe289ef136a16a4984872c034cc359d6c
--- /dev/null
+++ b/src/main/resources/PythonLibs/ssl.py
@@ -0,0 +1,10 @@
+"""
+This module provides very limited support for the SSL module on jython.
+
+See the jython wiki for more information.
+http://wiki.python.org/jython/SSLModule
+"""
+
+import socket
+
+wrap_socket = socket.ssl
diff --git a/src/main/resources/PythonLibs/stat.py b/src/main/resources/PythonLibs/stat.py
new file mode 100644
index 0000000000000000000000000000000000000000..abed5c9e0f57a118ee58aef158cf3c455d9821ec
--- /dev/null
+++ b/src/main/resources/PythonLibs/stat.py
@@ -0,0 +1,96 @@
+"""Constants/functions for interpreting results of os.stat() and os.lstat().
+
+Suggested usage: from stat import *
+"""
+
+# Indices for stat struct members in the tuple returned by os.stat()
+
+ST_MODE  = 0
+ST_INO   = 1
+ST_DEV   = 2
+ST_NLINK = 3
+ST_UID   = 4
+ST_GID   = 5
+ST_SIZE  = 6
+ST_ATIME = 7
+ST_MTIME = 8
+ST_CTIME = 9
+
+# Extract bits from the mode
+
+def S_IMODE(mode):
+    return mode & 07777
+
+def S_IFMT(mode):
+    return mode & 0170000
+
+# Constants used as S_IFMT() for various file types
+# (not all are implemented on all systems)
+
+S_IFDIR  = 0040000
+S_IFCHR  = 0020000
+S_IFBLK  = 0060000
+S_IFREG  = 0100000
+S_IFIFO  = 0010000
+S_IFLNK  = 0120000
+S_IFSOCK = 0140000
+
+# Functions to test for each file type
+
+def S_ISDIR(mode):
+    return S_IFMT(mode) == S_IFDIR
+
+def S_ISCHR(mode):
+    return S_IFMT(mode) == S_IFCHR
+
+def S_ISBLK(mode):
+    return S_IFMT(mode) == S_IFBLK
+
+def S_ISREG(mode):
+    return S_IFMT(mode) == S_IFREG
+
+def S_ISFIFO(mode):
+    return S_IFMT(mode) == S_IFIFO
+
+def S_ISLNK(mode):
+    return S_IFMT(mode) == S_IFLNK
+
+def S_ISSOCK(mode):
+    return S_IFMT(mode) == S_IFSOCK
+
+# Names for permission bits
+
+S_ISUID = 04000
+S_ISGID = 02000
+S_ENFMT = S_ISGID
+S_ISVTX = 01000
+S_IREAD = 00400
+S_IWRITE = 00200
+S_IEXEC = 00100
+S_IRWXU = 00700
+S_IRUSR = 00400
+S_IWUSR = 00200
+S_IXUSR = 00100
+S_IRWXG = 00070
+S_IRGRP = 00040
+S_IWGRP = 00020
+S_IXGRP = 00010
+S_IRWXO = 00007
+S_IROTH = 00004
+S_IWOTH = 00002
+S_IXOTH = 00001
+
+# Names for file flags
+
+UF_NODUMP    = 0x00000001
+UF_IMMUTABLE = 0x00000002
+UF_APPEND    = 0x00000004
+UF_OPAQUE    = 0x00000008
+UF_NOUNLINK  = 0x00000010
+UF_COMPRESSED = 0x00000020  # OS X: file is hfs-compressed
+UF_HIDDEN    = 0x00008000   # OS X: file should not be displayed
+SF_ARCHIVED  = 0x00010000
+SF_IMMUTABLE = 0x00020000
+SF_APPEND    = 0x00040000
+SF_NOUNLINK  = 0x00100000
+SF_SNAPSHOT  = 0x00200000
diff --git a/src/main/resources/PythonLibs/string.py b/src/main/resources/PythonLibs/string.py
new file mode 100644
index 0000000000000000000000000000000000000000..97278034a0fb8209d9602a682885ece73024f0be
--- /dev/null
+++ b/src/main/resources/PythonLibs/string.py
@@ -0,0 +1,642 @@
+"""A collection of string operations (most are no longer used).
+
+Warning: most of the code you see here isn't normally used nowadays.
+Beginning with Python 1.6, many of these functions are implemented as
+methods on the standard string object. They used to be implemented by
+a built-in module called strop, but strop is now obsolete itself.
+
+Public module variables:
+
+whitespace -- a string containing all characters considered whitespace
+lowercase -- a string containing all characters considered lowercase letters
+uppercase -- a string containing all characters considered uppercase letters
+letters -- a string containing all characters considered letters
+digits -- a string containing all characters considered decimal digits
+hexdigits -- a string containing all characters considered hexadecimal digits
+octdigits -- a string containing all characters considered octal digits
+punctuation -- a string containing all characters considered punctuation
+printable -- a string containing all characters considered printable
+
+"""
+
+# Some strings for ctype-style character classification
+whitespace = ' \t\n\r\v\f'
+lowercase = 'abcdefghijklmnopqrstuvwxyz'
+uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+letters = lowercase + uppercase
+ascii_lowercase = lowercase
+ascii_uppercase = uppercase
+ascii_letters = ascii_lowercase + ascii_uppercase
+digits = '0123456789'
+hexdigits = digits + 'abcdef' + 'ABCDEF'
+octdigits = '01234567'
+punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
+printable = digits + letters + punctuation + whitespace
+
+# Case conversion helpers
+# Use str to convert Unicode literal in case of -U
+l = map(chr, xrange(256))
+_idmap = str('').join(l)
+del l
+
+# Functions which aren't available as string methods.
+
+# Capitalize the words in a string, e.g. " aBc  dEf " -> "Abc Def".
+def capwords(s, sep=None):
+    """capwords(s [,sep]) -> string
+
+    Split the argument into words using split, capitalize each
+    word using capitalize, and join the capitalized words using
+    join.  If the optional second argument sep is absent or None,
+    runs of whitespace characters are replaced by a single space
+    and leading and trailing whitespace are removed, otherwise
+    sep is used to split and join the words.
+
+    """
+    return (sep or ' ').join(x.capitalize() for x in s.split(sep))
+
+
+# Construct a translation string
+_idmapL = None
+def maketrans(fromstr, tostr):
+    """maketrans(frm, to) -> string
+
+    Return a translation table (a string of 256 bytes long)
+    suitable for use in string.translate.  The strings frm and to
+    must be of the same length.
+
+    """
+    if len(fromstr) != len(tostr):
+        raise ValueError, "maketrans arguments must have same length"
+    global _idmapL
+    if not _idmapL:
+        _idmapL = list(_idmap)
+    L = _idmapL[:]
+    fromstr = map(ord, fromstr)
+    for i in range(len(fromstr)):
+        L[fromstr[i]] = tostr[i]
+    return ''.join(L)
+
+
+
+####################################################################
+import re as _re
+
+class _multimap:
+    """Helper class for combining multiple mappings.
+
+    Used by .{safe_,}substitute() to combine the mapping and keyword
+    arguments.
+    """
+    def __init__(self, primary, secondary):
+        self._primary = primary
+        self._secondary = secondary
+
+    def __getitem__(self, key):
+        try:
+            return self._primary[key]
+        except KeyError:
+            return self._secondary[key]
+
+
+class _TemplateMetaclass(type):
+    pattern = r"""
+    %(delim)s(?:
+      (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
+      (?P<named>%(id)s)      |   # delimiter and a Python identifier
+      {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
+      (?P<invalid>)              # Other ill-formed delimiter exprs
+    )
+    """
+
+    def __init__(cls, name, bases, dct):
+        super(_TemplateMetaclass, cls).__init__(name, bases, dct)
+        if 'pattern' in dct:
+            pattern = cls.pattern
+        else:
+            pattern = _TemplateMetaclass.pattern % {
+                'delim' : _re.escape(cls.delimiter),
+                'id'    : cls.idpattern,
+                }
+        cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
+
+
+class Template:
+    """A string class for supporting $-substitutions."""
+    __metaclass__ = _TemplateMetaclass
+
+    delimiter = '$'
+    idpattern = r'[_a-z][_a-z0-9]*'
+
+    def __init__(self, template):
+        self.template = template
+
+    # Search for $$, $identifier, ${identifier}, and any bare $'s
+
+    def _invalid(self, mo):
+        i = mo.start('invalid')
+        lines = self.template[:i].splitlines(True)
+        if not lines:
+            colno = 1
+            lineno = 1
+        else:
+            colno = i - len(''.join(lines[:-1]))
+            lineno = len(lines)
+        raise ValueError('Invalid placeholder in string: line %d, col %d' %
+                         (lineno, colno))
+
+    def substitute(self, *args, **kws):
+        if len(args) > 1:
+            raise TypeError('Too many positional arguments')
+        if not args:
+            mapping = kws
+        elif kws:
+            mapping = _multimap(kws, args[0])
+        else:
+            mapping = args[0]
+        # Helper function for .sub()
+        def convert(mo):
+            # Check the most common path first.
+            named = mo.group('named') or mo.group('braced')
+            if named is not None:
+                val = mapping[named]
+                # We use this idiom instead of str() because the latter will
+                # fail if val is a Unicode containing non-ASCII characters.
+                return '%s' % (val,)
+            if mo.group('escaped') is not None:
+                return self.delimiter
+            if mo.group('invalid') is not None:
+                self._invalid(mo)
+            raise ValueError('Unrecognized named group in pattern',
+                             self.pattern)
+        return self.pattern.sub(convert, self.template)
+
+    def safe_substitute(self, *args, **kws):
+        if len(args) > 1:
+            raise TypeError('Too many positional arguments')
+        if not args:
+            mapping = kws
+        elif kws:
+            mapping = _multimap(kws, args[0])
+        else:
+            mapping = args[0]
+        # Helper function for .sub()
+        def convert(mo):
+            named = mo.group('named')
+            if named is not None:
+                try:
+                    # We use this idiom instead of str() because the latter
+                    # will fail if val is a Unicode containing non-ASCII
+                    return '%s' % (mapping[named],)
+                except KeyError:
+                    return self.delimiter + named
+            braced = mo.group('braced')
+            if braced is not None:
+                try:
+                    return '%s' % (mapping[braced],)
+                except KeyError:
+                    return self.delimiter + '{' + braced + '}'
+            if mo.group('escaped') is not None:
+                return self.delimiter
+            if mo.group('invalid') is not None:
+                return self.delimiter
+            raise ValueError('Unrecognized named group in pattern',
+                             self.pattern)
+        return self.pattern.sub(convert, self.template)
+
+
+
+####################################################################
+# NOTE: Everything below here is deprecated.  Use string methods instead.
+# This stuff will go away in Python 3.0.
+
+# Backward compatible names for exceptions
+index_error = ValueError
+atoi_error = ValueError
+atof_error = ValueError
+atol_error = ValueError
+
+# convert UPPER CASE letters to lower case
+def lower(s):
+    """lower(s) -> string
+
+    Return a copy of the string s converted to lowercase.
+
+    """
+    return s.lower()
+
+# Convert lower case letters to UPPER CASE
+def upper(s):
+    """upper(s) -> string
+
+    Return a copy of the string s converted to uppercase.
+
+    """
+    return s.upper()
+
+# Swap lower case letters and UPPER CASE
+def swapcase(s):
+    """swapcase(s) -> string
+
+    Return a copy of the string s with upper case characters
+    converted to lowercase and vice versa.
+
+    """
+    return s.swapcase()
+
+# Strip leading and trailing tabs and spaces
+def strip(s, chars=None):
+    """strip(s [,chars]) -> string
+
+    Return a copy of the string s with leading and trailing
+    whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+    If chars is unicode, S will be converted to unicode before stripping.
+
+    """
+    return s.strip(chars)
+
+# Strip leading tabs and spaces
+def lstrip(s, chars=None):
+    """lstrip(s [,chars]) -> string
+
+    Return a copy of the string s with leading whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+
+    """
+    return s.lstrip(chars)
+
+# Strip trailing tabs and spaces
+def rstrip(s, chars=None):
+    """rstrip(s [,chars]) -> string
+
+    Return a copy of the string s with trailing whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+
+    """
+    return s.rstrip(chars)
+
+
+# Split a string into a list of space/tab-separated words
+def split(s, sep=None, maxsplit=-1):
+    """split(s [,sep [,maxsplit]]) -> list of strings
+
+    Return a list of the words in the string s, using sep as the
+    delimiter string.  If maxsplit is given, splits at no more than
+    maxsplit places (resulting in at most maxsplit+1 words).  If sep
+    is not specified or is None, any whitespace string is a separator.
+
+    (split and splitfields are synonymous)
+
+    """
+    return s.split(sep, maxsplit)
+splitfields = split
+
+# Split a string into a list of space/tab-separated words
+def rsplit(s, sep=None, maxsplit=-1):
+    """rsplit(s [,sep [,maxsplit]]) -> list of strings
+
+    Return a list of the words in the string s, using sep as the
+    delimiter string, starting at the end of the string and working
+    to the front.  If maxsplit is given, at most maxsplit splits are
+    done. If sep is not specified or is None, any whitespace string
+    is a separator.
+    """
+    return s.rsplit(sep, maxsplit)
+
+# Join fields with optional separator
+def join(words, sep = ' '):
+    """join(list [,sep]) -> string
+
+    Return a string composed of the words in list, with
+    intervening occurrences of sep.  The default separator is a
+    single space.
+
+    (joinfields and join are synonymous)
+
+    """
+    return sep.join(words)
+joinfields = join
+
+# Find substring, raise exception if not found
+def index(s, *args):
+    """index(s, sub [,start [,end]]) -> int
+
+    Like find but raises ValueError when the substring is not found.
+
+    """
+    return s.index(*args)
+
+# Find last substring, raise exception if not found
+def rindex(s, *args):
+    """rindex(s, sub [,start [,end]]) -> int
+
+    Like rfind but raises ValueError when the substring is not found.
+
+    """
+    return s.rindex(*args)
+
+# Count non-overlapping occurrences of substring
+def count(s, *args):
+    """count(s, sub[, start[,end]]) -> int
+
+    Return the number of occurrences of substring sub in string
+    s[start:end].  Optional arguments start and end are
+    interpreted as in slice notation.
+
+    """
+    return s.count(*args)
+
+# Find substring, return -1 if not found
+def find(s, *args):
+    """find(s, sub [,start [,end]]) -> in
+
+    Return the lowest index in s where substring sub is found,
+    such that sub is contained within s[start,end].  Optional
+    arguments start and end are interpreted as in slice notation.
+
+    Return -1 on failure.
+
+    """
+    return s.find(*args)
+
+# Find last substring, return -1 if not found
+def rfind(s, *args):
+    """rfind(s, sub [,start [,end]]) -> int
+
+    Return the highest index in s where substring sub is found,
+    such that sub is contained within s[start,end].  Optional
+    arguments start and end are interpreted as in slice notation.
+
+    Return -1 on failure.
+
+    """
+    return s.rfind(*args)
+
+# for a bit of speed
+_float = float
+_int = int
+_long = long
+
+# Convert string to float
+def atof(s):
+    """atof(s) -> float
+
+    Return the floating point number represented by the string s.
+
+    """
+    return _float(s)
+
+
+# Convert string to integer
+def atoi(s , base=10):
+    """atoi(s [,base]) -> int
+
+    Return the integer represented by the string s in the given
+    base, which defaults to 10.  The string s must consist of one
+    or more digits, possibly preceded by a sign.  If base is 0, it
+    is chosen from the leading characters of s, 0 for octal, 0x or
+    0X for hexadecimal.  If base is 16, a preceding 0x or 0X is
+    accepted.
+
+    """
+    return _int(s, base)
+
+
+# Convert string to long integer
+def atol(s, base=10):
+    """atol(s [,base]) -> long
+
+    Return the long integer represented by the string s in the
+    given base, which defaults to 10.  The string s must consist
+    of one or more digits, possibly preceded by a sign.  If base
+    is 0, it is chosen from the leading characters of s, 0 for
+    octal, 0x or 0X for hexadecimal.  If base is 16, a preceding
+    0x or 0X is accepted.  A trailing L or l is not accepted,
+    unless base is 0.
+
+    """
+    return _long(s, base)
+
+
+# Left-justify a string
+def ljust(s, width, *args):
+    """ljust(s, width[, fillchar]) -> string
+
+    Return a left-justified version of s, in a field of the
+    specified width, padded with spaces as needed.  The string is
+    never truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.ljust(width, *args)
+
+# Right-justify a string
+def rjust(s, width, *args):
+    """rjust(s, width[, fillchar]) -> string
+
+    Return a right-justified version of s, in a field of the
+    specified width, padded with spaces as needed.  The string is
+    never truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.rjust(width, *args)
+
+# Center a string
+def center(s, width, *args):
+    """center(s, width[, fillchar]) -> string
+
+    Return a center version of s, in a field of the specified
+    width. padded with spaces as needed.  The string is never
+    truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.center(width, *args)
+
+# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
+# Decadent feature: the argument may be a string or a number
+# (Use of this is deprecated; it should be a string as with ljust c.s.)
+def zfill(x, width):
+    """zfill(x, width) -> string
+
+    Pad a numeric string x with zeros on the left, to fill a field
+    of the specified width.  The string x is never truncated.
+
+    """
+    if not isinstance(x, basestring):
+        x = repr(x)
+    return x.zfill(width)
+
+# Expand tabs in a string.
+# Doesn't take non-printing chars into account, but does understand \n.
+def expandtabs(s, tabsize=8):
+    """expandtabs(s [,tabsize]) -> string
+
+    Return a copy of the string s with all tab characters replaced
+    by the appropriate number of spaces, depending on the current
+    column, and the tabsize (default 8).
+
+    """
+    return s.expandtabs(tabsize)
+
+# Character translation through look-up table.
+def translate(s, table, deletions=""):
+    """translate(s,table [,deletions]) -> string
+
+    Return a copy of the string s, where all characters occurring
+    in the optional argument deletions are removed, and the
+    remaining characters have been mapped through the given
+    translation table, which must be a string of length 256.  The
+    deletions argument is not allowed for Unicode strings.
+
+    """
+    if deletions or table is None:
+        return s.translate(table, deletions)
+    else:
+        # Add s[:0] so that if s is Unicode and table is an 8-bit string,
+        # table is converted to Unicode.  This means that table *cannot*
+        # be a dictionary -- for that feature, use u.translate() directly.
+        return s.translate(table + s[:0])
+
+# Capitalize a string, e.g. "aBc  dEf" -> "Abc  def".
+def capitalize(s):
+    """capitalize(s) -> string
+
+    Return a copy of the string s with only its first character
+    capitalized.
+
+    """
+    return s.capitalize()
+
+# Substring replacement (global)
+def replace(s, old, new, maxreplace=-1):
+    """replace (str, old, new[, maxreplace]) -> string
+
+    Return a copy of string str with all occurrences of substring
+    old replaced by new. If the optional argument maxreplace is
+    given, only the first maxreplace occurrences are replaced.
+
+    """
+    return s.replace(old, new, maxreplace)
+
+
+# Try importing optional built-in module "strop" -- if it exists,
+# it redefines some string operations that are 100-1000 times faster.
+# It also defines values for whitespace, lowercase and uppercase
+# that match <ctype.h>'s definitions.
+
+try:
+    from strop import maketrans, lowercase, uppercase, whitespace
+    letters = lowercase + uppercase
+except ImportError:
+    pass                                          # Use the original versions
+
+########################################################################
+# the Formatter class
+# see PEP 3101 for details and purpose of this class
+
+# The hard parts are reused from the C implementation.  They're exposed as "_"
+# prefixed methods of str and unicode.
+
+# The overall parser is implemented in str._formatter_parser.
+# The field name parser is implemented in str._formatter_field_name_split
+
+class Formatter(object):
+    def format(self, format_string, *args, **kwargs):
+        return self.vformat(format_string, args, kwargs)
+
+    def vformat(self, format_string, args, kwargs):
+        used_args = set()
+        result = self._vformat(format_string, args, kwargs, used_args, 2)
+        self.check_unused_args(used_args, args, kwargs)
+        return result
+
+    def _vformat(self, format_string, args, kwargs, used_args, recursion_depth):
+        if recursion_depth < 0:
+            raise ValueError('Max string recursion exceeded')
+        result = []
+        for literal_text, field_name, format_spec, conversion in \
+                self.parse(format_string):
+
+            # output the literal text
+            if literal_text:
+                result.append(literal_text)
+
+            # if there's a field, output it
+            if field_name is not None:
+                # this is some markup, find the object and do
+                #  the formatting
+
+                # given the field_name, find the object it references
+                #  and the argument it came from
+                obj, arg_used = self.get_field(field_name, args, kwargs)
+                used_args.add(arg_used)
+
+                # do any conversion on the resulting object
+                obj = self.convert_field(obj, conversion)
+
+                # expand the format spec, if needed
+                format_spec = self._vformat(format_spec, args, kwargs,
+                                            used_args, recursion_depth-1)
+
+                # format the object and append to the result
+                result.append(self.format_field(obj, format_spec))
+
+        return ''.join(result)
+
+
+    def get_value(self, key, args, kwargs):
+        if isinstance(key, (int, long)):
+            return args[key]
+        else:
+            return kwargs[key]
+
+
+    def check_unused_args(self, used_args, args, kwargs):
+        pass
+
+
+    def format_field(self, value, format_spec):
+        return format(value, format_spec)
+
+
+    def convert_field(self, value, conversion):
+        # do any conversion on the resulting object
+        if conversion is None:
+            return value
+        elif conversion == 's':
+            return str(value)
+        elif conversion == 'r':
+            return repr(value)
+        raise ValueError("Unknown conversion specifier {0!s}".format(conversion))
+
+
+    # returns an iterable that contains tuples of the form:
+    # (literal_text, field_name, format_spec, conversion)
+    # literal_text can be zero length
+    # field_name can be None, in which case there's no
+    #  object to format and output
+    # if field_name is not None, it is looked up, formatted
+    #  with format_spec and conversion and then used
+    def parse(self, format_string):
+        return format_string._formatter_parser()
+
+
+    # given a field_name, find the object it references.
+    #  field_name:   the field being looked up, e.g. "0.name"
+    #                 or "lookup[3]"
+    #  used_args:    a set of which args have been used
+    #  args, kwargs: as passed in to vformat
+    def get_field(self, field_name, args, kwargs):
+        first, rest = field_name._formatter_field_name_split()
+
+        obj = self.get_value(first, args, kwargs)
+
+        # loop through the rest of the field_name, doing
+        #  getattr or getitem as needed
+        for is_attr, i in rest:
+            if is_attr:
+                obj = getattr(obj, i)
+            else:
+                obj = obj[i]
+
+        return obj, first
diff --git a/src/main/resources/PythonLibs/subprocess.py b/src/main/resources/PythonLibs/subprocess.py
new file mode 100644
index 0000000000000000000000000000000000000000..b969a16762171c4e4af8189ef65568eadb42d115
--- /dev/null
+++ b/src/main/resources/PythonLibs/subprocess.py
@@ -0,0 +1,1897 @@
+# subprocess - Subprocesses with accessible I/O streams
+#
+# For more information about this module, see PEP 324.
+#
+# This module should remain compatible with Python 2.2, see PEP 291.
+#
+# Copyright (c) 2003-2005 by Peter Astrand <astrand@lysator.liu.se>
+#
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/2.4/license for licensing details.
+
+r"""subprocess - Subprocesses with accessible I/O streams
+
+This module allows you to spawn processes, connect to their
+input/output/error pipes, and obtain their return codes.  This module
+intends to replace several other, older modules and functions, like:
+
+os.system
+os.spawn*
+os.popen*
+popen2.*
+commands.*
+
+Information about how the subprocess module can be used to replace these
+modules and functions can be found below.
+
+
+
+Using the subprocess module
+===========================
+This module defines one class called Popen:
+
+class Popen(args, bufsize=0, executable=None,
+            stdin=None, stdout=None, stderr=None,
+            preexec_fn=None, close_fds=False, shell=False,
+            cwd=None, env=None, universal_newlines=False,
+            startupinfo=None, creationflags=0):
+
+
+Arguments are:
+
+args should be a string, or a sequence of program arguments.  The
+program to execute is normally the first item in the args sequence or
+string, but can be explicitly set by using the executable argument.
+
+On UNIX, with shell=False (default): In this case, the Popen class
+uses os.execvp() to execute the child program.  args should normally
+be a sequence.  A string will be treated as a sequence with the string
+as the only item (the program to execute).
+
+On UNIX, with shell=True: If args is a string, it specifies the
+command string to execute through the shell.  If args is a sequence,
+the first item specifies the command string, and any additional items
+will be treated as additional shell arguments.
+
+On Windows: the Popen class uses CreateProcess() to execute the child
+program, which operates on strings.  If args is a sequence, it will be
+converted to a string using the list2cmdline method.  Please note that
+not all MS Windows applications interpret the command line the same
+way: The list2cmdline is designed for applications using the same
+rules as the MS C runtime.
+
+bufsize, if given, has the same meaning as the corresponding argument
+to the built-in open() function: 0 means unbuffered, 1 means line
+buffered, any other positive value means use a buffer of
+(approximately) that size.  A negative bufsize means to use the system
+default, which usually means fully buffered.  The default value for
+bufsize is 0 (unbuffered).
+
+stdin, stdout and stderr specify the executed programs' standard
+input, standard output and standard error file handles, respectively.
+Valid values are PIPE, an existing file descriptor (a positive
+integer), an existing file object, and None.  PIPE indicates that a
+new pipe to the child should be created.  With None, no redirection
+will occur; the child's file handles will be inherited from the
+parent.  Additionally, stderr can be STDOUT, which indicates that the
+stderr data from the applications should be captured into the same
+file handle as for stdout.
+
+If preexec_fn is set to a callable object, this object will be called
+in the child process just before the child is executed.
+
+If close_fds is true, all file descriptors except 0, 1 and 2 will be
+closed before the child process is executed.
+
+if shell is true, the specified command will be executed through the
+shell.
+
+If cwd is not None, the current directory will be changed to cwd
+before the child is executed.
+
+If env is not None, it defines the environment variables for the new
+process.
+
+If universal_newlines is true, the file objects stdout and stderr are
+opened as a text files, but lines may be terminated by any of '\n',
+the Unix end-of-line convention, '\r', the Macintosh convention or
+'\r\n', the Windows convention.  All of these external representations
+are seen as '\n' by the Python program.  Note: This feature is only
+available if Python is built with universal newline support (the
+default).  Also, the newlines attribute of the file objects stdout,
+stdin and stderr are not updated by the communicate() method.
+
+The startupinfo and creationflags, if given, will be passed to the
+underlying CreateProcess() function.  They can specify things such as
+appearance of the main window and priority for the new process.
+(Windows only)
+
+
+This module also defines some shortcut functions:
+
+call(*popenargs, **kwargs):
+    Run command with arguments.  Wait for command to complete, then
+    return the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    retcode = call(["ls", "-l"])
+
+check_call(*popenargs, **kwargs):
+    Run command with arguments.  Wait for command to complete.  If the
+    exit code was zero then return, otherwise raise
+    CalledProcessError.  The CalledProcessError object will have the
+    return code in the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    check_call(["ls", "-l"])
+
+check_output(*popenargs, **kwargs):
+    Run command with arguments and return its output as a byte string.
+
+    If the exit code was non-zero it raises a CalledProcessError.  The
+    CalledProcessError object will have the return code in the returncode
+    attribute and output in the output attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    output = check_output(["ls", "-l", "/dev/null"])
+
+
+Exceptions
+----------
+Exceptions raised in the child process, before the new program has
+started to execute, will be re-raised in the parent.  Additionally,
+the exception object will have one extra attribute called
+'child_traceback', which is a string containing traceback information
+from the childs point of view.
+
+The most common exception raised is OSError.  This occurs, for
+example, when trying to execute a non-existent file.  Applications
+should prepare for OSErrors.
+
+A ValueError will be raised if Popen is called with invalid arguments.
+
+check_call() and check_output() will raise CalledProcessError, if the
+called process returns a non-zero return code.
+
+
+Security
+--------
+Unlike some other popen functions, this implementation will never call
+/bin/sh implicitly.  This means that all characters, including shell
+metacharacters, can safely be passed to child processes.
+
+
+Popen objects
+=============
+Instances of the Popen class have the following methods:
+
+poll()
+    Check if child process has terminated.  Returns returncode
+    attribute.
+
+wait()
+    Wait for child process to terminate.  Returns returncode attribute.
+
+communicate(input=None)
+    Interact with process: Send data to stdin.  Read data from stdout
+    and stderr, until end-of-file is reached.  Wait for process to
+    terminate.  The optional input argument should be a string to be
+    sent to the child process, or None, if no data should be sent to
+    the child.
+
+    communicate() returns a tuple (stdout, stderr).
+
+    Note: The data read is buffered in memory, so do not use this
+    method if the data size is large or unlimited.
+
+The following attributes are also available:
+
+stdin
+    If the stdin argument is PIPE, this attribute is a file object
+    that provides input to the child process.  Otherwise, it is None.
+
+stdout
+    If the stdout argument is PIPE, this attribute is a file object
+    that provides output from the child process.  Otherwise, it is
+    None.
+
+stderr
+    If the stderr argument is PIPE, this attribute is file object that
+    provides error output from the child process.  Otherwise, it is
+    None.
+
+pid
+    The process ID of the child process.
+
+returncode
+    The child return code.  A None value indicates that the process
+    hasn't terminated yet.  A negative value -N indicates that the
+    child was terminated by signal N (UNIX only).
+
+
+Replacing older functions with the subprocess module
+====================================================
+In this section, "a ==> b" means that b can be used as a replacement
+for a.
+
+Note: All functions in this section fail (more or less) silently if
+the executed program cannot be found; this module raises an OSError
+exception.
+
+In the following examples, we assume that the subprocess module is
+imported with "from subprocess import *".
+
+
+Replacing /bin/sh shell backquote
+---------------------------------
+output=`mycmd myarg`
+==>
+output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]
+
+
+Replacing shell pipe line
+-------------------------
+output=`dmesg | grep hda`
+==>
+p1 = Popen(["dmesg"], stdout=PIPE)
+p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
+output = p2.communicate()[0]
+
+
+Replacing os.system()
+---------------------
+sts = os.system("mycmd" + " myarg")
+==>
+p = Popen("mycmd" + " myarg", shell=True)
+pid, sts = os.waitpid(p.pid, 0)
+
+Note:
+
+* Calling the program through the shell is usually not required.
+
+* It's easier to look at the returncode attribute than the
+  exitstatus.
+
+A more real-world example would look like this:
+
+try:
+    retcode = call("mycmd" + " myarg", shell=True)
+    if retcode < 0:
+        print >>sys.stderr, "Child was terminated by signal", -retcode
+    else:
+        print >>sys.stderr, "Child returned", retcode
+except OSError, e:
+    print >>sys.stderr, "Execution failed:", e
+
+
+Replacing os.spawn*
+-------------------
+P_NOWAIT example:
+
+pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
+==>
+pid = Popen(["/bin/mycmd", "myarg"]).pid
+
+
+P_WAIT example:
+
+retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
+==>
+retcode = call(["/bin/mycmd", "myarg"])
+
+
+Vector example:
+
+os.spawnvp(os.P_NOWAIT, path, args)
+==>
+Popen([path] + args[1:])
+
+
+Environment example:
+
+os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
+==>
+Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})
+
+
+Replacing os.popen*
+-------------------
+pipe = os.popen("cmd", mode='r', bufsize)
+==>
+pipe = Popen("cmd", shell=True, bufsize=bufsize, stdout=PIPE).stdout
+
+pipe = os.popen("cmd", mode='w', bufsize)
+==>
+pipe = Popen("cmd", shell=True, bufsize=bufsize, stdin=PIPE).stdin
+
+
+(child_stdin, child_stdout) = os.popen2("cmd", mode, bufsize)
+==>
+p = Popen("cmd", shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdin, child_stdout) = (p.stdin, p.stdout)
+
+
+(child_stdin,
+ child_stdout,
+ child_stderr) = os.popen3("cmd", mode, bufsize)
+==>
+p = Popen("cmd", shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+(child_stdin,
+ child_stdout,
+ child_stderr) = (p.stdin, p.stdout, p.stderr)
+
+
+(child_stdin, child_stdout_and_stderr) = os.popen4("cmd", mode,
+                                                   bufsize)
+==>
+p = Popen("cmd", shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
+(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)
+
+On Unix, os.popen2, os.popen3 and os.popen4 also accept a sequence as
+the command to execute, in which case arguments will be passed
+directly to the program without shell intervention.  This usage can be
+replaced as follows:
+
+(child_stdin, child_stdout) = os.popen2(["/bin/ls", "-l"], mode,
+                                        bufsize)
+==>
+p = Popen(["/bin/ls", "-l"], bufsize=bufsize, stdin=PIPE, stdout=PIPE)
+(child_stdin, child_stdout) = (p.stdin, p.stdout)
+
+Return code handling translates as follows:
+
+pipe = os.popen("cmd", 'w')
+...
+rc = pipe.close()
+if rc is not None and rc % 256:
+    print "There were some errors"
+==>
+process = Popen("cmd", 'w', shell=True, stdin=PIPE)
+...
+process.stdin.close()
+if process.wait() != 0:
+    print "There were some errors"
+
+
+Replacing popen2.*
+------------------
+(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
+==>
+p = Popen(["somestring"], shell=True, bufsize=bufsize
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdout, child_stdin) = (p.stdout, p.stdin)
+
+On Unix, popen2 also accepts a sequence as the command to execute, in
+which case arguments will be passed directly to the program without
+shell intervention.  This usage can be replaced as follows:
+
+(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize,
+                                            mode)
+==>
+p = Popen(["mycmd", "myarg"], bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdout, child_stdin) = (p.stdout, p.stdin)
+
+The popen2.Popen3 and popen2.Popen4 basically works as subprocess.Popen,
+except that:
+
+* subprocess.Popen raises an exception if the execution fails
+* the capturestderr argument is replaced with the stderr argument.
+* stdin=PIPE and stdout=PIPE must be specified.
+* popen2 closes all filedescriptors by default, but you have to specify
+  close_fds=True with subprocess.Popen.
+"""
+
+import sys
+mswindows = (sys.platform == "win32")
+jython = sys.platform.startswith("java")
+
+import os
+import types
+import traceback
+import signal
+
+# Exception classes used by this module.
+class CalledProcessError(Exception):
+    """This exception is raised when a process run by check_call() or
+    check_output() returns a non-zero exit status.
+    The exit status will be stored in the returncode attribute;
+    check_output() will also store the output in the output attribute.
+    """
+    def __init__(self, returncode, cmd, output=None):
+        self.returncode = returncode
+        self.cmd = cmd
+        self.output = output
+    def __str__(self):
+        return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
+
+
+if mswindows:
+    import threading
+    import msvcrt
+    import _subprocess
+    class STARTUPINFO:
+        dwFlags = 0
+        hStdInput = None
+        hStdOutput = None
+        hStdError = None
+        wShowWindow = 0
+    class pywintypes:
+        error = IOError
+elif jython:
+    import errno
+    import threading
+    import java.io.File
+    import java.io.IOException
+    import java.lang.IllegalArgumentException
+    import java.lang.IllegalThreadStateException
+    import java.lang.ProcessBuilder
+    import java.lang.System
+    import java.lang.Thread
+    import java.nio.ByteBuffer
+    import org.python.core.io.RawIOBase
+    import org.python.core.io.StreamIO
+else:
+    import select
+    _has_poll = hasattr(select, 'poll')
+    import errno
+    import fcntl
+    import gc
+    import pickle
+
+    # When select or poll has indicated that the file is writable,
+    # we can write up to _PIPE_BUF bytes without risk of blocking.
+    # POSIX defines PIPE_BUF as >= 512.
+    _PIPE_BUF = getattr(select, 'PIPE_BUF', 512)
+
+
+__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call",
+           "check_output", "CalledProcessError"]
+
+if mswindows:
+    from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP
+    __all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP"])
+try:
+    MAXFD = os.sysconf("SC_OPEN_MAX")
+except:
+    MAXFD = 256
+
+_active = []
+
+def _cleanup():
+    for inst in _active[:]:
+        res = inst._internal_poll(_deadstate=sys.maxint)
+        if res is not None and res >= 0:
+            try:
+                _active.remove(inst)
+            except ValueError:
+                # This can happen if two threads create a new Popen instance.
+                # It's harmless that it was already removed, so ignore.
+                pass
+
+PIPE = -1
+STDOUT = -2
+
+
+def _eintr_retry_call(func, *args):
+    while True:
+        try:
+            return func(*args)
+        except OSError, e:
+            if e.errno == errno.EINTR:
+                continue
+            raise
+
+
+def call(*popenargs, **kwargs):
+    """Run command with arguments.  Wait for command to complete, then
+    return the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    retcode = call(["ls", "-l"])
+    """
+    return Popen(*popenargs, **kwargs).wait()
+
+
+def check_call(*popenargs, **kwargs):
+    """Run command with arguments.  Wait for command to complete.  If
+    the exit code was zero then return, otherwise raise
+    CalledProcessError.  The CalledProcessError object will have the
+    return code in the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    check_call(["ls", "-l"])
+    """
+    retcode = call(*popenargs, **kwargs)
+    if retcode:
+        cmd = kwargs.get("args")
+        if cmd is None:
+            cmd = popenargs[0]
+        raise CalledProcessError(retcode, cmd)
+    return 0
+
+
+def check_output(*popenargs, **kwargs):
+    r"""Run command with arguments and return its output as a byte string.
+
+    If the exit code was non-zero it raises a CalledProcessError.  The
+    CalledProcessError object will have the return code in the returncode
+    attribute and output in the output attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    >>> check_output(["ls", "-l", "/dev/null"])
+    'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'
+
+    The stdout argument is not allowed as it is used internally.
+    To capture standard error in the result, use stderr=STDOUT.
+
+    >>> check_output(["/bin/sh", "-c",
+    ...               "ls -l non_existent_file ; exit 0"],
+    ...              stderr=STDOUT)
+    'ls: non_existent_file: No such file or directory\n'
+    """
+    if 'stdout' in kwargs:
+        raise ValueError('stdout argument not allowed, it will be overridden.')
+    process = Popen(stdout=PIPE, *popenargs, **kwargs)
+    output, unused_err = process.communicate()
+    retcode = process.poll()
+    if retcode:
+        cmd = kwargs.get("args")
+        if cmd is None:
+            cmd = popenargs[0]
+        raise CalledProcessError(retcode, cmd, output=output)
+    return output
+
+
+def list2cmdline(seq):
+    """
+    Translate a sequence of arguments into a command line
+    string, using the same rules as the MS C runtime:
+
+    1) Arguments are delimited by white space, which is either a
+       space or a tab.
+
+    2) A string surrounded by double quotation marks is
+       interpreted as a single argument, regardless of white space
+       contained within.  A quoted string can be embedded in an
+       argument.
+
+    3) A double quotation mark preceded by a backslash is
+       interpreted as a literal double quotation mark.
+
+    4) Backslashes are interpreted literally, unless they
+       immediately precede a double quotation mark.
+
+    5) If backslashes immediately precede a double quotation mark,
+       every pair of backslashes is interpreted as a literal
+       backslash.  If the number of backslashes is odd, the last
+       backslash escapes the next double quotation mark as
+       described in rule 3.
+    """
+
+    # See
+    # http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
+    # or search http://msdn.microsoft.com for
+    # "Parsing C++ Command-Line Arguments"
+    result = []
+    needquote = False
+    for arg in seq:
+        bs_buf = []
+
+        # Add a space to separate this argument from the others
+        if result:
+            result.append(' ')
+
+        needquote = (" " in arg) or ("\t" in arg) or not arg
+        if needquote:
+            result.append('"')
+
+        for c in arg:
+            if c == '\\':
+                # Don't know if we need to double yet.
+                bs_buf.append(c)
+            elif c == '"':
+                # Double backslashes.
+                result.append('\\' * len(bs_buf)*2)
+                bs_buf = []
+                result.append('\\"')
+            else:
+                # Normal char
+                if bs_buf:
+                    result.extend(bs_buf)
+                    bs_buf = []
+                result.append(c)
+
+        # Add remaining backslashes, if any.
+        if bs_buf:
+            result.extend(bs_buf)
+
+        if needquote:
+            result.extend(bs_buf)
+            result.append('"')
+
+    return ''.join(result)
+
+
+if jython:
+    # Parse command line arguments for Windows
+    _win_oses = ['nt']
+
+    _cmdline2listimpl = None
+    _escape_args = None
+    _shell_command = None
+
+    def _cmdline2list(cmdline):
+        """Build an argv list from a Microsoft shell style cmdline str
+
+        The reverse of list2cmdline that follows the same MS C runtime
+        rules.
+
+        Java's ProcessBuilder takes a List<String> cmdline that's joined
+        with a list2cmdline-like routine for Windows CreateProcess
+        (which takes a String cmdline). This process ruins String
+        cmdlines from the user with escapes or quotes. To avoid this we
+        first parse these cmdlines into an argv.
+
+        Runtime.exec(String) is too naive and useless for this case.
+        """
+        whitespace = ' \t'
+        # count of preceding '\'
+        bs_count = 0
+        in_quotes = False
+        arg = []
+        argv = []
+
+        for ch in cmdline:
+            if ch in whitespace and not in_quotes:
+                if arg:
+                    # finalize arg and reset
+                    argv.append(''.join(arg))
+                    arg = []
+                bs_count = 0
+            elif ch == '\\':
+                arg.append(ch)
+                bs_count += 1
+            elif ch == '"':
+                if not bs_count % 2:
+                    # Even number of '\' followed by a '"'. Place one
+                    # '\' for every pair and treat '"' as a delimiter
+                    if bs_count:
+                        del arg[-(bs_count / 2):]
+                    in_quotes = not in_quotes
+                else:
+                    # Odd number of '\' followed by a '"'. Place one '\'
+                    # for every pair and treat '"' as an escape sequence
+                    # by the remaining '\'
+                    del arg[-(bs_count / 2 + 1):]
+                    arg.append(ch)
+                bs_count = 0
+            else:
+                # regular char
+                arg.append(ch)
+                bs_count = 0
+
+        # A single trailing '"' delimiter yields an empty arg
+        if arg or in_quotes:
+            argv.append(''.join(arg))
+
+        return argv
+
+    def _setup_platform():
+        """Setup the shell command and the command line argument escape
+        function depending on the underlying platform
+        """
+        global _cmdline2listimpl, _escape_args, _shell_command
+
+        if os._name in _win_oses:
+            _cmdline2listimpl = _cmdline2list
+            _escape_args = lambda args: [list2cmdline([arg]) for arg in args]
+        else:
+            _cmdline2listimpl = lambda args: [args]
+            _escape_args = lambda args: args
+
+        for shell_command in os._get_shell_commands():
+            executable = shell_command[0]
+            if not os.path.isabs(executable):
+                import distutils.spawn
+                executable = distutils.spawn.find_executable(executable)
+            if not executable or not os.path.exists(executable):
+                continue
+            shell_command[0] = executable
+            _shell_command = shell_command
+            return
+
+        if not _shell_command:
+            import warnings
+            warnings.warn('Unable to determine _shell_command for '
+                          'underlying os: %s' % os._name, RuntimeWarning, 3)
+    _setup_platform()
+
+
+    class _CouplerThread(java.lang.Thread):
+
+        """Couples a reader and writer RawIOBase.
+
+        Streams data from the reader's read_func (a RawIOBase readinto
+        method) to the writer's write_func (a RawIOBase write method) in
+        a separate thread. Optionally calls close_func when finished
+        streaming or an exception occurs.
+
+        This thread will fail safe when interrupted by Java's
+        Thread.interrupt.
+        """
+
+        # analagous to PC_PIPE_BUF, which is typically 512 or 4096
+        bufsize = 4096
+
+        def __init__(self, name, read_func, write_func, close_func=None):
+            self.read_func = read_func
+            self.write_func = write_func
+            self.close_func = close_func
+            self.setName('%s-%s (%s)' % (self.__class__.__name__, id(self),
+                                         name))
+            self.setDaemon(True)
+
+        def run(self):
+            buf = java.nio.ByteBuffer.allocate(self.bufsize)
+            while True:
+                try:
+                    count = self.read_func(buf)
+                    if count < 1:
+                        if self.close_func:
+                            self.close_func()
+                        break
+                    buf.flip()
+                    self.write_func(buf)
+                    buf.flip()
+                except IOError, ioe:
+                    if self.close_func:
+                        try:
+                            self.close_func()
+                        except:
+                            pass
+                    # XXX: hack, should really be a
+                    # ClosedByInterruptError(IOError) exception
+                    if str(ioe) == \
+                            'java.nio.channels.ClosedByInterruptException':
+                        return
+                    raise
+
+
+class Popen(object):
+    def __init__(self, args, bufsize=0, executable=None,
+                 stdin=None, stdout=None, stderr=None,
+                 preexec_fn=None, close_fds=False, shell=False,
+                 cwd=None, env=None, universal_newlines=False,
+                 startupinfo=None, creationflags=0):
+        """Create new Popen instance."""
+        _cleanup()
+
+        self._child_created = False
+        if not isinstance(bufsize, (int, long)):
+            raise TypeError("bufsize must be an integer")
+
+        if mswindows:
+            if preexec_fn is not None:
+                raise ValueError("preexec_fn is not supported on Windows "
+                                 "platforms")
+            if close_fds and (stdin is not None or stdout is not None or
+                              stderr is not None):
+                raise ValueError("close_fds is not supported on Windows "
+                                 "platforms if you redirect stdin/stdout/stderr")
+        else:
+            # POSIX
+            if startupinfo is not None:
+                raise ValueError("startupinfo is only supported on Windows "
+                                 "platforms")
+            if creationflags != 0:
+                raise ValueError("creationflags is only supported on Windows "
+                                 "platforms")
+        if jython:
+            if preexec_fn is not None:
+                raise ValueError("preexec_fn is not supported on the Jython "
+                                 "platform")
+
+        self.stdin = None
+        self.stdout = None
+        self.stderr = None
+        self.pid = None
+        self.returncode = None
+        self.universal_newlines = universal_newlines
+
+        # Input and output objects. The general principle is like
+        # this:
+        #
+        # Parent                   Child
+        # ------                   -----
+        # p2cwrite   ---stdin--->  p2cread
+        # c2pread    <--stdout---  c2pwrite
+        # errread    <--stderr---  errwrite
+        #
+        # On POSIX, the child objects are file descriptors.  On
+        # Windows, these are Windows file handles.  The parent objects
+        # are file descriptors on both platforms.  The parent objects
+        # are None when not using PIPEs. The child objects are None
+        # when not redirecting.
+
+        (p2cread, p2cwrite,
+         c2pread, c2pwrite,
+         errread, errwrite) = self._get_handles(stdin, stdout, stderr)
+
+        self._execute_child(args, executable, preexec_fn, close_fds,
+                            cwd, env, universal_newlines,
+                            startupinfo, creationflags, shell,
+                            p2cread, p2cwrite,
+                            c2pread, c2pwrite,
+                            errread, errwrite)
+
+        if mswindows:
+            if p2cwrite is not None:
+                p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0)
+            if c2pread is not None:
+                c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0)
+            if errread is not None:
+                errread = msvcrt.open_osfhandle(errread.Detach(), 0)
+
+        if jython:
+            self._stdin_thread = None
+            self._stdout_thread = None
+            self._stderr_thread = None
+
+            # 'ct' is for _CouplerThread
+            proc = self._process
+            ct2cwrite = org.python.core.io.StreamIO(proc.getOutputStream(),
+                                                    True)
+            c2ctread = org.python.core.io.StreamIO(proc.getInputStream(), True)
+            cterrread = org.python.core.io.StreamIO(proc.getErrorStream(),
+                                                    True)
+
+            # Use the java.lang.Process streams for PIPE, otherwise
+            # direct the desired file to/from the java.lang.Process
+            # streams in a separate thread
+            if p2cwrite == PIPE:
+                p2cwrite = ct2cwrite
+            else:
+                if p2cread is None:
+                    # Coupling stdin is not supported: there's no way to
+                    # cleanly interrupt it if it blocks the
+                    # _CouplerThread forever (we can Thread.interrupt()
+                    # its _CouplerThread but that closes stdin's
+                    # Channel)
+                    pass
+                else:
+                    self._stdin_thread = self._coupler_thread('stdin',
+                                                              p2cread.readinto,
+                                                              ct2cwrite.write,
+                                                              ct2cwrite.close)
+                    self._stdin_thread.start()
+
+            if c2pread == PIPE:
+                c2pread = c2ctread
+            else:
+                if c2pwrite is None:
+                    c2pwrite = org.python.core.io.StreamIO(
+                        java.lang.System.out, False)
+                self._stdout_thread = self._coupler_thread('stdout',
+                                                           c2ctread.readinto,
+                                                           c2pwrite.write)
+                self._stdout_thread.start()
+
+            if errread == PIPE:
+                errread = cterrread
+            elif not self._stderr_is_stdout(errwrite, c2pwrite):
+                if errwrite is None:
+                    errwrite = org.python.core.io.StreamIO(
+                        java.lang.System.err, False)
+                self._stderr_thread = self._coupler_thread('stderr',
+                                                           cterrread.readinto,
+                                                           errwrite.write)
+                self._stderr_thread.start()
+
+        if p2cwrite is not None:
+            self.stdin = os.fdopen(p2cwrite, 'wb', bufsize)
+        if c2pread is not None:
+            if universal_newlines:
+                self.stdout = os.fdopen(c2pread, 'rU', bufsize)
+            else:
+                self.stdout = os.fdopen(c2pread, 'rb', bufsize)
+        if errread is not None:
+            if universal_newlines:
+                self.stderr = os.fdopen(errread, 'rU', bufsize)
+            else:
+                self.stderr = os.fdopen(errread, 'rb', bufsize)
+
+
+    def _translate_newlines(self, data):
+        data = data.replace("\r\n", "\n")
+        data = data.replace("\r", "\n")
+        return data
+
+
+    def __del__(self, _maxint=sys.maxint, _active=_active):
+        if not self._child_created:
+            # We didn't get to successfully create a child process.
+            return
+        # In case the child hasn't been waited on, check if it's done.
+        self._internal_poll(_deadstate=_maxint)
+        if self.returncode is None and _active is not None:
+            # Child is still running, keep us alive until we can wait on it.
+            _active.append(self)
+
+
+    def communicate(self, input=None):
+        """Interact with process: Send data to stdin.  Read data from
+        stdout and stderr, until end-of-file is reached.  Wait for
+        process to terminate.  The optional input argument should be a
+        string to be sent to the child process, or None, if no data
+        should be sent to the child.
+
+        communicate() returns a tuple (stdout, stderr)."""
+
+        # Optimization: If we are only using one pipe, or no pipe at
+        # all, using select() or threads is unnecessary.
+        if [self.stdin, self.stdout, self.stderr].count(None) >= 2:
+            stdout = None
+            stderr = None
+            if self.stdin:
+                if input:
+                    self.stdin.write(input)
+                self.stdin.close()
+            elif self.stdout:
+                stdout = self.stdout.read()
+                self.stdout.close()
+            elif self.stderr:
+                stderr = self.stderr.read()
+                self.stderr.close()
+            self.wait()
+            return (stdout, stderr)
+
+        return self._communicate(input)
+
+
+    def poll(self):
+        return self._internal_poll()
+
+
+    if mswindows or jython:
+        #
+        # Windows and Jython shared methods
+        #
+        def _readerthread(self, fh, buffer):
+            buffer.append(fh.read())
+
+
+        def _communicate(self, input):
+            stdout = None # Return
+            stderr = None # Return
+
+            if self.stdout:
+                stdout = []
+                stdout_thread = threading.Thread(target=self._readerthread,
+                                                 args=(self.stdout, stdout))
+                stdout_thread.setDaemon(True)
+                stdout_thread.start()
+            if self.stderr:
+                stderr = []
+                stderr_thread = threading.Thread(target=self._readerthread,
+                                                 args=(self.stderr, stderr))
+                stderr_thread.setDaemon(True)
+                stderr_thread.start()
+
+            if self.stdin:
+                if input is not None:
+                    self.stdin.write(input)
+                self.stdin.close()
+
+            if self.stdout:
+                stdout_thread.join()
+            if self.stderr:
+                stderr_thread.join()
+
+            # All data exchanged.  Translate lists into strings.
+            if stdout is not None:
+                stdout = stdout[0]
+            if stderr is not None:
+                stderr = stderr[0]
+
+            # Translate newlines, if requested.  We cannot let the file
+            # object do the translation: It is based on stdio, which is
+            # impossible to combine with select (unless forcing no
+            # buffering).
+            if self.universal_newlines and hasattr(file, 'newlines'):
+                if stdout:
+                    stdout = self._translate_newlines(stdout)
+                if stderr:
+                    stderr = self._translate_newlines(stderr)
+
+            self.wait()
+            return (stdout, stderr)
+
+
+    if mswindows:
+        #
+        # Windows methods
+        #
+        def _get_handles(self, stdin, stdout, stderr):
+            """Construct and return tuple with IO objects:
+            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
+            """
+            if stdin is None and stdout is None and stderr is None:
+                return (None, None, None, None, None, None)
+
+            p2cread, p2cwrite = None, None
+            c2pread, c2pwrite = None, None
+            errread, errwrite = None, None
+
+            if stdin is None:
+                p2cread = _subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE)
+                if p2cread is None:
+                    p2cread, _ = _subprocess.CreatePipe(None, 0)
+            elif stdin == PIPE:
+                p2cread, p2cwrite = _subprocess.CreatePipe(None, 0)
+            elif isinstance(stdin, int):
+                p2cread = msvcrt.get_osfhandle(stdin)
+            else:
+                # Assuming file-like object
+                p2cread = msvcrt.get_osfhandle(stdin.fileno())
+            p2cread = self._make_inheritable(p2cread)
+
+            if stdout is None:
+                c2pwrite = _subprocess.GetStdHandle(_subprocess.STD_OUTPUT_HANDLE)
+                if c2pwrite is None:
+                    _, c2pwrite = _subprocess.CreatePipe(None, 0)
+            elif stdout == PIPE:
+                c2pread, c2pwrite = _subprocess.CreatePipe(None, 0)
+            elif isinstance(stdout, int):
+                c2pwrite = msvcrt.get_osfhandle(stdout)
+            else:
+                # Assuming file-like object
+                c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
+            c2pwrite = self._make_inheritable(c2pwrite)
+
+            if stderr is None:
+                errwrite = _subprocess.GetStdHandle(_subprocess.STD_ERROR_HANDLE)
+                if errwrite is None:
+                    _, errwrite = _subprocess.CreatePipe(None, 0)
+            elif stderr == PIPE:
+                errread, errwrite = _subprocess.CreatePipe(None, 0)
+            elif stderr == STDOUT:
+                errwrite = c2pwrite
+            elif isinstance(stderr, int):
+                errwrite = msvcrt.get_osfhandle(stderr)
+            else:
+                # Assuming file-like object
+                errwrite = msvcrt.get_osfhandle(stderr.fileno())
+            errwrite = self._make_inheritable(errwrite)
+
+            return (p2cread, p2cwrite,
+                    c2pread, c2pwrite,
+                    errread, errwrite)
+
+
+        def _make_inheritable(self, handle):
+            """Return a duplicate of handle, which is inheritable"""
+            return _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(),
+                                handle, _subprocess.GetCurrentProcess(), 0, 1,
+                                _subprocess.DUPLICATE_SAME_ACCESS)
+
+
+        def _find_w9xpopen(self):
+            """Find and return absolut path to w9xpopen.exe"""
+            w9xpopen = os.path.join(
+                            os.path.dirname(_subprocess.GetModuleFileName(0)),
+                                    "w9xpopen.exe")
+            if not os.path.exists(w9xpopen):
+                # Eeek - file-not-found - possibly an embedding
+                # situation - see if we can locate it in sys.exec_prefix
+                w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix),
+                                        "w9xpopen.exe")
+                if not os.path.exists(w9xpopen):
+                    raise RuntimeError("Cannot locate w9xpopen.exe, which is "
+                                       "needed for Popen to work with your "
+                                       "shell or platform.")
+            return w9xpopen
+
+
+        def _execute_child(self, args, executable, preexec_fn, close_fds,
+                           cwd, env, universal_newlines,
+                           startupinfo, creationflags, shell,
+                           p2cread, p2cwrite,
+                           c2pread, c2pwrite,
+                           errread, errwrite):
+            """Execute program (MS Windows version)"""
+
+            if not isinstance(args, types.StringTypes):
+                args = list2cmdline(args)
+
+            # Process startup details
+            if startupinfo is None:
+                startupinfo = STARTUPINFO()
+            if None not in (p2cread, c2pwrite, errwrite):
+                startupinfo.dwFlags |= _subprocess.STARTF_USESTDHANDLES
+                startupinfo.hStdInput = p2cread
+                startupinfo.hStdOutput = c2pwrite
+                startupinfo.hStdError = errwrite
+
+            if shell:
+                startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
+                startupinfo.wShowWindow = _subprocess.SW_HIDE
+                comspec = os.environ.get("COMSPEC", "cmd.exe")
+                args = '{} /c "{}"'.format (comspec, args)
+                if (_subprocess.GetVersion() >= 0x80000000 or
+                        os.path.basename(comspec).lower() == "command.com"):
+                    # Win9x, or using command.com on NT. We need to
+                    # use the w9xpopen intermediate program. For more
+                    # information, see KB Q150956
+                    # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp)
+                    w9xpopen = self._find_w9xpopen()
+                    args = '"%s" %s' % (w9xpopen, args)
+                    # Not passing CREATE_NEW_CONSOLE has been known to
+                    # cause random failures on win9x.  Specifically a
+                    # dialog: "Your program accessed mem currently in
+                    # use at xxx" and a hopeful warning about the
+                    # stability of your system.  Cost is Ctrl+C wont
+                    # kill children.
+                    creationflags |= _subprocess.CREATE_NEW_CONSOLE
+
+            # Start the process
+            try:
+                hp, ht, pid, tid = _subprocess.CreateProcess(executable, args,
+                                         # no special security
+                                         None, None,
+                                         int(not close_fds),
+                                         creationflags,
+                                         env,
+                                         cwd,
+                                         startupinfo)
+            except pywintypes.error, e:
+                # Translate pywintypes.error to WindowsError, which is
+                # a subclass of OSError.  FIXME: We should really
+                # translate errno using _sys_errlist (or simliar), but
+                # how can this be done from Python?
+                raise WindowsError(*e.args)
+            finally:
+                # Child is launched. Close the parent's copy of those pipe
+                # handles that only the child should have open.  You need
+                # to make sure that no handles to the write end of the
+                # output pipe are maintained in this process or else the
+                # pipe will not close when the child process exits and the
+                # ReadFile will hang.
+                if p2cread is not None:
+                    p2cread.Close()
+                if c2pwrite is not None:
+                    c2pwrite.Close()
+                if errwrite is not None:
+                    errwrite.Close()
+
+            # Retain the process handle, but close the thread handle
+            self._child_created = True
+            self._handle = hp
+            self.pid = pid
+            ht.Close()
+
+        def _internal_poll(self, _deadstate=None,
+                _WaitForSingleObject=_subprocess.WaitForSingleObject,
+                _WAIT_OBJECT_0=_subprocess.WAIT_OBJECT_0,
+                _GetExitCodeProcess=_subprocess.GetExitCodeProcess):
+            """Check if child process has terminated.  Returns returncode
+            attribute.
+
+            This method is called by __del__, so it can only refer to objects
+            in its local scope.
+
+            """
+            if self.returncode is None:
+                if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0:
+                    self.returncode = _GetExitCodeProcess(self._handle)
+            return self.returncode
+
+
+        def wait(self):
+            """Wait for child process to terminate.  Returns returncode
+            attribute."""
+            if self.returncode is None:
+                _subprocess.WaitForSingleObject(self._handle,
+                                                _subprocess.INFINITE)
+                self.returncode = _subprocess.GetExitCodeProcess(self._handle)
+            return self.returncode
+
+    elif jython:
+        #
+        # Jython methods
+        #
+        def _get_handles(self, stdin, stdout, stderr):
+            """Construct and return tuple with IO objects:
+            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
+            """
+            p2cread, p2cwrite = None, None
+            c2pread, c2pwrite = None, None
+            errread, errwrite = None, None
+
+            if stdin is None:
+                pass
+            elif stdin == PIPE:
+                p2cwrite = PIPE
+            elif isinstance(stdin, org.python.core.io.RawIOBase):
+                p2cread = stdin
+            else:
+                # Assuming file-like object
+                p2cread = stdin.fileno()
+
+            if stdout is None:
+                pass
+            elif stdout == PIPE:
+                c2pread = PIPE
+            elif isinstance(stdout, org.python.core.io.RawIOBase):
+                c2pwrite = stdout
+            else:
+                # Assuming file-like object
+                c2pwrite = stdout.fileno()
+
+            if stderr is None:
+                pass
+            elif stderr == PIPE:
+                errread = PIPE
+            elif (stderr == STDOUT or
+                  isinstance(stderr, org.python.core.io.RawIOBase)):
+                errwrite = stderr
+            else:
+                # Assuming file-like object
+                errwrite = stderr.fileno()
+
+            return (p2cread, p2cwrite,
+                    c2pread, c2pwrite,
+                    errread, errwrite)
+
+
+        def _stderr_is_stdout(self, errwrite, c2pwrite):
+            """Determine if the subprocess' stderr should be redirected
+            to stdout
+            """
+            return (errwrite == STDOUT or c2pwrite not in (None, PIPE) and
+                    c2pwrite is errwrite)
+
+
+        def _coupler_thread(self, *args, **kwargs):
+            """Return a _CouplerThread"""
+            return _CouplerThread(*args, **kwargs)
+
+
+        def _setup_env(self, env, builder_env):
+            """Carefully merge env with ProcessBuilder's only
+            overwriting key/values that differ
+
+            System.getenv (Map<String, String>) may be backed by
+            <byte[], byte[]> on UNIX platforms where these are really
+            bytes. ProcessBuilder's env inherits its contents and will
+            maintain those byte values (which may be butchered as
+            Strings) for the subprocess if they haven't been modified.
+            """
+            # Determine what's safe to merge
+            merge_env = dict((key, value) for key, value in env.iteritems()
+                             if key not in builder_env or
+                             builder_env.get(key) != value)
+
+            # Prune anything not in env
+            entries = builder_env.entrySet().iterator()
+            for entry in entries:
+                if entry.getKey() not in env:
+                    entries.remove()
+
+            builder_env.putAll(merge_env)
+
+
+        def _execute_child(self, args, executable, preexec_fn, close_fds,
+                           cwd, env, universal_newlines,
+                           startupinfo, creationflags, shell,
+                           p2cread, p2cwrite,
+                           c2pread, c2pwrite,
+                           errread, errwrite):
+            """Execute program (Java version)"""
+
+            if isinstance(args, types.StringTypes):
+                args = _cmdline2listimpl(args)
+            else:
+                args = list(args)
+                # NOTE: CPython posix (execv) will str() any unicode
+                # args first, maybe we should do the same on
+                # posix. Windows passes unicode through, however
+                if any(not isinstance(arg, (str, unicode)) for arg in args):
+                    raise TypeError('args must contain only strings')
+            args = _escape_args(args)
+
+            if shell:
+                args = _shell_command + args
+
+            if executable is not None:
+                args[0] = executable
+
+            builder = java.lang.ProcessBuilder(args)
+            # os.environ may be inherited for compatibility with CPython
+            self._setup_env(dict(os.environ if env is None else env),
+                            builder.environment())
+
+            if cwd is None:
+                cwd = os.getcwd()
+            elif not os.path.exists(cwd):
+                raise OSError(errno.ENOENT, os.strerror(errno.ENOENT), cwd)
+            elif not os.path.isdir(cwd):
+                raise OSError(errno.ENOTDIR, os.strerror(errno.ENOTDIR), cwd)
+            builder.directory(java.io.File(cwd))
+
+            # Let Java manage redirection of stderr to stdout (it's more
+            # accurate at doing so than _CouplerThreads). We redirect
+            # not only when stderr is marked as STDOUT, but also when
+            # c2pwrite is errwrite
+            if self._stderr_is_stdout(errwrite, c2pwrite):
+                builder.redirectErrorStream(True)
+
+            try:
+                self._process = builder.start()
+            except (java.io.IOException,
+                    java.lang.IllegalArgumentException), e:
+                raise OSError(e.getMessage() or e)
+            self._child_created = True
+
+
+        def poll(self, _deadstate=None):
+            """Check if child process has terminated.  Returns returncode
+            attribute."""
+            if self.returncode is None:
+                try:
+                    self.returncode = self._process.exitValue()
+                except java.lang.IllegalThreadStateException:
+                    pass
+            return self.returncode
+
+
+        def wait(self):
+            """Wait for child process to terminate.  Returns returncode
+            attribute."""
+            if self.returncode is None:
+                self.returncode = self._process.waitFor()
+                for coupler in (self._stdout_thread, self._stderr_thread):
+                    if coupler:
+                        coupler.join()
+                if self._stdin_thread:
+                    # The stdin thread may be blocked forever, forcibly
+                    # stop it
+                    self._stdin_thread.interrupt()
+            return self.returncode
+
+        def send_signal(self, sig):
+            """Send a signal to the process
+            """
+            if sig == signal.SIGTERM:
+                self.terminate()
+            elif sig == signal.CTRL_C_EVENT:
+                os.kill(self.pid, signal.CTRL_C_EVENT)
+            elif sig == signal.CTRL_BREAK_EVENT:
+                os.kill(self.pid, signal.CTRL_BREAK_EVENT)
+            else:
+                raise ValueError("Unsupported signal: {}".format(sig))
+
+        def terminate(self):
+            """Terminates the process
+            """
+            _subprocess.TerminateProcess(self._handle, 1)
+
+        kill = terminate
+
+    else:
+        #
+        # POSIX methods
+        #
+        def _get_handles(self, stdin, stdout, stderr):
+            """Construct and return tuple with IO objects:
+            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
+            """
+            p2cread, p2cwrite = None, None
+            c2pread, c2pwrite = None, None
+            errread, errwrite = None, None
+
+            if stdin is None:
+                pass
+            elif stdin == PIPE:
+                p2cread, p2cwrite = os.pipe()
+            elif isinstance(stdin, int):
+                p2cread = stdin
+            else:
+                # Assuming file-like object
+                p2cread = stdin.fileno()
+
+            if stdout is None:
+                pass
+            elif stdout == PIPE:
+                c2pread, c2pwrite = os.pipe()
+            elif isinstance(stdout, int):
+                c2pwrite = stdout
+            else:
+                # Assuming file-like object
+                c2pwrite = stdout.fileno()
+
+            if stderr is None:
+                pass
+            elif stderr == PIPE:
+                errread, errwrite = os.pipe()
+            elif stderr == STDOUT:
+                errwrite = c2pwrite
+            elif isinstance(stderr, int):
+                errwrite = stderr
+            else:
+                # Assuming file-like object
+                errwrite = stderr.fileno()
+
+            return (p2cread, p2cwrite,
+                    c2pread, c2pwrite,
+                    errread, errwrite)
+
+
+        def _set_cloexec_flag(self, fd, cloexec=True):
+            try:
+                cloexec_flag = fcntl.FD_CLOEXEC
+            except AttributeError:
+                cloexec_flag = 1
+
+            old = fcntl.fcntl(fd, fcntl.F_GETFD)
+            if cloexec:
+                fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag)
+            else:
+                fcntl.fcntl(fd, fcntl.F_SETFD, old & ~cloexec_flag)
+
+
+        def _close_fds(self, but):
+            if hasattr(os, 'closerange'):
+                os.closerange(3, but)
+                os.closerange(but + 1, MAXFD)
+            else:
+                for i in xrange(3, MAXFD):
+                    if i == but:
+                        continue
+                    try:
+                        os.close(i)
+                    except:
+                        pass
+
+
+        def _execute_child(self, args, executable, preexec_fn, close_fds,
+                           cwd, env, universal_newlines,
+                           startupinfo, creationflags, shell,
+                           p2cread, p2cwrite,
+                           c2pread, c2pwrite,
+                           errread, errwrite):
+            """Execute program (POSIX version)"""
+
+            if isinstance(args, types.StringTypes):
+                args = [args]
+            else:
+                args = list(args)
+
+            if shell:
+                args = ["/bin/sh", "-c"] + args
+                if executable:
+                    args[0] = executable
+
+            if executable is None:
+                executable = args[0]
+
+            # For transferring possible exec failure from child to parent
+            # The first char specifies the exception type: 0 means
+            # OSError, 1 means some other error.
+            errpipe_read, errpipe_write = os.pipe()
+            try:
+                try:
+                    self._set_cloexec_flag(errpipe_write)
+
+                    gc_was_enabled = gc.isenabled()
+                    # Disable gc to avoid bug where gc -> file_dealloc ->
+                    # write to stderr -> hang.  http://bugs.python.org/issue1336
+                    gc.disable()
+                    try:
+                        self.pid = os.fork()
+                    except:
+                        if gc_was_enabled:
+                            gc.enable()
+                        raise
+                    self._child_created = True
+                    if self.pid == 0:
+                        # Child
+                        try:
+                            # Close parent's pipe ends
+                            if p2cwrite is not None:
+                                os.close(p2cwrite)
+                            if c2pread is not None:
+                                os.close(c2pread)
+                            if errread is not None:
+                                os.close(errread)
+                            os.close(errpipe_read)
+
+                            # Dup fds for child
+                            def _dup2(a, b):
+                                # dup2() removes the CLOEXEC flag but
+                                # we must do it ourselves if dup2()
+                                # would be a no-op (issue #10806).
+                                if a == b:
+                                    self._set_cloexec_flag(a, False)
+                                elif a is not None:
+                                    os.dup2(a, b)
+                            _dup2(p2cread, 0)
+                            _dup2(c2pwrite, 1)
+                            _dup2(errwrite, 2)
+
+                            # Close pipe fds.  Make sure we don't close the
+                            # same fd more than once, or standard fds.
+                            closed = { None }
+                            for fd in [p2cread, c2pwrite, errwrite]:
+                                if fd not in closed and fd > 2:
+                                    os.close(fd)
+                                    closed.add(fd)
+
+                            # Close all other fds, if asked for
+                            if close_fds:
+                                self._close_fds(but=errpipe_write)
+
+                            if cwd is not None:
+                                os.chdir(cwd)
+
+                            if preexec_fn:
+                                preexec_fn()
+
+                            if env is None:
+                                os.execvp(executable, args)
+                            else:
+                                os.execvpe(executable, args, env)
+
+                        except:
+                            exc_type, exc_value, tb = sys.exc_info()
+                            # Save the traceback and attach it to the exception object
+                            exc_lines = traceback.format_exception(exc_type,
+                                                                   exc_value,
+                                                                   tb)
+                            exc_value.child_traceback = ''.join(exc_lines)
+                            os.write(errpipe_write, pickle.dumps(exc_value))
+
+                        # This exitcode won't be reported to applications, so it
+                        # really doesn't matter what we return.
+                        os._exit(255)
+
+                    # Parent
+                    if gc_was_enabled:
+                        gc.enable()
+                finally:
+                    # be sure the FD is closed no matter what
+                    os.close(errpipe_write)
+
+                if p2cread is not None and p2cwrite is not None:
+                    os.close(p2cread)
+                if c2pwrite is not None and c2pread is not None:
+                    os.close(c2pwrite)
+                if errwrite is not None and errread is not None:
+                    os.close(errwrite)
+
+                # Wait for exec to fail or succeed; possibly raising exception
+                # Exception limited to 1M
+                data = _eintr_retry_call(os.read, errpipe_read, 1048576)
+            finally:
+                # be sure the FD is closed no matter what
+                os.close(errpipe_read)
+
+            if data != "":
+                try:
+                    _eintr_retry_call(os.waitpid, self.pid, 0)
+                except OSError as e:
+                    if e.errno != errno.ECHILD:
+                        raise
+                child_exception = pickle.loads(data)
+                for fd in (p2cwrite, c2pread, errread):
+                    if fd is not None:
+                        os.close(fd)
+                raise child_exception
+
+
+        def _handle_exitstatus(self, sts, _WIFSIGNALED=os.WIFSIGNALED,
+                _WTERMSIG=os.WTERMSIG, _WIFEXITED=os.WIFEXITED,
+                _WEXITSTATUS=os.WEXITSTATUS):
+            # This method is called (indirectly) by __del__, so it cannot
+            # refer to anything outside of its local scope."""
+            if _WIFSIGNALED(sts):
+                self.returncode = -_WTERMSIG(sts)
+            elif _WIFEXITED(sts):
+                self.returncode = _WEXITSTATUS(sts)
+            else:
+                # Should never happen
+                raise RuntimeError("Unknown child exit status!")
+
+
+        def _internal_poll(self, _deadstate=None, _waitpid=os.waitpid,
+                _WNOHANG=os.WNOHANG, _os_error=os.error):
+            """Check if child process has terminated.  Returns returncode
+            attribute.
+
+            This method is called by __del__, so it cannot reference anything
+            outside of the local scope (nor can any methods it calls).
+
+            """
+            if self.returncode is None:
+                try:
+                    pid, sts = _waitpid(self.pid, _WNOHANG)
+                    if pid == self.pid:
+                        self._handle_exitstatus(sts)
+                except _os_error:
+                    if _deadstate is not None:
+                        self.returncode = _deadstate
+            return self.returncode
+
+
+        def wait(self):
+            """Wait for child process to terminate.  Returns returncode
+            attribute."""
+            if self.returncode is None:
+                try:
+                    pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0)
+                except OSError as e:
+                    if e.errno != errno.ECHILD:
+                        raise
+                    # This happens if SIGCLD is set to be ignored or waiting
+                    # for child processes has otherwise been disabled for our
+                    # process.  This child is dead, we can't get the status.
+                    sts = 0
+                self._handle_exitstatus(sts)
+            return self.returncode
+
+
+        def _communicate(self, input):
+            if self.stdin:
+                # Flush stdio buffer.  This might block, if the user has
+                # been writing to .stdin in an uncontrolled fashion.
+                self.stdin.flush()
+                if not input:
+                    self.stdin.close()
+
+            if _has_poll:
+                stdout, stderr = self._communicate_with_poll(input)
+            else:
+                stdout, stderr = self._communicate_with_select(input)
+
+            # All data exchanged.  Translate lists into strings.
+            if stdout is not None:
+                stdout = ''.join(stdout)
+            if stderr is not None:
+                stderr = ''.join(stderr)
+
+            # Translate newlines, if requested.  We cannot let the file
+            # object do the translation: It is based on stdio, which is
+            # impossible to combine with select (unless forcing no
+            # buffering).
+            if self.universal_newlines and hasattr(file, 'newlines'):
+                if stdout:
+                    stdout = self._translate_newlines(stdout)
+                if stderr:
+                    stderr = self._translate_newlines(stderr)
+
+            self.wait()
+            return (stdout, stderr)
+
+
+        def _communicate_with_poll(self, input):
+            stdout = None # Return
+            stderr = None # Return
+            fd2file = {}
+            fd2output = {}
+
+            poller = select.poll()
+            def register_and_append(file_obj, eventmask):
+                poller.register(file_obj.fileno(), eventmask)
+                fd2file[file_obj.fileno()] = file_obj
+
+            def close_unregister_and_remove(fd):
+                poller.unregister(fd)
+                fd2file[fd].close()
+                fd2file.pop(fd)
+
+            if self.stdin and input:
+                register_and_append(self.stdin, select.POLLOUT)
+
+            select_POLLIN_POLLPRI = select.POLLIN | select.POLLPRI
+            if self.stdout:
+                register_and_append(self.stdout, select_POLLIN_POLLPRI)
+                fd2output[self.stdout.fileno()] = stdout = []
+            if self.stderr:
+                register_and_append(self.stderr, select_POLLIN_POLLPRI)
+                fd2output[self.stderr.fileno()] = stderr = []
+
+            input_offset = 0
+            while fd2file:
+                try:
+                    ready = poller.poll()
+                except select.error, e:
+                    if e.args[0] == errno.EINTR:
+                        continue
+                    raise
+
+                for fd, mode in ready:
+                    if mode & select.POLLOUT:
+                        chunk = input[input_offset : input_offset + _PIPE_BUF]
+                        input_offset += os.write(fd, chunk)
+                        if input_offset >= len(input):
+                            close_unregister_and_remove(fd)
+                    elif mode & select_POLLIN_POLLPRI:
+                        data = os.read(fd, 4096)
+                        if not data:
+                            close_unregister_and_remove(fd)
+                        fd2output[fd].append(data)
+                    else:
+                        # Ignore hang up or errors.
+                        close_unregister_and_remove(fd)
+
+            return (stdout, stderr)
+
+
+        def _communicate_with_select(self, input):
+            read_set = []
+            write_set = []
+            stdout = None # Return
+            stderr = None # Return
+
+            if self.stdin and input:
+                write_set.append(self.stdin)
+            if self.stdout:
+                read_set.append(self.stdout)
+                stdout = []
+            if self.stderr:
+                read_set.append(self.stderr)
+                stderr = []
+
+            input_offset = 0
+            while read_set or write_set:
+                try:
+                    rlist, wlist, xlist = select.select(read_set, write_set, [])
+                except select.error, e:
+                    if e.args[0] == errno.EINTR:
+                        continue
+                    raise
+
+                if self.stdin in wlist:
+                    chunk = input[input_offset : input_offset + _PIPE_BUF]
+                    bytes_written = os.write(self.stdin.fileno(), chunk)
+                    input_offset += bytes_written
+                    if input_offset >= len(input):
+                        self.stdin.close()
+                        write_set.remove(self.stdin)
+
+                if self.stdout in rlist:
+                    data = os.read(self.stdout.fileno(), 1024)
+                    if data == "":
+                        self.stdout.close()
+                        read_set.remove(self.stdout)
+                    stdout.append(data)
+
+                if self.stderr in rlist:
+                    data = os.read(self.stderr.fileno(), 1024)
+                    if data == "":
+                        self.stderr.close()
+                        read_set.remove(self.stderr)
+                    stderr.append(data)
+
+            return (stdout, stderr)
+
+
+        def send_signal(self, sig):
+            """Send a signal to the process
+            """
+            os.kill(self.pid, sig)
+
+        def terminate(self):
+            """Terminate the process with SIGTERM
+            """
+            self.send_signal(signal.SIGTERM)
+
+        def kill(self):
+            """Kill the process with SIGKILL
+            """
+            self.send_signal(signal.SIGKILL)
+
+
+def _demo_posix():
+    #
+    # Example 1: Simple redirection: Get process list
+    #
+    plist = Popen(["ps"], stdout=PIPE).communicate()[0]
+    print "Process list:"
+    print plist
+
+    #
+    # Example 2: Change uid before executing child
+    #
+    if os.getuid() == 0:
+        p = Popen(["id"], preexec_fn=lambda: os.setuid(100))
+        p.wait()
+
+    #
+    # Example 3: Connecting several subprocesses
+    #
+    print "Looking for 'hda'..."
+    p1 = Popen(["dmesg"], stdout=PIPE)
+    p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
+    print repr(p2.communicate()[0])
+
+    #
+    # Example 4: Catch execution error
+    #
+    print
+    print "Trying a weird file..."
+    try:
+        print Popen(["/this/path/does/not/exist"]).communicate()
+    except OSError, e:
+        if e.errno == errno.ENOENT:
+            print "The file didn't exist.  I thought so..."
+            print "Child traceback:"
+            print e.child_traceback
+        else:
+            print "Error", e.errno
+    else:
+        print >>sys.stderr, "Gosh.  No error."
+
+
+def _demo_windows():
+    #
+    # Example 1: Connecting several subprocesses
+    #
+    print "Looking for 'PROMPT' in set output..."
+    p1 = Popen("set", stdout=PIPE, shell=True)
+    p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE)
+    print repr(p2.communicate()[0])
+
+    #
+    # Example 2: Simple execution of program
+    #
+    print "Executing calc..."
+    p = Popen("calc")
+    p.wait()
+
+
+def _demo_jython():
+    #
+    # Example 1: Return the number of processors on this machine
+    #
+    print "Running a jython subprocess to return the number of processors..."
+    p = Popen([sys.executable, "-c",
+               ('import sys;'
+                'from java.lang import Runtime;'
+                'sys.exit(Runtime.getRuntime().availableProcessors())')])
+    print p.wait()
+
+    #
+    # Example 2: Connecting several subprocesses
+    #
+    print "Connecting two jython subprocesses..."
+    p1 = Popen([sys.executable, "-c",
+                ('import os;'
+                 'print os.environ["foo"]')], env=dict(foo='bar'),
+               stdout=PIPE)
+    p2 = Popen([sys.executable, "-c",
+                ('import os, sys;'
+                 'their_foo = sys.stdin.read().strip();'
+                 'my_foo = os.environ["foo"];'
+                 'msg = "Their env\'s foo: %r, My env\'s foo: %r";'
+                 'print msg % (their_foo, my_foo)')],
+               env=dict(foo='baz'), stdin=p1.stdout, stdout=PIPE)
+    print p2.communicate()[0]
+
+
+if __name__ == "__main__":
+    if mswindows:
+        _demo_windows()
+    elif jython:
+        _demo_jython()
+    else:
+        _demo_posix()
diff --git a/src/main/resources/PythonLibs/symbol.py b/src/main/resources/PythonLibs/symbol.py
new file mode 100644
index 0000000000000000000000000000000000000000..b4d4e13ab80994818070133698ad1ce5baa8fe36
--- /dev/null
+++ b/src/main/resources/PythonLibs/symbol.py
@@ -0,0 +1,114 @@
+#! /usr/bin/env python
+
+"""Non-terminal symbols of Python grammar (from "graminit.h")."""
+
+#  This file is automatically generated; please don't muck it up!
+#
+#  To update the symbols in this file, 'cd' to the top directory of
+#  the python source tree after building the interpreter and run:
+#
+#    ./python Lib/symbol.py
+
+#--start constants--
+single_input = 256
+file_input = 257
+eval_input = 258
+decorator = 259
+decorators = 260
+decorated = 261
+funcdef = 262
+parameters = 263
+varargslist = 264
+fpdef = 265
+fplist = 266
+stmt = 267
+simple_stmt = 268
+small_stmt = 269
+expr_stmt = 270
+augassign = 271
+print_stmt = 272
+del_stmt = 273
+pass_stmt = 274
+flow_stmt = 275
+break_stmt = 276
+continue_stmt = 277
+return_stmt = 278
+yield_stmt = 279
+raise_stmt = 280
+import_stmt = 281
+import_name = 282
+import_from = 283
+import_as_name = 284
+dotted_as_name = 285
+import_as_names = 286
+dotted_as_names = 287
+dotted_name = 288
+global_stmt = 289
+exec_stmt = 290
+assert_stmt = 291
+compound_stmt = 292
+if_stmt = 293
+while_stmt = 294
+for_stmt = 295
+try_stmt = 296
+with_stmt = 297
+with_item = 298
+except_clause = 299
+suite = 300
+testlist_safe = 301
+old_test = 302
+old_lambdef = 303
+test = 304
+or_test = 305
+and_test = 306
+not_test = 307
+comparison = 308
+comp_op = 309
+expr = 310
+xor_expr = 311
+and_expr = 312
+shift_expr = 313
+arith_expr = 314
+term = 315
+factor = 316
+power = 317
+atom = 318
+listmaker = 319
+testlist_comp = 320
+lambdef = 321
+trailer = 322
+subscriptlist = 323
+subscript = 324
+sliceop = 325
+exprlist = 326
+testlist = 327
+dictorsetmaker = 328
+classdef = 329
+arglist = 330
+argument = 331
+list_iter = 332
+list_for = 333
+list_if = 334
+comp_iter = 335
+comp_for = 336
+comp_if = 337
+testlist1 = 338
+encoding_decl = 339
+yield_expr = 340
+#--end constants--
+
+sym_name = {}
+for _name, _value in globals().items():
+    if type(_value) is type(0):
+        sym_name[_value] = _name
+
+
+def main():
+    import sys
+    import token
+    if len(sys.argv) == 1:
+        sys.argv = sys.argv + ["Include/graminit.h", "Lib/symbol.py"]
+    token.main()
+
+if __name__ == "__main__":
+    main()
diff --git a/src/main/resources/PythonLibs/sysconfig.py b/src/main/resources/PythonLibs/sysconfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..f5ab0dff4d7b18d1057eec4a3527f4396e07cbf1
--- /dev/null
+++ b/src/main/resources/PythonLibs/sysconfig.py
@@ -0,0 +1,713 @@
+"""Provide access to Python's configuration information.
+
+"""
+import sys
+import os
+from os.path import pardir, realpath
+
+_INSTALL_SCHEMES = {
+    'posix_prefix': {
+        'stdlib': '{base}/lib/python{py_version_short}',
+        'platstdlib': '{platbase}/lib/python{py_version_short}',
+        'purelib': '{base}/lib/python{py_version_short}/site-packages',
+        'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
+        'include': '{base}/include/python{py_version_short}',
+        'platinclude': '{platbase}/include/python{py_version_short}',
+        'scripts': '{base}/bin',
+        'data': '{base}',
+        },
+    'posix_home': {
+        'stdlib': '{base}/lib/python',
+        'platstdlib': '{base}/lib/python',
+        'purelib': '{base}/lib/python',
+        'platlib': '{base}/lib/python',
+        'include': '{base}/include/python',
+        'platinclude': '{base}/include/python',
+        'scripts': '{base}/bin',
+        'data'   : '{base}',
+        },
+    'nt': {
+        'stdlib': '{base}/Lib',
+        'platstdlib': '{base}/Lib',
+        'purelib': '{base}/Lib/site-packages',
+        'platlib': '{base}/Lib/site-packages',
+        'include': '{base}/Include',
+        'platinclude': '{base}/Include',
+        'scripts': '{base}/Scripts',
+        'data'   : '{base}',
+        },
+    'os2': {
+        'stdlib': '{base}/Lib',
+        'platstdlib': '{base}/Lib',
+        'purelib': '{base}/Lib/site-packages',
+        'platlib': '{base}/Lib/site-packages',
+        'include': '{base}/Include',
+        'platinclude': '{base}/Include',
+        'scripts': '{base}/Scripts',
+        'data'   : '{base}',
+        },
+    'os2_home': {
+        'stdlib': '{userbase}/lib/python{py_version_short}',
+        'platstdlib': '{userbase}/lib/python{py_version_short}',
+        'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
+        'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
+        'include': '{userbase}/include/python{py_version_short}',
+        'scripts': '{userbase}/bin',
+        'data'   : '{userbase}',
+        },
+    'nt_user': {
+        'stdlib': '{userbase}/Python{py_version_nodot}',
+        'platstdlib': '{userbase}/Python{py_version_nodot}',
+        'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
+        'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
+        'include': '{userbase}/Python{py_version_nodot}/Include',
+        'scripts': '{userbase}/Scripts',
+        'data'   : '{userbase}',
+        },
+    'posix_user': {
+        'stdlib': '{userbase}/lib/python{py_version_short}',
+        'platstdlib': '{userbase}/lib/python{py_version_short}',
+        'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
+        'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
+        'include': '{userbase}/include/python{py_version_short}',
+        'scripts': '{userbase}/bin',
+        'data'   : '{userbase}',
+        },
+    'osx_framework_user': {
+        'stdlib': '{userbase}/lib/python',
+        'platstdlib': '{userbase}/lib/python',
+        'purelib': '{userbase}/lib/python/site-packages',
+        'platlib': '{userbase}/lib/python/site-packages',
+        'include': '{userbase}/include',
+        'scripts': '{userbase}/bin',
+        'data'   : '{userbase}',
+        },
+    'java': {
+        'stdlib': '{base}/lib/jython',
+        'platstdlib': '{base}/lib/jython',
+        'purelib': '{base}/lib/jython',
+        'platlib': '{base}/lib/jython',
+        'include': '{base}/include/jython',
+        'platinclude': '{base}/include/jython',
+        'scripts': '{base}/bin',
+        'data'   : '{base}',
+        },
+
+    'java_user': {
+        'stdlib': '{userbase}/lib/jython{py_version_short}',
+        'platstdlib': '{userbase}/lib/jython{py_version_short}',
+        'purelib': '{userbase}/lib/jython{py_version_short}/site-packages',
+        'platlib': '{userbase}/lib/jython{py_version_short}/site-packages',
+        'include': '{userbase}/include/jython{py_version_short}',
+        'scripts': '{userbase}/bin',
+        'data'   : '{userbase}',
+        },
+    }
+
+_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
+                'scripts', 'data')
+_PY_VERSION = sys.version.split()[0]
+_PY_VERSION_SHORT = sys.version[:3]
+_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
+_PREFIX = os.path.normpath(sys.prefix)
+_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
+_CONFIG_VARS = None
+_USER_BASE = None
+
+def _safe_realpath(path):
+    try:
+        return realpath(path)
+    except OSError:
+        return path
+
+if sys.executable:
+    _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
+else:
+    # sys.executable can be empty if argv[0] has been changed and Python is
+    # unable to retrieve the real program name
+    _PROJECT_BASE = _safe_realpath(os.getcwd())
+
+if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
+    _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
+# PC/VS7.1
+if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
+    _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
+# PC/AMD64
+if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
+    _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
+
+def is_python_build():
+    for fn in ("Setup.dist", "Setup.local"):
+        if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
+            return True
+    return False
+
+_PYTHON_BUILD = is_python_build()
+
+if _PYTHON_BUILD:
+    for scheme in ('posix_prefix', 'posix_home'):
+        _INSTALL_SCHEMES[scheme]['include'] = '{projectbase}/Include'
+        _INSTALL_SCHEMES[scheme]['platinclude'] = '{srcdir}'
+
+def _subst_vars(s, local_vars):
+    try:
+        return s.format(**local_vars)
+    except KeyError:
+        try:
+            return s.format(**os.environ)
+        except KeyError, var:
+            raise AttributeError('{%s}' % var)
+
+def _extend_dict(target_dict, other_dict):
+    target_keys = target_dict.keys()
+    for key, value in other_dict.items():
+        if key in target_keys:
+            continue
+        target_dict[key] = value
+
+def _expand_vars(scheme, vars):
+    res = {}
+    if vars is None:
+        vars = {}
+    _extend_dict(vars, get_config_vars())
+
+    for key, value in _INSTALL_SCHEMES[scheme].items():
+        if os.name in ('posix', 'nt', 'java'):
+            value = os.path.expanduser(value)
+        res[key] = os.path.normpath(_subst_vars(value, vars))
+    return res
+
+def _get_default_scheme():
+    if os.name == 'posix':
+        # the default scheme for posix is posix_prefix
+        return 'posix_prefix'
+    return os.name
+
+def _getuserbase():
+    env_base = os.environ.get("PYTHONUSERBASE", None)
+    def joinuser(*args):
+        return os.path.expanduser(os.path.join(*args))
+
+    # what about 'os2emx', 'riscos' ?
+    if os.name == "nt":
+        base = os.environ.get("APPDATA") or "~"
+        return env_base if env_base else joinuser(base, "Python")
+
+    if sys.platform == "darwin":
+        framework = get_config_var("PYTHONFRAMEWORK")
+        if framework:
+            return env_base if env_base else \
+                               joinuser("~", "Library", framework, "%d.%d"
+                                            % (sys.version_info[:2]))
+
+    return env_base if env_base else joinuser("~", ".local")
+
+
+def _parse_makefile(filename, vars=None):
+    """Parse a Makefile-style file.
+
+    A dictionary containing name/value pairs is returned.  If an
+    optional dictionary is passed in as the second argument, it is
+    used instead of a new dictionary.
+    """
+    import re
+    # Regexes needed for parsing Makefile (and similar syntaxes,
+    # like old-style Setup files).
+    _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
+    _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
+    _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
+
+    if vars is None:
+        vars = {}
+    done = {}
+    notdone = {}
+
+    with open(filename) as f:
+        lines = f.readlines()
+
+    for line in lines:
+        if line.startswith('#') or line.strip() == '':
+            continue
+        m = _variable_rx.match(line)
+        if m:
+            n, v = m.group(1, 2)
+            v = v.strip()
+            # `$$' is a literal `$' in make
+            tmpv = v.replace('$$', '')
+
+            if "$" in tmpv:
+                notdone[n] = v
+            else:
+                try:
+                    v = int(v)
+                except ValueError:
+                    # insert literal `$'
+                    done[n] = v.replace('$$', '$')
+                else:
+                    done[n] = v
+
+    # do variable interpolation here
+    while notdone:
+        for name in notdone.keys():
+            value = notdone[name]
+            m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
+            if m:
+                n = m.group(1)
+                found = True
+                if n in done:
+                    item = str(done[n])
+                elif n in notdone:
+                    # get it on a subsequent round
+                    found = False
+                elif n in os.environ:
+                    # do it like make: fall back to environment
+                    item = os.environ[n]
+                else:
+                    done[n] = item = ""
+                if found:
+                    after = value[m.end():]
+                    value = value[:m.start()] + item + after
+                    if "$" in after:
+                        notdone[name] = value
+                    else:
+                        try: value = int(value)
+                        except ValueError:
+                            done[name] = value.strip()
+                        else:
+                            done[name] = value
+                        del notdone[name]
+            else:
+                # bogus variable reference; just drop it since we can't deal
+                del notdone[name]
+    # strip spurious spaces
+    for k, v in done.items():
+        if isinstance(v, str):
+            done[k] = v.strip()
+
+    # save the results in the global dictionary
+    vars.update(done)
+    return vars
+
+
+def _get_makefile_filename():
+    if _PYTHON_BUILD:
+        return os.path.join(_PROJECT_BASE, "Makefile")
+    return os.path.join(get_path('platstdlib'), "config", "Makefile")
+
+
+def _init_posix(vars):
+    """Initialize the module as appropriate for POSIX systems."""
+    # load the installed Makefile:
+    makefile = _get_makefile_filename()
+    try:
+        _parse_makefile(makefile, vars)
+    except IOError, e:
+        msg = "invalid Python installation: unable to open %s" % makefile
+        if hasattr(e, "strerror"):
+            msg = msg + " (%s)" % e.strerror
+        raise IOError(msg)
+
+    # load the installed pyconfig.h:
+    config_h = get_config_h_filename()
+    try:
+        with open(config_h) as f:
+            parse_config_h(f, vars)
+    except IOError, e:
+        msg = "invalid Python installation: unable to open %s" % config_h
+        if hasattr(e, "strerror"):
+            msg = msg + " (%s)" % e.strerror
+        raise IOError(msg)
+
+    # On AIX, there are wrong paths to the linker scripts in the Makefile
+    # -- these paths are relative to the Python source, but when installed
+    # the scripts are in another directory.
+    if _PYTHON_BUILD:
+        vars['LDSHARED'] = vars['BLDSHARED']
+
+def _init_non_posix(vars):
+    """Initialize the module as appropriate for NT"""
+    # set basic install directories
+    vars['LIBDEST'] = get_path('stdlib')
+    vars['BINLIBDEST'] = get_path('platstdlib')
+    vars['INCLUDEPY'] = get_path('include')
+    vars['SO'] = '.pyd'
+    vars['EXE'] = '.exe'
+    vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
+    vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
+
+#
+# public APIs
+#
+
+
+def parse_config_h(fp, vars=None):
+    """Parse a config.h-style file.
+
+    A dictionary containing name/value pairs is returned.  If an
+    optional dictionary is passed in as the second argument, it is
+    used instead of a new dictionary.
+    """
+    import re
+    if vars is None:
+        vars = {}
+    define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
+    undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
+
+    while True:
+        line = fp.readline()
+        if not line:
+            break
+        m = define_rx.match(line)
+        if m:
+            n, v = m.group(1, 2)
+            try: v = int(v)
+            except ValueError: pass
+            vars[n] = v
+        else:
+            m = undef_rx.match(line)
+            if m:
+                vars[m.group(1)] = 0
+    return vars
+
+def get_config_h_filename():
+    """Returns the path of pyconfig.h."""
+    if _PYTHON_BUILD:
+        if os.name == "nt":
+            inc_dir = os.path.join(_PROJECT_BASE, "PC")
+        else:
+            inc_dir = _PROJECT_BASE
+    else:
+        inc_dir = get_path('platinclude')
+    return os.path.join(inc_dir, 'pyconfig.h')
+
+def get_scheme_names():
+    """Returns a tuple containing the schemes names."""
+    schemes = _INSTALL_SCHEMES.keys()
+    schemes.sort()
+    return tuple(schemes)
+
+def get_path_names():
+    """Returns a tuple containing the paths names."""
+    return _SCHEME_KEYS
+
+def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
+    """Returns a mapping containing an install scheme.
+
+    ``scheme`` is the install scheme name. If not provided, it will
+    return the default scheme for the current platform.
+    """
+    if expand:
+        return _expand_vars(scheme, vars)
+    else:
+        return _INSTALL_SCHEMES[scheme]
+
+def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
+    """Returns a path corresponding to the scheme.
+
+    ``scheme`` is the install scheme name.
+    """
+    return get_paths(scheme, vars, expand)[name]
+
+def get_config_vars(*args):
+    """With no arguments, return a dictionary of all configuration
+    variables relevant for the current platform.
+
+    On Unix, this means every variable defined in Python's installed Makefile;
+    On Windows and Mac OS it's a much smaller set.
+
+    With arguments, return a list of values that result from looking up
+    each argument in the configuration variable dictionary.
+    """
+    import re
+    global _CONFIG_VARS
+    if _CONFIG_VARS is None:
+        _CONFIG_VARS = {}
+        # Normalized versions of prefix and exec_prefix are handy to have;
+        # in fact, these are the standard versions used most places in the
+        # Distutils.
+        _CONFIG_VARS['prefix'] = _PREFIX
+        _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
+        _CONFIG_VARS['py_version'] = _PY_VERSION
+        _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
+        _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
+        _CONFIG_VARS['base'] = _PREFIX
+        _CONFIG_VARS['platbase'] = _EXEC_PREFIX
+        _CONFIG_VARS['projectbase'] = _PROJECT_BASE
+
+        if os.name in ('nt', 'os2'):
+            _init_non_posix(_CONFIG_VARS)
+        if os.name == 'posix':
+            _init_posix(_CONFIG_VARS)
+
+        # Setting 'userbase' is done below the call to the
+        # init function to enable using 'get_config_var' in
+        # the init-function.
+        _CONFIG_VARS['userbase'] = _getuserbase()
+
+        if 'srcdir' not in _CONFIG_VARS:
+            _CONFIG_VARS['srcdir'] = _PROJECT_BASE
+
+        # Convert srcdir into an absolute path if it appears necessary.
+        # Normally it is relative to the build directory.  However, during
+        # testing, for example, we might be running a non-installed python
+        # from a different directory.
+        if _PYTHON_BUILD and os.name == "posix":
+            base = _PROJECT_BASE
+            try:
+                cwd = os.getcwd()
+            except OSError:
+                cwd = None
+            if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
+                base != cwd):
+                # srcdir is relative and we are not in the same directory
+                # as the executable. Assume executable is in the build
+                # directory and make srcdir absolute.
+                srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
+                _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
+
+        if sys.platform == 'darwin':
+            kernel_version = os.uname()[2] # Kernel version (8.4.3)
+            major_version = int(kernel_version.split('.')[0])
+
+            if major_version < 8:
+                # On Mac OS X before 10.4, check if -arch and -isysroot
+                # are in CFLAGS or LDFLAGS and remove them if they are.
+                # This is needed when building extensions on a 10.3 system
+                # using a universal build of python.
+                for key in ('LDFLAGS', 'BASECFLAGS',
+                        # a number of derived variables. These need to be
+                        # patched up as well.
+                        'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
+                    flags = _CONFIG_VARS[key]
+                    flags = re.sub('-arch\s+\w+\s', ' ', flags)
+                    flags = re.sub('-isysroot [^ \t]*', ' ', flags)
+                    _CONFIG_VARS[key] = flags
+            else:
+                # Allow the user to override the architecture flags using
+                # an environment variable.
+                # NOTE: This name was introduced by Apple in OSX 10.5 and
+                # is used by several scripting languages distributed with
+                # that OS release.
+                if 'ARCHFLAGS' in os.environ:
+                    arch = os.environ['ARCHFLAGS']
+                    for key in ('LDFLAGS', 'BASECFLAGS',
+                        # a number of derived variables. These need to be
+                        # patched up as well.
+                        'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
+
+                        flags = _CONFIG_VARS[key]
+                        flags = re.sub('-arch\s+\w+\s', ' ', flags)
+                        flags = flags + ' ' + arch
+                        _CONFIG_VARS[key] = flags
+
+                # If we're on OSX 10.5 or later and the user tries to
+                # compiles an extension using an SDK that is not present
+                # on the current machine it is better to not use an SDK
+                # than to fail.
+                #
+                # The major usecase for this is users using a Python.org
+                # binary installer  on OSX 10.6: that installer uses
+                # the 10.4u SDK, but that SDK is not installed by default
+                # when you install Xcode.
+                #
+                CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
+                m = re.search('-isysroot\s+(\S+)', CFLAGS)
+                if m is not None:
+                    sdk = m.group(1)
+                    if not os.path.exists(sdk):
+                        for key in ('LDFLAGS', 'BASECFLAGS',
+                             # a number of derived variables. These need to be
+                             # patched up as well.
+                            'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
+
+                            flags = _CONFIG_VARS[key]
+                            flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
+                            _CONFIG_VARS[key] = flags
+
+    if args:
+        vals = []
+        for name in args:
+            vals.append(_CONFIG_VARS.get(name))
+        return vals
+    else:
+        return _CONFIG_VARS
+
+def get_config_var(name):
+    """Return the value of a single variable using the dictionary returned by
+    'get_config_vars()'.
+
+    Equivalent to get_config_vars().get(name)
+    """
+    return get_config_vars().get(name)
+
+def get_platform():
+    """Return a string that identifies the current platform.
+
+    This is used mainly to distinguish platform-specific build directories and
+    platform-specific built distributions.  Typically includes the OS name
+    and version and the architecture (as supplied by 'os.uname()'),
+    although the exact information included depends on the OS; eg. for IRIX
+    the architecture isn't particularly important (IRIX only runs on SGI
+    hardware), but for Linux the kernel version isn't particularly
+    important.
+
+    Examples of returned values:
+       linux-i586
+       linux-alpha (?)
+       solaris-2.6-sun4u
+       irix-5.3
+       irix64-6.2
+
+    Windows will return one of:
+       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
+       win-ia64 (64bit Windows on Itanium)
+       win32 (all others - specifically, sys.platform is returned)
+
+    For other non-POSIX platforms, currently just returns 'sys.platform'.
+    """
+    import re
+    if os.name == 'nt':
+        # sniff sys.version for architecture.
+        prefix = " bit ("
+        i = sys.version.find(prefix)
+        if i == -1:
+            return sys.platform
+        j = sys.version.find(")", i)
+        look = sys.version[i+len(prefix):j].lower()
+        if look == 'amd64':
+            return 'win-amd64'
+        if look == 'itanium':
+            return 'win-ia64'
+        return sys.platform
+
+    if os.name != "posix" or not hasattr(os, 'uname'):
+        # XXX what about the architecture? NT is Intel or Alpha,
+        # Mac OS is M68k or PPC, etc.
+        return sys.platform
+
+    # Try to distinguish various flavours of Unix
+    osname, host, release, version, machine = os.uname()
+
+    # Convert the OS name to lowercase, remove '/' characters
+    # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
+    osname = osname.lower().replace('/', '')
+    machine = machine.replace(' ', '_')
+    machine = machine.replace('/', '-')
+
+    if osname[:5] == "linux":
+        # At least on Linux/Intel, 'machine' is the processor --
+        # i386, etc.
+        # XXX what about Alpha, SPARC, etc?
+        return  "%s-%s" % (osname, machine)
+    elif osname[:5] == "sunos":
+        if release[0] >= "5":           # SunOS 5 == Solaris 2
+            osname = "solaris"
+            release = "%d.%s" % (int(release[0]) - 3, release[2:])
+            # We can't use "platform.architecture()[0]" because a
+            # bootstrap problem. We use a dict to get an error
+            # if some suspicious happens.
+            bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
+            machine += ".%s" % bitness[sys.maxint]
+        # fall through to standard osname-release-machine representation
+    elif osname[:4] == "irix":              # could be "irix64"!
+        return "%s-%s" % (osname, release)
+    elif osname[:3] == "aix":
+        return "%s-%s.%s" % (osname, version, release)
+    elif osname[:6] == "cygwin":
+        osname = "cygwin"
+        rel_re = re.compile (r'[\d.]+')
+        m = rel_re.match(release)
+        if m:
+            release = m.group()
+    elif osname[:6] == "darwin":
+        #
+        # For our purposes, we'll assume that the system version from
+        # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
+        # to. This makes the compatibility story a bit more sane because the
+        # machine is going to compile and link as if it were
+        # MACOSX_DEPLOYMENT_TARGET.
+        cfgvars = get_config_vars()
+        macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
+
+        if 1:
+            # Always calculate the release of the running machine,
+            # needed to determine if we can build fat binaries or not.
+
+            macrelease = macver
+            # Get the system version. Reading this plist is a documented
+            # way to get the system version (see the documentation for
+            # the Gestalt Manager)
+            try:
+                f = open('/System/Library/CoreServices/SystemVersion.plist')
+            except IOError:
+                # We're on a plain darwin box, fall back to the default
+                # behaviour.
+                pass
+            else:
+                try:
+                    m = re.search(
+                            r'<key>ProductUserVisibleVersion</key>\s*' +
+                            r'<string>(.*?)</string>', f.read())
+                    if m is not None:
+                        macrelease = '.'.join(m.group(1).split('.')[:2])
+                    # else: fall back to the default behaviour
+                finally:
+                    f.close()
+
+        if not macver:
+            macver = macrelease
+
+        if macver:
+            release = macver
+            osname = "macosx"
+
+            if (macrelease + '.') >= '10.4.' and \
+                    '-arch' in get_config_vars().get('CFLAGS', '').strip():
+                # The universal build will build fat binaries, but not on
+                # systems before 10.4
+                #
+                # Try to detect 4-way universal builds, those have machine-type
+                # 'universal' instead of 'fat'.
+
+                machine = 'fat'
+                cflags = get_config_vars().get('CFLAGS')
+
+                archs = re.findall('-arch\s+(\S+)', cflags)
+                archs = tuple(sorted(set(archs)))
+
+                if len(archs) == 1:
+                    machine = archs[0]
+                elif archs == ('i386', 'ppc'):
+                    machine = 'fat'
+                elif archs == ('i386', 'x86_64'):
+                    machine = 'intel'
+                elif archs == ('i386', 'ppc', 'x86_64'):
+                    machine = 'fat3'
+                elif archs == ('ppc64', 'x86_64'):
+                    machine = 'fat64'
+                elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
+                    machine = 'universal'
+                else:
+                    raise ValueError(
+                       "Don't know machine value for archs=%r"%(archs,))
+
+            elif machine == 'i386':
+                # On OSX the machine type returned by uname is always the
+                # 32-bit variant, even if the executable architecture is
+                # the 64-bit variant
+                if sys.maxint >= 2**32:
+                    machine = 'x86_64'
+
+            elif machine in ('PowerPC', 'Power_Macintosh'):
+                # Pick a sane name for the PPC architecture.
+                # See 'i386' case
+                if sys.maxint >= 2**32:
+                    machine = 'ppc64'
+                else:
+                    machine = 'ppc'
+
+    return "%s-%s-%s" % (osname, release, machine)
+
+
+def get_python_version():
+    return _PY_VERSION_SHORT
diff --git a/src/main/resources/PythonLibs/tabnanny.py b/src/main/resources/PythonLibs/tabnanny.py
new file mode 100644
index 0000000000000000000000000000000000000000..76665ac91a01d290f2771cb9ad6a9d15021f671c
--- /dev/null
+++ b/src/main/resources/PythonLibs/tabnanny.py
@@ -0,0 +1,329 @@
+#! /usr/bin/env python
+
+"""The Tab Nanny despises ambiguous indentation.  She knows no mercy.
+
+tabnanny -- Detection of ambiguous indentation
+
+For the time being this module is intended to be called as a script.
+However it is possible to import it into an IDE and use the function
+check() described below.
+
+Warning: The API provided by this module is likely to change in future
+releases; such changes may not be backward compatible.
+"""
+
+# Released to the public domain, by Tim Peters, 15 April 1998.
+
+# XXX Note: this is now a standard library module.
+# XXX The API needs to undergo changes however; the current code is too
+# XXX script-like.  This will be addressed later.
+
+__version__ = "6"
+
+import os
+import sys
+import getopt
+import tokenize
+if not hasattr(tokenize, 'NL'):
+    raise ValueError("tokenize.NL doesn't exist -- tokenize module too old")
+
+__all__ = ["check", "NannyNag", "process_tokens"]
+
+verbose = 0
+filename_only = 0
+
+def errprint(*args):
+    sep = ""
+    for arg in args:
+        sys.stderr.write(sep + str(arg))
+        sep = " "
+    sys.stderr.write("\n")
+
+def main():
+    global verbose, filename_only
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "qv")
+    except getopt.error, msg:
+        errprint(msg)
+        return
+    for o, a in opts:
+        if o == '-q':
+            filename_only = filename_only + 1
+        if o == '-v':
+            verbose = verbose + 1
+    if not args:
+        errprint("Usage:", sys.argv[0], "[-v] file_or_directory ...")
+        return
+    for arg in args:
+        check(arg)
+
+class NannyNag(Exception):
+    """
+    Raised by tokeneater() if detecting an ambiguous indent.
+    Captured and handled in check().
+    """
+    def __init__(self, lineno, msg, line):
+        self.lineno, self.msg, self.line = lineno, msg, line
+    def get_lineno(self):
+        return self.lineno
+    def get_msg(self):
+        return self.msg
+    def get_line(self):
+        return self.line
+
+def check(file):
+    """check(file_or_dir)
+
+    If file_or_dir is a directory and not a symbolic link, then recursively
+    descend the directory tree named by file_or_dir, checking all .py files
+    along the way. If file_or_dir is an ordinary Python source file, it is
+    checked for whitespace related problems. The diagnostic messages are
+    written to standard output using the print statement.
+    """
+
+    if os.path.isdir(file) and not os.path.islink(file):
+        if verbose:
+            print "%r: listing directory" % (file,)
+        names = os.listdir(file)
+        for name in names:
+            fullname = os.path.join(file, name)
+            if (os.path.isdir(fullname) and
+                not os.path.islink(fullname) or
+                os.path.normcase(name[-3:]) == ".py"):
+                check(fullname)
+        return
+
+    try:
+        f = open(file)
+    except IOError, msg:
+        errprint("%r: I/O Error: %s" % (file, msg))
+        return
+
+    if verbose > 1:
+        print "checking %r ..." % file
+
+    try:
+        process_tokens(tokenize.generate_tokens(f.readline))
+
+    except tokenize.TokenError, msg:
+        errprint("%r: Token Error: %s" % (file, msg))
+        return
+
+    except IndentationError, msg:
+        errprint("%r: Indentation Error: %s" % (file, msg))
+        return
+
+    except NannyNag, nag:
+        badline = nag.get_lineno()
+        line = nag.get_line()
+        if verbose:
+            print "%r: *** Line %d: trouble in tab city! ***" % (file, badline)
+            print "offending line: %r" % (line,)
+            print nag.get_msg()
+        else:
+            if ' ' in file: file = '"' + file + '"'
+            if filename_only: print file
+            else: print file, badline, repr(line)
+        return
+
+    if verbose:
+        print "%r: Clean bill of health." % (file,)
+
+class Whitespace:
+    # the characters used for space and tab
+    S, T = ' \t'
+
+    # members:
+    #   raw
+    #       the original string
+    #   n
+    #       the number of leading whitespace characters in raw
+    #   nt
+    #       the number of tabs in raw[:n]
+    #   norm
+    #       the normal form as a pair (count, trailing), where:
+    #       count
+    #           a tuple such that raw[:n] contains count[i]
+    #           instances of S * i + T
+    #       trailing
+    #           the number of trailing spaces in raw[:n]
+    #       It's A Theorem that m.indent_level(t) ==
+    #       n.indent_level(t) for all t >= 1 iff m.norm == n.norm.
+    #   is_simple
+    #       true iff raw[:n] is of the form (T*)(S*)
+
+    def __init__(self, ws):
+        self.raw  = ws
+        S, T = Whitespace.S, Whitespace.T
+        count = []
+        b = n = nt = 0
+        for ch in self.raw:
+            if ch == S:
+                n = n + 1
+                b = b + 1
+            elif ch == T:
+                n = n + 1
+                nt = nt + 1
+                if b >= len(count):
+                    count = count + [0] * (b - len(count) + 1)
+                count[b] = count[b] + 1
+                b = 0
+            else:
+                break
+        self.n    = n
+        self.nt   = nt
+        self.norm = tuple(count), b
+        self.is_simple = len(count) <= 1
+
+    # return length of longest contiguous run of spaces (whether or not
+    # preceding a tab)
+    def longest_run_of_spaces(self):
+        count, trailing = self.norm
+        return max(len(count)-1, trailing)
+
+    def indent_level(self, tabsize):
+        # count, il = self.norm
+        # for i in range(len(count)):
+        #    if count[i]:
+        #        il = il + (i/tabsize + 1)*tabsize * count[i]
+        # return il
+
+        # quicker:
+        # il = trailing + sum (i/ts + 1)*ts*count[i] =
+        # trailing + ts * sum (i/ts + 1)*count[i] =
+        # trailing + ts * sum i/ts*count[i] + count[i] =
+        # trailing + ts * [(sum i/ts*count[i]) + (sum count[i])] =
+        # trailing + ts * [(sum i/ts*count[i]) + num_tabs]
+        # and note that i/ts*count[i] is 0 when i < ts
+
+        count, trailing = self.norm
+        il = 0
+        for i in range(tabsize, len(count)):
+            il = il + i/tabsize * count[i]
+        return trailing + tabsize * (il + self.nt)
+
+    # return true iff self.indent_level(t) == other.indent_level(t)
+    # for all t >= 1
+    def equal(self, other):
+        return self.norm == other.norm
+
+    # return a list of tuples (ts, i1, i2) such that
+    # i1 == self.indent_level(ts) != other.indent_level(ts) == i2.
+    # Intended to be used after not self.equal(other) is known, in which
+    # case it will return at least one witnessing tab size.
+    def not_equal_witness(self, other):
+        n = max(self.longest_run_of_spaces(),
+                other.longest_run_of_spaces()) + 1
+        a = []
+        for ts in range(1, n+1):
+            if self.indent_level(ts) != other.indent_level(ts):
+                a.append( (ts,
+                           self.indent_level(ts),
+                           other.indent_level(ts)) )
+        return a
+
+    # Return True iff self.indent_level(t) < other.indent_level(t)
+    # for all t >= 1.
+    # The algorithm is due to Vincent Broman.
+    # Easy to prove it's correct.
+    # XXXpost that.
+    # Trivial to prove n is sharp (consider T vs ST).
+    # Unknown whether there's a faster general way.  I suspected so at
+    # first, but no longer.
+    # For the special (but common!) case where M and N are both of the
+    # form (T*)(S*), M.less(N) iff M.len() < N.len() and
+    # M.num_tabs() <= N.num_tabs(). Proof is easy but kinda long-winded.
+    # XXXwrite that up.
+    # Note that M is of the form (T*)(S*) iff len(M.norm[0]) <= 1.
+    def less(self, other):
+        if self.n >= other.n:
+            return False
+        if self.is_simple and other.is_simple:
+            return self.nt <= other.nt
+        n = max(self.longest_run_of_spaces(),
+                other.longest_run_of_spaces()) + 1
+        # the self.n >= other.n test already did it for ts=1
+        for ts in range(2, n+1):
+            if self.indent_level(ts) >= other.indent_level(ts):
+                return False
+        return True
+
+    # return a list of tuples (ts, i1, i2) such that
+    # i1 == self.indent_level(ts) >= other.indent_level(ts) == i2.
+    # Intended to be used after not self.less(other) is known, in which
+    # case it will return at least one witnessing tab size.
+    def not_less_witness(self, other):
+        n = max(self.longest_run_of_spaces(),
+                other.longest_run_of_spaces()) + 1
+        a = []
+        for ts in range(1, n+1):
+            if self.indent_level(ts) >= other.indent_level(ts):
+                a.append( (ts,
+                           self.indent_level(ts),
+                           other.indent_level(ts)) )
+        return a
+
+def format_witnesses(w):
+    firsts = map(lambda tup: str(tup[0]), w)
+    prefix = "at tab size"
+    if len(w) > 1:
+        prefix = prefix + "s"
+    return prefix + " " + ', '.join(firsts)
+
+def process_tokens(tokens):
+    INDENT = tokenize.INDENT
+    DEDENT = tokenize.DEDENT
+    NEWLINE = tokenize.NEWLINE
+    JUNK = tokenize.COMMENT, tokenize.NL
+    indents = [Whitespace("")]
+    check_equal = 0
+
+    for (type, token, start, end, line) in tokens:
+        if type == NEWLINE:
+            # a program statement, or ENDMARKER, will eventually follow,
+            # after some (possibly empty) run of tokens of the form
+            #     (NL | COMMENT)* (INDENT | DEDENT+)?
+            # If an INDENT appears, setting check_equal is wrong, and will
+            # be undone when we see the INDENT.
+            check_equal = 1
+
+        elif type == INDENT:
+            check_equal = 0
+            thisguy = Whitespace(token)
+            if not indents[-1].less(thisguy):
+                witness = indents[-1].not_less_witness(thisguy)
+                msg = "indent not greater e.g. " + format_witnesses(witness)
+                raise NannyNag(start[0], msg, line)
+            indents.append(thisguy)
+
+        elif type == DEDENT:
+            # there's nothing we need to check here!  what's important is
+            # that when the run of DEDENTs ends, the indentation of the
+            # program statement (or ENDMARKER) that triggered the run is
+            # equal to what's left at the top of the indents stack
+
+            # Ouch!  This assert triggers if the last line of the source
+            # is indented *and* lacks a newline -- then DEDENTs pop out
+            # of thin air.
+            # assert check_equal  # else no earlier NEWLINE, or an earlier INDENT
+            check_equal = 1
+
+            del indents[-1]
+
+        elif check_equal and type not in JUNK:
+            # this is the first "real token" following a NEWLINE, so it
+            # must be the first token of the next program statement, or an
+            # ENDMARKER; the "line" argument exposes the leading whitespace
+            # for this statement; in the case of ENDMARKER, line is an empty
+            # string, so will properly match the empty string with which the
+            # "indents" stack was seeded
+            check_equal = 0
+            thisguy = Whitespace(line)
+            if not indents[-1].equal(thisguy):
+                witness = indents[-1].not_equal_witness(thisguy)
+                msg = "indent not equal e.g. " + format_witnesses(witness)
+                raise NannyNag(start[0], msg, line)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/main/resources/PythonLibs/tarfile.py b/src/main/resources/PythonLibs/tarfile.py
new file mode 100644
index 0000000000000000000000000000000000000000..356705681dd611e220a95a231c9da6d1c32b596c
--- /dev/null
+++ b/src/main/resources/PythonLibs/tarfile.py
@@ -0,0 +1,2592 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+#-------------------------------------------------------------------
+# tarfile.py
+#-------------------------------------------------------------------
+# Copyright (C) 2002 Lars Gustäbel <lars@gustaebel.de>
+# All rights reserved.
+#
+# 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.
+#
+"""Read from and write to tar format archives.
+"""
+
+__version__ = "$Revision: 85213 $"
+# $Source$
+
+version     = "0.9.0"
+__author__  = "Lars Gustäbel (lars@gustaebel.de)"
+__date__    = "$Date: 2010-10-04 08:37:53 -0700 (ma, 04 loka   2010) $"
+__cvsid__   = "$Id: tarfile.py 85213 2010-10-04 15:37:53Z lars.gustaebel $"
+__credits__ = "Gustavo Niemeyer, Niels Gustäbel, Richard Townsend."
+
+#---------
+# Imports
+#---------
+import sys
+import os
+import shutil
+import stat
+import errno
+import time
+import struct
+import copy
+import re
+import operator
+
+try:
+    import grp, pwd
+except ImportError:
+    grp = pwd = None
+
+# from tarfile import *
+__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"]
+
+#---------------------------------------------------------
+# tar constants
+#---------------------------------------------------------
+NUL = "\0"                      # the null character
+BLOCKSIZE = 512                 # length of processing blocks
+RECORDSIZE = BLOCKSIZE * 20     # length of records
+GNU_MAGIC = "ustar  \0"         # magic gnu tar string
+POSIX_MAGIC = "ustar\x0000"     # magic posix tar string
+
+LENGTH_NAME = 100               # maximum length of a filename
+LENGTH_LINK = 100               # maximum length of a linkname
+LENGTH_PREFIX = 155             # maximum length of the prefix field
+
+REGTYPE = "0"                   # regular file
+AREGTYPE = "\0"                 # regular file
+LNKTYPE = "1"                   # link (inside tarfile)
+SYMTYPE = "2"                   # symbolic link
+CHRTYPE = "3"                   # character special device
+BLKTYPE = "4"                   # block special device
+DIRTYPE = "5"                   # directory
+FIFOTYPE = "6"                  # fifo special device
+CONTTYPE = "7"                  # contiguous file
+
+GNUTYPE_LONGNAME = "L"          # GNU tar longname
+GNUTYPE_LONGLINK = "K"          # GNU tar longlink
+GNUTYPE_SPARSE = "S"            # GNU tar sparse file
+
+XHDTYPE = "x"                   # POSIX.1-2001 extended header
+XGLTYPE = "g"                   # POSIX.1-2001 global header
+SOLARIS_XHDTYPE = "X"           # Solaris extended header
+
+USTAR_FORMAT = 0                # POSIX.1-1988 (ustar) format
+GNU_FORMAT = 1                  # GNU tar format
+PAX_FORMAT = 2                  # POSIX.1-2001 (pax) format
+DEFAULT_FORMAT = GNU_FORMAT
+
+#---------------------------------------------------------
+# tarfile constants
+#---------------------------------------------------------
+# File types that tarfile supports:
+SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE,
+                   SYMTYPE, DIRTYPE, FIFOTYPE,
+                   CONTTYPE, CHRTYPE, BLKTYPE,
+                   GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
+                   GNUTYPE_SPARSE)
+
+# File types that will be treated as a regular file.
+REGULAR_TYPES = (REGTYPE, AREGTYPE,
+                 CONTTYPE, GNUTYPE_SPARSE)
+
+# File types that are part of the GNU tar format.
+GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
+             GNUTYPE_SPARSE)
+
+# Fields from a pax header that override a TarInfo attribute.
+PAX_FIELDS = ("path", "linkpath", "size", "mtime",
+              "uid", "gid", "uname", "gname")
+
+# Fields in a pax header that are numbers, all other fields
+# are treated as strings.
+PAX_NUMBER_FIELDS = {
+    "atime": float,
+    "ctime": float,
+    "mtime": float,
+    "uid": int,
+    "gid": int,
+    "size": int
+}
+
+#---------------------------------------------------------
+# Bits used in the mode field, values in octal.
+#---------------------------------------------------------
+S_IFLNK = 0120000        # symbolic link
+S_IFREG = 0100000        # regular file
+S_IFBLK = 0060000        # block device
+S_IFDIR = 0040000        # directory
+S_IFCHR = 0020000        # character device
+S_IFIFO = 0010000        # fifo
+
+TSUID   = 04000          # set UID on execution
+TSGID   = 02000          # set GID on execution
+TSVTX   = 01000          # reserved
+
+TUREAD  = 0400           # read by owner
+TUWRITE = 0200           # write by owner
+TUEXEC  = 0100           # execute/search by owner
+TGREAD  = 0040           # read by group
+TGWRITE = 0020           # write by group
+TGEXEC  = 0010           # execute/search by group
+TOREAD  = 0004           # read by other
+TOWRITE = 0002           # write by other
+TOEXEC  = 0001           # execute/search by other
+
+#---------------------------------------------------------
+# initialization
+#---------------------------------------------------------
+ENCODING = sys.getfilesystemencoding()
+if ENCODING is None:
+    ENCODING = sys.getdefaultencoding()
+
+#---------------------------------------------------------
+# Some useful functions
+#---------------------------------------------------------
+
+def stn(s, length):
+    """Convert a python string to a null-terminated string buffer.
+    """
+    return s[:length] + (length - len(s)) * NUL
+
+def nts(s):
+    """Convert a null-terminated string field to a python string.
+    """
+    # Use the string up to the first null char.
+    p = s.find("\0")
+    if p == -1:
+        return s
+    return s[:p]
+
+def nti(s):
+    """Convert a number field to a python number.
+    """
+    # There are two possible encodings for a number field, see
+    # itn() below.
+    if s[0] != chr(0200):
+        try:
+            n = int(nts(s) or "0", 8)
+        except ValueError:
+            raise InvalidHeaderError("invalid header")
+    else:
+        n = 0L
+        for i in xrange(len(s) - 1):
+            n <<= 8
+            n += ord(s[i + 1])
+    return n
+
+def itn(n, digits=8, format=DEFAULT_FORMAT):
+    """Convert a python number to a number field.
+    """
+    # POSIX 1003.1-1988 requires numbers to be encoded as a string of
+    # octal digits followed by a null-byte, this allows values up to
+    # (8**(digits-1))-1. GNU tar allows storing numbers greater than
+    # that if necessary. A leading 0200 byte indicates this particular
+    # encoding, the following digits-1 bytes are a big-endian
+    # representation. This allows values up to (256**(digits-1))-1.
+    if 0 <= n < 8 ** (digits - 1):
+        s = "%0*o" % (digits - 1, n) + NUL
+    else:
+        if format != GNU_FORMAT or n >= 256 ** (digits - 1):
+            raise ValueError("overflow in number field")
+
+        if n < 0:
+            # XXX We mimic GNU tar's behaviour with negative numbers,
+            # this could raise OverflowError.
+            n = struct.unpack("L", struct.pack("l", n))[0]
+
+        s = ""
+        for i in xrange(digits - 1):
+            s = chr(n & 0377) + s
+            n >>= 8
+        s = chr(0200) + s
+    return s
+
+def uts(s, encoding, errors):
+    """Convert a unicode object to a string.
+    """
+    if errors == "utf-8":
+        # An extra error handler similar to the -o invalid=UTF-8 option
+        # in POSIX.1-2001. Replace untranslatable characters with their
+        # UTF-8 representation.
+        try:
+            return s.encode(encoding, "strict")
+        except UnicodeEncodeError:
+            x = []
+            for c in s:
+                try:
+                    x.append(c.encode(encoding, "strict"))
+                except UnicodeEncodeError:
+                    x.append(c.encode("utf8"))
+            return "".join(x)
+    else:
+        return s.encode(encoding, errors)
+
+def calc_chksums(buf):
+    """Calculate the checksum for a member's header by summing up all
+       characters except for the chksum field which is treated as if
+       it was filled with spaces. According to the GNU tar sources,
+       some tars (Sun and NeXT) calculate chksum with signed char,
+       which will be different if there are chars in the buffer with
+       the high bit set. So we calculate two checksums, unsigned and
+       signed.
+    """
+    unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512]))
+    signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512]))
+    return unsigned_chksum, signed_chksum
+
+def copyfileobj(src, dst, length=None):
+    """Copy length bytes from fileobj src to fileobj dst.
+       If length is None, copy the entire content.
+    """
+    if length == 0:
+        return
+    if length is None:
+        shutil.copyfileobj(src, dst)
+        return
+
+    BUFSIZE = 16 * 1024
+    blocks, remainder = divmod(length, BUFSIZE)
+    for b in xrange(blocks):
+        buf = src.read(BUFSIZE)
+        if len(buf) < BUFSIZE:
+            raise IOError("end of file reached")
+        dst.write(buf)
+
+    if remainder != 0:
+        buf = src.read(remainder)
+        if len(buf) < remainder:
+            raise IOError("end of file reached")
+        dst.write(buf)
+    return
+
+filemode_table = (
+    ((S_IFLNK,      "l"),
+     (S_IFREG,      "-"),
+     (S_IFBLK,      "b"),
+     (S_IFDIR,      "d"),
+     (S_IFCHR,      "c"),
+     (S_IFIFO,      "p")),
+
+    ((TUREAD,       "r"),),
+    ((TUWRITE,      "w"),),
+    ((TUEXEC|TSUID, "s"),
+     (TSUID,        "S"),
+     (TUEXEC,       "x")),
+
+    ((TGREAD,       "r"),),
+    ((TGWRITE,      "w"),),
+    ((TGEXEC|TSGID, "s"),
+     (TSGID,        "S"),
+     (TGEXEC,       "x")),
+
+    ((TOREAD,       "r"),),
+    ((TOWRITE,      "w"),),
+    ((TOEXEC|TSVTX, "t"),
+     (TSVTX,        "T"),
+     (TOEXEC,       "x"))
+)
+
+def filemode(mode):
+    """Convert a file's mode to a string of the form
+       -rwxrwxrwx.
+       Used by TarFile.list()
+    """
+    perm = []
+    for table in filemode_table:
+        for bit, char in table:
+            if mode & bit == bit:
+                perm.append(char)
+                break
+        else:
+            perm.append("-")
+    return "".join(perm)
+
+class TarError(Exception):
+    """Base exception."""
+    pass
+class ExtractError(TarError):
+    """General exception for extract errors."""
+    pass
+class ReadError(TarError):
+    """Exception for unreadble tar archives."""
+    pass
+class CompressionError(TarError):
+    """Exception for unavailable compression methods."""
+    pass
+class StreamError(TarError):
+    """Exception for unsupported operations on stream-like TarFiles."""
+    pass
+class HeaderError(TarError):
+    """Base exception for header errors."""
+    pass
+class EmptyHeaderError(HeaderError):
+    """Exception for empty headers."""
+    pass
+class TruncatedHeaderError(HeaderError):
+    """Exception for truncated headers."""
+    pass
+class EOFHeaderError(HeaderError):
+    """Exception for end of file headers."""
+    pass
+class InvalidHeaderError(HeaderError):
+    """Exception for invalid headers."""
+    pass
+class SubsequentHeaderError(HeaderError):
+    """Exception for missing and invalid extended headers."""
+    pass
+
+#---------------------------
+# internal stream interface
+#---------------------------
+class _LowLevelFile:
+    """Low-level file object. Supports reading and writing.
+       It is used instead of a regular file object for streaming
+       access.
+    """
+
+    def __init__(self, name, mode):
+        mode = {
+            "r": os.O_RDONLY,
+            "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
+        }[mode]
+        if hasattr(os, "O_BINARY"):
+            mode |= os.O_BINARY
+        self.fd = os.open(name, mode, 0666)
+
+    def close(self):
+        os.close(self.fd)
+
+    def read(self, size):
+        return os.read(self.fd, size)
+
+    def write(self, s):
+        os.write(self.fd, s)
+
+class _Stream:
+    """Class that serves as an adapter between TarFile and
+       a stream-like object.  The stream-like object only
+       needs to have a read() or write() method and is accessed
+       blockwise.  Use of gzip or bzip2 compression is possible.
+       A stream-like object could be for example: sys.stdin,
+       sys.stdout, a socket, a tape device etc.
+
+       _Stream is intended to be used only internally.
+    """
+
+    def __init__(self, name, mode, comptype, fileobj, bufsize):
+        """Construct a _Stream object.
+        """
+        self._extfileobj = True
+        if fileobj is None:
+            fileobj = _LowLevelFile(name, mode)
+            self._extfileobj = False
+
+        if comptype == '*':
+            # Enable transparent compression detection for the
+            # stream interface
+            fileobj = _StreamProxy(fileobj)
+            comptype = fileobj.getcomptype()
+
+        self.name     = name or ""
+        self.mode     = mode
+        self.comptype = comptype
+        self.fileobj  = fileobj
+        self.bufsize  = bufsize
+        self.buf      = ""
+        self.pos      = 0L
+        self.closed   = False
+
+        if comptype == "gz":
+            try:
+                import zlib
+            except ImportError:
+                raise CompressionError("zlib module is not available")
+            self.zlib = zlib
+            self.crc = zlib.crc32("") & 0xffffffffL
+            if mode == "r":
+                self._init_read_gz()
+            else:
+                self._init_write_gz()
+
+        if comptype == "bz2":
+            try:
+                import bz2
+            except ImportError:
+                raise CompressionError("bz2 module is not available")
+            if mode == "r":
+                self.dbuf = ""
+                self.cmp = bz2.BZ2Decompressor()
+            else:
+                self.cmp = bz2.BZ2Compressor()
+
+    def __del__(self):
+        if hasattr(self, "closed") and not self.closed:
+            self.close()
+
+    def _init_write_gz(self):
+        """Initialize for writing with gzip compression.
+        """
+        self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED,
+                                            -self.zlib.MAX_WBITS,
+                                            self.zlib.DEF_MEM_LEVEL,
+                                            0)
+        timestamp = struct.pack("<L", long(time.time()))
+        self.__write("\037\213\010\010%s\002\377" % timestamp)
+        if self.name.endswith(".gz"):
+            self.name = self.name[:-3]
+        self.__write(self.name + NUL)
+
+    def write(self, s):
+        """Write string s to the stream.
+        """
+        if self.comptype == "gz":
+            self.crc = self.zlib.crc32(s, self.crc) & 0xffffffffL
+        self.pos += len(s)
+        if self.comptype != "tar":
+            s = self.cmp.compress(s)
+        self.__write(s)
+
+    def __write(self, s):
+        """Write string s to the stream if a whole new block
+           is ready to be written.
+        """
+        self.buf += s
+        while len(self.buf) > self.bufsize:
+            self.fileobj.write(self.buf[:self.bufsize])
+            self.buf = self.buf[self.bufsize:]
+
+    def close(self):
+        """Close the _Stream object. No operation should be
+           done on it afterwards.
+        """
+        if self.closed:
+            return
+
+        if self.mode == "w" and self.comptype != "tar":
+            self.buf += self.cmp.flush()
+
+        if self.mode == "w" and self.buf:
+            self.fileobj.write(self.buf)
+            self.buf = ""
+            if self.comptype == "gz":
+                # The native zlib crc is an unsigned 32-bit integer, but
+                # the Python wrapper implicitly casts that to a signed C
+                # long.  So, on a 32-bit box self.crc may "look negative",
+                # while the same crc on a 64-bit box may "look positive".
+                # To avoid irksome warnings from the `struct` module, force
+                # it to look positive on all boxes.
+                self.fileobj.write(struct.pack("<L", self.crc & 0xffffffffL))
+                self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFFL))
+
+        if not self._extfileobj:
+            self.fileobj.close()
+
+        self.closed = True
+
+    def _init_read_gz(self):
+        """Initialize for reading a gzip compressed fileobj.
+        """
+        self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS)
+        self.dbuf = ""
+
+        # taken from gzip.GzipFile with some alterations
+        if self.__read(2) != "\037\213":
+            raise ReadError("not a gzip file")
+        if self.__read(1) != "\010":
+            raise CompressionError("unsupported compression method")
+
+        flag = ord(self.__read(1))
+        self.__read(6)
+
+        if flag & 4:
+            xlen = ord(self.__read(1)) + 256 * ord(self.__read(1))
+            self.read(xlen)
+        if flag & 8:
+            while True:
+                s = self.__read(1)
+                if not s or s == NUL:
+                    break
+        if flag & 16:
+            while True:
+                s = self.__read(1)
+                if not s or s == NUL:
+                    break
+        if flag & 2:
+            self.__read(2)
+
+    def tell(self):
+        """Return the stream's file pointer position.
+        """
+        return self.pos
+
+    def seek(self, pos=0):
+        """Set the stream's file pointer to pos. Negative seeking
+           is forbidden.
+        """
+        if pos - self.pos >= 0:
+            blocks, remainder = divmod(pos - self.pos, self.bufsize)
+            for i in xrange(blocks):
+                self.read(self.bufsize)
+            self.read(remainder)
+        else:
+            raise StreamError("seeking backwards is not allowed")
+        return self.pos
+
+    def read(self, size=None):
+        """Return the next size number of bytes from the stream.
+           If size is not defined, return all bytes of the stream
+           up to EOF.
+        """
+        if size is None:
+            t = []
+            while True:
+                buf = self._read(self.bufsize)
+                if not buf:
+                    break
+                t.append(buf)
+            buf = "".join(t)
+        else:
+            buf = self._read(size)
+        self.pos += len(buf)
+        return buf
+
+    def _read(self, size):
+        """Return size bytes from the stream.
+        """
+        if self.comptype == "tar":
+            return self.__read(size)
+
+        c = len(self.dbuf)
+        t = [self.dbuf]
+        while c < size:
+            buf = self.__read(self.bufsize)
+            if not buf:
+                break
+            try:
+                buf = self.cmp.decompress(buf)
+            except IOError:
+                raise ReadError("invalid compressed data")
+            t.append(buf)
+            c += len(buf)
+        t = "".join(t)
+        self.dbuf = t[size:]
+        return t[:size]
+
+    def __read(self, size):
+        """Return size bytes from stream. If internal buffer is empty,
+           read another block from the stream.
+        """
+        c = len(self.buf)
+        t = [self.buf]
+        while c < size:
+            buf = self.fileobj.read(self.bufsize)
+            if not buf:
+                break
+            t.append(buf)
+            c += len(buf)
+        t = "".join(t)
+        self.buf = t[size:]
+        return t[:size]
+# class _Stream
+
+class _StreamProxy(object):
+    """Small proxy class that enables transparent compression
+       detection for the Stream interface (mode 'r|*').
+    """
+
+    def __init__(self, fileobj):
+        self.fileobj = fileobj
+        self.buf = self.fileobj.read(BLOCKSIZE)
+
+    def read(self, size):
+        self.read = self.fileobj.read
+        return self.buf
+
+    def getcomptype(self):
+        if self.buf.startswith("\037\213\010"):
+            return "gz"
+        if self.buf.startswith("BZh91"):
+            return "bz2"
+        return "tar"
+
+    def close(self):
+        self.fileobj.close()
+# class StreamProxy
+
+class _BZ2Proxy(object):
+    """Small proxy class that enables external file object
+       support for "r:bz2" and "w:bz2" modes. This is actually
+       a workaround for a limitation in bz2 module's BZ2File
+       class which (unlike gzip.GzipFile) has no support for
+       a file object argument.
+    """
+
+    blocksize = 16 * 1024
+
+    def __init__(self, fileobj, mode):
+        self.fileobj = fileobj
+        self.mode = mode
+        self.name = getattr(self.fileobj, "name", None)
+        self.init()
+
+    def init(self):
+        import bz2
+        self.pos = 0
+        if self.mode == "r":
+            self.bz2obj = bz2.BZ2Decompressor()
+            self.fileobj.seek(0)
+            self.buf = ""
+        else:
+            self.bz2obj = bz2.BZ2Compressor()
+
+    def read(self, size):
+        b = [self.buf]
+        x = len(self.buf)
+        while x < size:
+            raw = self.fileobj.read(self.blocksize)
+            if not raw:
+                break
+            data = self.bz2obj.decompress(raw)
+            b.append(data)
+            x += len(data)
+        self.buf = "".join(b)
+
+        buf = self.buf[:size]
+        self.buf = self.buf[size:]
+        self.pos += len(buf)
+        return buf
+
+    def seek(self, pos):
+        if pos < self.pos:
+            self.init()
+        self.read(pos - self.pos)
+
+    def tell(self):
+        return self.pos
+
+    def write(self, data):
+        self.pos += len(data)
+        raw = self.bz2obj.compress(data)
+        self.fileobj.write(raw)
+
+    def close(self):
+        if self.mode == "w":
+            raw = self.bz2obj.flush()
+            self.fileobj.write(raw)
+# class _BZ2Proxy
+
+#------------------------
+# Extraction file object
+#------------------------
+class _FileInFile(object):
+    """A thin wrapper around an existing file object that
+       provides a part of its data as an individual file
+       object.
+    """
+
+    def __init__(self, fileobj, offset, size, sparse=None):
+        self.fileobj = fileobj
+        self.offset = offset
+        self.size = size
+        self.sparse = sparse
+        self.position = 0
+
+    def tell(self):
+        """Return the current file position.
+        """
+        return self.position
+
+    def seek(self, position):
+        """Seek to a position in the file.
+        """
+        self.position = position
+
+    def read(self, size=None):
+        """Read data from the file.
+        """
+        if size is None:
+            size = self.size - self.position
+        else:
+            size = min(size, self.size - self.position)
+
+        if self.sparse is None:
+            return self.readnormal(size)
+        else:
+            return self.readsparse(size)
+
+    def readnormal(self, size):
+        """Read operation for regular files.
+        """
+        self.fileobj.seek(self.offset + self.position)
+        self.position += size
+        return self.fileobj.read(size)
+
+    def readsparse(self, size):
+        """Read operation for sparse files.
+        """
+        data = []
+        while size > 0:
+            buf = self.readsparsesection(size)
+            if not buf:
+                break
+            size -= len(buf)
+            data.append(buf)
+        return "".join(data)
+
+    def readsparsesection(self, size):
+        """Read a single section of a sparse file.
+        """
+        section = self.sparse.find(self.position)
+
+        if section is None:
+            return ""
+
+        size = min(size, section.offset + section.size - self.position)
+
+        if isinstance(section, _data):
+            realpos = section.realpos + self.position - section.offset
+            self.fileobj.seek(self.offset + realpos)
+            self.position += size
+            return self.fileobj.read(size)
+        else:
+            self.position += size
+            return NUL * size
+#class _FileInFile
+
+
+class ExFileObject(object):
+    """File-like object for reading an archive member.
+       Is returned by TarFile.extractfile().
+    """
+    blocksize = 1024
+
+    def __init__(self, tarfile, tarinfo):
+        self.fileobj = _FileInFile(tarfile.fileobj,
+                                   tarinfo.offset_data,
+                                   tarinfo.size,
+                                   getattr(tarinfo, "sparse", None))
+        self.name = tarinfo.name
+        self.mode = "r"
+        self.closed = False
+        self.size = tarinfo.size
+
+        self.position = 0
+        self.buffer = ""
+
+    def read(self, size=None):
+        """Read at most size bytes from the file. If size is not
+           present or None, read all data until EOF is reached.
+        """
+        if self.closed:
+            raise ValueError("I/O operation on closed file")
+
+        buf = ""
+        if self.buffer:
+            if size is None:
+                buf = self.buffer
+                self.buffer = ""
+            else:
+                buf = self.buffer[:size]
+                self.buffer = self.buffer[size:]
+
+        if size is None:
+            buf += self.fileobj.read()
+        else:
+            buf += self.fileobj.read(size - len(buf))
+
+        self.position += len(buf)
+        return buf
+
+    def readline(self, size=-1):
+        """Read one entire line from the file. If size is present
+           and non-negative, return a string with at most that
+           size, which may be an incomplete line.
+        """
+        if self.closed:
+            raise ValueError("I/O operation on closed file")
+
+        if "\n" in self.buffer:
+            pos = self.buffer.find("\n") + 1
+        else:
+            buffers = [self.buffer]
+            while True:
+                buf = self.fileobj.read(self.blocksize)
+                buffers.append(buf)
+                if not buf or "\n" in buf:
+                    self.buffer = "".join(buffers)
+                    pos = self.buffer.find("\n") + 1
+                    if pos == 0:
+                        # no newline found.
+                        pos = len(self.buffer)
+                    break
+
+        if size != -1:
+            pos = min(size, pos)
+
+        buf = self.buffer[:pos]
+        self.buffer = self.buffer[pos:]
+        self.position += len(buf)
+        return buf
+
+    def readlines(self):
+        """Return a list with all remaining lines.
+        """
+        result = []
+        while True:
+            line = self.readline()
+            if not line: break
+            result.append(line)
+        return result
+
+    def tell(self):
+        """Return the current file position.
+        """
+        if self.closed:
+            raise ValueError("I/O operation on closed file")
+
+        return self.position
+
+    def seek(self, pos, whence=os.SEEK_SET):
+        """Seek to a position in the file.
+        """
+        if self.closed:
+            raise ValueError("I/O operation on closed file")
+
+        if whence == os.SEEK_SET:
+            self.position = min(max(pos, 0), self.size)
+        elif whence == os.SEEK_CUR:
+            if pos < 0:
+                self.position = max(self.position + pos, 0)
+            else:
+                self.position = min(self.position + pos, self.size)
+        elif whence == os.SEEK_END:
+            self.position = max(min(self.size + pos, self.size), 0)
+        else:
+            raise ValueError("Invalid argument")
+
+        self.buffer = ""
+        self.fileobj.seek(self.position)
+
+    def close(self):
+        """Close the file object.
+        """
+        self.closed = True
+
+    def __iter__(self):
+        """Get an iterator over the file's lines.
+        """
+        while True:
+            line = self.readline()
+            if not line:
+                break
+            yield line
+#class ExFileObject
+
+#------------------
+# Exported Classes
+#------------------
+class TarInfo(object):
+    """Informational class which holds the details about an
+       archive member given by a tar header block.
+       TarInfo objects are returned by TarFile.getmember(),
+       TarFile.getmembers() and TarFile.gettarinfo() and are
+       usually created internally.
+    """
+
+    def __init__(self, name=""):
+        """Construct a TarInfo object. name is the optional name
+           of the member.
+        """
+        self.name = name        # member name
+        self.mode = 0644        # file permissions
+        self.uid = 0            # user id
+        self.gid = 0            # group id
+        self.size = 0           # file size
+        self.mtime = 0          # modification time
+        self.chksum = 0         # header checksum
+        self.type = REGTYPE     # member type
+        self.linkname = ""      # link name
+        self.uname = ""         # user name
+        self.gname = ""         # group name
+        self.devmajor = 0       # device major number
+        self.devminor = 0       # device minor number
+
+        self.offset = 0         # the tar header starts here
+        self.offset_data = 0    # the file's data starts here
+
+        self.pax_headers = {}   # pax header information
+
+    # In pax headers the "name" and "linkname" field are called
+    # "path" and "linkpath".
+    def _getpath(self):
+        return self.name
+    def _setpath(self, name):
+        self.name = name
+    path = property(_getpath, _setpath)
+
+    def _getlinkpath(self):
+        return self.linkname
+    def _setlinkpath(self, linkname):
+        self.linkname = linkname
+    linkpath = property(_getlinkpath, _setlinkpath)
+
+    def __repr__(self):
+        return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
+
+    def get_info(self, encoding, errors):
+        """Return the TarInfo's attributes as a dictionary.
+        """
+        info = {
+            "name":     self.name,
+            "mode":     self.mode & 07777,
+            "uid":      self.uid,
+            "gid":      self.gid,
+            "size":     self.size,
+            "mtime":    self.mtime,
+            "chksum":   self.chksum,
+            "type":     self.type,
+            "linkname": self.linkname,
+            "uname":    self.uname,
+            "gname":    self.gname,
+            "devmajor": self.devmajor,
+            "devminor": self.devminor
+        }
+
+        if info["type"] == DIRTYPE and not info["name"].endswith("/"):
+            info["name"] += "/"
+
+        for key in ("name", "linkname", "uname", "gname"):
+            if type(info[key]) is unicode:
+                info[key] = info[key].encode(encoding, errors)
+
+        return info
+
+    def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="strict"):
+        """Return a tar header as a string of 512 byte blocks.
+        """
+        info = self.get_info(encoding, errors)
+
+        if format == USTAR_FORMAT:
+            return self.create_ustar_header(info)
+        elif format == GNU_FORMAT:
+            return self.create_gnu_header(info)
+        elif format == PAX_FORMAT:
+            return self.create_pax_header(info, encoding, errors)
+        else:
+            raise ValueError("invalid format")
+
+    def create_ustar_header(self, info):
+        """Return the object as a ustar header block.
+        """
+        info["magic"] = POSIX_MAGIC
+
+        if len(info["linkname"]) > LENGTH_LINK:
+            raise ValueError("linkname is too long")
+
+        if len(info["name"]) > LENGTH_NAME:
+            info["prefix"], info["name"] = self._posix_split_name(info["name"])
+
+        return self._create_header(info, USTAR_FORMAT)
+
+    def create_gnu_header(self, info):
+        """Return the object as a GNU header block sequence.
+        """
+        info["magic"] = GNU_MAGIC
+
+        buf = ""
+        if len(info["linkname"]) > LENGTH_LINK:
+            buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK)
+
+        if len(info["name"]) > LENGTH_NAME:
+            buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME)
+
+        return buf + self._create_header(info, GNU_FORMAT)
+
+    def create_pax_header(self, info, encoding, errors):
+        """Return the object as a ustar header block. If it cannot be
+           represented this way, prepend a pax extended header sequence
+           with supplement information.
+        """
+        info["magic"] = POSIX_MAGIC
+        pax_headers = self.pax_headers.copy()
+
+        # Test string fields for values that exceed the field length or cannot
+        # be represented in ASCII encoding.
+        for name, hname, length in (
+                ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK),
+                ("uname", "uname", 32), ("gname", "gname", 32)):
+
+            if hname in pax_headers:
+                # The pax header has priority.
+                continue
+
+            val = info[name].decode(encoding, errors)
+
+            # Try to encode the string as ASCII.
+            try:
+                val.encode("ascii")
+            except UnicodeEncodeError:
+                pax_headers[hname] = val
+                continue
+
+            if len(info[name]) > length:
+                pax_headers[hname] = val
+
+        # Test number fields for values that exceed the field limit or values
+        # that like to be stored as float.
+        for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)):
+            if name in pax_headers:
+                # The pax header has priority. Avoid overflow.
+                info[name] = 0
+                continue
+
+            val = info[name]
+            if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float):
+                pax_headers[name] = unicode(val)
+                info[name] = 0
+
+        # Create a pax extended header if necessary.
+        if pax_headers:
+            buf = self._create_pax_generic_header(pax_headers)
+        else:
+            buf = ""
+
+        return buf + self._create_header(info, USTAR_FORMAT)
+
+    @classmethod
+    def create_pax_global_header(cls, pax_headers):
+        """Return the object as a pax global header block sequence.
+        """
+        return cls._create_pax_generic_header(pax_headers, type=XGLTYPE)
+
+    def _posix_split_name(self, name):
+        """Split a name longer than 100 chars into a prefix
+           and a name part.
+        """
+        prefix = name[:LENGTH_PREFIX + 1]
+        while prefix and prefix[-1] != "/":
+            prefix = prefix[:-1]
+
+        name = name[len(prefix):]
+        prefix = prefix[:-1]
+
+        if not prefix or len(name) > LENGTH_NAME:
+            raise ValueError("name is too long")
+        return prefix, name
+
+    @staticmethod
+    def _create_header(info, format):
+        """Return a header block. info is a dictionary with file
+           information, format must be one of the *_FORMAT constants.
+        """
+        parts = [
+            stn(info.get("name", ""), 100),
+            itn(info.get("mode", 0) & 07777, 8, format),
+            itn(info.get("uid", 0), 8, format),
+            itn(info.get("gid", 0), 8, format),
+            itn(info.get("size", 0), 12, format),
+            itn(info.get("mtime", 0), 12, format),
+            "        ", # checksum field
+            info.get("type", REGTYPE),
+            stn(info.get("linkname", ""), 100),
+            stn(info.get("magic", POSIX_MAGIC), 8),
+            stn(info.get("uname", ""), 32),
+            stn(info.get("gname", ""), 32),
+            itn(info.get("devmajor", 0), 8, format),
+            itn(info.get("devminor", 0), 8, format),
+            stn(info.get("prefix", ""), 155)
+        ]
+
+        buf = struct.pack("%ds" % BLOCKSIZE, "".join(parts))
+        chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
+        buf = buf[:-364] + "%06o\0" % chksum + buf[-357:]
+        return buf
+
+    @staticmethod
+    def _create_payload(payload):
+        """Return the string payload filled with zero bytes
+           up to the next 512 byte border.
+        """
+        blocks, remainder = divmod(len(payload), BLOCKSIZE)
+        if remainder > 0:
+            payload += (BLOCKSIZE - remainder) * NUL
+        return payload
+
+    @classmethod
+    def _create_gnu_long_header(cls, name, type):
+        """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence
+           for name.
+        """
+        name += NUL
+
+        info = {}
+        info["name"] = "././@LongLink"
+        info["type"] = type
+        info["size"] = len(name)
+        info["magic"] = GNU_MAGIC
+
+        # create extended header + name blocks.
+        return cls._create_header(info, USTAR_FORMAT) + \
+                cls._create_payload(name)
+
+    @classmethod
+    def _create_pax_generic_header(cls, pax_headers, type=XHDTYPE):
+        """Return a POSIX.1-2001 extended or global header sequence
+           that contains a list of keyword, value pairs. The values
+           must be unicode objects.
+        """
+        records = []
+        for keyword, value in pax_headers.iteritems():
+            keyword = keyword.encode("utf8")
+            value = value.encode("utf8")
+            l = len(keyword) + len(value) + 3   # ' ' + '=' + '\n'
+            n = p = 0
+            while True:
+                n = l + len(str(p))
+                if n == p:
+                    break
+                p = n
+            records.append("%d %s=%s\n" % (p, keyword, value))
+        records = "".join(records)
+
+        # We use a hardcoded "././@PaxHeader" name like star does
+        # instead of the one that POSIX recommends.
+        info = {}
+        info["name"] = "././@PaxHeader"
+        info["type"] = type
+        info["size"] = len(records)
+        info["magic"] = POSIX_MAGIC
+
+        # Create pax header + record blocks.
+        return cls._create_header(info, USTAR_FORMAT) + \
+                cls._create_payload(records)
+
+    @classmethod
+    def frombuf(cls, buf):
+        """Construct a TarInfo object from a 512 byte string buffer.
+        """
+        if len(buf) == 0:
+            raise EmptyHeaderError("empty header")
+        if len(buf) != BLOCKSIZE:
+            raise TruncatedHeaderError("truncated header")
+        if buf.count(NUL) == BLOCKSIZE:
+            raise EOFHeaderError("end of file header")
+
+        chksum = nti(buf[148:156])
+        if chksum not in calc_chksums(buf):
+            raise InvalidHeaderError("bad checksum")
+
+        obj = cls()
+        obj.buf = buf
+        obj.name = nts(buf[0:100])
+        obj.mode = nti(buf[100:108])
+        obj.uid = nti(buf[108:116])
+        obj.gid = nti(buf[116:124])
+        obj.size = nti(buf[124:136])
+        obj.mtime = nti(buf[136:148])
+        obj.chksum = chksum
+        obj.type = buf[156:157]
+        obj.linkname = nts(buf[157:257])
+        obj.uname = nts(buf[265:297])
+        obj.gname = nts(buf[297:329])
+        obj.devmajor = nti(buf[329:337])
+        obj.devminor = nti(buf[337:345])
+        prefix = nts(buf[345:500])
+
+        # Old V7 tar format represents a directory as a regular
+        # file with a trailing slash.
+        if obj.type == AREGTYPE and obj.name.endswith("/"):
+            obj.type = DIRTYPE
+
+        # Remove redundant slashes from directories.
+        if obj.isdir():
+            obj.name = obj.name.rstrip("/")
+
+        # Reconstruct a ustar longname.
+        if prefix and obj.type not in GNU_TYPES:
+            obj.name = prefix + "/" + obj.name
+        return obj
+
+    @classmethod
+    def fromtarfile(cls, tarfile):
+        """Return the next TarInfo object from TarFile object
+           tarfile.
+        """
+        buf = tarfile.fileobj.read(BLOCKSIZE)
+        obj = cls.frombuf(buf)
+        obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
+        return obj._proc_member(tarfile)
+
+    #--------------------------------------------------------------------------
+    # The following are methods that are called depending on the type of a
+    # member. The entry point is _proc_member() which can be overridden in a
+    # subclass to add custom _proc_*() methods. A _proc_*() method MUST
+    # implement the following
+    # operations:
+    # 1. Set self.offset_data to the position where the data blocks begin,
+    #    if there is data that follows.
+    # 2. Set tarfile.offset to the position where the next member's header will
+    #    begin.
+    # 3. Return self or another valid TarInfo object.
+    def _proc_member(self, tarfile):
+        """Choose the right processing method depending on
+           the type and call it.
+        """
+        if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
+            return self._proc_gnulong(tarfile)
+        elif self.type == GNUTYPE_SPARSE:
+            return self._proc_sparse(tarfile)
+        elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE):
+            return self._proc_pax(tarfile)
+        else:
+            return self._proc_builtin(tarfile)
+
+    def _proc_builtin(self, tarfile):
+        """Process a builtin type or an unknown type which
+           will be treated as a regular file.
+        """
+        self.offset_data = tarfile.fileobj.tell()
+        offset = self.offset_data
+        if self.isreg() or self.type not in SUPPORTED_TYPES:
+            # Skip the following data blocks.
+            offset += self._block(self.size)
+        tarfile.offset = offset
+
+        # Patch the TarInfo object with saved global
+        # header information.
+        self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors)
+
+        return self
+
+    def _proc_gnulong(self, tarfile):
+        """Process the blocks that hold a GNU longname
+           or longlink member.
+        """
+        buf = tarfile.fileobj.read(self._block(self.size))
+
+        # Fetch the next header and process it.
+        try:
+            next = self.fromtarfile(tarfile)
+        except HeaderError:
+            raise SubsequentHeaderError("missing or bad subsequent header")
+
+        # Patch the TarInfo object from the next header with
+        # the longname information.
+        next.offset = self.offset
+        if self.type == GNUTYPE_LONGNAME:
+            next.name = nts(buf)
+        elif self.type == GNUTYPE_LONGLINK:
+            next.linkname = nts(buf)
+
+        return next
+
+    def _proc_sparse(self, tarfile):
+        """Process a GNU sparse header plus extra headers.
+        """
+        buf = self.buf
+        sp = _ringbuffer()
+        pos = 386
+        lastpos = 0L
+        realpos = 0L
+        # There are 4 possible sparse structs in the
+        # first header.
+        for i in xrange(4):
+            try:
+                offset = nti(buf[pos:pos + 12])
+                numbytes = nti(buf[pos + 12:pos + 24])
+            except ValueError:
+                break
+            if offset > lastpos:
+                sp.append(_hole(lastpos, offset - lastpos))
+            sp.append(_data(offset, numbytes, realpos))
+            realpos += numbytes
+            lastpos = offset + numbytes
+            pos += 24
+
+        isextended = ord(buf[482])
+        origsize = nti(buf[483:495])
+
+        # If the isextended flag is given,
+        # there are extra headers to process.
+        while isextended == 1:
+            buf = tarfile.fileobj.read(BLOCKSIZE)
+            pos = 0
+            for i in xrange(21):
+                try:
+                    offset = nti(buf[pos:pos + 12])
+                    numbytes = nti(buf[pos + 12:pos + 24])
+                except ValueError:
+                    break
+                if offset > lastpos:
+                    sp.append(_hole(lastpos, offset - lastpos))
+                sp.append(_data(offset, numbytes, realpos))
+                realpos += numbytes
+                lastpos = offset + numbytes
+                pos += 24
+            isextended = ord(buf[504])
+
+        if lastpos < origsize:
+            sp.append(_hole(lastpos, origsize - lastpos))
+
+        self.sparse = sp
+
+        self.offset_data = tarfile.fileobj.tell()
+        tarfile.offset = self.offset_data + self._block(self.size)
+        self.size = origsize
+
+        return self
+
+    def _proc_pax(self, tarfile):
+        """Process an extended or global header as described in
+           POSIX.1-2001.
+        """
+        # Read the header information.
+        buf = tarfile.fileobj.read(self._block(self.size))
+
+        # A pax header stores supplemental information for either
+        # the following file (extended) or all following files
+        # (global).
+        if self.type == XGLTYPE:
+            pax_headers = tarfile.pax_headers
+        else:
+            pax_headers = tarfile.pax_headers.copy()
+
+        # Parse pax header information. A record looks like that:
+        # "%d %s=%s\n" % (length, keyword, value). length is the size
+        # of the complete record including the length field itself and
+        # the newline. keyword and value are both UTF-8 encoded strings.
+        regex = re.compile(r"(\d+) ([^=]+)=", re.U)
+        pos = 0
+        while True:
+            match = regex.match(buf, pos)
+            if not match:
+                break
+
+            length, keyword = match.groups()
+            length = int(length)
+            value = buf[match.end(2) + 1:match.start(1) + length - 1]
+
+            keyword = keyword.decode("utf8")
+            value = value.decode("utf8")
+
+            pax_headers[keyword] = value
+            pos += length
+
+        # Fetch the next header.
+        try:
+            next = self.fromtarfile(tarfile)
+        except HeaderError:
+            raise SubsequentHeaderError("missing or bad subsequent header")
+
+        if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
+            # Patch the TarInfo object with the extended header info.
+            next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
+            next.offset = self.offset
+
+            if "size" in pax_headers:
+                # If the extended header replaces the size field,
+                # we need to recalculate the offset where the next
+                # header starts.
+                offset = next.offset_data
+                if next.isreg() or next.type not in SUPPORTED_TYPES:
+                    offset += next._block(next.size)
+                tarfile.offset = offset
+
+        return next
+
+    def _apply_pax_info(self, pax_headers, encoding, errors):
+        """Replace fields with supplemental information from a previous
+           pax extended or global header.
+        """
+        for keyword, value in pax_headers.iteritems():
+            if keyword not in PAX_FIELDS:
+                continue
+
+            if keyword == "path":
+                value = value.rstrip("/")
+
+            if keyword in PAX_NUMBER_FIELDS:
+                try:
+                    value = PAX_NUMBER_FIELDS[keyword](value)
+                except ValueError:
+                    value = 0
+            else:
+                value = uts(value, encoding, errors)
+
+            setattr(self, keyword, value)
+
+        self.pax_headers = pax_headers.copy()
+
+    def _block(self, count):
+        """Round up a byte count by BLOCKSIZE and return it,
+           e.g. _block(834) => 1024.
+        """
+        blocks, remainder = divmod(count, BLOCKSIZE)
+        if remainder:
+            blocks += 1
+        return blocks * BLOCKSIZE
+
+    def isreg(self):
+        return self.type in REGULAR_TYPES
+    def isfile(self):
+        return self.isreg()
+    def isdir(self):
+        return self.type == DIRTYPE
+    def issym(self):
+        return self.type == SYMTYPE
+    def islnk(self):
+        return self.type == LNKTYPE
+    def ischr(self):
+        return self.type == CHRTYPE
+    def isblk(self):
+        return self.type == BLKTYPE
+    def isfifo(self):
+        return self.type == FIFOTYPE
+    def issparse(self):
+        return self.type == GNUTYPE_SPARSE
+    def isdev(self):
+        return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
+# class TarInfo
+
+class TarFile(object):
+    """The TarFile Class provides an interface to tar archives.
+    """
+
+    debug = 0                   # May be set from 0 (no msgs) to 3 (all msgs)
+
+    dereference = False         # If true, add content of linked file to the
+                                # tar file, else the link.
+
+    ignore_zeros = False        # If true, skips empty or invalid blocks and
+                                # continues processing.
+
+    errorlevel = 1              # If 0, fatal errors only appear in debug
+                                # messages (if debug >= 0). If > 0, errors
+                                # are passed to the caller as exceptions.
+
+    format = DEFAULT_FORMAT     # The format to use when creating an archive.
+
+    encoding = ENCODING         # Encoding for 8-bit character strings.
+
+    errors = None               # Error handler for unicode conversion.
+
+    tarinfo = TarInfo           # The default TarInfo class to use.
+
+    fileobject = ExFileObject   # The default ExFileObject class to use.
+
+    def __init__(self, name=None, mode="r", fileobj=None, format=None,
+            tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
+            errors=None, pax_headers=None, debug=None, errorlevel=None):
+        """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
+           read from an existing archive, 'a' to append data to an existing
+           file or 'w' to create a new file overwriting an existing one. `mode'
+           defaults to 'r'.
+           If `fileobj' is given, it is used for reading or writing data. If it
+           can be determined, `mode' is overridden by `fileobj's mode.
+           `fileobj' is not closed, when TarFile is closed.
+        """
+        if len(mode) > 1 or mode not in "raw":
+            raise ValueError("mode must be 'r', 'a' or 'w'")
+        self.mode = mode
+        self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode]
+
+        if not fileobj:
+            if self.mode == "a" and not os.path.exists(name):
+                # Create nonexistent files in append mode.
+                self.mode = "w"
+                self._mode = "wb"
+            fileobj = bltn_open(name, self._mode)
+            self._extfileobj = False
+        else:
+            if name is None and hasattr(fileobj, "name"):
+                name = fileobj.name
+            if hasattr(fileobj, "mode"):
+                self._mode = fileobj.mode
+            self._extfileobj = True
+        self.name = os.path.abspath(name) if name else None
+        self.fileobj = fileobj
+
+        # Init attributes.
+        if format is not None:
+            self.format = format
+        if tarinfo is not None:
+            self.tarinfo = tarinfo
+        if dereference is not None:
+            self.dereference = dereference
+        if ignore_zeros is not None:
+            self.ignore_zeros = ignore_zeros
+        if encoding is not None:
+            self.encoding = encoding
+
+        if errors is not None:
+            self.errors = errors
+        elif mode == "r":
+            self.errors = "utf-8"
+        else:
+            self.errors = "strict"
+
+        if pax_headers is not None and self.format == PAX_FORMAT:
+            self.pax_headers = pax_headers
+        else:
+            self.pax_headers = {}
+
+        if debug is not None:
+            self.debug = debug
+        if errorlevel is not None:
+            self.errorlevel = errorlevel
+
+        # Init datastructures.
+        self.closed = False
+        self.members = []       # list of members as TarInfo objects
+        self._loaded = False    # flag if all members have been read
+        self.offset = self.fileobj.tell()
+                                # current position in the archive file
+        self.inodes = {}        # dictionary caching the inodes of
+                                # archive members already added
+
+        try:
+            if self.mode == "r":
+                self.firstmember = None
+                self.firstmember = self.next()
+
+            if self.mode == "a":
+                # Move to the end of the archive,
+                # before the first empty block.
+                while True:
+                    self.fileobj.seek(self.offset)
+                    try:
+                        tarinfo = self.tarinfo.fromtarfile(self)
+                        self.members.append(tarinfo)
+                    except EOFHeaderError:
+                        self.fileobj.seek(self.offset)
+                        break
+                    except HeaderError, e:
+                        raise ReadError(str(e))
+
+            if self.mode in "aw":
+                self._loaded = True
+
+                if self.pax_headers:
+                    buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
+                    self.fileobj.write(buf)
+                    self.offset += len(buf)
+        except:
+            if not self._extfileobj:
+                self.fileobj.close()
+            self.closed = True
+            raise
+
+    def _getposix(self):
+        return self.format == USTAR_FORMAT
+    def _setposix(self, value):
+        import warnings
+        warnings.warn("use the format attribute instead", DeprecationWarning,
+                      2)
+        if value:
+            self.format = USTAR_FORMAT
+        else:
+            self.format = GNU_FORMAT
+    posix = property(_getposix, _setposix)
+
+    #--------------------------------------------------------------------------
+    # Below are the classmethods which act as alternate constructors to the
+    # TarFile class. The open() method is the only one that is needed for
+    # public use; it is the "super"-constructor and is able to select an
+    # adequate "sub"-constructor for a particular compression using the mapping
+    # from OPEN_METH.
+    #
+    # This concept allows one to subclass TarFile without losing the comfort of
+    # the super-constructor. A sub-constructor is registered and made available
+    # by adding it to the mapping in OPEN_METH.
+
+    @classmethod
+    def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs):
+        """Open a tar archive for reading, writing or appending. Return
+           an appropriate TarFile class.
+
+           mode:
+           'r' or 'r:*' open for reading with transparent compression
+           'r:'         open for reading exclusively uncompressed
+           'r:gz'       open for reading with gzip compression
+           'r:bz2'      open for reading with bzip2 compression
+           'a' or 'a:'  open for appending, creating the file if necessary
+           'w' or 'w:'  open for writing without compression
+           'w:gz'       open for writing with gzip compression
+           'w:bz2'      open for writing with bzip2 compression
+
+           'r|*'        open a stream of tar blocks with transparent compression
+           'r|'         open an uncompressed stream of tar blocks for reading
+           'r|gz'       open a gzip compressed stream of tar blocks
+           'r|bz2'      open a bzip2 compressed stream of tar blocks
+           'w|'         open an uncompressed stream for writing
+           'w|gz'       open a gzip compressed stream for writing
+           'w|bz2'      open a bzip2 compressed stream for writing
+        """
+
+        if not name and not fileobj:
+            raise ValueError("nothing to open")
+
+        if mode in ("r", "r:*"):
+            # Find out which *open() is appropriate for opening the file.
+            for comptype in cls.OPEN_METH:
+                func = getattr(cls, cls.OPEN_METH[comptype])
+                if fileobj is not None:
+                    saved_pos = fileobj.tell()
+                try:
+                    return func(name, "r", fileobj, **kwargs)
+                except (ReadError, CompressionError), e:
+                    if fileobj is not None:
+                        fileobj.seek(saved_pos)
+                    continue
+            raise ReadError("file could not be opened successfully")
+
+        elif ":" in mode:
+            filemode, comptype = mode.split(":", 1)
+            filemode = filemode or "r"
+            comptype = comptype or "tar"
+
+            # Select the *open() function according to
+            # given compression.
+            if comptype in cls.OPEN_METH:
+                func = getattr(cls, cls.OPEN_METH[comptype])
+            else:
+                raise CompressionError("unknown compression type %r" % comptype)
+            return func(name, filemode, fileobj, **kwargs)
+
+        elif "|" in mode:
+            filemode, comptype = mode.split("|", 1)
+            filemode = filemode or "r"
+            comptype = comptype or "tar"
+
+            if filemode not in "rw":
+                raise ValueError("mode must be 'r' or 'w'")
+
+            t = cls(name, filemode,
+                    _Stream(name, filemode, comptype, fileobj, bufsize),
+                    **kwargs)
+            t._extfileobj = False
+            return t
+
+        elif mode in "aw":
+            return cls.taropen(name, mode, fileobj, **kwargs)
+
+        raise ValueError("undiscernible mode")
+
+    @classmethod
+    def taropen(cls, name, mode="r", fileobj=None, **kwargs):
+        """Open uncompressed tar archive name for reading or writing.
+        """
+        if len(mode) > 1 or mode not in "raw":
+            raise ValueError("mode must be 'r', 'a' or 'w'")
+        return cls(name, mode, fileobj, **kwargs)
+
+    @classmethod
+    def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
+        """Open gzip compressed tar archive name for reading or writing.
+           Appending is not allowed.
+        """
+        if len(mode) > 1 or mode not in "rw":
+            raise ValueError("mode must be 'r' or 'w'")
+
+        try:
+            import gzip
+            gzip.GzipFile
+        except (ImportError, AttributeError):
+            raise CompressionError("gzip module is not available")
+
+        fileobj = gzip.GzipFile(name, mode, compresslevel, fileobj)
+
+        try:
+            t = cls.taropen(name, mode, fileobj, **kwargs)
+        except IOError:
+            fileobj.close()
+            raise ReadError("not a gzip file")
+        t._extfileobj = False
+        return t
+
+    @classmethod
+    def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
+        """Open bzip2 compressed tar archive name for reading or writing.
+           Appending is not allowed.
+        """
+        if len(mode) > 1 or mode not in "rw":
+            raise ValueError("mode must be 'r' or 'w'.")
+
+        try:
+            import bz2
+        except ImportError:
+            raise CompressionError("bz2 module is not available")
+
+        if fileobj is not None:
+            fileobj = _BZ2Proxy(fileobj, mode)
+            extfileobj = True
+        else:
+            fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
+            extfileobj = False
+
+        try:
+            t = cls.taropen(name, mode, fileobj, **kwargs)
+        except (IOError, EOFError):
+            if not extfileobj:
+                fileobj.close()
+            raise ReadError("not a bzip2 file")
+        t._extfileobj = False
+        return t
+
+    # All *open() methods are registered here.
+    OPEN_METH = {
+        "tar": "taropen",   # uncompressed tar
+        "gz":  "gzopen",    # gzip compressed tar
+        "bz2": "bz2open"    # bzip2 compressed tar
+    }
+
+    #--------------------------------------------------------------------------
+    # The public methods which TarFile provides:
+
+    def close(self):
+        """Close the TarFile. In write-mode, two finishing zero blocks are
+           appended to the archive.
+        """
+        if self.closed:
+            return
+
+        if self.mode in "aw":
+            self.fileobj.write(NUL * (BLOCKSIZE * 2))
+            self.offset += (BLOCKSIZE * 2)
+            # fill up the end with zero-blocks
+            # (like option -b20 for tar does)
+            blocks, remainder = divmod(self.offset, RECORDSIZE)
+            if remainder > 0:
+                self.fileobj.write(NUL * (RECORDSIZE - remainder))
+
+        if not self._extfileobj:
+            self.fileobj.close()
+        self.closed = True
+
+    def getmember(self, name):
+        """Return a TarInfo object for member `name'. If `name' can not be
+           found in the archive, KeyError is raised. If a member occurs more
+           than once in the archive, its last occurrence is assumed to be the
+           most up-to-date version.
+        """
+        tarinfo = self._getmember(name)
+        if tarinfo is None:
+            raise KeyError("filename %r not found" % name)
+        return tarinfo
+
+    def getmembers(self):
+        """Return the members of the archive as a list of TarInfo objects. The
+           list has the same order as the members in the archive.
+        """
+        self._check()
+        if not self._loaded:    # if we want to obtain a list of
+            self._load()        # all members, we first have to
+                                # scan the whole archive.
+        return self.members
+
+    def getnames(self):
+        """Return the members of the archive as a list of their names. It has
+           the same order as the list returned by getmembers().
+        """
+        return [tarinfo.name for tarinfo in self.getmembers()]
+
+    def gettarinfo(self, name=None, arcname=None, fileobj=None):
+        """Create a TarInfo object for either the file `name' or the file
+           object `fileobj' (using os.fstat on its file descriptor). You can
+           modify some of the TarInfo's attributes before you add it using
+           addfile(). If given, `arcname' specifies an alternative name for the
+           file in the archive.
+        """
+        self._check("aw")
+
+        # When fileobj is given, replace name by
+        # fileobj's real name.
+        if fileobj is not None:
+            name = fileobj.name
+
+        # Building the name of the member in the archive.
+        # Backward slashes are converted to forward slashes,
+        # Absolute paths are turned to relative paths.
+        if arcname is None:
+            arcname = name
+        drv, arcname = os.path.splitdrive(arcname)
+        arcname = arcname.replace(os.sep, "/")
+        arcname = arcname.lstrip("/")
+
+        # Now, fill the TarInfo object with
+        # information specific for the file.
+        tarinfo = self.tarinfo()
+        tarinfo.tarfile = self
+
+        # Use os.stat or os.lstat, depending on platform
+        # and if symlinks shall be resolved.
+        if fileobj is None:
+            if hasattr(os, "lstat") and not self.dereference:
+                statres = os.lstat(name)
+            else:
+                statres = os.stat(name)
+        else:
+            statres = os.fstat(fileobj.fileno())
+        linkname = ""
+
+        stmd = statres.st_mode
+        if stat.S_ISREG(stmd):
+            inode = (statres.st_ino, statres.st_dev)
+            if not self.dereference and statres.st_nlink > 1 and \
+                    inode in self.inodes and arcname != self.inodes[inode]:
+                # Is it a hardlink to an already
+                # archived file?
+                type = LNKTYPE
+                linkname = self.inodes[inode]
+            else:
+                # The inode is added only if its valid.
+                # For win32 it is always 0.
+                type = REGTYPE
+                if inode[0]:
+                    self.inodes[inode] = arcname
+        elif stat.S_ISDIR(stmd):
+            type = DIRTYPE
+        elif stat.S_ISFIFO(stmd):
+            type = FIFOTYPE
+        elif stat.S_ISLNK(stmd):
+            type = SYMTYPE
+            linkname = os.readlink(name)
+        elif stat.S_ISCHR(stmd):
+            type = CHRTYPE
+        elif stat.S_ISBLK(stmd):
+            type = BLKTYPE
+        else:
+            return None
+
+        # Fill the TarInfo object with all
+        # information we can get.
+        tarinfo.name = arcname
+        tarinfo.mode = stmd
+        tarinfo.uid = statres.st_uid
+        tarinfo.gid = statres.st_gid
+        if type == REGTYPE:
+            tarinfo.size = statres.st_size
+        else:
+            tarinfo.size = 0L
+        tarinfo.mtime = statres.st_mtime
+        tarinfo.type = type
+        tarinfo.linkname = linkname
+        if pwd:
+            try:
+                tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
+            except KeyError:
+                pass
+        if grp:
+            try:
+                tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
+            except KeyError:
+                pass
+
+        if type in (CHRTYPE, BLKTYPE):
+            if hasattr(os, "major") and hasattr(os, "minor"):
+                tarinfo.devmajor = os.major(statres.st_rdev)
+                tarinfo.devminor = os.minor(statres.st_rdev)
+        return tarinfo
+
+    def list(self, verbose=True):
+        """Print a table of contents to sys.stdout. If `verbose' is False, only
+           the names of the members are printed. If it is True, an `ls -l'-like
+           output is produced.
+        """
+        self._check()
+
+        for tarinfo in self:
+            if verbose:
+                print filemode(tarinfo.mode),
+                print "%s/%s" % (tarinfo.uname or tarinfo.uid,
+                                 tarinfo.gname or tarinfo.gid),
+                if tarinfo.ischr() or tarinfo.isblk():
+                    print "%10s" % ("%d,%d" \
+                                    % (tarinfo.devmajor, tarinfo.devminor)),
+                else:
+                    print "%10d" % tarinfo.size,
+                print "%d-%02d-%02d %02d:%02d:%02d" \
+                      % time.localtime(tarinfo.mtime)[:6],
+
+            print tarinfo.name + ("/" if tarinfo.isdir() else ""),
+
+            if verbose:
+                if tarinfo.issym():
+                    print "->", tarinfo.linkname,
+                if tarinfo.islnk():
+                    print "link to", tarinfo.linkname,
+            print
+
+    def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
+        """Add the file `name' to the archive. `name' may be any type of file
+           (directory, fifo, symbolic link, etc.). If given, `arcname'
+           specifies an alternative name for the file in the archive.
+           Directories are added recursively by default. This can be avoided by
+           setting `recursive' to False. `exclude' is a function that should
+           return True for each filename to be excluded. `filter' is a function
+           that expects a TarInfo object argument and returns the changed
+           TarInfo object, if it returns None the TarInfo object will be
+           excluded from the archive.
+        """
+        self._check("aw")
+
+        if arcname is None:
+            arcname = name
+
+        # Exclude pathnames.
+        if exclude is not None:
+            import warnings
+            warnings.warn("use the filter argument instead",
+                    DeprecationWarning, 2)
+            if exclude(name):
+                self._dbg(2, "tarfile: Excluded %r" % name)
+                return
+
+        # Skip if somebody tries to archive the archive...
+        if self.name is not None and os.path.abspath(name) == self.name:
+            self._dbg(2, "tarfile: Skipped %r" % name)
+            return
+
+        self._dbg(1, name)
+
+        # Create a TarInfo object from the file.
+        tarinfo = self.gettarinfo(name, arcname)
+
+        if tarinfo is None:
+            self._dbg(1, "tarfile: Unsupported type %r" % name)
+            return
+
+        # Change or exclude the TarInfo object.
+        if filter is not None:
+            tarinfo = filter(tarinfo)
+            if tarinfo is None:
+                self._dbg(2, "tarfile: Excluded %r" % name)
+                return
+
+        # Append the tar header and data to the archive.
+        if tarinfo.isreg():
+            f = bltn_open(name, "rb")
+            self.addfile(tarinfo, f)
+            f.close()
+
+        elif tarinfo.isdir():
+            self.addfile(tarinfo)
+            if recursive:
+                for f in os.listdir(name):
+                    self.add(os.path.join(name, f), os.path.join(arcname, f),
+                            recursive, exclude, filter)
+
+        else:
+            self.addfile(tarinfo)
+
+    def addfile(self, tarinfo, fileobj=None):
+        """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
+           given, tarinfo.size bytes are read from it and added to the archive.
+           You can create TarInfo objects using gettarinfo().
+           On Windows platforms, `fileobj' should always be opened with mode
+           'rb' to avoid irritation about the file size.
+        """
+        self._check("aw")
+
+        tarinfo = copy.copy(tarinfo)
+
+        buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
+        self.fileobj.write(buf)
+        self.offset += len(buf)
+
+        # If there's data to follow, append it.
+        if fileobj is not None:
+            copyfileobj(fileobj, self.fileobj, tarinfo.size)
+            blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
+            if remainder > 0:
+                self.fileobj.write(NUL * (BLOCKSIZE - remainder))
+                blocks += 1
+            self.offset += blocks * BLOCKSIZE
+
+        self.members.append(tarinfo)
+
+    def extractall(self, path=".", members=None):
+        """Extract all members from the archive to the current working
+           directory and set owner, modification time and permissions on
+           directories afterwards. `path' specifies a different directory
+           to extract to. `members' is optional and must be a subset of the
+           list returned by getmembers().
+        """
+        directories = []
+
+        if members is None:
+            members = self
+
+        for tarinfo in members:
+            if tarinfo.isdir():
+                # Extract directories with a safe mode.
+                directories.append(tarinfo)
+                tarinfo = copy.copy(tarinfo)
+                tarinfo.mode = 0700
+            self.extract(tarinfo, path)
+
+        # Reverse sort directories.
+        directories.sort(key=operator.attrgetter('name'))
+        directories.reverse()
+
+        # Set correct owner, mtime and filemode on directories.
+        for tarinfo in directories:
+            dirpath = os.path.join(path, tarinfo.name)
+            try:
+                self.chown(tarinfo, dirpath)
+                self.utime(tarinfo, dirpath)
+                self.chmod(tarinfo, dirpath)
+            except ExtractError, e:
+                if self.errorlevel > 1:
+                    raise
+                else:
+                    self._dbg(1, "tarfile: %s" % e)
+
+    def extract(self, member, path=""):
+        """Extract a member from the archive to the current working directory,
+           using its full name. Its file information is extracted as accurately
+           as possible. `member' may be a filename or a TarInfo object. You can
+           specify a different directory using `path'.
+        """
+        self._check("r")
+
+        if isinstance(member, basestring):
+            tarinfo = self.getmember(member)
+        else:
+            tarinfo = member
+
+        # Prepare the link target for makelink().
+        if tarinfo.islnk():
+            tarinfo._link_target = os.path.join(path, tarinfo.linkname)
+
+        try:
+            self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
+        except EnvironmentError, e:
+            if self.errorlevel > 0:
+                raise
+            else:
+                if e.filename is None:
+                    self._dbg(1, "tarfile: %s" % e.strerror)
+                else:
+                    self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
+        except ExtractError, e:
+            if self.errorlevel > 1:
+                raise
+            else:
+                self._dbg(1, "tarfile: %s" % e)
+
+    def extractfile(self, member):
+        """Extract a member from the archive as a file object. `member' may be
+           a filename or a TarInfo object. If `member' is a regular file, a
+           file-like object is returned. If `member' is a link, a file-like
+           object is constructed from the link's target. If `member' is none of
+           the above, None is returned.
+           The file-like object is read-only and provides the following
+           methods: read(), readline(), readlines(), seek() and tell()
+        """
+        self._check("r")
+
+        if isinstance(member, basestring):
+            tarinfo = self.getmember(member)
+        else:
+            tarinfo = member
+
+        if tarinfo.isreg():
+            return self.fileobject(self, tarinfo)
+
+        elif tarinfo.type not in SUPPORTED_TYPES:
+            # If a member's type is unknown, it is treated as a
+            # regular file.
+            return self.fileobject(self, tarinfo)
+
+        elif tarinfo.islnk() or tarinfo.issym():
+            if isinstance(self.fileobj, _Stream):
+                # A small but ugly workaround for the case that someone tries
+                # to extract a (sym)link as a file-object from a non-seekable
+                # stream of tar blocks.
+                raise StreamError("cannot extract (sym)link as file object")
+            else:
+                # A (sym)link's file object is its target's file object.
+                return self.extractfile(self._find_link_target(tarinfo))
+        else:
+            # If there's no data associated with the member (directory, chrdev,
+            # blkdev, etc.), return None instead of a file object.
+            return None
+
+    def _extract_member(self, tarinfo, targetpath):
+        """Extract the TarInfo object tarinfo to a physical
+           file called targetpath.
+        """
+        # Fetch the TarInfo object for the given name
+        # and build the destination pathname, replacing
+        # forward slashes to platform specific separators.
+        targetpath = targetpath.rstrip("/")
+        targetpath = targetpath.replace("/", os.sep)
+
+        # Create all upper directories.
+        upperdirs = os.path.dirname(targetpath)
+        if upperdirs and not os.path.exists(upperdirs):
+            # Create directories that are not part of the archive with
+            # default permissions.
+            os.makedirs(upperdirs)
+
+        if tarinfo.islnk() or tarinfo.issym():
+            self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
+        else:
+            self._dbg(1, tarinfo.name)
+
+        if tarinfo.isreg():
+            self.makefile(tarinfo, targetpath)
+        elif tarinfo.isdir():
+            self.makedir(tarinfo, targetpath)
+        elif tarinfo.isfifo():
+            self.makefifo(tarinfo, targetpath)
+        elif tarinfo.ischr() or tarinfo.isblk():
+            self.makedev(tarinfo, targetpath)
+        elif tarinfo.islnk() or tarinfo.issym():
+            self.makelink(tarinfo, targetpath)
+        elif tarinfo.type not in SUPPORTED_TYPES:
+            self.makeunknown(tarinfo, targetpath)
+        else:
+            self.makefile(tarinfo, targetpath)
+
+        self.chown(tarinfo, targetpath)
+        if not tarinfo.issym():
+            self.chmod(tarinfo, targetpath)
+            self.utime(tarinfo, targetpath)
+
+    #--------------------------------------------------------------------------
+    # Below are the different file methods. They are called via
+    # _extract_member() when extract() is called. They can be replaced in a
+    # subclass to implement other functionality.
+
+    def makedir(self, tarinfo, targetpath):
+        """Make a directory called targetpath.
+        """
+        try:
+            # Use a safe mode for the directory, the real mode is set
+            # later in _extract_member().
+            os.mkdir(targetpath, 0700)
+        except EnvironmentError, e:
+            if e.errno != errno.EEXIST:
+                raise
+
+    def makefile(self, tarinfo, targetpath):
+        """Make a file called targetpath.
+        """
+        source = self.extractfile(tarinfo)
+        target = bltn_open(targetpath, "wb")
+        copyfileobj(source, target)
+        source.close()
+        target.close()
+
+    def makeunknown(self, tarinfo, targetpath):
+        """Make a file from a TarInfo object with an unknown type
+           at targetpath.
+        """
+        self.makefile(tarinfo, targetpath)
+        self._dbg(1, "tarfile: Unknown file type %r, " \
+                     "extracted as regular file." % tarinfo.type)
+
+    def makefifo(self, tarinfo, targetpath):
+        """Make a fifo called targetpath.
+        """
+        if hasattr(os, "mkfifo"):
+            os.mkfifo(targetpath)
+        else:
+            raise ExtractError("fifo not supported by system")
+
+    def makedev(self, tarinfo, targetpath):
+        """Make a character or block device called targetpath.
+        """
+        if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
+            raise ExtractError("special devices not supported by system")
+
+        mode = tarinfo.mode
+        if tarinfo.isblk():
+            mode |= stat.S_IFBLK
+        else:
+            mode |= stat.S_IFCHR
+
+        os.mknod(targetpath, mode,
+                 os.makedev(tarinfo.devmajor, tarinfo.devminor))
+
+    def makelink(self, tarinfo, targetpath):
+        """Make a (symbolic) link called targetpath. If it cannot be created
+          (platform limitation), we try to make a copy of the referenced file
+          instead of a link.
+        """
+        if hasattr(os, "symlink") and hasattr(os, "link"):
+            # For systems that support symbolic and hard links.
+            if tarinfo.issym():
+                os.symlink(tarinfo.linkname, targetpath)
+            else:
+                # See extract().
+                if os.path.exists(tarinfo._link_target):
+                    os.link(tarinfo._link_target, targetpath)
+                else:
+                    self._extract_member(self._find_link_target(tarinfo), targetpath)
+        else:
+            try:
+                self._extract_member(self._find_link_target(tarinfo), targetpath)
+            except KeyError:
+                raise ExtractError("unable to resolve link inside archive")
+
+    def chown(self, tarinfo, targetpath):
+        """Set owner of targetpath according to tarinfo.
+        """
+        if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
+            # We have to be root to do so.
+            try:
+                g = grp.getgrnam(tarinfo.gname)[2]
+            except KeyError:
+                try:
+                    g = grp.getgrgid(tarinfo.gid)[2]
+                except KeyError:
+                    g = os.getgid()
+            try:
+                u = pwd.getpwnam(tarinfo.uname)[2]
+            except KeyError:
+                try:
+                    u = pwd.getpwuid(tarinfo.uid)[2]
+                except KeyError:
+                    u = os.getuid()
+            try:
+                if tarinfo.issym() and hasattr(os, "lchown"):
+                    os.lchown(targetpath, u, g)
+                else:
+                    if sys.platform != "os2emx":
+                        os.chown(targetpath, u, g)
+            except EnvironmentError, e:
+                raise ExtractError("could not change owner")
+
+    def chmod(self, tarinfo, targetpath):
+        """Set file permissions of targetpath according to tarinfo.
+        """
+        if hasattr(os, 'chmod'):
+            try:
+                os.chmod(targetpath, tarinfo.mode)
+            except EnvironmentError, e:
+                raise ExtractError("could not change mode")
+
+    def utime(self, tarinfo, targetpath):
+        """Set modification time of targetpath according to tarinfo.
+        """
+        if not hasattr(os, 'utime'):
+            return
+        try:
+            os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
+        except EnvironmentError, e:
+            raise ExtractError("could not change modification time")
+
+    #--------------------------------------------------------------------------
+    def next(self):
+        """Return the next member of the archive as a TarInfo object, when
+           TarFile is opened for reading. Return None if there is no more
+           available.
+        """
+        self._check("ra")
+        if self.firstmember is not None:
+            m = self.firstmember
+            self.firstmember = None
+            return m
+
+        # Read the next block.
+        self.fileobj.seek(self.offset)
+        tarinfo = None
+        while True:
+            try:
+                tarinfo = self.tarinfo.fromtarfile(self)
+            except EOFHeaderError, e:
+                if self.ignore_zeros:
+                    self._dbg(2, "0x%X: %s" % (self.offset, e))
+                    self.offset += BLOCKSIZE
+                    continue
+            except InvalidHeaderError, e:
+                if self.ignore_zeros:
+                    self._dbg(2, "0x%X: %s" % (self.offset, e))
+                    self.offset += BLOCKSIZE
+                    continue
+                elif self.offset == 0:
+                    raise ReadError(str(e))
+            except EmptyHeaderError:
+                if self.offset == 0:
+                    raise ReadError("empty file")
+            except TruncatedHeaderError, e:
+                if self.offset == 0:
+                    raise ReadError(str(e))
+            except SubsequentHeaderError, e:
+                raise ReadError(str(e))
+            break
+
+        if tarinfo is not None:
+            self.members.append(tarinfo)
+        else:
+            self._loaded = True
+
+        return tarinfo
+
+    #--------------------------------------------------------------------------
+    # Little helper methods:
+
+    def _getmember(self, name, tarinfo=None, normalize=False):
+        """Find an archive member by name from bottom to top.
+           If tarinfo is given, it is used as the starting point.
+        """
+        # Ensure that all members have been loaded.
+        members = self.getmembers()
+
+        # Limit the member search list up to tarinfo.
+        if tarinfo is not None:
+            members = members[:members.index(tarinfo)]
+
+        if normalize:
+            name = os.path.normpath(name)
+
+        for member in reversed(members):
+            if normalize:
+                member_name = os.path.normpath(member.name)
+            else:
+                member_name = member.name
+
+            if name == member_name:
+                return member
+
+    def _load(self):
+        """Read through the entire archive file and look for readable
+           members.
+        """
+        while True:
+            tarinfo = self.next()
+            if tarinfo is None:
+                break
+        self._loaded = True
+
+    def _check(self, mode=None):
+        """Check if TarFile is still open, and if the operation's mode
+           corresponds to TarFile's mode.
+        """
+        if self.closed:
+            raise IOError("%s is closed" % self.__class__.__name__)
+        if mode is not None and self.mode not in mode:
+            raise IOError("bad operation for mode %r" % self.mode)
+
+    def _find_link_target(self, tarinfo):
+        """Find the target member of a symlink or hardlink member in the
+           archive.
+        """
+        if tarinfo.issym():
+            # Always search the entire archive.
+            linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname
+            limit = None
+        else:
+            # Search the archive before the link, because a hard link is
+            # just a reference to an already archived file.
+            linkname = tarinfo.linkname
+            limit = tarinfo
+
+        member = self._getmember(linkname, tarinfo=limit, normalize=True)
+        if member is None:
+            raise KeyError("linkname %r not found" % linkname)
+        return member
+
+    def __iter__(self):
+        """Provide an iterator object.
+        """
+        if self._loaded:
+            return iter(self.members)
+        else:
+            return TarIter(self)
+
+    def _dbg(self, level, msg):
+        """Write debugging output to sys.stderr.
+        """
+        if level <= self.debug:
+            print >> sys.stderr, msg
+
+    def __enter__(self):
+        self._check()
+        return self
+
+    def __exit__(self, type, value, traceback):
+        if type is None:
+            self.close()
+        else:
+            # An exception occurred. We must not call close() because
+            # it would try to write end-of-archive blocks and padding.
+            if not self._extfileobj:
+                self.fileobj.close()
+            self.closed = True
+# class TarFile
+
+class TarIter:
+    """Iterator Class.
+
+       for tarinfo in TarFile(...):
+           suite...
+    """
+
+    def __init__(self, tarfile):
+        """Construct a TarIter object.
+        """
+        self.tarfile = tarfile
+        self.index = 0
+    def __iter__(self):
+        """Return iterator object.
+        """
+        return self
+    def next(self):
+        """Return the next item using TarFile's next() method.
+           When all members have been read, set TarFile as _loaded.
+        """
+        # Fix for SF #1100429: Under rare circumstances it can
+        # happen that getmembers() is called during iteration,
+        # which will cause TarIter to stop prematurely.
+        if not self.tarfile._loaded:
+            tarinfo = self.tarfile.next()
+            if not tarinfo:
+                self.tarfile._loaded = True
+                raise StopIteration
+        else:
+            try:
+                tarinfo = self.tarfile.members[self.index]
+            except IndexError:
+                raise StopIteration
+        self.index += 1
+        return tarinfo
+
+# Helper classes for sparse file support
+class _section:
+    """Base class for _data and _hole.
+    """
+    def __init__(self, offset, size):
+        self.offset = offset
+        self.size = size
+    def __contains__(self, offset):
+        return self.offset <= offset < self.offset + self.size
+
+class _data(_section):
+    """Represent a data section in a sparse file.
+    """
+    def __init__(self, offset, size, realpos):
+        _section.__init__(self, offset, size)
+        self.realpos = realpos
+
+class _hole(_section):
+    """Represent a hole section in a sparse file.
+    """
+    pass
+
+class _ringbuffer(list):
+    """Ringbuffer class which increases performance
+       over a regular list.
+    """
+    def __init__(self):
+        self.idx = 0
+    def find(self, offset):
+        idx = self.idx
+        while True:
+            item = self[idx]
+            if offset in item:
+                break
+            idx += 1
+            if idx == len(self):
+                idx = 0
+            if idx == self.idx:
+                # End of File
+                return None
+        self.idx = idx
+        return item
+
+#---------------------------------------------
+# zipfile compatible TarFile class
+#---------------------------------------------
+TAR_PLAIN = 0           # zipfile.ZIP_STORED
+TAR_GZIPPED = 8         # zipfile.ZIP_DEFLATED
+class TarFileCompat:
+    """TarFile class compatible with standard module zipfile's
+       ZipFile class.
+    """
+    def __init__(self, file, mode="r", compression=TAR_PLAIN):
+        from warnings import warnpy3k
+        warnpy3k("the TarFileCompat class has been removed in Python 3.0",
+                stacklevel=2)
+        if compression == TAR_PLAIN:
+            self.tarfile = TarFile.taropen(file, mode)
+        elif compression == TAR_GZIPPED:
+            self.tarfile = TarFile.gzopen(file, mode)
+        else:
+            raise ValueError("unknown compression constant")
+        if mode[0:1] == "r":
+            members = self.tarfile.getmembers()
+            for m in members:
+                m.filename = m.name
+                m.file_size = m.size
+                m.date_time = time.gmtime(m.mtime)[:6]
+    def namelist(self):
+        return map(lambda m: m.name, self.infolist())
+    def infolist(self):
+        return filter(lambda m: m.type in REGULAR_TYPES,
+                      self.tarfile.getmembers())
+    def printdir(self):
+        self.tarfile.list()
+    def testzip(self):
+        return
+    def getinfo(self, name):
+        return self.tarfile.getmember(name)
+    def read(self, name):
+        return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
+    def write(self, filename, arcname=None, compress_type=None):
+        self.tarfile.add(filename, arcname)
+    def writestr(self, zinfo, bytes):
+        try:
+            from cStringIO import StringIO
+        except ImportError:
+            from StringIO import StringIO
+        import calendar
+        tinfo = TarInfo(zinfo.filename)
+        tinfo.size = len(bytes)
+        tinfo.mtime = calendar.timegm(zinfo.date_time)
+        self.tarfile.addfile(tinfo, StringIO(bytes))
+    def close(self):
+        self.tarfile.close()
+#class TarFileCompat
+
+#--------------------
+# exported functions
+#--------------------
+def is_tarfile(name):
+    """Return True if name points to a tar archive that we
+       are able to handle, else return False.
+    """
+    try:
+        t = open(name)
+        t.close()
+        return True
+    except TarError:
+        return False
+
+bltn_open = open
+open = TarFile.open
diff --git a/src/main/resources/PythonLibs/telnetlib.py b/src/main/resources/PythonLibs/telnetlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..e037f09894c85fc6568899143e380122b1249af1
--- /dev/null
+++ b/src/main/resources/PythonLibs/telnetlib.py
@@ -0,0 +1,664 @@
+r"""TELNET client class.
+
+Based on RFC 854: TELNET Protocol Specification, by J. Postel and
+J. Reynolds
+
+Example:
+
+>>> from telnetlib import Telnet
+>>> tn = Telnet('www.python.org', 79)   # connect to finger port
+>>> tn.write('guido\r\n')
+>>> print tn.read_all()
+Login       Name               TTY         Idle    When    Where
+guido    Guido van Rossum      pts/2        <Dec  2 11:10> snag.cnri.reston..
+
+>>>
+
+Note that read_all() won't read until eof -- it just reads some data
+-- but it guarantees to read at least one byte unless EOF is hit.
+
+It is possible to pass a Telnet object to select.select() in order to
+wait until more data is available.  Note that in this case,
+read_eager() may return '' even if there was data on the socket,
+because the protocol negotiation may have eaten the data.  This is why
+EOFError is needed in some cases to distinguish between "no data" and
+"connection closed" (since the socket also appears ready for reading
+when it is closed).
+
+To do:
+- option negotiation
+- timeout should be intrinsic to the connection object instead of an
+  option on one of the read calls only
+
+"""
+
+
+# Imported modules
+import sys
+import socket
+import select
+import os
+if os.name == 'java':
+    from select import cpython_compatible_select as select
+else:
+    from select import select
+del os
+
+
+__all__ = ["Telnet"]
+
+# Tunable parameters
+DEBUGLEVEL = 0
+
+# Telnet protocol defaults
+TELNET_PORT = 23
+
+# Telnet protocol characters (don't change)
+IAC  = chr(255) # "Interpret As Command"
+DONT = chr(254)
+DO   = chr(253)
+WONT = chr(252)
+WILL = chr(251)
+theNULL = chr(0)
+
+SE  = chr(240)  # Subnegotiation End
+NOP = chr(241)  # No Operation
+DM  = chr(242)  # Data Mark
+BRK = chr(243)  # Break
+IP  = chr(244)  # Interrupt process
+AO  = chr(245)  # Abort output
+AYT = chr(246)  # Are You There
+EC  = chr(247)  # Erase Character
+EL  = chr(248)  # Erase Line
+GA  = chr(249)  # Go Ahead
+SB =  chr(250)  # Subnegotiation Begin
+
+
+# Telnet protocol options code (don't change)
+# These ones all come from arpa/telnet.h
+BINARY = chr(0) # 8-bit data path
+ECHO = chr(1) # echo
+RCP = chr(2) # prepare to reconnect
+SGA = chr(3) # suppress go ahead
+NAMS = chr(4) # approximate message size
+STATUS = chr(5) # give status
+TM = chr(6) # timing mark
+RCTE = chr(7) # remote controlled transmission and echo
+NAOL = chr(8) # negotiate about output line width
+NAOP = chr(9) # negotiate about output page size
+NAOCRD = chr(10) # negotiate about CR disposition
+NAOHTS = chr(11) # negotiate about horizontal tabstops
+NAOHTD = chr(12) # negotiate about horizontal tab disposition
+NAOFFD = chr(13) # negotiate about formfeed disposition
+NAOVTS = chr(14) # negotiate about vertical tab stops
+NAOVTD = chr(15) # negotiate about vertical tab disposition
+NAOLFD = chr(16) # negotiate about output LF disposition
+XASCII = chr(17) # extended ascii character set
+LOGOUT = chr(18) # force logout
+BM = chr(19) # byte macro
+DET = chr(20) # data entry terminal
+SUPDUP = chr(21) # supdup protocol
+SUPDUPOUTPUT = chr(22) # supdup output
+SNDLOC = chr(23) # send location
+TTYPE = chr(24) # terminal type
+EOR = chr(25) # end or record
+TUID = chr(26) # TACACS user identification
+OUTMRK = chr(27) # output marking
+TTYLOC = chr(28) # terminal location number
+VT3270REGIME = chr(29) # 3270 regime
+X3PAD = chr(30) # X.3 PAD
+NAWS = chr(31) # window size
+TSPEED = chr(32) # terminal speed
+LFLOW = chr(33) # remote flow control
+LINEMODE = chr(34) # Linemode option
+XDISPLOC = chr(35) # X Display Location
+OLD_ENVIRON = chr(36) # Old - Environment variables
+AUTHENTICATION = chr(37) # Authenticate
+ENCRYPT = chr(38) # Encryption option
+NEW_ENVIRON = chr(39) # New - Environment variables
+# the following ones come from
+# http://www.iana.org/assignments/telnet-options
+# Unfortunately, that document does not assign identifiers
+# to all of them, so we are making them up
+TN3270E = chr(40) # TN3270E
+XAUTH = chr(41) # XAUTH
+CHARSET = chr(42) # CHARSET
+RSP = chr(43) # Telnet Remote Serial Port
+COM_PORT_OPTION = chr(44) # Com Port Control Option
+SUPPRESS_LOCAL_ECHO = chr(45) # Telnet Suppress Local Echo
+TLS = chr(46) # Telnet Start TLS
+KERMIT = chr(47) # KERMIT
+SEND_URL = chr(48) # SEND-URL
+FORWARD_X = chr(49) # FORWARD_X
+PRAGMA_LOGON = chr(138) # TELOPT PRAGMA LOGON
+SSPI_LOGON = chr(139) # TELOPT SSPI LOGON
+PRAGMA_HEARTBEAT = chr(140) # TELOPT PRAGMA HEARTBEAT
+EXOPL = chr(255) # Extended-Options-List
+NOOPT = chr(0)
+
+class Telnet:
+
+    """Telnet interface class.
+
+    An instance of this class represents a connection to a telnet
+    server.  The instance is initially not connected; the open()
+    method must be used to establish a connection.  Alternatively, the
+    host name and optional port number can be passed to the
+    constructor, too.
+
+    Don't try to reopen an already connected instance.
+
+    This class has many read_*() methods.  Note that some of them
+    raise EOFError when the end of the connection is read, because
+    they can return an empty string for other reasons.  See the
+    individual doc strings.
+
+    read_until(expected, [timeout])
+        Read until the expected string has been seen, or a timeout is
+        hit (default is no timeout); may block.
+
+    read_all()
+        Read all data until EOF; may block.
+
+    read_some()
+        Read at least one byte or EOF; may block.
+
+    read_very_eager()
+        Read all data available already queued or on the socket,
+        without blocking.
+
+    read_eager()
+        Read either data already queued or some data available on the
+        socket, without blocking.
+
+    read_lazy()
+        Read all data in the raw queue (processing it first), without
+        doing any socket I/O.
+
+    read_very_lazy()
+        Reads all data in the cooked queue, without doing any socket
+        I/O.
+
+    read_sb_data()
+        Reads available data between SB ... SE sequence. Don't block.
+
+    set_option_negotiation_callback(callback)
+        Each time a telnet option is read on the input flow, this callback
+        (if set) is called with the following parameters :
+        callback(telnet socket, command, option)
+            option will be chr(0) when there is no option.
+        No other action is done afterwards by telnetlib.
+
+    """
+
+    def __init__(self, host=None, port=0,
+                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
+        """Constructor.
+
+        When called without arguments, create an unconnected instance.
+        With a hostname argument, it connects the instance; port number
+        and timeout are optional.
+        """
+        self.debuglevel = DEBUGLEVEL
+        self.host = host
+        self.port = port
+        self.timeout = timeout
+        self.sock = None
+        self.rawq = ''
+        self.irawq = 0
+        self.cookedq = ''
+        self.eof = 0
+        self.iacseq = '' # Buffer for IAC sequence.
+        self.sb = 0 # flag for SB and SE sequence.
+        self.sbdataq = ''
+        self.option_callback = None
+        if host is not None:
+            self.open(host, port, timeout)
+
+    def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
+        """Connect to a host.
+
+        The optional second argument is the port number, which
+        defaults to the standard telnet port (23).
+
+        Don't try to reopen an already connected instance.
+        """
+        self.eof = 0
+        if not port:
+            port = TELNET_PORT
+        self.host = host
+        self.port = port
+        self.timeout = timeout
+        self.sock = socket.create_connection((host, port), timeout)
+
+    def __del__(self):
+        """Destructor -- close the connection."""
+        self.close()
+
+    def msg(self, msg, *args):
+        """Print a debug message, when the debug level is > 0.
+
+        If extra arguments are present, they are substituted in the
+        message using the standard string formatting operator.
+
+        """
+        if self.debuglevel > 0:
+            print 'Telnet(%s,%s):' % (self.host, self.port),
+            if args:
+                print msg % args
+            else:
+                print msg
+
+    def set_debuglevel(self, debuglevel):
+        """Set the debug level.
+
+        The higher it is, the more debug output you get (on sys.stdout).
+
+        """
+        self.debuglevel = debuglevel
+
+    def close(self):
+        """Close the connection."""
+        if self.sock:
+            self.sock.close()
+        self.sock = 0
+        self.eof = 1
+        self.iacseq = ''
+        self.sb = 0
+
+    def get_socket(self):
+        """Return the socket object used internally."""
+        return self.sock
+
+    def fileno(self):
+        """Return the fileno() of the socket object used internally."""
+        return self.sock.fileno()
+
+    def write(self, buffer):
+        """Write a string to the socket, doubling any IAC characters.
+
+        Can block if the connection is blocked.  May raise
+        socket.error if the connection is closed.
+
+        """
+        if IAC in buffer:
+            buffer = buffer.replace(IAC, IAC+IAC)
+        self.msg("send %r", buffer)
+        self.sock.sendall(buffer)
+
+    def read_until(self, match, timeout=None):
+        """Read until a given string is encountered or until timeout.
+
+        When no match is found, return whatever is available instead,
+        possibly the empty string.  Raise EOFError if the connection
+        is closed and no cooked data is available.
+
+        """
+        n = len(match)
+        self.process_rawq()
+        i = self.cookedq.find(match)
+        if i >= 0:
+            i = i+n
+            buf = self.cookedq[:i]
+            self.cookedq = self.cookedq[i:]
+            return buf
+        s_reply = ([self], [], [])
+        s_args = s_reply
+        if timeout is not None:
+            s_args = s_args + (timeout,)
+            from time import time
+            time_start = time()
+        while not self.eof and select(*s_args) == s_reply:
+            i = max(0, len(self.cookedq)-n)
+            self.fill_rawq()
+            self.process_rawq()
+            i = self.cookedq.find(match, i)
+            if i >= 0:
+                i = i+n
+                buf = self.cookedq[:i]
+                self.cookedq = self.cookedq[i:]
+                return buf
+            if timeout is not None:
+                elapsed = time() - time_start
+                if elapsed >= timeout:
+                    break
+                s_args = s_reply + (timeout-elapsed,)
+        return self.read_very_lazy()
+
+    def read_all(self):
+        """Read all data until EOF; block until connection closed."""
+        self.process_rawq()
+        while not self.eof:
+            self.fill_rawq()
+            self.process_rawq()
+        buf = self.cookedq
+        self.cookedq = ''
+        return buf
+
+    def read_some(self):
+        """Read at least one byte of cooked data unless EOF is hit.
+
+        Return '' if EOF is hit.  Block if no data is immediately
+        available.
+
+        """
+        self.process_rawq()
+        while not self.cookedq and not self.eof:
+            self.fill_rawq()
+            self.process_rawq()
+        buf = self.cookedq
+        self.cookedq = ''
+        return buf
+
+    def read_very_eager(self):
+        """Read everything that's possible without blocking in I/O (eager).
+
+        Raise EOFError if connection closed and no cooked data
+        available.  Return '' if no cooked data available otherwise.
+        Don't block unless in the midst of an IAC sequence.
+
+        """
+        self.process_rawq()
+        while not self.eof and self.sock_avail():
+            self.fill_rawq()
+            self.process_rawq()
+        return self.read_very_lazy()
+
+    def read_eager(self):
+        """Read readily available data.
+
+        Raise EOFError if connection closed and no cooked data
+        available.  Return '' if no cooked data available otherwise.
+        Don't block unless in the midst of an IAC sequence.
+
+        """
+        self.process_rawq()
+        while not self.cookedq and not self.eof and self.sock_avail():
+            self.fill_rawq()
+            self.process_rawq()
+        return self.read_very_lazy()
+
+    def read_lazy(self):
+        """Process and return data that's already in the queues (lazy).
+
+        Raise EOFError if connection closed and no data available.
+        Return '' if no cooked data available otherwise.  Don't block
+        unless in the midst of an IAC sequence.
+
+        """
+        self.process_rawq()
+        return self.read_very_lazy()
+
+    def read_very_lazy(self):
+        """Return any data available in the cooked queue (very lazy).
+
+        Raise EOFError if connection closed and no data available.
+        Return '' if no cooked data available otherwise.  Don't block.
+
+        """
+        buf = self.cookedq
+        self.cookedq = ''
+        if not buf and self.eof and not self.rawq:
+            raise EOFError, 'telnet connection closed'
+        return buf
+
+    def read_sb_data(self):
+        """Return any data available in the SB ... SE queue.
+
+        Return '' if no SB ... SE available. Should only be called
+        after seeing a SB or SE command. When a new SB command is
+        found, old unread SB data will be discarded. Don't block.
+
+        """
+        buf = self.sbdataq
+        self.sbdataq = ''
+        return buf
+
+    def set_option_negotiation_callback(self, callback):
+        """Provide a callback function called after each receipt of a telnet option."""
+        self.option_callback = callback
+
+    def process_rawq(self):
+        """Transfer from raw queue to cooked queue.
+
+        Set self.eof when connection is closed.  Don't block unless in
+        the midst of an IAC sequence.
+
+        """
+        buf = ['', '']
+        try:
+            while self.rawq:
+                c = self.rawq_getchar()
+                if not self.iacseq:
+                    if c == theNULL:
+                        continue
+                    if c == "\021":
+                        continue
+                    if c != IAC:
+                        buf[self.sb] = buf[self.sb] + c
+                        continue
+                    else:
+                        self.iacseq += c
+                elif len(self.iacseq) == 1:
+                    # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]'
+                    if c in (DO, DONT, WILL, WONT):
+                        self.iacseq += c
+                        continue
+
+                    self.iacseq = ''
+                    if c == IAC:
+                        buf[self.sb] = buf[self.sb] + c
+                    else:
+                        if c == SB: # SB ... SE start.
+                            self.sb = 1
+                            self.sbdataq = ''
+                        elif c == SE:
+                            self.sb = 0
+                            self.sbdataq = self.sbdataq + buf[1]
+                            buf[1] = ''
+                        if self.option_callback:
+                            # Callback is supposed to look into
+                            # the sbdataq
+                            self.option_callback(self.sock, c, NOOPT)
+                        else:
+                            # We can't offer automatic processing of
+                            # suboptions. Alas, we should not get any
+                            # unless we did a WILL/DO before.
+                            self.msg('IAC %d not recognized' % ord(c))
+                elif len(self.iacseq) == 2:
+                    cmd = self.iacseq[1]
+                    self.iacseq = ''
+                    opt = c
+                    if cmd in (DO, DONT):
+                        self.msg('IAC %s %d',
+                            cmd == DO and 'DO' or 'DONT', ord(opt))
+                        if self.option_callback:
+                            self.option_callback(self.sock, cmd, opt)
+                        else:
+                            self.sock.sendall(IAC + WONT + opt)
+                    elif cmd in (WILL, WONT):
+                        self.msg('IAC %s %d',
+                            cmd == WILL and 'WILL' or 'WONT', ord(opt))
+                        if self.option_callback:
+                            self.option_callback(self.sock, cmd, opt)
+                        else:
+                            self.sock.sendall(IAC + DONT + opt)
+        except EOFError: # raised by self.rawq_getchar()
+            self.iacseq = '' # Reset on EOF
+            self.sb = 0
+            pass
+        self.cookedq = self.cookedq + buf[0]
+        self.sbdataq = self.sbdataq + buf[1]
+
+    def rawq_getchar(self):
+        """Get next char from raw queue.
+
+        Block if no data is immediately available.  Raise EOFError
+        when connection is closed.
+
+        """
+        if not self.rawq:
+            self.fill_rawq()
+            if self.eof:
+                raise EOFError
+        c = self.rawq[self.irawq]
+        self.irawq = self.irawq + 1
+        if self.irawq >= len(self.rawq):
+            self.rawq = ''
+            self.irawq = 0
+        return c
+
+    def fill_rawq(self):
+        """Fill raw queue from exactly one recv() system call.
+
+        Block if no data is immediately available.  Set self.eof when
+        connection is closed.
+
+        """
+        if self.irawq >= len(self.rawq):
+            self.rawq = ''
+            self.irawq = 0
+        # The buffer size should be fairly small so as to avoid quadratic
+        # behavior in process_rawq() above
+        buf = self.sock.recv(50)
+        self.msg("recv %r", buf)
+        self.eof = (not buf)
+        self.rawq = self.rawq + buf
+
+    def sock_avail(self):
+        """Test whether data is available on the socket."""
+        return select([self], [], [], 0) == ([self], [], [])
+
+    def interact(self):
+        """Interaction function, emulates a very dumb telnet client."""
+        if sys.platform == "win32":
+            self.mt_interact()
+            return
+        while 1:
+            rfd, wfd, xfd = select([self, sys.stdin], [], [])
+            if self in rfd:
+                try:
+                    text = self.read_eager()
+                except EOFError:
+                    print '*** Connection closed by remote host ***'
+                    break
+                if text:
+                    sys.stdout.write(text)
+                    sys.stdout.flush()
+            if sys.stdin in rfd:
+                line = sys.stdin.readline()
+                if not line:
+                    break
+                self.write(line)
+
+    def mt_interact(self):
+        """Multithreaded version of interact()."""
+        import thread
+        thread.start_new_thread(self.listener, ())
+        while 1:
+            line = sys.stdin.readline()
+            if not line:
+                break
+            self.write(line)
+
+    def listener(self):
+        """Helper for mt_interact() -- this executes in the other thread."""
+        while 1:
+            try:
+                data = self.read_eager()
+            except EOFError:
+                print '*** Connection closed by remote host ***'
+                return
+            if data:
+                sys.stdout.write(data)
+            else:
+                sys.stdout.flush()
+
+    def expect(self, list, timeout=None):
+        """Read until one from a list of a regular expressions matches.
+
+        The first argument is a list of regular expressions, either
+        compiled (re.RegexObject instances) or uncompiled (strings).
+        The optional second argument is a timeout, in seconds; default
+        is no timeout.
+
+        Return a tuple of three items: the index in the list of the
+        first regular expression that matches; the match object
+        returned; and the text read up till and including the match.
+
+        If EOF is read and no text was read, raise EOFError.
+        Otherwise, when nothing matches, return (-1, None, text) where
+        text is the text received so far (may be the empty string if a
+        timeout happened).
+
+        If a regular expression ends with a greedy match (e.g. '.*')
+        or if more than one expression can match the same input, the
+        results are undeterministic, and may depend on the I/O timing.
+
+        """
+        re = None
+        list = list[:]
+        indices = range(len(list))
+        for i in indices:
+            if not hasattr(list[i], "search"):
+                if not re: import re
+                list[i] = re.compile(list[i])
+        if timeout is not None:
+            from time import time
+            time_start = time()
+        while 1:
+            self.process_rawq()
+            for i in indices:
+                m = list[i].search(self.cookedq)
+                if m:
+                    e = m.end()
+                    text = self.cookedq[:e]
+                    self.cookedq = self.cookedq[e:]
+                    return (i, m, text)
+            if self.eof:
+                break
+            if timeout is not None:
+                elapsed = time() - time_start
+                if elapsed >= timeout:
+                    break
+                s_args = ([self.fileno()], [], [], timeout-elapsed)
+                r, w, x = select(*s_args)
+                if not r:
+                    break
+            self.fill_rawq()
+        text = self.read_very_lazy()
+        if not text and self.eof:
+            raise EOFError
+        return (-1, None, text)
+
+
+def test():
+    """Test program for telnetlib.
+
+    Usage: python telnetlib.py [-d] ... [host [port]]
+
+    Default host is localhost; default port is 23.
+
+    """
+    debuglevel = 0
+    while sys.argv[1:] and sys.argv[1] == '-d':
+        debuglevel = debuglevel+1
+        del sys.argv[1]
+    host = 'localhost'
+    if sys.argv[1:]:
+        host = sys.argv[1]
+    port = 0
+    if sys.argv[2:]:
+        portstr = sys.argv[2]
+        try:
+            port = int(portstr)
+        except ValueError:
+            port = socket.getservbyname(portstr, 'tcp')
+    tn = Telnet()
+    tn.set_debuglevel(debuglevel)
+    tn.open(host, port, timeout=0.5)
+    tn.interact()
+    tn.close()
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/tempfile.py b/src/main/resources/PythonLibs/tempfile.py
new file mode 100644
index 0000000000000000000000000000000000000000..90e595e7868f938b9762b36bbe5c29883371d898
--- /dev/null
+++ b/src/main/resources/PythonLibs/tempfile.py
@@ -0,0 +1,618 @@
+"""Temporary files.
+
+This module provides generic, low- and high-level interfaces for
+creating temporary files and directories.  The interfaces listed
+as "safe" just below can be used without fear of race conditions.
+Those listed as "unsafe" cannot, and are provided for backward
+compatibility only.
+
+This module also provides some data items to the user:
+
+  TMP_MAX  - maximum number of names that will be tried before
+             giving up.
+  template - the default prefix for all temporary names.
+             You may change this to control the default prefix.
+  tempdir  - If this is set to a string before the first use of
+             any routine from this module, it will be considered as
+             another candidate location to store temporary files.
+"""
+
+__all__ = [
+    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
+    "SpooledTemporaryFile",
+    "mkstemp", "mkdtemp",                  # low level safe interfaces
+    "mktemp",                              # deprecated unsafe interface
+    "TMP_MAX", "gettempprefix",            # constants
+    "tempdir", "gettempdir"
+   ]
+
+
+# Imports.
+
+import os as _os
+import errno as _errno
+from random import Random as _Random
+
+try:
+    from cStringIO import StringIO as _StringIO
+except ImportError:
+    from StringIO import StringIO as _StringIO
+
+try:
+    import fcntl as _fcntl
+except ImportError:
+    def _set_cloexec(fd):
+        pass
+else:
+    def _set_cloexec(fd):
+        try:
+            flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
+        except IOError:
+            pass
+        else:
+            # flags read successfully, modify
+            flags |= _fcntl.FD_CLOEXEC
+            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
+
+
+try:
+    import thread as _thread
+except ImportError:
+    import dummy_thread as _thread
+_allocate_lock = _thread.allocate_lock
+
+_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
+if hasattr(_os, 'O_NOINHERIT'):
+    _text_openflags |= _os.O_NOINHERIT
+if hasattr(_os, 'O_NOFOLLOW'):
+    _text_openflags |= _os.O_NOFOLLOW
+
+_bin_openflags = _text_openflags
+if hasattr(_os, 'O_BINARY'):
+    _bin_openflags |= _os.O_BINARY
+
+if hasattr(_os, 'TMP_MAX'):
+    TMP_MAX = _os.TMP_MAX
+else:
+    TMP_MAX = 10000
+
+template = "tmp"
+
+# Internal routines.
+
+_once_lock = _allocate_lock()
+
+if hasattr(_os, "lstat"):
+    _stat = _os.lstat
+elif hasattr(_os, "stat"):
+    _stat = _os.stat
+else:
+    # Fallback.  All we need is something that raises os.error if the
+    # file doesn't exist.
+    def _stat(fn):
+        try:
+            f = open(fn)
+        except IOError:
+            raise _os.error
+        f.close()
+
+def _exists(fn):
+    try:
+        _stat(fn)
+    except _os.error:
+        return False
+    else:
+        return True
+
+class _RandomNameSequence:
+    """An instance of _RandomNameSequence generates an endless
+    sequence of unpredictable strings which can safely be incorporated
+    into file names.  Each string is six characters long.  Multiple
+    threads can safely use the same instance at the same time.
+
+    _RandomNameSequence is an iterator."""
+
+    characters = ("abcdefghijklmnopqrstuvwxyz" +
+                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+                  "0123456789_")
+
+    def __init__(self):
+        self.mutex = _allocate_lock()
+        self.normcase = _os.path.normcase
+
+    @property
+    def rng(self):
+        if _os.sys.platform.startswith("java"):
+            #A JVM run cannot determine or change its pid so dummy this.
+            cur_pid = 1
+        else:
+            cur_pid = _os.getpid()
+        
+        if cur_pid != getattr(self, '_rng_pid', None):
+            self._rng = _Random()
+            self._rng_pid = cur_pid
+        return self._rng
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        m = self.mutex
+        c = self.characters
+        choose = self.rng.choice
+
+        m.acquire()
+        try:
+            letters = [choose(c) for dummy in "123456"]
+        finally:
+            m.release()
+
+        return self.normcase(''.join(letters))
+
+def _candidate_tempdir_list():
+    """Generate a list of candidate temporary directories which
+    _get_default_tempdir will try."""
+
+    dirlist = []
+
+    # First, try the environment.
+    for envname in 'TMPDIR', 'TEMP', 'TMP':
+        dirname = _os.getenv(envname)
+        if dirname: dirlist.append(dirname)
+
+    # Failing that, try OS-specific locations.
+    if _os.name == 'riscos':
+        dirname = _os.getenv('Wimp$ScrapDir')
+        if dirname: dirlist.append(dirname)
+    elif _os.name == 'nt':
+        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
+    else:
+        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
+
+    # As a last resort, the current directory.
+    try:
+        dirlist.append(_os.getcwd())
+    except (AttributeError, _os.error):
+        dirlist.append(_os.curdir)
+
+    return dirlist
+
+def _get_default_tempdir():
+    """Calculate the default directory to use for temporary files.
+    This routine should be called exactly once.
+
+    We determine whether or not a candidate temp dir is usable by
+    trying to create and write to a file in that directory.  If this
+    is successful, the test file is deleted.  To prevent denial of
+    service, the name of the test file must be randomized."""
+
+    namer = _RandomNameSequence()
+    dirlist = _candidate_tempdir_list()
+    flags = _text_openflags
+
+    for dir in dirlist:
+        if dir != _os.curdir:
+            dir = _os.path.normcase(_os.path.abspath(dir))
+        # Try only a few names per directory.
+        for seq in xrange(100):
+            name = namer.next()
+            filename = _os.path.join(dir, name)
+            try:
+                fd = _os.open(filename, flags, 0600)
+                fp = _os.fdopen(fd, 'w')
+                fp.write('blat')
+                fp.close()
+                _os.unlink(filename)
+                del fp, fd
+                return dir
+            except (OSError, IOError), e:
+                if e[0] != _errno.EEXIST:
+                    break # no point trying more names in this directory
+                pass
+    raise IOError, (_errno.ENOENT,
+                    ("No usable temporary directory found in %s" % dirlist))
+
+_name_sequence = None
+
+def _get_candidate_names():
+    """Common setup sequence for all user-callable interfaces."""
+
+    global _name_sequence
+    if _name_sequence is None:
+        _once_lock.acquire()
+        try:
+            if _name_sequence is None:
+                _name_sequence = _RandomNameSequence()
+        finally:
+            _once_lock.release()
+    return _name_sequence
+
+
+def _mkstemp_inner(dir, pre, suf, flags):
+    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
+
+    names = _get_candidate_names()
+
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, pre + name + suf)
+        try:
+            fd = _os.open(file, flags, 0600)
+            _set_cloexec(fd)
+            return (fd, _os.path.abspath(file))
+        except OSError, e:
+            if e.errno == _errno.EEXIST:
+                continue # try again
+            raise
+
+    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
+
+
+# User visible interfaces.
+
+def gettempprefix():
+    """Accessor for tempdir.template."""
+    return template
+
+tempdir = None
+
+def gettempdir():
+    """Accessor for tempfile.tempdir."""
+    global tempdir
+    if tempdir is None:
+        _once_lock.acquire()
+        try:
+            if tempdir is None:
+                tempdir = _get_default_tempdir()
+        finally:
+            _once_lock.release()
+    return tempdir
+
+def mkstemp(suffix="", prefix=template, dir=None, text=False):
+    """User-callable function to create and return a unique temporary
+    file.  The return value is a pair (fd, name) where fd is the
+    file descriptor returned by os.open, and name is the filename.
+
+    If 'suffix' is specified, the file name will end with that suffix,
+    otherwise there will be no suffix.
+
+    If 'prefix' is specified, the file name will begin with that prefix,
+    otherwise a default prefix is used.
+
+    If 'dir' is specified, the file will be created in that directory,
+    otherwise a default directory is used.
+
+    If 'text' is specified and true, the file is opened in text
+    mode.  Else (the default) the file is opened in binary mode.  On
+    some operating systems, this makes no difference.
+
+    The file is readable and writable only by the creating user ID.
+    If the operating system uses permission bits to indicate whether a
+    file is executable, the file is executable by no one. The file
+    descriptor is not inherited by children of this process.
+
+    Caller is responsible for deleting the file when done with it.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    if text:
+        flags = _text_openflags
+    else:
+        flags = _bin_openflags
+
+    return _mkstemp_inner(dir, prefix, suffix, flags)
+
+
+def mkdtemp(suffix="", prefix=template, dir=None):
+    """User-callable function to create and return a unique temporary
+    directory.  The return value is the pathname of the directory.
+
+    Arguments are as for mkstemp, except that the 'text' argument is
+    not accepted.
+
+    The directory is readable, writable, and searchable only by the
+    creating user.
+
+    Caller is responsible for deleting the directory when done with it.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    names = _get_candidate_names()
+
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, prefix + name + suffix)
+        try:
+            _os.mkdir(file, 0700)
+            return file
+        except OSError, e:
+            if e.errno == _errno.EEXIST:
+                continue # try again
+            raise
+
+    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
+
+def mktemp(suffix="", prefix=template, dir=None):
+    """User-callable function to return a unique temporary file name.  The
+    file is not created.
+
+    Arguments are as for mkstemp, except that the 'text' argument is
+    not accepted.
+
+    This function is unsafe and should not be used.  The file name
+    refers to a file that did not exist at some point, but by the time
+    you get around to creating it, someone else may have beaten you to
+    the punch.
+    """
+
+##    from warnings import warn as _warn
+##    _warn("mktemp is a potential security risk to your program",
+##          RuntimeWarning, stacklevel=2)
+
+    if dir is None:
+        dir = gettempdir()
+
+    names = _get_candidate_names()
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, prefix + name + suffix)
+        if not _exists(file):
+            return file
+
+    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
+
+
+class _TemporaryFileWrapper:
+    """Temporary file wrapper
+
+    This class provides a wrapper around files opened for
+    temporary use.  In particular, it seeks to automatically
+    remove the file when it is no longer needed.
+    """
+
+    def __init__(self, file, name, delete=True):
+        self.file = file
+        self.name = name
+        self.close_called = False
+        self.delete = delete
+
+    def __getattr__(self, name):
+        # Attribute lookups are delegated to the underlying file
+        # and cached for non-numeric results
+        # (i.e. methods are cached, closed and friends are not)
+        file = self.__dict__['file']
+        a = getattr(file, name)
+        if not issubclass(type(a), type(0)):
+            setattr(self, name, a)
+        return a
+
+    # The underlying __enter__ method returns the wrong object
+    # (self.file) so override it to return the wrapper
+    def __enter__(self):
+        self.file.__enter__()
+        return self
+
+    # NT provides delete-on-close as a primitive, so we don't need
+    # the wrapper to do anything special.  We still use it so that
+    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
+    if _os.name != 'nt':
+        # Cache the unlinker so we don't get spurious errors at
+        # shutdown when the module-level "os" is None'd out.  Note
+        # that this must be referenced as self.unlink, because the
+        # name TemporaryFileWrapper may also get None'd out before
+        # __del__ is called.
+        unlink = _os.unlink
+
+        def close(self):
+            if not self.close_called:
+                self.close_called = True
+                self.file.close()
+                if self.delete:
+                    self.unlink(self.name)
+
+        def __del__(self):
+            self.close()
+
+        # Need to trap __exit__ as well to ensure the file gets
+        # deleted when used in a with statement
+        def __exit__(self, exc, value, tb):
+            result = self.file.__exit__(exc, value, tb)
+            self.close()
+            return result
+    else:
+        def __exit__(self, exc, value, tb):
+            self.file.__exit__(exc, value, tb)
+
+
+def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
+                       prefix=template, dir=None, delete=True):
+    """Create and return a temporary file.
+    Arguments:
+    'prefix', 'suffix', 'dir' -- as for mkstemp.
+    'mode' -- the mode argument to os.fdopen (default "w+b").
+    'bufsize' -- the buffer size argument to os.fdopen (default -1).
+    'delete' -- whether the file is deleted on close (default True).
+    The file is created as mkstemp() would do it.
+
+    Returns an object with a file-like interface; the name of the file
+    is accessible as file.name.  The file will be automatically deleted
+    when it is closed unless the 'delete' argument is set to False.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    if 'b' in mode:
+        flags = _bin_openflags
+    else:
+        flags = _text_openflags
+
+    # Setting O_TEMPORARY in the flags causes the OS to delete
+    # the file when it is closed.  This is only supported by Windows.
+    if _os.name == 'nt' and delete:
+        flags |= _os.O_TEMPORARY
+
+    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
+    file = _os.fdopen(fd, mode, bufsize)
+    return _TemporaryFileWrapper(file, name, delete)
+
+if _os.name != 'posix' or _os.sys.platform == 'cygwin':
+    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
+    # while it is open.
+    TemporaryFile = NamedTemporaryFile
+
+else:
+    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
+                      prefix=template, dir=None):
+        """Create and return a temporary file.
+        Arguments:
+        'prefix', 'suffix', 'dir' -- as for mkstemp.
+        'mode' -- the mode argument to os.fdopen (default "w+b").
+        'bufsize' -- the buffer size argument to os.fdopen (default -1).
+        The file is created as mkstemp() would do it.
+
+        Returns an object with a file-like interface.  The file has no
+        name, and will cease to exist when it is closed.
+        """
+
+        if dir is None:
+            dir = gettempdir()
+
+        if 'b' in mode:
+            flags = _bin_openflags
+        else:
+            flags = _text_openflags
+
+        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
+        try:
+            _os.unlink(name)
+            return _os.fdopen(fd, mode, bufsize)
+        except:
+            _os.close(fd)
+            raise
+
+class SpooledTemporaryFile:
+    """Temporary file wrapper, specialized to switch from
+    StringIO to a real file when it exceeds a certain size or
+    when a fileno is needed.
+    """
+    _rolled = False
+
+    def __init__(self, max_size=0, mode='w+b', bufsize=-1,
+                 suffix="", prefix=template, dir=None):
+        self._file = _StringIO()
+        self._max_size = max_size
+        self._rolled = False
+        self._TemporaryFileArgs = (mode, bufsize, suffix, prefix, dir)
+
+    def _check(self, file):
+        if self._rolled: return
+        max_size = self._max_size
+        if max_size and file.tell() > max_size:
+            self.rollover()
+
+    def rollover(self):
+        if self._rolled: return
+        file = self._file
+        newfile = self._file = TemporaryFile(*self._TemporaryFileArgs)
+        del self._TemporaryFileArgs
+
+        newfile.write(file.getvalue())
+        newfile.seek(file.tell(), 0)
+
+        self._rolled = True
+
+    # The method caching trick from NamedTemporaryFile
+    # won't work here, because _file may change from a
+    # _StringIO instance to a real file. So we list
+    # all the methods directly.
+
+    # Context management protocol
+    def __enter__(self):
+        if self._file.closed:
+            raise ValueError("Cannot enter context with closed file")
+        return self
+
+    def __exit__(self, exc, value, tb):
+        self._file.close()
+
+    # file protocol
+    def __iter__(self):
+        return self._file.__iter__()
+
+    def close(self):
+        self._file.close()
+
+    @property
+    def closed(self):
+        return self._file.closed
+
+    @property
+    def encoding(self):
+        return self._file.encoding
+
+    def fileno(self):
+        self.rollover()
+        return self._file.fileno()
+
+    def flush(self):
+        self._file.flush()
+
+    def isatty(self):
+        return self._file.isatty()
+
+    @property
+    def mode(self):
+        return self._file.mode
+
+    @property
+    def name(self):
+        return self._file.name
+
+    @property
+    def newlines(self):
+        return self._file.newlines
+
+    def next(self):
+        return self._file.next
+
+    def read(self, *args):
+        return self._file.read(*args)
+
+    def readline(self, *args):
+        return self._file.readline(*args)
+
+    def readlines(self, *args):
+        return self._file.readlines(*args)
+
+    def seek(self, *args):
+        self._file.seek(*args)
+
+    @property
+    def softspace(self):
+        return self._file.softspace
+
+    def tell(self):
+        return self._file.tell()
+
+    def truncate(self):
+        self._file.truncate()
+
+    def write(self, s):
+        file = self._file
+        rv = file.write(s)
+        self._check(file)
+        return rv
+
+    def writelines(self, iterable):
+        file = self._file
+        rv = file.writelines(iterable)
+        self._check(file)
+        return rv
+
+    def xreadlines(self, *args):
+        return self._file.xreadlines(*args)
diff --git a/src/main/resources/PythonLibs/textwrap.py b/src/main/resources/PythonLibs/textwrap.py
new file mode 100644
index 0000000000000000000000000000000000000000..62ea0b48e6c18955c08a43805067c072387fee61
--- /dev/null
+++ b/src/main/resources/PythonLibs/textwrap.py
@@ -0,0 +1,425 @@
+"""Text wrapping and filling.
+"""
+
+# Copyright (C) 1999-2001 Gregory P. Ward.
+# Copyright (C) 2002, 2003 Python Software Foundation.
+# Written by Greg Ward <gward@python.net>
+
+__revision__ = "$Id$"
+
+import string, re
+
+try:
+    _unicode = unicode
+except NameError:
+    # If Python is built without Unicode support, the unicode type
+    # will not exist. Fake one.
+    class _unicode(object):
+        pass
+
+# Do the right thing with boolean values for all known Python versions
+# (so this module can be copied to projects that don't depend on Python
+# 2.3, e.g. Optik and Docutils) by uncommenting the block of code below.
+#try:
+#    True, False
+#except NameError:
+#    (True, False) = (1, 0)
+
+__all__ = ['TextWrapper', 'wrap', 'fill', 'dedent']
+
+# Hardcode the recognized whitespace characters to the US-ASCII
+# whitespace characters.  The main reason for doing this is that in
+# ISO-8859-1, 0xa0 is non-breaking whitespace, so in certain locales
+# that character winds up in string.whitespace.  Respecting
+# string.whitespace in those cases would 1) make textwrap treat 0xa0 the
+# same as any other whitespace char, which is clearly wrong (it's a
+# *non-breaking* space), 2) possibly cause problems with Unicode,
+# since 0xa0 is not in range(128).
+_whitespace = '\t\n\x0b\x0c\r '
+
+class TextWrapper:
+    """
+    Object for wrapping/filling text.  The public interface consists of
+    the wrap() and fill() methods; the other methods are just there for
+    subclasses to override in order to tweak the default behaviour.
+    If you want to completely replace the main wrapping algorithm,
+    you'll probably have to override _wrap_chunks().
+
+    Several instance attributes control various aspects of wrapping:
+      width (default: 70)
+        the maximum width of wrapped lines (unless break_long_words
+        is false)
+      initial_indent (default: "")
+        string that will be prepended to the first line of wrapped
+        output.  Counts towards the line's width.
+      subsequent_indent (default: "")
+        string that will be prepended to all lines save the first
+        of wrapped output; also counts towards each line's width.
+      expand_tabs (default: true)
+        Expand tabs in input text to spaces before further processing.
+        Each tab will become 1 .. 8 spaces, depending on its position in
+        its line.  If false, each tab is treated as a single character.
+      replace_whitespace (default: true)
+        Replace all whitespace characters in the input text by spaces
+        after tab expansion.  Note that if expand_tabs is false and
+        replace_whitespace is true, every tab will be converted to a
+        single space!
+      fix_sentence_endings (default: false)
+        Ensure that sentence-ending punctuation is always followed
+        by two spaces.  Off by default because the algorithm is
+        (unavoidably) imperfect.
+      break_long_words (default: true)
+        Break words longer than 'width'.  If false, those words will not
+        be broken, and some lines might be longer than 'width'.
+      break_on_hyphens (default: true)
+        Allow breaking hyphenated words. If true, wrapping will occur
+        preferably on whitespaces and right after hyphens part of
+        compound words.
+      drop_whitespace (default: true)
+        Drop leading and trailing whitespace from lines.
+    """
+
+    whitespace_trans = string.maketrans(_whitespace, ' ' * len(_whitespace))
+
+    unicode_whitespace_trans = {}
+    uspace = ord(u' ')
+    for x in map(ord, _whitespace):
+        unicode_whitespace_trans[x] = uspace
+
+    # This funky little regex is just the trick for splitting
+    # text up into word-wrappable chunks.  E.g.
+    #   "Hello there -- you goof-ball, use the -b option!"
+    # splits into
+    #   Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option!
+    # (after stripping out empty strings).
+    wordsep_re = re.compile(
+        r'(\s+|'                                  # any whitespace
+        r'[^\s\w]*\w+[^0-9\W]-(?=\w+[^0-9\W])|'   # hyphenated words
+        r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))')   # em-dash
+
+    # This less funky little regex just split on recognized spaces. E.g.
+    #   "Hello there -- you goof-ball, use the -b option!"
+    # splits into
+    #   Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/
+    wordsep_simple_re = re.compile(r'(\s+)')
+
+    # XXX this is not locale- or charset-aware -- string.lowercase
+    # is US-ASCII only (and therefore English-only)
+    sentence_end_re = re.compile(r'[%s]'              # lowercase letter
+                                 r'[\.\!\?]'          # sentence-ending punct.
+                                 r'[\"\']?'           # optional end-of-quote
+                                 r'\Z'                # end of chunk
+                                 % string.lowercase)
+
+
+    def __init__(self,
+                 width=70,
+                 initial_indent="",
+                 subsequent_indent="",
+                 expand_tabs=True,
+                 replace_whitespace=True,
+                 fix_sentence_endings=False,
+                 break_long_words=True,
+                 drop_whitespace=True,
+                 break_on_hyphens=True):
+        self.width = width
+        self.initial_indent = initial_indent
+        self.subsequent_indent = subsequent_indent
+        self.expand_tabs = expand_tabs
+        self.replace_whitespace = replace_whitespace
+        self.fix_sentence_endings = fix_sentence_endings
+        self.break_long_words = break_long_words
+        self.drop_whitespace = drop_whitespace
+        self.break_on_hyphens = break_on_hyphens
+
+        # recompile the regexes for Unicode mode -- done in this clumsy way for
+        # backwards compatibility because it's rather common to monkey-patch
+        # the TextWrapper class' wordsep_re attribute.
+        self.wordsep_re_uni = re.compile(self.wordsep_re.pattern, re.U)
+        self.wordsep_simple_re_uni = re.compile(
+            self.wordsep_simple_re.pattern, re.U)
+
+
+    # -- Private methods -----------------------------------------------
+    # (possibly useful for subclasses to override)
+
+    def _munge_whitespace(self, text):
+        """_munge_whitespace(text : string) -> string
+
+        Munge whitespace in text: expand tabs and convert all other
+        whitespace characters to spaces.  Eg. " foo\tbar\n\nbaz"
+        becomes " foo    bar  baz".
+        """
+        if self.expand_tabs:
+            text = text.expandtabs()
+        if self.replace_whitespace:
+            if isinstance(text, str):
+                text = text.translate(self.whitespace_trans)
+            elif isinstance(text, _unicode):
+                text = text.translate(self.unicode_whitespace_trans)
+        return text
+
+
+    def _split(self, text):
+        """_split(text : string) -> [string]
+
+        Split the text to wrap into indivisible chunks.  Chunks are
+        not quite the same as words; see _wrap_chunks() for full
+        details.  As an example, the text
+          Look, goof-ball -- use the -b option!
+        breaks into the following chunks:
+          'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
+          'use', ' ', 'the', ' ', '-b', ' ', 'option!'
+        if break_on_hyphens is True, or in:
+          'Look,', ' ', 'goof-ball', ' ', '--', ' ',
+          'use', ' ', 'the', ' ', '-b', ' ', option!'
+        otherwise.
+        """
+        if isinstance(text, _unicode):
+            if self.break_on_hyphens:
+                pat = self.wordsep_re_uni
+            else:
+                pat = self.wordsep_simple_re_uni
+        else:
+            if self.break_on_hyphens:
+                pat = self.wordsep_re
+            else:
+                pat = self.wordsep_simple_re
+        chunks = pat.split(text)
+        chunks = filter(None, chunks)  # remove empty chunks
+        return chunks
+
+    def _fix_sentence_endings(self, chunks):
+        """_fix_sentence_endings(chunks : [string])
+
+        Correct for sentence endings buried in 'chunks'.  Eg. when the
+        original text contains "... foo.\nBar ...", munge_whitespace()
+        and split() will convert that to [..., "foo.", " ", "Bar", ...]
+        which has one too few spaces; this method simply changes the one
+        space to two.
+        """
+        i = 0
+        patsearch = self.sentence_end_re.search
+        while i < len(chunks)-1:
+            if chunks[i+1] == " " and patsearch(chunks[i]):
+                chunks[i+1] = "  "
+                i += 2
+            else:
+                i += 1
+
+    def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
+        """_handle_long_word(chunks : [string],
+                             cur_line : [string],
+                             cur_len : int, width : int)
+
+        Handle a chunk of text (most likely a word, not whitespace) that
+        is too long to fit in any line.
+        """
+        # Figure out when indent is larger than the specified width, and make
+        # sure at least one character is stripped off on every pass
+        if width < 1:
+            space_left = 1
+        else:
+            space_left = width - cur_len
+
+        # If we're allowed to break long words, then do so: put as much
+        # of the next chunk onto the current line as will fit.
+        if self.break_long_words:
+            cur_line.append(reversed_chunks[-1][:space_left])
+            reversed_chunks[-1] = reversed_chunks[-1][space_left:]
+
+        # Otherwise, we have to preserve the long word intact.  Only add
+        # it to the current line if there's nothing already there --
+        # that minimizes how much we violate the width constraint.
+        elif not cur_line:
+            cur_line.append(reversed_chunks.pop())
+
+        # If we're not allowed to break long words, and there's already
+        # text on the current line, do nothing.  Next time through the
+        # main loop of _wrap_chunks(), we'll wind up here again, but
+        # cur_len will be zero, so the next line will be entirely
+        # devoted to the long word that we can't handle right now.
+
+    def _wrap_chunks(self, chunks):
+        """_wrap_chunks(chunks : [string]) -> [string]
+
+        Wrap a sequence of text chunks and return a list of lines of
+        length 'self.width' or less.  (If 'break_long_words' is false,
+        some lines may be longer than this.)  Chunks correspond roughly
+        to words and the whitespace between them: each chunk is
+        indivisible (modulo 'break_long_words'), but a line break can
+        come between any two chunks.  Chunks should not have internal
+        whitespace; ie. a chunk is either all whitespace or a "word".
+        Whitespace chunks will be removed from the beginning and end of
+        lines, but apart from that whitespace is preserved.
+        """
+        lines = []
+        if self.width <= 0:
+            raise ValueError("invalid width %r (must be > 0)" % self.width)
+
+        # Arrange in reverse order so items can be efficiently popped
+        # from a stack of chucks.
+        chunks.reverse()
+
+        while chunks:
+
+            # Start the list of chunks that will make up the current line.
+            # cur_len is just the length of all the chunks in cur_line.
+            cur_line = []
+            cur_len = 0
+
+            # Figure out which static string will prefix this line.
+            if lines:
+                indent = self.subsequent_indent
+            else:
+                indent = self.initial_indent
+
+            # Maximum width for this line.
+            width = self.width - len(indent)
+
+            # First chunk on line is whitespace -- drop it, unless this
+            # is the very beginning of the text (ie. no lines started yet).
+            if self.drop_whitespace and chunks[-1].strip() == '' and lines:
+                del chunks[-1]
+
+            while chunks:
+                l = len(chunks[-1])
+
+                # Can at least squeeze this chunk onto the current line.
+                if cur_len + l <= width:
+                    cur_line.append(chunks.pop())
+                    cur_len += l
+
+                # Nope, this line is full.
+                else:
+                    break
+
+            # The current line is full, and the next chunk is too big to
+            # fit on *any* line (not just this one).
+            if chunks and len(chunks[-1]) > width:
+                self._handle_long_word(chunks, cur_line, cur_len, width)
+
+            # If the last chunk on this line is all whitespace, drop it.
+            if self.drop_whitespace and cur_line and cur_line[-1].strip() == '':
+                del cur_line[-1]
+
+            # Convert current line back to a string and store it in list
+            # of all lines (return value).
+            if cur_line:
+                lines.append(indent + ''.join(cur_line))
+
+        return lines
+
+
+    # -- Public interface ----------------------------------------------
+
+    def wrap(self, text):
+        """wrap(text : string) -> [string]
+
+        Reformat the single paragraph in 'text' so it fits in lines of
+        no more than 'self.width' columns, and return a list of wrapped
+        lines.  Tabs in 'text' are expanded with string.expandtabs(),
+        and all other whitespace characters (including newline) are
+        converted to space.
+        """
+        text = self._munge_whitespace(text)
+        chunks = self._split(text)
+        if self.fix_sentence_endings:
+            self._fix_sentence_endings(chunks)
+        return self._wrap_chunks(chunks)
+
+    def fill(self, text):
+        """fill(text : string) -> string
+
+        Reformat the single paragraph in 'text' to fit in lines of no
+        more than 'self.width' columns, and return a new string
+        containing the entire wrapped paragraph.
+        """
+        return "\n".join(self.wrap(text))
+
+
+# -- Convenience interface ---------------------------------------------
+
+def wrap(text, width=70, **kwargs):
+    """Wrap a single paragraph of text, returning a list of wrapped lines.
+
+    Reformat the single paragraph in 'text' so it fits in lines of no
+    more than 'width' columns, and return a list of wrapped lines.  By
+    default, tabs in 'text' are expanded with string.expandtabs(), and
+    all other whitespace characters (including newline) are converted to
+    space.  See TextWrapper class for available keyword args to customize
+    wrapping behaviour.
+    """
+    w = TextWrapper(width=width, **kwargs)
+    return w.wrap(text)
+
+def fill(text, width=70, **kwargs):
+    """Fill a single paragraph of text, returning a new string.
+
+    Reformat the single paragraph in 'text' to fit in lines of no more
+    than 'width' columns, and return a new string containing the entire
+    wrapped paragraph.  As with wrap(), tabs are expanded and other
+    whitespace characters converted to space.  See TextWrapper class for
+    available keyword args to customize wrapping behaviour.
+    """
+    w = TextWrapper(width=width, **kwargs)
+    return w.fill(text)
+
+
+# -- Loosely related functionality -------------------------------------
+
+_whitespace_only_re = re.compile('^[ \t]+$', re.MULTILINE)
+_leading_whitespace_re = re.compile('(^[ \t]*)(?:[^ \t\n])', re.MULTILINE)
+
+def dedent(text):
+    """Remove any common leading whitespace from every line in `text`.
+
+    This can be used to make triple-quoted strings line up with the left
+    edge of the display, while still presenting them in the source code
+    in indented form.
+
+    Note that tabs and spaces are both treated as whitespace, but they
+    are not equal: the lines "  hello" and "\thello" are
+    considered to have no common leading whitespace.  (This behaviour is
+    new in Python 2.5; older versions of this module incorrectly
+    expanded tabs before searching for common leading whitespace.)
+    """
+    # Look for the longest leading string of spaces and tabs common to
+    # all lines.
+    margin = None
+    text = _whitespace_only_re.sub('', text)
+    indents = _leading_whitespace_re.findall(text)
+    for indent in indents:
+        if margin is None:
+            margin = indent
+
+        # Current line more deeply indented than previous winner:
+        # no change (previous winner is still on top).
+        elif indent.startswith(margin):
+            pass
+
+        # Current line consistent with and no deeper than previous winner:
+        # it's the new winner.
+        elif margin.startswith(indent):
+            margin = indent
+
+        # Current line and previous winner have no common whitespace:
+        # there is no margin.
+        else:
+            margin = ""
+            break
+
+    # sanity check (testing/debugging only)
+    if 0 and margin:
+        for line in text.split("\n"):
+            assert not line or line.startswith(margin), \
+                   "line = %r, margin = %r" % (line, margin)
+
+    if margin:
+        text = re.sub(r'(?m)^' + margin, '', text)
+    return text
+
+if __name__ == "__main__":
+    #print dedent("\tfoo\n\tbar")
+    #print dedent("  \thello there\n  \t  how are you?")
+    print dedent("Hello there.\n  This is indented.")
diff --git a/src/main/resources/PythonLibs/this.py b/src/main/resources/PythonLibs/this.py
new file mode 100644
index 0000000000000000000000000000000000000000..37754b785ab17820732e8ce0b0f0c543ef075b12
--- /dev/null
+++ b/src/main/resources/PythonLibs/this.py
@@ -0,0 +1,28 @@
+s = """Gur Mra bs Clguba, ol Gvz Crgref
+
+Ornhgvshy vf orggre guna htyl.
+Rkcyvpvg vf orggre guna vzcyvpvg.
+Fvzcyr vf orggre guna pbzcyrk.
+Pbzcyrk vf orggre guna pbzcyvpngrq.
+Syng vf orggre guna arfgrq.
+Fcnefr vf orggre guna qrafr.
+Ernqnovyvgl pbhagf.
+Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.
+Nygubhtu cenpgvpnyvgl orngf chevgl.
+Reebef fubhyq arire cnff fvyragyl.
+Hayrff rkcyvpvgyl fvyraprq.
+Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
+Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
+Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.
+Abj vf orggre guna arire.
+Nygubhtu arire vf bsgra orggre guna *evtug* abj.
+Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.
+Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
+Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!"""
+
+d = {}
+for c in (65, 97):
+    for i in range(26):
+        d[chr(i+c)] = chr((i+13) % 26 + c)
+
+print "".join([d.get(c, c) for c in s])
diff --git a/src/main/resources/PythonLibs/threading.py b/src/main/resources/PythonLibs/threading.py
new file mode 100644
index 0000000000000000000000000000000000000000..6870b69fc9ad54b10dd30d537b2eeb0f834c6868
--- /dev/null
+++ b/src/main/resources/PythonLibs/threading.py
@@ -0,0 +1,428 @@
+from java.lang import InterruptedException
+from java.util import Collections, WeakHashMap
+from java.util.concurrent import Semaphore, CyclicBarrier
+from java.util.concurrent.locks import ReentrantLock
+from org.python.util import jython
+from org.python.core import Py
+from thread import _newFunctionThread
+from thread import _local as local
+from _threading import Lock, RLock, Condition, _Lock, _RLock, _threads, _active, _jthread_to_pythread, _register_thread, _unregister_thread
+import java.lang.Thread
+import sys as _sys
+from traceback import print_exc as _print_exc
+
+# Rename some stuff so "from threading import *" is safe
+__all__ = ['activeCount', 'active_count', 'Condition', 'currentThread',
+           'current_thread', 'enumerate', 'Event',
+           'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',
+           'Timer', 'setprofile', 'settrace', 'local', 'stack_size']
+
+_VERBOSE = False
+
+if __debug__:
+
+    class _Verbose(object):
+
+        def __init__(self, verbose=None):
+            if verbose is None:
+                verbose = _VERBOSE
+            self.__verbose = verbose
+
+        def _note(self, format, *args):
+            if self.__verbose:
+                format = format % args
+                format = "%s: %s\n" % (
+                    currentThread().getName(), format)
+                _sys.stderr.write(format)
+
+else:
+    # Disable this when using "python -O"
+    class _Verbose(object):
+        def __init__(self, verbose=None):
+            pass
+        def _note(self, *args):
+            pass
+
+# Support for profile and trace hooks
+
+_profile_hook = None
+_trace_hook = None
+
+def setprofile(func):
+    global _profile_hook
+    _profile_hook = func
+
+def settrace(func):
+    global _trace_hook
+    _trace_hook = func
+
+
+class Semaphore(object):
+    def __init__(self, value=1):
+        if value < 0:
+            raise ValueError("Semaphore initial value must be >= 0")
+        self._semaphore = java.util.concurrent.Semaphore(value)
+
+    def acquire(self, blocking=True):
+        if blocking:
+            self._semaphore.acquire()
+            return True
+        else:
+            return self._semaphore.tryAcquire()
+
+    def __enter__(self):
+        self.acquire()
+        return self
+
+    def release(self):
+        self._semaphore.release()
+
+    def __exit__(self, t, v, tb):
+        self.release()
+
+
+ThreadStates = {
+    java.lang.Thread.State.NEW : 'initial',
+    java.lang.Thread.State.RUNNABLE: 'started',
+    java.lang.Thread.State.BLOCKED: 'started',
+    java.lang.Thread.State.WAITING: 'started',
+    java.lang.Thread.State.TIMED_WAITING: 'started',
+    java.lang.Thread.State.TERMINATED: 'stopped',
+}
+
+class JavaThread(object):
+    def __init__(self, thread):
+        self._thread = thread
+        _register_thread(thread, self)
+
+    def __repr__(self):
+        _thread = self._thread
+        status = ThreadStates[_thread.getState()]
+        if _thread.isDaemon(): status + " daemon"
+        return "<%s(%s, %s %s)>" % (self.__class__.__name__, self.getName(), status, self.ident)
+
+    def __eq__(self, other):
+        if isinstance(other, JavaThread):
+            return self._thread == other._thread
+        else:
+            return False
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def start(self):
+        self._thread.start()
+
+    def run(self):
+        self._thread.run()
+
+    def join(self, timeout=None):
+        if timeout:
+            millis = timeout * 1000.
+            millis_int = int(millis)
+            nanos = int((millis - millis_int) * 1e6)
+            self._thread.join(millis_int, nanos)
+        else:
+            self._thread.join()
+
+    def ident(self):
+        return self._thread.getId()
+
+    ident = property(ident)
+
+    def getName(self):
+        return self._thread.getName()
+
+    def setName(self, name):
+        self._thread.setName(str(name))
+
+    name = property(getName, setName)
+
+    def isAlive(self):
+        return self._thread.isAlive()
+
+    is_alive = isAlive
+
+    def isDaemon(self):
+        return self._thread.isDaemon()
+
+    def setDaemon(self, daemonic):
+        self._thread.setDaemon(bool(daemonic))
+
+    def __tojava__(self, c):
+        if isinstance(self._thread, c):
+            return self._thread
+        if isinstance(self, c):
+            return self
+        return Py.NoConversion
+
+
+class Thread(JavaThread):
+    def __init__(self, group=None, target=None, name=None, args=None, kwargs=None):
+        assert group is None, "group argument must be None for now"
+        _thread = self._create_thread()
+        JavaThread.__init__(self, _thread)
+        if args is None:
+            args = ()
+        if kwargs is None:
+            kwargs = {}
+        self._target = target
+        self._args = args
+        self._kwargs = kwargs
+        if name:
+            self._thread.setName(str(name))
+
+    def _create_thread(self):
+        return _newFunctionThread(self.__bootstrap, ())
+
+    def run(self):
+        if self._target:
+            self._target(*self._args, **self._kwargs)
+
+    def __bootstrap(self):
+        try:
+            if _trace_hook:
+                _sys.settrace(_trace_hook)
+            if _profile_hook:
+                _sys.setprofile(_profile_hook)
+            try:
+                self.run()
+            except SystemExit:
+                pass
+            except InterruptedException:
+                # Quiet InterruptedExceptions if they're caused by
+                # _systemrestart
+                if not jython.shouldRestart:
+                    raise
+            except:
+                # If sys.stderr is no more (most likely from interpreter
+                # shutdown) use self.__stderr.  Otherwise still use sys (as in
+                # _sys) in case sys.stderr was redefined.
+                if _sys:
+                    _sys.stderr.write("Exception in thread %s:" %
+                            self.getName())
+                    _print_exc(file=_sys.stderr)
+                else:
+                    # Do the best job possible w/o a huge amt. of code to
+                    # approx. a traceback stack trace
+                    exc_type, exc_value, exc_tb = self.__exc_info()
+                    try:
+                        print>>self.__stderr, (
+                            "Exception in thread " + self.getName() +
+                            " (most likely raised during interpreter shutdown):")
+                        print>>self.__stderr, (
+                            "Traceback (most recent call last):")
+                        while exc_tb:
+                            print>>self.__stderr, (
+                                '  File "%s", line %s, in %s' %
+                                (exc_tb.tb_frame.f_code.co_filename,
+                                    exc_tb.tb_lineno,
+                                    exc_tb.tb_frame.f_code.co_name))
+                            exc_tb = exc_tb.tb_next
+                        print>>self.__stderr, ("%s: %s" % (exc_type, exc_value))
+                    # Make sure that exc_tb gets deleted since it is a memory
+                    # hog; deleting everything else is just for thoroughness
+                    finally:
+                        del exc_type, exc_value, exc_tb
+
+        finally:
+            self.__stop()
+            try:
+                self.__delete()
+            except:
+                pass
+
+    def __stop(self):
+        pass
+
+    def __delete(self):
+        _unregister_thread(self._thread)
+
+
+class _MainThread(Thread):
+    def __init__(self):
+        Thread.__init__(self, name="MainThread")
+        import atexit
+        atexit.register(self.__exitfunc)
+
+    def _create_thread(self):
+        return java.lang.Thread.currentThread()
+
+    def _set_daemon(self):
+        return False
+
+    def __exitfunc(self):
+        _unregister_thread(self._thread)
+        t = _pickSomeNonDaemonThread()
+        while t:
+            t.join()
+            t = _pickSomeNonDaemonThread()
+
+def _pickSomeNonDaemonThread():
+    for t in enumerate():
+        if not t.isDaemon() and t.isAlive():
+            return t
+    return None
+
+def currentThread():
+    jthread = java.lang.Thread.currentThread()
+    pythread = _jthread_to_pythread[jthread]
+    if pythread is None:
+        pythread = JavaThread(jthread)
+    return pythread
+
+current_thread = currentThread
+
+def activeCount():
+    return len(_threads)
+
+active_count = activeCount
+
+def enumerate():
+    return _threads.values()
+
+from thread import stack_size
+
+
+_MainThread()
+
+
+######################################################################
+# pure Python code from CPythonLib/threading.py
+
+# The timer class was contributed by Itamar Shtull-Trauring
+
+def Timer(*args, **kwargs):
+    return _Timer(*args, **kwargs)
+
+class _Timer(Thread):
+    """Call a function after a specified number of seconds:
+
+    t = Timer(30.0, f, args=[], kwargs={})
+    t.start()
+    t.cancel() # stop the timer's action if it's still waiting
+    """
+
+    def __init__(self, interval, function, args=[], kwargs={}):
+        Thread.__init__(self)
+        self.interval = interval
+        self.function = function
+        self.args = args
+        self.kwargs = kwargs
+        self.finished = Event()
+
+    def cancel(self):
+        """Stop the timer if it hasn't finished yet"""
+        self.finished.set()
+
+    def run(self):
+        self.finished.wait(self.interval)
+        if not self.finished.isSet():
+            self.function(*self.args, **self.kwargs)
+        self.finished.set()
+
+
+# NOT USED except by BoundedSemaphore
+class _Semaphore(_Verbose):
+
+    # After Tim Peters' semaphore class, but not quite the same (no maximum)
+
+    def __init__(self, value=1, verbose=None):
+        assert value >= 0, "Semaphore initial value must be >= 0"
+        _Verbose.__init__(self, verbose)
+        self.__cond = Condition(Lock())
+        self.__value = value
+
+    def acquire(self, blocking=1):
+        rc = False
+        self.__cond.acquire()
+        while self.__value == 0:
+            if not blocking:
+                break
+            if __debug__:
+                self._note("%s.acquire(%s): blocked waiting, value=%s",
+                           self, blocking, self.__value)
+            self.__cond.wait()
+        else:
+            self.__value = self.__value - 1
+            if __debug__:
+                self._note("%s.acquire: success, value=%s",
+                           self, self.__value)
+            rc = True
+        self.__cond.release()
+        return rc
+
+    def release(self):
+        self.__cond.acquire()
+        self.__value = self.__value + 1
+        if __debug__:
+            self._note("%s.release: success, value=%s",
+                       self, self.__value)
+        self.__cond.notify()
+        self.__cond.release()
+
+
+def BoundedSemaphore(*args, **kwargs):
+    return _BoundedSemaphore(*args, **kwargs)
+
+class _BoundedSemaphore(_Semaphore):
+    """Semaphore that checks that # releases is <= # acquires"""
+    def __init__(self, value=1, verbose=None):
+        _Semaphore.__init__(self, value, verbose)
+        self._initial_value = value
+
+    def __enter__(self):
+        self.acquire()
+        return self
+
+    def release(self):
+        if self._Semaphore__value >= self._initial_value:
+            raise ValueError, "Semaphore released too many times"
+        return _Semaphore.release(self)
+
+    def __exit__(self, t, v, tb):
+        self.release()
+
+
+def Event(*args, **kwargs):
+    return _Event(*args, **kwargs)
+
+class _Event(_Verbose):
+
+    # After Tim Peters' event class (without is_posted())
+
+    def __init__(self, verbose=None):
+        _Verbose.__init__(self, verbose)
+        self.__cond = Condition(Lock())
+        self.__flag = False
+
+    def isSet(self):
+        return self.__flag
+
+    is_set = isSet
+
+    def set(self):
+        self.__cond.acquire()
+        try:
+            self.__flag = True
+            self.__cond.notifyAll()
+        finally:
+            self.__cond.release()
+
+    def clear(self):
+        self.__cond.acquire()
+        try:
+            self.__flag = False
+        finally:
+            self.__cond.release()
+
+    def wait(self, timeout=None):
+        self.__cond.acquire()
+        try:
+            if not self.__flag:
+                self.__cond.wait(timeout)
+            # Issue 2005: Since CPython 2.7, threading.Event.wait(timeout) returns boolean.
+            # The function should return False if timeout is reached before the event is set.
+            return self.__flag
+        finally:
+            self.__cond.release()
diff --git a/src/main/resources/PythonLibs/timeit.py b/src/main/resources/PythonLibs/timeit.py
new file mode 100644
index 0000000000000000000000000000000000000000..3725282ac6106e43116605bb630096c5e360cee7
--- /dev/null
+++ b/src/main/resources/PythonLibs/timeit.py
@@ -0,0 +1,331 @@
+#! /usr/bin/env python
+
+"""Tool for measuring execution time of small code snippets.
+
+This module avoids a number of common traps for measuring execution
+times.  See also Tim Peters' introduction to the Algorithms chapter in
+the Python Cookbook, published by O'Reilly.
+
+Library usage: see the Timer class.
+
+Command line usage:
+    python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [--] [statement]
+
+Options:
+  -n/--number N: how many times to execute 'statement' (default: see below)
+  -r/--repeat N: how many times to repeat the timer (default 3)
+  -s/--setup S: statement to be executed once initially (default 'pass')
+  -t/--time: use time.time() (default on Unix)
+  -c/--clock: use time.clock() (default on Windows)
+  -v/--verbose: print raw timing results; repeat for more digits precision
+  -h/--help: print this usage message and exit
+  --: separate options from statement, use when statement starts with -
+  statement: statement to be timed (default 'pass')
+
+A multi-line statement may be given by specifying each line as a
+separate argument; indented lines are possible by enclosing an
+argument in quotes and using leading spaces.  Multiple -s options are
+treated similarly.
+
+If -n is not given, a suitable number of loops is calculated by trying
+successive powers of 10 until the total time is at least 0.2 seconds.
+
+The difference in default timer function is because on Windows,
+clock() has microsecond granularity but time()'s granularity is 1/60th
+of a second; on Unix, clock() has 1/100th of a second granularity and
+time() is much more precise.  On either platform, the default timer
+functions measure wall clock time, not the CPU time.  This means that
+other processes running on the same computer may interfere with the
+timing.  The best thing to do when accurate timing is necessary is to
+repeat the timing a few times and use the best time.  The -r option is
+good for this; the default of 3 repetitions is probably enough in most
+cases.  On Unix, you can use clock() to measure CPU time.
+
+Note: there is a certain baseline overhead associated with executing a
+pass statement.  The code here doesn't try to hide it, but you should
+be aware of it.  The baseline overhead can be measured by invoking the
+program without arguments.
+
+The baseline overhead differs between Python versions!  Also, to
+fairly compare older Python versions to Python 2.3, you may want to
+use python -O for the older versions to avoid timing SET_LINENO
+instructions.
+"""
+
+import gc
+import sys
+import time
+try:
+    import itertools
+except ImportError:
+    # Must be an older Python version (see timeit() below)
+    itertools = None
+
+__all__ = ["Timer"]
+
+dummy_src_name = "<timeit-src>"
+default_number = 1000000
+default_repeat = 3
+
+if sys.platform == "win32":
+    # On Windows, the best timer is time.clock()
+    default_timer = time.clock
+else:
+    # On most other platforms the best timer is time.time()
+    default_timer = time.time
+
+# Don't change the indentation of the template; the reindent() calls
+# in Timer.__init__() depend on setup being indented 4 spaces and stmt
+# being indented 8 spaces.
+template = """
+def inner(_it, _timer):
+    %(setup)s
+    _t0 = _timer()
+    for _i in _it:
+        %(stmt)s
+    _t1 = _timer()
+    return _t1 - _t0
+"""
+
+def reindent(src, indent):
+    """Helper to reindent a multi-line statement."""
+    return src.replace("\n", "\n" + " "*indent)
+
+def _template_func(setup, func):
+    """Create a timer function. Used if the "statement" is a callable."""
+    def inner(_it, _timer, _func=func):
+        setup()
+        _t0 = _timer()
+        for _i in _it:
+            _func()
+        _t1 = _timer()
+        return _t1 - _t0
+    return inner
+
+class Timer:
+    """Class for timing execution speed of small code snippets.
+
+    The constructor takes a statement to be timed, an additional
+    statement used for setup, and a timer function.  Both statements
+    default to 'pass'; the timer function is platform-dependent (see
+    module doc string).
+
+    To measure the execution time of the first statement, use the
+    timeit() method.  The repeat() method is a convenience to call
+    timeit() multiple times and return a list of results.
+
+    The statements may contain newlines, as long as they don't contain
+    multi-line string literals.
+    """
+
+    def __init__(self, stmt="pass", setup="pass", timer=default_timer):
+        """Constructor.  See class doc string."""
+        self.timer = timer
+        ns = {}
+        if isinstance(stmt, basestring):
+            stmt = reindent(stmt, 8)
+            if isinstance(setup, basestring):
+                setup = reindent(setup, 4)
+                src = template % {'stmt': stmt, 'setup': setup}
+            elif hasattr(setup, '__call__'):
+                src = template % {'stmt': stmt, 'setup': '_setup()'}
+                ns['_setup'] = setup
+            else:
+                raise ValueError("setup is neither a string nor callable")
+            self.src = src # Save for traceback display
+            code = compile(src, dummy_src_name, "exec")
+            exec code in globals(), ns
+            self.inner = ns["inner"]
+        elif hasattr(stmt, '__call__'):
+            self.src = None
+            if isinstance(setup, basestring):
+                _setup = setup
+                def setup():
+                    exec _setup in globals(), ns
+            elif not hasattr(setup, '__call__'):
+                raise ValueError("setup is neither a string nor callable")
+            self.inner = _template_func(setup, stmt)
+        else:
+            raise ValueError("stmt is neither a string nor callable")
+
+    def print_exc(self, file=None):
+        """Helper to print a traceback from the timed code.
+
+        Typical use:
+
+            t = Timer(...)       # outside the try/except
+            try:
+                t.timeit(...)    # or t.repeat(...)
+            except:
+                t.print_exc()
+
+        The advantage over the standard traceback is that source lines
+        in the compiled template will be displayed.
+
+        The optional file argument directs where the traceback is
+        sent; it defaults to sys.stderr.
+        """
+        import linecache, traceback
+        if self.src is not None:
+            linecache.cache[dummy_src_name] = (len(self.src),
+                                               None,
+                                               self.src.split("\n"),
+                                               dummy_src_name)
+        # else the source is already stored somewhere else
+
+        traceback.print_exc(file=file)
+
+    def timeit(self, number=default_number):
+        """Time 'number' executions of the main statement.
+
+        To be precise, this executes the setup statement once, and
+        then returns the time it takes to execute the main statement
+        a number of times, as a float measured in seconds.  The
+        argument is the number of times through the loop, defaulting
+        to one million.  The main statement, the setup statement and
+        the timer function to be used are passed to the constructor.
+        """
+        if itertools:
+            it = itertools.repeat(None, number)
+        else:
+            it = [None] * number
+        gcold = gc.isenabled()
+        try:
+            gc.disable()
+        except NotImplementedError:
+            pass # ignore on platforms like Jython
+        timing = self.inner(it, self.timer)
+        if gcold:
+            gc.enable()
+        return timing
+
+    def repeat(self, repeat=default_repeat, number=default_number):
+        """Call timeit() a few times.
+
+        This is a convenience function that calls the timeit()
+        repeatedly, returning a list of results.  The first argument
+        specifies how many times to call timeit(), defaulting to 3;
+        the second argument specifies the timer argument, defaulting
+        to one million.
+
+        Note: it's tempting to calculate mean and standard deviation
+        from the result vector and report these.  However, this is not
+        very useful.  In a typical case, the lowest value gives a
+        lower bound for how fast your machine can run the given code
+        snippet; higher values in the result vector are typically not
+        caused by variability in Python's speed, but by other
+        processes interfering with your timing accuracy.  So the min()
+        of the result is probably the only number you should be
+        interested in.  After that, you should look at the entire
+        vector and apply common sense rather than statistics.
+        """
+        r = []
+        for i in range(repeat):
+            t = self.timeit(number)
+            r.append(t)
+        return r
+
+def timeit(stmt="pass", setup="pass", timer=default_timer,
+           number=default_number):
+    """Convenience function to create Timer object and call timeit method."""
+    return Timer(stmt, setup, timer).timeit(number)
+
+def repeat(stmt="pass", setup="pass", timer=default_timer,
+           repeat=default_repeat, number=default_number):
+    """Convenience function to create Timer object and call repeat method."""
+    return Timer(stmt, setup, timer).repeat(repeat, number)
+
+def main(args=None):
+    """Main program, used when run as a script.
+
+    The optional argument specifies the command line to be parsed,
+    defaulting to sys.argv[1:].
+
+    The return value is an exit code to be passed to sys.exit(); it
+    may be None to indicate success.
+
+    When an exception happens during timing, a traceback is printed to
+    stderr and the return value is 1.  Exceptions at other times
+    (including the template compilation) are not caught.
+    """
+    if args is None:
+        args = sys.argv[1:]
+    import getopt
+    try:
+        opts, args = getopt.getopt(args, "n:s:r:tcvh",
+                                   ["number=", "setup=", "repeat=",
+                                    "time", "clock", "verbose", "help"])
+    except getopt.error, err:
+        print err
+        print "use -h/--help for command line help"
+        return 2
+    timer = default_timer
+    stmt = "\n".join(args) or "pass"
+    number = 0 # auto-determine
+    setup = []
+    repeat = default_repeat
+    verbose = 0
+    precision = 3
+    for o, a in opts:
+        if o in ("-n", "--number"):
+            number = int(a)
+        if o in ("-s", "--setup"):
+            setup.append(a)
+        if o in ("-r", "--repeat"):
+            repeat = int(a)
+            if repeat <= 0:
+                repeat = 1
+        if o in ("-t", "--time"):
+            timer = time.time
+        if o in ("-c", "--clock"):
+            timer = time.clock
+        if o in ("-v", "--verbose"):
+            if verbose:
+                precision += 1
+            verbose += 1
+        if o in ("-h", "--help"):
+            print __doc__,
+            return 0
+    setup = "\n".join(setup) or "pass"
+    # Include the current directory, so that local imports work (sys.path
+    # contains the directory of this script, rather than the current
+    # directory)
+    import os
+    sys.path.insert(0, os.curdir)
+    t = Timer(stmt, setup, timer)
+    if number == 0:
+        # determine number so that 0.2 <= total time < 2.0
+        for i in range(1, 10):
+            number = 10**i
+            try:
+                x = t.timeit(number)
+            except:
+                t.print_exc()
+                return 1
+            if verbose:
+                print "%d loops -> %.*g secs" % (number, precision, x)
+            if x >= 0.2:
+                break
+    try:
+        r = t.repeat(repeat, number)
+    except:
+        t.print_exc()
+        return 1
+    best = min(r)
+    if verbose:
+        print "raw times:", " ".join(["%.*g" % (precision, x) for x in r])
+    print "%d loops," % number,
+    usec = best * 1e6 / number
+    if usec < 1000:
+        print "best of %d: %.*g usec per loop" % (repeat, precision, usec)
+    else:
+        msec = usec / 1000
+        if msec < 1000:
+            print "best of %d: %.*g msec per loop" % (repeat, precision, msec)
+        else:
+            sec = msec / 1000
+            print "best of %d: %.*g sec per loop" % (repeat, precision, sec)
+    return None
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/src/main/resources/PythonLibs/token.py b/src/main/resources/PythonLibs/token.py
new file mode 100644
index 0000000000000000000000000000000000000000..34abf62016ac9ca377dd9c2313eda62b6c0f3d42
--- /dev/null
+++ b/src/main/resources/PythonLibs/token.py
@@ -0,0 +1,142 @@
+#! /usr/bin/env python
+
+"""Token constants (from "token.h")."""
+
+#  This file is automatically generated; please don't muck it up!
+#
+#  To update the symbols in this file, 'cd' to the top directory of
+#  the python source tree after building the interpreter and run:
+#
+#    ./python Lib/token.py
+
+#--start constants--
+ENDMARKER = 0
+NAME = 1
+NUMBER = 2
+STRING = 3
+NEWLINE = 4
+INDENT = 5
+DEDENT = 6
+LPAR = 7
+RPAR = 8
+LSQB = 9
+RSQB = 10
+COLON = 11
+COMMA = 12
+SEMI = 13
+PLUS = 14
+MINUS = 15
+STAR = 16
+SLASH = 17
+VBAR = 18
+AMPER = 19
+LESS = 20
+GREATER = 21
+EQUAL = 22
+DOT = 23
+PERCENT = 24
+BACKQUOTE = 25
+LBRACE = 26
+RBRACE = 27
+EQEQUAL = 28
+NOTEQUAL = 29
+LESSEQUAL = 30
+GREATEREQUAL = 31
+TILDE = 32
+CIRCUMFLEX = 33
+LEFTSHIFT = 34
+RIGHTSHIFT = 35
+DOUBLESTAR = 36
+PLUSEQUAL = 37
+MINEQUAL = 38
+STAREQUAL = 39
+SLASHEQUAL = 40
+PERCENTEQUAL = 41
+AMPEREQUAL = 42
+VBAREQUAL = 43
+CIRCUMFLEXEQUAL = 44
+LEFTSHIFTEQUAL = 45
+RIGHTSHIFTEQUAL = 46
+DOUBLESTAREQUAL = 47
+DOUBLESLASH = 48
+DOUBLESLASHEQUAL = 49
+AT = 50
+OP = 51
+ERRORTOKEN = 52
+N_TOKENS = 53
+NT_OFFSET = 256
+#--end constants--
+
+tok_name = {}
+for _name, _value in globals().items():
+    if type(_value) is type(0):
+        tok_name[_value] = _name
+del _name, _value
+
+
+def ISTERMINAL(x):
+    return x < NT_OFFSET
+
+def ISNONTERMINAL(x):
+    return x >= NT_OFFSET
+
+def ISEOF(x):
+    return x == ENDMARKER
+
+
+def main():
+    import re
+    import sys
+    args = sys.argv[1:]
+    inFileName = args and args[0] or "Include/token.h"
+    outFileName = "Lib/token.py"
+    if len(args) > 1:
+        outFileName = args[1]
+    try:
+        fp = open(inFileName)
+    except IOError, err:
+        sys.stdout.write("I/O error: %s\n" % str(err))
+        sys.exit(1)
+    lines = fp.read().split("\n")
+    fp.close()
+    prog = re.compile(
+        "#define[ \t][ \t]*([A-Z0-9][A-Z0-9_]*)[ \t][ \t]*([0-9][0-9]*)",
+        re.IGNORECASE)
+    tokens = {}
+    for line in lines:
+        match = prog.match(line)
+        if match:
+            name, val = match.group(1, 2)
+            val = int(val)
+            tokens[val] = name          # reverse so we can sort them...
+    keys = tokens.keys()
+    keys.sort()
+    # load the output skeleton from the target:
+    try:
+        fp = open(outFileName)
+    except IOError, err:
+        sys.stderr.write("I/O error: %s\n" % str(err))
+        sys.exit(2)
+    format = fp.read().split("\n")
+    fp.close()
+    try:
+        start = format.index("#--start constants--") + 1
+        end = format.index("#--end constants--")
+    except ValueError:
+        sys.stderr.write("target does not contain format markers")
+        sys.exit(3)
+    lines = []
+    for val in keys:
+        lines.append("%s = %d" % (tokens[val], val))
+    format[start:end] = lines
+    try:
+        fp = open(outFileName, 'w')
+    except IOError, err:
+        sys.stderr.write("I/O error: %s\n" % str(err))
+        sys.exit(4)
+    fp.write("\n".join(format))
+    fp.close()
+
+
+if __name__ == "__main__":
+    main()
diff --git a/src/main/resources/PythonLibs/tokenize.py b/src/main/resources/PythonLibs/tokenize.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca7b07493cfe0b30979b172f225bee8b5a814e33
--- /dev/null
+++ b/src/main/resources/PythonLibs/tokenize.py
@@ -0,0 +1,426 @@
+"""Tokenization help for Python programs.
+
+generate_tokens(readline) is a generator that breaks a stream of
+text into Python tokens.  It accepts a readline-like method which is called
+repeatedly to get the next line of input (or "" for EOF).  It generates
+5-tuples with these members:
+
+    the token type (see token.py)
+    the token (a string)
+    the starting (row, column) indices of the token (a 2-tuple of ints)
+    the ending (row, column) indices of the token (a 2-tuple of ints)
+    the original line (string)
+
+It is designed to match the working of the Python tokenizer exactly, except
+that it produces COMMENT tokens for comments and gives type OP for all
+operators
+
+Older entry points
+    tokenize_loop(readline, tokeneater)
+    tokenize(readline, tokeneater=printtoken)
+are the same, except instead of generating tokens, tokeneater is a callback
+function to which the 5 fields described above are passed as 5 arguments,
+each time a new token is found."""
+
+__author__ = 'Ka-Ping Yee <ping@lfw.org>'
+__credits__ = ('GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, '
+               'Skip Montanaro, Raymond Hettinger')
+
+import string, re
+from token import *
+
+import token
+__all__ = [x for x in dir(token) if not x.startswith("_")]
+__all__ += ["COMMENT", "tokenize", "generate_tokens", "NL", "untokenize"]
+del x
+del token
+
+COMMENT = N_TOKENS
+tok_name[COMMENT] = 'COMMENT'
+NL = N_TOKENS + 1
+tok_name[NL] = 'NL'
+N_TOKENS += 2
+
+def group(*choices): return '(' + '|'.join(choices) + ')'
+def any(*choices): return group(*choices) + '*'
+def maybe(*choices): return group(*choices) + '?'
+
+Whitespace = r'[ \f\t]*'
+Comment = r'#[^\r\n]*'
+Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
+Name = r'[a-zA-Z_]\w*'
+
+Hexnumber = r'0[xX][\da-fA-F]+[lL]?'
+Octnumber = r'(0[oO][0-7]+)|(0[0-7]*)[lL]?'
+Binnumber = r'0[bB][01]+[lL]?'
+Decnumber = r'[1-9]\d*[lL]?'
+Intnumber = group(Hexnumber, Binnumber, Octnumber, Decnumber)
+Exponent = r'[eE][-+]?\d+'
+Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
+Expfloat = r'\d+' + Exponent
+Floatnumber = group(Pointfloat, Expfloat)
+Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]')
+Number = group(Imagnumber, Floatnumber, Intnumber)
+
+# Tail end of ' string.
+Single = r"[^'\\]*(?:\\.[^'\\]*)*'"
+# Tail end of " string.
+Double = r'[^"\\]*(?:\\.[^"\\]*)*"'
+# Tail end of ''' string.
+Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''"
+# Tail end of """ string.
+Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
+Triple = group("[uUbB]?[rR]?'''", '[uUbB]?[rR]?"""')
+# Single-line ' or " string.
+String = group(r"[uUbB]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*'",
+               r'[uUbB]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*"')
+
+# Because of leftmost-then-longest match semantics, be sure to put the
+# longest operators first (e.g., if = came before ==, == would get
+# recognized as two instances of =).
+Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"<>", r"!=",
+                 r"//=?",
+                 r"[+\-*/%&|^=<>]=?",
+                 r"~")
+
+Bracket = '[][(){}]'
+Special = group(r'\r?\n', r'[:;.,`@]')
+Funny = group(Operator, Bracket, Special)
+
+PlainToken = group(Number, Funny, String, Name)
+Token = Ignore + PlainToken
+
+# First (or only) line of ' or " string.
+ContStr = group(r"[uUbB]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*" +
+                group("'", r'\\\r?\n'),
+                r'[uUbB]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*' +
+                group('"', r'\\\r?\n'))
+PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple)
+PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name)
+
+tokenprog, pseudoprog, single3prog, double3prog = map(
+    re.compile, (Token, PseudoToken, Single3, Double3))
+endprogs = {"'": re.compile(Single), '"': re.compile(Double),
+            "'''": single3prog, '"""': double3prog,
+            "r'''": single3prog, 'r"""': double3prog,
+            "u'''": single3prog, 'u"""': double3prog,
+            "ur'''": single3prog, 'ur"""': double3prog,
+            "R'''": single3prog, 'R"""': double3prog,
+            "U'''": single3prog, 'U"""': double3prog,
+            "uR'''": single3prog, 'uR"""': double3prog,
+            "Ur'''": single3prog, 'Ur"""': double3prog,
+            "UR'''": single3prog, 'UR"""': double3prog,
+            "b'''": single3prog, 'b"""': double3prog,
+            "br'''": single3prog, 'br"""': double3prog,
+            "B'''": single3prog, 'B"""': double3prog,
+            "bR'''": single3prog, 'bR"""': double3prog,
+            "Br'''": single3prog, 'Br"""': double3prog,
+            "BR'''": single3prog, 'BR"""': double3prog,
+            'r': None, 'R': None, 'u': None, 'U': None,
+            'b': None, 'B': None}
+
+triple_quoted = {}
+for t in ("'''", '"""',
+          "r'''", 'r"""', "R'''", 'R"""',
+          "u'''", 'u"""', "U'''", 'U"""',
+          "ur'''", 'ur"""', "Ur'''", 'Ur"""',
+          "uR'''", 'uR"""', "UR'''", 'UR"""',
+          "b'''", 'b"""', "B'''", 'B"""',
+          "br'''", 'br"""', "Br'''", 'Br"""',
+          "bR'''", 'bR"""', "BR'''", 'BR"""'):
+    triple_quoted[t] = t
+single_quoted = {}
+for t in ("'", '"',
+          "r'", 'r"', "R'", 'R"',
+          "u'", 'u"', "U'", 'U"',
+          "ur'", 'ur"', "Ur'", 'Ur"',
+          "uR'", 'uR"', "UR'", 'UR"',
+          "b'", 'b"', "B'", 'B"',
+          "br'", 'br"', "Br'", 'Br"',
+          "bR'", 'bR"', "BR'", 'BR"' ):
+    single_quoted[t] = t
+
+tabsize = 8
+
+class TokenError(Exception): pass
+
+class StopTokenizing(Exception): pass
+
+def printtoken(type, token, srow_scol, erow_ecol, line): # for testing
+    srow, scol = srow_scol
+    erow, ecol = erow_ecol
+    print "%d,%d-%d,%d:\t%s\t%s" % \
+        (srow, scol, erow, ecol, tok_name[type], repr(token))
+
+def tokenize(readline, tokeneater=printtoken):
+    """
+    The tokenize() function accepts two parameters: one representing the
+    input stream, and one providing an output mechanism for tokenize().
+
+    The first parameter, readline, must be a callable object which provides
+    the same interface as the readline() method of built-in file objects.
+    Each call to the function should return one line of input as a string.
+
+    The second parameter, tokeneater, must also be a callable object. It is
+    called once for each token, with five arguments, corresponding to the
+    tuples generated by generate_tokens().
+    """
+    try:
+        tokenize_loop(readline, tokeneater)
+    except StopTokenizing:
+        pass
+
+# backwards compatible interface
+def tokenize_loop(readline, tokeneater):
+    for token_info in generate_tokens(readline):
+        tokeneater(*token_info)
+
+class Untokenizer:
+
+    def __init__(self):
+        self.tokens = []
+        self.prev_row = 1
+        self.prev_col = 0
+
+    def add_whitespace(self, start):
+        row, col = start
+        assert row <= self.prev_row
+        col_offset = col - self.prev_col
+        if col_offset:
+            self.tokens.append(" " * col_offset)
+
+    def untokenize(self, iterable):
+        for t in iterable:
+            if len(t) == 2:
+                self.compat(t, iterable)
+                break
+            tok_type, token, start, end, line = t
+            self.add_whitespace(start)
+            self.tokens.append(token)
+            self.prev_row, self.prev_col = end
+            if tok_type in (NEWLINE, NL):
+                self.prev_row += 1
+                self.prev_col = 0
+        return "".join(self.tokens)
+
+    def compat(self, token, iterable):
+        startline = False
+        indents = []
+        toks_append = self.tokens.append
+        toknum, tokval = token
+        if toknum in (NAME, NUMBER):
+            tokval += ' '
+        if toknum in (NEWLINE, NL):
+            startline = True
+        prevstring = False
+        for tok in iterable:
+            toknum, tokval = tok[:2]
+
+            if toknum in (NAME, NUMBER):
+                tokval += ' '
+
+            # Insert a space between two consecutive strings
+            if toknum == STRING:
+                if prevstring:
+                    tokval = ' ' + tokval
+                prevstring = True
+            else:
+                prevstring = False
+
+            if toknum == INDENT:
+                indents.append(tokval)
+                continue
+            elif toknum == DEDENT:
+                indents.pop()
+                continue
+            elif toknum in (NEWLINE, NL):
+                startline = True
+            elif startline and indents:
+                toks_append(indents[-1])
+                startline = False
+            toks_append(tokval)
+
+def untokenize(iterable):
+    """Transform tokens back into Python source code.
+
+    Each element returned by the iterable must be a token sequence
+    with at least two elements, a token number and token value.  If
+    only two tokens are passed, the resulting output is poor.
+
+    Round-trip invariant for full input:
+        Untokenized source will match input source exactly
+
+    Round-trip invariant for limited intput:
+        # Output text will tokenize the back to the input
+        t1 = [tok[:2] for tok in generate_tokens(f.readline)]
+        newcode = untokenize(t1)
+        readline = iter(newcode.splitlines(1)).next
+        t2 = [tok[:2] for tok in generate_tokens(readline)]
+        assert t1 == t2
+    """
+    ut = Untokenizer()
+    return ut.untokenize(iterable)
+
+def generate_tokens(readline):
+    """
+    The generate_tokens() generator requires one argment, readline, which
+    must be a callable object which provides the same interface as the
+    readline() method of built-in file objects. Each call to the function
+    should return one line of input as a string.  Alternately, readline
+    can be a callable function terminating with StopIteration:
+        readline = open(myfile).next    # Example of alternate readline
+
+    The generator produces 5-tuples with these members: the token type; the
+    token string; a 2-tuple (srow, scol) of ints specifying the row and
+    column where the token begins in the source; a 2-tuple (erow, ecol) of
+    ints specifying the row and column where the token ends in the source;
+    and the line on which the token was found. The line passed is the
+    logical line; continuation lines are included.
+    """
+    lnum = parenlev = continued = 0
+    namechars, numchars = string.ascii_letters + '_', '0123456789'
+    contstr, needcont = '', 0
+    contline = None
+    indents = [0]
+
+    while 1:                                   # loop over lines in stream
+        try:
+            line = readline()
+        except StopIteration:
+            line = ''
+        lnum += 1
+        pos, max = 0, len(line)
+
+        if contstr:                            # continued string
+            if not line:
+                raise TokenError, ("EOF in multi-line string", strstart)
+            endmatch = endprog.match(line)
+            if endmatch:
+                pos = end = endmatch.end(0)
+                yield (STRING, contstr + line[:end],
+                       strstart, (lnum, end), contline + line)
+                contstr, needcont = '', 0
+                contline = None
+            elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n':
+                yield (ERRORTOKEN, contstr + line,
+                           strstart, (lnum, len(line)), contline)
+                contstr = ''
+                contline = None
+                continue
+            else:
+                contstr = contstr + line
+                contline = contline + line
+                continue
+
+        elif parenlev == 0 and not continued:  # new statement
+            if not line: break
+            column = 0
+            while pos < max:                   # measure leading whitespace
+                if line[pos] == ' ':
+                    column += 1
+                elif line[pos] == '\t':
+                    column = (column//tabsize + 1)*tabsize
+                elif line[pos] == '\f':
+                    column = 0
+                else:
+                    break
+                pos += 1
+            if pos == max:
+                break
+
+            if line[pos] in '#\r\n':           # skip comments or blank lines
+                if line[pos] == '#':
+                    comment_token = line[pos:].rstrip('\r\n')
+                    nl_pos = pos + len(comment_token)
+                    yield (COMMENT, comment_token,
+                           (lnum, pos), (lnum, pos + len(comment_token)), line)
+                    yield (NL, line[nl_pos:],
+                           (lnum, nl_pos), (lnum, len(line)), line)
+                else:
+                    yield ((NL, COMMENT)[line[pos] == '#'], line[pos:],
+                           (lnum, pos), (lnum, len(line)), line)
+                continue
+
+            if column > indents[-1]:           # count indents or dedents
+                indents.append(column)
+                yield (INDENT, line[:pos], (lnum, 0), (lnum, pos), line)
+            while column < indents[-1]:
+                if column not in indents:
+                    raise IndentationError(
+                        "unindent does not match any outer indentation level",
+                        ("<tokenize>", lnum, pos, line))
+                indents = indents[:-1]
+                yield (DEDENT, '', (lnum, pos), (lnum, pos), line)
+
+        else:                                  # continued statement
+            if not line:
+                raise TokenError, ("EOF in multi-line statement", (lnum, 0))
+            continued = 0
+
+        while pos < max:
+            pseudomatch = pseudoprog.match(line, pos)
+            if pseudomatch:                                # scan for tokens
+                start, end = pseudomatch.span(1)
+                spos, epos, pos = (lnum, start), (lnum, end), end
+                if start == end:
+                    continue
+                token, initial = line[start:end], line[start]
+
+                if initial in numchars or \
+                   (initial == '.' and token != '.'):      # ordinary number
+                    yield (NUMBER, token, spos, epos, line)
+                elif initial in '\r\n':
+                    yield (NL if parenlev > 0 else NEWLINE,
+                           token, spos, epos, line)
+                elif initial == '#':
+                    assert not token.endswith("\n")
+                    yield (COMMENT, token, spos, epos, line)
+                elif token in triple_quoted:
+                    endprog = endprogs[token]
+                    endmatch = endprog.match(line, pos)
+                    if endmatch:                           # all on one line
+                        pos = endmatch.end(0)
+                        token = line[start:pos]
+                        yield (STRING, token, spos, (lnum, pos), line)
+                    else:
+                        strstart = (lnum, start)           # multiple lines
+                        contstr = line[start:]
+                        contline = line
+                        break
+                elif initial in single_quoted or \
+                    token[:2] in single_quoted or \
+                    token[:3] in single_quoted:
+                    if token[-1] == '\n':                  # continued string
+                        strstart = (lnum, start)
+                        endprog = (endprogs[initial] or endprogs[token[1]] or
+                                   endprogs[token[2]])
+                        contstr, needcont = line[start:], 1
+                        contline = line
+                        break
+                    else:                                  # ordinary string
+                        yield (STRING, token, spos, epos, line)
+                elif initial in namechars:                 # ordinary name
+                    yield (NAME, token, spos, epos, line)
+                elif initial == '\\':                      # continued stmt
+                    continued = 1
+                else:
+                    if initial in '([{':
+                        parenlev += 1
+                    elif initial in ')]}':
+                        parenlev -= 1
+                    yield (OP, token, spos, epos, line)
+            else:
+                yield (ERRORTOKEN, line[pos],
+                           (lnum, pos), (lnum, pos+1), line)
+                pos += 1
+
+    for indent in indents[1:]:                 # pop remaining indent levels
+        yield (DEDENT, '', (lnum, 0), (lnum, 0), '')
+    yield (ENDMARKER, '', (lnum, 0), (lnum, 0), '')
+
+if __name__ == '__main__':                     # testing
+    import sys
+    if len(sys.argv) > 1:
+        tokenize(open(sys.argv[1]).readline)
+    else:
+        tokenize(sys.stdin.readline)
diff --git a/src/main/resources/PythonLibs/trace.py b/src/main/resources/PythonLibs/trace.py
new file mode 100644
index 0000000000000000000000000000000000000000..38a13e2a9f0fa92ddcfec3c92022c355a3a4a943
--- /dev/null
+++ b/src/main/resources/PythonLibs/trace.py
@@ -0,0 +1,819 @@
+#!/usr/bin/env python
+
+# portions copyright 2001, Autonomous Zones Industries, Inc., all rights...
+# err...  reserved and offered to the public under the terms of the
+# Python 2.2 license.
+# Author: Zooko O'Whielacronx
+# http://zooko.com/
+# mailto:zooko@zooko.com
+#
+# Copyright 2000, Mojam Media, Inc., all rights reserved.
+# Author: Skip Montanaro
+#
+# Copyright 1999, Bioreason, Inc., all rights reserved.
+# Author: Andrew Dalke
+#
+# Copyright 1995-1997, Automatrix, Inc., all rights reserved.
+# Author: Skip Montanaro
+#
+# Copyright 1991-1995, Stichting Mathematisch Centrum, all rights reserved.
+#
+#
+# Permission to use, copy, modify, and distribute this Python software and
+# its associated documentation for any purpose without fee is hereby
+# granted, provided that the above copyright notice appears in all copies,
+# and that both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of neither Automatrix,
+# Bioreason or Mojam Media be used in advertising or publicity pertaining to
+# distribution of the software without specific, written prior permission.
+#
+"""program/module to trace Python program or function execution
+
+Sample use, command line:
+  trace.py -c -f counts --ignore-dir '$prefix' spam.py eggs
+  trace.py -t --ignore-dir '$prefix' spam.py eggs
+  trace.py --trackcalls spam.py eggs
+
+Sample use, programmatically
+  import sys
+
+  # create a Trace object, telling it what to ignore, and whether to
+  # do tracing or line-counting or both.
+  tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix,], trace=0,
+                    count=1)
+  # run the new command using the given tracer
+  tracer.run('main()')
+  # make a report, placing output in /tmp
+  r = tracer.results()
+  r.write_results(show_missing=True, coverdir="/tmp")
+"""
+
+import linecache
+import os
+import re
+import sys
+import time
+import token
+import tokenize
+import inspect
+import gc
+import dis
+try:
+    import cPickle
+    pickle = cPickle
+except ImportError:
+    import pickle
+
+try:
+    import threading
+except ImportError:
+    _settrace = sys.settrace
+
+    def _unsettrace():
+        sys.settrace(None)
+else:
+    def _settrace(func):
+        threading.settrace(func)
+        sys.settrace(func)
+
+    def _unsettrace():
+        sys.settrace(None)
+        threading.settrace(None)
+
+def usage(outfile):
+    outfile.write("""Usage: %s [OPTIONS] <file> [ARGS]
+
+Meta-options:
+--help                Display this help then exit.
+--version             Output version information then exit.
+
+Otherwise, exactly one of the following three options must be given:
+-t, --trace           Print each line to sys.stdout before it is executed.
+-c, --count           Count the number of times each line is executed
+                      and write the counts to <module>.cover for each
+                      module executed, in the module's directory.
+                      See also `--coverdir', `--file', `--no-report' below.
+-l, --listfuncs       Keep track of which functions are executed at least
+                      once and write the results to sys.stdout after the
+                      program exits.
+-T, --trackcalls      Keep track of caller/called pairs and write the
+                      results to sys.stdout after the program exits.
+-r, --report          Generate a report from a counts file; do not execute
+                      any code.  `--file' must specify the results file to
+                      read, which must have been created in a previous run
+                      with `--count --file=FILE'.
+
+Modifiers:
+-f, --file=<file>     File to accumulate counts over several runs.
+-R, --no-report       Do not generate the coverage report files.
+                      Useful if you want to accumulate over several runs.
+-C, --coverdir=<dir>  Directory where the report files.  The coverage
+                      report for <package>.<module> is written to file
+                      <dir>/<package>/<module>.cover.
+-m, --missing         Annotate executable lines that were not executed
+                      with '>>>>>> '.
+-s, --summary         Write a brief summary on stdout for each file.
+                      (Can only be used with --count or --report.)
+-g, --timing          Prefix each line with the time since the program started.
+                      Only used while tracing.
+
+Filters, may be repeated multiple times:
+--ignore-module=<mod> Ignore the given module(s) and its submodules
+                      (if it is a package).  Accepts comma separated
+                      list of module names
+--ignore-dir=<dir>    Ignore files in the given directory (multiple
+                      directories can be joined by os.pathsep).
+""" % sys.argv[0])
+
+PRAGMA_NOCOVER = "#pragma NO COVER"
+
+# Simple rx to find lines with no code.
+rx_blank = re.compile(r'^\s*(#.*)?$')
+
+class Ignore:
+    def __init__(self, modules = None, dirs = None):
+        self._mods = modules or []
+        self._dirs = dirs or []
+
+        self._dirs = map(os.path.normpath, self._dirs)
+        self._ignore = { '<string>': 1 }
+
+    def names(self, filename, modulename):
+        if modulename in self._ignore:
+            return self._ignore[modulename]
+
+        # haven't seen this one before, so see if the module name is
+        # on the ignore list.  Need to take some care since ignoring
+        # "cmp" musn't mean ignoring "cmpcache" but ignoring
+        # "Spam" must also mean ignoring "Spam.Eggs".
+        for mod in self._mods:
+            if mod == modulename:  # Identical names, so ignore
+                self._ignore[modulename] = 1
+                return 1
+            # check if the module is a proper submodule of something on
+            # the ignore list
+            n = len(mod)
+            # (will not overflow since if the first n characters are the
+            # same and the name has not already occurred, then the size
+            # of "name" is greater than that of "mod")
+            if mod == modulename[:n] and modulename[n] == '.':
+                self._ignore[modulename] = 1
+                return 1
+
+        # Now check that __file__ isn't in one of the directories
+        if filename is None:
+            # must be a built-in, so we must ignore
+            self._ignore[modulename] = 1
+            return 1
+
+        # Ignore a file when it contains one of the ignorable paths
+        for d in self._dirs:
+            # The '+ os.sep' is to ensure that d is a parent directory,
+            # as compared to cases like:
+            #  d = "/usr/local"
+            #  filename = "/usr/local.py"
+            # or
+            #  d = "/usr/local.py"
+            #  filename = "/usr/local.py"
+            if filename.startswith(d + os.sep):
+                self._ignore[modulename] = 1
+                return 1
+
+        # Tried the different ways, so we don't ignore this module
+        self._ignore[modulename] = 0
+        return 0
+
+def modname(path):
+    """Return a plausible module name for the patch."""
+
+    base = os.path.basename(path)
+    filename, ext = os.path.splitext(base)
+    return filename
+
+def fullmodname(path):
+    """Return a plausible module name for the path."""
+
+    # If the file 'path' is part of a package, then the filename isn't
+    # enough to uniquely identify it.  Try to do the right thing by
+    # looking in sys.path for the longest matching prefix.  We'll
+    # assume that the rest is the package name.
+
+    comparepath = os.path.normcase(path)
+    longest = ""
+    for dir in sys.path:
+        dir = os.path.normcase(dir)
+        if comparepath.startswith(dir) and comparepath[len(dir)] == os.sep:
+            if len(dir) > len(longest):
+                longest = dir
+
+    if longest:
+        base = path[len(longest) + 1:]
+    else:
+        base = path
+    # the drive letter is never part of the module name
+    drive, base = os.path.splitdrive(base)
+    base = base.replace(os.sep, ".")
+    if os.altsep:
+        base = base.replace(os.altsep, ".")
+    filename, ext = os.path.splitext(base)
+    return filename.lstrip(".")
+
+class CoverageResults:
+    def __init__(self, counts=None, calledfuncs=None, infile=None,
+                 callers=None, outfile=None):
+        self.counts = counts
+        if self.counts is None:
+            self.counts = {}
+        self.counter = self.counts.copy() # map (filename, lineno) to count
+        self.calledfuncs = calledfuncs
+        if self.calledfuncs is None:
+            self.calledfuncs = {}
+        self.calledfuncs = self.calledfuncs.copy()
+        self.callers = callers
+        if self.callers is None:
+            self.callers = {}
+        self.callers = self.callers.copy()
+        self.infile = infile
+        self.outfile = outfile
+        if self.infile:
+            # Try to merge existing counts file.
+            try:
+                counts, calledfuncs, callers = \
+                        pickle.load(open(self.infile, 'rb'))
+                self.update(self.__class__(counts, calledfuncs, callers))
+            except (IOError, EOFError, ValueError), err:
+                print >> sys.stderr, ("Skipping counts file %r: %s"
+                                      % (self.infile, err))
+
+    def update(self, other):
+        """Merge in the data from another CoverageResults"""
+        counts = self.counts
+        calledfuncs = self.calledfuncs
+        callers = self.callers
+        other_counts = other.counts
+        other_calledfuncs = other.calledfuncs
+        other_callers = other.callers
+
+        for key in other_counts.keys():
+            counts[key] = counts.get(key, 0) + other_counts[key]
+
+        for key in other_calledfuncs.keys():
+            calledfuncs[key] = 1
+
+        for key in other_callers.keys():
+            callers[key] = 1
+
+    def write_results(self, show_missing=True, summary=False, coverdir=None):
+        """
+        @param coverdir
+        """
+        if self.calledfuncs:
+            print
+            print "functions called:"
+            calls = self.calledfuncs.keys()
+            calls.sort()
+            for filename, modulename, funcname in calls:
+                print ("filename: %s, modulename: %s, funcname: %s"
+                       % (filename, modulename, funcname))
+
+        if self.callers:
+            print
+            print "calling relationships:"
+            calls = self.callers.keys()
+            calls.sort()
+            lastfile = lastcfile = ""
+            for ((pfile, pmod, pfunc), (cfile, cmod, cfunc)) in calls:
+                if pfile != lastfile:
+                    print
+                    print "***", pfile, "***"
+                    lastfile = pfile
+                    lastcfile = ""
+                if cfile != pfile and lastcfile != cfile:
+                    print "  -->", cfile
+                    lastcfile = cfile
+                print "    %s.%s -> %s.%s" % (pmod, pfunc, cmod, cfunc)
+
+        # turn the counts data ("(filename, lineno) = count") into something
+        # accessible on a per-file basis
+        per_file = {}
+        for filename, lineno in self.counts.keys():
+            lines_hit = per_file[filename] = per_file.get(filename, {})
+            lines_hit[lineno] = self.counts[(filename, lineno)]
+
+        # accumulate summary info, if needed
+        sums = {}
+
+        for filename, count in per_file.iteritems():
+            # skip some "files" we don't care about...
+            if filename == "<string>":
+                continue
+            if filename.startswith("<doctest "):
+                continue
+
+            if filename.endswith((".pyc", ".pyo")):
+                filename = filename[:-1]
+
+            if coverdir is None:
+                dir = os.path.dirname(os.path.abspath(filename))
+                modulename = modname(filename)
+            else:
+                dir = coverdir
+                if not os.path.exists(dir):
+                    os.makedirs(dir)
+                modulename = fullmodname(filename)
+
+            # If desired, get a list of the line numbers which represent
+            # executable content (returned as a dict for better lookup speed)
+            if show_missing:
+                lnotab = find_executable_linenos(filename)
+            else:
+                lnotab = {}
+
+            source = linecache.getlines(filename)
+            coverpath = os.path.join(dir, modulename + ".cover")
+            n_hits, n_lines = self.write_results_file(coverpath, source,
+                                                      lnotab, count)
+
+            if summary and n_lines:
+                percent = 100 * n_hits // n_lines
+                sums[modulename] = n_lines, percent, modulename, filename
+
+        if summary and sums:
+            mods = sums.keys()
+            mods.sort()
+            print "lines   cov%   module   (path)"
+            for m in mods:
+                n_lines, percent, modulename, filename = sums[m]
+                print "%5d   %3d%%   %s   (%s)" % sums[m]
+
+        if self.outfile:
+            # try and store counts and module info into self.outfile
+            try:
+                pickle.dump((self.counts, self.calledfuncs, self.callers),
+                            open(self.outfile, 'wb'), 1)
+            except IOError, err:
+                print >> sys.stderr, "Can't save counts files because %s" % err
+
+    def write_results_file(self, path, lines, lnotab, lines_hit):
+        """Return a coverage results file in path."""
+
+        try:
+            outfile = open(path, "w")
+        except IOError, err:
+            print >> sys.stderr, ("trace: Could not open %r for writing: %s"
+                                  "- skipping" % (path, err))
+            return 0, 0
+
+        n_lines = 0
+        n_hits = 0
+        for i, line in enumerate(lines):
+            lineno = i + 1
+            # do the blank/comment match to try to mark more lines
+            # (help the reader find stuff that hasn't been covered)
+            if lineno in lines_hit:
+                outfile.write("%5d: " % lines_hit[lineno])
+                n_hits += 1
+                n_lines += 1
+            elif rx_blank.match(line):
+                outfile.write("       ")
+            else:
+                # lines preceded by no marks weren't hit
+                # Highlight them if so indicated, unless the line contains
+                # #pragma: NO COVER
+                if lineno in lnotab and not PRAGMA_NOCOVER in lines[i]:
+                    outfile.write(">>>>>> ")
+                    n_lines += 1
+                else:
+                    outfile.write("       ")
+            outfile.write(lines[i].expandtabs(8))
+        outfile.close()
+
+        return n_hits, n_lines
+
+def find_lines_from_code(code, strs):
+    """Return dict where keys are lines in the line number table."""
+    linenos = {}
+
+    for _, lineno in dis.findlinestarts(code):
+        if lineno not in strs:
+            linenos[lineno] = 1
+
+    return linenos
+
+def find_lines(code, strs):
+    """Return lineno dict for all code objects reachable from code."""
+    # get all of the lineno information from the code of this scope level
+    linenos = find_lines_from_code(code, strs)
+
+    # and check the constants for references to other code objects
+    for c in code.co_consts:
+        if inspect.iscode(c):
+            # find another code object, so recurse into it
+            linenos.update(find_lines(c, strs))
+    return linenos
+
+def find_strings(filename):
+    """Return a dict of possible docstring positions.
+
+    The dict maps line numbers to strings.  There is an entry for
+    line that contains only a string or a part of a triple-quoted
+    string.
+    """
+    d = {}
+    # If the first token is a string, then it's the module docstring.
+    # Add this special case so that the test in the loop passes.
+    prev_ttype = token.INDENT
+    f = open(filename)
+    for ttype, tstr, start, end, line in tokenize.generate_tokens(f.readline):
+        if ttype == token.STRING:
+            if prev_ttype == token.INDENT:
+                sline, scol = start
+                eline, ecol = end
+                for i in range(sline, eline + 1):
+                    d[i] = 1
+        prev_ttype = ttype
+    f.close()
+    return d
+
+def find_executable_linenos(filename):
+    """Return dict where keys are line numbers in the line number table."""
+    try:
+        prog = open(filename, "rU").read()
+    except IOError, err:
+        print >> sys.stderr, ("Not printing coverage data for %r: %s"
+                              % (filename, err))
+        return {}
+    code = compile(prog, filename, "exec")
+    strs = find_strings(filename)
+    return find_lines(code, strs)
+
+class Trace:
+    def __init__(self, count=1, trace=1, countfuncs=0, countcallers=0,
+                 ignoremods=(), ignoredirs=(), infile=None, outfile=None,
+                 timing=False):
+        """
+        @param count true iff it should count number of times each
+                     line is executed
+        @param trace true iff it should print out each line that is
+                     being counted
+        @param countfuncs true iff it should just output a list of
+                     (filename, modulename, funcname,) for functions
+                     that were called at least once;  This overrides
+                     `count' and `trace'
+        @param ignoremods a list of the names of modules to ignore
+        @param ignoredirs a list of the names of directories to ignore
+                     all of the (recursive) contents of
+        @param infile file from which to read stored counts to be
+                     added into the results
+        @param outfile file in which to write the results
+        @param timing true iff timing information be displayed
+        """
+        self.infile = infile
+        self.outfile = outfile
+        self.ignore = Ignore(ignoremods, ignoredirs)
+        self.counts = {}   # keys are (filename, linenumber)
+        self.blabbed = {} # for debugging
+        self.pathtobasename = {} # for memoizing os.path.basename
+        self.donothing = 0
+        self.trace = trace
+        self._calledfuncs = {}
+        self._callers = {}
+        self._caller_cache = {}
+        self.start_time = None
+        if timing:
+            self.start_time = time.time()
+        if countcallers:
+            self.globaltrace = self.globaltrace_trackcallers
+        elif countfuncs:
+            self.globaltrace = self.globaltrace_countfuncs
+        elif trace and count:
+            self.globaltrace = self.globaltrace_lt
+            self.localtrace = self.localtrace_trace_and_count
+        elif trace:
+            self.globaltrace = self.globaltrace_lt
+            self.localtrace = self.localtrace_trace
+        elif count:
+            self.globaltrace = self.globaltrace_lt
+            self.localtrace = self.localtrace_count
+        else:
+            # Ahem -- do nothing?  Okay.
+            self.donothing = 1
+
+    def run(self, cmd):
+        import __main__
+        dict = __main__.__dict__
+        self.runctx(cmd, dict, dict)
+
+    def runctx(self, cmd, globals=None, locals=None):
+        if globals is None: globals = {}
+        if locals is None: locals = {}
+        if not self.donothing:
+            _settrace(self.globaltrace)
+        try:
+            exec cmd in globals, locals
+        finally:
+            if not self.donothing:
+                _unsettrace()
+
+    def runfunc(self, func, *args, **kw):
+        result = None
+        if not self.donothing:
+            sys.settrace(self.globaltrace)
+        try:
+            result = func(*args, **kw)
+        finally:
+            if not self.donothing:
+                sys.settrace(None)
+        return result
+
+    def file_module_function_of(self, frame):
+        code = frame.f_code
+        filename = code.co_filename
+        if filename:
+            modulename = modname(filename)
+        else:
+            modulename = None
+
+        funcname = code.co_name
+        clsname = None
+        if code in self._caller_cache:
+            if self._caller_cache[code] is not None:
+                clsname = self._caller_cache[code]
+        else:
+            self._caller_cache[code] = None
+            ## use of gc.get_referrers() was suggested by Michael Hudson
+            # all functions which refer to this code object
+            funcs = [f for f in gc.get_referrers(code)
+                         if inspect.isfunction(f)]
+            # require len(func) == 1 to avoid ambiguity caused by calls to
+            # new.function(): "In the face of ambiguity, refuse the
+            # temptation to guess."
+            if len(funcs) == 1:
+                dicts = [d for d in gc.get_referrers(funcs[0])
+                             if isinstance(d, dict)]
+                if len(dicts) == 1:
+                    classes = [c for c in gc.get_referrers(dicts[0])
+                                   if hasattr(c, "__bases__")]
+                    if len(classes) == 1:
+                        # ditto for new.classobj()
+                        clsname = classes[0].__name__
+                        # cache the result - assumption is that new.* is
+                        # not called later to disturb this relationship
+                        # _caller_cache could be flushed if functions in
+                        # the new module get called.
+                        self._caller_cache[code] = clsname
+        if clsname is not None:
+            funcname = "%s.%s" % (clsname, funcname)
+
+        return filename, modulename, funcname
+
+    def globaltrace_trackcallers(self, frame, why, arg):
+        """Handler for call events.
+
+        Adds information about who called who to the self._callers dict.
+        """
+        if why == 'call':
+            # XXX Should do a better job of identifying methods
+            this_func = self.file_module_function_of(frame)
+            parent_func = self.file_module_function_of(frame.f_back)
+            self._callers[(parent_func, this_func)] = 1
+
+    def globaltrace_countfuncs(self, frame, why, arg):
+        """Handler for call events.
+
+        Adds (filename, modulename, funcname) to the self._calledfuncs dict.
+        """
+        if why == 'call':
+            this_func = self.file_module_function_of(frame)
+            self._calledfuncs[this_func] = 1
+
+    def globaltrace_lt(self, frame, why, arg):
+        """Handler for call events.
+
+        If the code block being entered is to be ignored, returns `None',
+        else returns self.localtrace.
+        """
+        if why == 'call':
+            code = frame.f_code
+            filename = frame.f_globals.get('__file__', None)
+            if filename:
+                # XXX modname() doesn't work right for packages, so
+                # the ignore support won't work right for packages
+                modulename = modname(filename)
+                if modulename is not None:
+                    ignore_it = self.ignore.names(filename, modulename)
+                    if not ignore_it:
+                        if self.trace:
+                            print (" --- modulename: %s, funcname: %s"
+                                   % (modulename, code.co_name))
+                        return self.localtrace
+            else:
+                return None
+
+    def localtrace_trace_and_count(self, frame, why, arg):
+        if why == "line":
+            # record the file name and line number of every trace
+            filename = frame.f_code.co_filename
+            lineno = frame.f_lineno
+            key = filename, lineno
+            self.counts[key] = self.counts.get(key, 0) + 1
+
+            if self.start_time:
+                print '%.2f' % (time.time() - self.start_time),
+            bname = os.path.basename(filename)
+            print "%s(%d): %s" % (bname, lineno,
+                                  linecache.getline(filename, lineno)),
+        return self.localtrace
+
+    def localtrace_trace(self, frame, why, arg):
+        if why == "line":
+            # record the file name and line number of every trace
+            filename = frame.f_code.co_filename
+            lineno = frame.f_lineno
+
+            if self.start_time:
+                print '%.2f' % (time.time() - self.start_time),
+            bname = os.path.basename(filename)
+            print "%s(%d): %s" % (bname, lineno,
+                                  linecache.getline(filename, lineno)),
+        return self.localtrace
+
+    def localtrace_count(self, frame, why, arg):
+        if why == "line":
+            filename = frame.f_code.co_filename
+            lineno = frame.f_lineno
+            key = filename, lineno
+            self.counts[key] = self.counts.get(key, 0) + 1
+        return self.localtrace
+
+    def results(self):
+        return CoverageResults(self.counts, infile=self.infile,
+                               outfile=self.outfile,
+                               calledfuncs=self._calledfuncs,
+                               callers=self._callers)
+
+def _err_exit(msg):
+    sys.stderr.write("%s: %s\n" % (sys.argv[0], msg))
+    sys.exit(1)
+
+def main(argv=None):
+    import getopt
+
+    if argv is None:
+        argv = sys.argv
+    try:
+        opts, prog_argv = getopt.getopt(argv[1:], "tcrRf:d:msC:lTg",
+                                        ["help", "version", "trace", "count",
+                                         "report", "no-report", "summary",
+                                         "file=", "missing",
+                                         "ignore-module=", "ignore-dir=",
+                                         "coverdir=", "listfuncs",
+                                         "trackcalls", "timing"])
+
+    except getopt.error, msg:
+        sys.stderr.write("%s: %s\n" % (sys.argv[0], msg))
+        sys.stderr.write("Try `%s --help' for more information\n"
+                         % sys.argv[0])
+        sys.exit(1)
+
+    trace = 0
+    count = 0
+    report = 0
+    no_report = 0
+    counts_file = None
+    missing = 0
+    ignore_modules = []
+    ignore_dirs = []
+    coverdir = None
+    summary = 0
+    listfuncs = False
+    countcallers = False
+    timing = False
+
+    for opt, val in opts:
+        if opt == "--help":
+            usage(sys.stdout)
+            sys.exit(0)
+
+        if opt == "--version":
+            sys.stdout.write("trace 2.0\n")
+            sys.exit(0)
+
+        if opt == "-T" or opt == "--trackcalls":
+            countcallers = True
+            continue
+
+        if opt == "-l" or opt == "--listfuncs":
+            listfuncs = True
+            continue
+
+        if opt == "-g" or opt == "--timing":
+            timing = True
+            continue
+
+        if opt == "-t" or opt == "--trace":
+            trace = 1
+            continue
+
+        if opt == "-c" or opt == "--count":
+            count = 1
+            continue
+
+        if opt == "-r" or opt == "--report":
+            report = 1
+            continue
+
+        if opt == "-R" or opt == "--no-report":
+            no_report = 1
+            continue
+
+        if opt == "-f" or opt == "--file":
+            counts_file = val
+            continue
+
+        if opt == "-m" or opt == "--missing":
+            missing = 1
+            continue
+
+        if opt == "-C" or opt == "--coverdir":
+            coverdir = val
+            continue
+
+        if opt == "-s" or opt == "--summary":
+            summary = 1
+            continue
+
+        if opt == "--ignore-module":
+            for mod in val.split(","):
+                ignore_modules.append(mod.strip())
+            continue
+
+        if opt == "--ignore-dir":
+            for s in val.split(os.pathsep):
+                s = os.path.expandvars(s)
+                # should I also call expanduser? (after all, could use $HOME)
+
+                s = s.replace("$prefix",
+                              os.path.join(sys.prefix, "lib",
+                                           "python" + sys.version[:3]))
+                s = s.replace("$exec_prefix",
+                              os.path.join(sys.exec_prefix, "lib",
+                                           "python" + sys.version[:3]))
+                s = os.path.normpath(s)
+                ignore_dirs.append(s)
+            continue
+
+        assert 0, "Should never get here"
+
+    if listfuncs and (count or trace):
+        _err_exit("cannot specify both --listfuncs and (--trace or --count)")
+
+    if not (count or trace or report or listfuncs or countcallers):
+        _err_exit("must specify one of --trace, --count, --report, "
+                  "--listfuncs, or --trackcalls")
+
+    if report and no_report:
+        _err_exit("cannot specify both --report and --no-report")
+
+    if report and not counts_file:
+        _err_exit("--report requires a --file")
+
+    if no_report and len(prog_argv) == 0:
+        _err_exit("missing name of file to run")
+
+    # everything is ready
+    if report:
+        results = CoverageResults(infile=counts_file, outfile=counts_file)
+        results.write_results(missing, summary=summary, coverdir=coverdir)
+    else:
+        sys.argv = prog_argv
+        progname = prog_argv[0]
+        sys.path[0] = os.path.split(progname)[0]
+
+        t = Trace(count, trace, countfuncs=listfuncs,
+                  countcallers=countcallers, ignoremods=ignore_modules,
+                  ignoredirs=ignore_dirs, infile=counts_file,
+                  outfile=counts_file, timing=timing)
+        try:
+            with open(progname) as fp:
+                code = compile(fp.read(), progname, 'exec')
+            # try to emulate __main__ namespace as much as possible
+            globs = {
+                '__file__': progname,
+                '__name__': '__main__',
+                '__package__': None,
+                '__cached__': None,
+            }
+            t.runctx(code, globs, globs)
+        except IOError, err:
+            _err_exit("Cannot run file %r because: %s" % (sys.argv[0], err))
+        except SystemExit:
+            pass
+
+        results = t.results()
+
+        if not no_report:
+            results.write_results(missing, summary=summary, coverdir=coverdir)
+
+if __name__=='__main__':
+    main()
diff --git a/src/main/resources/PythonLibs/traceback.py b/src/main/resources/PythonLibs/traceback.py
new file mode 100644
index 0000000000000000000000000000000000000000..da17d3a1f8051ffb29e42babbe100a2d59dd2d3d
--- /dev/null
+++ b/src/main/resources/PythonLibs/traceback.py
@@ -0,0 +1,319 @@
+"""Extract, format and print information about Python stack traces."""
+
+import linecache
+import sys
+import types
+
+__all__ = ['extract_stack', 'extract_tb', 'format_exception',
+           'format_exception_only', 'format_list', 'format_stack',
+           'format_tb', 'print_exc', 'format_exc', 'print_exception',
+           'print_last', 'print_stack', 'print_tb', 'tb_lineno']
+
+def _print(file, str='', terminator='\n'):
+    file.write(str+terminator)
+
+
+def print_list(extracted_list, file=None):
+    """Print the list of tuples as returned by extract_tb() or
+    extract_stack() as a formatted stack trace to the given file."""
+    if file is None:
+        file = sys.stderr
+    for filename, lineno, name, line in extracted_list:
+        _print(file,
+               '  File "%s", line %d, in %s' % (filename,lineno,name))
+        if line:
+            _print(file, '    %s' % line.strip())
+
+def format_list(extracted_list):
+    """Format a list of traceback entry tuples for printing.
+
+    Given a list of tuples as returned by extract_tb() or
+    extract_stack(), return a list of strings ready for printing.
+    Each string in the resulting list corresponds to the item with the
+    same index in the argument list.  Each string ends in a newline;
+    the strings may contain internal newlines as well, for those items
+    whose source text line is not None.
+    """
+    list = []
+    for filename, lineno, name, line in extracted_list:
+        item = '  File "%s", line %d, in %s\n' % (filename,lineno,name)
+        if line:
+            item = item + '    %s\n' % line.strip()
+        list.append(item)
+    return list
+
+
+def print_tb(tb, limit=None, file=None):
+    """Print up to 'limit' stack trace entries from the traceback 'tb'.
+
+    If 'limit' is omitted or None, all entries are printed.  If 'file'
+    is omitted or None, the output goes to sys.stderr; otherwise
+    'file' should be an open file or file-like object with a write()
+    method.
+    """
+    if file is None:
+        file = sys.stderr
+    if limit is None:
+        if hasattr(sys, 'tracebacklimit'):
+            limit = sys.tracebacklimit
+    n = 0
+    while tb is not None and (limit is None or n < limit):
+        f = tb.tb_frame
+        lineno = tb.tb_lineno
+        co = f.f_code
+        filename = co.co_filename
+        name = co.co_name
+        _print(file,
+               '  File "%s", line %d, in %s' % (filename, lineno, name))
+        linecache.checkcache(filename)
+        line = linecache.getline(filename, lineno, f.f_globals)
+        if line: _print(file, '    ' + line.strip())
+        tb = tb.tb_next
+        n = n+1
+
+def format_tb(tb, limit = None):
+    """A shorthand for 'format_list(extract_stack(f, limit))."""
+    return format_list(extract_tb(tb, limit))
+
+def extract_tb(tb, limit = None):
+    """Return list of up to limit pre-processed entries from traceback.
+
+    This is useful for alternate formatting of stack traces.  If
+    'limit' is omitted or None, all entries are extracted.  A
+    pre-processed stack trace entry is a quadruple (filename, line
+    number, function name, text) representing the information that is
+    usually printed for a stack trace.  The text is a string with
+    leading and trailing whitespace stripped; if the source is not
+    available it is None.
+    """
+    if limit is None:
+        if hasattr(sys, 'tracebacklimit'):
+            limit = sys.tracebacklimit
+    list = []
+    n = 0
+    while tb is not None and (limit is None or n < limit):
+        f = tb.tb_frame
+        lineno = tb.tb_lineno
+        co = f.f_code
+        filename = co.co_filename
+        name = co.co_name
+        linecache.checkcache(filename)
+        line = linecache.getline(filename, lineno, f.f_globals)
+        if line: line = line.strip()
+        else: line = None
+        list.append((filename, lineno, name, line))
+        tb = tb.tb_next
+        n = n+1
+    return list
+
+
+def print_exception(etype, value, tb, limit=None, file=None):
+    """Print exception up to 'limit' stack trace entries from 'tb' to 'file'.
+
+    This differs from print_tb() in the following ways: (1) if
+    traceback is not None, it prints a header "Traceback (most recent
+    call last):"; (2) it prints the exception type and value after the
+    stack trace; (3) if type is SyntaxError and value has the
+    appropriate format, it prints the line where the syntax error
+    occurred with a caret on the next line indicating the approximate
+    position of the error.
+    """
+    if file is None:
+        file = sys.stderr
+    if tb:
+        _print(file, 'Traceback (most recent call last):')
+        print_tb(tb, limit, file)
+    lines = format_exception_only(etype, value)
+    for line in lines:
+        _print(file, line, '')
+
+def format_exception(etype, value, tb, limit = None):
+    """Format a stack trace and the exception information.
+
+    The arguments have the same meaning as the corresponding arguments
+    to print_exception().  The return value is a list of strings, each
+    ending in a newline and some containing internal newlines.  When
+    these lines are concatenated and printed, exactly the same text is
+    printed as does print_exception().
+    """
+    if tb:
+        list = ['Traceback (most recent call last):\n']
+        list = list + format_tb(tb, limit)
+    else:
+        list = []
+    list = list + format_exception_only(etype, value)
+    return list
+
+def format_exception_only(etype, value):
+    """Format the exception part of a traceback.
+
+    The arguments are the exception type and value such as given by
+    sys.last_type and sys.last_value. The return value is a list of
+    strings, each ending in a newline.
+
+    Normally, the list contains a single string; however, for
+    SyntaxError exceptions, it contains several lines that (when
+    printed) display detailed information about where the syntax
+    error occurred.
+
+    The message indicating which exception occurred is always the last
+    string in the list.
+
+    """
+
+    # An instance should not have a meaningful value parameter, but
+    # sometimes does, particularly for string exceptions, such as
+    # >>> raise string1, string2  # deprecated
+    #
+    # Clear these out first because issubtype(string1, SyntaxError)
+    # would raise another exception and mask the original problem.
+    if (isinstance(etype, BaseException) or
+        isinstance(etype, types.InstanceType) or
+        etype is None or type(etype) is str):
+        return [_format_final_exc_line(etype, value)]
+
+    stype = etype.__name__
+
+    if not issubclass(etype, SyntaxError):
+        return [_format_final_exc_line(stype, value)]
+
+    # It was a syntax error; show exactly where the problem was found.
+    lines = []
+    try:
+        msg, (filename, lineno, offset, badline) = value.args
+    except Exception:
+        pass
+    else:
+        filename = filename or "<string>"
+        lines.append('  File "%s", line %d\n' % (filename, lineno))
+        if badline is not None:
+            lines.append('    %s\n' % badline.strip())
+            if offset is not None:
+                caretspace = badline.rstrip('\n')[:offset].lstrip()
+                # non-space whitespace (likes tabs) must be kept for alignment
+                caretspace = ((c.isspace() and c or ' ') for c in caretspace)
+                # only three spaces to account for offset1 == pos 0
+                lines.append('   %s^\n' % ''.join(caretspace))
+        value = msg
+
+    lines.append(_format_final_exc_line(stype, value))
+    return lines
+
+def _format_final_exc_line(etype, value):
+    """Return a list of a single line -- normal case for format_exception_only"""
+    valuestr = _some_str(value)
+    if value is None or not valuestr:
+        line = "%s\n" % etype
+    else:
+        line = "%s: %s\n" % (etype, valuestr)
+    return line
+
+def _some_str(value):
+    try:
+        return str(value)
+    except Exception:
+        pass
+    try:
+        value = unicode(value)
+        return value.encode("ascii", "backslashreplace")
+    except Exception:
+        pass
+    return '<unprintable %s object>' % type(value).__name__
+
+
+def print_exc(limit=None, file=None):
+    """Shorthand for 'print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback, limit, file)'.
+    (In fact, it uses sys.exc_info() to retrieve the same information
+    in a thread-safe way.)"""
+    if file is None:
+        file = sys.stderr
+    try:
+        etype, value, tb = sys.exc_info()
+        print_exception(etype, value, tb, limit, file)
+    finally:
+        etype = value = tb = None
+
+
+def format_exc(limit=None):
+    """Like print_exc() but return a string."""
+    try:
+        etype, value, tb = sys.exc_info()
+        return ''.join(format_exception(etype, value, tb, limit))
+    finally:
+        etype = value = tb = None
+
+
+def print_last(limit=None, file=None):
+    """This is a shorthand for 'print_exception(sys.last_type,
+    sys.last_value, sys.last_traceback, limit, file)'."""
+    if not hasattr(sys, "last_type"):
+        raise ValueError("no last exception")
+    if file is None:
+        file = sys.stderr
+    print_exception(sys.last_type, sys.last_value, sys.last_traceback,
+                    limit, file)
+
+
+def print_stack(f=None, limit=None, file=None):
+    """Print a stack trace from its invocation point.
+
+    The optional 'f' argument can be used to specify an alternate
+    stack frame at which to start. The optional 'limit' and 'file'
+    arguments have the same meaning as for print_exception().
+    """
+    if f is None:
+        try:
+            raise ZeroDivisionError
+        except ZeroDivisionError:
+            f = sys.exc_info()[2].tb_frame.f_back
+    print_list(extract_stack(f, limit), file)
+
+def format_stack(f=None, limit=None):
+    """Shorthand for 'format_list(extract_stack(f, limit))'."""
+    if f is None:
+        try:
+            raise ZeroDivisionError
+        except ZeroDivisionError:
+            f = sys.exc_info()[2].tb_frame.f_back
+    return format_list(extract_stack(f, limit))
+
+def extract_stack(f=None, limit = None):
+    """Extract the raw traceback from the current stack frame.
+
+    The return value has the same format as for extract_tb().  The
+    optional 'f' and 'limit' arguments have the same meaning as for
+    print_stack().  Each item in the list is a quadruple (filename,
+    line number, function name, text), and the entries are in order
+    from oldest to newest stack frame.
+    """
+    if f is None:
+        try:
+            raise ZeroDivisionError
+        except ZeroDivisionError:
+            f = sys.exc_info()[2].tb_frame.f_back
+    if limit is None:
+        if hasattr(sys, 'tracebacklimit'):
+            limit = sys.tracebacklimit
+    list = []
+    n = 0
+    while f is not None and (limit is None or n < limit):
+        lineno = f.f_lineno
+        co = f.f_code
+        filename = co.co_filename
+        name = co.co_name
+        linecache.checkcache(filename)
+        line = linecache.getline(filename, lineno, f.f_globals)
+        if line: line = line.strip()
+        else: line = None
+        list.append((filename, lineno, name, line))
+        f = f.f_back
+        n = n+1
+    list.reverse()
+    return list
+
+def tb_lineno(tb):
+    """Calculate correct line number of traceback given in tb.
+
+    Obsolete in 2.3.
+    """
+    return tb.tb_lineno
diff --git a/src/main/resources/PythonLibs/tty.py b/src/main/resources/PythonLibs/tty.py
new file mode 100644
index 0000000000000000000000000000000000000000..a72eb6755450bb07d9bb77fb9cdc3cf2f0148534
--- /dev/null
+++ b/src/main/resources/PythonLibs/tty.py
@@ -0,0 +1,36 @@
+"""Terminal utilities."""
+
+# Author: Steen Lumholt.
+
+from termios import *
+
+__all__ = ["setraw", "setcbreak"]
+
+# Indexes for termios list.
+IFLAG = 0
+OFLAG = 1
+CFLAG = 2
+LFLAG = 3
+ISPEED = 4
+OSPEED = 5
+CC = 6
+
+def setraw(fd, when=TCSAFLUSH):
+    """Put terminal into a raw mode."""
+    mode = tcgetattr(fd)
+    mode[IFLAG] = mode[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
+    mode[OFLAG] = mode[OFLAG] & ~(OPOST)
+    mode[CFLAG] = mode[CFLAG] & ~(CSIZE | PARENB)
+    mode[CFLAG] = mode[CFLAG] | CS8
+    mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
+    mode[CC][VMIN] = 1
+    mode[CC][VTIME] = 0
+    tcsetattr(fd, when, mode)
+
+def setcbreak(fd, when=TCSAFLUSH):
+    """Put terminal into a cbreak mode."""
+    mode = tcgetattr(fd)
+    mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON)
+    mode[CC][VMIN] = 1
+    mode[CC][VTIME] = 0
+    tcsetattr(fd, when, mode)
diff --git a/src/main/resources/PythonLibs/types.py b/src/main/resources/PythonLibs/types.py
new file mode 100644
index 0000000000000000000000000000000000000000..5e85b43d8eede95c66160378fc79c1d52f88891e
--- /dev/null
+++ b/src/main/resources/PythonLibs/types.py
@@ -0,0 +1,87 @@
+"""Define names for all type symbols known in the standard interpreter.
+
+Types that are part of optional modules (e.g. array) are not listed.
+"""
+import sys
+
+# Iterators in Python aren't a matter of type but of protocol.  A large
+# and changing number of builtin types implement *some* flavor of
+# iterator.  Don't check the type!  Use hasattr to check for both
+# "__iter__" and "next" attributes instead.
+
+NoneType = type(None)
+TypeType = type
+ObjectType = object
+
+IntType = int
+LongType = long
+FloatType = float
+BooleanType = bool
+try:
+    ComplexType = complex
+except NameError:
+    pass
+
+StringType = str
+
+# StringTypes is already outdated.  Instead of writing "type(x) in
+# types.StringTypes", you should use "isinstance(x, basestring)".  But
+# we keep around for compatibility with Python 2.2.
+try:
+    UnicodeType = unicode
+    StringTypes = (StringType, UnicodeType)
+except NameError:
+    StringTypes = (StringType,)
+
+# XXX: no buffer in jython
+#BufferType = buffer
+
+TupleType = tuple
+ListType = list
+DictType = DictionaryType = dict
+
+def _f(): pass
+FunctionType = type(_f)
+LambdaType = type(lambda: None)         # Same as FunctionType
+CodeType = type(_f.func_code)
+
+def _g():
+    yield 1
+GeneratorType = type(_g())
+
+class _C:
+    def _m(self): pass
+ClassType = type(_C)
+UnboundMethodType = type(_C._m)         # Same as MethodType
+_x = _C()
+InstanceType = type(_x)
+MethodType = type(_x._m)
+
+BuiltinFunctionType = type(len)
+BuiltinMethodType = type([].append)     # Same as BuiltinFunctionType
+
+# XXX: Jython sys is not a real module
+#ModuleType = type(sys)
+ModuleType = type(sys.modules[__name__])
+FileType = file
+XRangeType = xrange
+
+try:
+    raise TypeError
+except TypeError:
+    tb = sys.exc_info()[2]
+    TracebackType = type(tb)
+    FrameType = type(tb.tb_frame)
+    del tb
+
+SliceType = slice
+EllipsisType = type(Ellipsis)
+
+DictProxyType = type(TypeType.__dict__)
+NotImplementedType = type(NotImplemented)
+
+# For Jython, the following two types are identical
+GetSetDescriptorType = type(FunctionType.func_code)
+MemberDescriptorType = type(FunctionType.func_globals)
+
+del sys, _f, _g, _C, _x                           # Not for export
diff --git a/src/main/resources/PythonLibs/unicodedata.py b/src/main/resources/PythonLibs/unicodedata.py
new file mode 100644
index 0000000000000000000000000000000000000000..907772b4e3bd290b601181b289ac2fcef43ddf1e
--- /dev/null
+++ b/src/main/resources/PythonLibs/unicodedata.py
@@ -0,0 +1,258 @@
+import java.lang.Character
+from com.ibm.icu.text import Normalizer
+from com.ibm.icu.lang import UCharacter, UProperty
+from com.ibm.icu.util import VersionInfo
+from com.ibm.icu.lang.UCharacter import EastAsianWidth, DecompositionType
+from com.ibm.icu.lang.UCharacterEnums import ECharacterCategory, ECharacterDirection
+
+
+__all__ = (
+    "bidirectional", "category", "combining", "decimal", "decomposition", "digit", "east_asian_width",
+    "lookup", "mirrored", "name", "normalize", "numeric", "unidata_version")
+
+
+_forms = {
+    'NFC':  Normalizer.NFC,
+    'NFKC': Normalizer.NFKC,
+    'NFD':  Normalizer.NFD,
+    'NFKD': Normalizer.NFKD
+}
+
+Nonesuch = object()   # to distinguish from None, which is a valid return value for some functions
+
+
+def _validate_unichr(unichr):
+    if not(isinstance(unichr, unicode)):
+        raise TypeError("must be unicode, not {}".format(type(unichr).__name__))
+    if len(unichr) > 1 or len(unichr) == 0:
+        raise TypeError("need a single Unicode character as parameter")
+
+
+def _get_codepoint(unichr):
+    _validate_unichr(unichr)
+    return ord(unichr)
+
+
+def name(unichr, default=Nonesuch):
+    # handle None
+    n = UCharacter.getName(_get_codepoint(unichr))
+    if n is None:
+        if default is not Nonesuch:
+            return default
+        else:
+            raise ValueError("no such name")
+    return n
+
+
+def lookup(name):
+    codepoint = UCharacter.getCharFromName(name)
+    if codepoint == -1:
+        raise KeyError("undefined character name '{}".format(name))
+    return unichr(codepoint)
+
+
+def digit(unichr, default=Nonesuch):
+    d = UCharacter.digit(_get_codepoint(unichr))
+    if d == -1:
+        if default is not Nonesuch:
+            return default
+        else:
+            raise ValueError("not a digit")
+    return d
+
+
+def decimal(unichr, default=Nonesuch):
+    d = UCharacter.getNumericValue(_get_codepoint(unichr))
+    if d < 0 or d > 9:
+        if default is not Nonesuch:
+            return default
+        else:
+            raise ValueError("not a decimal")
+    return d
+
+
+def numeric(unichr, default=Nonesuch):
+    n = UCharacter.getUnicodeNumericValue(_get_codepoint(unichr))
+    if n == UCharacter.NO_NUMERIC_VALUE:
+        if default is not Nonesuch:
+            return default
+        else:
+            raise ValueError("not a numeric")
+    return n
+
+
+_decomp = {
+    DecompositionType.CANONICAL: "canonical",
+    DecompositionType.CIRCLE: "circle",
+    DecompositionType.COMPAT: "compat", 
+    DecompositionType.FINAL: "final", 
+    DecompositionType.FONT: "font",
+    DecompositionType.FRACTION: "fraction",
+    DecompositionType.INITIAL: "initial",
+    DecompositionType.ISOLATED: "isolated",
+    DecompositionType.MEDIAL: "medial",
+    DecompositionType.NARROW: "narrow",
+    DecompositionType.NOBREAK: "nobreak",
+    DecompositionType.NONE: None,
+    DecompositionType.SMALL: "small",
+    DecompositionType.SQUARE: "square",
+    DecompositionType.SUB: "sub",
+    DecompositionType.SUPER: "super",
+    DecompositionType.VERTICAL: "vertical", 
+    DecompositionType.WIDE: "wide"
+}
+
+def _get_decomp_type(unichr):
+    if unichr == u"\u2044":  # FRACTION SLASH
+        # special case this for CPython compatibility even though this returns as not being combining, eg, see
+        # http://www.fileformat.info/info/unicode/char/2044/index.htm
+        return "fraction"
+    else:
+        return _decomp[UCharacter.getIntPropertyValue(ord(unichr), UProperty.DECOMPOSITION_TYPE)]
+
+def decomposition(unichr):
+    _validate_unichr(unichr)
+    d = Normalizer.decompose(unichr, True)
+    decomp_type = None
+    if len(d) == 1:
+        decomp_type = _get_decomp_type(unichr)
+    else:
+        for c in d:
+            decomp_type = _get_decomp_type(c)
+            # print "Got a decomp_type %r %r %r" % (c, d, decomp_type)
+            if decomp_type is not None:
+                break
+    hexed = " ".join(("{0:04X}".format(ord(c)) for c in d))
+    if decomp_type:
+        return "<{}> {}".format(decomp_type, hexed)
+    elif len(d) == 1:
+        return ""
+    else:
+        return hexed
+
+
+# To map from ICU4J enumerations for category, bidirection, and
+# east_asian_width to the underlying property values that Python uses
+# from UnicodeData.txt required a manual mapping between the following
+# two files:
+#
+# http://icu-project.org/apiref/icu4j/constant-values.html
+# http://www.unicode.org/Public/6.3.0/ucd/PropertyValueAliases.txt
+
+_cat = {
+    ECharacterCategory.COMBINING_SPACING_MARK: "Mc",
+    ECharacterCategory.CONNECTOR_PUNCTUATION: "Pc",
+    ECharacterCategory.CONTROL: "Cc",
+    ECharacterCategory.CURRENCY_SYMBOL: "Sc",
+    ECharacterCategory.DASH_PUNCTUATION: "Pd",
+    ECharacterCategory.DECIMAL_DIGIT_NUMBER: "Nd",
+    ECharacterCategory.ENCLOSING_MARK: "Me",
+    ECharacterCategory.END_PUNCTUATION: "Pe",
+    ECharacterCategory.FINAL_PUNCTUATION: "Pf",
+    ECharacterCategory.FORMAT: "Cf",
+    # per http://icu-project.org/apiref/icu4j/com/ibm/icu/lang/UCharacterEnums.ECharacterCategory.html#GENERAL_OTHER_TYPES
+    # - no characters in [UnicodeData.txt] have this property
+    ECharacterCategory.GENERAL_OTHER_TYPES: "Cn Not Assigned",
+    ECharacterCategory.INITIAL_PUNCTUATION: "Pi",
+    ECharacterCategory.LETTER_NUMBER: "Nl",
+    ECharacterCategory.LINE_SEPARATOR: "Zl",
+    ECharacterCategory.LOWERCASE_LETTER: "Ll",
+    ECharacterCategory.MATH_SYMBOL: "Sm",
+    ECharacterCategory.MODIFIER_LETTER: "Lm",
+    ECharacterCategory.MODIFIER_SYMBOL: "Sk",
+    ECharacterCategory.NON_SPACING_MARK: "Mn",
+    ECharacterCategory.OTHER_LETTER: "Lo",
+    ECharacterCategory.OTHER_NUMBER: "No",
+    ECharacterCategory.OTHER_PUNCTUATION: "Po",
+    ECharacterCategory.OTHER_SYMBOL: "So",
+    ECharacterCategory.PARAGRAPH_SEPARATOR: "Zp",
+    ECharacterCategory.PRIVATE_USE: "Co",
+    ECharacterCategory.SPACE_SEPARATOR: "Zs",
+    ECharacterCategory.START_PUNCTUATION: "Ps",
+    ECharacterCategory.SURROGATE: "Cs",
+    ECharacterCategory.TITLECASE_LETTER: "Lt",
+    ECharacterCategory.UNASSIGNED: "Cn",
+    ECharacterCategory.UPPERCASE_LETTER: "Lu",
+}
+
+def category(unichr):
+    return _cat[UCharacter.getType(_get_codepoint(unichr))]
+
+
+_dir = {
+    ECharacterDirection.ARABIC_NUMBER: "An",
+    ECharacterDirection.BLOCK_SEPARATOR: "B",
+    ECharacterDirection.BOUNDARY_NEUTRAL: "BN",
+    ECharacterDirection.COMMON_NUMBER_SEPARATOR: "CS",
+    ECharacterDirection.DIR_NON_SPACING_MARK: "NSM",
+    ECharacterDirection.EUROPEAN_NUMBER: "EN",
+    ECharacterDirection.EUROPEAN_NUMBER_SEPARATOR: "ES",
+    ECharacterDirection.EUROPEAN_NUMBER_TERMINATOR: "ET",
+    ECharacterDirection.FIRST_STRONG_ISOLATE: "FSI",
+    ECharacterDirection.LEFT_TO_RIGHT: "L",
+    ECharacterDirection.LEFT_TO_RIGHT_EMBEDDING: "LRE",
+    ECharacterDirection.LEFT_TO_RIGHT_ISOLATE: "LRI",
+    ECharacterDirection.LEFT_TO_RIGHT_OVERRIDE: "LRO",
+    ECharacterDirection.OTHER_NEUTRAL: "ON",
+    ECharacterDirection.POP_DIRECTIONAL_FORMAT: "PDF",
+    ECharacterDirection.POP_DIRECTIONAL_ISOLATE: "PDI",
+    ECharacterDirection.RIGHT_TO_LEFT: "R",
+    ECharacterDirection.RIGHT_TO_LEFT_ARABIC: "AL",
+    ECharacterDirection.RIGHT_TO_LEFT_EMBEDDING: "RLE",
+    ECharacterDirection.RIGHT_TO_LEFT_ISOLATE: "RLI",
+    ECharacterDirection.RIGHT_TO_LEFT_OVERRIDE: "RLO",
+    ECharacterDirection.SEGMENT_SEPARATOR: "S",
+    ECharacterDirection.WHITE_SPACE_NEUTRAL: "WS"
+}
+
+def bidirectional(unichr):
+    return _dir[UCharacter.getDirection(_get_codepoint(unichr))]
+
+
+def combining(unichr):
+    return UCharacter.getCombiningClass(_get_codepoint(unichr))
+
+
+def mirrored(unichr):
+    return UCharacter.isMirrored(_get_codepoint(unichr))
+
+
+_eaw = {
+    # http://www.unicode.org/reports/tr11/
+    EastAsianWidth.AMBIGUOUS : "A",
+    EastAsianWidth.COUNT     : "?",  # apparently not used, see above TR
+    EastAsianWidth.FULLWIDTH : "F",
+    EastAsianWidth.HALFWIDTH : "H", 
+    EastAsianWidth.NARROW    : "Na",
+    EastAsianWidth.NEUTRAL   : "N",
+    EastAsianWidth.WIDE      : "W"
+}
+
+def east_asian_width(unichr):
+    return _eaw[UCharacter.getIntPropertyValue(_get_codepoint(unichr), UProperty.EAST_ASIAN_WIDTH)]
+
+
+def normalize(form, unistr):
+    """
+    Return the normal form 'form' for the Unicode string unistr.  Valid
+    values for form are 'NFC', 'NFKC', 'NFD', and 'NFKD'.
+    """
+
+    try:
+        normalizer_form = _forms[form]
+    except KeyError:
+        raise ValueError('invalid normalization form')
+
+    return Normalizer.normalize(unistr, normalizer_form)
+
+
+def get_icu_version():
+    versions = []
+    for k in VersionInfo.__dict__.iterkeys():
+        if k.startswith("UNICODE_"):
+            v = getattr(VersionInfo, k)
+            versions.append((v.getMajor(), v.getMinor(), v.getMilli()))
+    return ".".join(str(x) for x in max(versions))
+
+
+unidata_version = get_icu_version()
diff --git a/src/main/resources/PythonLibs/unittest/__init__.py b/src/main/resources/PythonLibs/unittest/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..201a3f0d2da21b70dbcdb09286cfe9691c7bda55
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/__init__.py
@@ -0,0 +1,69 @@
+"""
+Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
+Smalltalk testing framework.
+
+This module contains the core framework classes that form the basis of
+specific test cases and suites (TestCase, TestSuite etc.), and also a
+text-based utility class for running the tests and reporting the results
+ (TextTestRunner).
+
+Simple usage:
+
+    import unittest
+
+    class IntegerArithmenticTestCase(unittest.TestCase):
+        def testAdd(self):  ## test method names begin 'test*'
+            self.assertEqual((1 + 2), 3)
+            self.assertEqual(0 + 1, 1)
+        def testMultiply(self):
+            self.assertEqual((0 * 10), 0)
+            self.assertEqual((5 * 8), 40)
+
+    if __name__ == '__main__':
+        unittest.main()
+
+Further information is available in the bundled documentation, and from
+
+  http://docs.python.org/library/unittest.html
+
+Copyright (c) 1999-2003 Steve Purcell
+Copyright (c) 2003-2010 Python Software Foundation
+This module is free software, and you may redistribute it and/or modify
+it under the same terms as Python itself, so long as this copyright message
+and disclaimer are retained in their original form.
+
+IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
+AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+"""
+
+__all__ = ['TestResult', 'TestCase', 'TestSuite',
+           'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
+           'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
+           'expectedFailure', 'TextTestResult', 'installHandler',
+           'registerResult', 'removeResult', 'removeHandler']
+
+# Expose obsolete functions for backwards compatibility
+__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
+
+__unittest = True
+
+from .result import TestResult
+from .case import (TestCase, FunctionTestCase, SkipTest, skip, skipIf,
+                   skipUnless, expectedFailure)
+from .suite import BaseTestSuite, TestSuite
+from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
+                     findTestCases)
+from .main import TestProgram, main
+from .runner import TextTestRunner, TextTestResult
+from .signals import installHandler, registerResult, removeResult, removeHandler
+
+# deprecated
+_TextTestResult = TextTestResult
diff --git a/src/main/resources/PythonLibs/unittest/__main__.py b/src/main/resources/PythonLibs/unittest/__main__.py
new file mode 100644
index 0000000000000000000000000000000000000000..7320050ae954cc3037760f8470c91fbad7301280
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/__main__.py
@@ -0,0 +1,12 @@
+"""Main entry point"""
+
+import sys
+if sys.argv[0].endswith("__main__.py"):
+    sys.argv[0] = "python -m unittest"
+
+__unittest = True
+
+from .main import main, TestProgram, USAGE_AS_MAIN
+TestProgram.USAGE = USAGE_AS_MAIN
+
+main(module=None)
diff --git a/src/main/resources/PythonLibs/unittest/case.py b/src/main/resources/PythonLibs/unittest/case.py
new file mode 100644
index 0000000000000000000000000000000000000000..6257936618a82e514d30fe9f1064c88be01fb5ce
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/case.py
@@ -0,0 +1,1077 @@
+"""Test case implementation"""
+
+import collections
+import sys
+import functools
+import difflib
+import pprint
+import re
+import types
+import warnings
+
+from . import result
+from .util import (
+    strclass, safe_repr, unorderable_list_difference,
+    _count_diff_all_purpose, _count_diff_hashable
+)
+
+
+__unittest = True
+
+
+DIFF_OMITTED = ('\nDiff is %s characters long. '
+                 'Set self.maxDiff to None to see it.')
+
+class SkipTest(Exception):
+    """
+    Raise this exception in a test to skip it.
+
+    Usually you can use TestResult.skip() or one of the skipping decorators
+    instead of raising this directly.
+    """
+    pass
+
+class _ExpectedFailure(Exception):
+    """
+    Raise this when a test is expected to fail.
+
+    This is an implementation detail.
+    """
+
+    def __init__(self, exc_info):
+        super(_ExpectedFailure, self).__init__()
+        self.exc_info = exc_info
+
+class _UnexpectedSuccess(Exception):
+    """
+    The test was supposed to fail, but it didn't!
+    """
+    pass
+
+def _id(obj):
+    return obj
+
+def skip(reason):
+    """
+    Unconditionally skip a test.
+    """
+    def decorator(test_item):
+        if not isinstance(test_item, (type, types.ClassType)):
+            @functools.wraps(test_item)
+            def skip_wrapper(*args, **kwargs):
+                raise SkipTest(reason)
+            test_item = skip_wrapper
+
+        test_item.__unittest_skip__ = True
+        test_item.__unittest_skip_why__ = reason
+        return test_item
+    return decorator
+
+def skipIf(condition, reason):
+    """
+    Skip a test if the condition is true.
+    """
+    if condition:
+        return skip(reason)
+    return _id
+
+def skipUnless(condition, reason):
+    """
+    Skip a test unless the condition is true.
+    """
+    if not condition:
+        return skip(reason)
+    return _id
+
+
+def expectedFailure(func):
+    @functools.wraps(func)
+    def wrapper(*args, **kwargs):
+        try:
+            func(*args, **kwargs)
+        except Exception:
+            raise _ExpectedFailure(sys.exc_info())
+        raise _UnexpectedSuccess
+    return wrapper
+
+
+class _AssertRaisesContext(object):
+    """A context manager used to implement TestCase.assertRaises* methods."""
+
+    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 TestCase(object):
+    """A class whose instances are single test cases.
+
+    By default, the test code itself should be placed in a method named
+    'runTest'.
+
+    If the fixture may be used for many test cases, create as
+    many test methods as are needed. When instantiating such a TestCase
+    subclass, specify in the constructor arguments the name of the test method
+    that the instance is to execute.
+
+    Test authors should subclass TestCase for their own tests. Construction
+    and deconstruction of the test's environment ('fixture') can be
+    implemented by overriding the 'setUp' and 'tearDown' methods respectively.
+
+    If it is necessary to override the __init__ method, the base class
+    __init__ method must always be called. It is important that subclasses
+    should not change the signature of their __init__ method, since instances
+    of the classes are instantiated automatically by parts of the framework
+    in order to be run.
+    """
+
+    # This attribute determines which exception will be raised when
+    # the instance's assertion methods fail; test methods raising this
+    # exception will be deemed to have 'failed' rather than 'errored'
+
+    failureException = AssertionError
+
+    # This attribute determines whether long messages (including repr of
+    # objects used in assert methods) will be printed on failure in *addition*
+    # to any explicit message passed.
+
+    longMessage = False
+
+    # This attribute sets the maximum length of a diff in failure messages
+    # by assert methods using difflib. It is looked up as an instance attribute
+    # so can be configured by individual tests if required.
+
+    maxDiff = 80*8
+
+    # If a string is longer than _diffThreshold, use normal comparison instead
+    # of difflib.  See #11763.
+    _diffThreshold = 2**16
+
+    # Attribute used by TestSuite for classSetUp
+
+    _classSetupFailed = False
+
+    def __init__(self, methodName='runTest'):
+        """Create an instance of the class that will use the named test
+           method when executed. Raises a ValueError if the instance does
+           not have a method with the specified name.
+        """
+        self._testMethodName = methodName
+        self._resultForDoCleanups = None
+        try:
+            testMethod = getattr(self, methodName)
+        except AttributeError:
+            raise ValueError("no such test method in %s: %s" %
+                  (self.__class__, methodName))
+        self._testMethodDoc = testMethod.__doc__
+        self._cleanups = []
+
+        # Map types to custom assertEqual functions that will compare
+        # instances of said type in more detail to generate a more useful
+        # error message.
+        self._type_equality_funcs = {}
+        self.addTypeEqualityFunc(dict, 'assertDictEqual')
+        self.addTypeEqualityFunc(list, 'assertListEqual')
+        self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
+        self.addTypeEqualityFunc(set, 'assertSetEqual')
+        self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
+        try:
+            self.addTypeEqualityFunc(unicode, 'assertMultiLineEqual')
+        except NameError:
+            # No unicode support in this build
+            pass
+
+    def addTypeEqualityFunc(self, typeobj, function):
+        """Add a type specific assertEqual style function to compare a type.
+
+        This method is for use by TestCase subclasses that need to register
+        their own type equality functions to provide nicer error messages.
+
+        Args:
+            typeobj: The data type to call this function on when both values
+                    are of the same type in assertEqual().
+            function: The callable taking two arguments and an optional
+                    msg= argument that raises self.failureException with a
+                    useful error message when the two arguments are not equal.
+        """
+        self._type_equality_funcs[typeobj] = function
+
+    def addCleanup(self, function, *args, **kwargs):
+        """Add a function, with arguments, to be called when the test is
+        completed. Functions added are called on a LIFO basis and are
+        called after tearDown on test failure or success.
+
+        Cleanup items are called even if setUp fails (unlike tearDown)."""
+        self._cleanups.append((function, args, kwargs))
+
+    def setUp(self):
+        "Hook method for setting up the test fixture before exercising it."
+        pass
+
+    def tearDown(self):
+        "Hook method for deconstructing the test fixture after testing it."
+        pass
+
+    @classmethod
+    def setUpClass(cls):
+        "Hook method for setting up class fixture before running tests in the class."
+
+    @classmethod
+    def tearDownClass(cls):
+        "Hook method for deconstructing the class fixture after running all tests in the class."
+
+    def countTestCases(self):
+        return 1
+
+    def defaultTestResult(self):
+        return result.TestResult()
+
+    def shortDescription(self):
+        """Returns a one-line description of the test, or None if no
+        description has been provided.
+
+        The default implementation of this method returns the first line of
+        the specified test method's docstring.
+        """
+        doc = self._testMethodDoc
+        return doc and doc.split("\n")[0].strip() or None
+
+
+    def id(self):
+        return "%s.%s" % (strclass(self.__class__), self._testMethodName)
+
+    def __eq__(self, other):
+        if type(self) is not type(other):
+            return NotImplemented
+
+        return self._testMethodName == other._testMethodName
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __hash__(self):
+        return hash((type(self), self._testMethodName))
+
+    def __str__(self):
+        return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
+
+    def __repr__(self):
+        return "<%s testMethod=%s>" % \
+               (strclass(self.__class__), self._testMethodName)
+
+    def _addSkip(self, result, reason):
+        addSkip = getattr(result, 'addSkip', None)
+        if addSkip is not None:
+            addSkip(self, reason)
+        else:
+            warnings.warn("TestResult has no addSkip method, skips not reported",
+                          RuntimeWarning, 2)
+            result.addSuccess(self)
+
+    def run(self, result=None):
+        orig_result = result
+        if result is None:
+            result = self.defaultTestResult()
+            startTestRun = getattr(result, 'startTestRun', None)
+            if startTestRun is not None:
+                startTestRun()
+
+        self._resultForDoCleanups = result
+        result.startTest(self)
+
+        testMethod = getattr(self, self._testMethodName)
+        if (getattr(self.__class__, "__unittest_skip__", False) or
+            getattr(testMethod, "__unittest_skip__", False)):
+            # If the class or method was skipped.
+            try:
+                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
+                            or getattr(testMethod, '__unittest_skip_why__', ''))
+                self._addSkip(result, skip_why)
+            finally:
+                result.stopTest(self)
+            return
+        try:
+            success = False
+            try:
+                self.setUp()
+            except SkipTest as e:
+                self._addSkip(result, str(e))
+            except KeyboardInterrupt:
+                raise
+            except:
+                result.addError(self, sys.exc_info())
+            else:
+                try:
+                    testMethod()
+                except KeyboardInterrupt:
+                    raise
+                except self.failureException:
+                    result.addFailure(self, sys.exc_info())
+                except _ExpectedFailure as e:
+                    addExpectedFailure = getattr(result, 'addExpectedFailure', None)
+                    if addExpectedFailure is not None:
+                        addExpectedFailure(self, e.exc_info)
+                    else:
+                        warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
+                                      RuntimeWarning)
+                        result.addSuccess(self)
+                except _UnexpectedSuccess:
+                    addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
+                    if addUnexpectedSuccess is not None:
+                        addUnexpectedSuccess(self)
+                    else:
+                        warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
+                                      RuntimeWarning)
+                        result.addFailure(self, sys.exc_info())
+                except SkipTest as e:
+                    self._addSkip(result, str(e))
+                except:
+                    result.addError(self, sys.exc_info())
+                else:
+                    success = True
+
+                try:
+                    self.tearDown()
+                except KeyboardInterrupt:
+                    raise
+                except:
+                    result.addError(self, sys.exc_info())
+                    success = False
+
+            cleanUpSuccess = self.doCleanups()
+            success = success and cleanUpSuccess
+            if success:
+                result.addSuccess(self)
+        finally:
+            result.stopTest(self)
+            if orig_result is None:
+                stopTestRun = getattr(result, 'stopTestRun', None)
+                if stopTestRun is not None:
+                    stopTestRun()
+
+    def doCleanups(self):
+        """Execute all cleanup functions. Normally called for you after
+        tearDown."""
+        result = self._resultForDoCleanups
+        ok = True
+        while self._cleanups:
+            function, args, kwargs = self._cleanups.pop(-1)
+            try:
+                function(*args, **kwargs)
+            except KeyboardInterrupt:
+                raise
+            except:
+                ok = False
+                result.addError(self, sys.exc_info())
+        return ok
+
+    def __call__(self, *args, **kwds):
+        return self.run(*args, **kwds)
+
+    def debug(self):
+        """Run the test without collecting errors in a TestResult"""
+        self.setUp()
+        getattr(self, self._testMethodName)()
+        self.tearDown()
+        while self._cleanups:
+            function, args, kwargs = self._cleanups.pop(-1)
+            function(*args, **kwargs)
+
+    def skipTest(self, reason):
+        """Skip this test."""
+        raise SkipTest(reason)
+
+    def fail(self, msg=None):
+        """Fail immediately, with the given message."""
+        raise self.failureException(msg)
+
+    def assertFalse(self, expr, msg=None):
+        """Check that the expression is false."""
+        if expr:
+            msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
+            raise self.failureException(msg)
+
+    def assertTrue(self, expr, msg=None):
+        """Check that the expression is true."""
+        if not expr:
+            msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
+            raise self.failureException(msg)
+
+    def _formatMessage(self, msg, standardMsg):
+        """Honour the longMessage attribute when generating failure messages.
+        If longMessage is False this means:
+        * Use only an explicit message if it is provided
+        * Otherwise use the standard message for the assert
+
+        If longMessage is True:
+        * Use the standard message
+        * If an explicit message is provided, plus ' : ' and the explicit message
+        """
+        if not self.longMessage:
+            return msg or standardMsg
+        if msg is None:
+            return standardMsg
+        try:
+            # don't switch to '{}' formatting in Python 2.X
+            # it changes the way unicode input is handled
+            return '%s : %s' % (standardMsg, msg)
+        except UnicodeDecodeError:
+            return  '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
+
+
+    def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
+        """Fail unless an exception of class excClass is raised
+           by callableObj when invoked with arguments args and keyword
+           arguments kwargs. If a different type of exception is
+           raised, it will not be caught, and the test case will be
+           deemed to have suffered an error, exactly as for an
+           unexpected exception.
+
+           If called with callableObj omitted or None, will return a
+           context object used like this::
+
+                with self.assertRaises(SomeException):
+                    do_something()
+
+           The context manager keeps a reference to the exception as
+           the 'exception' attribute. This allows you to inspect the
+           exception after the assertion::
+
+               with self.assertRaises(SomeException) as cm:
+                   do_something()
+               the_exception = cm.exception
+               self.assertEqual(the_exception.error_code, 3)
+        """
+        context = _AssertRaisesContext(excClass, self)
+        if callableObj is None:
+            return context
+        with context:
+            callableObj(*args, **kwargs)
+
+    def _getAssertEqualityFunc(self, first, second):
+        """Get a detailed comparison function for the types of the two args.
+
+        Returns: A callable accepting (first, second, msg=None) that will
+        raise a failure exception if first != second with a useful human
+        readable error message for those types.
+        """
+        #
+        # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
+        # and vice versa.  I opted for the conservative approach in case
+        # subclasses are not intended to be compared in detail to their super
+        # class instances using a type equality func.  This means testing
+        # subtypes won't automagically use the detailed comparison.  Callers
+        # should use their type specific assertSpamEqual method to compare
+        # subclasses if the detailed comparison is desired and appropriate.
+        # See the discussion in http://bugs.python.org/issue2578.
+        #
+        if type(first) is type(second):
+            asserter = self._type_equality_funcs.get(type(first))
+            if asserter is not None:
+                if isinstance(asserter, basestring):
+                    asserter = getattr(self, asserter)
+                return asserter
+
+        return self._baseAssertEqual
+
+    def _baseAssertEqual(self, first, second, msg=None):
+        """The default assertEqual implementation, not type specific."""
+        if not first == second:
+            standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
+            msg = self._formatMessage(msg, standardMsg)
+            raise self.failureException(msg)
+
+    def assertEqual(self, first, second, msg=None):
+        """Fail if the two objects are unequal as determined by the '=='
+           operator.
+        """
+        assertion_func = self._getAssertEqualityFunc(first, second)
+        assertion_func(first, second, msg=msg)
+
+    def assertNotEqual(self, first, second, msg=None):
+        """Fail if the two objects are equal as determined by the '!='
+           operator.
+        """
+        if not first != second:
+            msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
+                                                          safe_repr(second)))
+            raise self.failureException(msg)
+
+
+    def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None):
+        """Fail if the two objects are unequal as determined by their
+           difference rounded to the given number of decimal places
+           (default 7) and comparing to zero, or by comparing that the
+           between the two objects is more than the given delta.
+
+           Note that decimal places (from zero) are usually not the same
+           as significant digits (measured from the most signficant digit).
+
+           If the two objects compare equal then they will automatically
+           compare almost equal.
+        """
+        if first == second:
+            # shortcut
+            return
+        if delta is not None and places is not None:
+            raise TypeError("specify delta or places not both")
+
+        if delta is not None:
+            if abs(first - second) <= delta:
+                return
+
+            standardMsg = '%s != %s within %s delta' % (safe_repr(first),
+                                                        safe_repr(second),
+                                                        safe_repr(delta))
+        else:
+            if places is None:
+                places = 7
+
+            if round(abs(second-first), places) == 0:
+                return
+
+            standardMsg = '%s != %s within %r places' % (safe_repr(first),
+                                                          safe_repr(second),
+                                                          places)
+        msg = self._formatMessage(msg, standardMsg)
+        raise self.failureException(msg)
+
+    def assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None):
+        """Fail if the two objects are equal as determined by their
+           difference rounded to the given number of decimal places
+           (default 7) and comparing to zero, or by comparing that the
+           between the two objects is less than the given delta.
+
+           Note that decimal places (from zero) are usually not the same
+           as significant digits (measured from the most signficant digit).
+
+           Objects that are equal automatically fail.
+        """
+        if delta is not None and places is not None:
+            raise TypeError("specify delta or places not both")
+        if delta is not None:
+            if not (first == second) and abs(first - second) > delta:
+                return
+            standardMsg = '%s == %s within %s delta' % (safe_repr(first),
+                                                        safe_repr(second),
+                                                        safe_repr(delta))
+        else:
+            if places is None:
+                places = 7
+            if not (first == second) and round(abs(second-first), places) != 0:
+                return
+            standardMsg = '%s == %s within %r places' % (safe_repr(first),
+                                                         safe_repr(second),
+                                                         places)
+
+        msg = self._formatMessage(msg, standardMsg)
+        raise self.failureException(msg)
+
+    # Synonyms for assertion methods
+
+    # The plurals are undocumented.  Keep them that way to discourage use.
+    # Do not add more.  Do not remove.
+    # Going through a deprecation cycle on these would annoy many people.
+    assertEquals = assertEqual
+    assertNotEquals = assertNotEqual
+    assertAlmostEquals = assertAlmostEqual
+    assertNotAlmostEquals = assertNotAlmostEqual
+    assert_ = assertTrue
+
+    # These fail* assertion method names are pending deprecation and will
+    # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
+    def _deprecate(original_func):
+        def deprecated_func(*args, **kwargs):
+            warnings.warn(
+                'Please use {0} instead.'.format(original_func.__name__),
+                PendingDeprecationWarning, 2)
+            return original_func(*args, **kwargs)
+        return deprecated_func
+
+    failUnlessEqual = _deprecate(assertEqual)
+    failIfEqual = _deprecate(assertNotEqual)
+    failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
+    failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
+    failUnless = _deprecate(assertTrue)
+    failUnlessRaises = _deprecate(assertRaises)
+    failIf = _deprecate(assertFalse)
+
+    def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
+        """An equality assertion for ordered sequences (like lists and tuples).
+
+        For the purposes of this function, a valid ordered sequence type is one
+        which can be indexed, has a length, and has an equality operator.
+
+        Args:
+            seq1: The first sequence to compare.
+            seq2: The second sequence to compare.
+            seq_type: The expected datatype of the sequences, or None if no
+                    datatype should be enforced.
+            msg: Optional message to use on failure instead of a list of
+                    differences.
+        """
+        if seq_type is not None:
+            seq_type_name = seq_type.__name__
+            if not isinstance(seq1, seq_type):
+                raise self.failureException('First sequence is not a %s: %s'
+                                        % (seq_type_name, safe_repr(seq1)))
+            if not isinstance(seq2, seq_type):
+                raise self.failureException('Second sequence is not a %s: %s'
+                                        % (seq_type_name, safe_repr(seq2)))
+        else:
+            seq_type_name = "sequence"
+
+        differing = None
+        try:
+            len1 = len(seq1)
+        except (TypeError, NotImplementedError):
+            differing = 'First %s has no length.    Non-sequence?' % (
+                    seq_type_name)
+
+        if differing is None:
+            try:
+                len2 = len(seq2)
+            except (TypeError, NotImplementedError):
+                differing = 'Second %s has no length.    Non-sequence?' % (
+                        seq_type_name)
+
+        if differing is None:
+            if seq1 == seq2:
+                return
+
+            seq1_repr = safe_repr(seq1)
+            seq2_repr = safe_repr(seq2)
+            if len(seq1_repr) > 30:
+                seq1_repr = seq1_repr[:30] + '...'
+            if len(seq2_repr) > 30:
+                seq2_repr = seq2_repr[:30] + '...'
+            elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
+            differing = '%ss differ: %s != %s\n' % elements
+
+            for i in xrange(min(len1, len2)):
+                try:
+                    item1 = seq1[i]
+                except (TypeError, IndexError, NotImplementedError):
+                    differing += ('\nUnable to index element %d of first %s\n' %
+                                 (i, seq_type_name))
+                    break
+
+                try:
+                    item2 = seq2[i]
+                except (TypeError, IndexError, NotImplementedError):
+                    differing += ('\nUnable to index element %d of second %s\n' %
+                                 (i, seq_type_name))
+                    break
+
+                if item1 != item2:
+                    differing += ('\nFirst differing element %d:\n%s\n%s\n' %
+                                 (i, item1, item2))
+                    break
+            else:
+                if (len1 == len2 and seq_type is None and
+                    type(seq1) != type(seq2)):
+                    # The sequences are the same, but have differing types.
+                    return
+
+            if len1 > len2:
+                differing += ('\nFirst %s contains %d additional '
+                             'elements.\n' % (seq_type_name, len1 - len2))
+                try:
+                    differing += ('First extra element %d:\n%s\n' %
+                                  (len2, seq1[len2]))
+                except (TypeError, IndexError, NotImplementedError):
+                    differing += ('Unable to index element %d '
+                                  'of first %s\n' % (len2, seq_type_name))
+            elif len1 < len2:
+                differing += ('\nSecond %s contains %d additional '
+                             'elements.\n' % (seq_type_name, len2 - len1))
+                try:
+                    differing += ('First extra element %d:\n%s\n' %
+                                  (len1, seq2[len1]))
+                except (TypeError, IndexError, NotImplementedError):
+                    differing += ('Unable to index element %d '
+                                  'of second %s\n' % (len1, seq_type_name))
+        standardMsg = differing
+        diffMsg = '\n' + '\n'.join(
+            difflib.ndiff(pprint.pformat(seq1).splitlines(),
+                          pprint.pformat(seq2).splitlines()))
+        standardMsg = self._truncateMessage(standardMsg, diffMsg)
+        msg = self._formatMessage(msg, standardMsg)
+        self.fail(msg)
+
+    def _truncateMessage(self, message, diff):
+        max_diff = self.maxDiff
+        if max_diff is None or len(diff) <= max_diff:
+            return message + diff
+        return message + (DIFF_OMITTED % len(diff))
+
+    def assertListEqual(self, list1, list2, msg=None):
+        """A list-specific equality assertion.
+
+        Args:
+            list1: The first list to compare.
+            list2: The second list to compare.
+            msg: Optional message to use on failure instead of a list of
+                    differences.
+
+        """
+        self.assertSequenceEqual(list1, list2, msg, seq_type=list)
+
+    def assertTupleEqual(self, tuple1, tuple2, msg=None):
+        """A tuple-specific equality assertion.
+
+        Args:
+            tuple1: The first tuple to compare.
+            tuple2: The second tuple to compare.
+            msg: Optional message to use on failure instead of a list of
+                    differences.
+        """
+        self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
+
+    def assertSetEqual(self, set1, set2, msg=None):
+        """A set-specific equality assertion.
+
+        Args:
+            set1: The first set to compare.
+            set2: The second set to compare.
+            msg: Optional message to use on failure instead of a list of
+                    differences.
+
+        assertSetEqual uses ducktyping to support different types of sets, and
+        is optimized for sets specifically (parameters must support a
+        difference method).
+        """
+        try:
+            difference1 = set1.difference(set2)
+        except TypeError, e:
+            self.fail('invalid type when attempting set difference: %s' % e)
+        except AttributeError, e:
+            self.fail('first argument does not support set difference: %s' % e)
+
+        try:
+            difference2 = set2.difference(set1)
+        except TypeError, e:
+            self.fail('invalid type when attempting set difference: %s' % e)
+        except AttributeError, e:
+            self.fail('second argument does not support set difference: %s' % e)
+
+        if not (difference1 or difference2):
+            return
+
+        lines = []
+        if difference1:
+            lines.append('Items in the first set but not the second:')
+            for item in difference1:
+                lines.append(repr(item))
+        if difference2:
+            lines.append('Items in the second set but not the first:')
+            for item in difference2:
+                lines.append(repr(item))
+
+        standardMsg = '\n'.join(lines)
+        self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertIn(self, member, container, msg=None):
+        """Just like self.assertTrue(a in b), but with a nicer default message."""
+        if member not in container:
+            standardMsg = '%s not found in %s' % (safe_repr(member),
+                                                  safe_repr(container))
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertNotIn(self, member, container, msg=None):
+        """Just like self.assertTrue(a not in b), but with a nicer default message."""
+        if member in container:
+            standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
+                                                        safe_repr(container))
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertIs(self, expr1, expr2, msg=None):
+        """Just like self.assertTrue(a is b), but with a nicer default message."""
+        if expr1 is not expr2:
+            standardMsg = '%s is not %s' % (safe_repr(expr1),
+                                             safe_repr(expr2))
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertIsNot(self, expr1, expr2, msg=None):
+        """Just like self.assertTrue(a is not b), but with a nicer default message."""
+        if expr1 is expr2:
+            standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertDictEqual(self, d1, d2, msg=None):
+        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
+        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
+
+        if d1 != d2:
+            standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
+            diff = ('\n' + '\n'.join(difflib.ndiff(
+                           pprint.pformat(d1).splitlines(),
+                           pprint.pformat(d2).splitlines())))
+            standardMsg = self._truncateMessage(standardMsg, diff)
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertDictContainsSubset(self, expected, actual, msg=None):
+        """Checks whether actual is a superset of expected."""
+        missing = []
+        mismatched = []
+        for key, value in expected.iteritems():
+            if key not in actual:
+                missing.append(key)
+            elif value != actual[key]:
+                mismatched.append('%s, expected: %s, actual: %s' %
+                                  (safe_repr(key), safe_repr(value),
+                                   safe_repr(actual[key])))
+
+        if not (missing or mismatched):
+            return
+
+        standardMsg = ''
+        if missing:
+            standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in
+                                                    missing)
+        if mismatched:
+            if standardMsg:
+                standardMsg += '; '
+            standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
+
+        self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
+        """An unordered sequence specific comparison. It asserts that
+        actual_seq and expected_seq have the same element counts.
+        Equivalent to::
+
+            self.assertEqual(Counter(iter(actual_seq)),
+                             Counter(iter(expected_seq)))
+
+        Asserts that each element has the same count in both sequences.
+        Example:
+            - [0, 1, 1] and [1, 0, 1] compare equal.
+            - [0, 0, 1] and [0, 1] compare unequal.
+        """
+        first_seq, second_seq = list(expected_seq), list(actual_seq)
+        with warnings.catch_warnings():
+            if sys.py3kwarning:
+                # Silence Py3k warning raised during the sorting
+                for _msg in ["(code|dict|type) inequality comparisons",
+                             "builtin_function_or_method order comparisons",
+                             "comparing unequal types"]:
+                    warnings.filterwarnings("ignore", _msg, DeprecationWarning)
+            try:
+                first = collections.Counter(first_seq)
+                second = collections.Counter(second_seq)
+            except TypeError:
+                # Handle case with unhashable elements
+                differences = _count_diff_all_purpose(first_seq, second_seq)
+            else:
+                if first == second:
+                    return
+                differences = _count_diff_hashable(first_seq, second_seq)
+
+        if differences:
+            standardMsg = 'Element counts were not equal:\n'
+            lines = ['First has %d, Second has %d:  %r' % diff for diff in differences]
+            diffMsg = '\n'.join(lines)
+            standardMsg = self._truncateMessage(standardMsg, diffMsg)
+            msg = self._formatMessage(msg, standardMsg)
+            self.fail(msg)
+
+    def assertMultiLineEqual(self, first, second, msg=None):
+        """Assert that two multi-line strings are equal."""
+        self.assertIsInstance(first, basestring,
+                'First argument is not a string')
+        self.assertIsInstance(second, basestring,
+                'Second argument is not a string')
+
+        if first != second:
+            # don't use difflib if the strings are too long
+            if (len(first) > self._diffThreshold or
+                len(second) > self._diffThreshold):
+                self._baseAssertEqual(first, second, msg)
+            firstlines = first.splitlines(True)
+            secondlines = second.splitlines(True)
+            if len(firstlines) == 1 and first.strip('\r\n') == first:
+                firstlines = [first + '\n']
+                secondlines = [second + '\n']
+            standardMsg = '%s != %s' % (safe_repr(first, True),
+                                        safe_repr(second, True))
+            diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
+            standardMsg = self._truncateMessage(standardMsg, diff)
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertLess(self, a, b, msg=None):
+        """Just like self.assertTrue(a < b), but with a nicer default message."""
+        if not a < b:
+            standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertLessEqual(self, a, b, msg=None):
+        """Just like self.assertTrue(a <= b), but with a nicer default message."""
+        if not a <= b:
+            standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertGreater(self, a, b, msg=None):
+        """Just like self.assertTrue(a > b), but with a nicer default message."""
+        if not a > b:
+            standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertGreaterEqual(self, a, b, msg=None):
+        """Just like self.assertTrue(a >= b), but with a nicer default message."""
+        if not a >= b:
+            standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertIsNone(self, obj, msg=None):
+        """Same as self.assertTrue(obj is None), with a nicer default message."""
+        if obj is not None:
+            standardMsg = '%s is not None' % (safe_repr(obj),)
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertIsNotNone(self, obj, msg=None):
+        """Included for symmetry with assertIsNone."""
+        if obj is None:
+            standardMsg = 'unexpectedly None'
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertIsInstance(self, obj, cls, msg=None):
+        """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
+        default message."""
+        if not isinstance(obj, cls):
+            standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertNotIsInstance(self, obj, cls, msg=None):
+        """Included for symmetry with assertIsInstance."""
+        if isinstance(obj, cls):
+            standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
+            self.fail(self._formatMessage(msg, standardMsg))
+
+    def assertRaisesRegexp(self, expected_exception, expected_regexp,
+                           callable_obj=None, *args, **kwargs):
+        """Asserts that the message in a raised exception matches a regexp.
+
+        Args:
+            expected_exception: Exception class expected to be raised.
+            expected_regexp: Regexp (re pattern object or string) expected
+                    to be found in error message.
+            callable_obj: Function to be called.
+            args: Extra args.
+            kwargs: Extra kwargs.
+        """
+        context = _AssertRaisesContext(expected_exception, self, expected_regexp)
+        if callable_obj is None:
+            return context
+        with context:
+            callable_obj(*args, **kwargs)
+
+    def assertRegexpMatches(self, text, expected_regexp, msg=None):
+        """Fail the test unless the text matches the regular expression."""
+        if isinstance(expected_regexp, basestring):
+            expected_regexp = re.compile(expected_regexp)
+        if not expected_regexp.search(text):
+            msg = msg or "Regexp didn't match"
+            msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
+            raise self.failureException(msg)
+
+    def assertNotRegexpMatches(self, text, unexpected_regexp, msg=None):
+        """Fail the test if the text matches the regular expression."""
+        if isinstance(unexpected_regexp, basestring):
+            unexpected_regexp = re.compile(unexpected_regexp)
+        match = unexpected_regexp.search(text)
+        if match:
+            msg = msg or "Regexp matched"
+            msg = '%s: %r matches %r in %r' % (msg,
+                                               text[match.start():match.end()],
+                                               unexpected_regexp.pattern,
+                                               text)
+            raise self.failureException(msg)
+
+
+class FunctionTestCase(TestCase):
+    """A test case that wraps a test function.
+
+    This is useful for slipping pre-existing test functions into the
+    unittest framework. Optionally, set-up and tidy-up functions can be
+    supplied. As with TestCase, the tidy-up ('tearDown') function will
+    always be called if the set-up ('setUp') function ran successfully.
+    """
+
+    def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
+        super(FunctionTestCase, self).__init__()
+        self._setUpFunc = setUp
+        self._tearDownFunc = tearDown
+        self._testFunc = testFunc
+        self._description = description
+
+    def setUp(self):
+        if self._setUpFunc is not None:
+            self._setUpFunc()
+
+    def tearDown(self):
+        if self._tearDownFunc is not None:
+            self._tearDownFunc()
+
+    def runTest(self):
+        self._testFunc()
+
+    def id(self):
+        return self._testFunc.__name__
+
+    def __eq__(self, other):
+        if not isinstance(other, self.__class__):
+            return NotImplemented
+
+        return self._setUpFunc == other._setUpFunc and \
+               self._tearDownFunc == other._tearDownFunc and \
+               self._testFunc == other._testFunc and \
+               self._description == other._description
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __hash__(self):
+        return hash((type(self), self._setUpFunc, self._tearDownFunc,
+                     self._testFunc, self._description))
+
+    def __str__(self):
+        return "%s (%s)" % (strclass(self.__class__),
+                            self._testFunc.__name__)
+
+    def __repr__(self):
+        return "<%s tec=%s>" % (strclass(self.__class__),
+                                     self._testFunc)
+
+    def shortDescription(self):
+        if self._description is not None:
+            return self._description
+        doc = self._testFunc.__doc__
+        return doc and doc.split("\n")[0].strip() or None
diff --git a/src/main/resources/PythonLibs/unittest/loader.py b/src/main/resources/PythonLibs/unittest/loader.py
new file mode 100644
index 0000000000000000000000000000000000000000..1288d2d2118552453c38da3bb360202e7229cbdb
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/loader.py
@@ -0,0 +1,316 @@
+"""Loading unittests."""
+
+import os
+import re
+import sys
+import traceback
+import types
+
+from functools import cmp_to_key as _CmpToKey
+from fnmatch import fnmatch
+
+from . import case, suite
+
+__unittest = True
+
+# what about .pyc or .pyo (etc)
+# we would need to avoid loading the same tests multiple times
+# from '.py', '.pyc' *and* '.pyo'
+VALID_MODULE_NAME = re.compile(r'[_a-z]\w*\.py$', re.IGNORECASE)
+
+
+def _make_failed_import_test(name, suiteClass):
+    message = 'Failed to import test module: %s\n%s' % (name, traceback.format_exc())
+    return _make_failed_test('ModuleImportFailure', name, ImportError(message),
+                             suiteClass)
+
+def _make_failed_load_tests(name, exception, suiteClass):
+    return _make_failed_test('LoadTestsFailure', name, exception, suiteClass)
+
+def _make_failed_test(classname, methodname, exception, suiteClass):
+    def testFailure(self):
+        raise exception
+    attrs = {methodname: testFailure}
+    TestClass = type(classname, (case.TestCase,), attrs)
+    return suiteClass((TestClass(methodname),))
+
+
+class TestLoader(object):
+    """
+    This class is responsible for loading tests according to various criteria
+    and returning them wrapped in a TestSuite
+    """
+    testMethodPrefix = 'test'
+    sortTestMethodsUsing = cmp
+    suiteClass = suite.TestSuite
+    _top_level_dir = None
+
+    def loadTestsFromTestCase(self, testCaseClass):
+        """Return a suite of all tests cases contained in testCaseClass"""
+        if issubclass(testCaseClass, suite.TestSuite):
+            raise TypeError("Test cases should not be derived from TestSuite." \
+                                " Maybe you meant to derive from TestCase?")
+        testCaseNames = self.getTestCaseNames(testCaseClass)
+        if not testCaseNames and hasattr(testCaseClass, 'runTest'):
+            testCaseNames = ['runTest']
+        loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
+        return loaded_suite
+
+    def loadTestsFromModule(self, module, use_load_tests=True):
+        """Return a suite of all tests cases contained in the given module"""
+        tests = []
+        for name in dir(module):
+            obj = getattr(module, name)
+            if isinstance(obj, type) and issubclass(obj, case.TestCase):
+                tests.append(self.loadTestsFromTestCase(obj))
+
+        load_tests = getattr(module, 'load_tests', None)
+        tests = self.suiteClass(tests)
+        if use_load_tests and load_tests is not None:
+            try:
+                return load_tests(self, tests, None)
+            except Exception, e:
+                return _make_failed_load_tests(module.__name__, e,
+                                               self.suiteClass)
+        return tests
+
+    def loadTestsFromName(self, name, module=None):
+        """Return a suite of all tests cases given a string specifier.
+
+        The name may resolve either to a module, a test case class, a
+        test method within a test case class, or a callable object which
+        returns a TestCase or TestSuite instance.
+
+        The method optionally resolves the names relative to a given module.
+        """
+        parts = name.split('.')
+        if module is None:
+            parts_copy = parts[:]
+            while parts_copy:
+                try:
+                    module = __import__('.'.join(parts_copy))
+                    break
+                except ImportError:
+                    del parts_copy[-1]
+                    if not parts_copy:
+                        raise
+            parts = parts[1:]
+        obj = module
+        for part in parts:
+            parent, obj = obj, getattr(obj, part)
+
+        if isinstance(obj, types.ModuleType):
+            return self.loadTestsFromModule(obj)
+        elif isinstance(obj, type) and issubclass(obj, case.TestCase):
+            return self.loadTestsFromTestCase(obj)
+        elif (isinstance(obj, types.UnboundMethodType) and
+              isinstance(parent, type) and
+              issubclass(parent, case.TestCase)):
+            return self.suiteClass([parent(obj.__name__)])
+        elif isinstance(obj, suite.TestSuite):
+            return obj
+        elif hasattr(obj, '__call__'):
+            test = obj()
+            if isinstance(test, suite.TestSuite):
+                return test
+            elif isinstance(test, case.TestCase):
+                return self.suiteClass([test])
+            else:
+                raise TypeError("calling %s returned %s, not a test" %
+                                (obj, test))
+        else:
+            raise TypeError("don't know how to make test from: %s" % obj)
+
+    def loadTestsFromNames(self, names, module=None):
+        """Return a suite of all tests cases found using the given sequence
+        of string specifiers. See 'loadTestsFromName()'.
+        """
+        suites = [self.loadTestsFromName(name, module) for name in names]
+        return self.suiteClass(suites)
+
+    def getTestCaseNames(self, testCaseClass):
+        """Return a sorted sequence of method names found within testCaseClass
+        """
+        def isTestMethod(attrname, testCaseClass=testCaseClass,
+                         prefix=self.testMethodPrefix):
+            return attrname.startswith(prefix) and \
+                hasattr(getattr(testCaseClass, attrname), '__call__')
+        testFnNames = filter(isTestMethod, dir(testCaseClass))
+        if self.sortTestMethodsUsing:
+            testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing))
+        return testFnNames
+
+    def discover(self, start_dir, pattern='test*.py', top_level_dir=None):
+        """Find and return all test modules from the specified start
+        directory, recursing into subdirectories to find them. Only test files
+        that match the pattern will be loaded. (Using shell style pattern
+        matching.)
+
+        All test modules must be importable from the top level of the project.
+        If the start directory is not the top level directory then the top
+        level directory must be specified separately.
+
+        If a test package name (directory with '__init__.py') matches the
+        pattern then the package will be checked for a 'load_tests' function. If
+        this exists then it will be called with loader, tests, pattern.
+
+        If load_tests exists then discovery does  *not* recurse into the package,
+        load_tests is responsible for loading all tests in the package.
+
+        The pattern is deliberately not stored as a loader attribute so that
+        packages can continue discovery themselves. top_level_dir is stored so
+        load_tests does not need to pass this argument in to loader.discover().
+        """
+        set_implicit_top = False
+        if top_level_dir is None and self._top_level_dir is not None:
+            # make top_level_dir optional if called from load_tests in a package
+            top_level_dir = self._top_level_dir
+        elif top_level_dir is None:
+            set_implicit_top = True
+            top_level_dir = start_dir
+
+        top_level_dir = os.path.abspath(top_level_dir)
+
+        if not top_level_dir in sys.path:
+            # all test modules must be importable from the top level directory
+            # should we *unconditionally* put the start directory in first
+            # in sys.path to minimise likelihood of conflicts between installed
+            # modules and development versions?
+            sys.path.insert(0, top_level_dir)
+        self._top_level_dir = top_level_dir
+
+        is_not_importable = False
+        if os.path.isdir(os.path.abspath(start_dir)):
+            start_dir = os.path.abspath(start_dir)
+            if start_dir != top_level_dir:
+                is_not_importable = not os.path.isfile(os.path.join(start_dir, '__init__.py'))
+        else:
+            # support for discovery from dotted module names
+            try:
+                __import__(start_dir)
+            except ImportError:
+                is_not_importable = True
+            else:
+                the_module = sys.modules[start_dir]
+                top_part = start_dir.split('.')[0]
+                start_dir = os.path.abspath(os.path.dirname((the_module.__file__)))
+                if set_implicit_top:
+                    self._top_level_dir = self._get_directory_containing_module(top_part)
+                    sys.path.remove(top_level_dir)
+
+        if is_not_importable:
+            raise ImportError('Start directory is not importable: %r' % start_dir)
+
+        tests = list(self._find_tests(start_dir, pattern))
+        return self.suiteClass(tests)
+
+    def _get_directory_containing_module(self, module_name):
+        module = sys.modules[module_name]
+        full_path = os.path.abspath(module.__file__)
+
+        if os.path.basename(full_path).lower().startswith('__init__.py'):
+            return os.path.dirname(os.path.dirname(full_path))
+        else:
+            # here we have been given a module rather than a package - so
+            # all we can do is search the *same* directory the module is in
+            # should an exception be raised instead
+            return os.path.dirname(full_path)
+
+    def _get_name_from_path(self, path):
+        path = os.path.splitext(os.path.normpath(path))[0]
+
+        _relpath = os.path.relpath(path, self._top_level_dir)
+        assert not os.path.isabs(_relpath), "Path must be within the project"
+        assert not _relpath.startswith('..'), "Path must be within the project"
+
+        name = _relpath.replace(os.path.sep, '.')
+        return name
+
+    def _get_module_from_name(self, name):
+        __import__(name)
+        return sys.modules[name]
+
+    def _match_path(self, path, full_path, pattern):
+        # override this method to use alternative matching strategy
+        return fnmatch(path, pattern)
+
+    def _find_tests(self, start_dir, pattern):
+        """Used by discovery. Yields test suites it loads."""
+        paths = os.listdir(start_dir)
+
+        for path in paths:
+            full_path = os.path.join(start_dir, path)
+            if os.path.isfile(full_path):
+                if not VALID_MODULE_NAME.match(path):
+                    # valid Python identifiers only
+                    continue
+                if not self._match_path(path, full_path, pattern):
+                    continue
+                # if the test file matches, load it
+                name = self._get_name_from_path(full_path)
+                try:
+                    module = self._get_module_from_name(name)
+                except:
+                    yield _make_failed_import_test(name, self.suiteClass)
+                else:
+                    mod_file = os.path.abspath(getattr(module, '__file__', full_path))
+                    realpath = os.path.splitext(mod_file)[0]
+                    if realpath.lower().endswith('$py'):  # This is needed for $py.class
+                        realpath = realpath[:-3]
+                    fullpath_noext = os.path.splitext(full_path)[0]
+                    if realpath.lower() != fullpath_noext.lower():
+                        module_dir = os.path.dirname(realpath)
+                        mod_name = os.path.splitext(os.path.basename(full_path))[0]
+                        expected_dir = os.path.dirname(full_path)
+                        msg = ("%r module incorrectly imported from %r. Expected %r. "
+                               "Is this module globally installed?")
+                        raise ImportError(msg % (mod_name, module_dir, expected_dir))
+                    yield self.loadTestsFromModule(module)
+            elif os.path.isdir(full_path):
+                if not os.path.isfile(os.path.join(full_path, '__init__.py')):
+                    continue
+
+                load_tests = None
+                tests = None
+                if fnmatch(path, pattern):
+                    # only check load_tests if the package directory itself matches the filter
+                    name = self._get_name_from_path(full_path)
+                    package = self._get_module_from_name(name)
+                    load_tests = getattr(package, 'load_tests', None)
+                    tests = self.loadTestsFromModule(package, use_load_tests=False)
+
+                if load_tests is None:
+                    if tests is not None:
+                        # tests loaded from package file
+                        yield tests
+                    # recurse into the package
+                    for test in self._find_tests(full_path, pattern):
+                        yield test
+                else:
+                    try:
+                        yield load_tests(self, tests, pattern)
+                    except Exception, e:
+                        yield _make_failed_load_tests(package.__name__, e,
+                                                      self.suiteClass)
+
+defaultTestLoader = TestLoader()
+
+
+def _makeLoader(prefix, sortUsing, suiteClass=None):
+    loader = TestLoader()
+    loader.sortTestMethodsUsing = sortUsing
+    loader.testMethodPrefix = prefix
+    if suiteClass:
+        loader.suiteClass = suiteClass
+    return loader
+
+def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
+    return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
+
+def makeSuite(testCaseClass, prefix='test', sortUsing=cmp,
+              suiteClass=suite.TestSuite):
+    return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
+
+def findTestCases(module, prefix='test', sortUsing=cmp,
+                  suiteClass=suite.TestSuite):
+    return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
diff --git a/src/main/resources/PythonLibs/unittest/main.py b/src/main/resources/PythonLibs/unittest/main.py
new file mode 100644
index 0000000000000000000000000000000000000000..b25367992de8ac7e004c906d9b6a104f83dffb80
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/main.py
@@ -0,0 +1,236 @@
+"""Unittest main program"""
+
+import sys
+import os
+import types
+
+from . import loader, runner
+from .signals import installHandler
+
+__unittest = True
+
+FAILFAST     = "  -f, --failfast   Stop on first failure\n"
+CATCHBREAK   = "  -c, --catch      Catch control-C and display results\n"
+BUFFEROUTPUT = "  -b, --buffer     Buffer stdout and stderr during test runs\n"
+
+USAGE_AS_MAIN = """\
+Usage: %(progName)s [options] [tests]
+
+Options:
+  -h, --help       Show this message
+  -v, --verbose    Verbose output
+  -q, --quiet      Minimal output
+%(failfast)s%(catchbreak)s%(buffer)s
+Examples:
+  %(progName)s test_module               - run tests from test_module
+  %(progName)s module.TestClass          - run tests from module.TestClass
+  %(progName)s module.Class.test_method  - run specified test method
+
+[tests] can be a list of any number of test modules, classes and test
+methods.
+
+Alternative Usage: %(progName)s discover [options]
+
+Options:
+  -v, --verbose    Verbose output
+%(failfast)s%(catchbreak)s%(buffer)s  -s directory     Directory to start discovery ('.' default)
+  -p pattern       Pattern to match test files ('test*.py' default)
+  -t directory     Top level directory of project (default to
+                   start directory)
+
+For test discovery all test modules must be importable from the top
+level directory of the project.
+"""
+
+USAGE_FROM_MODULE = """\
+Usage: %(progName)s [options] [test] [...]
+
+Options:
+  -h, --help       Show this message
+  -v, --verbose    Verbose output
+  -q, --quiet      Minimal output
+%(failfast)s%(catchbreak)s%(buffer)s
+Examples:
+  %(progName)s                               - run default set of tests
+  %(progName)s MyTestSuite                   - run suite 'MyTestSuite'
+  %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething
+  %(progName)s MyTestCase                    - run all 'test*' test methods
+                                               in MyTestCase
+"""
+
+
+
+class TestProgram(object):
+    """A command-line program that runs a set of tests; this is primarily
+       for making test modules conveniently executable.
+    """
+    USAGE = USAGE_FROM_MODULE
+
+    # defaults for testing
+    failfast = catchbreak = buffer = progName = None
+
+    def __init__(self, module='__main__', defaultTest=None, argv=None,
+                    testRunner=None, testLoader=loader.defaultTestLoader,
+                    exit=True, verbosity=1, failfast=None, catchbreak=None,
+                    buffer=None):
+        if isinstance(module, basestring):
+            self.module = __import__(module)
+            for part in module.split('.')[1:]:
+                self.module = getattr(self.module, part)
+        else:
+            self.module = module
+        if argv is None:
+            argv = sys.argv
+
+        self.exit = exit
+        self.failfast = failfast
+        self.catchbreak = catchbreak
+        self.verbosity = verbosity
+        self.buffer = buffer
+        self.defaultTest = defaultTest
+        self.testRunner = testRunner
+        self.testLoader = testLoader
+        self.progName = os.path.basename(argv[0])
+        self.parseArgs(argv)
+        self.runTests()
+
+    def usageExit(self, msg=None):
+        if msg:
+            print msg
+        usage = {'progName': self.progName, 'catchbreak': '', 'failfast': '',
+                 'buffer': ''}
+        if self.failfast != False:
+            usage['failfast'] = FAILFAST
+        if self.catchbreak != False:
+            usage['catchbreak'] = CATCHBREAK
+        if self.buffer != False:
+            usage['buffer'] = BUFFEROUTPUT
+        print self.USAGE % usage
+        sys.exit(2)
+
+    def parseArgs(self, argv):
+        if len(argv) > 1 and argv[1].lower() == 'discover':
+            self._do_discovery(argv[2:])
+            return
+
+        import getopt
+        long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer']
+        try:
+            options, args = getopt.getopt(argv[1:], 'hHvqfcb', long_opts)
+            for opt, value in options:
+                if opt in ('-h','-H','--help'):
+                    self.usageExit()
+                if opt in ('-q','--quiet'):
+                    self.verbosity = 0
+                if opt in ('-v','--verbose'):
+                    self.verbosity = 2
+                if opt in ('-f','--failfast'):
+                    if self.failfast is None:
+                        self.failfast = True
+                    # Should this raise an exception if -f is not valid?
+                if opt in ('-c','--catch'):
+                    if self.catchbreak is None:
+                        self.catchbreak = True
+                    # Should this raise an exception if -c is not valid?
+                if opt in ('-b','--buffer'):
+                    if self.buffer is None:
+                        self.buffer = True
+                    # Should this raise an exception if -b is not valid?
+            if len(args) == 0 and self.defaultTest is None:
+                # createTests will load tests from self.module
+                self.testNames = None
+            elif len(args) > 0:
+                self.testNames = args
+                if __name__ == '__main__':
+                    # to support python -m unittest ...
+                    self.module = None
+            else:
+                self.testNames = (self.defaultTest,)
+            self.createTests()
+        except getopt.error, msg:
+            self.usageExit(msg)
+
+    def createTests(self):
+        if self.testNames is None:
+            self.test = self.testLoader.loadTestsFromModule(self.module)
+        else:
+            self.test = self.testLoader.loadTestsFromNames(self.testNames,
+                                                           self.module)
+
+    def _do_discovery(self, argv, Loader=None):
+        if Loader is None:
+            Loader = lambda: self.testLoader
+
+        # handle command line args for test discovery
+        self.progName = '%s discover' % self.progName
+        import optparse
+        parser = optparse.OptionParser()
+        parser.prog = self.progName
+        parser.add_option('-v', '--verbose', dest='verbose', default=False,
+                          help='Verbose output', action='store_true')
+        if self.failfast != False:
+            parser.add_option('-f', '--failfast', dest='failfast', default=False,
+                              help='Stop on first fail or error',
+                              action='store_true')
+        if self.catchbreak != False:
+            parser.add_option('-c', '--catch', dest='catchbreak', default=False,
+                              help='Catch ctrl-C and display results so far',
+                              action='store_true')
+        if self.buffer != False:
+            parser.add_option('-b', '--buffer', dest='buffer', default=False,
+                              help='Buffer stdout and stderr during tests',
+                              action='store_true')
+        parser.add_option('-s', '--start-directory', dest='start', default='.',
+                          help="Directory to start discovery ('.' default)")
+        parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
+                          help="Pattern to match tests ('test*.py' default)")
+        parser.add_option('-t', '--top-level-directory', dest='top', default=None,
+                          help='Top level directory of project (defaults to start directory)')
+
+        options, args = parser.parse_args(argv)
+        if len(args) > 3:
+            self.usageExit()
+
+        for name, value in zip(('start', 'pattern', 'top'), args):
+            setattr(options, name, value)
+
+        # only set options from the parsing here
+        # if they weren't set explicitly in the constructor
+        if self.failfast is None:
+            self.failfast = options.failfast
+        if self.catchbreak is None:
+            self.catchbreak = options.catchbreak
+        if self.buffer is None:
+            self.buffer = options.buffer
+
+        if options.verbose:
+            self.verbosity = 2
+
+        start_dir = options.start
+        pattern = options.pattern
+        top_level_dir = options.top
+
+        loader = Loader()
+        self.test = loader.discover(start_dir, pattern, top_level_dir)
+
+    def runTests(self):
+        if self.catchbreak:
+            installHandler()
+        if self.testRunner is None:
+            self.testRunner = runner.TextTestRunner
+        if isinstance(self.testRunner, (type, types.ClassType)):
+            try:
+                testRunner = self.testRunner(verbosity=self.verbosity,
+                                             failfast=self.failfast,
+                                             buffer=self.buffer)
+            except TypeError:
+                # didn't accept the verbosity, buffer or failfast arguments
+                testRunner = self.testRunner()
+        else:
+            # it is assumed to be a TestRunner instance
+            testRunner = self.testRunner
+        self.result = testRunner.run(self.test)
+        if self.exit:
+            sys.exit(not self.result.wasSuccessful())
+
+main = TestProgram
diff --git a/src/main/resources/PythonLibs/unittest/result.py b/src/main/resources/PythonLibs/unittest/result.py
new file mode 100644
index 0000000000000000000000000000000000000000..2cc17d71c853541cfc491cf8b60181e587d92fee
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/result.py
@@ -0,0 +1,193 @@
+"""Test result object"""
+
+import os
+import sys
+import traceback
+
+from StringIO import StringIO
+
+from . import util
+from functools import wraps
+
+__unittest = True
+
+def failfast(method):
+    @wraps(method)
+    def inner(self, *args, **kw):
+        if getattr(self, 'failfast', False):
+            self.stop()
+        return method(self, *args, **kw)
+    return inner
+
+STDOUT_LINE = '\nStdout:\n%s'
+STDERR_LINE = '\nStderr:\n%s'
+
+
+class TestResult(object):
+    """Holder for test result information.
+
+    Test results are automatically managed by the TestCase and TestSuite
+    classes, and do not need to be explicitly manipulated by writers of tests.
+
+    Each instance holds the total number of tests run, and collections of
+    failures and errors that occurred among those test runs. The collections
+    contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
+    formatted traceback of the error that occurred.
+    """
+    _previousTestClass = None
+    _testRunEntered = False
+    _moduleSetUpFailed = False
+    def __init__(self, stream=None, descriptions=None, verbosity=None):
+        self.failfast = False
+        self.failures = []
+        self.errors = []
+        self.testsRun = 0
+        self.skipped = []
+        self.expectedFailures = []
+        self.unexpectedSuccesses = []
+        self.shouldStop = False
+        self.buffer = False
+        self._stdout_buffer = None
+        self._stderr_buffer = None
+        self._original_stdout = sys.stdout
+        self._original_stderr = sys.stderr
+        self._mirrorOutput = False
+
+    def printErrors(self):
+        "Called by TestRunner after test run"
+
+    def startTest(self, test):
+        "Called when the given test is about to be run"
+        self.testsRun += 1
+        self._mirrorOutput = False
+        self._setupStdout()
+
+    def _setupStdout(self):
+        if self.buffer:
+            if self._stderr_buffer is None:
+                self._stderr_buffer = StringIO()
+                self._stdout_buffer = StringIO()
+            sys.stdout = self._stdout_buffer
+            sys.stderr = self._stderr_buffer
+
+    def startTestRun(self):
+        """Called once before any tests are executed.
+
+        See startTest for a method called before each test.
+        """
+
+    def stopTest(self, test):
+        """Called when the given test has been run"""
+        self._restoreStdout()
+        self._mirrorOutput = False
+
+    def _restoreStdout(self):
+        if self.buffer:
+            if self._mirrorOutput:
+                output = sys.stdout.getvalue()
+                error = sys.stderr.getvalue()
+                if output:
+                    if not output.endswith('\n'):
+                        output += '\n'
+                    self._original_stdout.write(STDOUT_LINE % output)
+                if error:
+                    if not error.endswith('\n'):
+                        error += '\n'
+                    self._original_stderr.write(STDERR_LINE % error)
+
+            sys.stdout = self._original_stdout
+            sys.stderr = self._original_stderr
+            self._stdout_buffer.seek(0)
+            self._stdout_buffer.truncate()
+            self._stderr_buffer.seek(0)
+            self._stderr_buffer.truncate()
+
+    def stopTestRun(self):
+        """Called once after all tests are executed.
+
+        See stopTest for a method called after each test.
+        """
+
+    @failfast
+    def addError(self, test, err):
+        """Called when an error has occurred. 'err' is a tuple of values as
+        returned by sys.exc_info().
+        """
+        self.errors.append((test, self._exc_info_to_string(err, test)))
+        self._mirrorOutput = True
+
+    @failfast
+    def addFailure(self, test, err):
+        """Called when an error has occurred. 'err' is a tuple of values as
+        returned by sys.exc_info()."""
+        self.failures.append((test, self._exc_info_to_string(err, test)))
+        self._mirrorOutput = True
+
+    def addSuccess(self, test):
+        "Called when a test has completed successfully"
+        pass
+
+    def addSkip(self, test, reason):
+        """Called when a test is skipped."""
+        self.skipped.append((test, reason))
+
+    def addExpectedFailure(self, test, err):
+        """Called when an expected failure/error occured."""
+        self.expectedFailures.append(
+            (test, self._exc_info_to_string(err, test)))
+
+    @failfast
+    def addUnexpectedSuccess(self, test):
+        """Called when a test was expected to fail, but succeed."""
+        self.unexpectedSuccesses.append(test)
+
+    def wasSuccessful(self):
+        "Tells whether or not this result was a success"
+        return len(self.failures) == len(self.errors) == 0
+
+    def stop(self):
+        "Indicates that the tests should be aborted"
+        self.shouldStop = True
+
+    def _exc_info_to_string(self, err, test):
+        """Converts a sys.exc_info()-style tuple of values into a string."""
+        exctype, value, tb = err
+        # Skip test runner traceback levels
+        while tb and self._is_relevant_tb_level(tb):
+            tb = tb.tb_next
+
+        if exctype is test.failureException:
+            # Skip assert*() traceback levels
+            length = self._count_relevant_tb_levels(tb)
+            msgLines = traceback.format_exception(exctype, value, tb, length)
+        else:
+            msgLines = traceback.format_exception(exctype, value, tb)
+
+        if self.buffer:
+            output = sys.stdout.getvalue()
+            error = sys.stderr.getvalue()
+            if output:
+                if not output.endswith('\n'):
+                    output += '\n'
+                msgLines.append(STDOUT_LINE % output)
+            if error:
+                if not error.endswith('\n'):
+                    error += '\n'
+                msgLines.append(STDERR_LINE % error)
+        return ''.join(msgLines)
+
+
+    def _is_relevant_tb_level(self, tb):
+        return '__unittest' in tb.tb_frame.f_globals
+
+    def _count_relevant_tb_levels(self, tb):
+        length = 0
+        while tb and not self._is_relevant_tb_level(tb):
+            length += 1
+            tb = tb.tb_next
+        return length
+
+    def __repr__(self):
+        return ("<%s run=%i errors=%i failures=%i>" %
+               (util.strclass(self.__class__), self.testsRun, len(self.errors),
+                len(self.failures)))
diff --git a/src/main/resources/PythonLibs/unittest/runner.py b/src/main/resources/PythonLibs/unittest/runner.py
new file mode 100644
index 0000000000000000000000000000000000000000..7632fe9823ce51242cda0f17f885b149183ffc81
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/runner.py
@@ -0,0 +1,196 @@
+"""Running tests"""
+
+import sys
+import time
+
+from . import result
+from .signals import registerResult
+
+__unittest = True
+
+
+class _WritelnDecorator(object):
+    """Used to decorate file-like objects with a handy 'writeln' method"""
+    def __init__(self,stream):
+        self.stream = stream
+
+    def __getattr__(self, attr):
+        if attr in ('stream', '__getstate__'):
+            raise AttributeError(attr)
+        return getattr(self.stream,attr)
+
+    def writeln(self, arg=None):
+        if arg:
+            self.write(arg)
+        self.write('\n') # text-mode streams translate to \r\n if needed
+
+
+class TextTestResult(result.TestResult):
+    """A test result class that can print formatted text results to a stream.
+
+    Used by TextTestRunner.
+    """
+    separator1 = '=' * 70
+    separator2 = '-' * 70
+
+    def __init__(self, stream, descriptions, verbosity):
+        super(TextTestResult, self).__init__(stream, descriptions, verbosity)
+        self.stream = stream
+        self.showAll = verbosity > 1
+        self.dots = verbosity == 1
+        self.descriptions = descriptions
+
+    def getDescription(self, test):
+        doc_first_line = test.shortDescription()
+        if self.descriptions and doc_first_line:
+            return '\n'.join((str(test), doc_first_line))
+        else:
+            return str(test)
+
+    def startTest(self, test):
+        super(TextTestResult, self).startTest(test)
+        if self.showAll:
+            self.stream.write(self.getDescription(test))
+            self.stream.write(" ... ")
+            self.stream.flush()
+
+    def addSuccess(self, test):
+        super(TextTestResult, self).addSuccess(test)
+        if self.showAll:
+            self.stream.writeln("ok")
+        elif self.dots:
+            self.stream.write('.')
+            self.stream.flush()
+
+    def addError(self, test, err):
+        super(TextTestResult, self).addError(test, err)
+        if self.showAll:
+            self.stream.writeln("ERROR")
+        elif self.dots:
+            self.stream.write('E')
+            self.stream.flush()
+
+    def addFailure(self, test, err):
+        super(TextTestResult, self).addFailure(test, err)
+        if self.showAll:
+            self.stream.writeln("FAIL")
+        elif self.dots:
+            self.stream.write('F')
+            self.stream.flush()
+
+    def addSkip(self, test, reason):
+        super(TextTestResult, self).addSkip(test, reason)
+        if self.showAll:
+            self.stream.writeln("skipped {0!r}".format(reason))
+        elif self.dots:
+            self.stream.write("s")
+            self.stream.flush()
+
+    def addExpectedFailure(self, test, err):
+        super(TextTestResult, self).addExpectedFailure(test, err)
+        if self.showAll:
+            self.stream.writeln("expected failure")
+        elif self.dots:
+            self.stream.write("x")
+            self.stream.flush()
+
+    def addUnexpectedSuccess(self, test):
+        super(TextTestResult, self).addUnexpectedSuccess(test)
+        if self.showAll:
+            self.stream.writeln("unexpected success")
+        elif self.dots:
+            self.stream.write("u")
+            self.stream.flush()
+
+    def printErrors(self):
+        if self.dots or self.showAll:
+            self.stream.writeln()
+        self.printErrorList('ERROR', self.errors)
+        self.printErrorList('FAIL', self.failures)
+
+    def printErrorList(self, flavour, errors):
+        for test, err in errors:
+            self.stream.writeln(self.separator1)
+            self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
+            self.stream.writeln(self.separator2)
+            self.stream.writeln("%s" % err)
+
+
+class TextTestRunner(object):
+    """A test runner class that displays results in textual form.
+
+    It prints out the names of tests as they are run, errors as they
+    occur, and a summary of the results at the end of the test run.
+    """
+    resultclass = TextTestResult
+
+    def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
+                 failfast=False, buffer=False, resultclass=None):
+        self.stream = _WritelnDecorator(stream)
+        self.descriptions = descriptions
+        self.verbosity = verbosity
+        self.failfast = failfast
+        self.buffer = buffer
+        if resultclass is not None:
+            self.resultclass = resultclass
+
+    def _makeResult(self):
+        return self.resultclass(self.stream, self.descriptions, self.verbosity)
+
+    def run(self, test):
+        "Run the given test case or test suite."
+        result = self._makeResult()
+        registerResult(result)
+        result.failfast = self.failfast
+        result.buffer = self.buffer
+        startTime = time.time()
+        startTestRun = getattr(result, 'startTestRun', None)
+        if startTestRun is not None:
+            startTestRun()
+        try:
+            test(result)
+        finally:
+            stopTestRun = getattr(result, 'stopTestRun', None)
+            if stopTestRun is not None:
+                stopTestRun()
+        stopTime = time.time()
+        timeTaken = stopTime - startTime
+        result.printErrors()
+        if hasattr(result, 'separator2'):
+            self.stream.writeln(result.separator2)
+        run = result.testsRun
+        self.stream.writeln("Ran %d test%s in %.3fs" %
+                            (run, run != 1 and "s" or "", timeTaken))
+        self.stream.writeln()
+
+        expectedFails = unexpectedSuccesses = skipped = 0
+        try:
+            results = map(len, (result.expectedFailures,
+                                result.unexpectedSuccesses,
+                                result.skipped))
+        except AttributeError:
+            pass
+        else:
+            expectedFails, unexpectedSuccesses, skipped = results
+
+        infos = []
+        if not result.wasSuccessful():
+            self.stream.write("FAILED")
+            failed, errored = map(len, (result.failures, result.errors))
+            if failed:
+                infos.append("failures=%d" % failed)
+            if errored:
+                infos.append("errors=%d" % errored)
+        else:
+            self.stream.write("OK")
+        if skipped:
+            infos.append("skipped=%d" % skipped)
+        if expectedFails:
+            infos.append("expected failures=%d" % expectedFails)
+        if unexpectedSuccesses:
+            infos.append("unexpected successes=%d" % unexpectedSuccesses)
+        if infos:
+            self.stream.writeln(" (%s)" % (", ".join(infos),))
+        else:
+            self.stream.write("\n")
+        return result
diff --git a/src/main/resources/PythonLibs/unittest/signals.py b/src/main/resources/PythonLibs/unittest/signals.py
new file mode 100644
index 0000000000000000000000000000000000000000..e6a5fc524397121e170bd5a888957374b91ba946
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/signals.py
@@ -0,0 +1,71 @@
+import signal
+import weakref
+
+from functools import wraps
+
+__unittest = True
+
+
+class _InterruptHandler(object):
+    def __init__(self, default_handler):
+        self.called = False
+        self.original_handler = default_handler
+        if isinstance(default_handler, int):
+            if default_handler == signal.SIG_DFL:
+                # Pretend it's signal.default_int_handler instead.
+                default_handler = signal.default_int_handler
+            elif default_handler == signal.SIG_IGN:
+                # Not quite the same thing as SIG_IGN, but the closest we
+                # can make it: do nothing.
+                def default_handler(unused_signum, unused_frame):
+                    pass
+            else:
+                raise TypeError("expected SIGINT signal handler to be "
+                                "signal.SIG_IGN, signal.SIG_DFL, or a "
+                                "callable object")
+        self.default_handler = default_handler
+
+    def __call__(self, signum, frame):
+        installed_handler = signal.getsignal(signal.SIGINT)
+        if installed_handler is not self:
+            # if we aren't the installed handler, then delegate immediately
+            # to the default handler
+            self.default_handler(signum, frame)
+
+        if self.called:
+            self.default_handler(signum, frame)
+        self.called = True
+        for result in _results.keys():
+            result.stop()
+
+_results = weakref.WeakKeyDictionary()
+def registerResult(result):
+    _results[result] = 1
+
+def removeResult(result):
+    return bool(_results.pop(result, None))
+
+_interrupt_handler = None
+def installHandler():
+    global _interrupt_handler
+    if _interrupt_handler is None:
+        default_handler = signal.getsignal(signal.SIGINT)
+        _interrupt_handler = _InterruptHandler(default_handler)
+        signal.signal(signal.SIGINT, _interrupt_handler)
+
+
+def removeHandler(method=None):
+    if method is not None:
+        @wraps(method)
+        def inner(*args, **kwargs):
+            initial = signal.getsignal(signal.SIGINT)
+            removeHandler()
+            try:
+                return method(*args, **kwargs)
+            finally:
+                signal.signal(signal.SIGINT, initial)
+        return inner
+
+    global _interrupt_handler
+    if _interrupt_handler is not None:
+        signal.signal(signal.SIGINT, _interrupt_handler.original_handler)
diff --git a/src/main/resources/PythonLibs/unittest/suite.py b/src/main/resources/PythonLibs/unittest/suite.py
new file mode 100644
index 0000000000000000000000000000000000000000..633af5cb08552b3a2c4ed4326658d653b04f9718
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/suite.py
@@ -0,0 +1,303 @@
+"""TestSuite"""
+
+import sys
+
+from . import case
+from . import util
+
+__unittest = True
+
+
+def _call_if_exists(parent, attr):
+    func = getattr(parent, attr, lambda: None)
+    func()
+
+
+class BaseTestSuite(object):
+    """A simple test suite that doesn't provide class or module shared fixtures.
+    """
+    def __init__(self, tests=()):
+        self._tests = []
+        self.addTests(tests)
+
+    def __repr__(self):
+        return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))
+
+    def __eq__(self, other):
+        if not isinstance(other, self.__class__):
+            return NotImplemented
+        return list(self) == list(other)
+
+    def __ne__(self, other):
+        return not self == other
+
+    # Can't guarantee hash invariant, so flag as unhashable
+    __hash__ = None
+
+    def __iter__(self):
+        return iter(self._tests)
+
+    def countTestCases(self):
+        cases = 0
+        for test in self:
+            cases += test.countTestCases()
+        return cases
+
+    def addTest(self, test):
+        # sanity checks
+        if not hasattr(test, '__call__'):
+            raise TypeError("{} is not callable".format(repr(test)))
+        if isinstance(test, type) and issubclass(test,
+                                                 (case.TestCase, TestSuite)):
+            raise TypeError("TestCases and TestSuites must be instantiated "
+                            "before passing them to addTest()")
+        self._tests.append(test)
+
+    def addTests(self, tests):
+        if isinstance(tests, basestring):
+            raise TypeError("tests must be an iterable of tests, not a string")
+        for test in tests:
+            self.addTest(test)
+
+    def run(self, result):
+        for test in self:
+            if result.shouldStop:
+                break
+            test(result)
+        return result
+
+    def __call__(self, *args, **kwds):
+        return self.run(*args, **kwds)
+
+    def debug(self):
+        """Run the tests without collecting errors in a TestResult"""
+        for test in self:
+            test.debug()
+
+
+class TestSuite(BaseTestSuite):
+    """A test suite is a composite test consisting of a number of TestCases.
+
+    For use, create an instance of TestSuite, then add test case instances.
+    When all tests have been added, the suite can be passed to a test
+    runner, such as TextTestRunner. It will run the individual test cases
+    in the order in which they were added, aggregating the results. When
+    subclassing, do not forget to call the base class constructor.
+    """
+
+    def run(self, result, debug=False):
+        topLevel = False
+        if getattr(result, '_testRunEntered', False) is False:
+            result._testRunEntered = topLevel = True
+
+        for test in self:
+            if result.shouldStop:
+                break
+
+            if _isnotsuite(test):
+                self._tearDownPreviousClass(test, result)
+                self._handleModuleFixture(test, result)
+                self._handleClassSetUp(test, result)
+                result._previousTestClass = test.__class__
+
+                if (getattr(test.__class__, '_classSetupFailed', False) or
+                    getattr(result, '_moduleSetUpFailed', False)):
+                    continue
+
+            if not debug:
+                test(result)
+            else:
+                test.debug()
+
+        if topLevel:
+            self._tearDownPreviousClass(None, result)
+            self._handleModuleTearDown(result)
+            result._testRunEntered = False
+        return result
+
+    def debug(self):
+        """Run the tests without collecting errors in a TestResult"""
+        debug = _DebugResult()
+        self.run(debug, True)
+
+    ################################
+
+    def _handleClassSetUp(self, test, result):
+        previousClass = getattr(result, '_previousTestClass', None)
+        currentClass = test.__class__
+        if currentClass == previousClass:
+            return
+        if result._moduleSetUpFailed:
+            return
+        if getattr(currentClass, "__unittest_skip__", False):
+            return
+
+        try:
+            currentClass._classSetupFailed = False
+        except TypeError:
+            # test may actually be a function
+            # so its class will be a builtin-type
+            pass
+
+        setUpClass = getattr(currentClass, 'setUpClass', None)
+        if setUpClass is not None:
+            _call_if_exists(result, '_setupStdout')
+            try:
+                setUpClass()
+            except Exception as e:
+                if isinstance(result, _DebugResult):
+                    raise
+                currentClass._classSetupFailed = True
+                className = util.strclass(currentClass)
+                errorName = 'setUpClass (%s)' % className
+                self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
+
+    def _get_previous_module(self, result):
+        previousModule = None
+        previousClass = getattr(result, '_previousTestClass', None)
+        if previousClass is not None:
+            previousModule = previousClass.__module__
+        return previousModule
+
+
+    def _handleModuleFixture(self, test, result):
+        previousModule = self._get_previous_module(result)
+        currentModule = test.__class__.__module__
+        if currentModule == previousModule:
+            return
+
+        self._handleModuleTearDown(result)
+
+        result._moduleSetUpFailed = False
+        try:
+            module = sys.modules[currentModule]
+        except KeyError:
+            return
+        setUpModule = getattr(module, 'setUpModule', None)
+        if setUpModule is not None:
+            _call_if_exists(result, '_setupStdout')
+            try:
+                setUpModule()
+            except Exception, e:
+                if isinstance(result, _DebugResult):
+                    raise
+                result._moduleSetUpFailed = True
+                errorName = 'setUpModule (%s)' % currentModule
+                self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
+
+    def _addClassOrModuleLevelException(self, result, exception, errorName):
+        error = _ErrorHolder(errorName)
+        addSkip = getattr(result, 'addSkip', None)
+        if addSkip is not None and isinstance(exception, case.SkipTest):
+            addSkip(error, str(exception))
+        else:
+            result.addError(error, sys.exc_info())
+
+    def _handleModuleTearDown(self, result):
+        previousModule = self._get_previous_module(result)
+        if previousModule is None:
+            return
+        if result._moduleSetUpFailed:
+            return
+
+        try:
+            module = sys.modules[previousModule]
+        except KeyError:
+            return
+
+        tearDownModule = getattr(module, 'tearDownModule', None)
+        if tearDownModule is not None:
+            _call_if_exists(result, '_setupStdout')
+            try:
+                tearDownModule()
+            except Exception as e:
+                if isinstance(result, _DebugResult):
+                    raise
+                errorName = 'tearDownModule (%s)' % previousModule
+                self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
+
+    def _tearDownPreviousClass(self, test, result):
+        previousClass = getattr(result, '_previousTestClass', None)
+        currentClass = test.__class__
+        if currentClass == previousClass:
+            return
+        if getattr(previousClass, '_classSetupFailed', False):
+            return
+        if getattr(result, '_moduleSetUpFailed', False):
+            return
+        if getattr(previousClass, "__unittest_skip__", False):
+            return
+
+        tearDownClass = getattr(previousClass, 'tearDownClass', None)
+        if tearDownClass is not None:
+            _call_if_exists(result, '_setupStdout')
+            try:
+                tearDownClass()
+            except Exception, e:
+                if isinstance(result, _DebugResult):
+                    raise
+                className = util.strclass(previousClass)
+                errorName = 'tearDownClass (%s)' % className
+                self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
+
+
+class _ErrorHolder(object):
+    """
+    Placeholder for a TestCase inside a result. As far as a TestResult
+    is concerned, this looks exactly like a unit test. Used to insert
+    arbitrary errors into a test suite run.
+    """
+    # Inspired by the ErrorHolder from Twisted:
+    # http://twistedmatrix.com/trac/browser/trunk/twisted/trial/runner.py
+
+    # attribute used by TestResult._exc_info_to_string
+    failureException = None
+
+    def __init__(self, description):
+        self.description = description
+
+    def id(self):
+        return self.description
+
+    def shortDescription(self):
+        return None
+
+    def __repr__(self):
+        return "<ErrorHolder description=%r>" % (self.description,)
+
+    def __str__(self):
+        return self.id()
+
+    def run(self, result):
+        # could call result.addError(...) - but this test-like object
+        # shouldn't be run anyway
+        pass
+
+    def __call__(self, result):
+        return self.run(result)
+
+    def countTestCases(self):
+        return 0
+
+def _isnotsuite(test):
+    "A crude way to tell apart testcases and suites with duck-typing"
+    try:
+        iter(test)
+    except TypeError:
+        return True
+    return False
+
+
+class _DebugResult(object):
+    "Used by the TestSuite to hold previous class when running in debug."
+    _previousTestClass = None
+    _moduleSetUpFailed = False
+    shouldStop = False
diff --git a/src/main/resources/PythonLibs/unittest/util.py b/src/main/resources/PythonLibs/unittest/util.py
new file mode 100644
index 0000000000000000000000000000000000000000..220a024e9038bdfe662b3bd8ea2e2fae9641ca72
--- /dev/null
+++ b/src/main/resources/PythonLibs/unittest/util.py
@@ -0,0 +1,156 @@
+"""Various utility functions."""
+from collections import namedtuple, OrderedDict
+
+
+__unittest = True
+
+_MAX_LENGTH = 80
+def safe_repr(obj, short=False):
+    try:
+        result = repr(obj)
+    except Exception:
+        result = object.__repr__(obj)
+    if not short or len(result) < _MAX_LENGTH:
+        return result
+    return result[:_MAX_LENGTH] + ' [truncated]...'
+
+
+def strclass(cls):
+    return "%s.%s" % (cls.__module__, cls.__name__)
+
+def sorted_list_difference(expected, actual):
+    """Finds elements in only one or the other of two, sorted input lists.
+
+    Returns a two-element tuple of lists.    The first list contains those
+    elements in the "expected" list but not in the "actual" list, and the
+    second contains those elements in the "actual" list but not in the
+    "expected" list.    Duplicate elements in either input list are ignored.
+    """
+    i = j = 0
+    missing = []
+    unexpected = []
+    while True:
+        try:
+            e = expected[i]
+            a = actual[j]
+            if e < a:
+                missing.append(e)
+                i += 1
+                while expected[i] == e:
+                    i += 1
+            elif e > a:
+                unexpected.append(a)
+                j += 1
+                while actual[j] == a:
+                    j += 1
+            else:
+                i += 1
+                try:
+                    while expected[i] == e:
+                        i += 1
+                finally:
+                    j += 1
+                    while actual[j] == a:
+                        j += 1
+        except IndexError:
+            missing.extend(expected[i:])
+            unexpected.extend(actual[j:])
+            break
+    return missing, unexpected
+
+
+def unorderable_list_difference(expected, actual, ignore_duplicate=False):
+    """Same behavior as sorted_list_difference but
+    for lists of unorderable items (like dicts).
+
+    As it does a linear search per item (remove) it
+    has O(n*n) performance.
+    """
+    missing = []
+    unexpected = []
+    while expected:
+        item = expected.pop()
+        try:
+            actual.remove(item)
+        except ValueError:
+            missing.append(item)
+        if ignore_duplicate:
+            for lst in expected, actual:
+                try:
+                    while True:
+                        lst.remove(item)
+                except ValueError:
+                    pass
+    if ignore_duplicate:
+        while actual:
+            item = actual.pop()
+            unexpected.append(item)
+            try:
+                while True:
+                    actual.remove(item)
+            except ValueError:
+                pass
+        return missing, unexpected
+
+    # anything left in actual is unexpected
+    return missing, actual
+
+_Mismatch = namedtuple('Mismatch', 'actual expected value')
+
+def _count_diff_all_purpose(actual, expected):
+    'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
+    # elements need not be hashable
+    s, t = list(actual), list(expected)
+    m, n = len(s), len(t)
+    NULL = object()
+    result = []
+    for i, elem in enumerate(s):
+        if elem is NULL:
+            continue
+        cnt_s = cnt_t = 0
+        for j in range(i, m):
+            if s[j] == elem:
+                cnt_s += 1
+                s[j] = NULL
+        for j, other_elem in enumerate(t):
+            if other_elem == elem:
+                cnt_t += 1
+                t[j] = NULL
+        if cnt_s != cnt_t:
+            diff = _Mismatch(cnt_s, cnt_t, elem)
+            result.append(diff)
+
+    for i, elem in enumerate(t):
+        if elem is NULL:
+            continue
+        cnt_t = 0
+        for j in range(i, n):
+            if t[j] == elem:
+                cnt_t += 1
+                t[j] = NULL
+        diff = _Mismatch(0, cnt_t, elem)
+        result.append(diff)
+    return result
+
+def _ordered_count(iterable):
+    'Return dict of element counts, in the order they were first seen'
+    c = OrderedDict()
+    for elem in iterable:
+        c[elem] = c.get(elem, 0) + 1
+    return c
+
+def _count_diff_hashable(actual, expected):
+    'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
+    # elements must be hashable
+    s, t = _ordered_count(actual), _ordered_count(expected)
+    result = []
+    for elem, cnt_s in s.items():
+        cnt_t = t.get(elem, 0)
+        if cnt_s != cnt_t:
+            diff = _Mismatch(cnt_s, cnt_t, elem)
+            result.append(diff)
+    for elem, cnt_t in t.items():
+        if elem not in s:
+            diff = _Mismatch(0, cnt_t, elem)
+            result.append(diff)
+    return result
diff --git a/src/main/resources/PythonLibs/urllib.py b/src/main/resources/PythonLibs/urllib.py
new file mode 100644
index 0000000000000000000000000000000000000000..55da67738358e8a051909c231f31d6d1b66d307a
--- /dev/null
+++ b/src/main/resources/PythonLibs/urllib.py
@@ -0,0 +1,1602 @@
+"""Open an arbitrary URL.
+
+See the following document for more info on URLs:
+"Names and Addresses, URIs, URLs, URNs, URCs", at
+http://www.w3.org/pub/WWW/Addressing/Overview.html
+
+See also the HTTP spec (from which the error codes are derived):
+"HTTP - Hypertext Transfer Protocol", at
+http://www.w3.org/pub/WWW/Protocols/
+
+Related standards and specs:
+- RFC1808: the "relative URL" spec. (authoritative status)
+- RFC1738 - the "URL standard". (authoritative status)
+- RFC1630 - the "URI spec". (informational status)
+
+The object returned by URLopener().open(file) will differ per
+protocol.  All you know is that is has methods read(), readline(),
+readlines(), fileno(), close() and info().  The read*(), fileno()
+and close() methods work like those of open files.
+The info() method returns a mimetools.Message object which can be
+used to query various info about the object, if available.
+(mimetools.Message objects are queried with the getheader() method.)
+"""
+
+import string
+import socket
+import os
+import time
+import sys
+import base64
+
+from urlparse import urljoin as basejoin
+
+__all__ = ["urlopen", "URLopener", "FancyURLopener", "urlretrieve",
+           "urlcleanup", "quote", "quote_plus", "unquote", "unquote_plus",
+           "urlencode", "url2pathname", "pathname2url", "splittag",
+           "localhost", "thishost", "ftperrors", "basejoin", "unwrap",
+           "splittype", "splithost", "splituser", "splitpasswd", "splitport",
+           "splitnport", "splitquery", "splitattr", "splitvalue",
+           "getproxies"]
+
+__version__ = '1.17'    # XXX This version is not always updated :-(
+
+MAXFTPCACHE = 10        # Trim the ftp cache beyond this size
+
+# Helper for non-unix systems
+if (os._name if sys.platform.startswith('java') else os.name) == 'nt':
+    from nturl2path import url2pathname, pathname2url
+elif os.name == 'riscos':
+    from rourl2path import url2pathname, pathname2url
+else:
+    def url2pathname(pathname):
+        """OS-specific conversion from a relative URL of the 'file' scheme
+        to a file system path; not recommended for general use."""
+        return unquote(pathname)
+
+    def pathname2url(pathname):
+        """OS-specific conversion from a file system path to a relative URL
+        of the 'file' scheme; not recommended for general use."""
+        return quote(pathname)
+
+# This really consists of two pieces:
+# (1) a class which handles opening of all sorts of URLs
+#     (plus assorted utilities etc.)
+# (2) a set of functions for parsing URLs
+# XXX Should these be separated out into different modules?
+
+
+# Shortcut for basic usage
+_urlopener = None
+def urlopen(url, data=None, proxies=None):
+    """Create a file-like object for the specified URL to read from."""
+    from warnings import warnpy3k
+    warnpy3k("urllib.urlopen() has been removed in Python 3.0 in "
+             "favor of urllib2.urlopen()", stacklevel=2)
+
+    global _urlopener
+    if proxies is not None:
+        opener = FancyURLopener(proxies=proxies)
+    elif not _urlopener:
+        opener = FancyURLopener()
+        _urlopener = opener
+    else:
+        opener = _urlopener
+    if data is None:
+        return opener.open(url)
+    else:
+        return opener.open(url, data)
+def urlretrieve(url, filename=None, reporthook=None, data=None):
+    global _urlopener
+    if not _urlopener:
+        _urlopener = FancyURLopener()
+    return _urlopener.retrieve(url, filename, reporthook, data)
+def urlcleanup():
+    if _urlopener:
+        _urlopener.cleanup()
+    _safe_quoters.clear()
+    ftpcache.clear()
+
+# check for SSL
+try:
+    import ssl
+except:
+    _have_ssl = False
+else:
+    _have_ssl = True
+
+# exception raised when downloaded size does not match content-length
+class ContentTooShortError(IOError):
+    def __init__(self, message, content):
+        IOError.__init__(self, message)
+        self.content = content
+
+ftpcache = {}
+class URLopener:
+    """Class to open URLs.
+    This is a class rather than just a subroutine because we may need
+    more than one set of global protocol-specific options.
+    Note -- this is a base class for those who don't want the
+    automatic handling of errors type 302 (relocated) and 401
+    (authorization needed)."""
+
+    __tempfiles = None
+
+    version = "Python-urllib/%s" % __version__
+
+    # Constructor
+    def __init__(self, proxies=None, **x509):
+        if proxies is None:
+            proxies = getproxies()
+        assert hasattr(proxies, 'has_key'), "proxies must be a mapping"
+        self.proxies = proxies
+        self.key_file = x509.get('key_file')
+        self.cert_file = x509.get('cert_file')
+        self.addheaders = [('User-Agent', self.version)]
+        self.__tempfiles = []
+        self.__unlink = os.unlink # See cleanup()
+        self.tempcache = None
+        # Undocumented feature: if you assign {} to tempcache,
+        # it is used to cache files retrieved with
+        # self.retrieve().  This is not enabled by default
+        # since it does not work for changing documents (and I
+        # haven't got the logic to check expiration headers
+        # yet).
+        self.ftpcache = ftpcache
+        # Undocumented feature: you can use a different
+        # ftp cache by assigning to the .ftpcache member;
+        # in case you want logically independent URL openers
+        # XXX This is not threadsafe.  Bah.
+
+    def __del__(self):
+        self.close()
+
+    def close(self):
+        self.cleanup()
+
+    def cleanup(self):
+        # This code sometimes runs when the rest of this module
+        # has already been deleted, so it can't use any globals
+        # or import anything.
+        if self.__tempfiles:
+            for file in self.__tempfiles:
+                try:
+                    self.__unlink(file)
+                except OSError:
+                    pass
+            del self.__tempfiles[:]
+        if self.tempcache:
+            self.tempcache.clear()
+
+    def addheader(self, *args):
+        """Add a header to be used by the HTTP interface only
+        e.g. u.addheader('Accept', 'sound/basic')"""
+        self.addheaders.append(args)
+
+    # External interface
+    def open(self, fullurl, data=None):
+        """Use URLopener().open(file) instead of open(file, 'r')."""
+        fullurl = unwrap(toBytes(fullurl))
+        # percent encode url, fixing lame server errors for e.g, like space
+        # within url paths.
+        fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]|")
+        if self.tempcache and fullurl in self.tempcache:
+            filename, headers = self.tempcache[fullurl]
+            fp = open(filename, 'rb')
+            return addinfourl(fp, headers, fullurl)
+        urltype, url = splittype(fullurl)
+        if not urltype:
+            urltype = 'file'
+        if urltype in self.proxies:
+            proxy = self.proxies[urltype]
+            urltype, proxyhost = splittype(proxy)
+            host, selector = splithost(proxyhost)
+            url = (host, fullurl) # Signal special case to open_*()
+        else:
+            proxy = None
+        name = 'open_' + urltype
+        self.type = urltype
+        name = name.replace('-', '_')
+        if not hasattr(self, name):
+            if proxy:
+                return self.open_unknown_proxy(proxy, fullurl, data)
+            else:
+                return self.open_unknown(fullurl, data)
+        try:
+            if data is None:
+                return getattr(self, name)(url)
+            else:
+                return getattr(self, name)(url, data)
+        except socket.error, msg:
+            raise IOError, ('socket error', msg), sys.exc_info()[2]
+
+    def open_unknown(self, fullurl, data=None):
+        """Overridable interface to open unknown URL type."""
+        type, url = splittype(fullurl)
+        raise IOError, ('url error', 'unknown url type', type)
+
+    def open_unknown_proxy(self, proxy, fullurl, data=None):
+        """Overridable interface to open unknown URL type."""
+        type, url = splittype(fullurl)
+        raise IOError, ('url error', 'invalid proxy for %s' % type, proxy)
+
+    # External interface
+    def retrieve(self, url, filename=None, reporthook=None, data=None):
+        """retrieve(url) returns (filename, headers) for a local object
+        or (tempfilename, headers) for a remote object."""
+        url = unwrap(toBytes(url))
+        if self.tempcache and url in self.tempcache:
+            return self.tempcache[url]
+        type, url1 = splittype(url)
+        if filename is None and (not type or type == 'file'):
+            try:
+                fp = self.open_local_file(url1)
+                hdrs = fp.info()
+                fp.close()
+                return url2pathname(splithost(url1)[1]), hdrs
+            except IOError:
+                pass
+        fp = self.open(url, data)
+        try:
+            headers = fp.info()
+            if filename:
+                tfp = open(filename, 'wb')
+            else:
+                import tempfile
+                garbage, path = splittype(url)
+                garbage, path = splithost(path or "")
+                path, garbage = splitquery(path or "")
+                path, garbage = splitattr(path or "")
+                suffix = os.path.splitext(path)[1]
+                (fd, filename) = tempfile.mkstemp(suffix)
+                self.__tempfiles.append(filename)
+                tfp = os.fdopen(fd, 'wb')
+            try:
+                result = filename, headers
+                if self.tempcache is not None:
+                    self.tempcache[url] = result
+                bs = 1024*8
+                size = -1
+                read = 0
+                blocknum = 0
+                if "content-length" in headers:
+                    size = int(headers["Content-Length"])
+                if reporthook:
+                    reporthook(blocknum, bs, size)
+                while 1:
+                    block = fp.read(bs)
+                    if block == "":
+                        break
+                    read += len(block)
+                    tfp.write(block)
+                    blocknum += 1
+                    if reporthook:
+                        reporthook(blocknum, bs, size)
+            finally:
+                tfp.close()
+        finally:
+            fp.close()
+
+        # raise exception if actual size does not match content-length header
+        if size >= 0 and read < size:
+            raise ContentTooShortError("retrieval incomplete: got only %i out "
+                                       "of %i bytes" % (read, size), result)
+
+        return result
+
+    # Each method named open_<type> knows how to open that type of URL
+
+    def open_http(self, url, data=None):
+        """Use HTTP protocol."""
+        import httplib
+        user_passwd = None
+        proxy_passwd= None
+        if isinstance(url, str):
+            host, selector = splithost(url)
+            if host:
+                user_passwd, host = splituser(host)
+                host = unquote(host)
+            realhost = host
+        else:
+            host, selector = url
+            # check whether the proxy contains authorization information
+            proxy_passwd, host = splituser(host)
+            # now we proceed with the url we want to obtain
+            urltype, rest = splittype(selector)
+            url = rest
+            user_passwd = None
+            if urltype.lower() != 'http':
+                realhost = None
+            else:
+                realhost, rest = splithost(rest)
+                if realhost:
+                    user_passwd, realhost = splituser(realhost)
+                if user_passwd:
+                    selector = "%s://%s%s" % (urltype, realhost, rest)
+                if proxy_bypass(realhost):
+                    host = realhost
+
+            #print "proxy via http:", host, selector
+        if not host: raise IOError, ('http error', 'no host given')
+
+        if proxy_passwd:
+            proxy_passwd = unquote(proxy_passwd)
+            proxy_auth = base64.b64encode(proxy_passwd).strip()
+        else:
+            proxy_auth = None
+
+        if user_passwd:
+            user_passwd = unquote(user_passwd)
+            auth = base64.b64encode(user_passwd).strip()
+        else:
+            auth = None
+        h = httplib.HTTP(host)
+        if data is not None:
+            h.putrequest('POST', selector)
+            h.putheader('Content-Type', 'application/x-www-form-urlencoded')
+            h.putheader('Content-Length', '%d' % len(data))
+        else:
+            h.putrequest('GET', selector)
+        if proxy_auth: h.putheader('Proxy-Authorization', 'Basic %s' % proxy_auth)
+        if auth: h.putheader('Authorization', 'Basic %s' % auth)
+        if realhost: h.putheader('Host', realhost)
+        for args in self.addheaders: h.putheader(*args)
+        h.endheaders(data)
+        errcode, errmsg, headers = h.getreply()
+        fp = h.getfile()
+        if errcode == -1:
+            if fp: fp.close()
+            # something went wrong with the HTTP status line
+            raise IOError, ('http protocol error', 0,
+                            'got a bad status line', None)
+        # According to RFC 2616, "2xx" code indicates that the client's
+        # request was successfully received, understood, and accepted.
+        if (200 <= errcode < 300):
+            return addinfourl(fp, headers, "http:" + url, errcode)
+        else:
+            if data is None:
+                return self.http_error(url, fp, errcode, errmsg, headers)
+            else:
+                return self.http_error(url, fp, errcode, errmsg, headers, data)
+
+    def http_error(self, url, fp, errcode, errmsg, headers, data=None):
+        """Handle http errors.
+        Derived class can override this, or provide specific handlers
+        named http_error_DDD where DDD is the 3-digit error code."""
+        # First check if there's a specific handler for this error
+        name = 'http_error_%d' % errcode
+        if hasattr(self, name):
+            method = getattr(self, name)
+            if data is None:
+                result = method(url, fp, errcode, errmsg, headers)
+            else:
+                result = method(url, fp, errcode, errmsg, headers, data)
+            if result: return result
+        return self.http_error_default(url, fp, errcode, errmsg, headers)
+
+    def http_error_default(self, url, fp, errcode, errmsg, headers):
+        """Default error handler: close the connection and raise IOError."""
+        fp.close()
+        raise IOError, ('http error', errcode, errmsg, headers)
+
+    if _have_ssl:
+        def open_https(self, url, data=None):
+            """Use HTTPS protocol."""
+
+            import httplib
+            user_passwd = None
+            proxy_passwd = None
+            if isinstance(url, str):
+                host, selector = splithost(url)
+                if host:
+                    user_passwd, host = splituser(host)
+                    host = unquote(host)
+                realhost = host
+            else:
+                host, selector = url
+                # here, we determine, whether the proxy contains authorization information
+                proxy_passwd, host = splituser(host)
+                urltype, rest = splittype(selector)
+                url = rest
+                user_passwd = None
+                if urltype.lower() != 'https':
+                    realhost = None
+                else:
+                    realhost, rest = splithost(rest)
+                    if realhost:
+                        user_passwd, realhost = splituser(realhost)
+                    if user_passwd:
+                        selector = "%s://%s%s" % (urltype, realhost, rest)
+                #print "proxy via https:", host, selector
+            if not host: raise IOError, ('https error', 'no host given')
+            if proxy_passwd:
+                proxy_passwd = unquote(proxy_passwd)
+                proxy_auth = base64.b64encode(proxy_passwd).strip()
+            else:
+                proxy_auth = None
+            if user_passwd:
+                user_passwd = unquote(user_passwd)
+                auth = base64.b64encode(user_passwd).strip()
+            else:
+                auth = None
+            h = httplib.HTTPS(host, 0,
+                              key_file=self.key_file,
+                              cert_file=self.cert_file)
+            if data is not None:
+                h.putrequest('POST', selector)
+                h.putheader('Content-Type',
+                            'application/x-www-form-urlencoded')
+                h.putheader('Content-Length', '%d' % len(data))
+            else:
+                h.putrequest('GET', selector)
+            if proxy_auth: h.putheader('Proxy-Authorization', 'Basic %s' % proxy_auth)
+            if auth: h.putheader('Authorization', 'Basic %s' % auth)
+            if realhost: h.putheader('Host', realhost)
+            for args in self.addheaders: h.putheader(*args)
+            h.endheaders(data)
+            errcode, errmsg, headers = h.getreply()
+            fp = h.getfile()
+            if errcode == -1:
+                if fp: fp.close()
+                # something went wrong with the HTTP status line
+                raise IOError, ('http protocol error', 0,
+                                'got a bad status line', None)
+            # According to RFC 2616, "2xx" code indicates that the client's
+            # request was successfully received, understood, and accepted.
+            if (200 <= errcode < 300):
+                return addinfourl(fp, headers, "https:" + url, errcode)
+            else:
+                if data is None:
+                    return self.http_error(url, fp, errcode, errmsg, headers)
+                else:
+                    return self.http_error(url, fp, errcode, errmsg, headers,
+                                           data)
+
+    def open_file(self, url):
+        """Use local file or FTP depending on form of URL."""
+        if not isinstance(url, str):
+            raise IOError, ('file error', 'proxy support for file protocol currently not implemented')
+        if url[:2] == '//' and url[2:3] != '/' and url[2:12].lower() != 'localhost/':
+            return self.open_ftp(url)
+        else:
+            return self.open_local_file(url)
+
+    def open_local_file(self, url):
+        """Use local file."""
+        import mimetypes, mimetools, email.utils
+        try:
+            from cStringIO import StringIO
+        except ImportError:
+            from StringIO import StringIO
+        host, file = splithost(url)
+        localname = url2pathname(file)
+        try:
+            stats = os.stat(localname)
+        except OSError, e:
+            raise IOError(e.errno, e.strerror, e.filename)
+        size = stats.st_size
+        modified = email.utils.formatdate(stats.st_mtime, usegmt=True)
+        mtype = mimetypes.guess_type(url)[0]
+        headers = mimetools.Message(StringIO(
+            'Content-Type: %s\nContent-Length: %d\nLast-modified: %s\n' %
+            (mtype or 'text/plain', size, modified)))
+        if not host:
+            urlfile = file
+            if file[:1] == '/':
+                urlfile = 'file://' + file
+            elif file[:2] == './':
+                raise ValueError("local file url may start with / or file:. Unknown url of type: %s" % url)
+            return addinfourl(open(localname, 'rb'),
+                              headers, urlfile)
+        host, port = splitport(host)
+        if not port \
+           and socket.gethostbyname(host) in (localhost(), thishost()):
+            urlfile = file
+            if file[:1] == '/':
+                urlfile = 'file://' + file
+            return addinfourl(open(localname, 'rb'),
+                              headers, urlfile)
+        raise IOError, ('local file error', 'not on local host')
+
+    def open_ftp(self, url):
+        """Use FTP protocol."""
+        if not isinstance(url, str):
+            raise IOError, ('ftp error', 'proxy support for ftp protocol currently not implemented')
+        import mimetypes, mimetools
+        try:
+            from cStringIO import StringIO
+        except ImportError:
+            from StringIO import StringIO
+        host, path = splithost(url)
+        if not host: raise IOError, ('ftp error', 'no host given')
+        host, port = splitport(host)
+        user, host = splituser(host)
+        if user: user, passwd = splitpasswd(user)
+        else: passwd = None
+        host = unquote(host)
+        user = user or ''
+        passwd = passwd or ''
+        host = socket.gethostbyname(host)
+        if not port:
+            import ftplib
+            port = ftplib.FTP_PORT
+        else:
+            port = int(port)
+        path, attrs = splitattr(path)
+        path = unquote(path)
+        dirs = path.split('/')
+        dirs, file = dirs[:-1], dirs[-1]
+        if dirs and not dirs[0]: dirs = dirs[1:]
+        if dirs and not dirs[0]: dirs[0] = '/'
+        key = user, host, port, '/'.join(dirs)
+        # XXX thread unsafe!
+        if len(self.ftpcache) > MAXFTPCACHE:
+            # Prune the cache, rather arbitrarily
+            for k in self.ftpcache.keys():
+                if k != key:
+                    v = self.ftpcache[k]
+                    del self.ftpcache[k]
+                    v.close()
+        try:
+            if not key in self.ftpcache:
+                self.ftpcache[key] = \
+                    ftpwrapper(user, passwd, host, port, dirs)
+            if not file: type = 'D'
+            else: type = 'I'
+            for attr in attrs:
+                attr, value = splitvalue(attr)
+                if attr.lower() == 'type' and \
+                   value in ('a', 'A', 'i', 'I', 'd', 'D'):
+                    type = value.upper()
+            (fp, retrlen) = self.ftpcache[key].retrfile(file, type)
+            mtype = mimetypes.guess_type("ftp:" + url)[0]
+            headers = ""
+            if mtype:
+                headers += "Content-Type: %s\n" % mtype
+            if retrlen is not None and retrlen >= 0:
+                headers += "Content-Length: %d\n" % retrlen
+            headers = mimetools.Message(StringIO(headers))
+            return addinfourl(fp, headers, "ftp:" + url)
+        except ftperrors(), msg:
+            raise IOError, ('ftp error', msg), sys.exc_info()[2]
+
+    def open_data(self, url, data=None):
+        """Use "data" URL."""
+        if not isinstance(url, str):
+            raise IOError, ('data error', 'proxy support for data protocol currently not implemented')
+        # ignore POSTed data
+        #
+        # syntax of data URLs:
+        # dataurl   := "data:" [ mediatype ] [ ";base64" ] "," data
+        # mediatype := [ type "/" subtype ] *( ";" parameter )
+        # data      := *urlchar
+        # parameter := attribute "=" value
+        import mimetools
+        try:
+            from cStringIO import StringIO
+        except ImportError:
+            from StringIO import StringIO
+        try:
+            [type, data] = url.split(',', 1)
+        except ValueError:
+            raise IOError, ('data error', 'bad data URL')
+        if not type:
+            type = 'text/plain;charset=US-ASCII'
+        semi = type.rfind(';')
+        if semi >= 0 and '=' not in type[semi:]:
+            encoding = type[semi+1:]
+            type = type[:semi]
+        else:
+            encoding = ''
+        msg = []
+        msg.append('Date: %s'%time.strftime('%a, %d %b %Y %H:%M:%S GMT',
+                                            time.gmtime(time.time())))
+        msg.append('Content-type: %s' % type)
+        if encoding == 'base64':
+            data = base64.decodestring(data)
+        else:
+            data = unquote(data)
+        msg.append('Content-Length: %d' % len(data))
+        msg.append('')
+        msg.append(data)
+        msg = '\n'.join(msg)
+        f = StringIO(msg)
+        headers = mimetools.Message(f, 0)
+        #f.fileno = None     # needed for addinfourl
+        return addinfourl(f, headers, url)
+
+
+class FancyURLopener(URLopener):
+    """Derived class with handlers for errors we can handle (perhaps)."""
+
+    def __init__(self, *args, **kwargs):
+        URLopener.__init__(self, *args, **kwargs)
+        self.auth_cache = {}
+        self.tries = 0
+        self.maxtries = 10
+
+    def http_error_default(self, url, fp, errcode, errmsg, headers):
+        """Default error handling -- don't raise an exception."""
+        return addinfourl(fp, headers, "http:" + url, errcode)
+
+    def http_error_302(self, url, fp, errcode, errmsg, headers, data=None):
+        """Error 302 -- relocated (temporarily)."""
+        self.tries += 1
+        if self.maxtries and self.tries >= self.maxtries:
+            if hasattr(self, "http_error_500"):
+                meth = self.http_error_500
+            else:
+                meth = self.http_error_default
+            self.tries = 0
+            return meth(url, fp, 500,
+                        "Internal Server Error: Redirect Recursion", headers)
+        result = self.redirect_internal(url, fp, errcode, errmsg, headers,
+                                        data)
+        self.tries = 0
+        return result
+
+    def redirect_internal(self, url, fp, errcode, errmsg, headers, data):
+        if 'location' in headers:
+            newurl = headers['location']
+        elif 'uri' in headers:
+            newurl = headers['uri']
+        else:
+            return
+        fp.close()
+        # In case the server sent a relative URL, join with original:
+        newurl = basejoin(self.type + ":" + url, newurl)
+
+        # For security reasons we do not allow redirects to protocols
+        # other than HTTP, HTTPS or FTP.
+        newurl_lower = newurl.lower()
+        if not (newurl_lower.startswith('http://') or
+                newurl_lower.startswith('https://') or
+                newurl_lower.startswith('ftp://')):
+            raise IOError('redirect error', errcode,
+                          errmsg + " - Redirection to url '%s' is not allowed" %
+                          newurl,
+                          headers)
+
+        return self.open(newurl)
+
+    def http_error_301(self, url, fp, errcode, errmsg, headers, data=None):
+        """Error 301 -- also relocated (permanently)."""
+        return self.http_error_302(url, fp, errcode, errmsg, headers, data)
+
+    def http_error_303(self, url, fp, errcode, errmsg, headers, data=None):
+        """Error 303 -- also relocated (essentially identical to 302)."""
+        return self.http_error_302(url, fp, errcode, errmsg, headers, data)
+
+    def http_error_307(self, url, fp, errcode, errmsg, headers, data=None):
+        """Error 307 -- relocated, but turn POST into error."""
+        if data is None:
+            return self.http_error_302(url, fp, errcode, errmsg, headers, data)
+        else:
+            return self.http_error_default(url, fp, errcode, errmsg, headers)
+
+    def http_error_401(self, url, fp, errcode, errmsg, headers, data=None):
+        """Error 401 -- authentication required.
+        This function supports Basic authentication only."""
+        if not 'www-authenticate' in headers:
+            URLopener.http_error_default(self, url, fp,
+                                         errcode, errmsg, headers)
+        stuff = headers['www-authenticate']
+        import re
+        match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff)
+        if not match:
+            URLopener.http_error_default(self, url, fp,
+                                         errcode, errmsg, headers)
+        scheme, realm = match.groups()
+        if scheme.lower() != 'basic':
+            URLopener.http_error_default(self, url, fp,
+                                         errcode, errmsg, headers)
+        name = 'retry_' + self.type + '_basic_auth'
+        if data is None:
+            return getattr(self,name)(url, realm)
+        else:
+            return getattr(self,name)(url, realm, data)
+
+    def http_error_407(self, url, fp, errcode, errmsg, headers, data=None):
+        """Error 407 -- proxy authentication required.
+        This function supports Basic authentication only."""
+        if not 'proxy-authenticate' in headers:
+            URLopener.http_error_default(self, url, fp,
+                                         errcode, errmsg, headers)
+        stuff = headers['proxy-authenticate']
+        import re
+        match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff)
+        if not match:
+            URLopener.http_error_default(self, url, fp,
+                                         errcode, errmsg, headers)
+        scheme, realm = match.groups()
+        if scheme.lower() != 'basic':
+            URLopener.http_error_default(self, url, fp,
+                                         errcode, errmsg, headers)
+        name = 'retry_proxy_' + self.type + '_basic_auth'
+        if data is None:
+            return getattr(self,name)(url, realm)
+        else:
+            return getattr(self,name)(url, realm, data)
+
+    def retry_proxy_http_basic_auth(self, url, realm, data=None):
+        host, selector = splithost(url)
+        newurl = 'http://' + host + selector
+        proxy = self.proxies['http']
+        urltype, proxyhost = splittype(proxy)
+        proxyhost, proxyselector = splithost(proxyhost)
+        i = proxyhost.find('@') + 1
+        proxyhost = proxyhost[i:]
+        user, passwd = self.get_user_passwd(proxyhost, realm, i)
+        if not (user or passwd): return None
+        proxyhost = quote(user, safe='') + ':' + quote(passwd, safe='') + '@' + proxyhost
+        self.proxies['http'] = 'http://' + proxyhost + proxyselector
+        if data is None:
+            return self.open(newurl)
+        else:
+            return self.open(newurl, data)
+
+    def retry_proxy_https_basic_auth(self, url, realm, data=None):
+        host, selector = splithost(url)
+        newurl = 'https://' + host + selector
+        proxy = self.proxies['https']
+        urltype, proxyhost = splittype(proxy)
+        proxyhost, proxyselector = splithost(proxyhost)
+        i = proxyhost.find('@') + 1
+        proxyhost = proxyhost[i:]
+        user, passwd = self.get_user_passwd(proxyhost, realm, i)
+        if not (user or passwd): return None
+        proxyhost = quote(user, safe='') + ':' + quote(passwd, safe='') + '@' + proxyhost
+        self.proxies['https'] = 'https://' + proxyhost + proxyselector
+        if data is None:
+            return self.open(newurl)
+        else:
+            return self.open(newurl, data)
+
+    def retry_http_basic_auth(self, url, realm, data=None):
+        host, selector = splithost(url)
+        i = host.find('@') + 1
+        host = host[i:]
+        user, passwd = self.get_user_passwd(host, realm, i)
+        if not (user or passwd): return None
+        host = quote(user, safe='') + ':' + quote(passwd, safe='') + '@' + host
+        newurl = 'http://' + host + selector
+        if data is None:
+            return self.open(newurl)
+        else:
+            return self.open(newurl, data)
+
+    def retry_https_basic_auth(self, url, realm, data=None):
+        host, selector = splithost(url)
+        i = host.find('@') + 1
+        host = host[i:]
+        user, passwd = self.get_user_passwd(host, realm, i)
+        if not (user or passwd): return None
+        host = quote(user, safe='') + ':' + quote(passwd, safe='') + '@' + host
+        newurl = 'https://' + host + selector
+        if data is None:
+            return self.open(newurl)
+        else:
+            return self.open(newurl, data)
+
+    def get_user_passwd(self, host, realm, clear_cache=0):
+        key = realm + '@' + host.lower()
+        if key in self.auth_cache:
+            if clear_cache:
+                del self.auth_cache[key]
+            else:
+                return self.auth_cache[key]
+        user, passwd = self.prompt_user_passwd(host, realm)
+        if user or passwd: self.auth_cache[key] = (user, passwd)
+        return user, passwd
+
+    def prompt_user_passwd(self, host, realm):
+        """Override this in a GUI environment!"""
+        import getpass
+        try:
+            user = raw_input("Enter username for %s at %s: " % (realm,
+                                                                host))
+            passwd = getpass.getpass("Enter password for %s in %s at %s: " %
+                (user, realm, host))
+            return user, passwd
+        except KeyboardInterrupt:
+            print
+            return None, None
+
+
+# Utility functions
+
+_localhost = None
+def localhost():
+    """Return the IP address of the magic hostname 'localhost'."""
+    global _localhost
+    if _localhost is None:
+        _localhost = socket.gethostbyname('localhost')
+    return _localhost
+
+_thishost = None
+def thishost():
+    """Return the IP address of the current host."""
+    global _thishost
+    if _thishost is None:
+        _thishost = socket.gethostbyname(socket.gethostname())
+    return _thishost
+
+_ftperrors = None
+def ftperrors():
+    """Return the set of errors raised by the FTP class."""
+    global _ftperrors
+    if _ftperrors is None:
+        import ftplib
+        _ftperrors = ftplib.all_errors
+    return _ftperrors
+
+_noheaders = None
+def noheaders():
+    """Return an empty mimetools.Message object."""
+    global _noheaders
+    if _noheaders is None:
+        import mimetools
+        try:
+            from cStringIO import StringIO
+        except ImportError:
+            from StringIO import StringIO
+        _noheaders = mimetools.Message(StringIO(), 0)
+        _noheaders.fp.close()   # Recycle file descriptor
+    return _noheaders
+
+
+# Utility classes
+
+class ftpwrapper:
+    """Class used by open_ftp() for cache of open FTP connections."""
+
+    def __init__(self, user, passwd, host, port, dirs,
+                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
+                 persistent=True):
+        self.user = user
+        self.passwd = passwd
+        self.host = host
+        self.port = port
+        self.dirs = dirs
+        self.timeout = timeout
+        self.refcount = 0
+        self.keepalive = persistent
+        self.init()
+
+    def init(self):
+        import ftplib
+        self.busy = 0
+        self.ftp = ftplib.FTP()
+        self.ftp.connect(self.host, self.port, self.timeout)
+        self.ftp.login(self.user, self.passwd)
+        for dir in self.dirs:
+            self.ftp.cwd(dir)
+
+    def retrfile(self, file, type):
+        import ftplib
+        self.endtransfer()
+        if type in ('d', 'D'): cmd = 'TYPE A'; isdir = 1
+        else: cmd = 'TYPE ' + type; isdir = 0
+        try:
+            self.ftp.voidcmd(cmd)
+        except ftplib.all_errors:
+            self.init()
+            self.ftp.voidcmd(cmd)
+        conn = None
+        if file and not isdir:
+            # Try to retrieve as a file
+            try:
+                cmd = 'RETR ' + file
+                conn, retrlen = self.ftp.ntransfercmd(cmd)
+            except ftplib.error_perm, reason:
+                if str(reason)[:3] != '550':
+                    raise IOError, ('ftp error', reason), sys.exc_info()[2]
+        if not conn:
+            # Set transfer mode to ASCII!
+            self.ftp.voidcmd('TYPE A')
+            # Try a directory listing. Verify that directory exists.
+            if file:
+                pwd = self.ftp.pwd()
+                try:
+                    try:
+                        self.ftp.cwd(file)
+                    except ftplib.error_perm, reason:
+                        raise IOError, ('ftp error', reason), sys.exc_info()[2]
+                finally:
+                    self.ftp.cwd(pwd)
+                cmd = 'LIST ' + file
+            else:
+                cmd = 'LIST'
+            conn, retrlen = self.ftp.ntransfercmd(cmd)
+        self.busy = 1
+        ftpobj = addclosehook(conn.makefile('rb'), self.file_close)
+        self.refcount += 1
+        conn.close()
+        # Pass back both a suitably decorated object and a retrieval length
+        return (ftpobj, retrlen)
+
+    def endtransfer(self):
+        if not self.busy:
+            return
+        self.busy = 0
+        try:
+            self.ftp.voidresp()
+        except ftperrors():
+            pass
+
+    def close(self):
+        self.keepalive = False
+        if self.refcount <= 0:
+            self.real_close()
+
+    def file_close(self):
+        self.endtransfer()
+        self.refcount -= 1
+        if self.refcount <= 0 and not self.keepalive:
+            self.real_close()
+
+    def real_close(self):
+        self.endtransfer()
+        try:
+            self.ftp.close()
+        except ftperrors():
+            pass
+
+class addbase:
+    """Base class for addinfo and addclosehook."""
+
+    def __init__(self, fp):
+        self.fp = fp
+        self.read = self.fp.read
+        self.readline = self.fp.readline
+        if hasattr(self.fp, "readlines"): self.readlines = self.fp.readlines
+        if hasattr(self.fp, "fileno"):
+            self.fileno = self.fp.fileno
+        else:
+            self.fileno = lambda: None
+        if hasattr(self.fp, "__iter__"):
+            self.__iter__ = self.fp.__iter__
+            if hasattr(self.fp, "next"):
+                self.next = self.fp.next
+
+    def __repr__(self):
+        return '<%s at %r whose fp = %r>' % (self.__class__.__name__,
+                                             id(self), self.fp)
+
+    def close(self):
+        self.read = None
+        self.readline = None
+        self.readlines = None
+        self.fileno = None
+        if self.fp: self.fp.close()
+        self.fp = None
+
+class addclosehook(addbase):
+    """Class to add a close hook to an open file."""
+
+    def __init__(self, fp, closehook, *hookargs):
+        addbase.__init__(self, fp)
+        self.closehook = closehook
+        self.hookargs = hookargs
+
+    def close(self):
+        if self.closehook:
+            self.closehook(*self.hookargs)
+            self.closehook = None
+            self.hookargs = None
+        addbase.close(self)
+
+class addinfo(addbase):
+    """class to add an info() method to an open file."""
+
+    def __init__(self, fp, headers):
+        addbase.__init__(self, fp)
+        self.headers = headers
+
+    def info(self):
+        return self.headers
+
+class addinfourl(addbase):
+    """class to add info() and geturl() methods to an open file."""
+
+    def __init__(self, fp, headers, url, code=None):
+        addbase.__init__(self, fp)
+        self.headers = headers
+        self.url = url
+        self.code = code
+
+    def info(self):
+        return self.headers
+
+    def getcode(self):
+        return self.code
+
+    def geturl(self):
+        return self.url
+
+
+# Utilities to parse URLs (most of these return None for missing parts):
+# unwrap('<URL:type://host/path>') --> 'type://host/path'
+# splittype('type:opaquestring') --> 'type', 'opaquestring'
+# splithost('//host[:port]/path') --> 'host[:port]', '/path'
+# splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'
+# splitpasswd('user:passwd') -> 'user', 'passwd'
+# splitport('host:port') --> 'host', 'port'
+# splitquery('/path?query') --> '/path', 'query'
+# splittag('/path#tag') --> '/path', 'tag'
+# splitattr('/path;attr1=value1;attr2=value2;...') ->
+#   '/path', ['attr1=value1', 'attr2=value2', ...]
+# splitvalue('attr=value') --> 'attr', 'value'
+# unquote('abc%20def') -> 'abc def'
+# quote('abc def') -> 'abc%20def')
+
+try:
+    unicode
+except NameError:
+    def _is_unicode(x):
+        return 0
+else:
+    def _is_unicode(x):
+        return isinstance(x, unicode)
+
+def toBytes(url):
+    """toBytes(u"URL") --> 'URL'."""
+    # Most URL schemes require ASCII. If that changes, the conversion
+    # can be relaxed
+    if _is_unicode(url):
+        try:
+            url = url.encode("ASCII")
+        except UnicodeError:
+            raise UnicodeError("URL " + repr(url) +
+                               " contains non-ASCII characters")
+    return url
+
+def unwrap(url):
+    """unwrap('<URL:type://host/path>') --> 'type://host/path'."""
+    url = url.strip()
+    if url[:1] == '<' and url[-1:] == '>':
+        url = url[1:-1].strip()
+    if url[:4] == 'URL:': url = url[4:].strip()
+    return url
+
+_typeprog = None
+def splittype(url):
+    """splittype('type:opaquestring') --> 'type', 'opaquestring'."""
+    global _typeprog
+    if _typeprog is None:
+        import re
+        _typeprog = re.compile('^([^/:]+):')
+
+    match = _typeprog.match(url)
+    if match:
+        scheme = match.group(1)
+        return scheme.lower(), url[len(scheme) + 1:]
+    return None, url
+
+_hostprog = None
+def splithost(url):
+    """splithost('//host[:port]/path') --> 'host[:port]', '/path'."""
+    global _hostprog
+    if _hostprog is None:
+        import re
+        _hostprog = re.compile('^//([^/?]*)(.*)$')
+
+    match = _hostprog.match(url)
+    if match:
+        host_port = match.group(1)
+        path = match.group(2)
+        if path and not path.startswith('/'):
+            path = '/' + path
+        return host_port, path
+    return None, url
+
+_userprog = None
+def splituser(host):
+    """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'."""
+    global _userprog
+    if _userprog is None:
+        import re
+        _userprog = re.compile('^(.*)@(.*)$')
+
+    match = _userprog.match(host)
+    if match: return match.group(1, 2)
+    return None, host
+
+_passwdprog = None
+def splitpasswd(user):
+    """splitpasswd('user:passwd') -> 'user', 'passwd'."""
+    global _passwdprog
+    if _passwdprog is None:
+        import re
+        _passwdprog = re.compile('^([^:]*):(.*)$',re.S)
+
+    match = _passwdprog.match(user)
+    if match: return match.group(1, 2)
+    return user, None
+
+# splittag('/path#tag') --> '/path', 'tag'
+_portprog = None
+def splitport(host):
+    """splitport('host:port') --> 'host', 'port'."""
+    global _portprog
+    if _portprog is None:
+        import re
+        _portprog = re.compile('^(.*):([0-9]+)$')
+
+    match = _portprog.match(host)
+    if match: return match.group(1, 2)
+    return host, None
+
+_nportprog = None
+def splitnport(host, defport=-1):
+    """Split host and port, returning numeric port.
+    Return given default port if no ':' found; defaults to -1.
+    Return numerical port if a valid number are found after ':'.
+    Return None if ':' but not a valid number."""
+    global _nportprog
+    if _nportprog is None:
+        import re
+        _nportprog = re.compile('^(.*):(.*)$')
+
+    match = _nportprog.match(host)
+    if match:
+        host, port = match.group(1, 2)
+        try:
+            if not port: raise ValueError, "no digits"
+            nport = int(port)
+        except ValueError:
+            nport = None
+        return host, nport
+    return host, defport
+
+_queryprog = None
+def splitquery(url):
+    """splitquery('/path?query') --> '/path', 'query'."""
+    global _queryprog
+    if _queryprog is None:
+        import re
+        _queryprog = re.compile('^(.*)\?([^?]*)$')
+
+    match = _queryprog.match(url)
+    if match: return match.group(1, 2)
+    return url, None
+
+_tagprog = None
+def splittag(url):
+    """splittag('/path#tag') --> '/path', 'tag'."""
+    global _tagprog
+    if _tagprog is None:
+        import re
+        _tagprog = re.compile('^(.*)#([^#]*)$')
+
+    match = _tagprog.match(url)
+    if match: return match.group(1, 2)
+    return url, None
+
+def splitattr(url):
+    """splitattr('/path;attr1=value1;attr2=value2;...') ->
+        '/path', ['attr1=value1', 'attr2=value2', ...]."""
+    words = url.split(';')
+    return words[0], words[1:]
+
+_valueprog = None
+def splitvalue(attr):
+    """splitvalue('attr=value') --> 'attr', 'value'."""
+    global _valueprog
+    if _valueprog is None:
+        import re
+        _valueprog = re.compile('^([^=]*)=(.*)$')
+
+    match = _valueprog.match(attr)
+    if match: return match.group(1, 2)
+    return attr, None
+
+# urlparse contains a duplicate of this method to avoid a circular import.  If
+# you update this method, also update the copy in urlparse.  This code
+# duplication does not exist in Python3.
+
+_hexdig = '0123456789ABCDEFabcdef'
+_hextochr = dict((a + b, chr(int(a + b, 16)))
+                 for a in _hexdig for b in _hexdig)
+
+def unquote(s):
+    """unquote('abc%20def') -> 'abc def'."""
+    res = s.split('%')
+    # fastpath
+    if len(res) == 1:
+        return s
+    s = res[0]
+    for item in res[1:]:
+        try:
+            s += _hextochr[item[:2]] + item[2:]
+        except KeyError:
+            s += '%' + item
+        except UnicodeDecodeError:
+            s += unichr(int(item[:2], 16)) + item[2:]
+    return s
+
+def unquote_plus(s):
+    """unquote('%7e/abc+def') -> '~/abc def'"""
+    s = s.replace('+', ' ')
+    return unquote(s)
+
+always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+               'abcdefghijklmnopqrstuvwxyz'
+               '0123456789' '_.-')
+_safe_map = {}
+for i, c in zip(xrange(256), str(bytearray(xrange(256)))):
+    _safe_map[c] = c if (i < 128 and c in always_safe) else '%{:02X}'.format(i)
+_safe_quoters = {}
+
+def quote(s, safe='/'):
+    """quote('abc def') -> 'abc%20def'
+
+    Each part of a URL, e.g. the path info, the query, etc., has a
+    different set of reserved characters that must be quoted.
+
+    RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists
+    the following reserved characters.
+
+    reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+                  "$" | ","
+
+    Each of these characters is reserved in some component of a URL,
+    but not necessarily in all of them.
+
+    By default, the quote function is intended for quoting the path
+    section of a URL.  Thus, it will not encode '/'.  This character
+    is reserved, but in typical usage the quote function is being
+    called on a path where the existing slash characters are used as
+    reserved characters.
+    """
+    # fastpath
+    if not s:
+        if s is None:
+            raise TypeError('None object cannot be quoted')
+        return s
+    cachekey = (safe, always_safe)
+    try:
+        (quoter, safe) = _safe_quoters[cachekey]
+    except KeyError:
+        safe_map = _safe_map.copy()
+        safe_map.update([(c, c) for c in safe])
+        quoter = safe_map.__getitem__
+        safe = always_safe + safe
+        _safe_quoters[cachekey] = (quoter, safe)
+    if not s.rstrip(safe):
+        return s
+    return ''.join(map(quoter, s))
+
+def quote_plus(s, safe=''):
+    """Quote the query fragment of a URL; replacing ' ' with '+'"""
+    if ' ' in s:
+        s = quote(s, safe + ' ')
+        return s.replace(' ', '+')
+    return quote(s, safe)
+
+def urlencode(query, doseq=0):
+    """Encode a sequence of two-element tuples or dictionary into a URL query string.
+
+    If any values in the query arg are sequences and doseq is true, each
+    sequence element is converted to a separate parameter.
+
+    If the query arg is a sequence of two-element tuples, the order of the
+    parameters in the output will match the order of parameters in the
+    input.
+    """
+
+    if hasattr(query,"items"):
+        # mapping objects
+        query = query.items()
+    else:
+        # it's a bother at times that strings and string-like objects are
+        # sequences...
+        try:
+            # non-sequence items should not work with len()
+            # non-empty strings will fail this
+            if len(query) and not isinstance(query[0], tuple):
+                raise TypeError
+            # zero-length sequences of all types will get here and succeed,
+            # but that's a minor nit - since the original implementation
+            # allowed empty dicts that type of behavior probably should be
+            # preserved for consistency
+        except TypeError:
+            ty,va,tb = sys.exc_info()
+            raise TypeError, "not a valid non-string sequence or mapping object", tb
+
+    l = []
+    if not doseq:
+        # preserve old behavior
+        for k, v in query:
+            k = quote_plus(str(k))
+            v = quote_plus(str(v))
+            l.append(k + '=' + v)
+    else:
+        for k, v in query:
+            k = quote_plus(str(k))
+            if isinstance(v, str):
+                v = quote_plus(v)
+                l.append(k + '=' + v)
+            elif _is_unicode(v):
+                # is there a reasonable way to convert to ASCII?
+                # encode generates a string, but "replace" or "ignore"
+                # lose information and "strict" can raise UnicodeError
+                v = quote_plus(v.encode("ASCII","replace"))
+                l.append(k + '=' + v)
+            else:
+                try:
+                    # is this a sufficient test for sequence-ness?
+                    len(v)
+                except TypeError:
+                    # not a sequence
+                    v = quote_plus(str(v))
+                    l.append(k + '=' + v)
+                else:
+                    # loop over the sequence
+                    for elt in v:
+                        l.append(k + '=' + quote_plus(str(elt)))
+    return '&'.join(l)
+
+# Proxy handling
+def getproxies_environment():
+    """Return a dictionary of scheme -> proxy server URL mappings.
+
+    Scan the environment for variables named <scheme>_proxy;
+    this seems to be the standard convention.  If you need a
+    different way, you can pass a proxies dictionary to the
+    [Fancy]URLopener constructor.
+
+    """
+    proxies = {}
+    for name, value in os.environ.items():
+        name = name.lower()
+        if value and name[-6:] == '_proxy':
+            proxies[name[:-6]] = value
+    return proxies
+
+def proxy_bypass_environment(host):
+    """Test if proxies should not be used for a particular host.
+
+    Checks the environment for a variable named no_proxy, which should
+    be a list of DNS suffixes separated by commas, or '*' for all hosts.
+    """
+    no_proxy = os.environ.get('no_proxy', '') or os.environ.get('NO_PROXY', '')
+    # '*' is special case for always bypass
+    if no_proxy == '*':
+        return 1
+    # strip port off host
+    hostonly, port = splitport(host)
+    # check if the host ends with any of the DNS suffixes
+    no_proxy_list = [proxy.strip() for proxy in no_proxy.split(',')]
+    for name in no_proxy_list:
+        if name and (hostonly.endswith(name) or host.endswith(name)):
+            return 1
+    # otherwise, don't bypass
+    return 0
+
+
+if sys.platform == 'darwin':
+    from _scproxy import _get_proxy_settings, _get_proxies
+
+    def proxy_bypass_macosx_sysconf(host):
+        """
+        Return True iff this host shouldn't be accessed using a proxy
+
+        This function uses the MacOSX framework SystemConfiguration
+        to fetch the proxy information.
+        """
+        import re
+        import socket
+        from fnmatch import fnmatch
+
+        hostonly, port = splitport(host)
+
+        def ip2num(ipAddr):
+            parts = ipAddr.split('.')
+            parts = map(int, parts)
+            if len(parts) != 4:
+                parts = (parts + [0, 0, 0, 0])[:4]
+            return (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]
+
+        proxy_settings = _get_proxy_settings()
+
+        # Check for simple host names:
+        if '.' not in host:
+            if proxy_settings['exclude_simple']:
+                return True
+
+        hostIP = None
+
+        for value in proxy_settings.get('exceptions', ()):
+            # Items in the list are strings like these: *.local, 169.254/16
+            if not value: continue
+
+            m = re.match(r"(\d+(?:\.\d+)*)(/\d+)?", value)
+            if m is not None:
+                if hostIP is None:
+                    try:
+                        hostIP = socket.gethostbyname(hostonly)
+                        hostIP = ip2num(hostIP)
+                    except socket.error:
+                        continue
+
+                base = ip2num(m.group(1))
+                mask = m.group(2)
+                if mask is None:
+                    mask = 8 * (m.group(1).count('.') + 1)
+
+                else:
+                    mask = int(mask[1:])
+                mask = 32 - mask
+
+                if (hostIP >> mask) == (base >> mask):
+                    return True
+
+            elif fnmatch(host, value):
+                return True
+
+        return False
+
+    def getproxies_macosx_sysconf():
+        """Return a dictionary of scheme -> proxy server URL mappings.
+
+        This function uses the MacOSX framework SystemConfiguration
+        to fetch the proxy information.
+        """
+        return _get_proxies()
+
+    def proxy_bypass(host):
+        if getproxies_environment():
+            return proxy_bypass_environment(host)
+        else:
+            return proxy_bypass_macosx_sysconf(host)
+
+    def getproxies():
+        return getproxies_environment() or getproxies_macosx_sysconf()
+
+elif os.name == 'nt':
+    def getproxies_registry():
+        """Return a dictionary of scheme -> proxy server URL mappings.
+
+        Win32 uses the registry to store proxies.
+
+        """
+        proxies = {}
+        try:
+            import _winreg
+        except ImportError:
+            # Std module, so should be around - but you never know!
+            return proxies
+        try:
+            internetSettings = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
+                r'Software\Microsoft\Windows\CurrentVersion\Internet Settings')
+            proxyEnable = _winreg.QueryValueEx(internetSettings,
+                                               'ProxyEnable')[0]
+            if proxyEnable:
+                # Returned as Unicode but problems if not converted to ASCII
+                proxyServer = str(_winreg.QueryValueEx(internetSettings,
+                                                       'ProxyServer')[0])
+                if '=' in proxyServer:
+                    # Per-protocol settings
+                    for p in proxyServer.split(';'):
+                        protocol, address = p.split('=', 1)
+                        # See if address has a type:// prefix
+                        import re
+                        if not re.match('^([^/:]+)://', address):
+                            address = '%s://%s' % (protocol, address)
+                        proxies[protocol] = address
+                else:
+                    # Use one setting for all protocols
+                    if proxyServer[:5] == 'http:':
+                        proxies['http'] = proxyServer
+                    else:
+                        proxies['http'] = 'http://%s' % proxyServer
+                        proxies['https'] = 'https://%s' % proxyServer
+                        proxies['ftp'] = 'ftp://%s' % proxyServer
+            internetSettings.Close()
+        except (WindowsError, ValueError, TypeError):
+            # Either registry key not found etc, or the value in an
+            # unexpected format.
+            # proxies already set up to be empty so nothing to do
+            pass
+        return proxies
+
+    def getproxies():
+        """Return a dictionary of scheme -> proxy server URL mappings.
+
+        Returns settings gathered from the environment, if specified,
+        or the registry.
+
+        """
+        return getproxies_environment() or getproxies_registry()
+
+    def proxy_bypass_registry(host):
+        try:
+            import _winreg
+            import re
+        except ImportError:
+            # Std modules, so should be around - but you never know!
+            return 0
+        try:
+            internetSettings = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
+                r'Software\Microsoft\Windows\CurrentVersion\Internet Settings')
+            proxyEnable = _winreg.QueryValueEx(internetSettings,
+                                               'ProxyEnable')[0]
+            proxyOverride = str(_winreg.QueryValueEx(internetSettings,
+                                                     'ProxyOverride')[0])
+            # ^^^^ Returned as Unicode but problems if not converted to ASCII
+        except WindowsError:
+            return 0
+        if not proxyEnable or not proxyOverride:
+            return 0
+        # try to make a host list from name and IP address.
+        rawHost, port = splitport(host)
+        host = [rawHost]
+        try:
+            addr = socket.gethostbyname(rawHost)
+            if addr != rawHost:
+                host.append(addr)
+        except socket.error:
+            pass
+        try:
+            fqdn = socket.getfqdn(rawHost)
+            if fqdn != rawHost:
+                host.append(fqdn)
+        except socket.error:
+            pass
+        # make a check value list from the registry entry: replace the
+        # '<local>' string by the localhost entry and the corresponding
+        # canonical entry.
+        proxyOverride = proxyOverride.split(';')
+        # now check if we match one of the registry values.
+        for test in proxyOverride:
+            if test == '<local>':
+                if '.' not in rawHost:
+                    return 1
+            test = test.replace(".", r"\.")     # mask dots
+            test = test.replace("*", r".*")     # change glob sequence
+            test = test.replace("?", r".")      # change glob char
+            for val in host:
+                # print "%s <--> %s" %( test, val )
+                if re.match(test, val, re.I):
+                    return 1
+        return 0
+
+    def proxy_bypass(host):
+        """Return a dictionary of scheme -> proxy server URL mappings.
+
+        Returns settings gathered from the environment, if specified,
+        or the registry.
+
+        """
+        if getproxies_environment():
+            return proxy_bypass_environment(host)
+        else:
+            return proxy_bypass_registry(host)
+
+else:
+    # By default use environment variables
+    getproxies = getproxies_environment
+    proxy_bypass = proxy_bypass_environment
+
+# Test and time quote() and unquote()
+def test1():
+    s = ''
+    for i in range(256): s = s + chr(i)
+    s = s*4
+    t0 = time.time()
+    qs = quote(s)
+    uqs = unquote(qs)
+    t1 = time.time()
+    if uqs != s:
+        print 'Wrong!'
+    print repr(s)
+    print repr(qs)
+    print repr(uqs)
+    print round(t1 - t0, 3), 'sec'
+
+
+def reporthook(blocknum, blocksize, totalsize):
+    # Report during remote transfers
+    print "Block number: %d, Block size: %d, Total size: %d" % (
+        blocknum, blocksize, totalsize)
diff --git a/src/main/resources/PythonLibs/urllib2.py b/src/main/resources/PythonLibs/urllib2.py
new file mode 100644
index 0000000000000000000000000000000000000000..aadeb7371ebc694ff6c230a38f9c6c8c9425f58c
--- /dev/null
+++ b/src/main/resources/PythonLibs/urllib2.py
@@ -0,0 +1,1470 @@
+"""An extensible library for opening URLs using a variety of protocols
+
+The simplest way to use this module is to call the urlopen function,
+which accepts a string containing a URL or a Request object (described
+below).  It opens the URL and returns the results as file-like
+object; the returned object has some extra methods described below.
+
+The OpenerDirector manages a collection of Handler objects that do
+all the actual work.  Each Handler implements a particular protocol or
+option.  The OpenerDirector is a composite object that invokes the
+Handlers needed to open the requested URL.  For example, the
+HTTPHandler performs HTTP GET and POST requests and deals with
+non-error returns.  The HTTPRedirectHandler automatically deals with
+HTTP 301, 302, 303 and 307 redirect errors, and the HTTPDigestAuthHandler
+deals with digest authentication.
+
+urlopen(url, data=None) -- Basic usage is the same as original
+urllib.  pass the url and optionally data to post to an HTTP URL, and
+get a file-like object back.  One difference is that you can also pass
+a Request instance instead of URL.  Raises a URLError (subclass of
+IOError); for HTTP errors, raises an HTTPError, which can also be
+treated as a valid response.
+
+build_opener -- Function that creates a new OpenerDirector instance.
+Will install the default handlers.  Accepts one or more Handlers as
+arguments, either instances or Handler classes that it will
+instantiate.  If one of the argument is a subclass of the default
+handler, the argument will be installed instead of the default.
+
+install_opener -- Installs a new opener as the default opener.
+
+objects of interest:
+
+OpenerDirector -- Sets up the User Agent as the Python-urllib client and manages
+the Handler classes, while dealing with requests and responses.
+
+Request -- An object that encapsulates the state of a request.  The
+state can be as simple as the URL.  It can also include extra HTTP
+headers, e.g. a User-Agent.
+
+BaseHandler --
+
+exceptions:
+URLError -- A subclass of IOError, individual protocols have their own
+specific subclass.
+
+HTTPError -- Also a valid HTTP response, so you can treat an HTTP error
+as an exceptional event or valid response.
+
+internals:
+BaseHandler and parent
+_call_chain conventions
+
+Example usage:
+
+import urllib2
+
+# set up authentication info
+authinfo = urllib2.HTTPBasicAuthHandler()
+authinfo.add_password(realm='PDQ Application',
+                      uri='https://mahler:8092/site-updates.py',
+                      user='klem',
+                      passwd='geheim$parole')
+
+proxy_support = urllib2.ProxyHandler({"http" : "http://ahad-haam:3128"})
+
+# build a new opener that adds authentication and caching FTP handlers
+opener = urllib2.build_opener(proxy_support, authinfo, urllib2.CacheFTPHandler)
+
+# install it
+urllib2.install_opener(opener)
+
+f = urllib2.urlopen('http://www.python.org/')
+
+
+"""
+
+# XXX issues:
+# If an authentication error handler that tries to perform
+# authentication for some reason but fails, how should the error be
+# signalled?  The client needs to know the HTTP error code.  But if
+# the handler knows that the problem was, e.g., that it didn't know
+# that hash algo that requested in the challenge, it would be good to
+# pass that information along to the client, too.
+# ftp errors aren't handled cleanly
+# check digest against correct (i.e. non-apache) implementation
+
+# Possible extensions:
+# complex proxies  XXX not sure what exactly was meant by this
+# abstract factory for opener
+
+import base64
+import hashlib
+import httplib
+import mimetools
+import os
+import posixpath
+import random
+import re
+import socket
+import sys
+import time
+import urlparse
+import bisect
+import warnings
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+from urllib import (unwrap, unquote, splittype, splithost, quote,
+     addinfourl, splitport, splittag, toBytes,
+     splitattr, ftpwrapper, splituser, splitpasswd, splitvalue)
+
+# support for FileHandler, proxies via environment variables
+from urllib import localhost, url2pathname, getproxies, proxy_bypass
+
+# used in User-Agent header sent
+__version__ = sys.version[:3]
+
+_opener = None
+def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
+    global _opener
+    if _opener is None:
+        _opener = build_opener()
+    return _opener.open(url, data, timeout)
+
+def install_opener(opener):
+    global _opener
+    _opener = opener
+
+# do these error classes make sense?
+# make sure all of the IOError stuff is overridden.  we just want to be
+# subtypes.
+
+class URLError(IOError):
+    # URLError is a sub-type of IOError, but it doesn't share any of
+    # the implementation.  need to override __init__ and __str__.
+    # It sets self.args for compatibility with other EnvironmentError
+    # subclasses, but args doesn't have the typical format with errno in
+    # slot 0 and strerror in slot 1.  This may be better than nothing.
+    def __init__(self, reason):
+        self.args = reason,
+        self.reason = reason
+
+    def __str__(self):
+        return '<urlopen error %s>' % self.reason
+
+class HTTPError(URLError, addinfourl):
+    """Raised when HTTP error occurs, but also acts like non-error return"""
+    __super_init = addinfourl.__init__
+
+    def __init__(self, url, code, msg, hdrs, fp):
+        self.code = code
+        self.msg = msg
+        self.hdrs = hdrs
+        self.fp = fp
+        self.filename = url
+        # The addinfourl classes depend on fp being a valid file
+        # object.  In some cases, the HTTPError may not have a valid
+        # file object.  If this happens, the simplest workaround is to
+        # not initialize the base classes.
+        if fp is not None:
+            self.__super_init(fp, hdrs, url, code)
+
+    def __str__(self):
+        return 'HTTP Error %s: %s' % (self.code, self.msg)
+
+    # since URLError specifies a .reason attribute, HTTPError should also
+    #  provide this attribute. See issue13211 fo discussion.
+    @property
+    def reason(self):
+        return self.msg
+
+    def info(self):
+        return self.hdrs
+
+# copied from cookielib.py
+_cut_port_re = re.compile(r":\d+$")
+def request_host(request):
+    """Return request-host, as defined by RFC 2965.
+
+    Variation from RFC: returned value is lowercased, for convenient
+    comparison.
+
+    """
+    url = request.get_full_url()
+    host = urlparse.urlparse(url)[1]
+    if host == "":
+        host = request.get_header("Host", "")
+
+    # remove port, if present
+    host = _cut_port_re.sub("", host, 1)
+    return host.lower()
+
+class Request:
+
+    def __init__(self, url, data=None, headers={},
+                 origin_req_host=None, unverifiable=False):
+        # unwrap('<URL:type://host/path>') --> 'type://host/path'
+        self.__original = unwrap(url)
+        self.__original, self.__fragment = splittag(self.__original)
+        self.type = None
+        # self.__r_type is what's left after doing the splittype
+        self.host = None
+        self.port = None
+        self._tunnel_host = None
+        self.data = data
+        self.headers = {}
+        for key, value in headers.items():
+            self.add_header(key, value)
+        self.unredirected_hdrs = {}
+        if origin_req_host is None:
+            origin_req_host = request_host(self)
+        self.origin_req_host = origin_req_host
+        self.unverifiable = unverifiable
+
+    def __getattr__(self, attr):
+        # XXX this is a fallback mechanism to guard against these
+        # methods getting called in a non-standard order.  this may be
+        # too complicated and/or unnecessary.
+        # XXX should the __r_XXX attributes be public?
+        if attr[:12] == '_Request__r_':
+            name = attr[12:]
+            if hasattr(Request, 'get_' + name):
+                getattr(self, 'get_' + name)()
+                return getattr(self, attr)
+        raise AttributeError, attr
+
+    def get_method(self):
+        if self.has_data():
+            return "POST"
+        else:
+            return "GET"
+
+    # XXX these helper methods are lame
+
+    def add_data(self, data):
+        self.data = data
+
+    def has_data(self):
+        return self.data is not None
+
+    def get_data(self):
+        return self.data
+
+    def get_full_url(self):
+        if self.__fragment:
+            return '%s#%s' % (self.__original, self.__fragment)
+        else:
+            return self.__original
+
+    def get_type(self):
+        if self.type is None:
+            self.type, self.__r_type = splittype(self.__original)
+            if self.type is None:
+                raise ValueError, "unknown url type: %s" % self.__original
+        return self.type
+
+    def get_host(self):
+        if self.host is None:
+            self.host, self.__r_host = splithost(self.__r_type)
+            if self.host:
+                self.host = unquote(self.host)
+        return self.host
+
+    def get_selector(self):
+        return self.__r_host
+
+    def set_proxy(self, host, type):
+        if self.type == 'https' and not self._tunnel_host:
+            self._tunnel_host = self.host
+        else:
+            self.type = type
+            self.__r_host = self.__original
+
+        self.host = host
+
+    def has_proxy(self):
+        return self.__r_host == self.__original
+
+    def get_origin_req_host(self):
+        return self.origin_req_host
+
+    def is_unverifiable(self):
+        return self.unverifiable
+
+    def add_header(self, key, val):
+        # useful for something like authentication
+        self.headers[key.capitalize()] = val
+
+    def add_unredirected_header(self, key, val):
+        # will not be added to a redirected request
+        self.unredirected_hdrs[key.capitalize()] = val
+
+    def has_header(self, header_name):
+        return (header_name in self.headers or
+                header_name in self.unredirected_hdrs)
+
+    def get_header(self, header_name, default=None):
+        return self.headers.get(
+            header_name,
+            self.unredirected_hdrs.get(header_name, default))
+
+    def header_items(self):
+        hdrs = self.unredirected_hdrs.copy()
+        hdrs.update(self.headers)
+        return hdrs.items()
+
+class OpenerDirector:
+    def __init__(self):
+        client_version = "Python-urllib/%s" % __version__
+        self.addheaders = [('User-agent', client_version)]
+        # self.handlers is retained only for backward compatibility
+        self.handlers = []
+        # manage the individual handlers
+        self.handle_open = {}
+        self.handle_error = {}
+        self.process_response = {}
+        self.process_request = {}
+
+    def add_handler(self, handler):
+        if not hasattr(handler, "add_parent"):
+            raise TypeError("expected BaseHandler instance, got %r" %
+                            type(handler))
+
+        added = False
+        for meth in dir(handler):
+            if meth in ["redirect_request", "do_open", "proxy_open"]:
+                # oops, coincidental match
+                continue
+
+            i = meth.find("_")
+            protocol = meth[:i]
+            condition = meth[i+1:]
+
+            if condition.startswith("error"):
+                j = condition.find("_") + i + 1
+                kind = meth[j+1:]
+                try:
+                    kind = int(kind)
+                except ValueError:
+                    pass
+                lookup = self.handle_error.get(protocol, {})
+                self.handle_error[protocol] = lookup
+            elif condition == "open":
+                kind = protocol
+                lookup = self.handle_open
+            elif condition == "response":
+                kind = protocol
+                lookup = self.process_response
+            elif condition == "request":
+                kind = protocol
+                lookup = self.process_request
+            else:
+                continue
+
+            handlers = lookup.setdefault(kind, [])
+            if handlers:
+                bisect.insort(handlers, handler)
+            else:
+                handlers.append(handler)
+            added = True
+
+        if added:
+            bisect.insort(self.handlers, handler)
+            handler.add_parent(self)
+
+    def close(self):
+        # Only exists for backwards compatibility.
+        pass
+
+    def _call_chain(self, chain, kind, meth_name, *args):
+        # Handlers raise an exception if no one else should try to handle
+        # the request, or return None if they can't but another handler
+        # could.  Otherwise, they return the response.
+        handlers = chain.get(kind, ())
+        for handler in handlers:
+            func = getattr(handler, meth_name)
+
+            result = func(*args)
+            if result is not None:
+                return result
+
+    def open(self, fullurl, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
+        # accept a URL or a Request object
+        if isinstance(fullurl, basestring):
+            req = Request(fullurl, data)
+        else:
+            req = fullurl
+            if data is not None:
+                req.add_data(data)
+
+        req.timeout = timeout
+        protocol = req.get_type()
+
+        # pre-process request
+        meth_name = protocol+"_request"
+        for processor in self.process_request.get(protocol, []):
+            meth = getattr(processor, meth_name)
+            req = meth(req)
+
+        response = self._open(req, data)
+
+        # post-process response
+        meth_name = protocol+"_response"
+        for processor in self.process_response.get(protocol, []):
+            meth = getattr(processor, meth_name)
+            response = meth(req, response)
+
+        return response
+
+    def _open(self, req, data=None):
+        result = self._call_chain(self.handle_open, 'default',
+                                  'default_open', req)
+        if result:
+            return result
+
+        protocol = req.get_type()
+        result = self._call_chain(self.handle_open, protocol, protocol +
+                                  '_open', req)
+        if result:
+            return result
+
+        return self._call_chain(self.handle_open, 'unknown',
+                                'unknown_open', req)
+
+    def error(self, proto, *args):
+        if proto in ('http', 'https'):
+            # XXX http[s] protocols are special-cased
+            dict = self.handle_error['http'] # https is not different than http
+            proto = args[2]  # YUCK!
+            meth_name = 'http_error_%s' % proto
+            http_err = 1
+            orig_args = args
+        else:
+            dict = self.handle_error
+            meth_name = proto + '_error'
+            http_err = 0
+        args = (dict, proto, meth_name) + args
+        result = self._call_chain(*args)
+        if result:
+            return result
+
+        if http_err:
+            args = (dict, 'default', 'http_error_default') + orig_args
+            return self._call_chain(*args)
+
+# XXX probably also want an abstract factory that knows when it makes
+# sense to skip a superclass in favor of a subclass and when it might
+# make sense to include both
+
+def build_opener(*handlers):
+    """Create an opener object from a list of handlers.
+
+    The opener will use several default handlers, including support
+    for HTTP, FTP and when applicable, HTTPS.
+
+    If any of the handlers passed as arguments are subclasses of the
+    default handlers, the default handlers will not be used.
+    """
+    import types
+    def isclass(obj):
+        return isinstance(obj, (types.ClassType, type))
+
+    opener = OpenerDirector()
+    default_classes = [ProxyHandler, UnknownHandler, HTTPHandler,
+                       HTTPDefaultErrorHandler, HTTPRedirectHandler,
+                       FTPHandler, FileHandler, HTTPErrorProcessor]
+    if hasattr(httplib, 'HTTPS'):
+        default_classes.append(HTTPSHandler)
+    skip = set()
+    for klass in default_classes:
+        for check in handlers:
+            if isclass(check):
+                if issubclass(check, klass):
+                    skip.add(klass)
+            elif isinstance(check, klass):
+                skip.add(klass)
+    for klass in skip:
+        default_classes.remove(klass)
+
+    for klass in default_classes:
+        opener.add_handler(klass())
+
+    for h in handlers:
+        if isclass(h):
+            h = h()
+        opener.add_handler(h)
+    return opener
+
+class BaseHandler:
+    handler_order = 500
+
+    def add_parent(self, parent):
+        self.parent = parent
+
+    def close(self):
+        # Only exists for backwards compatibility
+        pass
+
+    def __lt__(self, other):
+        if not hasattr(other, "handler_order"):
+            # Try to preserve the old behavior of having custom classes
+            # inserted after default ones (works only for custom user
+            # classes which are not aware of handler_order).
+            return True
+        return self.handler_order < other.handler_order
+
+
+class HTTPErrorProcessor(BaseHandler):
+    """Process HTTP error responses."""
+    handler_order = 1000  # after all other processing
+
+    def http_response(self, request, response):
+        code, msg, hdrs = response.code, response.msg, response.info()
+
+        # According to RFC 2616, "2xx" code indicates that the client's
+        # request was successfully received, understood, and accepted.
+        if not (200 <= code < 300):
+            response = self.parent.error(
+                'http', request, response, code, msg, hdrs)
+
+        return response
+
+    https_response = http_response
+
+class HTTPDefaultErrorHandler(BaseHandler):
+    def http_error_default(self, req, fp, code, msg, hdrs):
+        raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
+
+class HTTPRedirectHandler(BaseHandler):
+    # maximum number of redirections to any single URL
+    # this is needed because of the state that cookies introduce
+    max_repeats = 4
+    # maximum total number of redirections (regardless of URL) before
+    # assuming we're in a loop
+    max_redirections = 10
+
+    def redirect_request(self, req, fp, code, msg, headers, newurl):
+        """Return a Request or None in response to a redirect.
+
+        This is called by the http_error_30x methods when a
+        redirection response is received.  If a redirection should
+        take place, return a new Request to allow http_error_30x to
+        perform the redirect.  Otherwise, raise HTTPError if no-one
+        else should try to handle this url.  Return None if you can't
+        but another Handler might.
+        """
+        m = req.get_method()
+        if (code in (301, 302, 303, 307) and m in ("GET", "HEAD")
+            or code in (301, 302, 303) and m == "POST"):
+            # Strictly (according to RFC 2616), 301 or 302 in response
+            # to a POST MUST NOT cause a redirection without confirmation
+            # from the user (of urllib2, in this case).  In practice,
+            # essentially all clients do redirect in this case, so we
+            # do the same.
+            # be conciliant with URIs containing a space
+            newurl = newurl.replace(' ', '%20')
+            newheaders = dict((k,v) for k,v in req.headers.items()
+                              if k.lower() not in ("content-length", "content-type")
+                             )
+            return Request(newurl,
+                           headers=newheaders,
+                           origin_req_host=req.get_origin_req_host(),
+                           unverifiable=True)
+        else:
+            raise HTTPError(req.get_full_url(), code, msg, headers, fp)
+
+    # Implementation note: To avoid the server sending us into an
+    # infinite loop, the request object needs to track what URLs we
+    # have already seen.  Do this by adding a handler-specific
+    # attribute to the Request object.
+    def http_error_302(self, req, fp, code, msg, headers):
+        # Some servers (incorrectly) return multiple Location headers
+        # (so probably same goes for URI).  Use first header.
+        if 'location' in headers:
+            newurl = headers.getheaders('location')[0]
+        elif 'uri' in headers:
+            newurl = headers.getheaders('uri')[0]
+        else:
+            return
+
+        # fix a possible malformed URL
+        urlparts = urlparse.urlparse(newurl)
+        if not urlparts.path:
+            urlparts = list(urlparts)
+            urlparts[2] = "/"
+        newurl = urlparse.urlunparse(urlparts)
+
+        newurl = urlparse.urljoin(req.get_full_url(), newurl)
+
+        # For security reasons we do not allow redirects to protocols
+        # other than HTTP, HTTPS or FTP.
+        newurl_lower = newurl.lower()
+        if not (newurl_lower.startswith('http://') or
+                newurl_lower.startswith('https://') or
+                newurl_lower.startswith('ftp://')):
+            raise HTTPError(newurl, code,
+                            msg + " - Redirection to url '%s' is not allowed" %
+                            newurl,
+                            headers, fp)
+
+        # XXX Probably want to forget about the state of the current
+        # request, although that might interact poorly with other
+        # handlers that also use handler-specific request attributes
+        new = self.redirect_request(req, fp, code, msg, headers, newurl)
+        if new is None:
+            return
+
+        # loop detection
+        # .redirect_dict has a key url if url was previously visited.
+        if hasattr(req, 'redirect_dict'):
+            visited = new.redirect_dict = req.redirect_dict
+            if (visited.get(newurl, 0) >= self.max_repeats or
+                len(visited) >= self.max_redirections):
+                raise HTTPError(req.get_full_url(), code,
+                                self.inf_msg + msg, headers, fp)
+        else:
+            visited = new.redirect_dict = req.redirect_dict = {}
+        visited[newurl] = visited.get(newurl, 0) + 1
+
+        # Don't close the fp until we are sure that we won't use it
+        # with HTTPError.
+        fp.read()
+        fp.close()
+
+        return self.parent.open(new, timeout=req.timeout)
+
+    http_error_301 = http_error_303 = http_error_307 = http_error_302
+
+    inf_msg = "The HTTP server returned a redirect error that would " \
+              "lead to an infinite loop.\n" \
+              "The last 30x error message was:\n"
+
+
+def _parse_proxy(proxy):
+    """Return (scheme, user, password, host/port) given a URL or an authority.
+
+    If a URL is supplied, it must have an authority (host:port) component.
+    According to RFC 3986, having an authority component means the URL must
+    have two slashes after the scheme:
+
+    >>> _parse_proxy('file:/ftp.example.com/')
+    Traceback (most recent call last):
+    ValueError: proxy URL with no authority: 'file:/ftp.example.com/'
+
+    The first three items of the returned tuple may be None.
+
+    Examples of authority parsing:
+
+    >>> _parse_proxy('proxy.example.com')
+    (None, None, None, 'proxy.example.com')
+    >>> _parse_proxy('proxy.example.com:3128')
+    (None, None, None, 'proxy.example.com:3128')
+
+    The authority component may optionally include userinfo (assumed to be
+    username:password):
+
+    >>> _parse_proxy('joe:password@proxy.example.com')
+    (None, 'joe', 'password', 'proxy.example.com')
+    >>> _parse_proxy('joe:password@proxy.example.com:3128')
+    (None, 'joe', 'password', 'proxy.example.com:3128')
+
+    Same examples, but with URLs instead:
+
+    >>> _parse_proxy('http://proxy.example.com/')
+    ('http', None, None, 'proxy.example.com')
+    >>> _parse_proxy('http://proxy.example.com:3128/')
+    ('http', None, None, 'proxy.example.com:3128')
+    >>> _parse_proxy('http://joe:password@proxy.example.com/')
+    ('http', 'joe', 'password', 'proxy.example.com')
+    >>> _parse_proxy('http://joe:password@proxy.example.com:3128')
+    ('http', 'joe', 'password', 'proxy.example.com:3128')
+
+    Everything after the authority is ignored:
+
+    >>> _parse_proxy('ftp://joe:password@proxy.example.com/rubbish:3128')
+    ('ftp', 'joe', 'password', 'proxy.example.com')
+
+    Test for no trailing '/' case:
+
+    >>> _parse_proxy('http://joe:password@proxy.example.com')
+    ('http', 'joe', 'password', 'proxy.example.com')
+
+    """
+    scheme, r_scheme = splittype(proxy)
+    if not r_scheme.startswith("/"):
+        # authority
+        scheme = None
+        authority = proxy
+    else:
+        # URL
+        if not r_scheme.startswith("//"):
+            raise ValueError("proxy URL with no authority: %r" % proxy)
+        # We have an authority, so for RFC 3986-compliant URLs (by ss 3.
+        # and 3.3.), path is empty or starts with '/'
+        end = r_scheme.find("/", 2)
+        if end == -1:
+            end = None
+        authority = r_scheme[2:end]
+    userinfo, hostport = splituser(authority)
+    if userinfo is not None:
+        user, password = splitpasswd(userinfo)
+    else:
+        user = password = None
+    return scheme, user, password, hostport
+
+class ProxyHandler(BaseHandler):
+    # Proxies must be in front
+    handler_order = 100
+
+    def __init__(self, proxies=None):
+        if proxies is None:
+            proxies = getproxies()
+        assert hasattr(proxies, 'has_key'), "proxies must be a mapping"
+        self.proxies = proxies
+        for type, url in proxies.items():
+            setattr(self, '%s_open' % type,
+                    lambda r, proxy=url, type=type, meth=self.proxy_open: \
+                    meth(r, proxy, type))
+
+    def proxy_open(self, req, proxy, type):
+        orig_type = req.get_type()
+        proxy_type, user, password, hostport = _parse_proxy(proxy)
+
+        if proxy_type is None:
+            proxy_type = orig_type
+
+        if req.host and proxy_bypass(req.host):
+            return None
+
+        if user and password:
+            user_pass = '%s:%s' % (unquote(user), unquote(password))
+            creds = base64.b64encode(user_pass).strip()
+            req.add_header('Proxy-authorization', 'Basic ' + creds)
+        hostport = unquote(hostport)
+        req.set_proxy(hostport, proxy_type)
+
+        if orig_type == proxy_type or orig_type == 'https':
+            # let other handlers take care of it
+            return None
+        else:
+            # need to start over, because the other handlers don't
+            # grok the proxy's URL type
+            # e.g. if we have a constructor arg proxies like so:
+            # {'http': 'ftp://proxy.example.com'}, we may end up turning
+            # a request for http://acme.example.com/a into one for
+            # ftp://proxy.example.com/a
+            return self.parent.open(req, timeout=req.timeout)
+
+class HTTPPasswordMgr:
+
+    def __init__(self):
+        self.passwd = {}
+
+    def add_password(self, realm, uri, user, passwd):
+        # uri could be a single URI or a sequence
+        if isinstance(uri, basestring):
+            uri = [uri]
+        if not realm in self.passwd:
+            self.passwd[realm] = {}
+        for default_port in True, False:
+            reduced_uri = tuple(
+                [self.reduce_uri(u, default_port) for u in uri])
+            self.passwd[realm][reduced_uri] = (user, passwd)
+
+    def find_user_password(self, realm, authuri):
+        domains = self.passwd.get(realm, {})
+        for default_port in True, False:
+            reduced_authuri = self.reduce_uri(authuri, default_port)
+            for uris, authinfo in domains.iteritems():
+                for uri in uris:
+                    if self.is_suburi(uri, reduced_authuri):
+                        return authinfo
+        return None, None
+
+    def reduce_uri(self, uri, default_port=True):
+        """Accept authority or URI and extract only the authority and path."""
+        # note HTTP URLs do not have a userinfo component
+        parts = urlparse.urlsplit(uri)
+        if parts[1]:
+            # URI
+            scheme = parts[0]
+            authority = parts[1]
+            path = parts[2] or '/'
+        else:
+            # host or host:port
+            scheme = None
+            authority = uri
+            path = '/'
+        host, port = splitport(authority)
+        if default_port and port is None and scheme is not None:
+            dport = {"http": 80,
+                     "https": 443,
+                     }.get(scheme)
+            if dport is not None:
+                authority = "%s:%d" % (host, dport)
+        return authority, path
+
+    def is_suburi(self, base, test):
+        """Check if test is below base in a URI tree
+
+        Both args must be URIs in reduced form.
+        """
+        if base == test:
+            return True
+        if base[0] != test[0]:
+            return False
+        common = posixpath.commonprefix((base[1], test[1]))
+        if len(common) == len(base[1]):
+            return True
+        return False
+
+
+class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr):
+
+    def find_user_password(self, realm, authuri):
+        user, password = HTTPPasswordMgr.find_user_password(self, realm,
+                                                            authuri)
+        if user is not None:
+            return user, password
+        return HTTPPasswordMgr.find_user_password(self, None, authuri)
+
+
+class AbstractBasicAuthHandler:
+
+    # XXX this allows for multiple auth-schemes, but will stupidly pick
+    # the last one with a realm specified.
+
+    # allow for double- and single-quoted realm values
+    # (single quotes are a violation of the RFC, but appear in the wild)
+    rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+'
+                    'realm=(["\']?)([^"\']*)\\2', re.I)
+
+    # XXX could pre-emptively send auth info already accepted (RFC 2617,
+    # end of section 2, and section 1.2 immediately after "credentials"
+    # production).
+
+    def __init__(self, password_mgr=None):
+        if password_mgr is None:
+            password_mgr = HTTPPasswordMgr()
+        self.passwd = password_mgr
+        self.add_password = self.passwd.add_password
+        self.retried = 0
+
+    def reset_retry_count(self):
+        self.retried = 0
+
+    def http_error_auth_reqed(self, authreq, host, req, headers):
+        # host may be an authority (without userinfo) or a URL with an
+        # authority
+        # XXX could be multiple headers
+        authreq = headers.get(authreq, None)
+
+        if self.retried > 5:
+            # retry sending the username:password 5 times before failing.
+            raise HTTPError(req.get_full_url(), 401, "basic auth failed",
+                            headers, None)
+        else:
+            self.retried += 1
+
+        if authreq:
+            mo = AbstractBasicAuthHandler.rx.search(authreq)
+            if mo:
+                scheme, quote, realm = mo.groups()
+                if quote not in ['"', "'"]:
+                    warnings.warn("Basic Auth Realm was unquoted",
+                                  UserWarning, 2)
+                if scheme.lower() == 'basic':
+                    response = self.retry_http_basic_auth(host, req, realm)
+                    if response and response.code != 401:
+                        self.retried = 0
+                    return response
+
+    def retry_http_basic_auth(self, host, req, realm):
+        user, pw = self.passwd.find_user_password(realm, host)
+        if pw is not None:
+            raw = "%s:%s" % (user, pw)
+            auth = 'Basic %s' % base64.b64encode(raw).strip()
+            if req.headers.get(self.auth_header, None) == auth:
+                return None
+            req.add_unredirected_header(self.auth_header, auth)
+            return self.parent.open(req, timeout=req.timeout)
+        else:
+            return None
+
+
+class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
+
+    auth_header = 'Authorization'
+
+    def http_error_401(self, req, fp, code, msg, headers):
+        url = req.get_full_url()
+        response = self.http_error_auth_reqed('www-authenticate',
+                                              url, req, headers)
+        self.reset_retry_count()
+        return response
+
+
+class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
+
+    auth_header = 'Proxy-authorization'
+
+    def http_error_407(self, req, fp, code, msg, headers):
+        # http_error_auth_reqed requires that there is no userinfo component in
+        # authority.  Assume there isn't one, since urllib2 does not (and
+        # should not, RFC 3986 s. 3.2.1) support requests for URLs containing
+        # userinfo.
+        authority = req.get_host()
+        response = self.http_error_auth_reqed('proxy-authenticate',
+                                          authority, req, headers)
+        self.reset_retry_count()
+        return response
+
+
+def randombytes(n):
+    """Return n random bytes."""
+    # Use /dev/urandom if it is available.  Fall back to random module
+    # if not.  It might be worthwhile to extend this function to use
+    # other platform-specific mechanisms for getting random bytes.
+    if os.path.exists("/dev/urandom"):
+        f = open("/dev/urandom")
+        s = f.read(n)
+        f.close()
+        return s
+    else:
+        L = [chr(random.randrange(0, 256)) for i in range(n)]
+        return "".join(L)
+
+class AbstractDigestAuthHandler:
+    # Digest authentication is specified in RFC 2617.
+
+    # XXX The client does not inspect the Authentication-Info header
+    # in a successful response.
+
+    # XXX It should be possible to test this implementation against
+    # a mock server that just generates a static set of challenges.
+
+    # XXX qop="auth-int" supports is shaky
+
+    def __init__(self, passwd=None):
+        if passwd is None:
+            passwd = HTTPPasswordMgr()
+        self.passwd = passwd
+        self.add_password = self.passwd.add_password
+        self.retried = 0
+        self.nonce_count = 0
+        self.last_nonce = None
+
+    def reset_retry_count(self):
+        self.retried = 0
+
+    def http_error_auth_reqed(self, auth_header, host, req, headers):
+        authreq = headers.get(auth_header, None)
+        if self.retried > 5:
+            # Don't fail endlessly - if we failed once, we'll probably
+            # fail a second time. Hm. Unless the Password Manager is
+            # prompting for the information. Crap. This isn't great
+            # but it's better than the current 'repeat until recursion
+            # depth exceeded' approach <wink>
+            raise HTTPError(req.get_full_url(), 401, "digest auth failed",
+                            headers, None)
+        else:
+            self.retried += 1
+        if authreq:
+            scheme = authreq.split()[0]
+            if scheme.lower() == 'digest':
+                return self.retry_http_digest_auth(req, authreq)
+
+    def retry_http_digest_auth(self, req, auth):
+        token, challenge = auth.split(' ', 1)
+        chal = parse_keqv_list(parse_http_list(challenge))
+        auth = self.get_authorization(req, chal)
+        if auth:
+            auth_val = 'Digest %s' % auth
+            if req.headers.get(self.auth_header, None) == auth_val:
+                return None
+            req.add_unredirected_header(self.auth_header, auth_val)
+            resp = self.parent.open(req, timeout=req.timeout)
+            return resp
+
+    def get_cnonce(self, nonce):
+        # The cnonce-value is an opaque
+        # quoted string value provided by the client and used by both client
+        # and server to avoid chosen plaintext attacks, to provide mutual
+        # authentication, and to provide some message integrity protection.
+        # This isn't a fabulous effort, but it's probably Good Enough.
+        dig = hashlib.sha1("%s:%s:%s:%s" % (self.nonce_count, nonce, time.ctime(),
+                                            randombytes(8))).hexdigest()
+        return dig[:16]
+
+    def get_authorization(self, req, chal):
+        try:
+            realm = chal['realm']
+            nonce = chal['nonce']
+            qop = chal.get('qop')
+            algorithm = chal.get('algorithm', 'MD5')
+            # mod_digest doesn't send an opaque, even though it isn't
+            # supposed to be optional
+            opaque = chal.get('opaque', None)
+        except KeyError:
+            return None
+
+        H, KD = self.get_algorithm_impls(algorithm)
+        if H is None:
+            return None
+
+        user, pw = self.passwd.find_user_password(realm, req.get_full_url())
+        if user is None:
+            return None
+
+        # XXX not implemented yet
+        if req.has_data():
+            entdig = self.get_entity_digest(req.get_data(), chal)
+        else:
+            entdig = None
+
+        A1 = "%s:%s:%s" % (user, realm, pw)
+        A2 = "%s:%s" % (req.get_method(),
+                        # XXX selector: what about proxies and full urls
+                        req.get_selector())
+        if qop == 'auth':
+            if nonce == self.last_nonce:
+                self.nonce_count += 1
+            else:
+                self.nonce_count = 1
+                self.last_nonce = nonce
+
+            ncvalue = '%08x' % self.nonce_count
+            cnonce = self.get_cnonce(nonce)
+            noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, H(A2))
+            respdig = KD(H(A1), noncebit)
+        elif qop is None:
+            respdig = KD(H(A1), "%s:%s" % (nonce, H(A2)))
+        else:
+            # XXX handle auth-int.
+            raise URLError("qop '%s' is not supported." % qop)
+
+        # XXX should the partial digests be encoded too?
+
+        base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \
+               'response="%s"' % (user, realm, nonce, req.get_selector(),
+                                  respdig)
+        if opaque:
+            base += ', opaque="%s"' % opaque
+        if entdig:
+            base += ', digest="%s"' % entdig
+        base += ', algorithm="%s"' % algorithm
+        if qop:
+            base += ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce)
+        return base
+
+    def get_algorithm_impls(self, algorithm):
+        # algorithm should be case-insensitive according to RFC2617
+        algorithm = algorithm.upper()
+        # lambdas assume digest modules are imported at the top level
+        if algorithm == 'MD5':
+            H = lambda x: hashlib.md5(x).hexdigest()
+        elif algorithm == 'SHA':
+            H = lambda x: hashlib.sha1(x).hexdigest()
+        # XXX MD5-sess
+        KD = lambda s, d: H("%s:%s" % (s, d))
+        return H, KD
+
+    def get_entity_digest(self, data, chal):
+        # XXX not implemented yet
+        return None
+
+
+class HTTPDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler):
+    """An authentication protocol defined by RFC 2069
+
+    Digest authentication improves on basic authentication because it
+    does not transmit passwords in the clear.
+    """
+
+    auth_header = 'Authorization'
+    handler_order = 490  # before Basic auth
+
+    def http_error_401(self, req, fp, code, msg, headers):
+        host = urlparse.urlparse(req.get_full_url())[1]
+        retry = self.http_error_auth_reqed('www-authenticate',
+                                           host, req, headers)
+        self.reset_retry_count()
+        return retry
+
+
+class ProxyDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler):
+
+    auth_header = 'Proxy-Authorization'
+    handler_order = 490  # before Basic auth
+
+    def http_error_407(self, req, fp, code, msg, headers):
+        host = req.get_host()
+        retry = self.http_error_auth_reqed('proxy-authenticate',
+                                           host, req, headers)
+        self.reset_retry_count()
+        return retry
+
+class AbstractHTTPHandler(BaseHandler):
+
+    def __init__(self, debuglevel=0):
+        self._debuglevel = debuglevel
+
+    def set_http_debuglevel(self, level):
+        self._debuglevel = level
+
+    def do_request_(self, request):
+        host = request.get_host()
+        if not host:
+            raise URLError('no host given')
+
+        if request.has_data():  # POST
+            data = request.get_data()
+            if not request.has_header('Content-type'):
+                request.add_unredirected_header(
+                    'Content-type',
+                    'application/x-www-form-urlencoded')
+            if not request.has_header('Content-length'):
+                request.add_unredirected_header(
+                    'Content-length', '%d' % len(data))
+
+        sel_host = host
+        if request.has_proxy():
+            scheme, sel = splittype(request.get_selector())
+            sel_host, sel_path = splithost(sel)
+
+        if not request.has_header('Host'):
+            request.add_unredirected_header('Host', sel_host)
+        for name, value in self.parent.addheaders:
+            name = name.capitalize()
+            if not request.has_header(name):
+                request.add_unredirected_header(name, value)
+
+        return request
+
+    def do_open(self, http_class, req):
+        """Return an addinfourl object for the request, using http_class.
+
+        http_class must implement the HTTPConnection API from httplib.
+        The addinfourl return value is a file-like object.  It also
+        has methods and attributes including:
+            - info(): return a mimetools.Message object for the headers
+            - geturl(): return the original request URL
+            - code: HTTP status code
+        """
+        host = req.get_host()
+        if not host:
+            raise URLError('no host given')
+
+        h = http_class(host, timeout=req.timeout) # will parse host:port
+        h.set_debuglevel(self._debuglevel)
+
+        headers = dict(req.unredirected_hdrs)
+        headers.update(dict((k, v) for k, v in req.headers.items()
+                            if k not in headers))
+
+        # We want to make an HTTP/1.1 request, but the addinfourl
+        # class isn't prepared to deal with a persistent connection.
+        # It will try to read all remaining data from the socket,
+        # which will block while the server waits for the next request.
+        # So make sure the connection gets closed after the (only)
+        # request.
+        headers["Connection"] = "close"
+        headers = dict(
+            (name.title(), val) for name, val in headers.items())
+
+        if req._tunnel_host:
+            tunnel_headers = {}
+            proxy_auth_hdr = "Proxy-Authorization"
+            if proxy_auth_hdr in headers:
+                tunnel_headers[proxy_auth_hdr] = headers[proxy_auth_hdr]
+                # Proxy-Authorization should not be sent to origin
+                # server.
+                del headers[proxy_auth_hdr]
+            h.set_tunnel(req._tunnel_host, headers=tunnel_headers)
+
+        try:
+            h.request(req.get_method(), req.get_selector(), req.data, headers)
+        except socket.error, err: # XXX what error?
+            h.close()
+            raise URLError(err)
+        else:
+            try:
+                r = h.getresponse(buffering=True)
+            except TypeError: # buffering kw not supported
+                r = h.getresponse()
+
+        # Pick apart the HTTPResponse object to get the addinfourl
+        # object initialized properly.
+
+        # Wrap the HTTPResponse object in socket's file object adapter
+        # for Windows.  That adapter calls recv(), so delegate recv()
+        # to read().  This weird wrapping allows the returned object to
+        # have readline() and readlines() methods.
+
+        # XXX It might be better to extract the read buffering code
+        # out of socket._fileobject() and into a base class.
+
+        r.recv = r.read
+        fp = socket._fileobject(r, close=True)
+
+        resp = addinfourl(fp, r.msg, req.get_full_url())
+        resp.code = r.status
+        resp.msg = r.reason
+        return resp
+
+
+class HTTPHandler(AbstractHTTPHandler):
+
+    def http_open(self, req):
+        return self.do_open(httplib.HTTPConnection, req)
+
+    http_request = AbstractHTTPHandler.do_request_
+
+if hasattr(httplib, 'HTTPS'):
+    class HTTPSHandler(AbstractHTTPHandler):
+
+        def https_open(self, req):
+            return self.do_open(httplib.HTTPSConnection, req)
+
+        https_request = AbstractHTTPHandler.do_request_
+
+class HTTPCookieProcessor(BaseHandler):
+    def __init__(self, cookiejar=None):
+        import cookielib
+        if cookiejar is None:
+            cookiejar = cookielib.CookieJar()
+        self.cookiejar = cookiejar
+
+    def http_request(self, request):
+        self.cookiejar.add_cookie_header(request)
+        return request
+
+    def http_response(self, request, response):
+        self.cookiejar.extract_cookies(response, request)
+        return response
+
+    https_request = http_request
+    https_response = http_response
+
+class UnknownHandler(BaseHandler):
+    def unknown_open(self, req):
+        type = req.get_type()
+        raise URLError('unknown url type: %s' % type)
+
+def parse_keqv_list(l):
+    """Parse list of key=value strings where keys are not duplicated."""
+    parsed = {}
+    for elt in l:
+        k, v = elt.split('=', 1)
+        if v[0] == '"' and v[-1] == '"':
+            v = v[1:-1]
+        parsed[k] = v
+    return parsed
+
+def parse_http_list(s):
+    """Parse lists as described by RFC 2068 Section 2.
+
+    In particular, parse comma-separated lists where the elements of
+    the list may include quoted-strings.  A quoted-string could
+    contain a comma.  A non-quoted string could have quotes in the
+    middle.  Neither commas nor quotes count if they are escaped.
+    Only double-quotes count, not single-quotes.
+    """
+    res = []
+    part = ''
+
+    escape = quote = False
+    for cur in s:
+        if escape:
+            part += cur
+            escape = False
+            continue
+        if quote:
+            if cur == '\\':
+                escape = True
+                continue
+            elif cur == '"':
+                quote = False
+            part += cur
+            continue
+
+        if cur == ',':
+            res.append(part)
+            part = ''
+            continue
+
+        if cur == '"':
+            quote = True
+
+        part += cur
+
+    # append last part
+    if part:
+        res.append(part)
+
+    return [part.strip() for part in res]
+
+def _safe_gethostbyname(host):
+    try:
+        return socket.gethostbyname(host)
+    except socket.gaierror:
+        return None
+
+class FileHandler(BaseHandler):
+    # Use local file or FTP depending on form of URL
+    def file_open(self, req):
+        url = req.get_selector()
+        if url[:2] == '//' and url[2:3] != '/' and (req.host and
+                req.host != 'localhost'):
+            req.type = 'ftp'
+            return self.parent.open(req)
+        else:
+            return self.open_local_file(req)
+
+    # names for the localhost
+    names = None
+    def get_names(self):
+        if FileHandler.names is None:
+            try:
+                FileHandler.names = tuple(
+                    socket.gethostbyname_ex('localhost')[2] +
+                    socket.gethostbyname_ex(socket.gethostname())[2])
+            except socket.gaierror:
+                FileHandler.names = (socket.gethostbyname('localhost'),)
+        return FileHandler.names
+
+    # not entirely sure what the rules are here
+    def open_local_file(self, req):
+        import email.utils
+        import mimetypes
+        host = req.get_host()
+        filename = req.get_selector()
+        localfile = url2pathname(filename)
+        try:
+            stats = os.stat(localfile)
+            size = stats.st_size
+            modified = email.utils.formatdate(stats.st_mtime, usegmt=True)
+            mtype = mimetypes.guess_type(filename)[0]
+            headers = mimetools.Message(StringIO(
+                'Content-type: %s\nContent-length: %d\nLast-modified: %s\n' %
+                (mtype or 'text/plain', size, modified)))
+            if host:
+                host, port = splitport(host)
+            if not host or \
+                (not port and _safe_gethostbyname(host) in self.get_names()):
+                if host:
+                    origurl = 'file://' + host + filename
+                else:
+                    origurl = 'file://' + filename
+                return addinfourl(open(localfile, 'rb'), headers, origurl)
+        except OSError, msg:
+            # urllib2 users shouldn't expect OSErrors coming from urlopen()
+            raise URLError(msg)
+        raise URLError('file not on local host')
+
+class FTPHandler(BaseHandler):
+    def ftp_open(self, req):
+        import ftplib
+        import mimetypes
+        host = req.get_host()
+        if not host:
+            raise URLError('ftp error: no host given')
+        host, port = splitport(host)
+        if port is None:
+            port = ftplib.FTP_PORT
+        else:
+            port = int(port)
+
+        # username/password handling
+        user, host = splituser(host)
+        if user:
+            user, passwd = splitpasswd(user)
+        else:
+            passwd = None
+        host = unquote(host)
+        user = user or ''
+        passwd = passwd or ''
+
+        try:
+            host = socket.gethostbyname(host)
+        except socket.error, msg:
+            raise URLError(msg)
+        path, attrs = splitattr(req.get_selector())
+        dirs = path.split('/')
+        dirs = map(unquote, dirs)
+        dirs, file = dirs[:-1], dirs[-1]
+        if dirs and not dirs[0]:
+            dirs = dirs[1:]
+        try:
+            fw = self.connect_ftp(user, passwd, host, port, dirs, req.timeout)
+            type = file and 'I' or 'D'
+            for attr in attrs:
+                attr, value = splitvalue(attr)
+                if attr.lower() == 'type' and \
+                   value in ('a', 'A', 'i', 'I', 'd', 'D'):
+                    type = value.upper()
+            fp, retrlen = fw.retrfile(file, type)
+            headers = ""
+            mtype = mimetypes.guess_type(req.get_full_url())[0]
+            if mtype:
+                headers += "Content-type: %s\n" % mtype
+            if retrlen is not None and retrlen >= 0:
+                headers += "Content-length: %d\n" % retrlen
+            sf = StringIO(headers)
+            headers = mimetools.Message(sf)
+            return addinfourl(fp, headers, req.get_full_url())
+        except ftplib.all_errors, msg:
+            raise URLError, ('ftp error: %s' % msg), sys.exc_info()[2]
+
+    def connect_ftp(self, user, passwd, host, port, dirs, timeout):
+        fw = ftpwrapper(user, passwd, host, port, dirs, timeout,
+                        persistent=False)
+##        fw.ftp.set_debuglevel(1)
+        return fw
+
+class CacheFTPHandler(FTPHandler):
+    # XXX would be nice to have pluggable cache strategies
+    # XXX this stuff is definitely not thread safe
+    def __init__(self):
+        self.cache = {}
+        self.timeout = {}
+        self.soonest = 0
+        self.delay = 60
+        self.max_conns = 16
+
+    def setTimeout(self, t):
+        self.delay = t
+
+    def setMaxConns(self, m):
+        self.max_conns = m
+
+    def connect_ftp(self, user, passwd, host, port, dirs, timeout):
+        key = user, host, port, '/'.join(dirs), timeout
+        if key in self.cache:
+            self.timeout[key] = time.time() + self.delay
+        else:
+            self.cache[key] = ftpwrapper(user, passwd, host, port, dirs, timeout)
+            self.timeout[key] = time.time() + self.delay
+        self.check_cache()
+        return self.cache[key]
+
+    def check_cache(self):
+        # first check for old ones
+        t = time.time()
+        if self.soonest <= t:
+            for k, v in self.timeout.items():
+                if v < t:
+                    self.cache[k].close()
+                    del self.cache[k]
+                    del self.timeout[k]
+        self.soonest = min(self.timeout.values())
+
+        # then check the size
+        if len(self.cache) == self.max_conns:
+            for k, v in self.timeout.items():
+                if v == self.soonest:
+                    del self.cache[k]
+                    del self.timeout[k]
+                    break
+            self.soonest = min(self.timeout.values())
+
+    def clear_cache(self):
+        for conn in self.cache.values():
+            conn.close()
+        self.cache.clear()
+        self.timeout.clear()
diff --git a/src/main/resources/PythonLibs/urlparse.py b/src/main/resources/PythonLibs/urlparse.py
new file mode 100644
index 0000000000000000000000000000000000000000..f370ce3bdcc17b11e446a1e83a7df74d50c6b7cb
--- /dev/null
+++ b/src/main/resources/PythonLibs/urlparse.py
@@ -0,0 +1,403 @@
+"""Parse (absolute and relative) URLs.
+
+urlparse module is based upon the following RFC specifications.
+
+RFC 3986 (STD66): "Uniform Resource Identifiers" by T. Berners-Lee, R. Fielding
+and L.  Masinter, January 2005.
+
+RFC 2732 : "Format for Literal IPv6 Addresses in URL's by R.Hinden, B.Carpenter
+and L.Masinter, December 1999.
+
+RFC 2396:  "Uniform Resource Identifiers (URI)": Generic Syntax by T.
+Berners-Lee, R. Fielding, and L. Masinter, August 1998.
+
+RFC 2368: "The mailto URL scheme", by P.Hoffman , L Masinter, J. Zwinski, July 1998.
+
+RFC 1808: "Relative Uniform Resource Locators", by R. Fielding, UC Irvine, June
+1995.
+
+RFC 1738: "Uniform Resource Locators (URL)" by T. Berners-Lee, L. Masinter, M.
+McCahill, December 1994
+
+RFC 3986 is considered the current standard and any future changes to
+urlparse module should conform with it.  The urlparse module is
+currently not entirely compliant with this RFC due to defacto
+scenarios for parsing, and for backward compatibility purposes, some
+parsing quirks from older RFCs are retained. The testcases in
+test_urlparse.py provides a good indicator of parsing behavior.
+
+"""
+
+__all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag",
+           "urlsplit", "urlunsplit", "parse_qs", "parse_qsl"]
+
+# A classification of schemes ('' means apply by default)
+uses_relative = ['ftp', 'http', 'gopher', 'nntp', 'imap',
+                 'wais', 'file', 'https', 'shttp', 'mms',
+                 'prospero', 'rtsp', 'rtspu', '', 'sftp',
+                 'svn', 'svn+ssh']
+uses_netloc = ['ftp', 'http', 'gopher', 'nntp', 'telnet',
+               'imap', 'wais', 'file', 'mms', 'https', 'shttp',
+               'snews', 'prospero', 'rtsp', 'rtspu', 'rsync', '',
+               'svn', 'svn+ssh', 'sftp','nfs','git', 'git+ssh']
+uses_params = ['ftp', 'hdl', 'prospero', 'http', 'imap',
+               'https', 'shttp', 'rtsp', 'rtspu', 'sip', 'sips',
+               'mms', '', 'sftp', 'tel']
+
+# These are not actually used anymore, but should stay for backwards
+# compatibility.  (They are undocumented, but have a public-looking name.)
+non_hierarchical = ['gopher', 'hdl', 'mailto', 'news',
+                    'telnet', 'wais', 'imap', 'snews', 'sip', 'sips']
+uses_query = ['http', 'wais', 'imap', 'https', 'shttp', 'mms',
+              'gopher', 'rtsp', 'rtspu', 'sip', 'sips', '']
+uses_fragment = ['ftp', 'hdl', 'http', 'gopher', 'news',
+                 'nntp', 'wais', 'https', 'shttp', 'snews',
+                 'file', 'prospero', '']
+
+# Characters valid in scheme names
+scheme_chars = ('abcdefghijklmnopqrstuvwxyz'
+                'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+                '0123456789'
+                '+-.')
+
+MAX_CACHE_SIZE = 20
+_parse_cache = {}
+
+def clear_cache():
+    """Clear the parse cache."""
+    _parse_cache.clear()
+
+
+class ResultMixin(object):
+    """Shared methods for the parsed result objects."""
+
+    @property
+    def username(self):
+        netloc = self.netloc
+        if "@" in netloc:
+            userinfo = netloc.rsplit("@", 1)[0]
+            if ":" in userinfo:
+                userinfo = userinfo.split(":", 1)[0]
+            return userinfo
+        return None
+
+    @property
+    def password(self):
+        netloc = self.netloc
+        if "@" in netloc:
+            userinfo = netloc.rsplit("@", 1)[0]
+            if ":" in userinfo:
+                return userinfo.split(":", 1)[1]
+        return None
+
+    @property
+    def hostname(self):
+        netloc = self.netloc.split('@')[-1]
+        if '[' in netloc and ']' in netloc:
+            return netloc.split(']')[0][1:].lower()
+        elif ':' in netloc:
+            return netloc.split(':')[0].lower()
+        elif netloc == '':
+            return None
+        else:
+            return netloc.lower()
+
+    @property
+    def port(self):
+        netloc = self.netloc.split('@')[-1].split(']')[-1]
+        if ':' in netloc:
+            port = netloc.split(':')[1]
+            port = int(port, 10)
+            # verify legal port
+            if (0 <= port <= 65535):
+                return port
+        return None
+
+from collections import namedtuple
+
+class SplitResult(namedtuple('SplitResult', 'scheme netloc path query fragment'), ResultMixin):
+
+    __slots__ = ()
+
+    def geturl(self):
+        return urlunsplit(self)
+
+
+class ParseResult(namedtuple('ParseResult', 'scheme netloc path params query fragment'), ResultMixin):
+
+    __slots__ = ()
+
+    def geturl(self):
+        return urlunparse(self)
+
+
+def urlparse(url, scheme='', allow_fragments=True):
+    """Parse a URL into 6 components:
+    <scheme>://<netloc>/<path>;<params>?<query>#<fragment>
+    Return a 6-tuple: (scheme, netloc, path, params, query, fragment).
+    Note that we don't break the components up in smaller bits
+    (e.g. netloc is a single string) and we don't expand % escapes."""
+    tuple = urlsplit(url, scheme, allow_fragments)
+    scheme, netloc, url, query, fragment = tuple
+    if scheme in uses_params and ';' in url:
+        url, params = _splitparams(url)
+    else:
+        params = ''
+    return ParseResult(scheme, netloc, url, params, query, fragment)
+
+def _splitparams(url):
+    if '/'  in url:
+        i = url.find(';', url.rfind('/'))
+        if i < 0:
+            return url, ''
+    else:
+        i = url.find(';')
+    return url[:i], url[i+1:]
+
+def _splitnetloc(url, start=0):
+    delim = len(url)   # position of end of domain part of url, default is end
+    for c in '/?#':    # look for delimiters; the order is NOT important
+        wdelim = url.find(c, start)        # find first of this delim
+        if wdelim >= 0:                    # if found
+            delim = min(delim, wdelim)     # use earliest delim position
+    return url[start:delim], url[delim:]   # return (domain, rest)
+
+def urlsplit(url, scheme='', allow_fragments=True):
+    """Parse a URL into 5 components:
+    <scheme>://<netloc>/<path>?<query>#<fragment>
+    Return a 5-tuple: (scheme, netloc, path, query, fragment).
+    Note that we don't break the components up in smaller bits
+    (e.g. netloc is a single string) and we don't expand % escapes."""
+    allow_fragments = bool(allow_fragments)
+    key = url, scheme, allow_fragments, type(url), type(scheme)
+    cached = _parse_cache.get(key, None)
+    if cached:
+        return cached
+    if len(_parse_cache) >= MAX_CACHE_SIZE: # avoid runaway growth
+        clear_cache()
+    netloc = query = fragment = ''
+    i = url.find(':')
+    if i > 0:
+        if url[:i] == 'http': # optimize the common case
+            scheme = url[:i].lower()
+            url = url[i+1:]
+            if url[:2] == '//':
+                netloc, url = _splitnetloc(url, 2)
+                if (('[' in netloc and ']' not in netloc) or
+                        (']' in netloc and '[' not in netloc)):
+                    raise ValueError("Invalid IPv6 URL")
+            if allow_fragments and '#' in url:
+                url, fragment = url.split('#', 1)
+            if '?' in url:
+                url, query = url.split('?', 1)
+            v = SplitResult(scheme, netloc, url, query, fragment)
+            _parse_cache[key] = v
+            return v
+        for c in url[:i]:
+            if c not in scheme_chars:
+                break
+        else:
+            # make sure "url" is not actually a port number (in which case
+            # "scheme" is really part of the path)
+            rest = url[i+1:]
+            if not rest or any(c not in '0123456789' for c in rest):
+                # not a port number
+                scheme, url = url[:i].lower(), rest
+
+    if url[:2] == '//':
+        netloc, url = _splitnetloc(url, 2)
+        if (('[' in netloc and ']' not in netloc) or
+                (']' in netloc and '[' not in netloc)):
+            raise ValueError("Invalid IPv6 URL")
+    if allow_fragments and '#' in url:
+        url, fragment = url.split('#', 1)
+    if '?' in url:
+        url, query = url.split('?', 1)
+    v = SplitResult(scheme, netloc, url, query, fragment)
+    _parse_cache[key] = v
+    return v
+
+def urlunparse(data):
+    """Put a parsed URL back together again.  This may result in a
+    slightly different, but equivalent URL, if the URL that was parsed
+    originally had redundant delimiters, e.g. a ? with an empty query
+    (the draft states that these are equivalent)."""
+    scheme, netloc, url, params, query, fragment = data
+    if params:
+        url = "%s;%s" % (url, params)
+    return urlunsplit((scheme, netloc, url, query, fragment))
+
+def urlunsplit(data):
+    """Combine the elements of a tuple as returned by urlsplit() into a
+    complete URL as a string. The data argument can be any five-item iterable.
+    This may result in a slightly different, but equivalent URL, if the URL that
+    was parsed originally had unnecessary delimiters (for example, a ? with an
+    empty query; the RFC states that these are equivalent)."""
+    scheme, netloc, url, query, fragment = data
+    if netloc or (scheme and scheme in uses_netloc and url[:2] != '//'):
+        if url and url[:1] != '/': url = '/' + url
+        url = '//' + (netloc or '') + url
+    if scheme:
+        url = scheme + ':' + url
+    if query:
+        url = url + '?' + query
+    if fragment:
+        url = url + '#' + fragment
+    return url
+
+def urljoin(base, url, allow_fragments=True):
+    """Join a base URL and a possibly relative URL to form an absolute
+    interpretation of the latter."""
+    if not base:
+        return url
+    if not url:
+        return base
+    bscheme, bnetloc, bpath, bparams, bquery, bfragment = \
+            urlparse(base, '', allow_fragments)
+    scheme, netloc, path, params, query, fragment = \
+            urlparse(url, bscheme, allow_fragments)
+    if scheme != bscheme or scheme not in uses_relative:
+        return url
+    if scheme in uses_netloc:
+        if netloc:
+            return urlunparse((scheme, netloc, path,
+                               params, query, fragment))
+        netloc = bnetloc
+    if path[:1] == '/':
+        return urlunparse((scheme, netloc, path,
+                           params, query, fragment))
+    if not path and not params:
+        path = bpath
+        params = bparams
+        if not query:
+            query = bquery
+        return urlunparse((scheme, netloc, path,
+                           params, query, fragment))
+    segments = bpath.split('/')[:-1] + path.split('/')
+    # XXX The stuff below is bogus in various ways...
+    if segments[-1] == '.':
+        segments[-1] = ''
+    while '.' in segments:
+        segments.remove('.')
+    while 1:
+        i = 1
+        n = len(segments) - 1
+        while i < n:
+            if (segments[i] == '..'
+                and segments[i-1] not in ('', '..')):
+                del segments[i-1:i+1]
+                break
+            i = i+1
+        else:
+            break
+    if segments == ['', '..']:
+        segments[-1] = ''
+    elif len(segments) >= 2 and segments[-1] == '..':
+        segments[-2:] = ['']
+    return urlunparse((scheme, netloc, '/'.join(segments),
+                       params, query, fragment))
+
+def urldefrag(url):
+    """Removes any existing fragment from URL.
+
+    Returns a tuple of the defragmented URL and the fragment.  If
+    the URL contained no fragments, the second element is the
+    empty string.
+    """
+    if '#' in url:
+        s, n, p, a, q, frag = urlparse(url)
+        defrag = urlunparse((s, n, p, a, q, ''))
+        return defrag, frag
+    else:
+        return url, ''
+
+# unquote method for parse_qs and parse_qsl
+# Cannot use directly from urllib as it would create a circular reference
+# because urllib uses urlparse methods (urljoin).  If you update this function,
+# update it also in urllib.  This code duplication does not existin in Python3.
+
+_hexdig = '0123456789ABCDEFabcdef'
+_hextochr = dict((a+b, chr(int(a+b,16)))
+                 for a in _hexdig for b in _hexdig)
+
+def unquote(s):
+    """unquote('abc%20def') -> 'abc def'."""
+    res = s.split('%')
+    # fastpath
+    if len(res) == 1:
+        return s
+    s = res[0]
+    for item in res[1:]:
+        try:
+            s += _hextochr[item[:2]] + item[2:]
+        except KeyError:
+            s += '%' + item
+        except UnicodeDecodeError:
+            s += unichr(int(item[:2], 16)) + item[2:]
+    return s
+
+def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
+    """Parse a query given as a string argument.
+
+        Arguments:
+
+        qs: percent-encoded query string to be parsed
+
+        keep_blank_values: flag indicating whether blank values in
+            percent-encoded queries should be treated as blank strings.
+            A true value indicates that blanks should be retained as
+            blank strings.  The default false value indicates that
+            blank values are to be ignored and treated as if they were
+            not included.
+
+        strict_parsing: flag indicating what to do with parsing errors.
+            If false (the default), errors are silently ignored.
+            If true, errors raise a ValueError exception.
+    """
+    dict = {}
+    for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
+        if name in dict:
+            dict[name].append(value)
+        else:
+            dict[name] = [value]
+    return dict
+
+def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
+    """Parse a query given as a string argument.
+
+    Arguments:
+
+    qs: percent-encoded query string to be parsed
+
+    keep_blank_values: flag indicating whether blank values in
+        percent-encoded queries should be treated as blank strings.  A
+        true value indicates that blanks should be retained as blank
+        strings.  The default false value indicates that blank values
+        are to be ignored and treated as if they were  not included.
+
+    strict_parsing: flag indicating what to do with parsing errors. If
+        false (the default), errors are silently ignored. If true,
+        errors raise a ValueError exception.
+
+    Returns a list, as G-d intended.
+    """
+    pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
+    r = []
+    for name_value in pairs:
+        if not name_value and not strict_parsing:
+            continue
+        nv = name_value.split('=', 1)
+        if len(nv) != 2:
+            if strict_parsing:
+                raise ValueError, "bad query field: %r" % (name_value,)
+            # Handle case of a control-name with no equal sign
+            if keep_blank_values:
+                nv.append('')
+            else:
+                continue
+        if len(nv[1]) or keep_blank_values:
+            name = unquote(nv[0].replace('+', ' '))
+            value = unquote(nv[1].replace('+', ' '))
+            r.append((name, value))
+
+    return r
diff --git a/src/main/resources/PythonLibs/user.py b/src/main/resources/PythonLibs/user.py
new file mode 100644
index 0000000000000000000000000000000000000000..596f0a74628eaa144a6437fec644a2d00df4a392
--- /dev/null
+++ b/src/main/resources/PythonLibs/user.py
@@ -0,0 +1,48 @@
+"""Hook to allow user-specified customization code to run.
+
+As a policy, Python doesn't run user-specified code on startup of
+Python programs (interactive sessions execute the script specified in
+the PYTHONSTARTUP environment variable if it exists).
+
+However, some programs or sites may find it convenient to allow users
+to have a standard customization file, which gets run when a program
+requests it.  This module implements such a mechanism.  A program
+that wishes to use the mechanism must execute the statement
+
+    import user
+
+The user module looks for a file .pythonrc.py in the user's home
+directory and if it can be opened, execfile()s it in its own global
+namespace.  Errors during this phase are not caught; that's up to the
+program that imports the user module, if it wishes.
+
+The user's .pythonrc.py could conceivably test for sys.version if it
+wishes to do different things depending on the Python version.
+
+"""
+from warnings import warnpy3k
+warnpy3k("the user module has been removed in Python 3.0", stacklevel=2)
+del warnpy3k
+
+import os
+
+home = os.curdir                        # Default
+if 'HOME' in os.environ:
+    home = os.environ['HOME']
+elif os.name == 'posix':
+    home = os.path.expanduser("~/")
+elif os.name == 'nt':                   # Contributed by Jeff Bauer
+    if 'HOMEPATH' in os.environ:
+        if 'HOMEDRIVE' in os.environ:
+            home = os.environ['HOMEDRIVE'] + os.environ['HOMEPATH']
+        else:
+            home = os.environ['HOMEPATH']
+
+pythonrc = os.path.join(home, ".pythonrc.py")
+try:
+    f = open(pythonrc)
+except IOError:
+    pass
+else:
+    f.close()
+    execfile(pythonrc)
diff --git a/src/main/resources/PythonLibs/uu.py b/src/main/resources/PythonLibs/uu.py
new file mode 100644
index 0000000000000000000000000000000000000000..d7726d8143a6468c6aa861ae6748447a0f06b167
--- /dev/null
+++ b/src/main/resources/PythonLibs/uu.py
@@ -0,0 +1,211 @@
+#! /usr/bin/env python
+
+# Copyright 1994 by Lance Ellinghouse
+# Cathedral City, California Republic, United States of America.
+#                        All Rights Reserved
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of Lance Ellinghouse
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE
+# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Modified by Jack Jansen, CWI, July 1995:
+# - Use binascii module to do the actual line-by-line conversion
+#   between ascii and binary. This results in a 1000-fold speedup. The C
+#   version is still 5 times faster, though.
+# - Arguments more compliant with python standard
+
+"""Implementation of the UUencode and UUdecode functions.
+
+encode(in_file, out_file [,name, mode])
+decode(in_file [, out_file, mode])
+"""
+
+import binascii
+import os
+import sys
+
+__all__ = ["Error", "encode", "decode"]
+
+class Error(Exception):
+    pass
+
+def encode(in_file, out_file, name=None, mode=None):
+    """Uuencode file"""
+    #
+    # If in_file is a pathname open it and change defaults
+    #
+
+    close_in_file = False
+    close_out_file = False
+
+    if in_file == '-':
+        in_file = sys.stdin
+    elif isinstance(in_file, basestring):
+        if name is None:
+            name = os.path.basename(in_file)
+        if mode is None:
+            try:
+                mode = os.stat(in_file).st_mode
+            except AttributeError:
+                pass
+        in_file = open(in_file, 'rb')
+        close_in_file = True
+    #
+    # Open out_file if it is a pathname
+    #
+    if out_file == '-':
+        out_file = sys.stdout
+    elif isinstance(out_file, basestring):
+        out_file = open(out_file, 'w')
+        close_out_file = True
+    #
+    # Set defaults for name and mode
+    #
+    if name is None:
+        name = '-'
+    if mode is None:
+        mode = 0666
+    #
+    # Write the data
+    #
+    out_file.write('begin %o %s\n' % ((mode&0777),name))
+    data = in_file.read(45)
+    while len(data) > 0:
+        out_file.write(binascii.b2a_uu(data))
+        data = in_file.read(45)
+    out_file.write(' \nend\n')
+
+    # Jython and other implementations requires files to be explicitly
+    # closed if we don't want to wait for GC
+    if close_in_file:
+        in_file.close()
+    if close_out_file:
+        out_file.close()
+
+def decode(in_file, out_file=None, mode=None, quiet=0):
+    """Decode uuencoded file"""
+
+    close_in_file = False
+    close_out_file = False
+
+    #
+    # Open the input file, if needed.
+    #
+    if in_file == '-':
+        in_file = sys.stdin
+    elif isinstance(in_file, basestring):
+        close_in_file = True
+        in_file = open(in_file)
+    #
+    # Read until a begin is encountered or we've exhausted the file
+    #
+    while True:
+        hdr = in_file.readline()
+        if not hdr:
+            raise Error('No valid begin line found in input file')
+        if not hdr.startswith('begin'):
+            continue
+        hdrfields = hdr.split(' ', 2)
+        if len(hdrfields) == 3 and hdrfields[0] == 'begin':
+            try:
+                int(hdrfields[1], 8)
+                break
+            except ValueError:
+                pass
+    if out_file is None:
+        out_file = hdrfields[2].rstrip()
+        if os.path.exists(out_file):
+            raise Error('Cannot overwrite existing file: %s' % out_file)
+    if mode is None:
+        mode = int(hdrfields[1], 8)
+    #
+    # Open the output file
+    #
+    opened = False
+    if out_file == '-':
+        out_file = sys.stdout
+    elif isinstance(out_file, basestring):
+        close_out_file = True
+        fp = open(out_file, 'wb')
+        try:
+            os.path.chmod(out_file, mode)
+        except AttributeError:
+            pass
+        out_file = fp
+        opened = True
+    #
+    # Main decoding loop
+    #
+    s = in_file.readline()
+    while s and s.strip() != 'end':
+        try:
+            data = binascii.a2b_uu(s)
+        except binascii.Error, v:
+            # Workaround for broken uuencoders by /Fredrik Lundh
+            nbytes = (((ord(s[0])-32) & 63) * 4 + 5) // 3
+            data = binascii.a2b_uu(s[:nbytes])
+            if not quiet:
+                sys.stderr.write("Warning: %s\n" % v)
+        out_file.write(data)
+        s = in_file.readline()
+    if not s:
+        raise Error('Truncated input file')
+    if opened:
+        out_file.close()
+
+    # Jython and other implementations requires files to be explicitly
+    # closed if we don't want to wait for GC
+    if close_in_file:
+        in_file.close()
+    if close_out_file:
+        out_file.close()
+
+def test():
+    """uuencode/uudecode main program"""
+
+    import optparse
+    parser = optparse.OptionParser(usage='usage: %prog [-d] [-t] [input [output]]')
+    parser.add_option('-d', '--decode', dest='decode', help='Decode (instead of encode)?', default=False, action='store_true')
+    parser.add_option('-t', '--text', dest='text', help='data is text, encoded format unix-compatible text?', default=False, action='store_true')
+
+    (options, args) = parser.parse_args()
+    if len(args) > 2:
+        parser.error('incorrect number of arguments')
+        sys.exit(1)
+
+    input = sys.stdin
+    output = sys.stdout
+    if len(args) > 0:
+        input = args[0]
+    if len(args) > 1:
+        output = args[1]
+
+    if options.decode:
+        if options.text:
+            if isinstance(output, basestring):
+                output = open(output, 'w')
+            else:
+                print sys.argv[0], ': cannot do -t to stdout'
+                sys.exit(1)
+        decode(input, output)
+    else:
+        if options.text:
+            if isinstance(input, basestring):
+                input = open(input, 'r')
+            else:
+                print sys.argv[0], ': cannot do -t from stdin'
+                sys.exit(1)
+        encode(input, output)
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/uuid.py b/src/main/resources/PythonLibs/uuid.py
new file mode 100644
index 0000000000000000000000000000000000000000..fdd0c5cbec08c26c2e86aaad4460a44badefb661
--- /dev/null
+++ b/src/main/resources/PythonLibs/uuid.py
@@ -0,0 +1,560 @@
+r"""UUID objects (universally unique identifiers) according to RFC 4122.
+
+This module provides immutable UUID objects (class UUID) and the functions
+uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
+UUIDs as specified in RFC 4122.
+
+If all you want is a unique ID, you should probably call uuid1() or uuid4().
+Note that uuid1() may compromise privacy since it creates a UUID containing
+the computer's network address.  uuid4() creates a random UUID.
+
+Typical usage:
+
+    >>> import uuid
+
+    # make a UUID based on the host ID and current time
+    >>> uuid.uuid1()
+    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
+
+    # make a UUID using an MD5 hash of a namespace UUID and a name
+    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
+    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
+
+    # make a random UUID
+    >>> uuid.uuid4()
+    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
+
+    # make a UUID using a SHA-1 hash of a namespace UUID and a name
+    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
+    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
+
+    # make a UUID from a string of hex digits (braces and hyphens ignored)
+    >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
+
+    # convert a UUID to a string of hex digits in standard form
+    >>> str(x)
+    '00010203-0405-0607-0809-0a0b0c0d0e0f'
+
+    # get the raw 16 bytes of the UUID
+    >>> x.bytes
+    '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
+
+    # make a UUID from a 16-byte string
+    >>> uuid.UUID(bytes=x.bytes)
+    UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
+"""
+
+__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
+
+RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
+    'reserved for NCS compatibility', 'specified in RFC 4122',
+    'reserved for Microsoft compatibility', 'reserved for future definition']
+
+class UUID(object):
+    """Instances of the UUID class represent UUIDs as specified in RFC 4122.
+    UUID objects are immutable, hashable, and usable as dictionary keys.
+    Converting a UUID to a string with str() yields something in the form
+    '12345678-1234-1234-1234-123456789abc'.  The UUID constructor accepts
+    five possible forms: a similar string of hexadecimal digits, or a tuple
+    of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
+    48-bit values respectively) as an argument named 'fields', or a string
+    of 16 bytes (with all the integer fields in big-endian order) as an
+    argument named 'bytes', or a string of 16 bytes (with the first three
+    fields in little-endian order) as an argument named 'bytes_le', or a
+    single 128-bit integer as an argument named 'int'.
+
+    UUIDs have these read-only attributes:
+
+        bytes       the UUID as a 16-byte string (containing the six
+                    integer fields in big-endian byte order)
+
+        bytes_le    the UUID as a 16-byte string (with time_low, time_mid,
+                    and time_hi_version in little-endian byte order)
+
+        fields      a tuple of the six integer fields of the UUID,
+                    which are also available as six individual attributes
+                    and two derived attributes:
+
+            time_low                the first 32 bits of the UUID
+            time_mid                the next 16 bits of the UUID
+            time_hi_version         the next 16 bits of the UUID
+            clock_seq_hi_variant    the next 8 bits of the UUID
+            clock_seq_low           the next 8 bits of the UUID
+            node                    the last 48 bits of the UUID
+
+            time                    the 60-bit timestamp
+            clock_seq               the 14-bit sequence number
+
+        hex         the UUID as a 32-character hexadecimal string
+
+        int         the UUID as a 128-bit integer
+
+        urn         the UUID as a URN as specified in RFC 4122
+
+        variant     the UUID variant (one of the constants RESERVED_NCS,
+                    RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
+
+        version     the UUID version number (1 through 5, meaningful only
+                    when the variant is RFC_4122)
+    """
+
+    def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
+                       int=None, version=None):
+        r"""Create a UUID from either a string of 32 hexadecimal digits,
+        a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
+        in little-endian order as the 'bytes_le' argument, a tuple of six
+        integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
+        8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
+        the 'fields' argument, or a single 128-bit integer as the 'int'
+        argument.  When a string of hex digits is given, curly braces,
+        hyphens, and a URN prefix are all optional.  For example, these
+        expressions all yield the same UUID:
+
+        UUID('{12345678-1234-5678-1234-567812345678}')
+        UUID('12345678123456781234567812345678')
+        UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
+        UUID(bytes='\x12\x34\x56\x78'*4)
+        UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
+                      '\x12\x34\x56\x78\x12\x34\x56\x78')
+        UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
+        UUID(int=0x12345678123456781234567812345678)
+
+        Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
+        be given.  The 'version' argument is optional; if given, the resulting
+        UUID will have its variant and version set according to RFC 4122,
+        overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
+        """
+
+        if [hex, bytes, bytes_le, fields, int].count(None) != 4:
+            raise TypeError('need one of hex, bytes, bytes_le, fields, or int')
+        if hex is not None:
+            hex = hex.replace('urn:', '').replace('uuid:', '')
+            hex = hex.strip('{}').replace('-', '')
+            if len(hex) != 32:
+                raise ValueError('badly formed hexadecimal UUID string')
+            int = long(hex, 16)
+        if bytes_le is not None:
+            if len(bytes_le) != 16:
+                raise ValueError('bytes_le is not a 16-char string')
+            bytes = (bytes_le[3] + bytes_le[2] + bytes_le[1] + bytes_le[0] +
+                     bytes_le[5] + bytes_le[4] + bytes_le[7] + bytes_le[6] +
+                     bytes_le[8:])
+        if bytes is not None:
+            if len(bytes) != 16:
+                raise ValueError('bytes is not a 16-char string')
+            int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
+        if fields is not None:
+            if len(fields) != 6:
+                raise ValueError('fields is not a 6-tuple')
+            (time_low, time_mid, time_hi_version,
+             clock_seq_hi_variant, clock_seq_low, node) = fields
+            if not 0 <= time_low < 1<<32L:
+                raise ValueError('field 1 out of range (need a 32-bit value)')
+            if not 0 <= time_mid < 1<<16L:
+                raise ValueError('field 2 out of range (need a 16-bit value)')
+            if not 0 <= time_hi_version < 1<<16L:
+                raise ValueError('field 3 out of range (need a 16-bit value)')
+            if not 0 <= clock_seq_hi_variant < 1<<8L:
+                raise ValueError('field 4 out of range (need an 8-bit value)')
+            if not 0 <= clock_seq_low < 1<<8L:
+                raise ValueError('field 5 out of range (need an 8-bit value)')
+            if not 0 <= node < 1<<48L:
+                raise ValueError('field 6 out of range (need a 48-bit value)')
+            clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low
+            int = ((time_low << 96L) | (time_mid << 80L) |
+                   (time_hi_version << 64L) | (clock_seq << 48L) | node)
+        if int is not None:
+            if not 0 <= int < 1<<128L:
+                raise ValueError('int is out of range (need a 128-bit value)')
+        if version is not None:
+            if not 1 <= version <= 5:
+                raise ValueError('illegal version number')
+            # Set the variant to RFC 4122.
+            int &= ~(0xc000 << 48L)
+            int |= 0x8000 << 48L
+            # Set the version number.
+            int &= ~(0xf000 << 64L)
+            int |= version << 76L
+        self.__dict__['int'] = int
+
+    def __cmp__(self, other):
+        if isinstance(other, UUID):
+            return cmp(self.int, other.int)
+        return NotImplemented
+
+    def __hash__(self):
+        return hash(self.int)
+
+    def __int__(self):
+        return self.int
+
+    def __repr__(self):
+        return 'UUID(%r)' % str(self)
+
+    def __setattr__(self, name, value):
+        raise TypeError('UUID objects are immutable')
+
+    def __str__(self):
+        hex = '%032x' % self.int
+        return '%s-%s-%s-%s-%s' % (
+            hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
+
+    def get_bytes(self):
+        bytes = ''
+        for shift in range(0, 128, 8):
+            bytes = chr((self.int >> shift) & 0xff) + bytes
+        return bytes
+
+    bytes = property(get_bytes)
+
+    def get_bytes_le(self):
+        bytes = self.bytes
+        return (bytes[3] + bytes[2] + bytes[1] + bytes[0] +
+                bytes[5] + bytes[4] + bytes[7] + bytes[6] + bytes[8:])
+
+    bytes_le = property(get_bytes_le)
+
+    def get_fields(self):
+        return (self.time_low, self.time_mid, self.time_hi_version,
+                self.clock_seq_hi_variant, self.clock_seq_low, self.node)
+
+    fields = property(get_fields)
+
+    def get_time_low(self):
+        return self.int >> 96L
+
+    time_low = property(get_time_low)
+
+    def get_time_mid(self):
+        return (self.int >> 80L) & 0xffff
+
+    time_mid = property(get_time_mid)
+
+    def get_time_hi_version(self):
+        return (self.int >> 64L) & 0xffff
+
+    time_hi_version = property(get_time_hi_version)
+
+    def get_clock_seq_hi_variant(self):
+        return (self.int >> 56L) & 0xff
+
+    clock_seq_hi_variant = property(get_clock_seq_hi_variant)
+
+    def get_clock_seq_low(self):
+        return (self.int >> 48L) & 0xff
+
+    clock_seq_low = property(get_clock_seq_low)
+
+    def get_time(self):
+        return (((self.time_hi_version & 0x0fffL) << 48L) |
+                (self.time_mid << 32L) | self.time_low)
+
+    time = property(get_time)
+
+    def get_clock_seq(self):
+        return (((self.clock_seq_hi_variant & 0x3fL) << 8L) |
+                self.clock_seq_low)
+
+    clock_seq = property(get_clock_seq)
+
+    def get_node(self):
+        return self.int & 0xffffffffffff
+
+    node = property(get_node)
+
+    def get_hex(self):
+        return '%032x' % self.int
+
+    hex = property(get_hex)
+
+    def get_urn(self):
+        return 'urn:uuid:' + str(self)
+
+    urn = property(get_urn)
+
+    def get_variant(self):
+        if not self.int & (0x8000 << 48L):
+            return RESERVED_NCS
+        elif not self.int & (0x4000 << 48L):
+            return RFC_4122
+        elif not self.int & (0x2000 << 48L):
+            return RESERVED_MICROSOFT
+        else:
+            return RESERVED_FUTURE
+
+    variant = property(get_variant)
+
+    def get_version(self):
+        # The version bits are only meaningful for RFC 4122 UUIDs.
+        if self.variant == RFC_4122:
+            return int((self.int >> 76L) & 0xf)
+
+    version = property(get_version)
+
+def _find_mac(command, args, hw_identifiers, get_index):
+    import os
+    for dir in ['', '/sbin/', '/usr/sbin']:
+        executable = os.path.join(dir, command)
+        if not os.path.exists(executable):
+            continue
+
+        try:
+            # LC_ALL to get English output, 2>/dev/null to
+            # prevent output on stderr
+            cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args)
+            with os.popen(cmd) as pipe:
+                for line in pipe:
+                    words = line.lower().split()
+                    for i in range(len(words)):
+                        if words[i] in hw_identifiers:
+                            return int(
+                                words[get_index(i)].replace(':', ''), 16)
+        except IOError:
+            continue
+    return None
+
+def _ifconfig_getnode():
+    """Get the hardware address on Unix by running ifconfig."""
+
+    # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
+    for args in ('', '-a', '-av'):
+        mac = _find_mac('ifconfig', args, ['hwaddr', 'ether'], lambda i: i+1)
+        if mac:
+            return mac
+
+    import socket
+    ip_addr = socket.gethostbyname(socket.gethostname())
+
+    # Try getting the MAC addr from arp based on our IP address (Solaris).
+    mac = _find_mac('arp', '-an', [ip_addr], lambda i: -1)
+    if mac:
+        return mac
+
+    # This might work on HP-UX.
+    mac = _find_mac('lanscan', '-ai', ['lan0'], lambda i: 0)
+    if mac:
+        return mac
+
+    return None
+
+def _ipconfig_getnode():
+    """Get the hardware address on Windows by running ipconfig.exe."""
+    import os, re
+    dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
+    try:
+        import ctypes
+        buffer = ctypes.create_string_buffer(300)
+        ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
+        dirs.insert(0, buffer.value.decode('mbcs'))
+    except:
+        pass
+    for dir in dirs:
+        try:
+            pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all')
+        except IOError:
+            continue
+        else:
+            for line in pipe:
+                value = line.split(':')[-1].strip().lower()
+                if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
+                    return int(value.replace('-', ''), 16)
+        finally:
+            pipe.close()
+
+def _netbios_getnode():
+    """Get the hardware address on Windows using NetBIOS calls.
+    See http://support.microsoft.com/kb/118623 for details."""
+    import win32wnet, netbios
+    ncb = netbios.NCB()
+    ncb.Command = netbios.NCBENUM
+    ncb.Buffer = adapters = netbios.LANA_ENUM()
+    adapters._pack()
+    if win32wnet.Netbios(ncb) != 0:
+        return
+    adapters._unpack()
+    for i in range(adapters.length):
+        ncb.Reset()
+        ncb.Command = netbios.NCBRESET
+        ncb.Lana_num = ord(adapters.lana[i])
+        if win32wnet.Netbios(ncb) != 0:
+            continue
+        ncb.Reset()
+        ncb.Command = netbios.NCBASTAT
+        ncb.Lana_num = ord(adapters.lana[i])
+        ncb.Callname = '*'.ljust(16)
+        ncb.Buffer = status = netbios.ADAPTER_STATUS()
+        if win32wnet.Netbios(ncb) != 0:
+            continue
+        status._unpack()
+        bytes = map(ord, status.adapter_address)
+        return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) +
+                (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5])
+
+# Thanks to Thomas Heller for ctypes and for his help with its use here.
+
+# If ctypes is available, use it to find system routines for UUID generation.
+_uuid_generate_random = _uuid_generate_time = _UuidCreate = None
+try:
+    import ctypes, ctypes.util
+
+    # The uuid_generate_* routines are provided by libuuid on at least
+    # Linux and FreeBSD, and provided by libc on Mac OS X.
+    for libname in ['uuid', 'c']:
+        try:
+            lib = ctypes.CDLL(ctypes.util.find_library(libname))
+        except:
+            continue
+        if hasattr(lib, 'uuid_generate_random'):
+            _uuid_generate_random = lib.uuid_generate_random
+        if hasattr(lib, 'uuid_generate_time'):
+            _uuid_generate_time = lib.uuid_generate_time
+
+    # The uuid_generate_* functions are broken on MacOS X 10.5, as noted
+    # in issue #8621 the function generates the same sequence of values
+    # in the parent process and all children created using fork (unless
+    # those children use exec as well).
+    #
+    # Assume that the uuid_generate functions are broken from 10.5 onward,
+    # the test can be adjusted when a later version is fixed.
+    import sys
+    if sys.platform == 'darwin':
+        import os
+        if int(os.uname()[2].split('.')[0]) >= 9:
+            _uuid_generate_random = _uuid_generate_time = None
+
+    # On Windows prior to 2000, UuidCreate gives a UUID containing the
+    # hardware address.  On Windows 2000 and later, UuidCreate makes a
+    # random UUID and UuidCreateSequential gives a UUID containing the
+    # hardware address.  These routines are provided by the RPC runtime.
+    # NOTE:  at least on Tim's WinXP Pro SP2 desktop box, while the last
+    # 6 bytes returned by UuidCreateSequential are fixed, they don't appear
+    # to bear any relationship to the MAC address of any network device
+    # on the box.
+    try:
+        lib = ctypes.windll.rpcrt4
+    except:
+        lib = None
+    _UuidCreate = getattr(lib, 'UuidCreateSequential',
+                          getattr(lib, 'UuidCreate', None))
+except:
+    pass
+
+def _unixdll_getnode():
+    """Get the hardware address on Unix using ctypes."""
+    _buffer = ctypes.create_string_buffer(16)
+    _uuid_generate_time(_buffer)
+    return UUID(bytes=_buffer.raw).node
+
+def _windll_getnode():
+    """Get the hardware address on Windows using ctypes."""
+    _buffer = ctypes.create_string_buffer(16)
+    if _UuidCreate(_buffer) == 0:
+        return UUID(bytes=_buffer.raw).node
+
+def _random_getnode():
+    """Get a random node ID, with eighth bit set as suggested by RFC 4122."""
+    import random
+    return random.randrange(0, 1<<48L) | 0x010000000000L
+
+_node = None
+
+def getnode():
+    """Get the hardware address as a 48-bit positive integer.
+
+    The first time this runs, it may launch a separate program, which could
+    be quite slow.  If all attempts to obtain the hardware address fail, we
+    choose a random 48-bit number with its eighth bit set to 1 as recommended
+    in RFC 4122.
+    """
+
+    global _node
+    if _node is not None:
+        return _node
+
+    import sys
+    if sys.platform == 'win32':
+        getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
+    else:
+        getters = [_unixdll_getnode, _ifconfig_getnode]
+
+    for getter in getters + [_random_getnode]:
+        try:
+            _node = getter()
+        except:
+            continue
+        if _node is not None:
+            return _node
+
+_last_timestamp = None
+
+def uuid1(node=None, clock_seq=None):
+    """Generate a UUID from a host ID, sequence number, and the current time.
+    If 'node' is not given, getnode() is used to obtain the hardware
+    address.  If 'clock_seq' is given, it is used as the sequence number;
+    otherwise a random 14-bit sequence number is chosen."""
+
+    # When the system provides a version-1 UUID generator, use it (but don't
+    # use UuidCreate here because its UUIDs don't conform to RFC 4122).
+    if _uuid_generate_time and node is clock_seq is None:
+        _buffer = ctypes.create_string_buffer(16)
+        _uuid_generate_time(_buffer)
+        return UUID(bytes=_buffer.raw)
+
+    global _last_timestamp
+    import time
+    nanoseconds = int(time.time() * 1e9)
+    # 0x01b21dd213814000 is the number of 100-ns intervals between the
+    # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
+    timestamp = int(nanoseconds//100) + 0x01b21dd213814000L
+    if _last_timestamp is not None and timestamp <= _last_timestamp:
+        timestamp = _last_timestamp + 1
+    _last_timestamp = timestamp
+    if clock_seq is None:
+        import random
+        clock_seq = random.randrange(1<<14L) # instead of stable storage
+    time_low = timestamp & 0xffffffffL
+    time_mid = (timestamp >> 32L) & 0xffffL
+    time_hi_version = (timestamp >> 48L) & 0x0fffL
+    clock_seq_low = clock_seq & 0xffL
+    clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL
+    if node is None:
+        node = getnode()
+    return UUID(fields=(time_low, time_mid, time_hi_version,
+                        clock_seq_hi_variant, clock_seq_low, node), version=1)
+
+def uuid3(namespace, name):
+    """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
+    from hashlib import md5
+    hash = md5(namespace.bytes + name).digest()
+    return UUID(bytes=hash[:16], version=3)
+
+def uuid4():
+    """Generate a random UUID."""
+
+    # When the system provides a version-4 UUID generator, use it.
+    if _uuid_generate_random:
+        _buffer = ctypes.create_string_buffer(16)
+        _uuid_generate_random(_buffer)
+        return UUID(bytes=_buffer.raw)
+
+    # Otherwise, get randomness from urandom or the 'random' module.
+    try:
+        import os
+        return UUID(bytes=os.urandom(16), version=4)
+    except:
+        import random
+        bytes = [chr(random.randrange(256)) for i in range(16)]
+        return UUID(bytes=bytes, version=4)
+
+def uuid5(namespace, name):
+    """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
+    from hashlib import sha1
+    hash = sha1(namespace.bytes + name).digest()
+    return UUID(bytes=hash[:16], version=5)
+
+# The following standard UUIDs are for use with uuid3() or uuid5().
+
+NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
+NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
+NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
+NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')
diff --git a/src/main/resources/PythonLibs/warnings.py b/src/main/resources/PythonLibs/warnings.py
new file mode 100644
index 0000000000000000000000000000000000000000..0668e7681d88d20eb0a6df0e163187a78ade4c38
--- /dev/null
+++ b/src/main/resources/PythonLibs/warnings.py
@@ -0,0 +1,424 @@
+"""Python part of the warnings subsystem."""
+
+# Note: function level imports should *not* be used
+# in this module as it may cause import lock deadlock.
+# See bug 683658.
+import linecache
+import sys
+import types
+
+__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
+           "resetwarnings", "catch_warnings"]
+
+def warnpy3k(message, category=None, stacklevel=1):
+    """Issue a deprecation warning for Python 3.x related changes.
+
+    Warnings are omitted unless Python is started with the -3 option.
+    """
+    if sys.py3kwarning:
+        if category is None:
+            category = DeprecationWarning
+        warn(message, category, stacklevel+1)
+
+def _show_warning(message, category, filename, lineno, file=None, line=None):
+    """Hook to write a warning to a file; replace if you like."""
+    if file is None:
+        file = sys.stderr
+    try:
+        file.write(formatwarning(message, category, filename, lineno, line))
+    except IOError:
+        pass # the file (probably stderr) is invalid - this warning gets lost.
+# Keep a working version around in case the deprecation of the old API is
+# triggered.
+showwarning = _show_warning
+
+def formatwarning(message, category, filename, lineno, line=None):
+    """Function to format a warning the standard way."""
+    s =  "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
+    line = linecache.getline(filename, lineno) if line is None else line
+    if line:
+        line = line.strip()
+        s += "  %s\n" % line
+    return s
+
+def filterwarnings(action, message="", category=Warning, module="", lineno=0,
+                   append=0):
+    """Insert an entry into the list of warnings filters (at the front).
+
+    'action' -- one of "error", "ignore", "always", "default", "module",
+                or "once"
+    'message' -- a regex that the warning message must match
+    'category' -- a class that the warning must be a subclass of
+    'module' -- a regex that the module name must match
+    'lineno' -- an integer line number, 0 matches all warnings
+    'append' -- if true, append to the list of filters
+    """
+    import re
+    assert action in ("error", "ignore", "always", "default", "module",
+                      "once"), "invalid action: %r" % (action,)
+    assert isinstance(message, basestring), "message must be a string"
+    assert isinstance(category, (type, types.ClassType)), \
+           "category must be a class"
+    assert issubclass(category, Warning), "category must be a Warning subclass"
+    assert isinstance(module, basestring), "module must be a string"
+    assert isinstance(lineno, int) and lineno >= 0, \
+           "lineno must be an int >= 0"
+    item = (action, re.compile(message, re.I), category,
+            re.compile(module), lineno)
+    if append:
+        filters.append(item)
+    else:
+        filters.insert(0, item)
+
+def simplefilter(action, category=Warning, lineno=0, append=0):
+    """Insert a simple entry into the list of warnings filters (at the front).
+
+    A simple filter matches all modules and messages.
+    'action' -- one of "error", "ignore", "always", "default", "module",
+                or "once"
+    'category' -- a class that the warning must be a subclass of
+    'lineno' -- an integer line number, 0 matches all warnings
+    'append' -- if true, append to the list of filters
+    """
+    assert action in ("error", "ignore", "always", "default", "module",
+                      "once"), "invalid action: %r" % (action,)
+    assert isinstance(lineno, int) and lineno >= 0, \
+           "lineno must be an int >= 0"
+    item = (action, None, category, None, lineno)
+    if append:
+        filters.append(item)
+    else:
+        filters.insert(0, item)
+
+def resetwarnings():
+    """Clear the list of warning filters, so that no filters are active."""
+    filters[:] = []
+
+class _OptionError(Exception):
+    """Exception used by option processing helpers."""
+    pass
+
+# Helper to process -W options passed via sys.warnoptions
+def _processoptions(args):
+    for arg in args:
+        try:
+            _setoption(arg)
+        except _OptionError, msg:
+            print >>sys.stderr, "Invalid -W option ignored:", msg
+
+# Helper for _processoptions()
+def _setoption(arg):
+    import re
+    parts = arg.split(':')
+    if len(parts) > 5:
+        raise _OptionError("too many fields (max 5): %r" % (arg,))
+    while len(parts) < 5:
+        parts.append('')
+    action, message, category, module, lineno = [s.strip()
+                                                 for s in parts]
+    action = _getaction(action)
+    message = re.escape(message)
+    category = _getcategory(category)
+    module = re.escape(module)
+    if module:
+        module = module + '$'
+    if lineno:
+        try:
+            lineno = int(lineno)
+            if lineno < 0:
+                raise ValueError
+        except (ValueError, OverflowError):
+            raise _OptionError("invalid lineno %r" % (lineno,))
+    else:
+        lineno = 0
+    filterwarnings(action, message, category, module, lineno)
+
+# Helper for _setoption()
+def _getaction(action):
+    if not action:
+        return "default"
+    if action == "all": return "always" # Alias
+    for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
+        if a.startswith(action):
+            return a
+    raise _OptionError("invalid action: %r" % (action,))
+
+# Helper for _setoption()
+def _getcategory(category):
+    import re
+    if not category:
+        return Warning
+    if re.match("^[a-zA-Z0-9_]+$", category):
+        try:
+            cat = eval(category)
+        except NameError:
+            raise _OptionError("unknown warning category: %r" % (category,))
+    else:
+        i = category.rfind(".")
+        module = category[:i]
+        klass = category[i+1:]
+        try:
+            m = __import__(module, None, None, [klass])
+        except ImportError:
+            raise _OptionError("invalid module name: %r" % (module,))
+        try:
+            cat = getattr(m, klass)
+        except AttributeError:
+            raise _OptionError("unknown warning category: %r" % (category,))
+    if not issubclass(cat, Warning):
+        raise _OptionError("invalid warning category: %r" % (category,))
+    return cat
+
+class SysGlobals:
+    '''sys.__dict__ values are reflectedfields, so we use this.'''
+    def __getitem__(self, key):
+        try:
+            return getattr(sys, key)
+        except AttributeError:
+            raise KeyError(key)
+
+    def get(self, key, default=None):
+        if key in self:
+            return self[key]
+        return default
+
+    def setdefault(self, key, default=None):
+        if key not in self:
+            sys.__dict__[key] = default
+        return self[key]
+
+    def __contains__(self, key):
+        return key in sys.__dict__
+
+# Code typically replaced by _warnings
+def warn(message, category=None, stacklevel=1):
+    """Issue a warning, or maybe ignore it or raise an exception."""
+    # Check if message is already a Warning object
+    if isinstance(message, Warning):
+        category = message.__class__
+    # Check category argument
+    if category is None:
+        category = UserWarning
+    assert issubclass(category, Warning)
+    # Get context information
+    try:
+        caller = sys._getframe(stacklevel)
+    except ValueError:
+        globals = SysGlobals()
+        lineno = 1
+    else:
+        globals = caller.f_globals
+        lineno = caller.f_lineno
+    if '__name__' in globals:
+        module = globals['__name__']
+    else:
+        module = "<string>"
+    filename = globals.get('__file__')
+    if filename:
+        fnl = filename.lower()
+        if fnl.endswith((".pyc", ".pyo")):
+            filename = filename[:-1]
+        elif fnl.endswith("$py.class"):
+            filename = filename[:-9] + '.py'
+    else:
+        if module == "__main__":
+            try:
+                filename = sys.argv[0]
+            except (AttributeError, TypeError):
+                # embedded interpreters don't have sys.argv, see bug #839151
+                filename = '__main__'
+        if not filename:
+            filename = module
+    registry = globals.setdefault("__warningregistry__", {})
+    warn_explicit(message, category, filename, lineno, module, registry,
+                  globals)
+
+def warn_explicit(message, category, filename, lineno,
+                  module=None, registry=None, module_globals=None):
+    lineno = int(lineno)
+    if module is None:
+        module = filename or "<unknown>"
+        if module[-3:].lower() == ".py":
+            module = module[:-3] # XXX What about leading pathname?
+    if registry is None:
+        registry = {}
+    if isinstance(message, Warning):
+        text = str(message)
+        category = message.__class__
+    else:
+        text = message
+        message = category(message)
+    key = (text, category, lineno)
+    # Quick test for common case
+    if registry.get(key):
+        return
+    # Search the filters
+    for item in globals().get('filters', _filters):
+        action, msg, cat, mod, ln = item
+        if ((msg is None or msg.match(text)) and
+            issubclass(category, cat) and
+            (mod is None or mod.match(module)) and
+            (ln == 0 or lineno == ln)):
+            break
+    else:
+        action = globals().get('defaultaction', default_action)
+    # Early exit actions
+    if action == "ignore":
+        registry[key] = 1
+        return
+
+    # Prime the linecache for formatting, in case the
+    # "file" is actually in a zipfile or something.
+    linecache.getlines(filename, module_globals)
+
+    if action == "error":
+        raise message
+    # Other actions
+    if action == "once":
+        _onceregistry = globals().get('onceregistry', once_registry)
+        registry[key] = 1
+        oncekey = (text, category)
+        if _onceregistry.get(oncekey):
+            return
+        _onceregistry[oncekey] = 1
+    elif action == "always":
+        pass
+    elif action == "module":
+        registry[key] = 1
+        altkey = (text, category, 0)
+        if registry.get(altkey):
+            return
+        registry[altkey] = 1
+    elif action == "default":
+        registry[key] = 1
+    else:
+        # Unrecognized actions are errors
+        raise RuntimeError(
+              "Unrecognized action (%r) in warnings.filters:\n %s" %
+              (action, item))
+    # Print message and context
+    fn = globals().get('showwarning', _show_warning)
+    fn(message, category, filename, lineno)
+
+
+class WarningMessage(object):
+
+    """Holds the result of a single showwarning() call."""
+
+    _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
+                        "line")
+
+    def __init__(self, message, category, filename, lineno, file=None,
+                    line=None):
+        local_values = locals()
+        for attr in self._WARNING_DETAILS:
+            setattr(self, attr, local_values[attr])
+        self._category_name = category.__name__ if category else None
+
+    def __str__(self):
+        return ("{message : %r, category : %r, filename : %r, lineno : %s, "
+                    "line : %r}" % (self.message, self._category_name,
+                                    self.filename, self.lineno, self.line))
+
+
+class catch_warnings(object):
+
+    """A context manager that copies and restores the warnings filter upon
+    exiting the context.
+
+    The 'record' argument specifies whether warnings should be captured by a
+    custom implementation of warnings.showwarning() and be appended to a list
+    returned by the context manager. Otherwise None is returned by the context
+    manager. The objects appended to the list are arguments whose attributes
+    mirror the arguments to showwarning().
+
+    The 'module' argument is to specify an alternative module to the module
+    named 'warnings' and imported under that name. This argument is only useful
+    when testing the warnings module itself.
+
+    """
+
+    def __init__(self, record=False, module=None):
+        """Specify whether to record warnings and if an alternative module
+        should be used other than sys.modules['warnings'].
+
+        For compatibility with Python 3.0, please consider all arguments to be
+        keyword-only.
+
+        """
+        self._record = record
+        self._module = sys.modules['warnings'] if module is None else module
+        self._entered = False
+
+    def __repr__(self):
+        args = []
+        if self._record:
+            args.append("record=True")
+        if self._module is not sys.modules['warnings']:
+            args.append("module=%r" % self._module)
+        name = type(self).__name__
+        return "%s(%s)" % (name, ", ".join(args))
+
+    def __enter__(self):
+        if self._entered:
+            raise RuntimeError("Cannot enter %r twice" % self)
+        self._entered = True
+        self._filters = self._module.filters
+        self._module.filters = self._module._filters = self._filters[:]
+        self._showwarning = self._module.showwarning
+        if self._record:
+            log = []
+            def showwarning(*args, **kwargs):
+                log.append(WarningMessage(*args, **kwargs))
+            self._module.showwarning = showwarning
+            return log
+        else:
+            return None
+
+    def __exit__(self, *exc_info):
+        if not self._entered:
+            raise RuntimeError("Cannot exit %r without entering first" % self)
+        self._module.filters = self._module._filters = self._filters
+        self._module.showwarning = self._showwarning
+
+
+# filters contains a sequence of filter 5-tuples
+# The components of the 5-tuple are:
+# - an action: error, ignore, always, default, module, or once
+# - a compiled regex that must match the warning message
+# - a class representing the warning category
+# - a compiled regex that must match the module that is being warned
+# - a line number for the line being warning, or 0 to mean any line
+# If either if the compiled regexs are None, match anything.
+_warnings_defaults = False
+try:
+    from _warnings import (filters, default_action, once_registry,
+                            warn, warn_explicit)
+    defaultaction = default_action
+    onceregistry = once_registry
+    _warnings_defaults = True
+    _filters = filters
+except ImportError:
+    filters = _filters = []
+    defaultaction = default_action = "default"
+    onceregistry = once_registry = {}
+
+
+# Module initialization
+_processoptions(sys.warnoptions)
+if not _warnings_defaults:
+    silence = [ImportWarning, PendingDeprecationWarning]
+    # Don't silence DeprecationWarning if -3 or -Q was used.
+    if not sys.py3kwarning and not sys.flags.division_warning:
+        silence.append(DeprecationWarning)
+    for cls in silence:
+        simplefilter("ignore", category=cls)
+    bytes_warning = sys.flags.bytes_warning
+    if bytes_warning > 1:
+        bytes_action = "error"
+    elif bytes_warning:
+        bytes_action = "default"
+    else:
+        bytes_action = "ignore"
+    simplefilter(bytes_action, category=BytesWarning, append=1)
+del _warnings_defaults
diff --git a/src/main/resources/PythonLibs/weakref.py b/src/main/resources/PythonLibs/weakref.py
new file mode 100644
index 0000000000000000000000000000000000000000..e905c643f3247e1c1d754f82611a29ebdcbb715a
--- /dev/null
+++ b/src/main/resources/PythonLibs/weakref.py
@@ -0,0 +1,385 @@
+"""Weak reference support for Python.
+
+This module is an implementation of PEP 205:
+
+http://www.python.org/dev/peps/pep-0205/
+"""
+
+# Naming convention: Variables named "wr" are weak reference objects;
+# they are called this instead of "ref" to avoid name collisions with
+# the module-global ref() function imported from _weakref.
+
+import UserDict
+
+from _weakref import (
+     getweakrefcount,
+     getweakrefs,
+     ref,
+     proxy,
+     CallableProxyType,
+     ProxyType,
+     ReferenceType)
+
+from _weakrefset import WeakSet
+
+from exceptions import ReferenceError
+
+
+ProxyTypes = (ProxyType, CallableProxyType)
+
+__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
+           "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType",
+           "CallableProxyType", "ProxyTypes", "WeakValueDictionary", 'WeakSet']
+
+
+class WeakValueDictionary(UserDict.UserDict):
+    """Mapping class that references values weakly.
+
+    Entries in the dictionary will be discarded when no strong
+    reference to the value exists anymore
+    """
+    # We inherit the constructor without worrying about the input
+    # dictionary; since it uses our .update() method, we get the right
+    # checks (if the other dictionary is a WeakValueDictionary,
+    # objects are unwrapped on the way out, and we always wrap on the
+    # way in).
+
+    def __init__(self, *args, **kw):
+        def remove(wr, selfref=ref(self)):
+            self = selfref()
+            if self is not None:
+                try:
+                    del self.data[wr.key]
+                except KeyError:
+                    pass
+        self._remove = remove
+        UserDict.UserDict.__init__(self, *args, **kw)
+
+    def __getitem__(self, key):
+        o = self.data[key]()
+        if o is None:
+            raise KeyError, key
+        else:
+            return o
+
+    def __contains__(self, key):
+        try:
+            o = self.data[key]()
+        except KeyError:
+            return False
+        return o is not None
+
+    def has_key(self, key):
+        try:
+            o = self.data[key]()
+        except KeyError:
+            return False
+        return o is not None
+
+    def __repr__(self):
+        return "<WeakValueDictionary at %s>" % id(self)
+
+    def __setitem__(self, key, value):
+        self.data[key] = KeyedRef(value, self._remove, key)
+
+    def copy(self):
+        new = WeakValueDictionary()
+        for key, wr in self.data.items():
+            o = wr()
+            if o is not None:
+                new[key] = o
+        return new
+
+    __copy__ = copy
+
+    def __deepcopy__(self, memo):
+        from copy import deepcopy
+        new = self.__class__()
+        for key, wr in self.data.items():
+            o = wr()
+            if o is not None:
+                new[deepcopy(key, memo)] = o
+        return new
+
+    def get(self, key, default=None):
+        try:
+            wr = self.data[key]
+        except KeyError:
+            return default
+        else:
+            o = wr()
+            if o is None:
+                # This should only happen
+                return default
+            else:
+                return o
+
+    def items(self):
+        L = []
+        for key, wr in self.data.items():
+            o = wr()
+            if o is not None:
+                L.append((key, o))
+        return L
+
+    def iteritems(self):
+        for wr in self.data.itervalues():
+            value = wr()
+            if value is not None:
+                yield wr.key, value
+
+    def iterkeys(self):
+        return self.data.iterkeys()
+
+    def __iter__(self):
+        return self.data.iterkeys()
+
+    def itervaluerefs(self):
+        """Return an iterator that yields the weak references to the values.
+
+        The references are not guaranteed to be 'live' at the time
+        they are used, so the result of calling the references needs
+        to be checked before being used.  This can be used to avoid
+        creating references that will cause the garbage collector to
+        keep the values around longer than needed.
+
+        """
+        return self.data.itervalues()
+
+    def itervalues(self):
+        for wr in self.data.itervalues():
+            obj = wr()
+            if obj is not None:
+                yield obj
+
+    def popitem(self):
+        while 1:
+            key, wr = self.data.popitem()
+            o = wr()
+            if o is not None:
+                return key, o
+
+    def pop(self, key, *args):
+        try:
+            o = self.data.pop(key)()
+        except KeyError:
+            if args:
+                return args[0]
+            raise
+        if o is None:
+            raise KeyError, key
+        else:
+            return o
+
+    def setdefault(self, key, default=None):
+        try:
+            wr = self.data[key]
+        except KeyError:
+            self.data[key] = KeyedRef(default, self._remove, key)
+            return default
+        else:
+            return wr()
+
+    def update(self, dict=None, **kwargs):
+        d = self.data
+        if dict is not None:
+            if not hasattr(dict, "items"):
+                dict = type({})(dict)
+            for key, o in dict.items():
+                d[key] = KeyedRef(o, self._remove, key)
+        if len(kwargs):
+            self.update(kwargs)
+
+    def valuerefs(self):
+        """Return a list of weak references to the values.
+
+        The references are not guaranteed to be 'live' at the time
+        they are used, so the result of calling the references needs
+        to be checked before being used.  This can be used to avoid
+        creating references that will cause the garbage collector to
+        keep the values around longer than needed.
+
+        """
+        return self.data.values()
+
+    def values(self):
+        L = []
+        for wr in self.data.values():
+            o = wr()
+            if o is not None:
+                L.append(o)
+        return L
+
+
+class KeyedRef(ref):
+    """Specialized reference that includes a key corresponding to the value.
+
+    This is used in the WeakValueDictionary to avoid having to create
+    a function object for each key stored in the mapping.  A shared
+    callback object can use the 'key' attribute of a KeyedRef instead
+    of getting a reference to the key from an enclosing scope.
+
+    """
+
+    __slots__ = "key",
+
+    def __new__(type, ob, callback, key):
+        self = ref.__new__(type, ob, callback)
+        self.key = key
+        return self
+
+    def __init__(self, ob, callback, key):
+        super(KeyedRef,  self).__init__(ob, callback)
+
+
+class WeakKeyDictionary(UserDict.UserDict):
+    """ Mapping class that references keys weakly.
+
+    Entries in the dictionary will be discarded when there is no
+    longer a strong reference to the key. This can be used to
+    associate additional data with an object owned by other parts of
+    an application without adding attributes to those objects. This
+    can be especially useful with objects that override attribute
+    accesses.
+    """
+
+    def __init__(self, dict=None):
+        self.data = {}
+        def remove(k, selfref=ref(self)):
+            self = selfref()
+            if self is not None:
+                try:
+                    del self.data[k]
+                except KeyError:
+                    pass
+        self._remove = remove
+        if dict is not None: self.update(dict)
+
+    def __delitem__(self, key):
+        del self.data[ref(key)]
+
+    def __getitem__(self, key):
+        return self.data[ref(key)]
+
+    def __repr__(self):
+        return "<WeakKeyDictionary at %s>" % id(self)
+
+    def __setitem__(self, key, value):
+        self.data[ref(key, self._remove)] = value
+
+    def copy(self):
+        new = WeakKeyDictionary()
+        for key, value in self.data.items():
+            o = key()
+            if o is not None:
+                new[o] = value
+        return new
+
+    __copy__ = copy
+
+    def __deepcopy__(self, memo):
+        from copy import deepcopy
+        new = self.__class__()
+        for key, value in self.data.items():
+            o = key()
+            if o is not None:
+                new[o] = deepcopy(value, memo)
+        return new
+
+    def get(self, key, default=None):
+        return self.data.get(ref(key),default)
+
+    def has_key(self, key):
+        try:
+            wr = ref(key)
+        except TypeError:
+            return 0
+        return wr in self.data
+
+    def __contains__(self, key):
+        try:
+            wr = ref(key)
+        except TypeError:
+            return 0
+        return wr in self.data
+
+    def items(self):
+        L = []
+        for key, value in self.data.items():
+            o = key()
+            if o is not None:
+                L.append((o, value))
+        return L
+
+    def iteritems(self):
+        for wr, value in self.data.iteritems():
+            key = wr()
+            if key is not None:
+                yield key, value
+
+    def iterkeyrefs(self):
+        """Return an iterator that yields the weak references to the keys.
+
+        The references are not guaranteed to be 'live' at the time
+        they are used, so the result of calling the references needs
+        to be checked before being used.  This can be used to avoid
+        creating references that will cause the garbage collector to
+        keep the keys around longer than needed.
+
+        """
+        return self.data.iterkeys()
+
+    def iterkeys(self):
+        for wr in self.data.iterkeys():
+            obj = wr()
+            if obj is not None:
+                yield obj
+
+    def __iter__(self):
+        return self.iterkeys()
+
+    def itervalues(self):
+        return self.data.itervalues()
+
+    def keyrefs(self):
+        """Return a list of weak references to the keys.
+
+        The references are not guaranteed to be 'live' at the time
+        they are used, so the result of calling the references needs
+        to be checked before being used.  This can be used to avoid
+        creating references that will cause the garbage collector to
+        keep the keys around longer than needed.
+
+        """
+        return self.data.keys()
+
+    def keys(self):
+        L = []
+        for wr in self.data.keys():
+            o = wr()
+            if o is not None:
+                L.append(o)
+        return L
+
+    def popitem(self):
+        while 1:
+            key, value = self.data.popitem()
+            o = key()
+            if o is not None:
+                return o, value
+
+    def pop(self, key, *args):
+        return self.data.pop(ref(key), *args)
+
+    def setdefault(self, key, default=None):
+        return self.data.setdefault(ref(key, self._remove),default)
+
+    def update(self, dict=None, **kwargs):
+        d = self.data
+        if dict is not None:
+            if not hasattr(dict, "items"):
+                dict = type({})(dict)
+            for key, value in dict.items():
+                d[ref(key, self._remove)] = value
+        if len(kwargs):
+            self.update(kwargs)
diff --git a/src/main/resources/PythonLibs/whichdb.py b/src/main/resources/PythonLibs/whichdb.py
new file mode 100644
index 0000000000000000000000000000000000000000..9071430b154c080c1e7278032e151d8800e7abc2
--- /dev/null
+++ b/src/main/resources/PythonLibs/whichdb.py
@@ -0,0 +1,117 @@
+# !/usr/bin/env python
+"""Guess which db package to use to open a db file."""
+
+import os
+import struct
+import sys
+
+try:
+    import dbm
+    _dbmerror = dbm.error
+except ImportError:
+    dbm = None
+    # just some sort of valid exception which might be raised in the
+    # dbm test
+    _dbmerror = IOError
+
+def whichdb(filename):
+    """Guess which db package to use to open a db file.
+
+    Return values:
+
+    - None if the database file can't be read;
+    - empty string if the file can be read but can't be recognized
+    - the module name (e.g. "dbm" or "gdbm") if recognized.
+
+    Importing the given module may still fail, and opening the
+    database using that module may still fail.
+    """
+
+    # Check for dbm first -- this has a .pag and a .dir file
+    try:
+        f = open(filename + os.extsep + "pag", "rb")
+        f.close()
+        # dbm linked with gdbm on OS/2 doesn't have .dir file
+        if not (dbm.library == "GNU gdbm" and sys.platform == "os2emx"):
+            f = open(filename + os.extsep + "dir", "rb")
+            f.close()
+        return "dbm"
+    except IOError:
+        # some dbm emulations based on Berkeley DB generate a .db file
+        # some do not, but they should be caught by the dbhash checks
+        try:
+            f = open(filename + os.extsep + "db", "rb")
+            f.close()
+            # guarantee we can actually open the file using dbm
+            # kind of overkill, but since we are dealing with emulations
+            # it seems like a prudent step
+            if dbm is not None:
+                d = dbm.open(filename)
+                d.close()
+                return "dbm"
+        except (IOError, _dbmerror):
+            pass
+
+    # Check for dumbdbm next -- this has a .dir and a .dat file
+    try:
+        # First check for presence of files
+        os.stat(filename + os.extsep + "dat")
+        size = os.stat(filename + os.extsep + "dir").st_size
+        # dumbdbm files with no keys are empty
+        if size == 0:
+            return "dumbdbm"
+        f = open(filename + os.extsep + "dir", "rb")
+        try:
+            if f.read(1) in ("'", '"'):
+                return "dumbdbm"
+        finally:
+            f.close()
+    except (OSError, IOError):
+        pass
+
+    # See if the file exists, return None if not
+    try:
+        f = open(filename, "rb")
+    except IOError:
+        return None
+
+    # Read the start of the file -- the magic number
+    s16 = f.read(16)
+    f.close()
+    s = s16[0:4]
+
+    # Return "" if not at least 4 bytes
+    if len(s) != 4:
+        return ""
+
+    # Convert to 4-byte int in native byte order -- return "" if impossible
+    try:
+        (magic,) = struct.unpack("=l", s)
+    except struct.error:
+        return ""
+
+    # Check for GNU dbm
+    if magic in (0x13579ace, 0x13579acd, 0x13579acf):
+        return "gdbm"
+
+    # Check for old Berkeley db hash file format v2
+    if magic in (0x00061561, 0x61150600):
+        return "bsddb185"
+
+    # Later versions of Berkeley db hash file have a 12-byte pad in
+    # front of the file type
+    try:
+        (magic,) = struct.unpack("=l", s16[-4:])
+    except struct.error:
+        return ""
+
+    # Check for BSD hash
+    if magic in (0x00061561, 0x61150600):
+        return "dbhash"
+
+    # Unknown
+    return ""
+
+if __name__ == "__main__":
+    for filename in sys.argv[1:]:
+        print whichdb(filename) or "UNKNOWN", filename
diff --git a/src/main/resources/PythonLibs/wsgiref.egg-info b/src/main/resources/PythonLibs/wsgiref.egg-info
new file mode 100644
index 0000000000000000000000000000000000000000..c0b7893c349dc091b93cb24239f2249e25a7d828
--- /dev/null
+++ b/src/main/resources/PythonLibs/wsgiref.egg-info
@@ -0,0 +1,8 @@
+Metadata-Version: 1.0
+Name: wsgiref
+Version: 0.1.2
+Summary: WSGI (PEP 333) Reference Library
+Author: Phillip J. Eby
+Author-email: web-sig@python.org
+License: PSF or ZPL
+Platform: UNKNOWN
diff --git a/src/main/resources/PythonLibs/wsgiref/__init__.py b/src/main/resources/PythonLibs/wsgiref/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..46c579f8ececc0b52cdde2f74fd6159108d4b311
--- /dev/null
+++ b/src/main/resources/PythonLibs/wsgiref/__init__.py
@@ -0,0 +1,23 @@
+"""wsgiref -- a WSGI (PEP 333) Reference Library
+
+Current Contents:
+
+* util -- Miscellaneous useful functions and wrappers
+
+* headers -- Manage response headers
+
+* handlers -- base classes for server/gateway implementations
+
+* simple_server -- a simple BaseHTTPServer that supports WSGI
+
+* validate -- validation wrapper that sits between an app and a server
+  to detect errors in either
+
+To-Do:
+
+* cgi_gateway -- Run WSGI apps under CGI (pending a deployment standard)
+
+* cgi_wrapper -- Run CGI apps under WSGI
+
+* router -- a simple middleware component that handles URL traversal
+"""
diff --git a/src/main/resources/PythonLibs/wsgiref/handlers.py b/src/main/resources/PythonLibs/wsgiref/handlers.py
new file mode 100644
index 0000000000000000000000000000000000000000..8cb57e223aa0d3c1cd77fb0b67c5aa58c257548d
--- /dev/null
+++ b/src/main/resources/PythonLibs/wsgiref/handlers.py
@@ -0,0 +1,450 @@
+"""Base classes for server/gateway implementations"""
+
+from types import StringType
+from util import FileWrapper, guess_scheme, is_hop_by_hop
+from headers import Headers
+
+import sys, os, time
+
+__all__ = ['BaseHandler', 'SimpleHandler', 'BaseCGIHandler', 'CGIHandler']
+
+try:
+    dict
+except NameError:
+    def dict(items):
+        d = {}
+        for k,v in items:
+            d[k] = v
+        return d
+
+# Uncomment for 2.2 compatibility.
+#try:
+#    True
+#    False
+#except NameError:
+#    True = not None
+#    False = not True
+
+
+# Weekday and month names for HTTP date/time formatting; always English!
+_weekdayname = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
+_monthname = [None, # Dummy so we can use 1-based month numbers
+              "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+              "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+
+def format_date_time(timestamp):
+    year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp)
+    return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
+        _weekdayname[wd], day, _monthname[month], year, hh, mm, ss
+    )
+
+
+class BaseHandler:
+    """Manage the invocation of a WSGI application"""
+
+    # Configuration parameters; can override per-subclass or per-instance
+    wsgi_version = (1,0)
+    wsgi_multithread = True
+    wsgi_multiprocess = True
+    wsgi_run_once = False
+
+    origin_server = True    # We are transmitting direct to client
+    http_version  = "1.0"   # Version that should be used for response
+    server_software = None  # String name of server software, if any
+
+    # os_environ is used to supply configuration from the OS environment:
+    # by default it's a copy of 'os.environ' as of import time, but you can
+    # override this in e.g. your __init__ method.
+    os_environ = dict(os.environ.items())
+
+    # Collaborator classes
+    wsgi_file_wrapper = FileWrapper     # set to None to disable
+    headers_class = Headers             # must be a Headers-like class
+
+    # Error handling (also per-subclass or per-instance)
+    traceback_limit = None  # Print entire traceback to self.get_stderr()
+    error_status = "500 Internal Server Error"
+    error_headers = [('Content-Type','text/plain')]
+    error_body = "A server error occurred.  Please contact the administrator."
+
+    # State variables (don't mess with these)
+    status = result = None
+    headers_sent = False
+    headers = None
+    bytes_sent = 0
+
+    def run(self, application):
+        """Invoke the application"""
+        # Note to self: don't move the close()!  Asynchronous servers shouldn't
+        # call close() from finish_response(), so if you close() anywhere but
+        # the double-error branch here, you'll break asynchronous servers by
+        # prematurely closing.  Async servers must return from 'run()' without
+        # closing if there might still be output to iterate over.
+        try:
+            self.setup_environ()
+            self.result = application(self.environ, self.start_response)
+            self.finish_response()
+        except:
+            try:
+                self.handle_error()
+            except:
+                # If we get an error handling an error, just give up already!
+                self.close()
+                raise   # ...and let the actual server figure it out.
+
+
+    def setup_environ(self):
+        """Set up the environment for one request"""
+
+        env = self.environ = self.os_environ.copy()
+        self.add_cgi_vars()
+
+        env['wsgi.input']        = self.get_stdin()
+        env['wsgi.errors']       = self.get_stderr()
+        env['wsgi.version']      = self.wsgi_version
+        env['wsgi.run_once']     = self.wsgi_run_once
+        env['wsgi.url_scheme']   = self.get_scheme()
+        env['wsgi.multithread']  = self.wsgi_multithread
+        env['wsgi.multiprocess'] = self.wsgi_multiprocess
+
+        if self.wsgi_file_wrapper is not None:
+            env['wsgi.file_wrapper'] = self.wsgi_file_wrapper
+
+        if self.origin_server and self.server_software:
+            env.setdefault('SERVER_SOFTWARE',self.server_software)
+
+
+    def finish_response(self):
+        """Send any iterable data, then close self and the iterable
+
+        Subclasses intended for use in asynchronous servers will
+        want to redefine this method, such that it sets up callbacks
+        in the event loop to iterate over the data, and to call
+        'self.close()' once the response is finished.
+        """
+        try:
+            if not self.result_is_file() or not self.sendfile():
+                for data in self.result:
+                    self.write(data)
+                self.finish_content()
+        finally:
+            self.close()
+
+
+    def get_scheme(self):
+        """Return the URL scheme being used"""
+        return guess_scheme(self.environ)
+
+
+    def set_content_length(self):
+        """Compute Content-Length or switch to chunked encoding if possible"""
+        try:
+            blocks = len(self.result)
+        except (TypeError,AttributeError,NotImplementedError):
+            pass
+        else:
+            if blocks==1:
+                self.headers['Content-Length'] = str(self.bytes_sent)
+                return
+        # XXX Try for chunked encoding if origin server and client is 1.1
+
+
+    def cleanup_headers(self):
+        """Make any necessary header changes or defaults
+
+        Subclasses can extend this to add other defaults.
+        """
+        if 'Content-Length' not in self.headers:
+            self.set_content_length()
+
+    def start_response(self, status, headers,exc_info=None):
+        """'start_response()' callable as specified by PEP 333"""
+
+        if exc_info:
+            try:
+                if self.headers_sent:
+                    # Re-raise original exception if headers sent
+                    raise exc_info[0], exc_info[1], exc_info[2]
+            finally:
+                exc_info = None        # avoid dangling circular ref
+        elif self.headers is not None:
+            raise AssertionError("Headers already set!")
+
+        assert type(status) is StringType,"Status must be a string"
+        assert len(status)>=4,"Status must be at least 4 characters"
+        assert int(status[:3]),"Status message must begin w/3-digit code"
+        assert status[3]==" ", "Status message must have a space after code"
+        if __debug__:
+            for name,val in headers:
+                assert type(name) is StringType,"Header names must be strings"
+                assert type(val) is StringType,"Header values must be strings"
+                assert not is_hop_by_hop(name),"Hop-by-hop headers not allowed"
+        self.status = status
+        self.headers = self.headers_class(headers)
+        return self.write
+
+
+    def send_preamble(self):
+        """Transmit version/status/date/server, via self._write()"""
+        if self.origin_server:
+            if self.client_is_modern():
+                self._write('HTTP/%s %s\r\n' % (self.http_version,self.status))
+                if 'Date' not in self.headers:
+                    self._write(
+                        'Date: %s\r\n' % format_date_time(time.time())
+                    )
+                if self.server_software and 'Server' not in self.headers:
+                    self._write('Server: %s\r\n' % self.server_software)
+        else:
+            self._write('Status: %s\r\n' % self.status)
+
+    def write(self, data):
+        """'write()' callable as specified by PEP 333"""
+
+        assert type(data) is StringType,"write() argument must be string"
+
+        if not self.status:
+            raise AssertionError("write() before start_response()")
+
+        elif not self.headers_sent:
+            # Before the first output, send the stored headers
+            self.bytes_sent = len(data)    # make sure we know content-length
+            self.send_headers()
+        else:
+            self.bytes_sent += len(data)
+
+        # XXX check Content-Length and truncate if too many bytes written?
+        self._write(data)
+        self._flush()
+
+
+    def sendfile(self):
+        """Platform-specific file transmission
+
+        Override this method in subclasses to support platform-specific
+        file transmission.  It is only called if the application's
+        return iterable ('self.result') is an instance of
+        'self.wsgi_file_wrapper'.
+
+        This method should return a true value if it was able to actually
+        transmit the wrapped file-like object using a platform-specific
+        approach.  It should return a false value if normal iteration
+        should be used instead.  An exception can be raised to indicate
+        that transmission was attempted, but failed.
+
+        NOTE: this method should call 'self.send_headers()' if
+        'self.headers_sent' is false and it is going to attempt direct
+        transmission of the file.
+        """
+        return False   # No platform-specific transmission by default
+
+
+    def finish_content(self):
+        """Ensure headers and content have both been sent"""
+        if not self.headers_sent:
+            # Only zero Content-Length if not set by the application (so
+            # that HEAD requests can be satisfied properly, see #3839)
+            self.headers.setdefault('Content-Length', "0")
+            self.send_headers()
+        else:
+            pass # XXX check if content-length was too short?
+
+    def close(self):
+        """Close the iterable (if needed) and reset all instance vars
+
+        Subclasses may want to also drop the client connection.
+        """
+        try:
+            if hasattr(self.result,'close'):
+                self.result.close()
+        finally:
+            self.result = self.headers = self.status = self.environ = None
+            self.bytes_sent = 0; self.headers_sent = False
+
+
+    def send_headers(self):
+        """Transmit headers to the client, via self._write()"""
+        self.cleanup_headers()
+        self.headers_sent = True
+        if not self.origin_server or self.client_is_modern():
+            self.send_preamble()
+            self._write(str(self.headers))
+
+
+    def result_is_file(self):
+        """True if 'self.result' is an instance of 'self.wsgi_file_wrapper'"""
+        wrapper = self.wsgi_file_wrapper
+        return wrapper is not None and isinstance(self.result,wrapper)
+
+
+    def client_is_modern(self):
+        """True if client can accept status and headers"""
+        return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
+
+
+    def log_exception(self,exc_info):
+        """Log the 'exc_info' tuple in the server log
+
+        Subclasses may override to retarget the output or change its format.
+        """
+        try:
+            from traceback import print_exception
+            stderr = self.get_stderr()
+            print_exception(
+                exc_info[0], exc_info[1], exc_info[2],
+                self.traceback_limit, stderr
+            )
+            stderr.flush()
+        finally:
+            exc_info = None
+
+    def handle_error(self):
+        """Log current error, and send error output to client if possible"""
+        self.log_exception(sys.exc_info())
+        if not self.headers_sent:
+            self.result = self.error_output(self.environ, self.start_response)
+            self.finish_response()
+        # XXX else: attempt advanced recovery techniques for HTML or text?
+
+    def error_output(self, environ, start_response):
+        """WSGI mini-app to create error output
+
+        By default, this just uses the 'error_status', 'error_headers',
+        and 'error_body' attributes to generate an output page.  It can
+        be overridden in a subclass to dynamically generate diagnostics,
+        choose an appropriate message for the user's preferred language, etc.
+
+        Note, however, that it's not recommended from a security perspective to
+        spit out diagnostics to any old user; ideally, you should have to do
+        something special to enable diagnostic output, which is why we don't
+        include any here!
+        """
+        start_response(self.error_status,self.error_headers[:],sys.exc_info())
+        return [self.error_body]
+
+
+    # Pure abstract methods; *must* be overridden in subclasses
+
+    def _write(self,data):
+        """Override in subclass to buffer data for send to client
+
+        It's okay if this method actually transmits the data; BaseHandler
+        just separates write and flush operations for greater efficiency
+        when the underlying system actually has such a distinction.
+        """
+        raise NotImplementedError
+
+    def _flush(self):
+        """Override in subclass to force sending of recent '_write()' calls
+
+        It's okay if this method is a no-op (i.e., if '_write()' actually
+        sends the data.
+        """
+        raise NotImplementedError
+
+    def get_stdin(self):
+        """Override in subclass to return suitable 'wsgi.input'"""
+        raise NotImplementedError
+
+    def get_stderr(self):
+        """Override in subclass to return suitable 'wsgi.errors'"""
+        raise NotImplementedError
+
+    def add_cgi_vars(self):
+        """Override in subclass to insert CGI variables in 'self.environ'"""
+        raise NotImplementedError
+
+
+class SimpleHandler(BaseHandler):
+    """Handler that's just initialized with streams, environment, etc.
+
+    This handler subclass is intended for synchronous HTTP/1.0 origin servers,
+    and handles sending the entire response output, given the correct inputs.
+
+    Usage::
+
+        handler = SimpleHandler(
+            inp,out,err,env, multithread=False, multiprocess=True
+        )
+        handler.run(app)"""
+
+    def __init__(self,stdin,stdout,stderr,environ,
+        multithread=True, multiprocess=False
+    ):
+        self.stdin = stdin
+        self.stdout = stdout
+        self.stderr = stderr
+        self.base_env = environ
+        self.wsgi_multithread = multithread
+        self.wsgi_multiprocess = multiprocess
+
+    def get_stdin(self):
+        return self.stdin
+
+    def get_stderr(self):
+        return self.stderr
+
+    def add_cgi_vars(self):
+        self.environ.update(self.base_env)
+
+    def _write(self,data):
+        self.stdout.write(data)
+        self._write = self.stdout.write
+
+    def _flush(self):
+        self.stdout.flush()
+        self._flush = self.stdout.flush
+
+
+class BaseCGIHandler(SimpleHandler):
+
+    """CGI-like systems using input/output/error streams and environ mapping
+
+    Usage::
+
+        handler = BaseCGIHandler(inp,out,err,env)
+        handler.run(app)
+
+    This handler class is useful for gateway protocols like ReadyExec and
+    FastCGI, that have usable input/output/error streams and an environment
+    mapping.  It's also the base class for CGIHandler, which just uses
+    sys.stdin, os.environ, and so on.
+
+    The constructor also takes keyword arguments 'multithread' and
+    'multiprocess' (defaulting to 'True' and 'False' respectively) to control
+    the configuration sent to the application.  It sets 'origin_server' to
+    False (to enable CGI-like output), and assumes that 'wsgi.run_once' is
+    False.
+    """
+
+    origin_server = False
+
+
+class CGIHandler(BaseCGIHandler):
+
+    """CGI-based invocation via sys.stdin/stdout/stderr and os.environ
+
+    Usage::
+
+        CGIHandler().run(app)
+
+    The difference between this class and BaseCGIHandler is that it always
+    uses 'wsgi.run_once' of 'True', 'wsgi.multithread' of 'False', and
+    'wsgi.multiprocess' of 'True'.  It does not take any initialization
+    parameters, but always uses 'sys.stdin', 'os.environ', and friends.
+
+    If you need to override any of these parameters, use BaseCGIHandler
+    instead.
+    """
+
+    wsgi_run_once = True
+    # Do not allow os.environ to leak between requests in Google App Engine
+    # and other multi-run CGI use cases.  This is not easily testable.
+    # See http://bugs.python.org/issue7250
+    os_environ = {}
+
+    def __init__(self):
+        BaseCGIHandler.__init__(
+            self, sys.stdin, sys.stdout, sys.stderr, dict(os.environ.items()),
+            multithread=False, multiprocess=True
+        )
diff --git a/src/main/resources/PythonLibs/wsgiref/headers.py b/src/main/resources/PythonLibs/wsgiref/headers.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c8c60c891355d68219c1a1022589fd639504dcf
--- /dev/null
+++ b/src/main/resources/PythonLibs/wsgiref/headers.py
@@ -0,0 +1,169 @@
+"""Manage HTTP Response Headers
+
+Much of this module is red-handedly pilfered from email.message in the stdlib,
+so portions are Copyright (C) 2001,2002 Python Software Foundation, and were
+written by Barry Warsaw.
+"""
+
+from types import ListType, TupleType
+
+# Regular expression that matches `special' characters in parameters, the
+# existence of which force quoting of the parameter value.
+import re
+tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
+
+def _formatparam(param, value=None, quote=1):
+    """Convenience function to format and return a key=value pair.
+
+    This will quote the value if needed or if quote is true.
+    """
+    if value is not None and len(value) > 0:
+        if quote or tspecials.search(value):
+            value = value.replace('\\', '\\\\').replace('"', r'\"')
+            return '%s="%s"' % (param, value)
+        else:
+            return '%s=%s' % (param, value)
+    else:
+        return param
+
+
+class Headers:
+
+    """Manage a collection of HTTP response headers"""
+
+    def __init__(self,headers):
+        if type(headers) is not ListType:
+            raise TypeError("Headers must be a list of name/value tuples")
+        self._headers = headers
+
+    def __len__(self):
+        """Return the total number of headers, including duplicates."""
+        return len(self._headers)
+
+    def __setitem__(self, name, val):
+        """Set the value of a header."""
+        del self[name]
+        self._headers.append((name, val))
+
+    def __delitem__(self,name):
+        """Delete all occurrences of a header, if present.
+
+        Does *not* raise an exception if the header is missing.
+        """
+        name = name.lower()
+        self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name]
+
+    def __getitem__(self,name):
+        """Get the first header value for 'name'
+
+        Return None if the header is missing instead of raising an exception.
+
+        Note that if the header appeared multiple times, the first exactly which
+        occurrance gets returned is undefined.  Use getall() to get all
+        the values matching a header field name.
+        """
+        return self.get(name)
+
+    def has_key(self, name):
+        """Return true if the message contains the header."""
+        return self.get(name) is not None
+
+    __contains__ = has_key
+
+
+    def get_all(self, name):
+        """Return a list of all the values for the named field.
+
+        These will be sorted in the order they appeared in the original header
+        list or were added to this instance, and may contain duplicates.  Any
+        fields deleted and re-inserted are always appended to the header list.
+        If no fields exist with the given name, returns an empty list.
+        """
+        name = name.lower()
+        return [kv[1] for kv in self._headers if kv[0].lower()==name]
+
+
+    def get(self,name,default=None):
+        """Get the first header value for 'name', or return 'default'"""
+        name = name.lower()
+        for k,v in self._headers:
+            if k.lower()==name:
+                return v
+        return default
+
+
+    def keys(self):
+        """Return a list of all the header field names.
+
+        These will be sorted in the order they appeared in the original header
+        list, or were added to this instance, and may contain duplicates.
+        Any fields deleted and re-inserted are always appended to the header
+        list.
+        """
+        return [k for k, v in self._headers]
+
+    def values(self):
+        """Return a list of all header values.
+
+        These will be sorted in the order they appeared in the original header
+        list, or were added to this instance, and may contain duplicates.
+        Any fields deleted and re-inserted are always appended to the header
+        list.
+        """
+        return [v for k, v in self._headers]
+
+    def items(self):
+        """Get all the header fields and values.
+
+        These will be sorted in the order they were in the original header
+        list, or were added to this instance, and may contain duplicates.
+        Any fields deleted and re-inserted are always appended to the header
+        list.
+        """
+        return self._headers[:]
+
+    def __repr__(self):
+        return "Headers(%r)" % self._headers
+
+    def __str__(self):
+        """str() returns the formatted headers, complete with end line,
+        suitable for direct HTTP transmission."""
+        return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['',''])
+
+    def setdefault(self,name,value):
+        """Return first matching header value for 'name', or 'value'
+
+        If there is no header named 'name', add a new header with name 'name'
+        and value 'value'."""
+        result = self.get(name)
+        if result is None:
+            self._headers.append((name,value))
+            return value
+        else:
+            return result
+
+    def add_header(self, _name, _value, **_params):
+        """Extended header setting.
+
+        _name is the header field to add.  keyword arguments can be used to set
+        additional parameters for the header field, with underscores converted
+        to dashes.  Normally the parameter will be added as key="value" unless
+        value is None, in which case only the key will be added.
+
+        Example:
+
+        h.add_header('content-disposition', 'attachment', filename='bud.gif')
+
+        Note that unlike the corresponding 'email.message' method, this does
+        *not* handle '(charset, language, value)' tuples: all values must be
+        strings or None.
+        """
+        parts = []
+        if _value is not None:
+            parts.append(_value)
+        for k, v in _params.items():
+            if v is None:
+                parts.append(k.replace('_', '-'))
+            else:
+                parts.append(_formatparam(k.replace('_', '-'), v))
+        self._headers.append((_name, "; ".join(parts)))
diff --git a/src/main/resources/PythonLibs/wsgiref/simple_server.py b/src/main/resources/PythonLibs/wsgiref/simple_server.py
new file mode 100644
index 0000000000000000000000000000000000000000..e6a385b03c74d3a63d2c34a9ab978ad9a2bf0301
--- /dev/null
+++ b/src/main/resources/PythonLibs/wsgiref/simple_server.py
@@ -0,0 +1,155 @@
+"""BaseHTTPServer that implements the Python WSGI protocol (PEP 333, rev 1.21)
+
+This is both an example of how WSGI can be implemented, and a basis for running
+simple web applications on a local machine, such as might be done when testing
+or debugging an application.  It has not been reviewed for security issues,
+however, and we strongly recommend that you use a "real" web server for
+production use.
+
+For example usage, see the 'if __name__=="__main__"' block at the end of the
+module.  See also the BaseHTTPServer module docs for other API information.
+"""
+
+from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+import urllib, sys
+from wsgiref.handlers import SimpleHandler
+
+__version__ = "0.1"
+__all__ = ['WSGIServer', 'WSGIRequestHandler', 'demo_app', 'make_server']
+
+
+server_version = "WSGIServer/" + __version__
+sys_version = "Python/" + sys.version.split()[0]
+software_version = server_version + ' ' + sys_version
+
+
+class ServerHandler(SimpleHandler):
+
+    server_software = software_version
+
+    def close(self):
+        try:
+            self.request_handler.log_request(
+                self.status.split(' ',1)[0], self.bytes_sent
+            )
+        finally:
+            SimpleHandler.close(self)
+
+
+
+class WSGIServer(HTTPServer):
+
+    """BaseHTTPServer that implements the Python WSGI protocol"""
+
+    application = None
+
+    def server_bind(self):
+        """Override server_bind to store the server name."""
+        HTTPServer.server_bind(self)
+        self.setup_environ()
+
+    def setup_environ(self):
+        # Set up base environment
+        env = self.base_environ = {}
+        env['SERVER_NAME'] = self.server_name
+        env['GATEWAY_INTERFACE'] = 'CGI/1.1'
+        env['SERVER_PORT'] = str(self.server_port)
+        env['REMOTE_HOST']=''
+        env['CONTENT_LENGTH']=''
+        env['SCRIPT_NAME'] = ''
+
+    def get_app(self):
+        return self.application
+
+    def set_app(self,application):
+        self.application = application
+
+
+
+class WSGIRequestHandler(BaseHTTPRequestHandler):
+
+    server_version = "WSGIServer/" + __version__
+
+    def get_environ(self):
+        env = self.server.base_environ.copy()
+        env['SERVER_PROTOCOL'] = self.request_version
+        env['REQUEST_METHOD'] = self.command
+        if '?' in self.path:
+            path,query = self.path.split('?',1)
+        else:
+            path,query = self.path,''
+
+        env['PATH_INFO'] = urllib.unquote(path)
+        env['QUERY_STRING'] = query
+
+        host = self.address_string()
+        if host != self.client_address[0]:
+            env['REMOTE_HOST'] = host
+        env['REMOTE_ADDR'] = self.client_address[0]
+
+        if self.headers.typeheader is None:
+            env['CONTENT_TYPE'] = self.headers.type
+        else:
+            env['CONTENT_TYPE'] = self.headers.typeheader
+
+        length = self.headers.getheader('content-length')
+        if length:
+            env['CONTENT_LENGTH'] = length
+
+        for h in self.headers.headers:
+            k,v = h.split(':',1)
+            k=k.replace('-','_').upper(); v=v.strip()
+            if k in env:
+                continue                    # skip content length, type,etc.
+            if 'HTTP_'+k in env:
+                env['HTTP_'+k] += ','+v     # comma-separate multiple headers
+            else:
+                env['HTTP_'+k] = v
+        return env
+
+    def get_stderr(self):
+        return sys.stderr
+
+    def handle(self):
+        """Handle a single HTTP request"""
+
+        self.raw_requestline = self.rfile.readline()
+        if not self.parse_request(): # An error code has been sent, just exit
+            return
+
+        handler = ServerHandler(
+            self.rfile, self.wfile, self.get_stderr(), self.get_environ()
+        )
+        handler.request_handler = self      # backpointer for logging
+        handler.run(self.server.get_app())
+
+
+
+def demo_app(environ,start_response):
+    from StringIO import StringIO
+    stdout = StringIO()
+    print >>stdout, "Hello world!"
+    print >>stdout
+    h = environ.items(); h.sort()
+    for k,v in h:
+        print >>stdout, k,'=', repr(v)
+    start_response("200 OK", [('Content-Type','text/plain')])
+    return [stdout.getvalue()]
+
+
+def make_server(
+    host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
+):
+    """Create a new WSGI server listening on `host` and `port` for `app`"""
+    server = server_class((host, port), handler_class)
+    server.set_app(app)
+    return server
+
+
+if __name__ == '__main__':
+    httpd = make_server('', 8000, demo_app)
+    sa = httpd.socket.getsockname()
+    print "Serving HTTP on", sa[0], "port", sa[1], "..."
+    import webbrowser
+    webbrowser.open('http://localhost:8000/xyz?abc')
+    httpd.handle_request()  # serve one request, then exit
diff --git a/src/main/resources/PythonLibs/wsgiref/util.py b/src/main/resources/PythonLibs/wsgiref/util.py
new file mode 100644
index 0000000000000000000000000000000000000000..194b187a4dc8d6461f4ecfa8f1b438fccf7c3516
--- /dev/null
+++ b/src/main/resources/PythonLibs/wsgiref/util.py
@@ -0,0 +1,165 @@
+"""Miscellaneous WSGI-related Utilities"""
+
+import posixpath
+
+__all__ = [
+    'FileWrapper', 'guess_scheme', 'application_uri', 'request_uri',
+    'shift_path_info', 'setup_testing_defaults',
+]
+
+
+class FileWrapper:
+    """Wrapper to convert file-like objects to iterables"""
+
+    def __init__(self, filelike, blksize=8192):
+        self.filelike = filelike
+        self.blksize = blksize
+        if hasattr(filelike,'close'):
+            self.close = filelike.close
+
+    def __getitem__(self,key):
+        data = self.filelike.read(self.blksize)
+        if data:
+            return data
+        raise IndexError
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        data = self.filelike.read(self.blksize)
+        if data:
+            return data
+        raise StopIteration
+
+def guess_scheme(environ):
+    """Return a guess for whether 'wsgi.url_scheme' should be 'http' or 'https'
+    """
+    if environ.get("HTTPS") in ('yes','on','1'):
+        return 'https'
+    else:
+        return 'http'
+
+def application_uri(environ):
+    """Return the application's base URI (no PATH_INFO or QUERY_STRING)"""
+    url = environ['wsgi.url_scheme']+'://'
+    from urllib import quote
+
+    if environ.get('HTTP_HOST'):
+        url += environ['HTTP_HOST']
+    else:
+        url += environ['SERVER_NAME']
+
+        if environ['wsgi.url_scheme'] == 'https':
+            if environ['SERVER_PORT'] != '443':
+                url += ':' + environ['SERVER_PORT']
+        else:
+            if environ['SERVER_PORT'] != '80':
+                url += ':' + environ['SERVER_PORT']
+
+    url += quote(environ.get('SCRIPT_NAME') or '/')
+    return url
+
+def request_uri(environ, include_query=1):
+    """Return the full request URI, optionally including the query string"""
+    url = application_uri(environ)
+    from urllib import quote
+    path_info = quote(environ.get('PATH_INFO',''),safe='/;=,')
+    if not environ.get('SCRIPT_NAME'):
+        url += path_info[1:]
+    else:
+        url += path_info
+    if include_query and environ.get('QUERY_STRING'):
+        url += '?' + environ['QUERY_STRING']
+    return url
+
+def shift_path_info(environ):
+    """Shift a name from PATH_INFO to SCRIPT_NAME, returning it
+
+    If there are no remaining path segments in PATH_INFO, return None.
+    Note: 'environ' is modified in-place; use a copy if you need to keep
+    the original PATH_INFO or SCRIPT_NAME.
+
+    Note: when PATH_INFO is just a '/', this returns '' and appends a trailing
+    '/' to SCRIPT_NAME, even though empty path segments are normally ignored,
+    and SCRIPT_NAME doesn't normally end in a '/'.  This is intentional
+    behavior, to ensure that an application can tell the difference between
+    '/x' and '/x/' when traversing to objects.
+    """
+    path_info = environ.get('PATH_INFO','')
+    if not path_info:
+        return None
+
+    path_parts = path_info.split('/')
+    path_parts[1:-1] = [p for p in path_parts[1:-1] if p and p != '.']
+    name = path_parts[1]
+    del path_parts[1]
+
+    script_name = environ.get('SCRIPT_NAME','')
+    script_name = posixpath.normpath(script_name+'/'+name)
+    if script_name.endswith('/'):
+        script_name = script_name[:-1]
+    if not name and not script_name.endswith('/'):
+        script_name += '/'
+
+    environ['SCRIPT_NAME'] = script_name
+    environ['PATH_INFO']   = '/'.join(path_parts)
+
+    # Special case: '/.' on PATH_INFO doesn't get stripped,
+    # because we don't strip the last element of PATH_INFO
+    # if there's only one path part left.  Instead of fixing this
+    # above, we fix it here so that PATH_INFO gets normalized to
+    # an empty string in the environ.
+    if name=='.':
+        name = None
+    return name
+
+def setup_testing_defaults(environ):
+    """Update 'environ' with trivial defaults for testing purposes
+
+    This adds various parameters required for WSGI, including HTTP_HOST,
+    SERVER_NAME, SERVER_PORT, REQUEST_METHOD, SCRIPT_NAME, PATH_INFO,
+    and all of the wsgi.* variables.  It only supplies default values,
+    and does not replace any existing settings for these variables.
+
+    This routine is intended to make it easier for unit tests of WSGI
+    servers and applications to set up dummy environments.  It should *not*
+    be used by actual WSGI servers or applications, since the data is fake!
+    """
+
+    environ.setdefault('SERVER_NAME','127.0.0.1')
+    environ.setdefault('SERVER_PROTOCOL','HTTP/1.0')
+
+    environ.setdefault('HTTP_HOST',environ['SERVER_NAME'])
+    environ.setdefault('REQUEST_METHOD','GET')
+
+    if 'SCRIPT_NAME' not in environ and 'PATH_INFO' not in environ:
+        environ.setdefault('SCRIPT_NAME','')
+        environ.setdefault('PATH_INFO','/')
+
+    environ.setdefault('wsgi.version', (1,0))
+    environ.setdefault('wsgi.run_once', 0)
+    environ.setdefault('wsgi.multithread', 0)
+    environ.setdefault('wsgi.multiprocess', 0)
+
+    from StringIO import StringIO
+    environ.setdefault('wsgi.input', StringIO(""))
+    environ.setdefault('wsgi.errors', StringIO())
+    environ.setdefault('wsgi.url_scheme',guess_scheme(environ))
+
+    if environ['wsgi.url_scheme']=='http':
+        environ.setdefault('SERVER_PORT', '80')
+    elif environ['wsgi.url_scheme']=='https':
+        environ.setdefault('SERVER_PORT', '443')
+
+
+
+_hoppish = {
+    'connection':1, 'keep-alive':1, 'proxy-authenticate':1,
+    'proxy-authorization':1, 'te':1, 'trailers':1, 'transfer-encoding':1,
+    'upgrade':1
+}.__contains__
+
+def is_hop_by_hop(header_name):
+    """Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header"""
+    return _hoppish(header_name.lower())
diff --git a/src/main/resources/PythonLibs/wsgiref/validate.py b/src/main/resources/PythonLibs/wsgiref/validate.py
new file mode 100644
index 0000000000000000000000000000000000000000..04a893d7c614a351cd1ffda5d664cde764119dd3
--- /dev/null
+++ b/src/main/resources/PythonLibs/wsgiref/validate.py
@@ -0,0 +1,432 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# Also licenced under the Apache License, 2.0: http://opensource.org/licenses/apache2.0.php
+# Licensed to PSF under a Contributor Agreement
+"""
+Middleware to check for obedience to the WSGI specification.
+
+Some of the things this checks:
+
+* Signature of the application and start_response (including that
+  keyword arguments are not used).
+
+* Environment checks:
+
+  - Environment is a dictionary (and not a subclass).
+
+  - That all the required keys are in the environment: REQUEST_METHOD,
+    SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors,
+    wsgi.multithread, wsgi.multiprocess, wsgi.run_once
+
+  - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the
+    environment (these headers should appear as CONTENT_LENGTH and
+    CONTENT_TYPE).
+
+  - Warns if QUERY_STRING is missing, as the cgi module acts
+    unpredictably in that case.
+
+  - That CGI-style variables (that don't contain a .) have
+    (non-unicode) string values
+
+  - That wsgi.version is a tuple
+
+  - That wsgi.url_scheme is 'http' or 'https' (@@: is this too
+    restrictive?)
+
+  - Warns if the REQUEST_METHOD is not known (@@: probably too
+    restrictive).
+
+  - That SCRIPT_NAME and PATH_INFO are empty or start with /
+
+  - That at least one of SCRIPT_NAME or PATH_INFO are set.
+
+  - That CONTENT_LENGTH is a positive integer.
+
+  - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should
+    be '/').
+
+  - That wsgi.input has the methods read, readline, readlines, and
+    __iter__
+
+  - That wsgi.errors has the methods flush, write, writelines
+
+* The status is a string, contains a space, starts with an integer,
+  and that integer is in range (> 100).
+
+* That the headers is a list (not a subclass, not another kind of
+  sequence).
+
+* That the items of the headers are tuples of strings.
+
+* That there is no 'status' header (that is used in CGI, but not in
+  WSGI).
+
+* That the headers don't contain newlines or colons, end in _ or -, or
+  contain characters codes below 037.
+
+* That Content-Type is given if there is content (CGI often has a
+  default content type, but WSGI does not).
+
+* That no Content-Type is given when there is no content (@@: is this
+  too restrictive?)
+
+* That the exc_info argument to start_response is a tuple or None.
+
+* That all calls to the writer are with strings, and no other methods
+  on the writer are accessed.
+
+* That wsgi.input is used properly:
+
+  - .read() is called with zero or one argument
+
+  - That it returns a string
+
+  - That readline, readlines, and __iter__ return strings
+
+  - That .close() is not called
+
+  - No other methods are provided
+
+* That wsgi.errors is used properly:
+
+  - .write() and .writelines() is called with a string
+
+  - That .close() is not called, and no other methods are provided.
+
+* The response iterator:
+
+  - That it is not a string (it should be a list of a single string; a
+    string will work, but perform horribly).
+
+  - That .next() returns a string
+
+  - That the iterator is not iterated over until start_response has
+    been called (that can signal either a server or application
+    error).
+
+  - That .close() is called (doesn't raise exception, only prints to
+    sys.stderr, because we only know it isn't called when the object
+    is garbage collected).
+"""
+__all__ = ['validator']
+
+
+import re
+import sys
+from types import DictType, StringType, TupleType, ListType
+import warnings
+
+header_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9\-_]*$')
+bad_header_value_re = re.compile(r'[\000-\037]')
+
+class WSGIWarning(Warning):
+    """
+    Raised in response to WSGI-spec-related warnings
+    """
+
+def assert_(cond, *args):
+    if not cond:
+        raise AssertionError(*args)
+
+def validator(application):
+
+    """
+    When applied between a WSGI server and a WSGI application, this
+    middleware will check for WSGI compliancy on a number of levels.
+    This middleware does not modify the request or response in any
+    way, but will raise an AssertionError if anything seems off
+    (except for a failure to close the application iterator, which
+    will be printed to stderr -- there's no way to raise an exception
+    at that point).
+    """
+
+    def lint_app(*args, **kw):
+        assert_(len(args) == 2, "Two arguments required")
+        assert_(not kw, "No keyword arguments allowed")
+        environ, start_response = args
+
+        check_environ(environ)
+
+        # We use this to check if the application returns without
+        # calling start_response:
+        start_response_started = []
+
+        def start_response_wrapper(*args, **kw):
+            assert_(len(args) == 2 or len(args) == 3, (
+                "Invalid number of arguments: %s" % (args,)))
+            assert_(not kw, "No keyword arguments allowed")
+            status = args[0]
+            headers = args[1]
+            if len(args) == 3:
+                exc_info = args[2]
+            else:
+                exc_info = None
+
+            check_status(status)
+            check_headers(headers)
+            check_content_type(status, headers)
+            check_exc_info(exc_info)
+
+            start_response_started.append(None)
+            return WriteWrapper(start_response(*args))
+
+        environ['wsgi.input'] = InputWrapper(environ['wsgi.input'])
+        environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors'])
+
+        iterator = application(environ, start_response_wrapper)
+        assert_(iterator is not None and iterator != False,
+            "The application must return an iterator, if only an empty list")
+
+        check_iterator(iterator)
+
+        return IteratorWrapper(iterator, start_response_started)
+
+    return lint_app
+
+class InputWrapper:
+
+    def __init__(self, wsgi_input):
+        self.input = wsgi_input
+
+    def read(self, *args):
+        assert_(len(args) <= 1)
+        v = self.input.read(*args)
+        assert_(type(v) is type(""))
+        return v
+
+    def readline(self):
+        v = self.input.readline()
+        assert_(type(v) is type(""))
+        return v
+
+    def readlines(self, *args):
+        assert_(len(args) <= 1)
+        lines = self.input.readlines(*args)
+        assert_(type(lines) is type([]))
+        for line in lines:
+            assert_(type(line) is type(""))
+        return lines
+
+    def __iter__(self):
+        while 1:
+            line = self.readline()
+            if not line:
+                return
+            yield line
+
+    def close(self):
+        assert_(0, "input.close() must not be called")
+
+class ErrorWrapper:
+
+    def __init__(self, wsgi_errors):
+        self.errors = wsgi_errors
+
+    def write(self, s):
+        assert_(type(s) is type(""))
+        self.errors.write(s)
+
+    def flush(self):
+        self.errors.flush()
+
+    def writelines(self, seq):
+        for line in seq:
+            self.write(line)
+
+    def close(self):
+        assert_(0, "errors.close() must not be called")
+
+class WriteWrapper:
+
+    def __init__(self, wsgi_writer):
+        self.writer = wsgi_writer
+
+    def __call__(self, s):
+        assert_(type(s) is type(""))
+        self.writer(s)
+
+class PartialIteratorWrapper:
+
+    def __init__(self, wsgi_iterator):
+        self.iterator = wsgi_iterator
+
+    def __iter__(self):
+        # We want to make sure __iter__ is called
+        return IteratorWrapper(self.iterator, None)
+
+class IteratorWrapper:
+
+    def __init__(self, wsgi_iterator, check_start_response):
+        self.original_iterator = wsgi_iterator
+        self.iterator = iter(wsgi_iterator)
+        self.closed = False
+        self.check_start_response = check_start_response
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        assert_(not self.closed,
+            "Iterator read after closed")
+        v = self.iterator.next()
+        if self.check_start_response is not None:
+            assert_(self.check_start_response,
+                "The application returns and we started iterating over its body, but start_response has not yet been called")
+            self.check_start_response = None
+        return v
+
+    def close(self):
+        self.closed = True
+        if hasattr(self.original_iterator, 'close'):
+            self.original_iterator.close()
+
+    def __del__(self):
+        if not self.closed:
+            sys.stderr.write(
+                "Iterator garbage collected without being closed")
+        assert_(self.closed,
+            "Iterator garbage collected without being closed")
+
+def check_environ(environ):
+    assert_(type(environ) is DictType,
+        "Environment is not of the right type: %r (environment: %r)"
+        % (type(environ), environ))
+
+    for key in ['REQUEST_METHOD', 'SERVER_NAME', 'SERVER_PORT',
+                'wsgi.version', 'wsgi.input', 'wsgi.errors',
+                'wsgi.multithread', 'wsgi.multiprocess',
+                'wsgi.run_once']:
+        assert_(key in environ,
+            "Environment missing required key: %r" % (key,))
+
+    for key in ['HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH']:
+        assert_(key not in environ,
+            "Environment should not have the key: %s "
+            "(use %s instead)" % (key, key[5:]))
+
+    if 'QUERY_STRING' not in environ:
+        warnings.warn(
+            'QUERY_STRING is not in the WSGI environment; the cgi '
+            'module will use sys.argv when this variable is missing, '
+            'so application errors are more likely',
+            WSGIWarning)
+
+    for key in environ.keys():
+        if '.' in key:
+            # Extension, we don't care about its type
+            continue
+        assert_(type(environ[key]) is StringType,
+            "Environmental variable %s is not a string: %r (value: %r)"
+            % (key, type(environ[key]), environ[key]))
+
+    assert_(type(environ['wsgi.version']) is TupleType,
+        "wsgi.version should be a tuple (%r)" % (environ['wsgi.version'],))
+    assert_(environ['wsgi.url_scheme'] in ('http', 'https'),
+        "wsgi.url_scheme unknown: %r" % environ['wsgi.url_scheme'])
+
+    check_input(environ['wsgi.input'])
+    check_errors(environ['wsgi.errors'])
+
+    # @@: these need filling out:
+    if environ['REQUEST_METHOD'] not in (
+        'GET', 'HEAD', 'POST', 'OPTIONS','PUT','DELETE','TRACE'):
+        warnings.warn(
+            "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'],
+            WSGIWarning)
+
+    assert_(not environ.get('SCRIPT_NAME')
+            or environ['SCRIPT_NAME'].startswith('/'),
+        "SCRIPT_NAME doesn't start with /: %r" % environ['SCRIPT_NAME'])
+    assert_(not environ.get('PATH_INFO')
+            or environ['PATH_INFO'].startswith('/'),
+        "PATH_INFO doesn't start with /: %r" % environ['PATH_INFO'])
+    if environ.get('CONTENT_LENGTH'):
+        assert_(int(environ['CONTENT_LENGTH']) >= 0,
+            "Invalid CONTENT_LENGTH: %r" % environ['CONTENT_LENGTH'])
+
+    if not environ.get('SCRIPT_NAME'):
+        assert_('PATH_INFO' in environ,
+            "One of SCRIPT_NAME or PATH_INFO are required (PATH_INFO "
+            "should at least be '/' if SCRIPT_NAME is empty)")
+    assert_(environ.get('SCRIPT_NAME') != '/',
+        "SCRIPT_NAME cannot be '/'; it should instead be '', and "
+        "PATH_INFO should be '/'")
+
+def check_input(wsgi_input):
+    for attr in ['read', 'readline', 'readlines', '__iter__']:
+        assert_(hasattr(wsgi_input, attr),
+            "wsgi.input (%r) doesn't have the attribute %s"
+            % (wsgi_input, attr))
+
+def check_errors(wsgi_errors):
+    for attr in ['flush', 'write', 'writelines']:
+        assert_(hasattr(wsgi_errors, attr),
+            "wsgi.errors (%r) doesn't have the attribute %s"
+            % (wsgi_errors, attr))
+
+def check_status(status):
+    assert_(type(status) is StringType,
+        "Status must be a string (not %r)" % status)
+    # Implicitly check that we can turn it into an integer:
+    status_code = status.split(None, 1)[0]
+    assert_(len(status_code) == 3,
+        "Status codes must be three characters: %r" % status_code)
+    status_int = int(status_code)
+    assert_(status_int >= 100, "Status code is invalid: %r" % status_int)
+    if len(status) < 4 or status[3] != ' ':
+        warnings.warn(
+            "The status string (%r) should be a three-digit integer "
+            "followed by a single space and a status explanation"
+            % status, WSGIWarning)
+
+def check_headers(headers):
+    assert_(type(headers) is ListType,
+        "Headers (%r) must be of type list: %r"
+        % (headers, type(headers)))
+    header_names = {}
+    for item in headers:
+        assert_(type(item) is TupleType,
+            "Individual headers (%r) must be of type tuple: %r"
+            % (item, type(item)))
+        assert_(len(item) == 2)
+        name, value = item
+        assert_(name.lower() != 'status',
+            "The Status header cannot be used; it conflicts with CGI "
+            "script, and HTTP status is not given through headers "
+            "(value: %r)." % value)
+        header_names[name.lower()] = None
+        assert_('\n' not in name and ':' not in name,
+            "Header names may not contain ':' or '\\n': %r" % name)
+        assert_(header_re.search(name), "Bad header name: %r" % name)
+        assert_(not name.endswith('-') and not name.endswith('_'),
+            "Names may not end in '-' or '_': %r" % name)
+        if bad_header_value_re.search(value):
+            assert_(0, "Bad header value: %r (bad char: %r)"
+            % (value, bad_header_value_re.search(value).group(0)))
+
+def check_content_type(status, headers):
+    code = int(status.split(None, 1)[0])
+    # @@: need one more person to verify this interpretation of RFC 2616
+    #     http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+    NO_MESSAGE_BODY = (204, 304)
+    for name, value in headers:
+        if name.lower() == 'content-type':
+            if code not in NO_MESSAGE_BODY:
+                return
+            assert_(0, ("Content-Type header found in a %s response, "
+                        "which must not return content.") % code)
+    if code not in NO_MESSAGE_BODY:
+        assert_(0, "No Content-Type header found in headers (%s)" % headers)
+
+def check_exc_info(exc_info):
+    assert_(exc_info is None or type(exc_info) is type(()),
+        "exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info)))
+    # More exc_info checks?
+
+def check_iterator(iterator):
+    # Technically a string is legal, which is why it's a really bad
+    # idea, because it may cause the response to be returned
+    # character-by-character
+    assert_(not isinstance(iterator, str),
+        "You should not return a string as your application iterator, "
+        "instead return a single-item list containing that string.")
diff --git a/src/main/resources/PythonLibs/xdrlib.py b/src/main/resources/PythonLibs/xdrlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef172dd37d68b50bc369221c61e7e95f6e36e51a
--- /dev/null
+++ b/src/main/resources/PythonLibs/xdrlib.py
@@ -0,0 +1,231 @@
+"""Implements (a subset of) Sun XDR -- eXternal Data Representation.
+
+See: RFC 1014
+
+"""
+
+import struct
+try:
+    from cStringIO import StringIO as _StringIO
+except ImportError:
+    from StringIO import StringIO as _StringIO
+
+__all__ = ["Error", "Packer", "Unpacker", "ConversionError"]
+
+# exceptions
+class Error(Exception):
+    """Exception class for this module. Use:
+
+    except xdrlib.Error, var:
+        # var has the Error instance for the exception
+
+    Public ivars:
+        msg -- contains the message
+
+    """
+    def __init__(self, msg):
+        self.msg = msg
+    def __repr__(self):
+        return repr(self.msg)
+    def __str__(self):
+        return str(self.msg)
+
+
+class ConversionError(Error):
+    pass
+
+
+
+class Packer:
+    """Pack various data representations into a buffer."""
+
+    def __init__(self):
+        self.reset()
+
+    def reset(self):
+        self.__buf = _StringIO()
+
+    def get_buffer(self):
+        return self.__buf.getvalue()
+    # backwards compatibility
+    get_buf = get_buffer
+
+    def pack_uint(self, x):
+        self.__buf.write(struct.pack('>L', x))
+
+    def pack_int(self, x):
+        self.__buf.write(struct.pack('>l', x))
+
+    pack_enum = pack_int
+
+    def pack_bool(self, x):
+        if x: self.__buf.write('\0\0\0\1')
+        else: self.__buf.write('\0\0\0\0')
+
+    def pack_uhyper(self, x):
+        self.pack_uint(x>>32 & 0xffffffffL)
+        self.pack_uint(x & 0xffffffffL)
+
+    pack_hyper = pack_uhyper
+
+    def pack_float(self, x):
+        try: self.__buf.write(struct.pack('>f', x))
+        except struct.error, msg:
+            raise ConversionError, msg
+
+    def pack_double(self, x):
+        try: self.__buf.write(struct.pack('>d', x))
+        except struct.error, msg:
+            raise ConversionError, msg
+
+    def pack_fstring(self, n, s):
+        if n < 0:
+            raise ValueError, 'fstring size must be nonnegative'
+        data = s[:n]
+        n = ((n+3)//4)*4
+        data = data + (n - len(data)) * '\0'
+        self.__buf.write(data)
+
+    pack_fopaque = pack_fstring
+
+    def pack_string(self, s):
+        n = len(s)
+        self.pack_uint(n)
+        self.pack_fstring(n, s)
+
+    pack_opaque = pack_string
+    pack_bytes = pack_string
+
+    def pack_list(self, list, pack_item):
+        for item in list:
+            self.pack_uint(1)
+            pack_item(item)
+        self.pack_uint(0)
+
+    def pack_farray(self, n, list, pack_item):
+        if len(list) != n:
+            raise ValueError, 'wrong array size'
+        for item in list:
+            pack_item(item)
+
+    def pack_array(self, list, pack_item):
+        n = len(list)
+        self.pack_uint(n)
+        self.pack_farray(n, list, pack_item)
+
+
+
+class Unpacker:
+    """Unpacks various data representations from the given buffer."""
+
+    def __init__(self, data):
+        self.reset(data)
+
+    def reset(self, data):
+        self.__buf = data
+        self.__pos = 0
+
+    def get_position(self):
+        return self.__pos
+
+    def set_position(self, position):
+        self.__pos = position
+
+    def get_buffer(self):
+        return self.__buf
+
+    def done(self):
+        if self.__pos < len(self.__buf):
+            raise Error('unextracted data remains')
+
+    def unpack_uint(self):
+        i = self.__pos
+        self.__pos = j = i+4
+        data = self.__buf[i:j]
+        if len(data) < 4:
+            raise EOFError
+        x = struct.unpack('>L', data)[0]
+        try:
+            return int(x)
+        except OverflowError:
+            return x
+
+    def unpack_int(self):
+        i = self.__pos
+        self.__pos = j = i+4
+        data = self.__buf[i:j]
+        if len(data) < 4:
+            raise EOFError
+        return struct.unpack('>l', data)[0]
+
+    unpack_enum = unpack_int
+
+    def unpack_bool(self):
+        return bool(self.unpack_int())
+
+    def unpack_uhyper(self):
+        hi = self.unpack_uint()
+        lo = self.unpack_uint()
+        return long(hi)<<32 | lo
+
+    def unpack_hyper(self):
+        x = self.unpack_uhyper()
+        if x >= 0x8000000000000000L:
+            x = x - 0x10000000000000000L
+        return x
+
+    def unpack_float(self):
+        i = self.__pos
+        self.__pos = j = i+4
+        data = self.__buf[i:j]
+        if len(data) < 4:
+            raise EOFError
+        return struct.unpack('>f', data)[0]
+
+    def unpack_double(self):
+        i = self.__pos
+        self.__pos = j = i+8
+        data = self.__buf[i:j]
+        if len(data) < 8:
+            raise EOFError
+        return struct.unpack('>d', data)[0]
+
+    def unpack_fstring(self, n):
+        if n < 0:
+            raise ValueError, 'fstring size must be nonnegative'
+        i = self.__pos
+        j = i + (n+3)//4*4
+        if j > len(self.__buf):
+            raise EOFError
+        self.__pos = j
+        return self.__buf[i:i+n]
+
+    unpack_fopaque = unpack_fstring
+
+    def unpack_string(self):
+        n = self.unpack_uint()
+        return self.unpack_fstring(n)
+
+    unpack_opaque = unpack_string
+    unpack_bytes = unpack_string
+
+    def unpack_list(self, unpack_item):
+        list = []
+        while 1:
+            x = self.unpack_uint()
+            if x == 0: break
+            if x != 1:
+                raise ConversionError, '0 or 1 expected, got %r' % (x,)
+            item = unpack_item()
+            list.append(item)
+        return list
+
+    def unpack_farray(self, n, unpack_item):
+        list = []
+        for i in range(n):
+            list.append(unpack_item())
+        return list
+
+    def unpack_array(self, unpack_item):
+        n = self.unpack_uint()
+        return self.unpack_farray(n, unpack_item)
diff --git a/src/main/resources/PythonLibs/xml/FtCore.py b/src/main/resources/PythonLibs/xml/FtCore.py
new file mode 100644
index 0000000000000000000000000000000000000000..d58885f44e2dacec42b9578b8b3c62baeb1ef3af
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/FtCore.py
@@ -0,0 +1,58 @@
+"""
+Contains various definitions common to modules acquired from 4Suite
+"""
+
+__all__ = ["FtException", "get_translator"]
+
+
+class FtException(Exception):
+    def __init__(self, errorCode, messages, args):
+        # By defining __str__, args will be available.  Otherwise
+        # the __init__ of Exception sets it to the passed in arguments.
+        self.params = args
+        self.errorCode = errorCode
+        self.message = messages[errorCode] % args
+        Exception.__init__(self, self.message, args)
+
+    def __str__(self):
+        return self.message
+
+
+# What follows is used to provide support for I18N in the rest of the
+# 4Suite-derived packages in PyXML.
+#
+# Each sub-package of the top-level "xml" package that contains 4Suite
+# code is really a separate text domain, but they're all called
+# '4Suite'.  For each domain, a translation object is provided using
+# message catalogs stored inside the package.  The code below defines
+# a get_translator() function that returns an appropriate gettext
+# function to be used as _() in the sub-package named by the
+# parameter.  This handles all the compatibility issues related to
+# Python versions (whether the gettext module can be found) and
+# whether the message catalogs can actually be found.
+
+def _(msg):
+    return msg
+
+try:
+    import gettext
+
+except (ImportError, IOError):
+    def get_translator(pkg):
+        return _
+
+else:
+    import os
+
+    _cache = {}
+    _top = os.path.dirname(os.path.abspath(__file__))
+
+    def get_translator(pkg):
+        if not _cache.has_key(pkg):
+            locale_dir = os.path.join(_top, pkg.replace(".", os.sep))
+            try:
+                f = gettext.translation('4Suite', locale_dir).gettext
+            except IOError:
+                f = _
+            _cache[pkg] = f
+        return _cache[pkg]
diff --git a/src/main/resources/PythonLibs/xml/Uri.py b/src/main/resources/PythonLibs/xml/Uri.py
new file mode 100644
index 0000000000000000000000000000000000000000..730f3caa38d5ca804c75a38af61cda27603c7c64
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/Uri.py
@@ -0,0 +1,380 @@
+# pylint: disable-msg=C0103
+#
+# backported code from 4Suite with slight modifications, started from r1.89 of
+# Ft/Lib/Uri.py, by syt@logilab.fr on 2005-02-09
+#
+# part if not all of this code should probably move to urlparse (or be used
+# to fix some existant functions in this module)
+#
+#
+# Copyright 2004 Fourthought, Inc. (USA).
+# Detailed license and copyright information: http://4suite.org/COPYRIGHT
+# Project home, documentation, distributions: http://4suite.org/
+import os.path
+import sys
+import re
+import urlparse, urllib, urllib2
+
+def UnsplitUriRef(uriRefSeq):
+    """should replace urlparse.urlunsplit
+
+    Given a sequence as would be produced by SplitUriRef(), assembles and
+    returns a URI reference as a string.
+    """
+    if not isinstance(uriRefSeq, (tuple, list)):
+        raise TypeError("sequence expected, got %s" % type(uriRefSeq))
+    (scheme, authority, path, query, fragment) = uriRefSeq
+    uri = ''
+    if scheme is not None:
+        uri += scheme + ':'
+    if authority is not None:
+        uri += '//' + authority
+    uri += path
+    if query is not None:
+        uri += '?' + query
+    if fragment is not None:
+        uri += '#' + fragment
+    return uri
+
+SPLIT_URI_REF_PATTERN = re.compile(r"^(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?(?P<path>[^?#]*)(?:\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?$")
+
+def SplitUriRef(uriref):
+    """should replace urlparse.urlsplit
+
+    Given a valid URI reference as a string, returns a tuple representing the
+    generic URI components, as per RFC 2396 appendix B. The tuple's structure
+    is (scheme, authority, path, query, fragment).
+
+    All values will be strings (possibly empty) or None if undefined.
+
+    Note that per rfc3986, there is no distinction between a path and
+    an "opaque part", as there was in RFC 2396.
+    """
+    # the pattern will match every possible string, so it's safe to
+    # assume there's a groupdict method to call.
+    g = SPLIT_URI_REF_PATTERN.match(uriref).groupdict()
+    scheme      = g['scheme']
+    authority   = g['authority']
+    path        = g['path']
+    query       = g['query']
+    fragment    = g['fragment']
+    return (scheme, authority, path, query, fragment)
+
+
+def Absolutize(uriRef, baseUri):
+    """
+    Resolves a URI reference to absolute form, effecting the result of RFC
+    3986 section 5. The URI reference is considered to be relative to the
+    given base URI.
+
+    It is the caller's responsibility to ensure that the base URI matches
+    the absolute-URI syntax rule of RFC 3986, and that its path component
+    does not contain '.' or '..' segments if the scheme is hierarchical.
+    Unexpected results may occur otherwise.
+
+    This function only conducts a minimal sanity check in order to determine
+    if relative resolution is possible: it raises a UriException if the base
+    URI does not have a scheme component. While it is true that the base URI
+    is irrelevant if the URI reference has a scheme, an exception is raised
+    in order to signal that the given string does not even come close to
+    meeting the criteria to be usable as a base URI.
+
+    It is the caller's responsibility to make a determination of whether the
+    URI reference constitutes a "same-document reference", as defined in RFC
+    2396 or RFC 3986. As per the spec, dereferencing a same-document
+    reference "should not" involve retrieval of a new representation of the
+    referenced resource. Note that the two specs have different definitions
+    of same-document reference: RFC 2396 says it is *only* the cases where the
+    reference is the empty string, or "#" followed by a fragment; RFC 3986
+    requires making a comparison of the base URI to the absolute form of the
+    reference (as is returned by the spec), minus its fragment component,
+    if any.
+
+    This function is similar to urlparse.urljoin() and urllib.basejoin().
+    Those functions, however, are (as of Python 2.3) outdated, buggy, and/or
+    designed to produce results acceptable for use with other core Python
+    libraries, rather than being earnest implementations of the relevant
+    specs. Their problems are most noticeable in their handling of
+    same-document references and 'file:' URIs, both being situations that
+    come up far too often to consider the functions reliable enough for
+    general use.
+    """
+    # Reasons to avoid using urllib.basejoin() and urlparse.urljoin():
+    # - Both are partial implementations of long-obsolete specs.
+    # - Both accept relative URLs as the base, which no spec allows.
+    # - urllib.basejoin() mishandles the '' and '..' references.
+    # - If the base URL uses a non-hierarchical or relative path,
+    #    or if the URL scheme is unrecognized, the result is not
+    #    always as expected (partly due to issues in RFC 1808).
+    # - If the authority component of a 'file' URI is empty,
+    #    the authority component is removed altogether. If it was
+    #    not present, an empty authority component is in the result.
+    # - '.' and '..' segments are not always collapsed as well as they
+    #    should be (partly due to issues in RFC 1808).
+    # - Effective Python 2.4, urllib.basejoin() *is* urlparse.urljoin(),
+    #    but urlparse.urljoin() is still based on RFC 1808.
+
+    # This procedure is based on the pseudocode in RFC 3986 sec. 5.2.
+    #
+    # ensure base URI is absolute
+    if not baseUri:
+        raise ValueError('baseUri is required and must be a non empty string')
+    if not IsAbsolute(baseUri):
+        raise ValueError('%r is not an absolute URI' % baseUri)
+    # shortcut for the simplest same-document reference cases
+    if uriRef == '' or uriRef[0] == '#':
+        return baseUri.split('#')[0] + uriRef
+    # ensure a clean slate
+    tScheme = tAuth = tPath = tQuery = None
+    # parse the reference into its components
+    (rScheme, rAuth, rPath, rQuery, rFrag) = SplitUriRef(uriRef)
+    # if the reference is absolute, eliminate '.' and '..' path segments
+    # and skip to the end
+    if rScheme is not None:
+        tScheme = rScheme
+        tAuth = rAuth
+        tPath = RemoveDotSegments(rPath)
+        tQuery = rQuery
+    else:
+        # the base URI's scheme, and possibly more, will be inherited
+        (bScheme, bAuth, bPath, bQuery, bFrag) = SplitUriRef(baseUri)
+        # if the reference is a net-path, just eliminate '.' and '..' path
+        # segments; no other changes needed.
+        if rAuth is not None:
+            tAuth = rAuth
+            tPath = RemoveDotSegments(rPath)
+            tQuery = rQuery
+        # if it's not a net-path, we need to inherit pieces of the base URI
+        else:
+            # use base URI's path if the reference's path is empty
+            if not rPath:
+                tPath = bPath
+                # use the reference's query, if any, or else the base URI's,
+                tQuery = rQuery is not None and rQuery or bQuery
+            # the reference's path is not empty
+            else:
+                # just use the reference's path if it's absolute
+                if rPath[0] == '/':
+                    tPath = RemoveDotSegments(rPath)
+                # merge the reference's relative path with the base URI's path
+                else:
+                    if bAuth is not None and not bPath:
+                        tPath = '/' + rPath
+                    else:
+                        tPath = bPath[:bPath.rfind('/')+1] + rPath
+                    tPath = RemoveDotSegments(tPath)
+                # use the reference's query
+                tQuery = rQuery
+            # since the reference isn't a net-path,
+            # use the authority from the base URI
+            tAuth = bAuth
+        # inherit the scheme from the base URI
+        tScheme = bScheme
+    # always use the reference's fragment (but no need to define another var)
+    #tFrag = rFrag
+
+    # now compose the target URI (RFC 3986 sec. 5.3)
+    return UnsplitUriRef((tScheme, tAuth, tPath, tQuery, rFrag))
+
+
+REG_NAME_HOST_PATTERN = re.compile(r"^(?:(?:[0-9A-Za-z\-_\.!~*'();&=+$,]|(?:%[0-9A-Fa-f]{2}))*)$")
+
+def MakeUrllibSafe(uriRef):
+    """
+    Makes the given RFC 3986-conformant URI reference safe for passing
+    to legacy urllib functions. The result may not be a valid URI.
+
+    As of Python 2.3.3, urllib.urlopen() does not fully support
+    internationalized domain names, it does not strip fragment components,
+    and on Windows, it expects file URIs to use '|' instead of ':' in the
+    path component corresponding to the drivespec. It also relies on
+    urllib.unquote(), which mishandles unicode arguments. This function
+    produces a URI reference that will work around these issues, although
+    the IDN workaround is limited to Python 2.3 only. May raise a
+    UnicodeEncodeError if the URI reference is Unicode and erroneously
+    contains non-ASCII characters.
+    """
+    # IDN support requires decoding any percent-encoded octets in the
+    # host part (if it's a reg-name) of the authority component, and when
+    # doing DNS lookups, applying IDNA encoding to that string first.
+    # As of Python 2.3, there is an IDNA codec, and the socket and httplib
+    # modules accept Unicode strings and apply IDNA encoding automatically
+    # where necessary. However, urllib.urlopen() has not yet been updated
+    # to do the same; it raises an exception if you give it a Unicode
+    # string, and does no conversion on non-Unicode strings, meaning you
+    # have to give it an IDNA string yourself. We will only support it on
+    # Python 2.3 and up.
+    #
+    # see if host is a reg-name, as opposed to IPv4 or IPv6 addr.
+    if isinstance(uriRef, unicode):
+        try:
+            uriRef = uriRef.encode('us-ascii') # parts of urllib are not unicode safe
+        except UnicodeError:
+            raise ValueError("uri %r must consist of ASCII characters." % uriRef)
+    (scheme, auth, path, query, frag) = urlparse.urlsplit(uriRef)
+    if auth and auth.find('@') > -1:
+        userinfo, hostport = auth.split('@')
+    else:
+        userinfo = None
+        hostport = auth
+    if hostport and hostport.find(':') > -1:
+        host, port = hostport.split(':')
+    else:
+        host = hostport
+        port = None
+    if host and REG_NAME_HOST_PATTERN.match(host):
+        # percent-encoded hostnames will always fail DNS lookups
+        host = urllib.unquote(host) #PercentDecode(host)
+        # IDNA-encode if possible.
+        # We shouldn't do this for schemes that don't need DNS lookup,
+        # but are there any (that you'd be calling urlopen for)?
+        if sys.version_info[0:2] >= (2, 3):
+            if isinstance(host, str):
+                host = host.decode('utf-8')
+            host = host.encode('idna')
+        # reassemble the authority with the new hostname
+        # (percent-decoded, and possibly IDNA-encoded)
+        auth = ''
+        if userinfo:
+            auth += userinfo + '@'
+        auth += host
+        if port:
+            auth += ':' + port
+
+    # On Windows, ensure that '|', not ':', is used in a drivespec.
+    if os.name == 'nt' and scheme == 'file':
+        path = path.replace(':', '|', 1)
+
+    # Note that we drop fragment, if any. See RFC 3986 sec. 3.5.
+    uri = urlparse.urlunsplit((scheme, auth, path, query, None))
+
+    return uri
+
+
+
+def BaseJoin(base, uriRef):
+    """
+    Merges a base URI reference with another URI reference, returning a
+    new URI reference.
+
+    It behaves exactly the same as Absolutize(), except the arguments
+    are reversed, and it accepts any URI reference (even a relative URI)
+    as the base URI. If the base has no scheme component, it is
+    evaluated as if it did, and then the scheme component of the result
+    is removed from the result, unless the uriRef had a scheme. Thus, if
+    neither argument has a scheme component, the result won't have one.
+
+    This function is named BaseJoin because it is very much like
+    urllib.basejoin(), but it follows the current rfc3986 algorithms
+    for path merging, dot segment elimination, and inheritance of query
+    and fragment components.
+
+    WARNING: This function exists for 2 reasons: (1) because of a need
+    within the 4Suite repository to perform URI reference absolutization
+    using base URIs that are stored (inappropriately) as absolute paths
+    in the subjects of statements in the RDF model, and (2) because of
+    a similar need to interpret relative repo paths in a 4Suite product
+    setup.xml file as being relative to a path that can be set outside
+    the document. When these needs go away, this function probably will,
+    too, so it is not advisable to use it.
+    """
+    if IsAbsolute(base):
+        return Absolutize(uriRef, base)
+    else:
+        dummyscheme = 'basejoin'
+        res = Absolutize(uriRef, '%s:%s' % (dummyscheme, base))
+        if IsAbsolute(uriRef):
+            # scheme will be inherited from uriRef
+            return res
+        else:
+            # no scheme in, no scheme out
+            return res[len(dummyscheme)+1:]
+
+
+def RemoveDotSegments(path):
+    """
+    Supports Absolutize() by implementing the remove_dot_segments function
+    described in RFC 3986 sec. 5.2.  It collapses most of the '.' and '..'
+    segments out of a path without eliminating empty segments. It is intended
+    to be used during the path merging process and may not give expected
+    results when used independently. Use NormalizePathSegments() or
+    NormalizePathSegmentsInUri() if more general normalization is desired.
+
+    semi-private because it is not for general use. I've implemented it
+    using two segment stacks, as alluded to in the spec, rather than the
+    explicit string-walking algorithm that would be too inefficient. (mbrown)
+    """
+    # return empty string if entire path is just "." or ".."
+    if path == '.' or path == '..':
+        return path[0:0] # preserves string type
+    # remove all "./" or "../" segments at the beginning
+    while path:
+        if path[:2] == './':
+            path = path[2:]
+        elif path[:3] == '../':
+            path = path[3:]
+        else:
+            break
+    # We need to keep track of whether there was a leading slash,
+    # because we're going to drop it in order to prevent our list of
+    # segments from having an ambiguous empty first item when we call
+    # split().
+    leading_slash = 0
+    if path[:1] == '/':
+        path = path[1:]
+        leading_slash = 1
+    # replace a trailing "/." with just "/"
+    if path[-2:] == '/.':
+        path = path[:-1]
+    # convert the segments into a list and process each segment in
+    # order from left to right.
+    segments = path.split('/')
+    keepers = []
+    segments.reverse()
+    while segments:
+        seg = segments.pop()
+        # '..' means drop the previous kept segment, if any.
+        # If none, and if the path is relative, then keep the '..'.
+        # If the '..' was the last segment, ensure
+        # that the result ends with '/'.
+        if seg == '..':
+            if keepers:
+                keepers.pop()
+            elif not leading_slash:
+                keepers.append(seg)
+            if not segments:
+                keepers.append('')
+        # ignore '.' segments and keep all others, even empty ones
+        elif seg != '.':
+            keepers.append(seg)
+    # reassemble the kept segments
+    return leading_slash * '/' + '/'.join(keepers)
+
+
+SCHEME_PATTERN = re.compile(r'([a-zA-Z][a-zA-Z0-9+\-.]*):')
+def GetScheme(uriRef):
+    """
+    Obtains, with optimum efficiency, just the scheme from a URI reference.
+    Returns a string, or if no scheme could be found, returns None.
+    """
+    # Using a regex seems to be the best option. Called 50,000 times on
+    # different URIs, on a 1.0-GHz PIII with FreeBSD 4.7 and Python
+    # 2.2.1, this method completed in 0.95s, and 0.05s if there was no
+    # scheme to find. By comparison,
+    #   urllib.splittype()[0] took 1.5s always;
+    #   Ft.Lib.Uri.SplitUriRef()[0] took 2.5s always;
+    #   urlparse.urlparse()[0] took 3.5s always.
+    m = SCHEME_PATTERN.match(uriRef)
+    if m is None:
+        return None
+    else:
+        return m.group(1)
+
+
+def IsAbsolute(identifier):
+    """
+    Given a string believed to be a URI or URI reference, tests that it is
+    absolute (as per RFC 2396), not relative -- i.e., that it has a scheme.
+    """
+    # We do it this way to avoid compiling another massive regex.
+    return GetScheme(identifier) is not None
diff --git a/src/main/resources/PythonLibs/xml/__init__.py b/src/main/resources/PythonLibs/xml/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e6d31444431dc7138efde512f51cdccab51f996d
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/__init__.py
@@ -0,0 +1,36 @@
+"""Core XML support for Jython.
+
+This package contains two sub-packages:
+
+dom -- The W3C Document Object Model.  This supports DOM Level 1 +
+       Namespaces.
+
+sax -- The Simple API for XML, developed by XML-Dev, led by David
+       Megginson and ported to Python by Lars Marius Garshol.  This
+       supports the SAX 2 API.
+
+"""
+
+__all__ = ['dom', 'sax']
+
+
+_MINIMUM_XMLPLUS_VERSION = (0, 8, 5)
+
+
+try:
+    import _xmlplus
+except ImportError:
+    pass
+else:
+    try:
+        v = _xmlplus.version_info
+    except AttributeError:
+        # _xmlplus is too old; ignore it
+        pass
+    else:
+        if v >= _MINIMUM_XMLPLUS_VERSION:
+            import sys
+            _xmlplus.__path__.extend(__path__)
+            sys.modules[__name__] = _xmlplus
+        else:
+            del v
diff --git a/src/main/resources/PythonLibs/xml/dom/MessageSource.py b/src/main/resources/PythonLibs/xml/dom/MessageSource.py
new file mode 100644
index 0000000000000000000000000000000000000000..d9503ae1f6ddf7c01e35e3f83a7f203b2282e7c0
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/dom/MessageSource.py
@@ -0,0 +1,54 @@
+# DOMException
+from xml.dom import INDEX_SIZE_ERR, DOMSTRING_SIZE_ERR , HIERARCHY_REQUEST_ERR
+from xml.dom import WRONG_DOCUMENT_ERR, INVALID_CHARACTER_ERR, NO_DATA_ALLOWED_ERR
+from xml.dom import NO_MODIFICATION_ALLOWED_ERR, NOT_FOUND_ERR, NOT_SUPPORTED_ERR
+from xml.dom import INUSE_ATTRIBUTE_ERR, INVALID_STATE_ERR, SYNTAX_ERR
+from xml.dom import INVALID_MODIFICATION_ERR, NAMESPACE_ERR, INVALID_ACCESS_ERR
+from xml.dom import VALIDATION_ERR
+
+# EventException
+from xml.dom import UNSPECIFIED_EVENT_TYPE_ERR
+
+#Range Exceptions
+from xml.dom import BAD_BOUNDARYPOINTS_ERR
+from xml.dom import INVALID_NODE_TYPE_ERR
+
+# Fourthought Exceptions
+from xml.dom import XML_PARSE_ERR
+
+from xml.FtCore import get_translator
+
+_ = get_translator("dom")
+
+
+DOMExceptionStrings = {
+    INDEX_SIZE_ERR: _("Index error accessing NodeList or NamedNodeMap"),
+    DOMSTRING_SIZE_ERR: _("DOMString exceeds maximum size"),
+    HIERARCHY_REQUEST_ERR: _("Node manipulation results in invalid parent/child relationship."),
+    WRONG_DOCUMENT_ERR: _("Node is from a different document"),
+    INVALID_CHARACTER_ERR: _("Invalid or illegal character"),
+    NO_DATA_ALLOWED_ERR: _("Node does not support data"),
+    NO_MODIFICATION_ALLOWED_ERR: _("Attempt to modify a read-only object"),
+    NOT_FOUND_ERR: _("Node does not exist in this context"),
+    NOT_SUPPORTED_ERR: _("Object or operation not supported"),
+    INUSE_ATTRIBUTE_ERR: _("Attribute already in use by an element"),
+    INVALID_STATE_ERR: _("Object is not, or is no longer, usable"),
+    SYNTAX_ERR: _("Specified string is invalid or illegal"),
+    INVALID_MODIFICATION_ERR: _("Attempt to modify the type of a node"),
+    NAMESPACE_ERR: _("Invalid or illegal namespace operation"),
+    INVALID_ACCESS_ERR: _("Object does not support this operation or parameter"),
+    VALIDATION_ERR: _("Operation would invalidate partial validity constraint"),
+    }
+
+EventExceptionStrings = {
+    UNSPECIFIED_EVENT_TYPE_ERR : _("Uninitialized type in Event object"),
+    }
+
+FtExceptionStrings = {
+    XML_PARSE_ERR : _("XML parse error at line %d, column %d: %s"),
+    }
+
+RangeExceptionStrings = {
+    BAD_BOUNDARYPOINTS_ERR : _("Invalid Boundary Points specified for Range"),
+    INVALID_NODE_TYPE_ERR : _("Invalid Container Node")
+    }
diff --git a/src/main/resources/PythonLibs/xml/dom/NodeFilter.py b/src/main/resources/PythonLibs/xml/dom/NodeFilter.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc052459da4a73bfab59a0bf2ab2e30429db9955
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/dom/NodeFilter.py
@@ -0,0 +1,27 @@
+# This is the Python mapping for interface NodeFilter from
+# DOM2-Traversal-Range. It contains only constants.
+
+class NodeFilter:
+    """
+    This is the DOM2 NodeFilter interface. It contains only constants.
+    """
+    FILTER_ACCEPT = 1
+    FILTER_REJECT = 2
+    FILTER_SKIP   = 3
+
+    SHOW_ALL                    = 0xFFFFFFFFL
+    SHOW_ELEMENT                = 0x00000001
+    SHOW_ATTRIBUTE              = 0x00000002
+    SHOW_TEXT                   = 0x00000004
+    SHOW_CDATA_SECTION          = 0x00000008
+    SHOW_ENTITY_REFERENCE       = 0x00000010
+    SHOW_ENTITY                 = 0x00000020
+    SHOW_PROCESSING_INSTRUCTION = 0x00000040
+    SHOW_COMMENT                = 0x00000080
+    SHOW_DOCUMENT               = 0x00000100
+    SHOW_DOCUMENT_TYPE          = 0x00000200
+    SHOW_DOCUMENT_FRAGMENT      = 0x00000400
+    SHOW_NOTATION               = 0x00000800
+
+    def acceptNode(self, node):
+        raise NotImplementedError
diff --git a/src/main/resources/PythonLibs/xml/dom/__init__.py b/src/main/resources/PythonLibs/xml/dom/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c645bfe67ed49daa9eaedd63d262eb62e35a87d
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/dom/__init__.py
@@ -0,0 +1,232 @@
+########################################################################
+#
+# File Name:            __init__.py
+#
+#
+"""
+WWW: http://4suite.org/4DOM         e-mail: support@4suite.org
+
+Copyright (c) 2000 Fourthought Inc, USA.   All Rights Reserved.
+See  http://4suite.org/COPYRIGHT  for license and copyright information
+"""
+
+
+class Node:
+    """Class giving the nodeType and tree-position constants."""
+
+    # DOM implementations may use this as a base class for their own
+    # Node implementations.  If they don't, the constants defined here
+    # should still be used as the canonical definitions as they match
+    # the values given in the W3C recommendation.  Client code can
+    # safely refer to these values in all tests of Node.nodeType
+    # values.
+
+    ELEMENT_NODE                = 1
+    ATTRIBUTE_NODE              = 2
+    TEXT_NODE                   = 3
+    CDATA_SECTION_NODE          = 4
+    ENTITY_REFERENCE_NODE       = 5
+    ENTITY_NODE                 = 6
+    PROCESSING_INSTRUCTION_NODE = 7
+    COMMENT_NODE                = 8
+    DOCUMENT_NODE               = 9
+    DOCUMENT_TYPE_NODE          = 10
+    DOCUMENT_FRAGMENT_NODE      = 11
+    NOTATION_NODE               = 12
+
+    # Based on DOM Level 3 (WD 9 April 2002)
+
+    TREE_POSITION_PRECEDING    = 0x01
+    TREE_POSITION_FOLLOWING    = 0x02
+    TREE_POSITION_ANCESTOR     = 0x04
+    TREE_POSITION_DESCENDENT   = 0x08
+    TREE_POSITION_EQUIVALENT   = 0x10
+    TREE_POSITION_SAME_NODE    = 0x20
+    TREE_POSITION_DISCONNECTED = 0x00
+
+class UserDataHandler:
+    """Class giving the operation constants for UserDataHandler.handle()."""
+
+    # Based on DOM Level 3 (WD 9 April 2002)
+
+    NODE_CLONED   = 1
+    NODE_IMPORTED = 2
+    NODE_DELETED  = 3
+    NODE_RENAMED  = 4
+
+class DOMError:
+    """Class giving constants for error severity."""
+
+    # Based on DOM Level 3 (WD 9 April 2002)
+
+    SEVERITY_WARNING     = 0
+    SEVERITY_ERROR       = 1
+    SEVERITY_FATAL_ERROR = 2
+
+
+# DOMException codes
+INDEX_SIZE_ERR                 = 1
+DOMSTRING_SIZE_ERR             = 2
+HIERARCHY_REQUEST_ERR          = 3
+WRONG_DOCUMENT_ERR             = 4
+INVALID_CHARACTER_ERR          = 5
+NO_DATA_ALLOWED_ERR            = 6
+NO_MODIFICATION_ALLOWED_ERR    = 7
+NOT_FOUND_ERR                  = 8
+NOT_SUPPORTED_ERR              = 9
+INUSE_ATTRIBUTE_ERR            = 10
+# DOM Level 2
+INVALID_STATE_ERR              = 11
+SYNTAX_ERR                     = 12
+INVALID_MODIFICATION_ERR       = 13
+NAMESPACE_ERR                  = 14
+INVALID_ACCESS_ERR             = 15
+# DOM Level 3
+VALIDATION_ERR                 = 16
+
+# EventException codes
+UNSPECIFIED_EVENT_TYPE_ERR     = 0
+
+# Fourthought specific codes
+FT_EXCEPTION_BASE = 1000
+XML_PARSE_ERR = FT_EXCEPTION_BASE + 1
+
+#RangeException codes
+BAD_BOUNDARYPOINTS_ERR = 1
+INVALID_NODE_TYPE_ERR = 2
+
+
+class DOMException(Exception):
+    def __init__(self, code, msg=''):
+        self.code = code
+        self.msg = msg or DOMExceptionStrings[code]
+
+    def __str__(self):
+        return self.msg
+
+class EventException(Exception):
+    def __init__(self, code, msg=''):
+        self.code = code
+        self.msg = msg or EventExceptionStrings[code]
+        return
+
+    def __str__(self):
+        return self.msg
+
+class RangeException(Exception):
+    def __init__(self, code, msg):
+        self.code = code
+        self.msg = msg or RangeExceptionStrings[code]
+        Exception.__init__(self, self.msg)
+
+class FtException(Exception):
+    def __init__(self, code, *args):
+        self.code = code
+        self.msg = FtExceptionStrings[code] % args
+        return
+
+    def __str__(self):
+        return self.msg
+
+class IndexSizeErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, INDEX_SIZE_ERR, msg)
+
+class DomstringSizeErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, DOMSTRING_SIZE_ERR, msg)
+
+# DOMStringSizeErr was accidentally introduced in rev 1.14 of this
+# file, and was released as part of PyXML 0.6.4, 0.6.5, 0.6.6, 0.7,
+# and 0.7.1.  It has never been part of the Python DOM API, although
+# it better matches the W3C recommendation.  It should remain for
+# compatibility, unfortunately.
+#
+DOMStringSizeErr = DomstringSizeErr
+
+class HierarchyRequestErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, HIERARCHY_REQUEST_ERR, msg)
+
+class WrongDocumentErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, WRONG_DOCUMENT_ERR, msg)
+
+class InvalidCharacterErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, INVALID_CHARACTER_ERR, msg)
+
+class NoDataAllowedErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, NO_DATA_ALLOWED_ERR, msg)
+
+class NoModificationAllowedErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, NO_MODIFICATION_ALLOWED_ERR, msg)
+
+class NotFoundErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, NOT_FOUND_ERR, msg)
+
+class NotSupportedErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, NOT_SUPPORTED_ERR, msg)
+
+class InuseAttributeErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, INUSE_ATTRIBUTE_ERR, msg)
+
+class InvalidStateErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, INVALID_STATE_ERR, msg)
+
+class SyntaxErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, SYNTAX_ERR, msg)
+
+class InvalidModificationErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, INVALID_MODIFICATION_ERR, msg)
+
+class NamespaceErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, NAMESPACE_ERR, msg)
+
+class InvalidAccessErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, INVALID_ACCESS_ERR, msg)
+
+class ValidationErr(DOMException):
+    def __init__(self, msg=''):
+        DOMException.__init__(self, VALIDATION_ERR, msg)
+
+class UnspecifiedEventTypeErr(EventException):
+    def __init__(self, msg=''):
+        EventException.__init__(self, UNSPECIFIED_EVENT_TYPE_ERR, msg)
+
+class XmlParseErr(FtException):
+    def __init__(self, msg=''):
+        FtException.__init__(self, XML_PARSE_ERR, msg)
+
+#Specific Range Exceptions
+class BadBoundaryPointsErr(RangeException):
+    def __init__(self, msg=''):
+        RangeException.__init__(self, BAD_BOUNDARYPOINTS_ERR, msg)
+
+class InvalidNodeTypeErr(RangeException):
+    def __init__(self, msg=''):
+        RangeException.__init__(self, INVALID_NODE_TYPE_ERR, msg)
+
+XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace"
+XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/"
+XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml"
+EMPTY_NAMESPACE = None
+EMPTY_PREFIX = None
+
+import MessageSource
+DOMExceptionStrings = MessageSource.__dict__['DOMExceptionStrings']
+EventExceptionStrings = MessageSource.__dict__['EventExceptionStrings']
+FtExceptionStrings = MessageSource.__dict__['FtExceptionStrings']
+RangeExceptionStrings = MessageSource.__dict__['RangeExceptionStrings']
+
+from domreg import getDOMImplementation,registerDOMImplementation
diff --git a/src/main/resources/PythonLibs/xml/dom/domreg.py b/src/main/resources/PythonLibs/xml/dom/domreg.py
new file mode 100644
index 0000000000000000000000000000000000000000..117ca498202eaf73330c190ec65067bf2f3dfb08
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/dom/domreg.py
@@ -0,0 +1,99 @@
+"""Registration facilities for DOM. This module should not be used
+directly. Instead, the functions getDOMImplementation and
+registerDOMImplementation should be imported from xml.dom."""
+
+from xml.dom.minicompat import *  # isinstance, StringTypes
+
+# This is a list of well-known implementations.  Well-known names
+# should be published by posting to xml-sig@python.org, and are
+# subsequently recorded in this file.
+
+well_known_implementations = {
+    'minidom':'xml.dom.minidom',
+    '4DOM': 'xml.dom.DOMImplementation',
+    }
+
+# DOM implementations not officially registered should register
+# themselves with their
+
+registered = {}
+
+def registerDOMImplementation(name, factory):
+    """registerDOMImplementation(name, factory)
+
+    Register the factory function with the name. The factory function
+    should return an object which implements the DOMImplementation
+    interface. The factory function can either return the same object,
+    or a new one (e.g. if that implementation supports some
+    customization)."""
+
+    registered[name] = factory
+
+def _good_enough(dom, features):
+    "_good_enough(dom, features) -> Return 1 if the dom offers the features"
+    for f,v in features:
+        if not dom.hasFeature(f,v):
+            return 0
+    return 1
+
+def getDOMImplementation(name = None, features = ()):
+    """getDOMImplementation(name = None, features = ()) -> DOM implementation.
+
+    Return a suitable DOM implementation. The name is either
+    well-known, the module name of a DOM implementation, or None. If
+    it is not None, imports the corresponding module and returns
+    DOMImplementation object if the import succeeds.
+
+    If name is not given, consider the available implementations to
+    find one with the required feature set. If no implementation can
+    be found, raise an ImportError. The features list must be a sequence
+    of (feature, version) pairs which are passed to hasFeature."""
+
+    import os
+    creator = None
+    mod = well_known_implementations.get(name)
+    if mod:
+        mod = __import__(mod, {}, {}, ['getDOMImplementation'])
+        return mod.getDOMImplementation()
+    elif name:
+        return registered[name]()
+    elif os.environ.has_key("PYTHON_DOM"):
+        return getDOMImplementation(name = os.environ["PYTHON_DOM"])
+
+    # User did not specify a name, try implementations in arbitrary
+    # order, returning the one that has the required features
+    if isinstance(features, StringTypes):
+        features = _parse_feature_string(features)
+    for creator in registered.values():
+        dom = creator()
+        if _good_enough(dom, features):
+            return dom
+
+    for creator in well_known_implementations.keys():
+        try:
+            dom = getDOMImplementation(name = creator)
+        except StandardError: # typically ImportError, or AttributeError
+            continue
+        if _good_enough(dom, features):
+            return dom
+
+    raise ImportError,"no suitable DOM implementation found"
+
+def _parse_feature_string(s):
+    features = []
+    parts = s.split()
+    i = 0
+    length = len(parts)
+    while i < length:
+        feature = parts[i]
+        if feature[0] in "0123456789":
+            raise ValueError, "bad feature name: " + `feature`
+        i = i + 1
+        version = None
+        if i < length:
+            v = parts[i]
+            if v[0] in "0123456789":
+                i = i + 1
+                version = v
+        features.append((feature, version))
+    return tuple(features)
diff --git a/src/main/resources/PythonLibs/xml/dom/minicompat.py b/src/main/resources/PythonLibs/xml/dom/minicompat.py
new file mode 100644
index 0000000000000000000000000000000000000000..9f2f8f76271d7e37e7c003ba13b9cf85bbbdb935
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/dom/minicompat.py
@@ -0,0 +1,184 @@
+"""Python version compatibility support for minidom."""
+
+# This module should only be imported using "import *".
+#
+# The following names are defined:
+#
+#   isinstance    -- version of the isinstance() function that accepts
+#                    tuples as the second parameter regardless of the
+#                    Python version
+#
+#   NodeList      -- lightest possible NodeList implementation
+#
+#   EmptyNodeList -- lightest possible NodeList that is guarateed to
+#                    remain empty (immutable)
+#
+#   StringTypes   -- tuple of defined string types
+#
+#   GetattrMagic  -- base class used to make _get_<attr> be magically
+#                    invoked when available
+#   defproperty   -- function used in conjunction with GetattrMagic;
+#                    using these together is needed to make them work
+#                    as efficiently as possible in both Python 2.2+
+#                    and older versions.  For example:
+#
+#                        class MyClass(GetattrMagic):
+#                            def _get_myattr(self):
+#                                return something
+#
+#                        defproperty(MyClass, "myattr",
+#                                    "return some value")
+#
+#                    For Python 2.2 and newer, this will construct a
+#                    property object on the class, which avoids
+#                    needing to override __getattr__().  It will only
+#                    work for read-only attributes.
+#
+#                    For older versions of Python, inheriting from
+#                    GetattrMagic will use the traditional
+#                    __getattr__() hackery to achieve the same effect,
+#                    but less efficiently.
+#
+#                    defproperty() should be used for each version of
+#                    the relevant _get_<property>() function.
+#
+#   NewStyle      -- base class to cause __slots__ to be honored in
+#                    the new world
+#
+#   True, False   -- only for Python 2.2 and earlier
+
+__all__ = ["NodeList", "EmptyNodeList", "NewStyle",
+           "StringTypes", "defproperty", "GetattrMagic"]
+
+import xml.dom
+
+try:
+    unicode
+except NameError:
+    StringTypes = type(''),
+else:
+    StringTypes = type(''), type(unicode(''))
+
+
+# define True and False only if not defined as built-ins
+try:
+    True
+except NameError:
+    True = 1
+    False = 0
+    __all__.extend(["True", "False"])
+
+
+try:
+    isinstance('', StringTypes)
+except TypeError:
+    #
+    # Wrap isinstance() to make it compatible with the version in
+    # Python 2.2 and newer.
+    #
+    _isinstance = isinstance
+    def isinstance(obj, type_or_seq):
+        try:
+            return _isinstance(obj, type_or_seq)
+        except TypeError:
+            for t in type_or_seq:
+                if _isinstance(obj, t):
+                    return 1
+            return 0
+    __all__.append("isinstance")
+
+
+if list is type([]):
+    class NodeList(list):
+        __slots__ = ()
+
+        def item(self, index):
+            if 0 <= index < len(self):
+                return self[index]
+
+        def _get_length(self):
+            return len(self)
+
+        def _set_length(self, value):
+            raise xml.dom.NoModificationAllowedErr(
+                "attempt to modify read-only attribute 'length'")
+
+        length = property(_get_length, _set_length,
+                          doc="The number of nodes in the NodeList.")
+
+        def __getstate__(self):
+            return list(self)
+
+        def __setstate__(self, state):
+            self[:] = state
+
+    class EmptyNodeList(tuple):
+        __slots__ = ()
+
+        def __add__(self, other):
+            NL = NodeList()
+            NL.extend(other)
+            return NL
+
+        def __radd__(self, other):
+            NL = NodeList()
+            NL.extend(other)
+            return NL
+
+        def item(self, index):
+            return None
+
+        def _get_length(self):
+            return 0
+
+        def _set_length(self, value):
+            raise xml.dom.NoModificationAllowedErr(
+                "attempt to modify read-only attribute 'length'")
+
+        length = property(_get_length, _set_length,
+                          doc="The number of nodes in the NodeList.")
+
+else:
+    def NodeList():
+        return []
+
+    def EmptyNodeList():
+        return []
+
+
+try:
+    property
+except NameError:
+    def defproperty(klass, name, doc):
+        # taken care of by the base __getattr__()
+        pass
+
+    class GetattrMagic:
+        def __getattr__(self, key):
+            if key.startswith("_"):
+                raise AttributeError, key
+
+            try:
+                get = getattr(self, "_get_" + key)
+            except AttributeError:
+                raise AttributeError, key
+            return get()
+
+    class NewStyle:
+        pass
+
+else:
+    def defproperty(klass, name, doc):
+        get = getattr(klass, ("_get_" + name)).im_func
+        def set(self, value, name=name):
+            raise xml.dom.NoModificationAllowedErr(
+                "attempt to modify read-only attribute " + repr(name))
+        assert not hasattr(klass, "_set_" + name), \
+               "expected not to find _set_" + name
+        prop = property(get, set, doc=doc)
+        setattr(klass, name, prop)
+
+    class GetattrMagic:
+        pass
+
+    NewStyle = object
diff --git a/src/main/resources/PythonLibs/xml/dom/minidom.py b/src/main/resources/PythonLibs/xml/dom/minidom.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7f3be9d557c3918a0bf164456a87a0d6aa20c92
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/dom/minidom.py
@@ -0,0 +1,1944 @@
+"""\
+minidom.py -- a lightweight DOM implementation.
+
+parse("foo.xml")
+
+parseString("<foo><bar/></foo>")
+
+Todo:
+=====
+ * convenience methods for getting elements and text.
+ * more testing
+ * bring some of the writer and linearizer code into conformance with this
+        interface
+ * SAX 2 namespaces
+"""
+
+import xml.dom
+
+from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE, domreg
+from xml.dom.minicompat import *
+from xml.dom.xmlbuilder import DOMImplementationLS, DocumentLS
+
+_TupleType = type(())
+
+# This is used by the ID-cache invalidation checks; the list isn't
+# actually complete, since the nodes being checked will never be the
+# DOCUMENT_NODE or DOCUMENT_FRAGMENT_NODE.  (The node being checked is
+# the node being added or removed, not the node being modified.)
+#
+_nodeTypes_with_children = (xml.dom.Node.ELEMENT_NODE,
+                            xml.dom.Node.ENTITY_REFERENCE_NODE)
+
+
+class Node(xml.dom.Node, GetattrMagic):
+    namespaceURI = None # this is non-null only for elements and attributes
+    parentNode = None
+    ownerDocument = None
+    nextSibling = None
+    previousSibling = None
+
+    prefix = EMPTY_PREFIX # non-null only for NS elements and attributes
+
+    def __nonzero__(self):
+        return True
+
+    def toxml(self, encoding = None):
+        return self.toprettyxml("", "", encoding)
+
+    def toprettyxml(self, indent="\t", newl="\n", encoding = None):
+        # indent = the indentation string to prepend, per level
+        # newl = the newline string to append
+        writer = _get_StringIO()
+        if encoding is not None:
+            import codecs
+            # Can't use codecs.getwriter to preserve 2.0 compatibility
+            writer = codecs.lookup(encoding)[3](writer)
+        if self.nodeType == Node.DOCUMENT_NODE:
+            # Can pass encoding only to document, to put it into XML header
+            self.writexml(writer, "", indent, newl, encoding)
+        else:
+            self.writexml(writer, "", indent, newl)
+        return writer.getvalue()
+
+    def hasAttributes(self):
+        return False
+
+    def hasChildNodes(self):
+        if self.childNodes:
+            return True
+        else:
+            return False
+
+    def _get_childNodes(self):
+        return self.childNodes
+
+    def _get_firstChild(self):
+        if self.childNodes:
+            return self.childNodes[0]
+
+    def _get_lastChild(self):
+        if self.childNodes:
+            return self.childNodes[-1]
+
+    def insertBefore(self, newChild, refChild):
+        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
+            for c in tuple(newChild.childNodes):
+                self.insertBefore(c, refChild)
+            ### The DOM does not clearly specify what to return in this case
+            return newChild
+        if newChild.nodeType not in self._child_node_types:
+            raise xml.dom.HierarchyRequestErr(
+                "%s cannot be child of %s" % (repr(newChild), repr(self)))
+        if newChild.parentNode is not None:
+            newChild.parentNode.removeChild(newChild)
+        if refChild is None:
+            self.appendChild(newChild)
+        else:
+            try:
+                index = self.childNodes.index(refChild)
+            except ValueError:
+                raise xml.dom.NotFoundErr()
+            if newChild.nodeType in _nodeTypes_with_children:
+                _clear_id_cache(self)
+            self.childNodes.insert(index, newChild)
+            newChild.nextSibling = refChild
+            refChild.previousSibling = newChild
+            if index:
+                node = self.childNodes[index-1]
+                node.nextSibling = newChild
+                newChild.previousSibling = node
+            else:
+                newChild.previousSibling = None
+            newChild.parentNode = self
+        return newChild
+
+    def appendChild(self, node):
+        if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
+            for c in tuple(node.childNodes):
+                self.appendChild(c)
+            ### The DOM does not clearly specify what to return in this case
+            return node
+        if node.nodeType not in self._child_node_types:
+            raise xml.dom.HierarchyRequestErr(
+                "%s cannot be child of %s" % (repr(node), repr(self)))
+        elif node.nodeType in _nodeTypes_with_children:
+            _clear_id_cache(self)
+        if node.parentNode is not None:
+            node.parentNode.removeChild(node)
+        _append_child(self, node)
+        node.nextSibling = None
+        return node
+
+    def replaceChild(self, newChild, oldChild):
+        if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
+            refChild = oldChild.nextSibling
+            self.removeChild(oldChild)
+            return self.insertBefore(newChild, refChild)
+        if newChild.nodeType not in self._child_node_types:
+            raise xml.dom.HierarchyRequestErr(
+                "%s cannot be child of %s" % (repr(newChild), repr(self)))
+        if newChild.parentNode is not None:
+            newChild.parentNode.removeChild(newChild)
+        if newChild is oldChild:
+            return
+        try:
+            index = self.childNodes.index(oldChild)
+        except ValueError:
+            raise xml.dom.NotFoundErr()
+        if (newChild.nodeType in _nodeTypes_with_children
+            or oldChild.nodeType in _nodeTypes_with_children):
+            _clear_id_cache(self)
+        self.childNodes[index] = newChild
+        newChild.parentNode = self
+        oldChild.parentNode = None
+        newChild.nextSibling = oldChild.nextSibling
+        newChild.previousSibling = oldChild.previousSibling
+        oldChild.nextSibling = None
+        oldChild.previousSibling = None
+        if newChild.previousSibling:
+            newChild.previousSibling.nextSibling = newChild
+        if newChild.nextSibling:
+            newChild.nextSibling.previousSibling = newChild
+        return oldChild
+
+    def removeChild(self, oldChild):
+        try:
+            self.childNodes.remove(oldChild)
+        except ValueError:
+            raise xml.dom.NotFoundErr()
+        if oldChild.nextSibling is not None:
+            oldChild.nextSibling.previousSibling = oldChild.previousSibling
+        if oldChild.previousSibling is not None:
+            oldChild.previousSibling.nextSibling = oldChild.nextSibling
+        oldChild.nextSibling = oldChild.previousSibling = None
+        if oldChild.nodeType in _nodeTypes_with_children:
+            _clear_id_cache(self)
+
+        oldChild.parentNode = None
+        return oldChild
+
+    def normalize(self):
+        L = []
+        for child in self.childNodes:
+            if child.nodeType == Node.TEXT_NODE:
+                data = child.data
+                if data and L and L[-1].nodeType == child.nodeType:
+                    # collapse text node
+                    node = L[-1]
+                    node.data = node.data + child.data
+                    node.nextSibling = child.nextSibling
+                    child.unlink()
+                elif data:
+                    if L:
+                        L[-1].nextSibling = child
+                        child.previousSibling = L[-1]
+                    else:
+                        child.previousSibling = None
+                    L.append(child)
+                else:
+                    # empty text node; discard
+                    child.unlink()
+            else:
+                if L:
+                    L[-1].nextSibling = child
+                    child.previousSibling = L[-1]
+                else:
+                    child.previousSibling = None
+                L.append(child)
+                if child.nodeType == Node.ELEMENT_NODE:
+                    child.normalize()
+        if self.childNodes:
+            self.childNodes[:] = L
+        return
+
+    def cloneNode(self, deep):
+        return _clone_node(self, deep, self.ownerDocument or self)
+
+    def isSupported(self, feature, version):
+        return self.ownerDocument.implementation.hasFeature(feature, version)
+
+    def _get_localName(self):
+        # Overridden in Element and Attr where localName can be Non-Null
+        return None
+
+    # Node interfaces from Level 3 (WD 9 April 2002)
+
+    def isSameNode(self, other):
+        return self is other
+
+    def getInterface(self, feature):
+        if self.isSupported(feature, None):
+            return self
+        else:
+            return None
+
+    # The "user data" functions use a dictionary that is only present
+    # if some user data has been set, so be careful not to assume it
+    # exists.
+
+    def getUserData(self, key):
+        try:
+            return self._user_data[key][0]
+        except (AttributeError, KeyError):
+            return None
+
+    def setUserData(self, key, data, handler):
+        old = None
+        try:
+            d = self._user_data
+        except AttributeError:
+            d = {}
+            self._user_data = d
+        if d.has_key(key):
+            old = d[key][0]
+        if data is None:
+            # ignore handlers passed for None
+            handler = None
+            if old is not None:
+                del d[key]
+        else:
+            d[key] = (data, handler)
+        return old
+
+    def _call_user_data_handler(self, operation, src, dst):
+        if hasattr(self, "_user_data"):
+            for key, (data, handler) in self._user_data.items():
+                if handler is not None:
+                    handler.handle(operation, key, data, src, dst)
+
+    # minidom-specific API:
+
+    def unlink(self):
+        self.parentNode = self.ownerDocument = None
+        if self.childNodes:
+            for child in self.childNodes:
+                child.unlink()
+            self.childNodes = NodeList()
+        self.previousSibling = None
+        self.nextSibling = None
+
+defproperty(Node, "firstChild", doc="First child node, or None.")
+defproperty(Node, "lastChild",  doc="Last child node, or None.")
+defproperty(Node, "localName",  doc="Namespace-local name of this node.")
+
+
+def _append_child(self, node):
+    # fast path with less checks; usable by DOM builders if careful
+    childNodes = self.childNodes
+    if childNodes:
+        last = childNodes[-1]
+        node.__dict__["previousSibling"] = last
+        last.__dict__["nextSibling"] = node
+    childNodes.append(node)
+    node.__dict__["parentNode"] = self
+
+def _in_document(node):
+    # return True iff node is part of a document tree
+    while node is not None:
+        if node.nodeType == Node.DOCUMENT_NODE:
+            return True
+        node = node.parentNode
+    return False
+
+def _write_data(writer, data):
+    "Writes datachars to writer."
+    data = data.replace("&", "&amp;").replace("<", "&lt;")
+    data = data.replace("\"", "&quot;").replace(">", "&gt;")
+    writer.write(data)
+
+def _get_elements_by_tagName_helper(parent, name, rc):
+    for node in parent.childNodes:
+        if node.nodeType == Node.ELEMENT_NODE and \
+            (name == "*" or node.tagName == name):
+            rc.append(node)
+        _get_elements_by_tagName_helper(node, name, rc)
+    return rc
+
+def _get_elements_by_tagName_ns_helper(parent, nsURI, localName, rc):
+    for node in parent.childNodes:
+        if node.nodeType == Node.ELEMENT_NODE:
+            if ((localName == "*" or node.localName == localName) and
+                (nsURI == "*" or node.namespaceURI == nsURI)):
+                rc.append(node)
+            _get_elements_by_tagName_ns_helper(node, nsURI, localName, rc)
+    return rc
+
+class DocumentFragment(Node):
+    nodeType = Node.DOCUMENT_FRAGMENT_NODE
+    nodeName = "#document-fragment"
+    nodeValue = None
+    attributes = None
+    parentNode = None
+    _child_node_types = (Node.ELEMENT_NODE,
+                         Node.TEXT_NODE,
+                         Node.CDATA_SECTION_NODE,
+                         Node.ENTITY_REFERENCE_NODE,
+                         Node.PROCESSING_INSTRUCTION_NODE,
+                         Node.COMMENT_NODE,
+                         Node.NOTATION_NODE)
+
+    def __init__(self):
+        self.childNodes = NodeList()
+
+
+class Attr(Node):
+    nodeType = Node.ATTRIBUTE_NODE
+    attributes = None
+    ownerElement = None
+    specified = False
+    _is_id = False
+
+    _child_node_types = (Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE)
+
+    def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
+                 prefix=None):
+        # skip setattr for performance
+        d = self.__dict__
+        d["nodeName"] = d["name"] = qName
+        d["namespaceURI"] = namespaceURI
+        d["prefix"] = prefix
+        d['childNodes'] = NodeList()
+
+        # Add the single child node that represents the value of the attr
+        self.childNodes.append(Text())
+
+        # nodeValue and value are set elsewhere
+
+    def _get_localName(self):
+        return self.nodeName.split(":", 1)[-1]
+
+    def _get_name(self):
+        return self.name
+
+    def _get_specified(self):
+        return self.specified
+
+    def __setattr__(self, name, value):
+        d = self.__dict__
+        if name in ("value", "nodeValue"):
+            d["value"] = d["nodeValue"] = value
+            d2 = self.childNodes[0].__dict__
+            d2["data"] = d2["nodeValue"] = value
+            if self.ownerElement is not None:
+                _clear_id_cache(self.ownerElement)
+        elif name in ("name", "nodeName"):
+            d["name"] = d["nodeName"] = value
+            if self.ownerElement is not None:
+                _clear_id_cache(self.ownerElement)
+        else:
+            d[name] = value
+
+    def _set_prefix(self, prefix):
+        nsuri = self.namespaceURI
+        if prefix == "xmlns":
+            if nsuri and nsuri != XMLNS_NAMESPACE:
+                raise xml.dom.NamespaceErr(
+                    "illegal use of 'xmlns' prefix for the wrong namespace")
+        d = self.__dict__
+        d['prefix'] = prefix
+        if prefix is None:
+            newName = self.localName
+        else:
+            newName = "%s:%s" % (prefix, self.localName)
+        if self.ownerElement:
+            _clear_id_cache(self.ownerElement)
+        d['nodeName'] = d['name'] = newName
+
+    def _set_value(self, value):
+        d = self.__dict__
+        d['value'] = d['nodeValue'] = value
+        if self.ownerElement:
+            _clear_id_cache(self.ownerElement)
+        self.childNodes[0].data = value
+
+    def unlink(self):
+        # This implementation does not call the base implementation
+        # since most of that is not needed, and the expense of the
+        # method call is not warranted.  We duplicate the removal of
+        # children, but that's all we needed from the base class.
+        elem = self.ownerElement
+        if elem is not None:
+            del elem._attrs[self.nodeName]
+            del elem._attrsNS[(self.namespaceURI, self.localName)]
+            if self._is_id:
+                self._is_id = False
+                elem._magic_id_nodes -= 1
+                self.ownerDocument._magic_id_count -= 1
+        for child in self.childNodes:
+            child.unlink()
+        del self.childNodes[:]
+
+    def _get_isId(self):
+        if self._is_id:
+            return True
+        doc = self.ownerDocument
+        elem = self.ownerElement
+        if doc is None or elem is None:
+            return False
+
+        info = doc._get_elem_info(elem)
+        if info is None:
+            return False
+        if self.namespaceURI:
+            return info.isIdNS(self.namespaceURI, self.localName)
+        else:
+            return info.isId(self.nodeName)
+
+    def _get_schemaType(self):
+        doc = self.ownerDocument
+        elem = self.ownerElement
+        if doc is None or elem is None:
+            return _no_type
+
+        info = doc._get_elem_info(elem)
+        if info is None:
+            return _no_type
+        if self.namespaceURI:
+            return info.getAttributeTypeNS(self.namespaceURI, self.localName)
+        else:
+            return info.getAttributeType(self.nodeName)
+
+defproperty(Attr, "isId",       doc="True if this attribute is an ID.")
+defproperty(Attr, "localName",  doc="Namespace-local name of this attribute.")
+defproperty(Attr, "schemaType", doc="Schema type for this attribute.")
+
+
+class NamedNodeMap(NewStyle, GetattrMagic):
+    """The attribute list is a transient interface to the underlying
+    dictionaries.  Mutations here will change the underlying element's
+    dictionary.
+
+    Ordering is imposed artificially and does not reflect the order of
+    attributes as found in an input document.
+    """
+
+    __slots__ = ('_attrs', '_attrsNS', '_ownerElement')
+
+    def __init__(self, attrs, attrsNS, ownerElement):
+        self._attrs = attrs
+        self._attrsNS = attrsNS
+        self._ownerElement = ownerElement
+
+    def _get_length(self):
+        return len(self._attrs)
+
+    def item(self, index):
+        try:
+            return self[self._attrs.keys()[index]]
+        except IndexError:
+            return None
+
+    def items(self):
+        L = []
+        for node in self._attrs.values():
+            L.append((node.nodeName, node.value))
+        return L
+
+    def itemsNS(self):
+        L = []
+        for node in self._attrs.values():
+            L.append(((node.namespaceURI, node.localName), node.value))
+        return L
+
+    def has_key(self, key):
+        if isinstance(key, StringTypes):
+            return self._attrs.has_key(key)
+        else:
+            return self._attrsNS.has_key(key)
+
+    def keys(self):
+        return self._attrs.keys()
+
+    def keysNS(self):
+        return self._attrsNS.keys()
+
+    def values(self):
+        return self._attrs.values()
+
+    def get(self, name, value=None):
+        return self._attrs.get(name, value)
+
+    __len__ = _get_length
+
+    def __cmp__(self, other):
+        if self._attrs is getattr(other, "_attrs", None):
+            return 0
+        else:
+            return cmp(id(self), id(other))
+
+    def __getitem__(self, attname_or_tuple):
+        if isinstance(attname_or_tuple, _TupleType):
+            return self._attrsNS[attname_or_tuple]
+        else:
+            return self._attrs[attname_or_tuple]
+
+    # same as set
+    def __setitem__(self, attname, value):
+        if isinstance(value, StringTypes):
+            try:
+                node = self._attrs[attname]
+            except KeyError:
+                node = Attr(attname)
+                node.ownerDocument = self._ownerElement.ownerDocument
+                self.setNamedItem(node)
+            node.value = value
+        else:
+            if not isinstance(value, Attr):
+                raise TypeError, "value must be a string or Attr object"
+            node = value
+            self.setNamedItem(node)
+
+    def getNamedItem(self, name):
+        try:
+            return self._attrs[name]
+        except KeyError:
+            return None
+
+    def getNamedItemNS(self, namespaceURI, localName):
+        try:
+            return self._attrsNS[(namespaceURI, localName)]
+        except KeyError:
+            return None
+
+    def removeNamedItem(self, name):
+        n = self.getNamedItem(name)
+        if n is not None:
+            _clear_id_cache(self._ownerElement)
+            del self._attrs[n.nodeName]
+            del self._attrsNS[(n.namespaceURI, n.localName)]
+            if n.__dict__.has_key('ownerElement'):
+                n.__dict__['ownerElement'] = None
+            return n
+        else:
+            raise xml.dom.NotFoundErr()
+
+    def removeNamedItemNS(self, namespaceURI, localName):
+        n = self.getNamedItemNS(namespaceURI, localName)
+        if n is not None:
+            _clear_id_cache(self._ownerElement)
+            del self._attrsNS[(n.namespaceURI, n.localName)]
+            del self._attrs[n.nodeName]
+            if n.__dict__.has_key('ownerElement'):
+                n.__dict__['ownerElement'] = None
+            return n
+        else:
+            raise xml.dom.NotFoundErr()
+
+    def setNamedItem(self, node):
+        if not isinstance(node, Attr):
+            raise xml.dom.HierarchyRequestErr(
+                "%s cannot be child of %s" % (repr(node), repr(self)))
+        old = self._attrs.get(node.name)
+        if old:
+            old.unlink()
+            old.ownerDocument = self._ownerElement.ownerDocument
+        self._attrs[node.name] = node
+        self._attrsNS[(node.namespaceURI, node.localName)] = node
+        node.ownerElement = self._ownerElement
+        _clear_id_cache(node.ownerElement)
+        return old
+
+    def setNamedItemNS(self, node):
+        return self.setNamedItem(node)
+
+    def __delitem__(self, attname_or_tuple):
+        node = self[attname_or_tuple]
+        _clear_id_cache(node.ownerElement)
+        node.unlink()
+
+    def __getstate__(self):
+        return self._attrs, self._attrsNS, self._ownerElement
+
+    def __setstate__(self, state):
+        self._attrs, self._attrsNS, self._ownerElement = state
+
+defproperty(NamedNodeMap, "length",
+            doc="Number of nodes in the NamedNodeMap.")
+
+AttributeList = NamedNodeMap
+
+
+class TypeInfo(NewStyle):
+    __slots__ = 'namespace', 'name'
+
+    def __init__(self, namespace, name):
+        self.namespace = namespace
+        self.name = name
+
+    def __repr__(self):
+        if self.namespace:
+            return "<TypeInfo %s (from %s)>" % (`self.name`, `self.namespace`)
+        else:
+            return "<TypeInfo %s>" % `self.name`
+
+    def _get_name(self):
+        return self.name
+
+    def _get_namespace(self):
+        return self.namespace
+
+_no_type = TypeInfo(None, None)
+
+class Element(Node):
+    nodeType = Node.ELEMENT_NODE
+    nodeValue = None
+    schemaType = _no_type
+
+    _magic_id_nodes = 0
+
+    _child_node_types = (Node.ELEMENT_NODE,
+                         Node.PROCESSING_INSTRUCTION_NODE,
+                         Node.COMMENT_NODE,
+                         Node.TEXT_NODE,
+                         Node.CDATA_SECTION_NODE,
+                         Node.ENTITY_REFERENCE_NODE)
+
+    def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
+                 localName=None):
+        self.tagName = self.nodeName = tagName
+        self.prefix = prefix
+        self.namespaceURI = namespaceURI
+        self.childNodes = NodeList()
+
+        self._attrs = {}   # attributes are double-indexed:
+        self._attrsNS = {} #    tagName -> Attribute
+                           #    URI,localName -> Attribute
+                           # in the future: consider lazy generation
+                           # of attribute objects this is too tricky
+                           # for now because of headaches with
+                           # namespaces.
+
+    def _get_localName(self):
+        return self.tagName.split(":", 1)[-1]
+
+    def _get_tagName(self):
+        return self.tagName
+
+    def unlink(self):
+        for attr in self._attrs.values():
+            attr.unlink()
+        self._attrs = None
+        self._attrsNS = None
+        Node.unlink(self)
+
+    def getAttribute(self, attname):
+        try:
+            return self._attrs[attname].value
+        except KeyError:
+            return ""
+
+    def getAttributeNS(self, namespaceURI, localName):
+        try:
+            return self._attrsNS[(namespaceURI, localName)].value
+        except KeyError:
+            return ""
+
+    def setAttribute(self, attname, value):
+        attr = self.getAttributeNode(attname)
+        if attr is None:
+            attr = Attr(attname)
+            # for performance
+            d = attr.__dict__
+            d["value"] = d["nodeValue"] = value
+            d["ownerDocument"] = self.ownerDocument
+            self.setAttributeNode(attr)
+        elif value != attr.value:
+            d = attr.__dict__
+            d["value"] = d["nodeValue"] = value
+            if attr.isId:
+                _clear_id_cache(self)
+
+    def setAttributeNS(self, namespaceURI, qualifiedName, value):
+        prefix, localname = _nssplit(qualifiedName)
+        attr = self.getAttributeNodeNS(namespaceURI, localname)
+        if attr is None:
+            # for performance
+            attr = Attr(qualifiedName, namespaceURI, localname, prefix)
+            d = attr.__dict__
+            d["prefix"] = prefix
+            d["nodeName"] = qualifiedName
+            d["value"] = d["nodeValue"] = value
+            d["ownerDocument"] = self.ownerDocument
+            self.setAttributeNode(attr)
+        else:
+            d = attr.__dict__
+            if value != attr.value:
+                d["value"] = d["nodeValue"] = value
+                if attr.isId:
+                    _clear_id_cache(self)
+            if attr.prefix != prefix:
+                d["prefix"] = prefix
+                d["nodeName"] = qualifiedName
+
+    def getAttributeNode(self, attrname):
+        return self._attrs.get(attrname)
+
+    def getAttributeNodeNS(self, namespaceURI, localName):
+        return self._attrsNS.get((namespaceURI, localName))
+
+    def setAttributeNode(self, attr):
+        if attr.ownerElement not in (None, self):
+            raise xml.dom.InuseAttributeErr("attribute node already owned")
+        old1 = self._attrs.get(attr.name, None)
+        if old1 is not None:
+            self.removeAttributeNode(old1)
+        old2 = self._attrsNS.get((attr.namespaceURI, attr.localName), None)
+        if old2 is not None and old2 is not old1:
+            self.removeAttributeNode(old2)
+        _set_attribute_node(self, attr)
+
+        if old1 is not attr:
+            # It might have already been part of this node, in which case
+            # it doesn't represent a change, and should not be returned.
+            return old1
+        if old2 is not attr:
+            return old2
+
+    setAttributeNodeNS = setAttributeNode
+
+    def removeAttribute(self, name):
+        try:
+            attr = self._attrs[name]
+        except KeyError:
+            raise xml.dom.NotFoundErr()
+        self.removeAttributeNode(attr)
+
+    def removeAttributeNS(self, namespaceURI, localName):
+        try:
+            attr = self._attrsNS[(namespaceURI, localName)]
+        except KeyError:
+            raise xml.dom.NotFoundErr()
+        self.removeAttributeNode(attr)
+
+    def removeAttributeNode(self, node):
+        if node is None:
+            raise xml.dom.NotFoundErr()
+        try:
+            self._attrs[node.name]
+        except KeyError:
+            raise xml.dom.NotFoundErr()
+        _clear_id_cache(self)
+        node.unlink()
+        # Restore this since the node is still useful and otherwise
+        # unlinked
+        node.ownerDocument = self.ownerDocument
+        return node
+
+    removeAttributeNodeNS = removeAttributeNode
+
+    def hasAttribute(self, name):
+        return self._attrs.has_key(name)
+
+    def hasAttributeNS(self, namespaceURI, localName):
+        return self._attrsNS.has_key((namespaceURI, localName))
+
+    def getElementsByTagName(self, name):
+        return _get_elements_by_tagName_helper(self, name, NodeList())
+
+    def getElementsByTagNameNS(self, namespaceURI, localName):
+        return _get_elements_by_tagName_ns_helper(
+            self, namespaceURI, localName, NodeList())
+
+    def __repr__(self):
+        return "<DOM Element: %s at %#x>" % (self.tagName, id(self))
+
+    def writexml(self, writer, indent="", addindent="", newl=""):
+        # indent = current indentation
+        # addindent = indentation to add to higher levels
+        # newl = newline string
+        writer.write(indent+"<" + self.tagName)
+
+        attrs = self._get_attributes()
+        a_names = attrs.keys()
+        a_names.sort()
+
+        for a_name in a_names:
+            writer.write(" %s=\"" % a_name)
+            _write_data(writer, attrs[a_name].value)
+            writer.write("\"")
+        if self.childNodes:
+            writer.write(">%s"%(newl))
+            for node in self.childNodes:
+                node.writexml(writer,indent+addindent,addindent,newl)
+            writer.write("%s</%s>%s" % (indent,self.tagName,newl))
+        else:
+            writer.write("/>%s"%(newl))
+
+    def _get_attributes(self):
+        return NamedNodeMap(self._attrs, self._attrsNS, self)
+
+    def hasAttributes(self):
+        if self._attrs:
+            return True
+        else:
+            return False
+
+    # DOM Level 3 attributes, based on the 22 Oct 2002 draft
+
+    def setIdAttribute(self, name):
+        idAttr = self.getAttributeNode(name)
+        self.setIdAttributeNode(idAttr)
+
+    def setIdAttributeNS(self, namespaceURI, localName):
+        idAttr = self.getAttributeNodeNS(namespaceURI, localName)
+        self.setIdAttributeNode(idAttr)
+
+    def setIdAttributeNode(self, idAttr):
+        if idAttr is None or not self.isSameNode(idAttr.ownerElement):
+            raise xml.dom.NotFoundErr()
+        if _get_containing_entref(self) is not None:
+            raise xml.dom.NoModificationAllowedErr()
+        if not idAttr._is_id:
+            idAttr.__dict__['_is_id'] = True
+            self._magic_id_nodes += 1
+            self.ownerDocument._magic_id_count += 1
+            _clear_id_cache(self)
+
+defproperty(Element, "attributes",
+            doc="NamedNodeMap of attributes on the element.")
+defproperty(Element, "localName",
+            doc="Namespace-local name of this element.")
+
+
+def _set_attribute_node(element, attr):
+    _clear_id_cache(element)
+    element._attrs[attr.name] = attr
+    element._attrsNS[(attr.namespaceURI, attr.localName)] = attr
+
+    # This creates a circular reference, but Element.unlink()
+    # breaks the cycle since the references to the attribute
+    # dictionaries are tossed.
+    attr.__dict__['ownerElement'] = element
+
+
+class Childless:
+    """Mixin that makes childless-ness easy to implement and avoids
+    the complexity of the Node methods that deal with children.
+    """
+
+    attributes = None
+    childNodes = EmptyNodeList()
+    firstChild = None
+    lastChild = None
+
+    def _get_firstChild(self):
+        return None
+
+    def _get_lastChild(self):
+        return None
+
+    def appendChild(self, node):
+        raise xml.dom.HierarchyRequestErr(
+            self.nodeName + " nodes cannot have children")
+
+    def hasChildNodes(self):
+        return False
+
+    def insertBefore(self, newChild, refChild):
+        raise xml.dom.HierarchyRequestErr(
+            self.nodeName + " nodes do not have children")
+
+    def removeChild(self, oldChild):
+        raise xml.dom.NotFoundErr(
+            self.nodeName + " nodes do not have children")
+
+    def replaceChild(self, newChild, oldChild):
+        raise xml.dom.HierarchyRequestErr(
+            self.nodeName + " nodes do not have children")
+
+
+class ProcessingInstruction(Childless, Node):
+    nodeType = Node.PROCESSING_INSTRUCTION_NODE
+
+    def __init__(self, target, data):
+        self.target = self.nodeName = target
+        self.data = self.nodeValue = data
+
+    def _get_data(self):
+        return self.data
+    def _set_data(self, value):
+        d = self.__dict__
+        d['data'] = d['nodeValue'] = value
+
+    def _get_target(self):
+        return self.target
+    def _set_target(self, value):
+        d = self.__dict__
+        d['target'] = d['nodeName'] = value
+
+    def __setattr__(self, name, value):
+        if name == "data" or name == "nodeValue":
+            self.__dict__['data'] = self.__dict__['nodeValue'] = value
+        elif name == "target" or name == "nodeName":
+            self.__dict__['target'] = self.__dict__['nodeName'] = value
+        else:
+            self.__dict__[name] = value
+
+    def writexml(self, writer, indent="", addindent="", newl=""):
+        writer.write("%s<?%s %s?>%s" % (indent,self.target, self.data, newl))
+
+
+class CharacterData(Childless, Node):
+    def _get_length(self):
+        return len(self.data)
+    __len__ = _get_length
+
+    def _get_data(self):
+        return self.__dict__['data']
+    def _set_data(self, data):
+        d = self.__dict__
+        d['data'] = d['nodeValue'] = data
+
+    _get_nodeValue = _get_data
+    _set_nodeValue = _set_data
+
+    def __setattr__(self, name, value):
+        if name == "data" or name == "nodeValue":
+            self.__dict__['data'] = self.__dict__['nodeValue'] = value
+        else:
+            self.__dict__[name] = value
+
+    def __repr__(self):
+        data = self.data
+        if len(data) > 10:
+            dotdotdot = "..."
+        else:
+            dotdotdot = ""
+        return "<DOM %s node \"%s%s\">" % (
+            self.__class__.__name__, data[0:10], dotdotdot)
+
+    def substringData(self, offset, count):
+        if offset < 0:
+            raise xml.dom.IndexSizeErr("offset cannot be negative")
+        if offset > len(self.data):
+            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
+        if count < 0:
+            raise xml.dom.IndexSizeErr("count cannot be negative")
+        return self.data[offset:offset+count]
+
+    def appendData(self, arg):
+        self.data = self.data + arg
+
+    def insertData(self, offset, arg):
+        if offset < 0:
+            raise xml.dom.IndexSizeErr("offset cannot be negative")
+        if offset > len(self.data):
+            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
+        if arg:
+            self.data = "%s%s%s" % (
+                self.data[:offset], arg, self.data[offset:])
+
+    def deleteData(self, offset, count):
+        if offset < 0:
+            raise xml.dom.IndexSizeErr("offset cannot be negative")
+        if offset > len(self.data):
+            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
+        if count < 0:
+            raise xml.dom.IndexSizeErr("count cannot be negative")
+        if count:
+            self.data = self.data[:offset] + self.data[offset+count:]
+
+    def replaceData(self, offset, count, arg):
+        if offset < 0:
+            raise xml.dom.IndexSizeErr("offset cannot be negative")
+        if offset > len(self.data):
+            raise xml.dom.IndexSizeErr("offset cannot be beyond end of data")
+        if count < 0:
+            raise xml.dom.IndexSizeErr("count cannot be negative")
+        if count:
+            self.data = "%s%s%s" % (
+                self.data[:offset], arg, self.data[offset+count:])
+
+defproperty(CharacterData, "length", doc="Length of the string data.")
+
+
+class Text(CharacterData):
+
+    # This class doesn't have an __init__() by design; the intent is
+    # to speed construction of new instances.  Once an instance is
+    # created, the .data and .ownerDocument attributes will need to be
+    # initialized.  Subclasses may add an __init__() and initialize
+    # those members there or require them to be initialized later.
+
+    nodeType = Node.TEXT_NODE
+    nodeName = "#text"
+    attributes = None
+
+    def splitText(self, offset):
+        if offset < 0 or offset > len(self.data):
+            raise xml.dom.IndexSizeErr("illegal offset value")
+        newText = self.__class__()
+        newText.data = self.data[offset:]
+        newText.ownerDocument = self.ownerDocument
+        next = self.nextSibling
+        if self.parentNode and self in self.parentNode.childNodes:
+            if next is None:
+                self.parentNode.appendChild(newText)
+            else:
+                self.parentNode.insertBefore(newText, next)
+        self.data = self.data[:offset]
+        return newText
+
+    def writexml(self, writer, indent="", addindent="", newl=""):
+        _write_data(writer, "%s%s%s"%(indent, self.data, newl))
+
+    # DOM Level 3 (WD 9 April 2002)
+
+    def _get_wholeText(self):
+        L = [self.data]
+        n = self.previousSibling
+        while n is not None:
+            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
+                L.insert(0, n.data)
+                n = n.previousSibling
+            else:
+                break
+        n = self.nextSibling
+        while n is not None:
+            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
+                L.append(n.data)
+                n = n.nextSibling
+            else:
+                break
+        return ''.join(L)
+
+    def replaceWholeText(self, content):
+        # XXX This needs to be seriously changed if minidom ever
+        # supports EntityReference nodes.
+        parent = self.parentNode
+        n = self.previousSibling
+        while n is not None:
+            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
+                next = n.previousSibling
+                parent.removeChild(n)
+                n = next
+            else:
+                break
+        n = self.nextSibling
+        if not content:
+            parent.removeChild(self)
+        while n is not None:
+            if n.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
+                next = n.nextSibling
+                parent.removeChild(n)
+                n = next
+            else:
+                break
+        if content:
+            d = self.__dict__
+            d['data'] = content
+            d['nodeValue'] = content
+            return self
+        else:
+            return None
+
+    def _get_isWhitespaceInElementContent(self):
+        if self.data.strip():
+            return False
+        elem = _get_containing_element(self)
+        if elem is None:
+            return False
+        info = self.ownerDocument._get_elem_info(elem)
+        if info is None:
+            return False
+        else:
+            return info.isElementContent()
+
+defproperty(Text, "isWhitespaceInElementContent",
+            doc="True iff this text node contains only whitespace"
+                " and is in element content.")
+defproperty(Text, "wholeText",
+            doc="The text of all logically-adjacent text nodes.")
+
+
+def _get_containing_element(node):
+    c = node.parentNode
+    while c is not None:
+        if c.nodeType == Node.ELEMENT_NODE:
+            return c
+        c = c.parentNode
+    return None
+
+def _get_containing_entref(node):
+    c = node.parentNode
+    while c is not None:
+        if c.nodeType == Node.ENTITY_REFERENCE_NODE:
+            return c
+        c = c.parentNode
+    return None
+
+
+class Comment(Childless, CharacterData):
+    nodeType = Node.COMMENT_NODE
+    nodeName = "#comment"
+
+    def __init__(self, data):
+        self.data = self.nodeValue = data
+
+    def writexml(self, writer, indent="", addindent="", newl=""):
+        writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
+
+
+class CDATASection(Text):
+    nodeType = Node.CDATA_SECTION_NODE
+    nodeName = "#cdata-section"
+
+    def writexml(self, writer, indent="", addindent="", newl=""):
+        if self.data.find("]]>") >= 0:
+            raise ValueError("']]>' not allowed in a CDATA section")
+        writer.write("<![CDATA[%s]]>" % self.data)
+
+
+class ReadOnlySequentialNamedNodeMap(NewStyle, GetattrMagic):
+    __slots__ = '_seq',
+
+    def __init__(self, seq=()):
+        # seq should be a list or tuple
+        self._seq = seq
+
+    def __len__(self):
+        return len(self._seq)
+
+    def _get_length(self):
+        return len(self._seq)
+
+    def getNamedItem(self, name):
+        for n in self._seq:
+            if n.nodeName == name:
+                return n
+
+    def getNamedItemNS(self, namespaceURI, localName):
+        for n in self._seq:
+            if n.namespaceURI == namespaceURI and n.localName == localName:
+                return n
+
+    def __getitem__(self, name_or_tuple):
+        if isinstance(name_or_tuple, _TupleType):
+            node = self.getNamedItemNS(*name_or_tuple)
+        else:
+            node = self.getNamedItem(name_or_tuple)
+        if node is None:
+            raise KeyError, name_or_tuple
+        return node
+
+    def item(self, index):
+        if index < 0:
+            return None
+        try:
+            return self._seq[index]
+        except IndexError:
+            return None
+
+    def removeNamedItem(self, name):
+        raise xml.dom.NoModificationAllowedErr(
+            "NamedNodeMap instance is read-only")
+
+    def removeNamedItemNS(self, namespaceURI, localName):
+        raise xml.dom.NoModificationAllowedErr(
+            "NamedNodeMap instance is read-only")
+
+    def setNamedItem(self, node):
+        raise xml.dom.NoModificationAllowedErr(
+            "NamedNodeMap instance is read-only")
+
+    def setNamedItemNS(self, node):
+        raise xml.dom.NoModificationAllowedErr(
+            "NamedNodeMap instance is read-only")
+
+    def __getstate__(self):
+        return [self._seq]
+
+    def __setstate__(self, state):
+        assert len(state) == 1
+        self._seq = state[0]
+
+defproperty(ReadOnlySequentialNamedNodeMap, "length",
+            doc="Number of entries in the NamedNodeMap.")
+
+
+class Identified:
+    """Mix-in class that supports the publicId and systemId attributes."""
+
+    def _identified_mixin_init(self, publicId, systemId):
+        self.publicId = publicId
+        self.systemId = systemId
+
+    def _get_publicId(self):
+        return self.publicId
+
+    def _get_systemId(self):
+        return self.systemId
+
+class DocumentType(Identified, Childless, Node):
+    nodeType = Node.DOCUMENT_TYPE_NODE
+    nodeValue = None
+    name = None
+    publicId = None
+    systemId = None
+    internalSubset = None
+
+    def __init__(self, qualifiedName):
+        self.entities = ReadOnlySequentialNamedNodeMap()
+        self.notations = ReadOnlySequentialNamedNodeMap()
+        if qualifiedName:
+            prefix, localname = _nssplit(qualifiedName)
+            self.name = localname
+        self.nodeName = self.name
+
+    def _get_internalSubset(self):
+        return self.internalSubset
+
+    def cloneNode(self, deep):
+        if self.ownerDocument is None:
+            # it's ok
+            clone = DocumentType(None)
+            clone.name = self.name
+            clone.nodeName = self.name
+            operation = xml.dom.UserDataHandler.NODE_CLONED
+            if deep:
+                clone.entities._seq = []
+                clone.notations._seq = []
+                for n in self.notations._seq:
+                    notation = Notation(n.nodeName, n.publicId, n.systemId)
+                    clone.notations._seq.append(notation)
+                    n._call_user_data_handler(operation, n, notation)
+                for e in self.entities._seq:
+                    entity = Entity(e.nodeName, e.publicId, e.systemId,
+                                    e.notationName)
+                    entity.actualEncoding = e.actualEncoding
+                    entity.encoding = e.encoding
+                    entity.version = e.version
+                    clone.entities._seq.append(entity)
+                    e._call_user_data_handler(operation, n, entity)
+            self._call_user_data_handler(operation, self, clone)
+            return clone
+        else:
+            return None
+
+    def writexml(self, writer, indent="", addindent="", newl=""):
+        writer.write("<!DOCTYPE ")
+        writer.write(self.name)
+        if self.publicId:
+            writer.write("\n  PUBLIC '%s'\n  '%s'"
+                         % (self.publicId, self.systemId))
+        elif self.systemId:
+            writer.write("\n  SYSTEM '%s'" % self.systemId)
+        if self.internalSubset is not None:
+            writer.write(" [")
+            writer.write(self.internalSubset)
+            writer.write("]")
+        writer.write(">\n")
+
+class Entity(Identified, Node):
+    attributes = None
+    nodeType = Node.ENTITY_NODE
+    nodeValue = None
+
+    actualEncoding = None
+    encoding = None
+    version = None
+
+    def __init__(self, name, publicId, systemId, notation):
+        self.nodeName = name
+        self.notationName = notation
+        self.childNodes = NodeList()
+        self._identified_mixin_init(publicId, systemId)
+
+    def _get_actualEncoding(self):
+        return self.actualEncoding
+
+    def _get_encoding(self):
+        return self.encoding
+
+    def _get_version(self):
+        return self.version
+
+    def appendChild(self, newChild):
+        raise xml.dom.HierarchyRequestErr(
+            "cannot append children to an entity node")
+
+    def insertBefore(self, newChild, refChild):
+        raise xml.dom.HierarchyRequestErr(
+            "cannot insert children below an entity node")
+
+    def removeChild(self, oldChild):
+        raise xml.dom.HierarchyRequestErr(
+            "cannot remove children from an entity node")
+
+    def replaceChild(self, newChild, oldChild):
+        raise xml.dom.HierarchyRequestErr(
+            "cannot replace children of an entity node")
+
+class Notation(Identified, Childless, Node):
+    nodeType = Node.NOTATION_NODE
+    nodeValue = None
+
+    def __init__(self, name, publicId, systemId):
+        self.nodeName = name
+        self._identified_mixin_init(publicId, systemId)
+
+
+class DOMImplementation(DOMImplementationLS):
+    _features = [("core", "1.0"),
+                 ("core", "2.0"),
+                 ("core", "3.0"),
+                 ("core", None),
+                 ("xml", "1.0"),
+                 ("xml", "2.0"),
+                 ("xml", "3.0"),
+                 ("xml", None),
+                 ("ls-load", "3.0"),
+                 ("ls-load", None),
+                 ]
+
+    def hasFeature(self, feature, version):
+        if version == "":
+            version = None
+        return (feature.lower(), version) in self._features
+
+    def createDocument(self, namespaceURI, qualifiedName, doctype):
+        if doctype and doctype.parentNode is not None:
+            raise xml.dom.WrongDocumentErr(
+                "doctype object owned by another DOM tree")
+        doc = self._create_document()
+
+        add_root_element = not (namespaceURI is None
+                                and qualifiedName is None
+                                and doctype is None)
+
+        if not qualifiedName and add_root_element:
+            # The spec is unclear what to raise here; SyntaxErr
+            # would be the other obvious candidate. Since Xerces raises
+            # InvalidCharacterErr, and since SyntaxErr is not listed
+            # for createDocument, that seems to be the better choice.
+            # XXX: need to check for illegal characters here and in
+            # createElement.
+
+            # DOM Level III clears this up when talking about the return value
+            # of this function.  If namespaceURI, qName and DocType are
+            # Null the document is returned without a document element
+            # Otherwise if doctype or namespaceURI are not None
+            # Then we go back to the above problem
+            raise xml.dom.InvalidCharacterErr("Element with no name")
+
+        if add_root_element:
+            prefix, localname = _nssplit(qualifiedName)
+            if prefix == "xml" \
+               and namespaceURI != "http://www.w3.org/XML/1998/namespace":
+                raise xml.dom.NamespaceErr("illegal use of 'xml' prefix")
+            if prefix and not namespaceURI:
+                raise xml.dom.NamespaceErr(
+                    "illegal use of prefix without namespaces")
+            element = doc.createElementNS(namespaceURI, qualifiedName)
+            if doctype:
+                doc.appendChild(doctype)
+            doc.appendChild(element)
+
+        if doctype:
+            doctype.parentNode = doctype.ownerDocument = doc
+
+        doc.doctype = doctype
+        doc.implementation = self
+        return doc
+
+    def createDocumentType(self, qualifiedName, publicId, systemId):
+        doctype = DocumentType(qualifiedName)
+        doctype.publicId = publicId
+        doctype.systemId = systemId
+        return doctype
+
+    # DOM Level 3 (WD 9 April 2002)
+
+    def getInterface(self, feature):
+        if self.hasFeature(feature, None):
+            return self
+        else:
+            return None
+
+    # internal
+    def _create_document(self):
+        return Document()
+
+class ElementInfo(NewStyle):
+    """Object that represents content-model information for an element.
+
+    This implementation is not expected to be used in practice; DOM
+    builders should provide implementations which do the right thing
+    using information available to it.
+
+    """
+
+    __slots__ = 'tagName',
+
+    def __init__(self, name):
+        self.tagName = name
+
+    def getAttributeType(self, aname):
+        return _no_type
+
+    def getAttributeTypeNS(self, namespaceURI, localName):
+        return _no_type
+
+    def isElementContent(self):
+        return False
+
+    def isEmpty(self):
+        """Returns true iff this element is declared to have an EMPTY
+        content model."""
+        return False
+
+    def isId(self, aname):
+        """Returns true iff the named attribte is a DTD-style ID."""
+        return False
+
+    def isIdNS(self, namespaceURI, localName):
+        """Returns true iff the identified attribute is a DTD-style ID."""
+        return False
+
+    def __getstate__(self):
+        return self.tagName
+
+    def __setstate__(self, state):
+        self.tagName = state
+
+def _clear_id_cache(node):
+    if node.nodeType == Node.DOCUMENT_NODE:
+        node._id_cache.clear()
+        node._id_search_stack = None
+    elif _in_document(node):
+        node.ownerDocument._id_cache.clear()
+        node.ownerDocument._id_search_stack= None
+
+class Document(Node, DocumentLS):
+    _child_node_types = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
+                         Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE)
+
+    nodeType = Node.DOCUMENT_NODE
+    nodeName = "#document"
+    nodeValue = None
+    attributes = None
+    doctype = None
+    parentNode = None
+    previousSibling = nextSibling = None
+
+    implementation = DOMImplementation()
+
+    # Document attributes from Level 3 (WD 9 April 2002)
+
+    actualEncoding = None
+    encoding = None
+    standalone = None
+    version = None
+    strictErrorChecking = False
+    errorHandler = None
+    documentURI = None
+
+    _magic_id_count = 0
+
+    def __init__(self):
+        self.childNodes = NodeList()
+        # mapping of (namespaceURI, localName) -> ElementInfo
+        #        and tagName -> ElementInfo
+        self._elem_info = {}
+        self._id_cache = {}
+        self._id_search_stack = None
+
+    def _get_elem_info(self, element):
+        if element.namespaceURI:
+            key = element.namespaceURI, element.localName
+        else:
+            key = element.tagName
+        return self._elem_info.get(key)
+
+    def _get_actualEncoding(self):
+        return self.actualEncoding
+
+    def _get_doctype(self):
+        return self.doctype
+
+    def _get_documentURI(self):
+        return self.documentURI
+
+    def _get_encoding(self):
+        return self.encoding
+
+    def _get_errorHandler(self):
+        return self.errorHandler
+
+    def _get_standalone(self):
+        return self.standalone
+
+    def _get_strictErrorChecking(self):
+        return self.strictErrorChecking
+
+    def _get_version(self):
+        return self.version
+
+    def appendChild(self, node):
+        if node.nodeType not in self._child_node_types:
+            raise xml.dom.HierarchyRequestErr(
+                "%s cannot be child of %s" % (repr(node), repr(self)))
+        if node.parentNode is not None:
+            # This needs to be done before the next test since this
+            # may *be* the document element, in which case it should
+            # end up re-ordered to the end.
+            node.parentNode.removeChild(node)
+
+        if node.nodeType == Node.ELEMENT_NODE \
+           and self._get_documentElement():
+            raise xml.dom.HierarchyRequestErr(
+                "two document elements disallowed")
+        return Node.appendChild(self, node)
+
+    def removeChild(self, oldChild):
+        try:
+            self.childNodes.remove(oldChild)
+        except ValueError:
+            raise xml.dom.NotFoundErr()
+        oldChild.nextSibling = oldChild.previousSibling = None
+        oldChild.parentNode = None
+        if self.documentElement is oldChild:
+            self.documentElement = None
+
+        return oldChild
+
+    def _get_documentElement(self):
+        for node in self.childNodes:
+            if node.nodeType == Node.ELEMENT_NODE:
+                return node
+
+    def unlink(self):
+        if self.doctype is not None:
+            self.doctype.unlink()
+            self.doctype = None
+        Node.unlink(self)
+
+    def cloneNode(self, deep):
+        if not deep:
+            return None
+        clone = self.implementation.createDocument(None, None, None)
+        clone.encoding = self.encoding
+        clone.standalone = self.standalone
+        clone.version = self.version
+        for n in self.childNodes:
+            childclone = _clone_node(n, deep, clone)
+            assert childclone.ownerDocument.isSameNode(clone)
+            clone.childNodes.append(childclone)
+            if childclone.nodeType == Node.DOCUMENT_NODE:
+                assert clone.documentElement is None
+            elif childclone.nodeType == Node.DOCUMENT_TYPE_NODE:
+                assert clone.doctype is None
+                clone.doctype = childclone
+            childclone.parentNode = clone
+        self._call_user_data_handler(xml.dom.UserDataHandler.NODE_CLONED,
+                                     self, clone)
+        return clone
+
+    def createDocumentFragment(self):
+        d = DocumentFragment()
+        d.ownerDocument = self
+        return d
+
+    def createElement(self, tagName):
+        e = Element(tagName)
+        e.ownerDocument = self
+        return e
+
+    def createTextNode(self, data):
+        if not isinstance(data, StringTypes):
+            raise TypeError, "node contents must be a string"
+        t = Text()
+        t.data = data
+        t.ownerDocument = self
+        return t
+
+    def createCDATASection(self, data):
+        if not isinstance(data, StringTypes):
+            raise TypeError, "node contents must be a string"
+        c = CDATASection()
+        c.data = data
+        c.ownerDocument = self
+        return c
+
+    def createComment(self, data):
+        c = Comment(data)
+        c.ownerDocument = self
+        return c
+
+    def createProcessingInstruction(self, target, data):
+        p = ProcessingInstruction(target, data)
+        p.ownerDocument = self
+        return p
+
+    def createAttribute(self, qName):
+        a = Attr(qName)
+        a.ownerDocument = self
+        a.value = ""
+        return a
+
+    def createElementNS(self, namespaceURI, qualifiedName):
+        prefix, localName = _nssplit(qualifiedName)
+        e = Element(qualifiedName, namespaceURI, prefix)
+        e.ownerDocument = self
+        return e
+
+    def createAttributeNS(self, namespaceURI, qualifiedName):
+        prefix, localName = _nssplit(qualifiedName)
+        a = Attr(qualifiedName, namespaceURI, localName, prefix)
+        a.ownerDocument = self
+        a.value = ""
+        return a
+
+    # A couple of implementation-specific helpers to create node types
+    # not supported by the W3C DOM specs:
+
+    def _create_entity(self, name, publicId, systemId, notationName):
+        e = Entity(name, publicId, systemId, notationName)
+        e.ownerDocument = self
+        return e
+
+    def _create_notation(self, name, publicId, systemId):
+        n = Notation(name, publicId, systemId)
+        n.ownerDocument = self
+        return n
+
+    def getElementById(self, id):
+        if self._id_cache.has_key(id):
+            return self._id_cache[id]
+        if not (self._elem_info or self._magic_id_count):
+            return None
+
+        stack = self._id_search_stack
+        if stack is None:
+            # we never searched before, or the cache has been cleared
+            stack = [self.documentElement]
+            self._id_search_stack = stack
+        elif not stack:
+            # Previous search was completed and cache is still valid;
+            # no matching node.
+            return None
+
+        result = None
+        while stack:
+            node = stack.pop()
+            # add child elements to stack for continued searching
+            stack.extend([child for child in node.childNodes
+                          if child.nodeType in _nodeTypes_with_children])
+            # check this node
+            info = self._get_elem_info(node)
+            if info:
+                # We have to process all ID attributes before
+                # returning in order to get all the attributes set to
+                # be IDs using Element.setIdAttribute*().
+                for attr in node.attributes.values():
+                    if attr.namespaceURI:
+                        if info.isIdNS(attr.namespaceURI, attr.localName):
+                            self._id_cache[attr.value] = node
+                            if attr.value == id:
+                                result = node
+                            elif not node._magic_id_nodes:
+                                break
+                    elif info.isId(attr.name):
+                        self._id_cache[attr.value] = node
+                        if attr.value == id:
+                            result = node
+                        elif not node._magic_id_nodes:
+                            break
+                    elif attr._is_id:
+                        self._id_cache[attr.value] = node
+                        if attr.value == id:
+                            result = node
+                        elif node._magic_id_nodes == 1:
+                            break
+            elif node._magic_id_nodes:
+                for attr in node.attributes.values():
+                    if attr._is_id:
+                        self._id_cache[attr.value] = node
+                        if attr.value == id:
+                            result = node
+            if result is not None:
+                break
+        return result
+
+    def getElementsByTagName(self, name):
+        return _get_elements_by_tagName_helper(self, name, NodeList())
+
+    def getElementsByTagNameNS(self, namespaceURI, localName):
+        return _get_elements_by_tagName_ns_helper(
+            self, namespaceURI, localName, NodeList())
+
+    def isSupported(self, feature, version):
+        return self.implementation.hasFeature(feature, version)
+
+    def importNode(self, node, deep):
+        if node.nodeType == Node.DOCUMENT_NODE:
+            raise xml.dom.NotSupportedErr("cannot import document nodes")
+        elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
+            raise xml.dom.NotSupportedErr("cannot import document type nodes")
+        return _clone_node(node, deep, self)
+
+    def writexml(self, writer, indent="", addindent="", newl="",
+                 encoding = None):
+        if encoding is None:
+            writer.write('<?xml version="1.0" ?>\n')
+        else:
+            writer.write('<?xml version="1.0" encoding="%s"?>\n' % encoding)
+        for node in self.childNodes:
+            node.writexml(writer, indent, addindent, newl)
+
+    # DOM Level 3 (WD 9 April 2002)
+
+    def renameNode(self, n, namespaceURI, name):
+        if n.ownerDocument is not self:
+            raise xml.dom.WrongDocumentErr(
+                "cannot rename nodes from other documents;\n"
+                "expected %s,\nfound %s" % (self, n.ownerDocument))
+        if n.nodeType not in (Node.ELEMENT_NODE, Node.ATTRIBUTE_NODE):
+            raise xml.dom.NotSupportedErr(
+                "renameNode() only applies to element and attribute nodes")
+        if namespaceURI != EMPTY_NAMESPACE:
+            if ':' in name:
+                prefix, localName = name.split(':', 1)
+                if (  prefix == "xmlns"
+                      and namespaceURI != xml.dom.XMLNS_NAMESPACE):
+                    raise xml.dom.NamespaceErr(
+                        "illegal use of 'xmlns' prefix")
+            else:
+                if (  name == "xmlns"
+                      and namespaceURI != xml.dom.XMLNS_NAMESPACE
+                      and n.nodeType == Node.ATTRIBUTE_NODE):
+                    raise xml.dom.NamespaceErr(
+                        "illegal use of the 'xmlns' attribute")
+                prefix = None
+                localName = name
+        else:
+            prefix = None
+            localName = None
+        if n.nodeType == Node.ATTRIBUTE_NODE:
+            element = n.ownerElement
+            if element is not None:
+                is_id = n._is_id
+                element.removeAttributeNode(n)
+        else:
+            element = None
+        # avoid __setattr__
+        d = n.__dict__
+        d['prefix'] = prefix
+        d['localName'] = localName
+        d['namespaceURI'] = namespaceURI
+        d['nodeName'] = name
+        if n.nodeType == Node.ELEMENT_NODE:
+            d['tagName'] = name
+        else:
+            # attribute node
+            d['name'] = name
+            if element is not None:
+                element.setAttributeNode(n)
+                if is_id:
+                    element.setIdAttributeNode(n)
+        # It's not clear from a semantic perspective whether we should
+        # call the user data handlers for the NODE_RENAMED event since
+        # we're re-using the existing node.  The draft spec has been
+        # interpreted as meaning "no, don't call the handler unless a
+        # new node is created."
+        return n
+
+defproperty(Document, "documentElement",
+            doc="Top-level element of this document.")
+
+
+def _clone_node(node, deep, newOwnerDocument):
+    """
+    Clone a node and give it the new owner document.
+    Called by Node.cloneNode and Document.importNode
+    """
+    if node.ownerDocument.isSameNode(newOwnerDocument):
+        operation = xml.dom.UserDataHandler.NODE_CLONED
+    else:
+        operation = xml.dom.UserDataHandler.NODE_IMPORTED
+    if node.nodeType == Node.ELEMENT_NODE:
+        clone = newOwnerDocument.createElementNS(node.namespaceURI,
+                                                 node.nodeName)
+        for attr in node.attributes.values():
+            clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
+            a = clone.getAttributeNodeNS(attr.namespaceURI, attr.localName)
+            a.specified = attr.specified
+
+        if deep:
+            for child in node.childNodes:
+                c = _clone_node(child, deep, newOwnerDocument)
+                clone.appendChild(c)
+
+    elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
+        clone = newOwnerDocument.createDocumentFragment()
+        if deep:
+            for child in node.childNodes:
+                c = _clone_node(child, deep, newOwnerDocument)
+                clone.appendChild(c)
+
+    elif node.nodeType == Node.TEXT_NODE:
+        clone = newOwnerDocument.createTextNode(node.data)
+    elif node.nodeType == Node.CDATA_SECTION_NODE:
+        clone = newOwnerDocument.createCDATASection(node.data)
+    elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
+        clone = newOwnerDocument.createProcessingInstruction(node.target,
+                                                             node.data)
+    elif node.nodeType == Node.COMMENT_NODE:
+        clone = newOwnerDocument.createComment(node.data)
+    elif node.nodeType == Node.ATTRIBUTE_NODE:
+        clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
+                                                   node.nodeName)
+        clone.specified = True
+        clone.value = node.value
+    elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
+        assert node.ownerDocument is not newOwnerDocument
+        operation = xml.dom.UserDataHandler.NODE_IMPORTED
+        clone = newOwnerDocument.implementation.createDocumentType(
+            node.name, node.publicId, node.systemId)
+        clone.ownerDocument = newOwnerDocument
+        if deep:
+            clone.entities._seq = []
+            clone.notations._seq = []
+            for n in node.notations._seq:
+                notation = Notation(n.nodeName, n.publicId, n.systemId)
+                notation.ownerDocument = newOwnerDocument
+                clone.notations._seq.append(notation)
+                if hasattr(n, '_call_user_data_handler'):
+                    n._call_user_data_handler(operation, n, notation)
+            for e in node.entities._seq:
+                entity = Entity(e.nodeName, e.publicId, e.systemId,
+                                e.notationName)
+                entity.actualEncoding = e.actualEncoding
+                entity.encoding = e.encoding
+                entity.version = e.version
+                entity.ownerDocument = newOwnerDocument
+                clone.entities._seq.append(entity)
+                if hasattr(e, '_call_user_data_handler'):
+                    e._call_user_data_handler(operation, n, entity)
+    else:
+        # Note the cloning of Document and DocumentType nodes is
+        # implemenetation specific.  minidom handles those cases
+        # directly in the cloneNode() methods.
+        raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
+
+    # Check for _call_user_data_handler() since this could conceivably
+    # used with other DOM implementations (one of the FourThought
+    # DOMs, perhaps?).
+    if hasattr(node, '_call_user_data_handler'):
+        node._call_user_data_handler(operation, node, clone)
+    return clone
+
+
+def _nssplit(qualifiedName):
+    fields = qualifiedName.split(':', 1)
+    if len(fields) == 2:
+        return fields
+    else:
+        return (None, fields[0])
+
+
+def _get_StringIO():
+    # we can't use cStringIO since it doesn't support Unicode strings
+    from StringIO import StringIO
+    return StringIO()
+
+def _do_pulldom_parse(func, args, kwargs):
+    events = apply(func, args, kwargs)
+    toktype, rootNode = events.getEvent()
+    events.expandNode(rootNode)
+    events.clear()
+    rootNode.normalize()
+    return rootNode
+
+def parse(file, parser=None, bufsize=None):
+    """Parse a file into a DOM by filename or file object."""
+    import sys
+    if parser is None and bufsize is None and sys.platform[:4] != "java":
+        try:
+            from xml.dom import expatbuilder
+            return expatbuilder.parse(file)
+        except ImportError:
+            pass
+    from xml.dom import pulldom
+    return _do_pulldom_parse(pulldom.parse, (file,),
+            {'parser': parser, 'bufsize': bufsize})
+
+def parseString(string, parser=None):
+    """Parse a file into a DOM from a string."""
+    import sys
+    if parser is None and sys.platform[:4] != "java":
+        from xml.dom import expatbuilder
+        return expatbuilder.parseString(string)
+    from xml.dom import pulldom
+    return _do_pulldom_parse(pulldom.parseString, (string,),
+                                 {'parser': parser})
+
+def getDOMImplementation(features=None):
+    if features:
+        if isinstance(features, StringTypes):
+            features = domreg._parse_feature_string(features)
+        for f, v in features:
+            if not Document.implementation.hasFeature(f, v):
+                return None
+    return Document.implementation
diff --git a/src/main/resources/PythonLibs/xml/dom/pulldom.py b/src/main/resources/PythonLibs/xml/dom/pulldom.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c99fb233e73ed63595b7eb6239ba45da1bd5c0f
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/dom/pulldom.py
@@ -0,0 +1,352 @@
+import xml.sax
+import xml.sax.handler
+import types
+
+try:
+    _StringTypes = [types.StringType, types.UnicodeType]
+except AttributeError:
+    _StringTypes = [types.StringType]
+
+START_ELEMENT = "START_ELEMENT"
+END_ELEMENT = "END_ELEMENT"
+COMMENT = "COMMENT"
+START_DOCUMENT = "START_DOCUMENT"
+END_DOCUMENT = "END_DOCUMENT"
+PROCESSING_INSTRUCTION = "PROCESSING_INSTRUCTION"
+IGNORABLE_WHITESPACE = "IGNORABLE_WHITESPACE"
+CHARACTERS = "CHARACTERS"
+
+class PullDOM(xml.sax.ContentHandler):
+    _locator = None
+    document = None
+
+    def __init__(self, documentFactory=None):
+        from xml.dom import XML_NAMESPACE
+        self.documentFactory = documentFactory
+        self.firstEvent = [None, None]
+        self.lastEvent = self.firstEvent
+        self.elementStack = []
+        self.push = self.elementStack.append
+        try:
+            self.pop = self.elementStack.pop
+        except AttributeError:
+            # use class' pop instead
+            pass
+        self._ns_contexts = [{XML_NAMESPACE:'xml'}] # contains uri -> prefix dicts
+        self._current_context = self._ns_contexts[-1]
+        self.pending_events = []
+
+    def pop(self):
+        result = self.elementStack[-1]
+        del self.elementStack[-1]
+        return result
+
+    def setDocumentLocator(self, locator):
+        self._locator = locator
+
+    def startPrefixMapping(self, prefix, uri):
+        if not hasattr(self, '_xmlns_attrs'):
+            self._xmlns_attrs = []
+        self._xmlns_attrs.append((prefix or 'xmlns', uri))
+        self._ns_contexts.append(self._current_context.copy())
+        self._current_context[uri] = prefix or None
+
+    def endPrefixMapping(self, prefix):
+        self._current_context = self._ns_contexts.pop()
+
+    def startElementNS(self, name, tagName , attrs):
+        uri, localname = name
+        if uri:
+            # When using namespaces, the reader may or may not
+            # provide us with the original name. If not, create
+            # *a* valid tagName from the current context.
+            if tagName is None:
+                prefix = self._current_context[uri]
+                if prefix:
+                    tagName = prefix + ":" + localname
+                else:
+                    tagName = localname
+            if self.document:
+                node = self.document.createElementNS(uri, tagName)
+            else:
+                node = self.buildDocument(uri, tagName)
+        else:
+            # When the tagname is not prefixed, it just appears as
+            # localname
+            if self.document:
+                node = self.document.createElement(localname)
+            else:
+                node = self.buildDocument(None, localname)
+
+        # Retrieve xml namespace declaration attributes.
+        xmlns_uri = 'http://www.w3.org/2000/xmlns/'
+        xmlns_attrs = getattr(self, '_xmlns_attrs', None)
+        if xmlns_attrs is not None:
+            for aname, value in xmlns_attrs:
+                if aname == 'xmlns':
+                    qname = aname
+                else:
+                    qname = 'xmlns:' + aname
+                attr = self.document.createAttributeNS(xmlns_uri, qname)
+                attr.value = value
+                node.setAttributeNodeNS(attr)
+            self._xmlns_attrs = []
+        for aname,value in attrs.items():
+            a_uri, a_localname = aname
+            if a_uri:
+                prefix = self._current_context[a_uri]
+                if prefix:
+                    qname = prefix + ":" + a_localname
+                else:
+                    qname = a_localname
+                attr = self.document.createAttributeNS(a_uri, qname)
+                node.setAttributeNodeNS(attr)
+            else:
+                attr = self.document.createAttribute(a_localname)
+                node.setAttributeNode(attr)
+            attr.value = value
+
+        self.lastEvent[1] = [(START_ELEMENT, node), None]
+        self.lastEvent = self.lastEvent[1]
+        self.push(node)
+
+    def endElementNS(self, name, tagName):
+        self.lastEvent[1] = [(END_ELEMENT, self.pop()), None]
+        self.lastEvent = self.lastEvent[1]
+
+    def startElement(self, name, attrs):
+        if self.document:
+            node = self.document.createElement(name)
+        else:
+            node = self.buildDocument(None, name)
+
+        for aname,value in attrs.items():
+            attr = self.document.createAttribute(aname)
+            attr.value = value
+            node.setAttributeNode(attr)
+
+        self.lastEvent[1] = [(START_ELEMENT, node), None]
+        self.lastEvent = self.lastEvent[1]
+        self.push(node)
+
+    def endElement(self, name):
+        self.lastEvent[1] = [(END_ELEMENT, self.pop()), None]
+        self.lastEvent = self.lastEvent[1]
+
+    def comment(self, s):
+        if self.document:
+            node = self.document.createComment(s)
+            self.lastEvent[1] = [(COMMENT, node), None]
+            self.lastEvent = self.lastEvent[1]
+        else:
+            event = [(COMMENT, s), None]
+            self.pending_events.append(event)
+
+    def processingInstruction(self, target, data):
+        if self.document:
+            node = self.document.createProcessingInstruction(target, data)
+            self.lastEvent[1] = [(PROCESSING_INSTRUCTION, node), None]
+            self.lastEvent = self.lastEvent[1]
+        else:
+            event = [(PROCESSING_INSTRUCTION, target, data), None]
+            self.pending_events.append(event)
+
+    def ignorableWhitespace(self, chars):
+        node = self.document.createTextNode(chars)
+        self.lastEvent[1] = [(IGNORABLE_WHITESPACE, node), None]
+        self.lastEvent = self.lastEvent[1]
+
+    def characters(self, chars):
+        node = self.document.createTextNode(chars)
+        self.lastEvent[1] = [(CHARACTERS, node), None]
+        self.lastEvent = self.lastEvent[1]
+
+    def startDocument(self):
+        if self.documentFactory is None:
+            import xml.dom.minidom
+            self.documentFactory = xml.dom.minidom.Document.implementation
+
+    def buildDocument(self, uri, tagname):
+        # Can't do that in startDocument, since we need the tagname
+        # XXX: obtain DocumentType
+        node = self.documentFactory.createDocument(uri, tagname, None)
+        self.document = node
+        self.lastEvent[1] = [(START_DOCUMENT, node), None]
+        self.lastEvent = self.lastEvent[1]
+        self.push(node)
+        # Put everything we have seen so far into the document
+        for e in self.pending_events:
+            if e[0][0] == PROCESSING_INSTRUCTION:
+                _,target,data = e[0]
+                n = self.document.createProcessingInstruction(target, data)
+                e[0] = (PROCESSING_INSTRUCTION, n)
+            elif e[0][0] == COMMENT:
+                n = self.document.createComment(e[0][1])
+                e[0] = (COMMENT, n)
+            else:
+                raise AssertionError("Unknown pending event ",e[0][0])
+            self.lastEvent[1] = e
+            self.lastEvent = e
+        self.pending_events = None
+        return node.firstChild
+
+    def endDocument(self):
+        self.lastEvent[1] = [(END_DOCUMENT, self.document), None]
+        self.pop()
+
+    def clear(self):
+        "clear(): Explicitly release parsing structures"
+        self.document = None
+
+class ErrorHandler:
+    def warning(self, exception):
+        print exception
+    def error(self, exception):
+        raise exception
+    def fatalError(self, exception):
+        raise exception
+
+class DOMEventStream:
+    def __init__(self, stream, parser, bufsize):
+        self.stream = stream
+        self.parser = parser
+        self.bufsize = bufsize
+        if not hasattr(self.parser, 'feed'):
+            self.getEvent = self._slurp
+        self.reset()
+
+    def reset(self):
+        self.pulldom = PullDOM()
+        # This content handler relies on namespace support
+        self.parser.setFeature(xml.sax.handler.feature_namespaces, 1)
+        self.parser.setContentHandler(self.pulldom)
+
+    def __getitem__(self, pos):
+        rc = self.getEvent()
+        if rc:
+            return rc
+        raise IndexError
+
+    def next(self):
+        rc = self.getEvent()
+        if rc:
+            return rc
+        raise StopIteration
+
+    def __iter__(self):
+        return self
+
+    def expandNode(self, node):
+        event = self.getEvent()
+        parents = [node]
+        while event:
+            token, cur_node = event
+            if cur_node is node:
+                return
+            if token != END_ELEMENT:
+                parents[-1].appendChild(cur_node)
+            if token == START_ELEMENT:
+                parents.append(cur_node)
+            elif token == END_ELEMENT:
+                del parents[-1]
+            event = self.getEvent()
+
+    def getEvent(self):
+        # use IncrementalParser interface, so we get the desired
+        # pull effect
+        if not self.pulldom.firstEvent[1]:
+            self.pulldom.lastEvent = self.pulldom.firstEvent
+        while not self.pulldom.firstEvent[1]:
+            buf = self.stream.read(self.bufsize)
+            if not buf:
+                self.parser.close()
+                return None
+            self.parser.feed(buf)
+        rc = self.pulldom.firstEvent[1][0]
+        self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1]
+        return rc
+
+    def _slurp(self):
+        """ Fallback replacement for getEvent() using the
+            standard SAX2 interface, which means we slurp the
+            SAX events into memory (no performance gain, but
+            we are compatible to all SAX parsers).
+        """
+        self.parser.parse(self.stream)
+        self.getEvent = self._emit
+        return self._emit()
+
+    def _emit(self):
+        """ Fallback replacement for getEvent() that emits
+            the events that _slurp() read previously.
+        """
+        if self.pulldom.firstEvent[1] is None:
+            return None
+        rc = self.pulldom.firstEvent[1][0]
+        self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1]
+        return rc
+
+    def clear(self):
+        """clear(): Explicitly release parsing objects"""
+        self.pulldom.clear()
+        del self.pulldom
+        self.parser = None
+        self.stream = None
+
+class SAX2DOM(PullDOM):
+
+    def startElementNS(self, name, tagName , attrs):
+        PullDOM.startElementNS(self, name, tagName, attrs)
+        curNode = self.elementStack[-1]
+        parentNode = self.elementStack[-2]
+        parentNode.appendChild(curNode)
+
+    def startElement(self, name, attrs):
+        PullDOM.startElement(self, name, attrs)
+        curNode = self.elementStack[-1]
+        parentNode = self.elementStack[-2]
+        parentNode.appendChild(curNode)
+
+    def processingInstruction(self, target, data):
+        PullDOM.processingInstruction(self, target, data)
+        node = self.lastEvent[0][1]
+        parentNode = self.elementStack[-1]
+        parentNode.appendChild(node)
+
+    def ignorableWhitespace(self, chars):
+        PullDOM.ignorableWhitespace(self, chars)
+        node = self.lastEvent[0][1]
+        parentNode = self.elementStack[-1]
+        parentNode.appendChild(node)
+
+    def characters(self, chars):
+        PullDOM.characters(self, chars)
+        node = self.lastEvent[0][1]
+        parentNode = self.elementStack[-1]
+        parentNode.appendChild(node)
+
+
+default_bufsize = (2 ** 14) - 20
+
+def parse(stream_or_string, parser=None, bufsize=None):
+    if bufsize is None:
+        bufsize = default_bufsize
+    if type(stream_or_string) in _StringTypes:
+        stream = open(stream_or_string)
+    else:
+        stream = stream_or_string
+    if not parser:
+        parser = xml.sax.make_parser()
+    return DOMEventStream(stream, parser, bufsize)
+
+def parseString(string, parser=None):
+    try:
+        from cStringIO import StringIO
+    except ImportError:
+        from StringIO import StringIO
+
+    bufsize = len(string)
+    buf = StringIO(string)
+    if not parser:
+        parser = xml.sax.make_parser()
+    return DOMEventStream(buf, parser, bufsize)
diff --git a/src/main/resources/PythonLibs/xml/dom/xmlbuilder.py b/src/main/resources/PythonLibs/xml/dom/xmlbuilder.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd43c37ed3f87bf2ed49cbc13bde7a602c3034df
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/dom/xmlbuilder.py
@@ -0,0 +1,388 @@
+"""Implementation of the DOM Level 3 'LS-Load' feature."""
+
+import copy
+import xml.dom
+
+from xml.dom.minicompat import *
+
+from xml.dom.NodeFilter import NodeFilter
+
+
+__all__ = ["DOMBuilder", "DOMEntityResolver", "DOMInputSource"]
+
+
+class Options:
+    """Features object that has variables set for each DOMBuilder feature.
+
+    The DOMBuilder class uses an instance of this class to pass settings to
+    the ExpatBuilder class.
+    """
+
+    # Note that the DOMBuilder class in LoadSave constrains which of these
+    # values can be set using the DOM Level 3 LoadSave feature.
+
+    namespaces = 1
+    namespace_declarations = True
+    validation = False
+    external_parameter_entities = True
+    external_general_entities = True
+    external_dtd_subset = True
+    validate_if_schema = False
+    validate = False
+    datatype_normalization = False
+    create_entity_ref_nodes = True
+    entities = True
+    whitespace_in_element_content = True
+    cdata_sections = True
+    comments = True
+    charset_overrides_xml_encoding = True
+    infoset = False
+    supported_mediatypes_only = False
+
+    errorHandler = None
+    filter = None
+
+
+class DOMBuilder:
+    entityResolver = None
+    errorHandler = None
+    filter = None
+
+    ACTION_REPLACE = 1
+    ACTION_APPEND_AS_CHILDREN = 2
+    ACTION_INSERT_AFTER = 3
+    ACTION_INSERT_BEFORE = 4
+
+    _legal_actions = (ACTION_REPLACE, ACTION_APPEND_AS_CHILDREN,
+                      ACTION_INSERT_AFTER, ACTION_INSERT_BEFORE)
+
+    def __init__(self):
+        self._options = Options()
+
+    def _get_entityResolver(self):
+        return self.entityResolver
+    def _set_entityResolver(self, entityResolver):
+        self.entityResolver = entityResolver
+
+    def _get_errorHandler(self):
+        return self.errorHandler
+    def _set_errorHandler(self, errorHandler):
+        self.errorHandler = errorHandler
+
+    def _get_filter(self):
+        return self.filter
+    def _set_filter(self, filter):
+        self.filter = filter
+
+    def setFeature(self, name, state):
+        if self.supportsFeature(name):
+            state = state and 1 or 0
+            try:
+                settings = self._settings[(_name_xform(name), state)]
+            except KeyError:
+                raise xml.dom.NotSupportedErr(
+                    "unsupported feature: " + `name`)
+            else:
+                for name, value in settings:
+                    setattr(self._options, name, value)
+        else:
+            raise xml.dom.NotFoundErr("unknown feature: " + repr(name))
+
+    def supportsFeature(self, name):
+        return hasattr(self._options, _name_xform(name))
+
+    def canSetFeature(self, name, state):
+        key = (_name_xform(name), state and 1 or 0)
+        return self._settings.has_key(key)
+
+    # This dictionary maps from (feature,value) to a list of
+    # (option,value) pairs that should be set on the Options object.
+    # If a (feature,value) setting is not in this dictionary, it is
+    # not supported by the DOMBuilder.
+    #
+    _settings = {
+        ("namespace_declarations", 0): [
+            ("namespace_declarations", 0)],
+        ("namespace_declarations", 1): [
+            ("namespace_declarations", 1)],
+        ("validation", 0): [
+            ("validation", 0)],
+        ("external_general_entities", 0): [
+            ("external_general_entities", 0)],
+        ("external_general_entities", 1): [
+            ("external_general_entities", 1)],
+        ("external_parameter_entities", 0): [
+            ("external_parameter_entities", 0)],
+        ("external_parameter_entities", 1): [
+            ("external_parameter_entities", 1)],
+        ("validate_if_schema", 0): [
+            ("validate_if_schema", 0)],
+        ("create_entity_ref_nodes", 0): [
+            ("create_entity_ref_nodes", 0)],
+        ("create_entity_ref_nodes", 1): [
+            ("create_entity_ref_nodes", 1)],
+        ("entities", 0): [
+            ("create_entity_ref_nodes", 0),
+            ("entities", 0)],
+        ("entities", 1): [
+            ("entities", 1)],
+        ("whitespace_in_element_content", 0): [
+            ("whitespace_in_element_content", 0)],
+        ("whitespace_in_element_content", 1): [
+            ("whitespace_in_element_content", 1)],
+        ("cdata_sections", 0): [
+            ("cdata_sections", 0)],
+        ("cdata_sections", 1): [
+            ("cdata_sections", 1)],
+        ("comments", 0): [
+            ("comments", 0)],
+        ("comments", 1): [
+            ("comments", 1)],
+        ("charset_overrides_xml_encoding", 0): [
+            ("charset_overrides_xml_encoding", 0)],
+        ("charset_overrides_xml_encoding", 1): [
+            ("charset_overrides_xml_encoding", 1)],
+        ("infoset", 0): [],
+        ("infoset", 1): [
+            ("namespace_declarations", 0),
+            ("validate_if_schema", 0),
+            ("create_entity_ref_nodes", 0),
+            ("entities", 0),
+            ("cdata_sections", 0),
+            ("datatype_normalization", 1),
+            ("whitespace_in_element_content", 1),
+            ("comments", 1),
+            ("charset_overrides_xml_encoding", 1)],
+        ("supported_mediatypes_only", 0): [
+            ("supported_mediatypes_only", 0)],
+        ("namespaces", 0): [
+            ("namespaces", 0)],
+        ("namespaces", 1): [
+            ("namespaces", 1)],
+    }
+
+    def getFeature(self, name):
+        xname = _name_xform(name)
+        try:
+            return getattr(self._options, xname)
+        except AttributeError:
+            if name == "infoset":
+                options = self._options
+                return (options.datatype_normalization
+                        and options.whitespace_in_element_content
+                        and options.comments
+                        and options.charset_overrides_xml_encoding
+                        and not (options.namespace_declarations
+                                 or options.validate_if_schema
+                                 or options.create_entity_ref_nodes
+                                 or options.entities
+                                 or options.cdata_sections))
+            raise xml.dom.NotFoundErr("feature %s not known" % repr(name))
+
+    def parseURI(self, uri):
+        if self.entityResolver:
+            input = self.entityResolver.resolveEntity(None, uri)
+        else:
+            input = DOMEntityResolver().resolveEntity(None, uri)
+        return self.parse(input)
+
+    def parse(self, input):
+        options = copy.copy(self._options)
+        options.filter = self.filter
+        options.errorHandler = self.errorHandler
+        fp = input.byteStream
+        if fp is None and options.systemId:
+            import urllib2
+            fp = urllib2.urlopen(input.systemId)
+        return self._parse_bytestream(fp, options)
+
+    def parseWithContext(self, input, cnode, action):
+        if action not in self._legal_actions:
+            raise ValueError("not a legal action")
+        raise NotImplementedError("Haven't written this yet...")
+
+    def _parse_bytestream(self, stream, options):
+        import xml.dom.expatbuilder
+        builder = xml.dom.expatbuilder.makeBuilder(options)
+        return builder.parseFile(stream)
+
+
+def _name_xform(name):
+    return name.lower().replace('-', '_')
+
+
+class DOMEntityResolver(NewStyle):
+    __slots__ = '_opener',
+
+    def resolveEntity(self, publicId, systemId):
+        assert systemId is not None
+        source = DOMInputSource()
+        source.publicId = publicId
+        source.systemId = systemId
+        source.byteStream = self._get_opener().open(systemId)
+
+        # determine the encoding if the transport provided it
+        source.encoding = self._guess_media_encoding(source)
+
+        # determine the base URI is we can
+        import posixpath, urlparse
+        parts = urlparse.urlparse(systemId)
+        scheme, netloc, path, params, query, fragment = parts
+        # XXX should we check the scheme here as well?
+        if path and not path.endswith("/"):
+            path = posixpath.dirname(path) + "/"
+            parts = scheme, netloc, path, params, query, fragment
+            source.baseURI = urlparse.urlunparse(parts)
+
+        return source
+
+    def _get_opener(self):
+        try:
+            return self._opener
+        except AttributeError:
+            self._opener = self._create_opener()
+            return self._opener
+
+    def _create_opener(self):
+        import urllib2
+        return urllib2.build_opener()
+
+    def _guess_media_encoding(self, source):
+        info = source.byteStream.info()
+        if info.has_key("Content-Type"):
+            for param in info.getplist():
+                if param.startswith("charset="):
+                    return param.split("=", 1)[1].lower()
+
+
+class DOMInputSource(NewStyle):
+    __slots__ = ('byteStream', 'characterStream', 'stringData',
+                 'encoding', 'publicId', 'systemId', 'baseURI')
+
+    def __init__(self):
+        self.byteStream = None
+        self.characterStream = None
+        self.stringData = None
+        self.encoding = None
+        self.publicId = None
+        self.systemId = None
+        self.baseURI = None
+
+    def _get_byteStream(self):
+        return self.byteStream
+    def _set_byteStream(self, byteStream):
+        self.byteStream = byteStream
+
+    def _get_characterStream(self):
+        return self.characterStream
+    def _set_characterStream(self, characterStream):
+        self.characterStream = characterStream
+
+    def _get_stringData(self):
+        return self.stringData
+    def _set_stringData(self, data):
+        self.stringData = data
+
+    def _get_encoding(self):
+        return self.encoding
+    def _set_encoding(self, encoding):
+        self.encoding = encoding
+
+    def _get_publicId(self):
+        return self.publicId
+    def _set_publicId(self, publicId):
+        self.publicId = publicId
+
+    def _get_systemId(self):
+        return self.systemId
+    def _set_systemId(self, systemId):
+        self.systemId = systemId
+
+    def _get_baseURI(self):
+        return self.baseURI
+    def _set_baseURI(self, uri):
+        self.baseURI = uri
+
+
+class DOMBuilderFilter:
+    """Element filter which can be used to tailor construction of
+    a DOM instance.
+    """
+
+    # There's really no need for this class; concrete implementations
+    # should just implement the endElement() and startElement()
+    # methods as appropriate.  Using this makes it easy to only
+    # implement one of them.
+
+    FILTER_ACCEPT = 1
+    FILTER_REJECT = 2
+    FILTER_SKIP = 3
+    FILTER_INTERRUPT = 4
+
+    whatToShow = NodeFilter.SHOW_ALL
+
+    def _get_whatToShow(self):
+        return self.whatToShow
+
+    def acceptNode(self, element):
+        return self.FILTER_ACCEPT
+
+    def startContainer(self, element):
+        return self.FILTER_ACCEPT
+
+del NodeFilter
+
+
+class DocumentLS:
+    """Mixin to create documents that conform to the load/save spec."""
+
+    async = False
+
+    def _get_async(self):
+        return False
+    def _set_async(self, async):
+        if async:
+            raise xml.dom.NotSupportedErr(
+                "asynchronous document loading is not supported")
+
+    def abort(self):
+        # What does it mean to "clear" a document?  Does the
+        # documentElement disappear?
+        raise NotImplementedError(
+            "haven't figured out what this means yet")
+
+    def load(self, uri):
+        raise NotImplementedError("haven't written this yet")
+
+    def loadXML(self, source):
+        raise NotImplementedError("haven't written this yet")
+
+    def saveXML(self, snode):
+        if snode is None:
+            snode = self
+        elif snode.ownerDocument is not self:
+            raise xml.dom.WrongDocumentErr()
+        return snode.toxml()
+
+
+class DOMImplementationLS:
+    MODE_SYNCHRONOUS = 1
+    MODE_ASYNCHRONOUS = 2
+
+    def createDOMBuilder(self, mode, schemaType):
+        if schemaType is not None:
+            raise xml.dom.NotSupportedErr(
+                "schemaType not yet supported")
+        if mode == self.MODE_SYNCHRONOUS:
+            return DOMBuilder()
+        if mode == self.MODE_ASYNCHRONOUS:
+            raise xml.dom.NotSupportedErr(
+                "asynchronous builders are not supported")
+        raise ValueError("unknown value for mode")
+
+    def createDOMWriter(self):
+        raise NotImplementedError(
+            "the writer interface hasn't been written yet!")
+
+    def createDOMInputSource(self):
+        return DOMInputSource()
diff --git a/src/main/resources/PythonLibs/xml/etree/ElementInclude.py b/src/main/resources/PythonLibs/xml/etree/ElementInclude.py
new file mode 100644
index 0000000000000000000000000000000000000000..84fd7548b28a0c5f51193caf28bdf045cc1ea3a7
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/etree/ElementInclude.py
@@ -0,0 +1,143 @@
+#
+# ElementTree
+# $Id: ElementInclude.py 3375 2008-02-13 08:05:08Z fredrik $
+#
+# limited xinclude support for element trees
+#
+# history:
+# 2003-08-15 fl   created
+# 2003-11-14 fl   fixed default loader
+#
+# Copyright (c) 2003-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2008 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+
+##
+# Limited XInclude support for the ElementTree package.
+##
+
+import copy
+from . import ElementTree
+
+XINCLUDE = "{http://www.w3.org/2001/XInclude}"
+
+XINCLUDE_INCLUDE = XINCLUDE + "include"
+XINCLUDE_FALLBACK = XINCLUDE + "fallback"
+
+##
+# Fatal include error.
+
+class FatalIncludeError(SyntaxError):
+    pass
+
+##
+# Default loader.  This loader reads an included resource from disk.
+#
+# @param href Resource reference.
+# @param parse Parse mode.  Either "xml" or "text".
+# @param encoding Optional text encoding.
+# @return The expanded resource.  If the parse mode is "xml", this
+#    is an ElementTree instance.  If the parse mode is "text", this
+#    is a Unicode string.  If the loader fails, it can return None
+#    or raise an IOError exception.
+# @throws IOError If the loader fails to load the resource.
+
+def default_loader(href, parse, encoding=None):
+    file = open(href)
+    if parse == "xml":
+        data = ElementTree.parse(file).getroot()
+    else:
+        data = file.read()
+        if encoding:
+            data = data.decode(encoding)
+    file.close()
+    return data
+
+##
+# Expand XInclude directives.
+#
+# @param elem Root element.
+# @param loader Optional resource loader.  If omitted, it defaults
+#     to {@link default_loader}.  If given, it should be a callable
+#     that implements the same interface as <b>default_loader</b>.
+# @throws FatalIncludeError If the function fails to include a given
+#     resource, or if the tree contains malformed XInclude elements.
+# @throws IOError If the function fails to load a given resource.
+
+def include(elem, loader=None):
+    if loader is None:
+        loader = default_loader
+    # look for xinclude elements
+    i = 0
+    while i < len(elem):
+        e = elem[i]
+        if e.tag == XINCLUDE_INCLUDE:
+            # process xinclude directive
+            href = e.get("href")
+            parse = e.get("parse", "xml")
+            if parse == "xml":
+                node = loader(href, parse)
+                if node is None:
+                    raise FatalIncludeError(
+                        "cannot load %r as %r" % (href, parse)
+                        )
+                node = copy.copy(node)
+                if e.tail:
+                    node.tail = (node.tail or "") + e.tail
+                elem[i] = node
+            elif parse == "text":
+                text = loader(href, parse, e.get("encoding"))
+                if text is None:
+                    raise FatalIncludeError(
+                        "cannot load %r as %r" % (href, parse)
+                        )
+                if i:
+                    node = elem[i-1]
+                    node.tail = (node.tail or "") + text + (e.tail or "")
+                else:
+                    elem.text = (elem.text or "") + text + (e.tail or "")
+                del elem[i]
+                continue
+            else:
+                raise FatalIncludeError(
+                    "unknown parse type in xi:include tag (%r)" % parse
+                )
+        elif e.tag == XINCLUDE_FALLBACK:
+            raise FatalIncludeError(
+                "xi:fallback tag must be child of xi:include (%r)" % e.tag
+                )
+        else:
+            include(e, loader)
+        i = i + 1
diff --git a/src/main/resources/PythonLibs/xml/etree/ElementPath.py b/src/main/resources/PythonLibs/xml/etree/ElementPath.py
new file mode 100644
index 0000000000000000000000000000000000000000..4a626d799c827d818bfdb7cdede151039f984277
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/etree/ElementPath.py
@@ -0,0 +1,303 @@
+#
+# ElementTree
+# $Id: ElementPath.py 3375 2008-02-13 08:05:08Z fredrik $
+#
+# limited xpath support for element trees
+#
+# history:
+# 2003-05-23 fl   created
+# 2003-05-28 fl   added support for // etc
+# 2003-08-27 fl   fixed parsing of periods in element names
+# 2007-09-10 fl   new selection engine
+# 2007-09-12 fl   fixed parent selector
+# 2007-09-13 fl   added iterfind; changed findall to return a list
+# 2007-11-30 fl   added namespaces support
+# 2009-10-30 fl   added child element value filter
+#
+# Copyright (c) 2003-2009 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2009 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+
+##
+# Implementation module for XPath support.  There's usually no reason
+# to import this module directly; the <b>ElementTree</b> does this for
+# you, if needed.
+##
+
+import re
+
+xpath_tokenizer_re = re.compile(
+    "("
+    "'[^']*'|\"[^\"]*\"|"
+    "::|"
+    "//?|"
+    "\.\.|"
+    "\(\)|"
+    "[/.*:\[\]\(\)@=])|"
+    "((?:\{[^}]+\})?[^/\[\]\(\)@=\s]+)|"
+    "\s+"
+    )
+
+def xpath_tokenizer(pattern, namespaces=None):
+    for token in xpath_tokenizer_re.findall(pattern):
+        tag = token[1]
+        if tag and tag[0] != "{" and ":" in tag:
+            try:
+                prefix, uri = tag.split(":", 1)
+                if not namespaces:
+                    raise KeyError
+                yield token[0], "{%s}%s" % (namespaces[prefix], uri)
+            except KeyError:
+                raise SyntaxError("prefix %r not found in prefix map" % prefix)
+        else:
+            yield token
+
+def get_parent_map(context):
+    parent_map = context.parent_map
+    if parent_map is None:
+        context.parent_map = parent_map = {}
+        for p in context.root.iter():
+            for e in p:
+                parent_map[e] = p
+    return parent_map
+
+def prepare_child(next, token):
+    tag = token[1]
+    def select(context, result):
+        for elem in result:
+            for e in elem:
+                if e.tag == tag:
+                    yield e
+    return select
+
+def prepare_star(next, token):
+    def select(context, result):
+        for elem in result:
+            for e in elem:
+                yield e
+    return select
+
+def prepare_self(next, token):
+    def select(context, result):
+        for elem in result:
+            yield elem
+    return select
+
+def prepare_descendant(next, token):
+    token = next()
+    if token[0] == "*":
+        tag = "*"
+    elif not token[0]:
+        tag = token[1]
+    else:
+        raise SyntaxError("invalid descendant")
+    def select(context, result):
+        for elem in result:
+            for e in elem.iter(tag):
+                if e is not elem:
+                    yield e
+    return select
+
+def prepare_parent(next, token):
+    def select(context, result):
+        # FIXME: raise error if .. is applied at toplevel?
+        parent_map = get_parent_map(context)
+        result_map = {}
+        for elem in result:
+            if elem in parent_map:
+                parent = parent_map[elem]
+                if parent not in result_map:
+                    result_map[parent] = None
+                    yield parent
+    return select
+
+def prepare_predicate(next, token):
+    # FIXME: replace with real parser!!! refs:
+    # http://effbot.org/zone/simple-iterator-parser.htm
+    # http://javascript.crockford.com/tdop/tdop.html
+    signature = []
+    predicate = []
+    while 1:
+        token = next()
+        if token[0] == "]":
+            break
+        if token[0] and token[0][:1] in "'\"":
+            token = "'", token[0][1:-1]
+        signature.append(token[0] or "-")
+        predicate.append(token[1])
+    signature = "".join(signature)
+    # use signature to determine predicate type
+    if signature == "@-":
+        # [@attribute] predicate
+        key = predicate[1]
+        def select(context, result):
+            for elem in result:
+                if elem.get(key) is not None:
+                    yield elem
+        return select
+    if signature == "@-='":
+        # [@attribute='value']
+        key = predicate[1]
+        value = predicate[-1]
+        def select(context, result):
+            for elem in result:
+                if elem.get(key) == value:
+                    yield elem
+        return select
+    if signature == "-" and not re.match("\d+$", predicate[0]):
+        # [tag]
+        tag = predicate[0]
+        def select(context, result):
+            for elem in result:
+                if elem.find(tag) is not None:
+                    yield elem
+        return select
+    if signature == "-='" and not re.match("\d+$", predicate[0]):
+        # [tag='value']
+        tag = predicate[0]
+        value = predicate[-1]
+        def select(context, result):
+            for elem in result:
+                for e in elem.findall(tag):
+                    if "".join(e.itertext()) == value:
+                        yield elem
+                        break
+        return select
+    if signature == "-" or signature == "-()" or signature == "-()-":
+        # [index] or [last()] or [last()-index]
+        if signature == "-":
+            index = int(predicate[0]) - 1
+        else:
+            if predicate[0] != "last":
+                raise SyntaxError("unsupported function")
+            if signature == "-()-":
+                try:
+                    index = int(predicate[2]) - 1
+                except ValueError:
+                    raise SyntaxError("unsupported expression")
+            else:
+                index = -1
+        def select(context, result):
+            parent_map = get_parent_map(context)
+            for elem in result:
+                try:
+                    parent = parent_map[elem]
+                    # FIXME: what if the selector is "*" ?
+                    elems = list(parent.findall(elem.tag))
+                    if elems[index] is elem:
+                        yield elem
+                except (IndexError, KeyError):
+                    pass
+        return select
+    raise SyntaxError("invalid predicate")
+
+ops = {
+    "": prepare_child,
+    "*": prepare_star,
+    ".": prepare_self,
+    "..": prepare_parent,
+    "//": prepare_descendant,
+    "[": prepare_predicate,
+    }
+
+_cache = {}
+
+class _SelectorContext:
+    parent_map = None
+    def __init__(self, root):
+        self.root = root
+
+# --------------------------------------------------------------------
+
+##
+# Generate all matching objects.
+
+def iterfind(elem, path, namespaces=None):
+    # compile selector pattern
+    if path[-1:] == "/":
+        path = path + "*" # implicit all (FIXME: keep this?)
+    try:
+        selector = _cache[path]
+    except KeyError:
+        if len(_cache) > 100:
+            _cache.clear()
+        if path[:1] == "/":
+            raise SyntaxError("cannot use absolute path on element")
+        next = iter(xpath_tokenizer(path, namespaces)).next
+        token = next()
+        selector = []
+        while 1:
+            try:
+                selector.append(ops[token[0]](next, token))
+            except StopIteration:
+                raise SyntaxError("invalid path")
+            try:
+                token = next()
+                if token[0] == "/":
+                    token = next()
+            except StopIteration:
+                break
+        _cache[path] = selector
+    # execute selector pattern
+    result = [elem]
+    context = _SelectorContext(elem)
+    for select in selector:
+        result = select(context, result)
+    return result
+
+##
+# Find first matching object.
+
+def find(elem, path, namespaces=None):
+    try:
+        return iterfind(elem, path, namespaces).next()
+    except StopIteration:
+        return None
+
+##
+# Find all matching objects.
+
+def findall(elem, path, namespaces=None):
+    return list(iterfind(elem, path, namespaces))
+
+##
+# Find text for first matching object.
+
+def findtext(elem, path, default=None, namespaces=None):
+    try:
+        elem = iterfind(elem, path, namespaces).next()
+        return elem.text or ""
+    except StopIteration:
+        return default
diff --git a/src/main/resources/PythonLibs/xml/etree/ElementTree.py b/src/main/resources/PythonLibs/xml/etree/ElementTree.py
new file mode 100644
index 0000000000000000000000000000000000000000..cd33cd08a6c524ff160fcf37cc0702179d8e13e9
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/etree/ElementTree.py
@@ -0,0 +1,1669 @@
+#
+# ElementTree
+# $Id: ElementTree.py 3440 2008-07-18 14:45:01Z fredrik $
+#
+# light-weight XML support for Python 2.3 and later.
+#
+# history (since 1.2.6):
+# 2005-11-12 fl   added tostringlist/fromstringlist helpers
+# 2006-07-05 fl   merged in selected changes from the 1.3 sandbox
+# 2006-07-05 fl   removed support for 2.1 and earlier
+# 2007-06-21 fl   added deprecation/future warnings
+# 2007-08-25 fl   added doctype hook, added parser version attribute etc
+# 2007-08-26 fl   added new serializer code (better namespace handling, etc)
+# 2007-08-27 fl   warn for broken /tag searches on tree level
+# 2007-09-02 fl   added html/text methods to serializer (experimental)
+# 2007-09-05 fl   added method argument to tostring/tostringlist
+# 2007-09-06 fl   improved error handling
+# 2007-09-13 fl   added itertext, iterfind; assorted cleanups
+# 2007-12-15 fl   added C14N hooks, copy method (experimental)
+#
+# Copyright (c) 1999-2008 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2008 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+
+__all__ = [
+    # public symbols
+    "Comment",
+    "dump",
+    "Element", "ElementTree",
+    "fromstring", "fromstringlist",
+    "iselement", "iterparse",
+    "parse", "ParseError",
+    "PI", "ProcessingInstruction",
+    "QName",
+    "SubElement",
+    "tostring", "tostringlist",
+    "TreeBuilder",
+    "VERSION",
+    "XML",
+    "XMLParser", "XMLTreeBuilder",
+    ]
+
+VERSION = "1.3.0"
+
+##
+# The <b>Element</b> type is a flexible container object, designed to
+# store hierarchical data structures in memory. The type can be
+# described as a cross between a list and a dictionary.
+# <p>
+# Each element has a number of properties associated with it:
+# <ul>
+# <li>a <i>tag</i>. This is a string identifying what kind of data
+# this element represents (the element type, in other words).</li>
+# <li>a number of <i>attributes</i>, stored in a Python dictionary.</li>
+# <li>a <i>text</i> string.</li>
+# <li>an optional <i>tail</i> string.</li>
+# <li>a number of <i>child elements</i>, stored in a Python sequence</li>
+# </ul>
+#
+# To create an element instance, use the {@link #Element} constructor
+# or the {@link #SubElement} factory function.
+# <p>
+# The {@link #ElementTree} class can be used to wrap an element
+# structure, and convert it from and to XML.
+##
+
+import sys
+import re
+import warnings
+
+
+class _SimpleElementPath(object):
+    # emulate pre-1.2 find/findtext/findall behaviour
+    def find(self, element, tag, namespaces=None):
+        for elem in element:
+            if elem.tag == tag:
+                return elem
+        return None
+    def findtext(self, element, tag, default=None, namespaces=None):
+        elem = self.find(element, tag)
+        if elem is None:
+            return default
+        return elem.text or ""
+    def iterfind(self, element, tag, namespaces=None):
+        if tag[:3] == ".//":
+            for elem in element.iter(tag[3:]):
+                yield elem
+        for elem in element:
+            if elem.tag == tag:
+                yield elem
+    def findall(self, element, tag, namespaces=None):
+        return list(self.iterfind(element, tag, namespaces))
+
+try:
+    from . import ElementPath
+except ImportError:
+    ElementPath = _SimpleElementPath()
+
+##
+# Parser error.  This is a subclass of <b>SyntaxError</b>.
+# <p>
+# In addition to the exception value, an exception instance contains a
+# specific exception code in the <b>code</b> attribute, and the line and
+# column of the error in the <b>position</b> attribute.
+
+class ParseError(SyntaxError):
+    pass
+
+# --------------------------------------------------------------------
+
+##
+# Checks if an object appears to be a valid element object.
+#
+# @param An element instance.
+# @return A true value if this is an element object.
+# @defreturn flag
+
+def iselement(element):
+    # FIXME: not sure about this; might be a better idea to look
+    # for tag/attrib/text attributes
+    return isinstance(element, Element) or hasattr(element, "tag")
+
+##
+# Element class.  This class defines the Element interface, and
+# provides a reference implementation of this interface.
+# <p>
+# The element name, attribute names, and attribute values can be
+# either ASCII strings (ordinary Python strings containing only 7-bit
+# ASCII characters) or Unicode strings.
+#
+# @param tag The element name.
+# @param attrib An optional dictionary, containing element attributes.
+# @param **extra Additional attributes, given as keyword arguments.
+# @see Element
+# @see SubElement
+# @see Comment
+# @see ProcessingInstruction
+
+class Element(object):
+    # <tag attrib>text<child/>...</tag>tail
+
+    ##
+    # (Attribute) Element tag.
+
+    tag = None
+
+    ##
+    # (Attribute) Element attribute dictionary.  Where possible, use
+    # {@link #Element.get},
+    # {@link #Element.set},
+    # {@link #Element.keys}, and
+    # {@link #Element.items} to access
+    # element attributes.
+
+    attrib = None
+
+    ##
+    # (Attribute) Text before first subelement.  This is either a
+    # string or the value None.  Note that if there was no text, this
+    # attribute may be either None or an empty string, depending on
+    # the parser.
+
+    text = None
+
+    ##
+    # (Attribute) Text after this element's end tag, but before the
+    # next sibling element's start tag.  This is either a string or
+    # the value None.  Note that if there was no text, this attribute
+    # may be either None or an empty string, depending on the parser.
+
+    tail = None # text after end tag, if any
+
+    # constructor
+
+    def __init__(self, tag, attrib={}, **extra):
+        attrib = attrib.copy()
+        attrib.update(extra)
+        self.tag = tag
+        self.attrib = attrib
+        self._children = []
+
+    def __repr__(self):
+        return "<Element %s at 0x%x>" % (repr(self.tag), id(self))
+
+    ##
+    # Creates a new element object of the same type as this element.
+    #
+    # @param tag Element tag.
+    # @param attrib Element attributes, given as a dictionary.
+    # @return A new element instance.
+
+    def makeelement(self, tag, attrib):
+        return self.__class__(tag, attrib)
+
+    ##
+    # (Experimental) Copies the current element.  This creates a
+    # shallow copy; subelements will be shared with the original tree.
+    #
+    # @return A new element instance.
+
+    def copy(self):
+        elem = self.makeelement(self.tag, self.attrib)
+        elem.text = self.text
+        elem.tail = self.tail
+        elem[:] = self
+        return elem
+
+    ##
+    # Returns the number of subelements.  Note that this only counts
+    # full elements; to check if there's any content in an element, you
+    # have to check both the length and the <b>text</b> attribute.
+    #
+    # @return The number of subelements.
+
+    def __len__(self):
+        return len(self._children)
+
+    def __nonzero__(self):
+        warnings.warn(
+            "The behavior of this method will change in future versions.  "
+            "Use specific 'len(elem)' or 'elem is not None' test instead.",
+            FutureWarning, stacklevel=2
+            )
+        return len(self._children) != 0 # emulate old behaviour, for now
+
+    ##
+    # Returns the given subelement, by index.
+    #
+    # @param index What subelement to return.
+    # @return The given subelement.
+    # @exception IndexError If the given element does not exist.
+
+    def __getitem__(self, index):
+        return self._children[index]
+
+    ##
+    # Replaces the given subelement, by index.
+    #
+    # @param index What subelement to replace.
+    # @param element The new element value.
+    # @exception IndexError If the given element does not exist.
+
+    def __setitem__(self, index, element):
+        # if isinstance(index, slice):
+        #     for elt in element:
+        #         assert iselement(elt)
+        # else:
+        #     assert iselement(element)
+        self._children[index] = element
+
+    ##
+    # Deletes the given subelement, by index.
+    #
+    # @param index What subelement to delete.
+    # @exception IndexError If the given element does not exist.
+
+    def __delitem__(self, index):
+        del self._children[index]
+
+    ##
+    # Adds a subelement to the end of this element.  In document order,
+    # the new element will appear after the last existing subelement (or
+    # directly after the text, if it's the first subelement), but before
+    # the end tag for this element.
+    #
+    # @param element The element to add.
+
+    def append(self, element):
+        # assert iselement(element)
+        self._children.append(element)
+
+    ##
+    # Appends subelements from a sequence.
+    #
+    # @param elements A sequence object with zero or more elements.
+    # @since 1.3
+
+    def extend(self, elements):
+        # for element in elements:
+        #     assert iselement(element)
+        self._children.extend(elements)
+
+    ##
+    # Inserts a subelement at the given position in this element.
+    #
+    # @param index Where to insert the new subelement.
+
+    def insert(self, index, element):
+        # assert iselement(element)
+        self._children.insert(index, element)
+
+    ##
+    # Removes a matching subelement.  Unlike the <b>find</b> methods,
+    # this method compares elements based on identity, not on tag
+    # value or contents.  To remove subelements by other means, the
+    # easiest way is often to use a list comprehension to select what
+    # elements to keep, and use slice assignment to update the parent
+    # element.
+    #
+    # @param element What element to remove.
+    # @exception ValueError If a matching element could not be found.
+
+    def remove(self, element):
+        # assert iselement(element)
+        self._children.remove(element)
+
+    ##
+    # (Deprecated) Returns all subelements.  The elements are returned
+    # in document order.
+    #
+    # @return A list of subelements.
+    # @defreturn list of Element instances
+
+    def getchildren(self):
+        warnings.warn(
+            "This method will be removed in future versions.  "
+            "Use 'list(elem)' or iteration over elem instead.",
+            DeprecationWarning, stacklevel=2
+            )
+        return self._children
+
+    ##
+    # Finds the first matching subelement, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return The first matching element, or None if no element was found.
+    # @defreturn Element or None
+
+    def find(self, path, namespaces=None):
+        return ElementPath.find(self, path, namespaces)
+
+    ##
+    # Finds text for the first matching subelement, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @param default What to return if the element was not found.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return The text content of the first matching element, or the
+    #     default value no element was found.  Note that if the element
+    #     is found, but has no text content, this method returns an
+    #     empty string.
+    # @defreturn string
+
+    def findtext(self, path, default=None, namespaces=None):
+        return ElementPath.findtext(self, path, default, namespaces)
+
+    ##
+    # Finds all matching subelements, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return A list or other sequence containing all matching elements,
+    #    in document order.
+    # @defreturn list of Element instances
+
+    def findall(self, path, namespaces=None):
+        return ElementPath.findall(self, path, namespaces)
+
+    ##
+    # Finds all matching subelements, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return An iterator or sequence containing all matching elements,
+    #    in document order.
+    # @defreturn a generated sequence of Element instances
+
+    def iterfind(self, path, namespaces=None):
+        return ElementPath.iterfind(self, path, namespaces)
+
+    ##
+    # Resets an element.  This function removes all subelements, clears
+    # all attributes, and sets the <b>text</b> and <b>tail</b> attributes
+    # to None.
+
+    def clear(self):
+        self.attrib.clear()
+        self._children = []
+        self.text = self.tail = None
+
+    ##
+    # Gets an element attribute.  Equivalent to <b>attrib.get</b>, but
+    # some implementations may handle this a bit more efficiently.
+    #
+    # @param key What attribute to look for.
+    # @param default What to return if the attribute was not found.
+    # @return The attribute value, or the default value, if the
+    #     attribute was not found.
+    # @defreturn string or None
+
+    def get(self, key, default=None):
+        return self.attrib.get(key, default)
+
+    ##
+    # Sets an element attribute.  Equivalent to <b>attrib[key] = value</b>,
+    # but some implementations may handle this a bit more efficiently.
+    #
+    # @param key What attribute to set.
+    # @param value The attribute value.
+
+    def set(self, key, value):
+        self.attrib[key] = value
+
+    ##
+    # Gets a list of attribute names.  The names are returned in an
+    # arbitrary order (just like for an ordinary Python dictionary).
+    # Equivalent to <b>attrib.keys()</b>.
+    #
+    # @return A list of element attribute names.
+    # @defreturn list of strings
+
+    def keys(self):
+        return self.attrib.keys()
+
+    ##
+    # Gets element attributes, as a sequence.  The attributes are
+    # returned in an arbitrary order.  Equivalent to <b>attrib.items()</b>.
+    #
+    # @return A list of (name, value) tuples for all attributes.
+    # @defreturn list of (string, string) tuples
+
+    def items(self):
+        return self.attrib.items()
+
+    ##
+    # Creates a tree iterator.  The iterator loops over this element
+    # and all subelements, in document order, and returns all elements
+    # with a matching tag.
+    # <p>
+    # If the tree structure is modified during iteration, new or removed
+    # elements may or may not be included.  To get a stable set, use the
+    # list() function on the iterator, and loop over the resulting list.
+    #
+    # @param tag What tags to look for (default is to return all elements).
+    # @return An iterator containing all the matching elements.
+    # @defreturn iterator
+
+    def iter(self, tag=None):
+        if tag == "*":
+            tag = None
+        if tag is None or self.tag == tag:
+            yield self
+        for e in self._children:
+            for e in e.iter(tag):
+                yield e
+
+    # compatibility
+    def getiterator(self, tag=None):
+        # Change for a DeprecationWarning in 1.4
+        warnings.warn(
+            "This method will be removed in future versions.  "
+            "Use 'elem.iter()' or 'list(elem.iter())' instead.",
+            PendingDeprecationWarning, stacklevel=2
+        )
+        return list(self.iter(tag))
+
+    ##
+    # Creates a text iterator.  The iterator loops over this element
+    # and all subelements, in document order, and returns all inner
+    # text.
+    #
+    # @return An iterator containing all inner text.
+    # @defreturn iterator
+
+    def itertext(self):
+        tag = self.tag
+        if not isinstance(tag, basestring) and tag is not None:
+            return
+        if self.text:
+            yield self.text
+        for e in self:
+            for s in e.itertext():
+                yield s
+            if e.tail:
+                yield e.tail
+
+# compatibility
+_Element = _ElementInterface = Element
+
+##
+# Subelement factory.  This function creates an element instance, and
+# appends it to an existing element.
+# <p>
+# The element name, attribute names, and attribute values can be
+# either 8-bit ASCII strings or Unicode strings.
+#
+# @param parent The parent element.
+# @param tag The subelement name.
+# @param attrib An optional dictionary, containing element attributes.
+# @param **extra Additional attributes, given as keyword arguments.
+# @return An element instance.
+# @defreturn Element
+
+def SubElement(parent, tag, attrib={}, **extra):
+    attrib = attrib.copy()
+    attrib.update(extra)
+    element = parent.makeelement(tag, attrib)
+    parent.append(element)
+    return element
+
+##
+# Comment element factory.  This factory function creates a special
+# element that will be serialized as an XML comment by the standard
+# serializer.
+# <p>
+# The comment string can be either an 8-bit ASCII string or a Unicode
+# string.
+#
+# @param text A string containing the comment string.
+# @return An element instance, representing a comment.
+# @defreturn Element
+
+def Comment(text=None):
+    element = Element(Comment)
+    element.text = text
+    return element
+
+##
+# PI element factory.  This factory function creates a special element
+# that will be serialized as an XML processing instruction by the standard
+# serializer.
+#
+# @param target A string containing the PI target.
+# @param text A string containing the PI contents, if any.
+# @return An element instance, representing a PI.
+# @defreturn Element
+
+def ProcessingInstruction(target, text=None):
+    element = Element(ProcessingInstruction)
+    element.text = target
+    if text:
+        element.text = element.text + " " + text
+    return element
+
+PI = ProcessingInstruction
+
+##
+# QName wrapper.  This can be used to wrap a QName attribute value, in
+# order to get proper namespace handling on output.
+#
+# @param text A string containing the QName value, in the form {uri}local,
+#     or, if the tag argument is given, the URI part of a QName.
+# @param tag Optional tag.  If given, the first argument is interpreted as
+#     an URI, and this argument is interpreted as a local name.
+# @return An opaque object, representing the QName.
+
+class QName(object):
+    def __init__(self, text_or_uri, tag=None):
+        if tag:
+            text_or_uri = "{%s}%s" % (text_or_uri, tag)
+        self.text = text_or_uri
+    def __str__(self):
+        return self.text
+    def __hash__(self):
+        return hash(self.text)
+    def __cmp__(self, other):
+        if isinstance(other, QName):
+            return cmp(self.text, other.text)
+        return cmp(self.text, other)
+
+# --------------------------------------------------------------------
+
+##
+# ElementTree wrapper class.  This class represents an entire element
+# hierarchy, and adds some extra support for serialization to and from
+# standard XML.
+#
+# @param element Optional root element.
+# @keyparam file Optional file handle or file name.  If given, the
+#     tree is initialized with the contents of this XML file.
+
+class ElementTree(object):
+
+    def __init__(self, element=None, file=None):
+        # assert element is None or iselement(element)
+        self._root = element # first node
+        if file:
+            self.parse(file)
+
+    ##
+    # Gets the root element for this tree.
+    #
+    # @return An element instance.
+    # @defreturn Element
+
+    def getroot(self):
+        return self._root
+
+    ##
+    # Replaces the root element for this tree.  This discards the
+    # current contents of the tree, and replaces it with the given
+    # element.  Use with care.
+    #
+    # @param element An element instance.
+
+    def _setroot(self, element):
+        # assert iselement(element)
+        self._root = element
+
+    ##
+    # Loads an external XML document into this element tree.
+    #
+    # @param source A file name or file object.  If a file object is
+    #     given, it only has to implement a <b>read(n)</b> method.
+    # @keyparam parser An optional parser instance.  If not given, the
+    #     standard {@link XMLParser} parser is used.
+    # @return The document root element.
+    # @defreturn Element
+    # @exception ParseError If the parser fails to parse the document.
+
+    def parse(self, source, parser=None):
+        close_source = False
+        if not hasattr(source, "read"):
+            source = open(source, "rb")
+            close_source = True
+        try:
+            if not parser:
+                parser = XMLParser(target=TreeBuilder())
+            while 1:
+                data = source.read(65536)
+                if not data:
+                    break
+                parser.feed(data)
+            self._root = parser.close()
+            return self._root
+        finally:
+            if close_source:
+                source.close()
+
+    ##
+    # Creates a tree iterator for the root element.  The iterator loops
+    # over all elements in this tree, in document order.
+    #
+    # @param tag What tags to look for (default is to return all elements)
+    # @return An iterator.
+    # @defreturn iterator
+
+    def iter(self, tag=None):
+        # assert self._root is not None
+        return self._root.iter(tag)
+
+    # compatibility
+    def getiterator(self, tag=None):
+        # Change for a DeprecationWarning in 1.4
+        warnings.warn(
+            "This method will be removed in future versions.  "
+            "Use 'tree.iter()' or 'list(tree.iter())' instead.",
+            PendingDeprecationWarning, stacklevel=2
+        )
+        return list(self.iter(tag))
+
+    ##
+    # Finds the first toplevel element with given tag.
+    # Same as getroot().find(path).
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return The first matching element, or None if no element was found.
+    # @defreturn Element or None
+
+    def find(self, path, namespaces=None):
+        # assert self._root is not None
+        if path[:1] == "/":
+            path = "." + path
+            warnings.warn(
+                "This search is broken in 1.3 and earlier, and will be "
+                "fixed in a future version.  If you rely on the current "
+                "behaviour, change it to %r" % path,
+                FutureWarning, stacklevel=2
+                )
+        return self._root.find(path, namespaces)
+
+    ##
+    # Finds the element text for the first toplevel element with given
+    # tag.  Same as getroot().findtext(path).
+    #
+    # @param path What toplevel element to look for.
+    # @param default What to return if the element was not found.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return The text content of the first matching element, or the
+    #     default value no element was found.  Note that if the element
+    #     is found, but has no text content, this method returns an
+    #     empty string.
+    # @defreturn string
+
+    def findtext(self, path, default=None, namespaces=None):
+        # assert self._root is not None
+        if path[:1] == "/":
+            path = "." + path
+            warnings.warn(
+                "This search is broken in 1.3 and earlier, and will be "
+                "fixed in a future version.  If you rely on the current "
+                "behaviour, change it to %r" % path,
+                FutureWarning, stacklevel=2
+                )
+        return self._root.findtext(path, default, namespaces)
+
+    ##
+    # Finds all toplevel elements with the given tag.
+    # Same as getroot().findall(path).
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return A list or iterator containing all matching elements,
+    #    in document order.
+    # @defreturn list of Element instances
+
+    def findall(self, path, namespaces=None):
+        # assert self._root is not None
+        if path[:1] == "/":
+            path = "." + path
+            warnings.warn(
+                "This search is broken in 1.3 and earlier, and will be "
+                "fixed in a future version.  If you rely on the current "
+                "behaviour, change it to %r" % path,
+                FutureWarning, stacklevel=2
+                )
+        return self._root.findall(path, namespaces)
+
+    ##
+    # Finds all matching subelements, by tag name or path.
+    # Same as getroot().iterfind(path).
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return An iterator or sequence containing all matching elements,
+    #    in document order.
+    # @defreturn a generated sequence of Element instances
+
+    def iterfind(self, path, namespaces=None):
+        # assert self._root is not None
+        if path[:1] == "/":
+            path = "." + path
+            warnings.warn(
+                "This search is broken in 1.3 and earlier, and will be "
+                "fixed in a future version.  If you rely on the current "
+                "behaviour, change it to %r" % path,
+                FutureWarning, stacklevel=2
+                )
+        return self._root.iterfind(path, namespaces)
+
+    ##
+    # Writes the element tree to a file, as XML.
+    #
+    # @def write(file, **options)
+    # @param file A file name, or a file object opened for writing.
+    # @param **options Options, given as keyword arguments.
+    # @keyparam encoding Optional output encoding (default is US-ASCII).
+    # @keyparam xml_declaration Controls if an XML declaration should
+    #     be added to the file.  Use False for never, True for always,
+    #     None for only if not US-ASCII or UTF-8.  None is default.
+    # @keyparam default_namespace Sets the default XML namespace (for "xmlns").
+    # @keyparam method Optional output method ("xml", "html", "text" or
+    #     "c14n"; default is "xml").
+
+    def write(self, file_or_filename,
+              # keyword arguments
+              encoding=None,
+              xml_declaration=None,
+              default_namespace=None,
+              method=None):
+        # assert self._root is not None
+        if not method:
+            method = "xml"
+        elif method not in _serialize:
+            # FIXME: raise an ImportError for c14n if ElementC14N is missing?
+            raise ValueError("unknown method %r" % method)
+        if hasattr(file_or_filename, "write"):
+            file = file_or_filename
+        else:
+            file = open(file_or_filename, "wb")
+        write = file.write
+        if not encoding:
+            if method == "c14n":
+                encoding = "utf-8"
+            else:
+                encoding = "us-ascii"
+        elif xml_declaration or (xml_declaration is None and
+                                 encoding not in ("utf-8", "us-ascii")):
+            if method == "xml":
+                write("<?xml version='1.0' encoding='%s'?>\n" % encoding)
+        if method == "text":
+            _serialize_text(write, self._root, encoding)
+        else:
+            qnames, namespaces = _namespaces(
+                self._root, encoding, default_namespace
+                )
+            serialize = _serialize[method]
+            serialize(write, self._root, encoding, qnames, namespaces)
+        if file_or_filename is not file:
+            file.close()
+
+    def write_c14n(self, file):
+        # lxml.etree compatibility.  use output method instead
+        return self.write(file, method="c14n")
+
+# --------------------------------------------------------------------
+# serialization support
+
+def _namespaces(elem, encoding, default_namespace=None):
+    # identify namespaces used in this tree
+
+    # maps qnames to *encoded* prefix:local names
+    qnames = {None: None}
+
+    # maps uri:s to prefixes
+    namespaces = {}
+    if default_namespace:
+        namespaces[default_namespace] = ""
+
+    def encode(text):
+        return text.encode(encoding)
+
+    def add_qname(qname):
+        # calculate serialized qname representation
+        try:
+            if qname[:1] == "{":
+                uri, tag = qname[1:].rsplit("}", 1)
+                prefix = namespaces.get(uri)
+                if prefix is None:
+                    prefix = _namespace_map.get(uri)
+                    if prefix is None:
+                        prefix = "ns%d" % len(namespaces)
+                    if prefix != "xml":
+                        namespaces[uri] = prefix
+                if prefix:
+                    qnames[qname] = encode("%s:%s" % (prefix, tag))
+                else:
+                    qnames[qname] = encode(tag) # default element
+            else:
+                if default_namespace:
+                    # FIXME: can this be handled in XML 1.0?
+                    raise ValueError(
+                        "cannot use non-qualified names with "
+                        "default_namespace option"
+                        )
+                qnames[qname] = encode(qname)
+        except TypeError:
+            _raise_serialization_error(qname)
+
+    # populate qname and namespaces table
+    try:
+        iterate = elem.iter
+    except AttributeError:
+        iterate = elem.getiterator # cET compatibility
+    for elem in iterate():
+        tag = elem.tag
+        if isinstance(tag, QName):
+            if tag.text not in qnames:
+                add_qname(tag.text)
+        elif isinstance(tag, basestring):
+            if tag not in qnames:
+                add_qname(tag)
+        elif tag is not None and tag is not Comment and tag is not PI:
+            _raise_serialization_error(tag)
+        for key, value in elem.items():
+            if isinstance(key, QName):
+                key = key.text
+            if key not in qnames:
+                add_qname(key)
+            if isinstance(value, QName) and value.text not in qnames:
+                add_qname(value.text)
+        text = elem.text
+        if isinstance(text, QName) and text.text not in qnames:
+            add_qname(text.text)
+    return qnames, namespaces
+
+def _serialize_xml(write, elem, encoding, qnames, namespaces):
+    tag = elem.tag
+    text = elem.text
+    if tag is Comment:
+        write("<!--%s-->" % _encode(text, encoding))
+    elif tag is ProcessingInstruction:
+        write("<?%s?>" % _encode(text, encoding))
+    else:
+        tag = qnames[tag]
+        if tag is None:
+            if text:
+                write(_escape_cdata(text, encoding))
+            for e in elem:
+                _serialize_xml(write, e, encoding, qnames, None)
+        else:
+            write("<" + tag)
+            items = elem.items()
+            if items or namespaces:
+                if namespaces:
+                    for v, k in sorted(namespaces.items(),
+                                       key=lambda x: x[1]):  # sort on prefix
+                        if k:
+                            k = ":" + k
+                        write(" xmlns%s=\"%s\"" % (
+                            k.encode(encoding),
+                            _escape_attrib(v, encoding)
+                            ))
+                for k, v in sorted(items):  # lexical order
+                    if isinstance(k, QName):
+                        k = k.text
+                    if isinstance(v, QName):
+                        v = qnames[v.text]
+                    else:
+                        v = _escape_attrib(v, encoding)
+                    write(" %s=\"%s\"" % (qnames[k], v))
+            if text or len(elem):
+                write(">")
+                if text:
+                    write(_escape_cdata(text, encoding))
+                for e in elem:
+                    _serialize_xml(write, e, encoding, qnames, None)
+                write("</" + tag + ">")
+            else:
+                write(" />")
+    if elem.tail:
+        write(_escape_cdata(elem.tail, encoding))
+
+HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
+              "img", "input", "isindex", "link", "meta", "param")
+
+try:
+    HTML_EMPTY = set(HTML_EMPTY)
+except NameError:
+    pass
+
+def _serialize_html(write, elem, encoding, qnames, namespaces):
+    tag = elem.tag
+    text = elem.text
+    if tag is Comment:
+        write("<!--%s-->" % _escape_cdata(text, encoding))
+    elif tag is ProcessingInstruction:
+        write("<?%s?>" % _escape_cdata(text, encoding))
+    else:
+        tag = qnames[tag]
+        if tag is None:
+            if text:
+                write(_escape_cdata(text, encoding))
+            for e in elem:
+                _serialize_html(write, e, encoding, qnames, None)
+        else:
+            write("<" + tag)
+            items = elem.items()
+            if items or namespaces:
+                if namespaces:
+                    for v, k in sorted(namespaces.items(),
+                                       key=lambda x: x[1]):  # sort on prefix
+                        if k:
+                            k = ":" + k
+                        write(" xmlns%s=\"%s\"" % (
+                            k.encode(encoding),
+                            _escape_attrib(v, encoding)
+                            ))
+                for k, v in sorted(items):  # lexical order
+                    if isinstance(k, QName):
+                        k = k.text
+                    if isinstance(v, QName):
+                        v = qnames[v.text]
+                    else:
+                        v = _escape_attrib_html(v, encoding)
+                    # FIXME: handle boolean attributes
+                    write(" %s=\"%s\"" % (qnames[k], v))
+            write(">")
+            tag = tag.lower()
+            if text:
+                if tag == "script" or tag == "style":
+                    write(_encode(text, encoding))
+                else:
+                    write(_escape_cdata(text, encoding))
+            for e in elem:
+                _serialize_html(write, e, encoding, qnames, None)
+            if tag not in HTML_EMPTY:
+                write("</" + tag + ">")
+    if elem.tail:
+        write(_escape_cdata(elem.tail, encoding))
+
+def _serialize_text(write, elem, encoding):
+    for part in elem.itertext():
+        write(part.encode(encoding))
+    if elem.tail:
+        write(elem.tail.encode(encoding))
+
+_serialize = {
+    "xml": _serialize_xml,
+    "html": _serialize_html,
+    "text": _serialize_text,
+# this optional method is imported at the end of the module
+#   "c14n": _serialize_c14n,
+}
+
+##
+# Registers a namespace prefix.  The registry is global, and any
+# existing mapping for either the given prefix or the namespace URI
+# will be removed.
+#
+# @param prefix Namespace prefix.
+# @param uri Namespace uri.  Tags and attributes in this namespace
+#     will be serialized with the given prefix, if at all possible.
+# @exception ValueError If the prefix is reserved, or is otherwise
+#     invalid.
+
+def register_namespace(prefix, uri):
+    if re.match("ns\d+$", prefix):
+        raise ValueError("Prefix format reserved for internal use")
+    for k, v in _namespace_map.items():
+        if k == uri or v == prefix:
+            del _namespace_map[k]
+    _namespace_map[uri] = prefix
+
+_namespace_map = {
+    # "well-known" namespace prefixes
+    "http://www.w3.org/XML/1998/namespace": "xml",
+    "http://www.w3.org/1999/xhtml": "html",
+    "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
+    "http://schemas.xmlsoap.org/wsdl/": "wsdl",
+    # xml schema
+    "http://www.w3.org/2001/XMLSchema": "xs",
+    "http://www.w3.org/2001/XMLSchema-instance": "xsi",
+    # dublin core
+    "http://purl.org/dc/elements/1.1/": "dc",
+}
+
+def _raise_serialization_error(text):
+    raise TypeError(
+        "cannot serialize %r (type %s)" % (text, type(text).__name__)
+        )
+
+def _encode(text, encoding):
+    try:
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+def _escape_cdata(text, encoding):
+    # escape character data
+    try:
+        # it's worth avoiding do-nothing calls for strings that are
+        # shorter than 500 character, or so.  assume that's, by far,
+        # the most common case in most applications.
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if "<" in text:
+            text = text.replace("<", "&lt;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+def _escape_attrib(text, encoding):
+    # escape attribute value
+    try:
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if "<" in text:
+            text = text.replace("<", "&lt;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        if "\"" in text:
+            text = text.replace("\"", "&quot;")
+        if "\n" in text:
+            text = text.replace("\n", "&#10;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+def _escape_attrib_html(text, encoding):
+    # escape attribute value
+    try:
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        if "\"" in text:
+            text = text.replace("\"", "&quot;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+# --------------------------------------------------------------------
+
+##
+# Generates a string representation of an XML element, including all
+# subelements.
+#
+# @param element An Element instance.
+# @keyparam encoding Optional output encoding (default is US-ASCII).
+# @keyparam method Optional output method ("xml", "html", "text" or
+#     "c14n"; default is "xml").
+# @return An encoded string containing the XML data.
+# @defreturn string
+
+def tostring(element, encoding=None, method=None):
+    class dummy:
+        pass
+    data = []
+    file = dummy()
+    file.write = data.append
+    ElementTree(element).write(file, encoding, method=method)
+    return "".join(data)
+
+##
+# Generates a string representation of an XML element, including all
+# subelements.  The string is returned as a sequence of string fragments.
+#
+# @param element An Element instance.
+# @keyparam encoding Optional output encoding (default is US-ASCII).
+# @keyparam method Optional output method ("xml", "html", "text" or
+#     "c14n"; default is "xml").
+# @return A sequence object containing the XML data.
+# @defreturn sequence
+# @since 1.3
+
+def tostringlist(element, encoding=None, method=None):
+    class dummy:
+        pass
+    data = []
+    file = dummy()
+    file.write = data.append
+    ElementTree(element).write(file, encoding, method=method)
+    # FIXME: merge small fragments into larger parts
+    return data
+
+##
+# Writes an element tree or element structure to sys.stdout.  This
+# function should be used for debugging only.
+# <p>
+# The exact output format is implementation dependent.  In this
+# version, it's written as an ordinary XML file.
+#
+# @param elem An element tree or an individual element.
+
+def dump(elem):
+    # debugging
+    if not isinstance(elem, ElementTree):
+        elem = ElementTree(elem)
+    elem.write(sys.stdout)
+    tail = elem.getroot().tail
+    if not tail or tail[-1] != "\n":
+        sys.stdout.write("\n")
+
+# --------------------------------------------------------------------
+# parsing
+
+##
+# Parses an XML document into an element tree.
+#
+# @param source A filename or file object containing XML data.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return An ElementTree instance
+
+def parse(source, parser=None):
+    tree = ElementTree()
+    tree.parse(source, parser)
+    return tree
+
+##
+# Parses an XML document into an element tree incrementally, and reports
+# what's going on to the user.
+#
+# @param source A filename or file object containing XML data.
+# @param events A list of events to report back.  If omitted, only "end"
+#     events are reported.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return A (event, elem) iterator.
+
+def iterparse(source, events=None, parser=None):
+    close_source = False
+    if not hasattr(source, "read"):
+        source = open(source, "rb")
+        close_source = True
+    if not parser:
+        parser = XMLParser(target=TreeBuilder())
+    return _IterParseIterator(source, events, parser, close_source)
+
+class _IterParseIterator(object):
+
+    def __init__(self, source, events, parser, close_source=False):
+        self._file = source
+        self._close_file = close_source
+        self._events = []
+        self._index = 0
+        self._error = None
+        self.root = self._root = None
+        self._parser = parser
+        # wire up the parser for event reporting
+        parser = self._parser._parser
+        append = self._events.append
+        if events is None:
+            events = ["end"]
+        for event in events:
+            if event == "start":
+                try:
+                    parser.ordered_attributes = 1
+                    parser.specified_attributes = 1
+                    def handler(tag, attrib_in, event=event, append=append,
+                                start=self._parser._start_list):
+                        append((event, start(tag, attrib_in)))
+                    parser.StartElementHandler = handler
+                except AttributeError:
+                    def handler(tag, attrib_in, event=event, append=append,
+                                start=self._parser._start):
+                        append((event, start(tag, attrib_in)))
+                    parser.StartElementHandler = handler
+            elif event == "end":
+                def handler(tag, event=event, append=append,
+                            end=self._parser._end):
+                    append((event, end(tag)))
+                parser.EndElementHandler = handler
+            elif event == "start-ns":
+                def handler(prefix, uri, event=event, append=append):
+                    try:
+                        uri = (uri or "").encode("ascii")
+                    except UnicodeError:
+                        pass
+                    append((event, (prefix or "", uri or "")))
+                parser.StartNamespaceDeclHandler = handler
+            elif event == "end-ns":
+                def handler(prefix, event=event, append=append):
+                    append((event, None))
+                parser.EndNamespaceDeclHandler = handler
+            else:
+                raise ValueError("unknown event %r" % event)
+
+    def next(self):
+        while 1:
+            try:
+                item = self._events[self._index]
+                self._index += 1
+                return item
+            except IndexError:
+                pass
+            if self._error:
+                e = self._error
+                self._error = None
+                raise e
+            if self._parser is None:
+                self.root = self._root
+                if self._close_file:
+                    self._file.close()
+                raise StopIteration
+            # load event buffer
+            del self._events[:]
+            self._index = 0
+            data = self._file.read(16384)
+            if data:
+                try:
+                    self._parser.feed(data)
+                except SyntaxError as exc:
+                    self._error = exc
+            else:
+                self._root = self._parser.close()
+                self._parser = None
+
+    def __iter__(self):
+        return self
+
+##
+# Parses an XML document from a string constant.  This function can
+# be used to embed "XML literals" in Python code.
+#
+# @param source A string containing XML data.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return An Element instance.
+# @defreturn Element
+
+def XML(text, parser=None):
+    if not parser:
+        parser = XMLParser(target=TreeBuilder())
+    parser.feed(text)
+    return parser.close()
+
+##
+# Parses an XML document from a string constant, and also returns
+# a dictionary which maps from element id:s to elements.
+#
+# @param source A string containing XML data.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return A tuple containing an Element instance and a dictionary.
+# @defreturn (Element, dictionary)
+
+def XMLID(text, parser=None):
+    if not parser:
+        parser = XMLParser(target=TreeBuilder())
+    parser.feed(text)
+    tree = parser.close()
+    ids = {}
+    for elem in tree.iter():
+        id = elem.get("id")
+        if id:
+            ids[id] = elem
+    return tree, ids
+
+##
+# Parses an XML document from a string constant.  Same as {@link #XML}.
+#
+# @def fromstring(text)
+# @param source A string containing XML data.
+# @return An Element instance.
+# @defreturn Element
+
+fromstring = XML
+
+##
+# Parses an XML document from a sequence of string fragments.
+#
+# @param sequence A list or other sequence containing XML data fragments.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return An Element instance.
+# @defreturn Element
+# @since 1.3
+
+def fromstringlist(sequence, parser=None):
+    if not parser:
+        parser = XMLParser(target=TreeBuilder())
+    for text in sequence:
+        parser.feed(text)
+    return parser.close()
+
+# --------------------------------------------------------------------
+
+##
+# Generic element structure builder.  This builder converts a sequence
+# of {@link #TreeBuilder.start}, {@link #TreeBuilder.data}, and {@link
+# #TreeBuilder.end} method calls to a well-formed element structure.
+# <p>
+# You can use this class to build an element structure using a custom XML
+# parser, or a parser for some other XML-like format.
+#
+# @param element_factory Optional element factory.  This factory
+#    is called to create new Element instances, as necessary.
+
+class TreeBuilder(object):
+
+    def __init__(self, element_factory=None):
+        self._data = [] # data collector
+        self._elem = [] # element stack
+        self._last = None # last element
+        self._tail = None # true if we're after an end tag
+        if element_factory is None:
+            element_factory = Element
+        self._factory = element_factory
+
+    ##
+    # Flushes the builder buffers, and returns the toplevel document
+    # element.
+    #
+    # @return An Element instance.
+    # @defreturn Element
+
+    def close(self):
+        assert len(self._elem) == 0, "missing end tags"
+        assert self._last is not None, "missing toplevel element"
+        return self._last
+
+    def _flush(self):
+        if self._data:
+            if self._last is not None:
+                text = "".join(self._data)
+                if self._tail:
+                    assert self._last.tail is None, "internal error (tail)"
+                    self._last.tail = text
+                else:
+                    assert self._last.text is None, "internal error (text)"
+                    self._last.text = text
+            self._data = []
+
+    ##
+    # Adds text to the current element.
+    #
+    # @param data A string.  This should be either an 8-bit string
+    #    containing ASCII text, or a Unicode string.
+
+    def data(self, data):
+        self._data.append(data)
+
+    ##
+    # Opens a new element.
+    #
+    # @param tag The element name.
+    # @param attrib A dictionary containing element attributes.
+    # @return The opened element.
+    # @defreturn Element
+
+    def start(self, tag, attrs):
+        self._flush()
+        self._last = elem = self._factory(tag, attrs)
+        if self._elem:
+            self._elem[-1].append(elem)
+        self._elem.append(elem)
+        self._tail = 0
+        return elem
+
+    ##
+    # Closes the current element.
+    #
+    # @param tag The element name.
+    # @return The closed element.
+    # @defreturn Element
+
+    def end(self, tag):
+        self._flush()
+        self._last = self._elem.pop()
+        assert self._last.tag == tag,\
+               "end tag mismatch (expected %s, got %s)" % (
+                   self._last.tag, tag)
+        self._tail = 1
+        return self._last
+
+##
+# Element structure builder for XML source data, based on the
+# <b>expat</b> parser.
+#
+# @keyparam target Target object.  If omitted, the builder uses an
+#     instance of the standard {@link #TreeBuilder} class.
+# @keyparam html Predefine HTML entities.  This flag is not supported
+#     by the current implementation.
+# @keyparam encoding Optional encoding.  If given, the value overrides
+#     the encoding specified in the XML file.
+# @see #ElementTree
+# @see #TreeBuilder
+
+class XMLParser(object):
+
+    def __init__(self, html=0, target=None, encoding=None):
+        try:
+            from xml.parsers import expat
+        except ImportError:
+            try:
+                import pyexpat as expat
+            except ImportError:
+                raise ImportError(
+                    "No module named expat; use SimpleXMLTreeBuilder instead"
+                    )
+        parser = expat.ParserCreate(encoding, "}")
+        if target is None:
+            target = TreeBuilder()
+        # underscored names are provided for compatibility only
+        self.parser = self._parser = parser
+        self.target = self._target = target
+        self._error = expat.error
+        self._names = {} # name memo cache
+        # callbacks
+        parser.DefaultHandlerExpand = self._default
+        parser.StartElementHandler = self._start
+        parser.EndElementHandler = self._end
+        parser.CharacterDataHandler = self._data
+        # optional callbacks
+        parser.CommentHandler = self._comment
+        parser.ProcessingInstructionHandler = self._pi
+        # let expat do the buffering, if supported
+        try:
+            self._parser.buffer_text = 1
+        except AttributeError:
+            pass
+        # use new-style attribute handling, if supported
+        try:
+            self._parser.ordered_attributes = 1
+            self._parser.specified_attributes = 1
+            parser.StartElementHandler = self._start_list
+        except AttributeError:
+            pass
+        self._doctype = None
+        self.entity = {}
+        try:
+            self.version = "Expat %d.%d.%d" % expat.version_info
+        except AttributeError:
+            pass # unknown
+
+    def _raiseerror(self, value):
+        err = ParseError(value)
+        err.code = value.code
+        err.position = value.lineno, value.offset
+        raise err
+
+    def _fixtext(self, text):
+        # convert text string to ascii, if possible
+        try:
+            return text.encode("ascii")
+        except UnicodeError:
+            return text
+
+    def _fixname(self, key):
+        # expand qname, and convert name string to ascii, if possible
+        try:
+            name = self._names[key]
+        except KeyError:
+            name = key
+            if "}" in name:
+                name = "{" + name
+            self._names[key] = name = self._fixtext(name)
+        return name
+
+    def _start(self, tag, attrib_in):
+        fixname = self._fixname
+        fixtext = self._fixtext
+        tag = fixname(tag)
+        attrib = {}
+        for key, value in attrib_in.items():
+            attrib[fixname(key)] = fixtext(value)
+        return self.target.start(tag, attrib)
+
+    def _start_list(self, tag, attrib_in):
+        fixname = self._fixname
+        fixtext = self._fixtext
+        tag = fixname(tag)
+        attrib = {}
+        if attrib_in:
+            for i in range(0, len(attrib_in), 2):
+                attrib[fixname(attrib_in[i])] = fixtext(attrib_in[i+1])
+        return self.target.start(tag, attrib)
+
+    def _data(self, text):
+        return self.target.data(self._fixtext(text))
+
+    def _end(self, tag):
+        return self.target.end(self._fixname(tag))
+
+    def _comment(self, data):
+        try:
+            comment = self.target.comment
+        except AttributeError:
+            pass
+        else:
+            return comment(self._fixtext(data))
+
+    def _pi(self, target, data):
+        try:
+            pi = self.target.pi
+        except AttributeError:
+            pass
+        else:
+            return pi(self._fixtext(target), self._fixtext(data))
+
+    def _default(self, text):
+        prefix = text[:1]
+        if prefix == "&":
+            # deal with undefined entities
+            try:
+                self.target.data(self.entity[text[1:-1]])
+            except KeyError:
+                from xml.parsers import expat
+                err = expat.error(
+                    "undefined entity %s: line %d, column %d" %
+                    (text, self._parser.ErrorLineNumber,
+                    self._parser.ErrorColumnNumber)
+                    )
+                err.code = 11 # XML_ERROR_UNDEFINED_ENTITY
+                err.lineno = self._parser.ErrorLineNumber
+                err.offset = self._parser.ErrorColumnNumber
+                raise err
+        elif prefix == "<" and text[:9] == "<!DOCTYPE":
+            self._doctype = [] # inside a doctype declaration
+        elif self._doctype is not None:
+            # parse doctype contents
+            if prefix == ">":
+                self._doctype = None
+                return
+            text = text.strip()
+            if not text:
+                return
+            self._doctype.append(text)
+            n = len(self._doctype)
+            if n > 2:
+                type = self._doctype[1]
+                if type == "PUBLIC" and n == 4:
+                    name, type, pubid, system = self._doctype
+                elif type == "SYSTEM" and n == 3:
+                    name, type, system = self._doctype
+                    pubid = None
+                else:
+                    return
+                if pubid:
+                    pubid = pubid[1:-1]
+                if hasattr(self.target, "doctype"):
+                    self.target.doctype(name, pubid, system[1:-1])
+                elif self.doctype is not self._XMLParser__doctype:
+                    # warn about deprecated call
+                    self._XMLParser__doctype(name, pubid, system[1:-1])
+                    self.doctype(name, pubid, system[1:-1])
+                self._doctype = None
+
+    ##
+    # (Deprecated) Handles a doctype declaration.
+    #
+    # @param name Doctype name.
+    # @param pubid Public identifier.
+    # @param system System identifier.
+
+    def doctype(self, name, pubid, system):
+        """This method of XMLParser is deprecated."""
+        warnings.warn(
+            "This method of XMLParser is deprecated.  Define doctype() "
+            "method on the TreeBuilder target.",
+            DeprecationWarning,
+            )
+
+    # sentinel, if doctype is redefined in a subclass
+    __doctype = doctype
+
+    ##
+    # Feeds data to the parser.
+    #
+    # @param data Encoded data.
+
+    def feed(self, data):
+        try:
+            self._parser.Parse(data, 0)
+        except self._error, v:
+            self._raiseerror(v)
+
+    ##
+    # Finishes feeding data to the parser.
+    #
+    # @return An element structure.
+    # @defreturn Element
+
+    def close(self):
+        try:
+            self._parser.Parse("", 1) # end of data
+        except self._error, v:
+            self._raiseerror(v)
+        tree = self.target.close()
+        del self.target, self._parser # get rid of circular references
+        return tree
+
+# compatibility
+XMLTreeBuilder = XMLParser
+
+# workaround circular import.
+try:
+    from ElementC14N import _serialize_c14n
+    _serialize["c14n"] = _serialize_c14n
+except ImportError:
+    pass
diff --git a/src/main/resources/PythonLibs/xml/etree/__init__.py b/src/main/resources/PythonLibs/xml/etree/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..27fd8f6d4e36029830517a8884fac7da56d25eb7
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/etree/__init__.py
@@ -0,0 +1,33 @@
+# $Id: __init__.py 3375 2008-02-13 08:05:08Z fredrik $
+# elementtree package
+
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2008 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
diff --git a/src/main/resources/PythonLibs/xml/etree/cElementTree.py b/src/main/resources/PythonLibs/xml/etree/cElementTree.py
new file mode 100644
index 0000000000000000000000000000000000000000..cad55e8d0227701df58d225136c6848e5b306687
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/etree/cElementTree.py
@@ -0,0 +1,11 @@
+# make an exact copy of ElementTree's namespace here to support even
+# private API usage
+from xml.etree.ElementTree import (
+    Comment, Element, ElementPath, ElementTree, PI, ParseError,
+    ProcessingInstruction, QName, SubElement, TreeBuilder, VERSION, XML, XMLID,
+    XMLParser, XMLTreeBuilder, _Element, _ElementInterface, _SimpleElementPath,
+    __all__, __doc__, __file__, __name__, __package__, _encode,
+    _escape_attrib, _escape_cdata, _namespace_map,
+    _raise_serialization_error, dump, fromstring, fromstringlist,
+    iselement, iterparse, parse, re, register_namespace, sys, tostring,
+    tostringlist)
diff --git a/src/main/resources/PythonLibs/xml/parsers/__init__.py b/src/main/resources/PythonLibs/xml/parsers/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/main/resources/PythonLibs/xml/parsers/expat.py b/src/main/resources/PythonLibs/xml/parsers/expat.py
new file mode 100644
index 0000000000000000000000000000000000000000..31b432304f23a9817232938d0696d841894e3c2c
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/parsers/expat.py
@@ -0,0 +1,606 @@
+# coding: utf-8
+
+#------------------------------------------------------------------------------
+# Copyright (c) 2008 Sébastien Boisgérault
+#
+# 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.
+# -----------------------------------------------------------------------------
+
+__all__ = ["ExpatError", "ParserCreate", "XMLParserType", "error", "errors"]
+
+# Jython check
+import sys
+if not sys.platform.startswith('java'):
+    raise ImportError("this version of expat requires the jython interpreter")
+
+# Standard Python Library
+import re
+import types
+
+# Jython
+from org.python.core import Py
+from org.python.core.util import StringUtil
+from jarray import array
+
+# Java Standard Edition
+from java.io import ByteArrayInputStream
+from java.lang import String, StringBuilder
+from org.xml.sax import InputSource
+from org.xml.sax import SAXNotRecognizedException, SAXParseException
+from org.xml.sax.helpers import XMLReaderFactory
+from org.xml.sax.ext import DefaultHandler2
+
+# Xerces
+_mangled_xerces_parser_name = "org.python.apache.xerces.parsers.SAXParser"
+_xerces_parser_name = "org.apache.xerces.parsers.SAXParser"
+
+
+# @expat args registry
+_register = {}
+
+
+def ParserCreate(encoding=None, namespace_separator=None):
+    return XMLParser(encoding, namespace_separator)
+
+
+class XMLParser(object):
+
+    def __init__(self, encoding, namespace_separator):
+        self.encoding = encoding
+        self.CurrentLineNumber = 1
+        self.CurrentColumnNumber = 0
+        self._NextLineNumber = 1
+        self._NextColumnNumber = 0
+        self.ErrorLineNumber = -1
+        self.ErrorColumnNumber = -1
+        self.ErrorCode = None
+
+        if namespace_separator is None:
+            self.namespace_separator = namespace_separator
+        elif isinstance(namespace_separator, basestring):
+            self.namespace_separator = str(namespace_separator)
+            if len(self.namespace_separator) > 1:
+                error = ("namespace_separator must be at most one character, "
+                         "omitted, or None")
+                raise ValueError(error)
+        else:
+            error = ("ParserCreate() argument 2 must be string or None, "
+                     "not %s" % type(namespace_separator).__name__)
+            raise TypeError(error)
+
+        # See http://bugs.jython.org/issue1537
+        try:
+            self._reader = XMLReaderFactory.createXMLReader(_mangled_xerces_parser_name)
+        except:
+            self._reader = XMLReaderFactory.createXMLReader(_xerces_parser_name)
+
+        if self.namespace_separator is None:
+            try:
+                feature = "http://xml.org/sax/features/namespaces"
+                self._reader.setFeature(feature, False)
+            except SAXNotRecognizedException:
+                error = ("namespace support cannot be disabled; "
+                         "set namespace_separator to a string of length 1.")
+                raise ValueError(error)
+
+        self._base = None
+        self._buffer_text = True
+        self._returns_unicode = True
+
+        self._data = StringBuilder()
+
+        self._handler = XMLEventHandler(self)
+        self._reader.setContentHandler(self._handler)
+        self._reader.setErrorHandler(self._handler)
+        self._reader.setDTDHandler(self._handler)
+        self._reader.setEntityResolver(self._handler)
+
+        sax_properties = ("lexical-handler", "declaration-handler")
+        for name in sax_properties:
+            try:
+                name = "http://xml.org/sax/properties/" + name
+                self._reader.setProperty(name, self._handler)
+            except SAXNotRecognizedException:
+                error = "can't set property %r" % name
+                raise NotImplementedError(error)
+
+        apache_features = (("nonvalidating/load-external-dtd", False),)
+        for name, value in apache_features:
+            try:
+                name = "http://apache.org/xml/features/" + name
+                self._reader.setFeature(name, value)
+            except SAXNotRecognizedException:
+                error = "can't set feature %r" % name
+                raise NotImplementedError(error)
+
+        # experimental
+        #f = "http://xml.org/sax/features/external-general-entities"
+        f = "http://xml.org/sax/features/external-parameter-entities"
+        #self._reader.setFeature(f, False)
+
+        # check
+        f = "http://xml.org/sax/features/use-entity-resolver2"
+        assert self._reader.getFeature(f)
+
+    def GetBase(self):
+        return self._base
+
+    def SetBase(self, base):
+        self._base = base
+
+    def _error(self, value=None):
+        raise AttributeError("'XMLParser' has no such attribute")
+
+    def _get_buffer_text(self):
+        return self._buffer_text
+
+    def _set_buffer_text(self, value):
+        self._buffer_text = bool(value)
+
+    def _get_returns_unicode(self):
+        return bool(self._returns_unicode)
+
+    def _set_returns_unicode(self, value):
+        self._returns_unicode = value
+
+    # 'ordered' and 'specified' attributes are not supported
+    ordered_attributes = property(_error, _error)
+    specified_attributes = property(_error, _error)
+    # any setting is allowed, but it won't make a difference
+    buffer_text = property(_get_buffer_text, _set_buffer_text)
+    # non-significant read-only values
+    buffer_used = property(lambda self: None)
+    buffer_size = property(lambda self: None)
+    # 'returns_unicode' attribute is properly supported
+    returns_unicode = property(_get_returns_unicode, _set_returns_unicode)
+
+    def _expat_error(self, sax_error):
+        sax_message = sax_error.getMessage()
+        pattern = 'The entity ".*" was referenced, but not declared\.'
+        if re.match(pattern, sax_message):
+            expat_message = "undefined entity: line %s, column %s" % \
+                            (self.ErrorLineNumber, self.ErrorColumnNumber)
+        else:
+            expat_message = sax_message
+        error = ExpatError(expat_message)
+        error.lineno = self.ErrorLineNumber
+        error.offset = self.ErrorColumnNumber
+        error.code = self.ErrorCode
+        return error
+
+    def Parse(self, data, isfinal=False):
+        # The 'data' argument should be an encoded text: a str instance that
+        # represents an array of bytes. If instead it is a unicode string,
+        # only the us-ascii range is considered safe enough to be silently
+        # converted.
+        if isinstance(data, unicode):
+            data = data.encode(sys.getdefaultencoding())
+
+        self._data.append(data)
+
+        if isfinal:
+            bytes = StringUtil.toBytes(self._data.toString())
+            byte_stream = ByteArrayInputStream(bytes)
+            source = InputSource(byte_stream)
+            if self.encoding is not None:
+                source.setEncoding(self.encoding)
+            try:
+                self._reader.parse(source)
+            except SAXParseException, sax_error:
+                # Experiments tend to show that the '_Next*' parser locations
+                # match more closely expat behavior than the 'Current*' or sax
+                # error locations.
+                self.ErrorLineNumber = self._NextLineNumber
+                self.ErrorColumnNumber = self._NextColumnNumber
+                self.ErrorCode = None
+                raise self._expat_error(sax_error)
+            return 1
+
+    def ParseFile(self, file):
+        # TODO: pseudo-buffering if a read without argument is not supported.
+        #       document parse / parsefile usage.
+        return self.Parse(file.read(), isfinal=True)
+
+
+XMLParserType = XMLParser
+
+
+def _encode(arg, encoding):
+    if isinstance(arg, unicode):
+        return arg.encode(encoding)
+    else:
+        if isinstance(arg, dict):
+            iterator = arg.iteritems()
+        else:
+            iterator = iter(arg)
+        return type(arg)(_encode(_arg, encoding) for _arg in iterator)
+
+
+def expat(callback=None, guard=True, force=False, returns=None):
+    def _expat(method):
+        name = method.__name__
+        context = id(sys._getframe(1))
+        key = name, context
+        append = _register.setdefault(key, []).append
+        append((method, callback, guard, force, returns))
+
+        def new_method(*args):
+            self = args[0]
+            parser = self.parser
+            self._update_location(event=name) # bug if multiple method def
+            for (method, callback, guard, force, returns) in _register[key]:
+                if guard not in (True, False):
+                    guard = getattr(self, guard)
+                _callback = callback and guard and \
+                            getattr(parser, callback, None)
+                if _callback or force:
+                    results = method(*args)
+                    if _callback:
+                        if not isinstance(results, tuple):
+                            results = (results,)
+                        if not parser.returns_unicode:
+                            results = _encode(results, "utf-8")
+                        _callback(*results)
+                    return returns
+
+        new_method.__name__ = name
+        #new_method.__doc__ = method.__doc__ # what to do with multiple docs ?
+        return new_method
+    return _expat
+
+
+class XMLEventHandler(DefaultHandler2):
+
+    def __init__(self, parser):
+        self.parser = parser
+        self._tags = {}
+        self.not_in_dtd = True
+        self._entity = {}
+        self._previous_event = None
+
+    # --- Helpers -------------------------------------------------------------
+
+    def _intern(self, tag):
+        return self._tags.setdefault(tag, tag)
+
+    def _qualify(self, local_name, qname, namespace=None):
+        namespace_separator = self.parser.namespace_separator
+        if namespace_separator is None:
+            return qname
+        if not namespace:
+            return local_name
+        else:
+            return namespace + namespace_separator + local_name
+
+    def _char_slice_to_unicode(self, characters, start, length):
+        """Convert a char[] slice to a PyUnicode instance"""
+        text = Py.newUnicode(String(characters[start:start + length]))
+        return text
+
+    def _expat_content_model(self, name, model_):
+        # TODO : implement a model parser
+        return (name, model_) # does not fit expat conventions
+
+    def _update_location(self, event=None):
+        parser = self.parser
+        locator = self._locator
+
+        # ugly hack that takes care of a xerces-specific (?) locator issue:
+        # locate start and end elements at the '<' instead of the first tag
+        # type character.
+        if event == "startElement" and self._previous_event == "characters":
+            parser._NextColumnNumber = max(parser._NextColumnNumber - 1, 0)
+        if event == "endElement" and self._previous_event == "characters":
+            parser._NextColumnNumber = max(parser._NextColumnNumber - 2, 0)
+        # TODO: use the same trick to report accurate error locations ?
+
+        parser.CurrentLineNumber = parser._NextLineNumber
+        parser.CurrentColumnNumber = parser._NextColumnNumber
+        parser._NextLineNumber = locator.getLineNumber()
+        parser._NextColumnNumber = locator.getColumnNumber() - 1
+
+        self._previous_event = event
+
+    # --- ContentHandler Interface --------------------------------------------
+
+    @expat("ProcessingInstructionHandler")
+    def processingInstruction(self, target, data):
+        return target, data
+
+    @expat("StartElementHandler")
+    def startElement(self, namespace, local_name, qname, attributes):
+        tag = self._qualify(local_name, qname, namespace)
+        attribs = {}
+        length = attributes.getLength()
+        for index in range(length):
+            local_name = attributes.getLocalName(index)
+            qname = attributes.getQName(index)
+            namespace = attributes.getURI(index)
+            name = self._qualify(local_name, qname, namespace)
+            value = attributes.getValue(index)
+            attribs[name] = value
+        return self._intern(tag), attribs
+
+    @expat("EndElementHandler")
+    def endElement(self, namespace, local_name, qname):
+        return self._intern(self._qualify(local_name, qname, namespace))
+
+    @expat("CharacterDataHandler")
+    def characters(self, characters, start, length):
+        return self._char_slice_to_unicode(characters, start, length)
+
+    @expat("DefaultHandlerExpand")
+    def characters(self, characters, start, length):
+        return self._char_slice_to_unicode(characters, start, length)
+
+    @expat("DefaultHandler")
+    def characters(self, characters, start, length):
+        # TODO: make a helper function here
+        if self._entity["location"] == (self.parser.CurrentLineNumber,
+                                        self.parser.CurrentColumnNumber):
+            return "&%s;" % self._entity["name"]
+        else:
+            return self._char_slice_to_unicode(characters, start, length)
+
+    @expat("StartNamespaceDeclHandler")
+    def startPrefixMapping(self, prefix, uri):
+        return prefix, uri
+
+    @expat("EndNamespaceDeclHandler")
+    def endPrefixMapping(self, prefix):
+        return prefix
+
+    empty_source = InputSource(ByteArrayInputStream(array([], "b")))
+
+    @expat("ExternalEntityRefHandler", guard="not_in_dtd",
+                                       returns=empty_source)
+    def resolveEntity(self, name, publicId, baseURI, systemId):
+        context = name # wrong. see expat headers documentation.
+        base = self.parser.GetBase()
+        return context, base, systemId, publicId
+
+    @expat("DefaultHandlerExpand", guard="not_in_dtd",
+                                   returns=empty_source)
+    def resolveEntity(self, name, publicId, baseURI, systemId):
+        return "&%s;" % name
+
+    @expat("DefaultHandler", guard="not_in_dtd",
+                             returns=empty_source)
+    def resolveEntity(self, name, publicId, baseURI, systemId):
+        return "&%s;" % name
+
+    @expat(force=True, returns=empty_source)
+    def resolveEntity(self, name, publicId, baseURI, systemId):
+        pass
+
+    def setDocumentLocator(self, locator):
+        self._locator = locator
+
+    def skippedEntity(self, name):
+        error = ExpatError()
+        error.lineno = self.ErrorLineNumber = self.parser._NextLineNumber
+        error.offset = self.ErrorColumnNumber = self.parser._NextColumnNumber
+        error.code = self.ErrorCode = None
+        message = "undefined entity &%s;: line %s, column %s"
+        message = message % (name, error.lineno, error.offset)
+        error.__init__(message)
+        raise error
+
+    # --- LexicalHandler Interface --------------------------------------------
+
+    @expat("CommentHandler")
+    def comment(self, characters, start, length):
+        return self._char_slice_to_unicode(characters, start, length)
+
+    @expat("StartCdataSectionHandler")
+    def startCDATA(self):
+        return ()
+
+    @expat("EndCdataSectionHandler")
+    def endCDATA(self):
+        return ()
+
+    @expat("StartDoctypeDeclHandler", force=True)
+    def startDTD(self, name, publicId, systemId):
+        self.not_in_dtd = False
+        has_internal_subset = 0 # don't know this ...
+        return name, systemId, publicId, has_internal_subset
+
+    @expat("EndDoctypeDeclHandler", force=True)
+    def endDTD(self):
+        self.not_in_dtd = True
+
+    def startEntity(self, name):
+        self._entity = {}
+        self._entity["location"] = (self.parser._NextLineNumber,
+                                    self.parser._NextColumnNumber)
+        self._entity["name"] = name
+
+    def endEntity(self, name):
+        pass
+
+    # --- DTDHandler Interface ------------------------------------------------
+
+    @expat("NotationDeclHandler")
+    def notationDecl(self, name, publicId, systemId):
+        base = self.parser.GetBase()
+        return name, base, systemId, publicId
+
+    @expat("UnparsedEntityDeclHandler") # deprecated
+    def unparsedEntityDecl(self, name, publicId, systemId, notationName):
+        base = self.parser.GetBase()
+        return name, base, systemId, publicId, notationName
+
+    # --- DeclHandler Interface -----------------------------------------------
+
+    @expat("AttlistDeclHandler")
+    def attributeDecl(self, eName, aName, type, mode, value):
+        # TODO: adapt mode, required, etc.
+        required = False
+        return eName, aName, type, value, required
+
+    @expat("ElementDeclHandler")
+    def elementDecl(self, name, model):
+        return self._expat_content_model(name, model)
+
+    @expat("EntityDeclHandler")
+    def externalEntityDecl(self, name, publicId, systemId):
+        base = self.parser.GetBase()
+        value = None
+        is_parameter_entity = None
+        notation_name = None
+        return (name, is_parameter_entity, value, base, systemId, publicId,
+                notation_name)
+
+    @expat("EntityDeclHandler")
+    def internalEntityDecl(self, name, value):
+        base = self.parser.GetBase()
+        is_parameter_entity = None
+        notation_name = None
+        systemId, publicId = None, None
+        return (name, is_parameter_entity, value, base, systemId, publicId,
+                notation_name)
+
+
+def _init_model():
+    global model
+    model = types.ModuleType("pyexpat.model")
+    model.__doc__ = "Constants used to interpret content model information."
+    quantifiers = "NONE, OPT, REP, PLUS"
+    for i, quantifier in enumerate(quantifiers.split(", ")):
+        setattr(model, "XML_CQUANT_" + quantifier, i)
+    types_ = "EMPTY, ANY, MIXED, NAME, CHOICE, SEQ"
+    for i, type_ in enumerate(types_.split(", ")):
+        setattr(model, "XML_CTYPE_" + type_, i+1)
+
+_init_model()
+del _init_model
+
+
+class ExpatError(Exception):
+    pass
+
+
+error = ExpatError
+
+
+def _init_error_strings():
+    global ErrorString
+    error_strings = (
+        None,
+        "out of memory",
+        "syntax error",
+        "no element found",
+        "not well-formed (invalid token)",
+        "unclosed token",
+        "partial character",
+        "mismatched tag",
+        "duplicate attribute",
+        "junk after document element",
+        "illegal parameter entity reference",
+        "undefined entity",
+        "recursive entity reference",
+        "asynchronous entity",
+        "reference to invalid character number",
+        "reference to binary entity",
+        "reference to external entity in attribute",
+        "XML or text declaration not at start of entity",
+        "unknown encoding",
+        "encoding specified in XML declaration is incorrect",
+        "unclosed CDATA section",
+        "error in processing external entity reference",
+        "document is not standalone",
+        "unexpected parser state - please send a bug report",
+        "entity declared in parameter entity",
+        "requested feature requires XML_DTD support in Expat",
+        "cannot change setting once parsing has begun",
+        "unbound prefix",
+        "must not undeclare prefix",
+        "incomplete markup in parameter entity",
+        "XML declaration not well-formed",
+        "text declaration not well-formed",
+        "illegal character(s) in public id",
+        "parser suspended",
+        "parser not suspended",
+        "parsing aborted",
+        "parsing finished",
+        "cannot suspend in external parameter entity")
+    def ErrorString(code):
+        try:
+            return error_strings[code]
+        except IndexError:
+            return None
+
+_init_error_strings()
+del _init_error_strings
+
+
+def _init_errors():
+    global errors
+
+    errors = types.ModuleType("pyexpat.errors")
+    errors.__doc__ = "Constants used to describe error conditions."
+
+    error_names = """
+    XML_ERROR_NONE
+    XML_ERROR_NONE,
+    XML_ERROR_NO_MEMORY,
+    XML_ERROR_SYNTAX,
+    XML_ERROR_NO_ELEMENTS,
+    XML_ERROR_INVALID_TOKEN,
+    XML_ERROR_UNCLOSED_TOKEN,
+    XML_ERROR_PARTIAL_CHAR,
+    XML_ERROR_TAG_MISMATCH,
+    XML_ERROR_DUPLICATE_ATTRIBUTE,
+    XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+    XML_ERROR_PARAM_ENTITY_REF,
+    XML_ERROR_UNDEFINED_ENTITY,
+    XML_ERROR_RECURSIVE_ENTITY_REF,
+    XML_ERROR_ASYNC_ENTITY,
+    XML_ERROR_BAD_CHAR_REF,
+    XML_ERROR_BINARY_ENTITY_REF,
+    XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+    XML_ERROR_MISPLACED_XML_PI,
+    XML_ERROR_UNKNOWN_ENCODING,
+    XML_ERROR_INCORRECT_ENCODING,
+    XML_ERROR_UNCLOSED_CDATA_SECTION,
+    XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+    XML_ERROR_NOT_STANDALONE,
+    XML_ERROR_UNEXPECTED_STATE,
+    XML_ERROR_ENTITY_DECLARED_IN_PE,
+    XML_ERROR_FEATURE_REQUIRES_XML_DTD,
+    XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING,
+    XML_ERROR_UNBOUND_PREFIX,
+    XML_ERROR_UNDECLARING_PREFIX,
+    XML_ERROR_INCOMPLETE_PE,
+    XML_ERROR_XML_DECL,
+    XML_ERROR_TEXT_DECL,
+    XML_ERROR_PUBLICID,
+    XML_ERROR_SUSPENDED,
+    XML_ERROR_NOT_SUSPENDED,
+    XML_ERROR_ABORTED,
+    XML_ERROR_FINISHED,
+    XML_ERROR_SUSPEND_PE
+    """
+    error_names = [name.strip() for name in error_names.split(',')]
+    for i, name in enumerate(error_names[1:]):
+        setattr(errors, name, ErrorString(i+1))
+
+_init_errors()
+del _init_errors
diff --git a/src/main/resources/PythonLibs/xml/sax/__init__.py b/src/main/resources/PythonLibs/xml/sax/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..0606990e031c9802c30ae857088063df3dc0ac7c
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/sax/__init__.py
@@ -0,0 +1,102 @@
+"""Simple API for XML (SAX) implementation for Python.
+
+This module provides an implementation of the SAX 2 interface;
+information about the Java version of the interface can be found at
+http://www.megginson.com/SAX/.  The Python version of the interface is
+documented at <...>.
+
+This package contains the following modules:
+
+handler -- Base classes and constants which define the SAX 2 API for
+           the 'client-side' of SAX for Python.
+
+saxutils -- Implementation of the convenience classes commonly used to
+            work with SAX.
+
+xmlreader -- Base classes and constants which define the SAX 2 API for
+             the parsers used with SAX for Python.
+
+drivers2 -- Contains the driver for that wraps a Java sax implementation in python
+            objects.
+"""
+
+from xmlreader import InputSource
+from handler import ContentHandler, ErrorHandler
+from _exceptions import SAXException, SAXNotRecognizedException, \
+                        SAXParseException, SAXNotSupportedException, \
+                        SAXReaderNotAvailable
+
+
+def parse(source, handler, errorHandler=ErrorHandler()):
+    parser = make_parser()
+    parser.setContentHandler(handler)
+    parser.setErrorHandler(errorHandler)
+    parser.parse(source)
+
+def parseString(string, handler, errorHandler=ErrorHandler()):
+    try:
+        from cStringIO import StringIO
+    except ImportError:
+        from StringIO import StringIO
+
+    if errorHandler is None:
+        errorHandler = ErrorHandler()
+    parser = make_parser()
+    parser.setContentHandler(handler)
+    parser.setErrorHandler(errorHandler)
+
+    inpsrc = InputSource()
+    inpsrc.setByteStream(StringIO(string))
+    parser.parse(inpsrc)
+
+# this is the parser list used by the make_parser function if no
+# alternatives are given as parameters to the function
+
+default_parser_list = ["xml.sax.drivers2.drv_javasax"]
+
+# tell modulefinder that importing sax potentially imports expatreader
+_false = 0
+if _false:
+    import xml.sax.drivers2.drv_javasax
+
+import os, sys
+if os.environ.has_key("PY_SAX_PARSER"):
+    default_parser_list = os.environ["PY_SAX_PARSER"].split(",")
+del os
+
+_key = "python.xml.sax.parser"
+if sys.platform[:4] == "java" and sys.registry.containsKey(_key):
+    default_parser_list = sys.registry.getProperty(_key).split(",")
+
+
+def make_parser(parser_list = []):
+    """Creates and returns a SAX parser.
+
+    Creates the first parser it is able to instantiate of the ones
+    given in the list created by doing parser_list +
+    default_parser_list.  The lists must contain the names of Python
+    modules containing both a SAX parser and a create_parser function."""
+
+    for parser_name in parser_list + default_parser_list:
+        try:
+            return _create_parser(parser_name)
+        except ImportError,e:
+            import sys
+            if sys.modules.has_key(parser_name):
+                # The parser module was found, but importing it
+                # failed unexpectedly, pass this exception through
+                raise
+        except SAXReaderNotAvailable:
+            # The parser module detected that it won't work properly,
+            # so try the next one
+            pass
+
+    raise SAXReaderNotAvailable("No parsers found", None)
+
+# --- Internal utility methods used by make_parser
+
+def _create_parser(parser_name):
+    drv_module = __import__(parser_name,{},{},['create_parser'])
+    return drv_module.create_parser()
+
+del sys
diff --git a/src/main/resources/PythonLibs/xml/sax/_exceptions.py b/src/main/resources/PythonLibs/xml/sax/_exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d1cefead6ab94e8e02e7dd1e385f901629f584f
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/sax/_exceptions.py
@@ -0,0 +1,127 @@
+"""Different kinds of SAX Exceptions"""
+
+# ===== SAXEXCEPTION =====
+
+class SAXException(Exception):
+    """Encapsulate an XML error or warning. This class can contain
+    basic error or warning information from either the XML parser or
+    the application: you can subclass it to provide additional
+    functionality, or to add localization. Note that although you will
+    receive a SAXException as the argument to the handlers in the
+    ErrorHandler interface, you are not actually required to throw
+    the exception; instead, you can simply read the information in
+    it."""
+
+    def __init__(self, msg, exception=None):
+        """Creates an exception. The message is required, but the exception
+        is optional."""
+        self._msg = msg
+        self._exception = exception
+        Exception.__init__(self, msg)
+
+    def getMessage(self):
+        "Return a message for this exception."
+        return self._msg
+
+    def getException(self):
+        "Return the embedded exception, or None if there was none."
+        return self._exception
+
+    def __str__(self):
+        "Create a string representation of the exception."
+        return self._msg
+
+    def __getitem__(self, ix):
+        """Avoids weird error messages if someone does exception[ix] by
+        mistake, since Exception has __getitem__ defined."""
+        raise AttributeError("__getitem__")
+
+
+# ===== SAXPARSEEXCEPTION =====
+
+class SAXParseException(SAXException):
+    """Encapsulate an XML parse error or warning.
+
+    This exception will include information for locating the error in
+    the original XML document. Note that although the application will
+    receive a SAXParseException as the argument to the handlers in the
+    ErrorHandler interface, the application is not actually required
+    to throw the exception; instead, it can simply read the
+    information in it and take a different action.
+
+    Since this exception is a subclass of SAXException, it inherits
+    the ability to wrap another exception."""
+
+    def __init__(self, msg, exception, locator):
+        "Creates the exception. The exception parameter is allowed to be None."
+        SAXException.__init__(self, msg, exception)
+        self._locator = locator
+
+        # We need to cache this stuff at construction time.
+        # If this exception is thrown, the objects through which we must
+        # traverse to get this information may be deleted by the time
+        # it gets caught.
+        self._systemId = self._locator.getSystemId()
+        self._colnum = self._locator.getColumnNumber()
+        self._linenum = self._locator.getLineNumber()
+
+    def getColumnNumber(self):
+        """The column number of the end of the text where the exception
+        occurred."""
+        return self._colnum
+
+    def getLineNumber(self):
+        "The line number of the end of the text where the exception occurred."
+        return self._linenum
+
+    def getPublicId(self):
+        "Get the public identifier of the entity where the exception occurred."
+        return self._locator.getPublicId()
+
+    def getSystemId(self):
+        "Get the system identifier of the entity where the exception occurred."
+        return self._systemId
+
+    def __str__(self):
+        "Create a string representation of the exception."
+        sysid = self.getSystemId()
+        if sysid is None:
+            sysid = "<unknown>"
+        linenum = self.getLineNumber()
+        if linenum is None:
+            linenum = "?"
+        colnum = self.getColumnNumber()
+        if colnum is None:
+            colnum = "?"
+        return "%s:%s:%s: %s" % (sysid, linenum, colnum, self._msg)
+
+
+# ===== SAXNOTRECOGNIZEDEXCEPTION =====
+
+class SAXNotRecognizedException(SAXException):
+    """Exception class for an unrecognized identifier.
+
+    An XMLReader will raise this exception when it is confronted with an
+    unrecognized feature or property. SAX applications and extensions may
+    use this class for similar purposes."""
+
+
+# ===== SAXNOTSUPPORTEDEXCEPTION =====
+
+class SAXNotSupportedException(SAXException):
+    """Exception class for an unsupported operation.
+
+    An XMLReader will raise this exception when a service it cannot
+    perform is requested (specifically setting a state or value). SAX
+    applications and extensions may use this class for similar
+    purposes."""
+
+# ===== SAXNOTSUPPORTEDEXCEPTION =====
+
+class SAXReaderNotAvailable(SAXNotSupportedException):
+    """Exception class for a missing driver.
+
+    An XMLReader module (driver) should raise this exception when it
+    is first imported, e.g. when a support module cannot be imported.
+    It also may be raised during parsing, e.g. if executing an external
+    program is not permitted."""
diff --git a/src/main/resources/PythonLibs/xml/sax/drivers2/__init__.py b/src/main/resources/PythonLibs/xml/sax/drivers2/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..96a8f30ee0d3cab71389f7a4985c8a9f5aa1f5e0
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/sax/drivers2/__init__.py
@@ -0,0 +1 @@
+"Directory for SAX version 2 drivers."
diff --git a/src/main/resources/PythonLibs/xml/sax/drivers2/drv_javasax.py b/src/main/resources/PythonLibs/xml/sax/drivers2/drv_javasax.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec85c6fffeb641ce092da3eac68fc05ec936b8d1
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/sax/drivers2/drv_javasax.py
@@ -0,0 +1,382 @@
+"""
+SAX driver for the Java SAX parsers. Can only be used in Jython.
+
+$Id: drv_javasax.py,v 1.5 2003/01/26 09:08:51 loewis Exp $
+"""
+
+# --- Initialization
+
+version = "0.10"
+revision = "$Revision: 1.5 $"
+
+import string
+from xml.sax import xmlreader, saxutils
+from xml.sax.handler import feature_namespaces, feature_namespace_prefixes
+from xml.sax import _exceptions
+
+# we only work in jython
+import sys
+if sys.platform[:4] != "java":
+    raise _exceptions.SAXReaderNotAvailable("drv_javasax not available in CPython", None)
+del sys
+
+# get the necessary Java SAX classes
+try:
+    from org.python.core import FilelikeInputStream
+    from org.xml.sax.helpers import XMLReaderFactory
+    from org.xml import sax as javasax
+    from org.xml.sax.ext import LexicalHandler
+except ImportError:
+    raise _exceptions.SAXReaderNotAvailable("SAX is not on the classpath", None)
+
+# get some JAXP stuff
+try:
+    from javax.xml.parsers import SAXParserFactory, ParserConfigurationException
+    factory = SAXParserFactory.newInstance()
+    jaxp = 1
+except ImportError:
+    jaxp = 0
+
+from java.lang import String
+
+
+def _wrap_sax_exception(e):
+    return _exceptions.SAXParseException(e.message,
+                                         e.exception,
+                                         SimpleLocator(e.columnNumber,
+                                                              e.lineNumber,
+                                                              e.publicId,
+                                                              e.systemId))
+
+class JyErrorHandlerWrapper(javasax.ErrorHandler):
+    def __init__(self, err_handler):
+        self._err_handler = err_handler
+
+    def error(self, exc):
+        self._err_handler.error(_wrap_sax_exception(exc))
+
+    def fatalError(self, exc):
+        self._err_handler.fatalError(_wrap_sax_exception(exc))
+
+    def warning(self, exc):
+        self._err_handler.warning(_wrap_sax_exception(exc))
+
+class JyInputSourceWrapper(javasax.InputSource):
+    def __init__(self, source):
+        if isinstance(source, basestring):
+            javasax.InputSource.__init__(self, source)
+        elif hasattr(source, "read"):#file like object
+            f = source
+            javasax.InputSource.__init__(self, FilelikeInputStream(f))
+            if hasattr(f, "name"):
+                self.setSystemId(f.name)
+        else:#xml.sax.xmlreader.InputSource object
+            #Use byte stream constructor if possible so that Xerces won't attempt to open
+            #the url at systemId unless it's really there
+            if source.getByteStream():
+                javasax.InputSource.__init__(self,
+                                             FilelikeInputStream(source.getByteStream()))
+            else:
+                javasax.InputSource.__init__(self)
+            if source.getSystemId():
+                self.setSystemId(source.getSystemId())
+            self.setPublicId(source.getPublicId())
+            self.setEncoding(source.getEncoding())
+
+class JyEntityResolverWrapper(javasax.EntityResolver):
+    def __init__(self, entityResolver):
+        self._resolver = entityResolver
+
+    def resolveEntity(self, pubId, sysId):
+        return JyInputSourceWrapper(self._resolver.resolveEntity(pubId, sysId))
+
+class JyDTDHandlerWrapper(javasax.DTDHandler):
+    def __init__(self, dtdHandler):
+        self._handler = dtdHandler
+
+    def notationDecl(self, name, publicId, systemId):
+        self._handler.notationDecl(name, publicId, systemId)
+
+    def unparsedEntityDecl(self, name, publicId, systemId, notationName):
+        self._handler.unparsedEntityDecl(name, publicId, systemId, notationName)
+
+class SimpleLocator(xmlreader.Locator):
+    def __init__(self, colNum, lineNum, pubId, sysId):
+        self.colNum = colNum
+        self.lineNum = lineNum
+        self.pubId = pubId
+        self.sysId = sysId
+
+    def getColumnNumber(self):
+        return self.colNum
+
+    def getLineNumber(self):
+        return self.lineNum
+
+    def getPublicId(self):
+        return self.pubId
+
+    def getSystemId(self):
+        return self.sysId
+
+# --- JavaSAXParser
+class JavaSAXParser(xmlreader.XMLReader, javasax.ContentHandler, LexicalHandler):
+    "SAX driver for the Java SAX parsers."
+
+    def __init__(self, jdriver = None):
+        xmlreader.XMLReader.__init__(self)
+        self._parser = create_java_parser(jdriver)
+        self._parser.setFeature(feature_namespaces, 0)
+        self._parser.setFeature(feature_namespace_prefixes, 0)
+        self._parser.setContentHandler(self)
+        self._nsattrs = AttributesNSImpl()
+        self._attrs = AttributesImpl()
+        self.setEntityResolver(self.getEntityResolver())
+        self.setErrorHandler(self.getErrorHandler())
+        self.setDTDHandler(self.getDTDHandler())
+        try:
+            self._parser.setProperty("http://xml.org/sax/properties/lexical-handler", self)
+        except Exception, x:
+            pass
+
+    # XMLReader methods
+
+    def parse(self, source):
+        "Parse an XML document from a URL or an InputSource."
+        self._parser.parse(JyInputSourceWrapper(source))
+
+    def getFeature(self, name):
+        return self._parser.getFeature(name)
+
+    def setFeature(self, name, state):
+        self._parser.setFeature(name, state)
+
+    def getProperty(self, name):
+        return self._parser.getProperty(name)
+
+    def setProperty(self, name, value):
+        self._parser.setProperty(name, value)
+
+    def setEntityResolver(self, resolver):
+        self._parser.entityResolver = JyEntityResolverWrapper(resolver)
+        xmlreader.XMLReader.setEntityResolver(self, resolver)
+
+    def setErrorHandler(self, err_handler):
+        self._parser.errorHandler = JyErrorHandlerWrapper(err_handler)
+        xmlreader.XMLReader.setErrorHandler(self, err_handler)
+
+    def setDTDHandler(self, dtd_handler):
+        self._parser.setDTDHandler(JyDTDHandlerWrapper(dtd_handler))
+        xmlreader.XMLReader.setDTDHandler(self, dtd_handler)
+
+    # ContentHandler methods
+    def setDocumentLocator(self, locator):
+        self._cont_handler.setDocumentLocator(locator)
+
+    def startDocument(self):
+        self._cont_handler.startDocument()
+        self._namespaces = self._parser.getFeature(feature_namespaces)
+
+    def startElement(self, uri, lname, qname, attrs):
+        if self._namespaces:
+            self._nsattrs._attrs = attrs
+            self._cont_handler.startElementNS((uri or None, lname), qname,
+                                              self._nsattrs)
+        else:
+            self._attrs._attrs = attrs
+            self._cont_handler.startElement(qname, self._attrs)
+
+    def startPrefixMapping(self, prefix, uri):
+        self._cont_handler.startPrefixMapping(prefix, uri)
+
+    def characters(self, char, start, len):
+        self._cont_handler.characters(unicode(String(char, start, len)))
+
+    def ignorableWhitespace(self, char, start, len):
+        self._cont_handler.ignorableWhitespace(unicode(String(char, start,
+                                                              len)))
+
+    def endElement(self, uri, lname, qname):
+        if self._namespaces:
+            self._cont_handler.endElementNS((uri or None, lname), qname)
+        else:
+            self._cont_handler.endElement(qname)
+
+    def endPrefixMapping(self, prefix):
+        self._cont_handler.endPrefixMapping(prefix)
+
+    def endDocument(self):
+        self._cont_handler.endDocument()
+
+    def processingInstruction(self, target, data):
+        self._cont_handler.processingInstruction(target, data)
+
+    # Lexical handler methods
+    def comment(self, char, start, len):
+        try:
+            # Need to wrap this in a try..except in case the parser does not support lexical events
+            self._cont_handler.comment(unicode(String(char, start, len)))
+        except:
+            pass
+
+    def startCDATA(self):
+        pass # TODO
+
+    def endCDATA(self):
+        pass # TODO
+
+    def startDTD(self, name, publicId, systemId):
+        pass # TODO
+
+    def endDTD(self):
+        pass # TODO
+
+    def startEntity(self, name):
+        pass # TODO
+
+    def endEntity(self, name):
+        pass # TODO
+
+def _fixTuple(nsTuple, frm, to):
+    if isinstance(nsTuple, tuple) and len(nsTuple) == 2:
+        nsUri, localName = nsTuple
+        if nsUri == frm:
+            nsUri = to
+        return (nsUri, localName)
+    return nsTuple
+
+def _makeJavaNsTuple(nsTuple):
+    return _fixTuple(nsTuple, None, '')
+
+def _makePythonNsTuple(nsTuple):
+    return _fixTuple(nsTuple, '', None)
+
+class AttributesImpl:
+
+    def __init__(self, attrs = None):
+        self._attrs = attrs
+
+    def getLength(self):
+        return self._attrs.getLength()
+
+    def getType(self, name):
+        return self._attrs.getType(_makeJavaNsTuple(name))
+
+    def getValue(self, name):
+        value = self._attrs.getValue(_makeJavaNsTuple(name))
+        if value == None:
+            raise KeyError(name)
+        return value
+
+    def getNames(self):
+        return [_makePythonNsTuple(self._attrs.getQName(index)) for index in range(len(self))]
+
+    def getQNames(self):
+        return [self._attrs.getQName(index) for index in range(len(self))]
+
+    def getValueByQName(self, qname):
+        idx = self._attrs.getIndex(qname)
+        if idx == -1:
+            raise KeyError, qname
+        return self._attrs.getValue(idx)
+
+    def getNameByQName(self, qname):
+        idx = self._attrs.getIndex(qname)
+        if idx == -1:
+            raise KeyError, qname
+        return qname
+
+    def getQNameByName(self, name):
+        idx = self._attrs.getIndex(_makeJavaNsTuple(name))
+        if idx == -1:
+            raise KeyError, name
+        return name
+
+    def __len__(self):
+        return self._attrs.getLength()
+
+    def __getitem__(self, name):
+        return self.getValue(name)
+
+    def keys(self):
+        return self.getNames()
+
+    def copy(self):
+        return self.__class__(self._attrs)
+
+    def items(self):
+        return [(name, self[name]) for name in self.getNames()]
+
+    def values(self):
+        return map(self.getValue, self.getNames())
+
+    def get(self, name, alt=None):
+        try:
+            return self.getValue(name)
+        except KeyError:
+            return alt
+
+    def has_key(self, name):
+        try:
+            self.getValue(name)
+            return True
+        except KeyError:
+            return False
+
+# --- AttributesNSImpl
+
+class AttributesNSImpl(AttributesImpl):
+
+    def __init__(self, attrs=None):
+        AttributesImpl.__init__(self, attrs)
+
+    def getType(self, name):
+        name = _makeJavaNsTuple(name)
+        return self._attrs.getType(name[0], name[1])
+
+    def getValue(self, name):
+        jname = _makeJavaNsTuple(name)
+        value = self._attrs.getValue(jname[0], jname[1])
+        if value == None:
+            raise KeyError(name)
+        return value
+
+    def getNames(self):
+        names = []
+        for idx in range(len(self)):
+            names.append(_makePythonNsTuple( (self._attrs.getURI(idx), self._attrs.getLocalName(idx)) ))
+        return names
+
+    def getNameByQName(self, qname):
+        idx = self._attrs.getIndex(qname)
+        if idx == -1:
+            raise KeyError, qname
+        return _makePythonNsTuple( (self._attrs.getURI(idx), self._attrs.getLocalName(idx)) )
+
+    def getQNameByName(self, name):
+        name = _makeJavaNsTuple(name)
+        idx = self._attrs.getIndex(name[0], name[1])
+        if idx == -1:
+            raise KeyError, name
+        return self._attrs.getQName(idx)
+
+    def getQNames(self):
+        return [self._attrs.getQName(idx) for idx in range(len(self))]
+
+# ---
+
+def create_java_parser(jdriver = None):
+    try:
+        if jdriver:
+            return XMLReaderFactory.createXMLReader(jdriver)
+        elif jaxp:
+            return factory.newSAXParser().getXMLReader()
+        else:
+            return XMLReaderFactory.createXMLReader()
+    except ParserConfigurationException, e:
+        raise _exceptions.SAXReaderNotAvailable(e.getMessage())
+    except javasax.SAXException, e:
+        raise _exceptions.SAXReaderNotAvailable(e.getMessage())
+
+def create_parser(jdriver = None):
+    return JavaSAXParser(jdriver)
diff --git a/src/main/resources/PythonLibs/xml/sax/handler.py b/src/main/resources/PythonLibs/xml/sax/handler.py
new file mode 100644
index 0000000000000000000000000000000000000000..aff66e695535fd14a91360e65e01144789fe0bc3
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/sax/handler.py
@@ -0,0 +1,345 @@
+"""
+This module contains the core classes of version 2.0 of SAX for Python.
+This file provides only default classes with absolutely minimum
+functionality, from which drivers and applications can be subclassed.
+
+Many of these classes are empty and are included only as documentation
+of the interfaces.
+
+$Id: handler.py,v 1.5 2002/02/14 08:09:36 loewis Exp $
+"""
+
+version = '2.0beta'
+
+#============================================================================
+#
+# HANDLER INTERFACES
+#
+#============================================================================
+
+# ===== ERRORHANDLER =====
+
+class ErrorHandler:
+    """Basic interface for SAX error handlers.
+
+    If you create an object that implements this interface, then
+    register the object with your XMLReader, the parser will call the
+    methods in your object to report all warnings and errors. There
+    are three levels of errors available: warnings, (possibly)
+    recoverable errors, and unrecoverable errors. All methods take a
+    SAXParseException as the only parameter."""
+
+    def error(self, exception):
+        "Handle a recoverable error."
+        raise exception
+
+    def fatalError(self, exception):
+        "Handle a non-recoverable error."
+        raise exception
+
+    def warning(self, exception):
+        "Handle a warning."
+        print exception
+
+
+# ===== CONTENTHANDLER =====
+
+class ContentHandler:
+    """Interface for receiving logical document content events.
+
+    This is the main callback interface in SAX, and the one most
+    important to applications. The order of events in this interface
+    mirrors the order of the information in the document."""
+
+    def __init__(self):
+        self._locator = None
+
+    def setDocumentLocator(self, locator):
+        """Called by the parser to give the application a locator for
+        locating the origin of document events.
+
+        SAX parsers are strongly encouraged (though not absolutely
+        required) to supply a locator: if it does so, it must supply
+        the locator to the application by invoking this method before
+        invoking any of the other methods in the DocumentHandler
+        interface.
+
+        The locator allows the application to determine the end
+        position of any document-related event, even if the parser is
+        not reporting an error. Typically, the application will use
+        this information for reporting its own errors (such as
+        character content that does not match an application's
+        business rules). The information returned by the locator is
+        probably not sufficient for use with a search engine.
+
+        Note that the locator will return correct information only
+        during the invocation of the events in this interface. The
+        application should not attempt to use it at any other time."""
+        self._locator = locator
+
+    def startDocument(self):
+        """Receive notification of the beginning of a document.
+
+        The SAX parser will invoke this method only once, before any
+        other methods in this interface or in DTDHandler (except for
+        setDocumentLocator)."""
+
+    def endDocument(self):
+        """Receive notification of the end of a document.
+
+        The SAX parser will invoke this method only once, and it will
+        be the last method invoked during the parse. The parser shall
+        not invoke this method until it has either abandoned parsing
+        (because of an unrecoverable error) or reached the end of
+        input."""
+
+    def startPrefixMapping(self, prefix, uri):
+        """Begin the scope of a prefix-URI Namespace mapping.
+
+        The information from this event is not necessary for normal
+        Namespace processing: the SAX XML reader will automatically
+        replace prefixes for element and attribute names when the
+        http://xml.org/sax/features/namespaces feature is true (the
+        default).
+
+        There are cases, however, when applications need to use
+        prefixes in character data or in attribute values, where they
+        cannot safely be expanded automatically; the
+        start/endPrefixMapping event supplies the information to the
+        application to expand prefixes in those contexts itself, if
+        necessary.
+
+        Note that start/endPrefixMapping events are not guaranteed to
+        be properly nested relative to each-other: all
+        startPrefixMapping events will occur before the corresponding
+        startElement event, and all endPrefixMapping events will occur
+        after the corresponding endElement event, but their order is
+        not guaranteed."""
+
+    def endPrefixMapping(self, prefix):
+        """End the scope of a prefix-URI mapping.
+
+        See startPrefixMapping for details. This event will always
+        occur after the corresponding endElement event, but the order
+        of endPrefixMapping events is not otherwise guaranteed."""
+
+    def startElement(self, name, attrs):
+        """Signals the start of an element in non-namespace mode.
+
+        The name parameter contains the raw XML 1.0 name of the
+        element type as a string and the attrs parameter holds an
+        instance of the Attributes class containing the attributes of
+        the element."""
+
+    def endElement(self, name):
+        """Signals the end of an element in non-namespace mode.
+
+        The name parameter contains the name of the element type, just
+        as with the startElement event."""
+
+    def startElementNS(self, name, qname, attrs):
+        """Signals the start of an element in namespace mode.
+
+        The name parameter contains the name of the element type as a
+        (uri, localname) tuple, the qname parameter the raw XML 1.0
+        name used in the source document, and the attrs parameter
+        holds an instance of the Attributes class containing the
+        attributes of the element.
+
+        The uri part of the name tuple is None for elements which have
+        no namespace."""
+
+    def endElementNS(self, name, qname):
+        """Signals the end of an element in namespace mode.
+
+        The name parameter contains the name of the element type, just
+        as with the startElementNS event."""
+
+    def characters(self, content):
+        """Receive notification of character data.
+
+        The Parser will call this method to report each chunk of
+        character data. SAX parsers may return all contiguous
+        character data in a single chunk, or they may split it into
+        several chunks; however, all of the characters in any single
+        event must come from the same external entity so that the
+        Locator provides useful information."""
+
+    def ignorableWhitespace(self, whitespace):
+        """Receive notification of ignorable whitespace in element content.
+
+        Validating Parsers must use this method to report each chunk
+        of ignorable whitespace (see the W3C XML 1.0 recommendation,
+        section 2.10): non-validating parsers may also use this method
+        if they are capable of parsing and using content models.
+
+        SAX parsers may return all contiguous whitespace in a single
+        chunk, or they may split it into several chunks; however, all
+        of the characters in any single event must come from the same
+        external entity, so that the Locator provides useful
+        information.
+
+        The application must not attempt to read from the array
+        outside of the specified range."""
+
+    def processingInstruction(self, target, data):
+        """Receive notification of a processing instruction.
+
+        The Parser will invoke this method once for each processing
+        instruction found: note that processing instructions may occur
+        before or after the main document element.
+
+        A SAX parser should never report an XML declaration (XML 1.0,
+        section 2.8) or a text declaration (XML 1.0, section 4.3.1)
+        using this method."""
+
+    def skippedEntity(self, name):
+        """Receive notification of a skipped entity.
+
+        The Parser will invoke this method once for each entity
+        skipped. Non-validating processors may skip entities if they
+        have not seen the declarations (because, for example, the
+        entity was declared in an external DTD subset). All processors
+        may skip external entities, depending on the values of the
+        http://xml.org/sax/features/external-general-entities and the
+        http://xml.org/sax/features/external-parameter-entities
+        properties."""
+
+
+# ===== DTDHandler =====
+
+class DTDHandler:
+    """Handle DTD events.
+
+    This interface specifies only those DTD events required for basic
+    parsing (unparsed entities and attributes)."""
+
+    def notationDecl(self, name, publicId, systemId):
+        "Handle a notation declaration event."
+
+    def unparsedEntityDecl(self, name, publicId, systemId, ndata):
+        "Handle an unparsed entity declaration event."
+
+
+# ===== ENTITYRESOLVER =====
+
+class EntityResolver:
+    """Basic interface for resolving entities. If you create an object
+    implementing this interface, then register the object with your
+    Parser, the parser will call the method in your object to
+    resolve all external entities. Note that DefaultHandler implements
+    this interface with the default behaviour."""
+
+    def resolveEntity(self, publicId, systemId):
+        """Resolve the system identifier of an entity and return either
+        the system identifier to read from as a string, or an InputSource
+        to read from."""
+        return systemId
+
+
+#============================================================================
+#
+# CORE FEATURES
+#
+#============================================================================
+
+feature_namespaces = "http://xml.org/sax/features/namespaces"
+# true: Perform Namespace processing (default).
+# false: Optionally do not perform Namespace processing
+#        (implies namespace-prefixes).
+# access: (parsing) read-only; (not parsing) read/write
+
+feature_namespace_prefixes = "http://xml.org/sax/features/namespace-prefixes"
+# true: Report the original prefixed names and attributes used for Namespace
+#       declarations.
+# false: Do not report attributes used for Namespace declarations, and
+#        optionally do not report original prefixed names (default).
+# access: (parsing) read-only; (not parsing) read/write
+
+feature_string_interning = "http://xml.org/sax/features/string-interning"
+# true: All element names, prefixes, attribute names, Namespace URIs, and
+#       local names are interned using the built-in intern function.
+# false: Names are not necessarily interned, although they may be (default).
+# access: (parsing) read-only; (not parsing) read/write
+
+feature_validation = "http://xml.org/sax/features/validation"
+# true: Report all validation errors (implies external-general-entities and
+#       external-parameter-entities).
+# false: Do not report validation errors.
+# access: (parsing) read-only; (not parsing) read/write
+
+feature_external_ges = "http://xml.org/sax/features/external-general-entities"
+# true: Include all external general (text) entities.
+# false: Do not include external general entities.
+# access: (parsing) read-only; (not parsing) read/write
+
+feature_external_pes = "http://xml.org/sax/features/external-parameter-entities"
+# true: Include all external parameter entities, including the external
+#       DTD subset.
+# false: Do not include any external parameter entities, even the external
+#        DTD subset.
+# access: (parsing) read-only; (not parsing) read/write
+
+all_features = [feature_namespaces,
+                feature_namespace_prefixes,
+                feature_string_interning,
+                feature_validation,
+                feature_external_ges,
+                feature_external_pes]
+
+
+#============================================================================
+#
+# CORE PROPERTIES
+#
+#============================================================================
+
+property_lexical_handler = "http://xml.org/sax/properties/lexical-handler"
+# data type: xml.sax.sax2lib.LexicalHandler
+# description: An optional extension handler for lexical events like comments.
+# access: read/write
+
+property_declaration_handler = "http://xml.org/sax/properties/declaration-handler"
+# data type: xml.sax.sax2lib.DeclHandler
+# description: An optional extension handler for DTD-related events other
+#              than notations and unparsed entities.
+# access: read/write
+
+property_dom_node = "http://xml.org/sax/properties/dom-node"
+# data type: org.w3c.dom.Node
+# description: When parsing, the current DOM node being visited if this is
+#              a DOM iterator; when not parsing, the root DOM node for
+#              iteration.
+# access: (parsing) read-only; (not parsing) read/write
+
+property_xml_string = "http://xml.org/sax/properties/xml-string"
+# data type: String
+# description: The literal string of characters that was the source for
+#              the current event.
+# access: read-only
+
+property_encoding = "http://www.python.org/sax/properties/encoding"
+# data type: String
+# description: The name of the encoding to assume for input data.
+# access: write: set the encoding, e.g. established by a higher-level
+#                protocol. May change during parsing (e.g. after
+#                processing a META tag)
+#         read:  return the current encoding (possibly established through
+#                auto-detection.
+# initial value: UTF-8
+#
+
+property_interning_dict = "http://www.python.org/sax/properties/interning-dict"
+# data type: Dictionary
+# description: The dictionary used to intern common strings in the document
+# access: write: Request that the parser uses a specific dictionary, to
+#                allow interning across different documents
+#         read:  return the current interning dictionary, or None
+#
+
+all_properties = [property_lexical_handler,
+                  property_dom_node,
+                  property_declaration_handler,
+                  property_xml_string,
+                  property_encoding,
+                  property_interning_dict]
diff --git a/src/main/resources/PythonLibs/xml/sax/saxlib.py b/src/main/resources/PythonLibs/xml/sax/saxlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..64603799d0ba1ed9f8e195043113dabd6066972b
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/sax/saxlib.py
@@ -0,0 +1,430 @@
+"""
+This module contains the core classes of version 2.0 of SAX for Python.
+This file provides only default classes with absolutely minimum
+functionality, from which drivers and applications can be subclassed.
+
+Many of these classes are empty and are included only as documentation
+of the interfaces.
+
+$Id: saxlib.py,v 1.12 2002/05/10 14:49:21 akuchling Exp $
+"""
+
+version = '2.0beta'
+
+# A number of interfaces used to live in saxlib, but are now in
+# various other modules for Python 2 compatibility. If nobody uses
+# them here any longer, the references can be removed
+
+from handler import ErrorHandler, ContentHandler, DTDHandler, EntityResolver
+from xmlreader import XMLReader, InputSource, Locator, IncrementalParser
+from _exceptions import *
+
+from handler import \
+     feature_namespaces,\
+     feature_namespace_prefixes,\
+     feature_string_interning,\
+     feature_validation,\
+     feature_external_ges,\
+     feature_external_pes,\
+     all_features,\
+     property_lexical_handler,\
+     property_declaration_handler,\
+     property_dom_node,\
+     property_xml_string,\
+     all_properties
+
+#============================================================================
+#
+# MAIN INTERFACES
+#
+#============================================================================
+
+# ===== XMLFILTER =====
+
+class XMLFilter(XMLReader):
+    """Interface for a SAX2 parser filter.
+
+    A parser filter is an XMLReader that gets its events from another
+    XMLReader (which may in turn also be a filter) rather than from a
+    primary source like a document or other non-SAX data source.
+    Filters can modify a stream of events before passing it on to its
+    handlers."""
+
+    def __init__(self, parent = None):
+        """Creates a filter instance, allowing applications to set the
+        parent on instantiation."""
+        XMLReader.__init__(self)
+        self._parent = parent
+
+    def setParent(self, parent):
+        """Sets the parent XMLReader of this filter. The argument may
+        not be None."""
+        self._parent = parent
+
+    def getParent(self):
+        "Returns the parent of this filter."
+        return self._parent
+
+# ===== ATTRIBUTES =====
+
+class Attributes:
+    """Interface for a list of XML attributes.
+
+    Contains a list of XML attributes, accessible by name."""
+
+    def getLength(self):
+        "Returns the number of attributes in the list."
+        raise NotImplementedError("This method must be implemented!")
+
+    def getType(self, name):
+        "Returns the type of the attribute with the given name."
+        raise NotImplementedError("This method must be implemented!")
+
+    def getValue(self, name):
+        "Returns the value of the attribute with the given name."
+        raise NotImplementedError("This method must be implemented!")
+
+    def getValueByQName(self, name):
+        """Returns the value of the attribute with the given raw (or
+        qualified) name."""
+        raise NotImplementedError("This method must be implemented!")
+
+    def getNameByQName(self, name):
+        """Returns the namespace name of the attribute with the given
+        raw (or qualified) name."""
+        raise NotImplementedError("This method must be implemented!")
+
+    def getNames(self):
+        """Returns a list of the names of all attributes
+        in the list."""
+        raise NotImplementedError("This method must be implemented!")
+
+    def getQNames(self):
+        """Returns a list of the raw qualified names of all attributes
+        in the list."""
+        raise NotImplementedError("This method must be implemented!")
+
+    def __len__(self):
+        "Alias for getLength."
+        raise NotImplementedError("This method must be implemented!")
+
+    def __getitem__(self, name):
+        "Alias for getValue."
+        raise NotImplementedError("This method must be implemented!")
+
+    def keys(self):
+        "Returns a list of the attribute names in the list."
+        raise NotImplementedError("This method must be implemented!")
+
+    def has_key(self, name):
+        "True if the attribute is in the list, false otherwise."
+        raise NotImplementedError("This method must be implemented!")
+
+    def get(self, name, alternative=None):
+        """Return the value associated with attribute name; if it is not
+        available, then return the alternative."""
+        raise NotImplementedError("This method must be implemented!")
+
+    def copy(self):
+        "Return a copy of the Attributes object."
+        raise NotImplementedError("This method must be implemented!")
+
+    def items(self):
+        "Return a list of (attribute_name, value) pairs."
+        raise NotImplementedError("This method must be implemented!")
+
+    def values(self):
+        "Return a list of all attribute values."
+        raise NotImplementedError("This method must be implemented!")
+
+
+#============================================================================
+#
+# HANDLER INTERFACES
+#
+#============================================================================
+
+
+# ===== DECLHANDLER =====
+
+class DeclHandler:
+    """Optional SAX2 handler for DTD declaration events.
+
+    Note that some DTD declarations are already reported through the
+    DTDHandler interface. All events reported to this handler will
+    occur between the startDTD and endDTD events of the
+    LexicalHandler.
+
+    To set the DeclHandler for an XMLReader, use the setProperty method
+    with the identifier http://xml.org/sax/handlers/DeclHandler."""
+
+    def attributeDecl(self, elem_name, attr_name, type, value_def, value):
+        """Report an attribute type declaration.
+
+        Only the first declaration will be reported. The type will be
+        one of the strings "CDATA", "ID", "IDREF", "IDREFS",
+        "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", or "NOTATION", or
+        a list of names (in the case of enumerated definitions).
+
+        elem_name is the element type name, attr_name the attribute
+        type name, type a string representing the attribute type,
+        value_def a string representing the default declaration
+        ('#IMPLIED', '#REQUIRED', '#FIXED' or None). value is a string
+        representing the attribute's default value, or None if there
+        is none."""
+
+    def elementDecl(self, elem_name, content_model):
+        """Report an element type declaration.
+
+        Only the first declaration will be reported.
+
+        content_model is the string 'EMPTY', the string 'ANY' or the content
+        model structure represented as tuple (separator, tokens, modifier)
+        where separator is the separator in the token list (that is, '|' or
+        ','), tokens is the list of tokens (element type names or tuples
+        representing parentheses) and modifier is the quantity modifier
+        ('*', '?' or '+')."""
+
+    def internalEntityDecl(self, name, value):
+        """Report an internal entity declaration.
+
+        Only the first declaration of an entity will be reported.
+
+        name is the name of the entity. If it is a parameter entity,
+        the name will begin with '%'. value is the replacement text of
+        the entity."""
+
+    def externalEntityDecl(self, name, public_id, system_id):
+        """Report a parsed entity declaration. (Unparsed entities are
+        reported to the DTDHandler.)
+
+        Only the first declaration for each entity will be reported.
+
+        name is the name of the entity. If it is a parameter entity,
+        the name will begin with '%'. public_id and system_id are the
+        public and system identifiers of the entity. public_id will be
+        None if none were declared."""
+
+
+
+# ===== LEXICALHANDLER =====
+
+class LexicalHandler:
+    """Optional SAX2 handler for lexical events.
+
+    This handler is used to obtain lexical information about an XML
+    document, that is, information about how the document was encoded
+    (as opposed to what it contains, which is reported to the
+    ContentHandler), such as comments and CDATA marked section
+    boundaries.
+
+    To set the LexicalHandler of an XMLReader, use the setProperty
+    method with the property identifier
+    'http://xml.org/sax/handlers/LexicalHandler'. There is no
+    guarantee that the XMLReader will support or recognize this
+    property."""
+
+    def comment(self, content):
+        """Reports a comment anywhere in the document (including the
+        DTD and outside the document element).
+
+        content is a string that holds the contents of the comment."""
+
+    def startDTD(self, name, public_id, system_id):
+        """Report the start of the DTD declarations, if the document
+        has an associated DTD.
+
+        A startEntity event will be reported before declaration events
+        from the external DTD subset are reported, and this can be
+        used to infer from which subset DTD declarations derive.
+
+        name is the name of the document element type, public_id the
+        public identifier of the DTD (or None if none were supplied)
+        and system_id the system identfier of the external subset (or
+        None if none were supplied)."""
+
+    def endDTD(self):
+        "Signals the end of DTD declarations."
+
+    def startEntity(self, name):
+        """Report the beginning of an entity.
+
+        The start and end of the document entity is not reported. The
+        start and end of the external DTD subset is reported with the
+        pseudo-name '[dtd]'.
+
+        Skipped entities will be reported through the skippedEntity
+        event of the ContentHandler rather than through this event.
+
+        name is the name of the entity. If it is a parameter entity,
+        the name will begin with '%'."""
+
+    def endEntity(self, name):
+        """Reports the end of an entity. name is the name of the
+        entity, and follows the same conventions as for
+        startEntity."""
+
+    def startCDATA(self):
+        """Reports the beginning of a CDATA marked section.
+
+        The contents of the CDATA marked section will be reported
+        through the characters event."""
+
+    def endCDATA(self):
+        "Reports the end of a CDATA marked section."
+
+
+#============================================================================
+#
+# SAX 1.0 COMPATIBILITY CLASSES
+# Note that these are all deprecated.
+#
+#============================================================================
+
+# ===== ATTRIBUTELIST =====
+
+class AttributeList:
+    """Interface for an attribute list. This interface provides
+    information about a list of attributes for an element (only
+    specified or defaulted attributes will be reported). Note that the
+    information returned by this object will be valid only during the
+    scope of the DocumentHandler.startElement callback, and the
+    attributes will not necessarily be provided in the order declared
+    or specified."""
+
+    def getLength(self):
+        "Return the number of attributes in list."
+
+    def getName(self, i):
+        "Return the name of an attribute in the list."
+
+    def getType(self, i):
+        """Return the type of an attribute in the list. (Parameter can be
+        either integer index or attribute name.)"""
+
+    def getValue(self, i):
+        """Return the value of an attribute in the list. (Parameter can be
+        either integer index or attribute name.)"""
+
+    def __len__(self):
+        "Alias for getLength."
+
+    def __getitem__(self, key):
+        "Alias for getName (if key is an integer) and getValue (if string)."
+
+    def keys(self):
+        "Returns a list of the attribute names."
+
+    def has_key(self, key):
+        "True if the attribute is in the list, false otherwise."
+
+    def get(self, key, alternative=None):
+        """Return the value associated with attribute name; if it is not
+        available, then return the alternative."""
+
+    def copy(self):
+        "Return a copy of the AttributeList."
+
+    def items(self):
+        "Return a list of (attribute_name,value) pairs."
+
+    def values(self):
+        "Return a list of all attribute values."
+
+
+# ===== DOCUMENTHANDLER =====
+
+class DocumentHandler:
+    """Handle general document events. This is the main client
+    interface for SAX: it contains callbacks for the most important
+    document events, such as the start and end of elements. You need
+    to create an object that implements this interface, and then
+    register it with the Parser. If you do not want to implement
+    the entire interface, you can derive a class from HandlerBase,
+    which implements the default functionality. You can find the
+    location of any document event using the Locator interface
+    supplied by setDocumentLocator()."""
+
+    def characters(self, ch, start, length):
+        "Handle a character data event."
+
+    def endDocument(self):
+        "Handle an event for the end of a document."
+
+    def endElement(self, name):
+        "Handle an event for the end of an element."
+
+    def ignorableWhitespace(self, ch, start, length):
+        "Handle an event for ignorable whitespace in element content."
+
+    def processingInstruction(self, target, data):
+        "Handle a processing instruction event."
+
+    def setDocumentLocator(self, locator):
+        "Receive an object for locating the origin of SAX document events."
+
+    def startDocument(self):
+        "Handle an event for the beginning of a document."
+
+    def startElement(self, name, atts):
+        "Handle an event for the beginning of an element."
+
+
+# ===== HANDLERBASE =====
+
+class HandlerBase(EntityResolver, DTDHandler, DocumentHandler,\
+                     ErrorHandler):
+    """Default base class for handlers. This class implements the
+    default behaviour for four SAX interfaces: EntityResolver,
+    DTDHandler, DocumentHandler, and ErrorHandler: rather
+    than implementing those full interfaces, you may simply extend
+    this class and override the methods that you need. Note that the
+    use of this class is optional (you are free to implement the
+    interfaces directly if you wish)."""
+
+
+# ===== PARSER =====
+
+class Parser:
+    """Basic interface for SAX (Simple API for XML) parsers. All SAX
+    parsers must implement this basic interface: it allows users to
+    register handlers for different types of events and to initiate a
+    parse from a URI, a character stream, or a byte stream. SAX
+    parsers should also implement a zero-argument constructor."""
+
+    def __init__(self):
+        self.doc_handler = DocumentHandler()
+        self.dtd_handler = DTDHandler()
+        self.ent_handler = EntityResolver()
+        self.err_handler = ErrorHandler()
+
+    def parse(self, systemId):
+        "Parse an XML document from a system identifier."
+
+    def parseFile(self, fileobj):
+        "Parse an XML document from a file-like object."
+
+    def setDocumentHandler(self, handler):
+        "Register an object to receive basic document-related events."
+        self.doc_handler=handler
+
+    def setDTDHandler(self, handler):
+        "Register an object to receive basic DTD-related events."
+        self.dtd_handler=handler
+
+    def setEntityResolver(self, resolver):
+        "Register an object to resolve external entities."
+        self.ent_handler=resolver
+
+    def setErrorHandler(self, handler):
+        "Register an object to receive error-message events."
+        self.err_handler=handler
+
+    def setLocale(self, locale):
+        """Allow an application to set the locale for errors and warnings.
+
+        SAX parsers are not required to provide localisation for errors
+        and warnings; if they cannot support the requested locale,
+        however, they must throw a SAX exception. Applications may
+        request a locale change in the middle of a parse."""
+        raise SAXNotSupportedException("Locale support not implemented")
diff --git a/src/main/resources/PythonLibs/xml/sax/saxutils.py b/src/main/resources/PythonLibs/xml/sax/saxutils.py
new file mode 100644
index 0000000000000000000000000000000000000000..8d4ad9e90ae75ce77b98f2a6dc1f61eeea422fd5
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/sax/saxutils.py
@@ -0,0 +1,813 @@
+"""
+A library of useful helper classes to the saxlib classes, for the
+convenience of application and driver writers.
+
+$Id: saxutils.py,v 1.37 2005/04/13 14:02:08 syt Exp $
+"""
+import os, urlparse, urllib2, types
+import handler
+import xmlreader
+import sys, _exceptions, saxlib
+
+from xml.Uri import Absolutize, MakeUrllibSafe,IsAbsolute
+
+try:
+    _StringTypes = [types.StringType, types.UnicodeType]
+except AttributeError: # 1.5 compatibility:UnicodeType not defined
+    _StringTypes = [types.StringType]
+
+def __dict_replace(s, d):
+    """Replace substrings of a string using a dictionary."""
+    for key, value in d.items():
+        s = s.replace(key, value)
+    return s
+
+def escape(data, entities={}):
+    """Escape &, <, and > in a string of data.
+
+    You can escape other strings of data by passing a dictionary as
+    the optional entities parameter.  The keys and values must all be
+    strings; each key will be replaced with its corresponding value.
+    """
+    data = data.replace("&", "&amp;")
+    data = data.replace("<", "&lt;")
+    data = data.replace(">", "&gt;")
+    if entities:
+        data = __dict_replace(data, entities)
+    return data
+
+def unescape(data, entities={}):
+    """Unescape &amp;, &lt;, and &gt; in a string of data.
+
+    You can unescape other strings of data by passing a dictionary as
+    the optional entities parameter.  The keys and values must all be
+    strings; each key will be replaced with its corresponding value.
+    """
+    data = data.replace("&lt;", "<")
+    data = data.replace("&gt;", ">")
+    if entities:
+        data = __dict_replace(data, entities)
+    # must do ampersand last
+    return data.replace("&amp;", "&")
+
+def quoteattr(data, entities={}):
+    """Escape and quote an attribute value.
+
+    Escape &, <, and > in a string of data, then quote it for use as
+    an attribute value.  The \" character will be escaped as well, if
+    necessary.
+
+    You can escape other strings of data by passing a dictionary as
+    the optional entities parameter.  The keys and values must all be
+    strings; each key will be replaced with its corresponding value.
+    """
+    data = escape(data, entities)
+    if '"' in data:
+        if "'" in data:
+            data = '"%s"' % data.replace('"', "&quot;")
+        else:
+            data = "'%s'" % data
+    else:
+        data = '"%s"' % data
+    return data
+
+# --- DefaultHandler
+
+class DefaultHandler(handler.EntityResolver, handler.DTDHandler,
+                     handler.ContentHandler, handler.ErrorHandler):
+    """Default base class for SAX2 event handlers. Implements empty
+    methods for all callback methods, which can be overridden by
+    application implementors. Replaces the deprecated SAX1 HandlerBase
+    class."""
+
+# --- Location
+
+class Location:
+    """Represents a location in an XML entity. Initialized by being passed
+    a locator, from which it reads off the current location, which is then
+    stored internally."""
+
+    def __init__(self, locator):
+        self.__col = locator.getColumnNumber()
+        self.__line = locator.getLineNumber()
+        self.__pubid = locator.getPublicId()
+        self.__sysid = locator.getSystemId()
+
+    def getColumnNumber(self):
+        return self.__col
+
+    def getLineNumber(self):
+        return self.__line
+
+    def getPublicId(self):
+        return self.__pubid
+
+    def getSystemId(self):
+        return self.__sysid
+
+    def __str__(self):
+        if self.__line is None:
+            line = "?"
+        else:
+            line = self.__line
+        if self.__col is None:
+            col = "?"
+        else:
+            col = self.__col
+        return "%s:%s:%s" % (
+            self.__sysid or self.__pubid or "<unknown>",
+            line, col)
+
+# --- ErrorPrinter
+
+class ErrorPrinter:
+    "A simple class that just prints error messages to standard out."
+
+    def __init__(self, level=0, outfile=sys.stderr):
+        self._level = level
+        self._outfile = outfile
+
+    def warning(self, exception):
+        if self._level <= 0:
+            self._outfile.write("WARNING in %s: %s\n" %
+                               (self.__getpos(exception),
+                                exception.getMessage()))
+
+    def error(self, exception):
+        if self._level <= 1:
+            self._outfile.write("ERROR in %s: %s\n" %
+                               (self.__getpos(exception),
+                                exception.getMessage()))
+
+    def fatalError(self, exception):
+        if self._level <= 2:
+            self._outfile.write("FATAL ERROR in %s: %s\n" %
+                               (self.__getpos(exception),
+                                exception.getMessage()))
+
+    def __getpos(self, exception):
+        if isinstance(exception, _exceptions.SAXParseException):
+            return "%s:%s:%s" % (exception.getSystemId(),
+                                 exception.getLineNumber(),
+                                 exception.getColumnNumber())
+        else:
+            return "<unknown>"
+
+# --- ErrorRaiser
+
+class ErrorRaiser:
+    "A simple class that just raises the exceptions it is passed."
+
+    def __init__(self, level = 0):
+        self._level = level
+
+    def error(self, exception):
+        if self._level <= 1:
+            raise exception
+
+    def fatalError(self, exception):
+        if self._level <= 2:
+            raise exception
+
+    def warning(self, exception):
+        if self._level <= 0:
+            raise exception
+
+# --- AttributesImpl now lives in xmlreader
+from xmlreader import AttributesImpl
+
+# --- XMLGenerator is the SAX2 ContentHandler for writing back XML
+import codecs
+
+def _outputwrapper(stream,encoding):
+    writerclass = codecs.lookup(encoding)[3]
+    return writerclass(stream)
+
+if hasattr(codecs, "register_error"):
+    def writetext(stream, text, entities={}):
+        stream.errors = "xmlcharrefreplace"
+        stream.write(escape(text, entities))
+        stream.errors = "strict"
+else:
+    def writetext(stream, text, entities={}):
+        text = escape(text, entities)
+        try:
+            stream.write(text)
+        except UnicodeError:
+            for c in text:
+                try:
+                    stream.write(c)
+                except UnicodeError:
+                    stream.write("&#%d;" % ord(c))
+
+def writeattr(stream, text):
+    countdouble = text.count('"')
+    if countdouble:
+        countsingle = text.count("'")
+        if countdouble <= countsingle:
+            entities = {'"': "&quot;"}
+            quote = '"'
+        else:
+            entities = {"'": "&apos;"}
+            quote = "'"
+    else:
+        entities = {}
+        quote = '"'
+    stream.write(quote)
+    writetext(stream, text, entities)
+    stream.write(quote)
+
+
+class XMLGenerator(handler.ContentHandler):
+    GENERATED_PREFIX = "xml.sax.saxutils.prefix%s"
+
+    def __init__(self, out=None, encoding="iso-8859-1"):
+        if out is None:
+            import sys
+            out = sys.stdout
+        handler.ContentHandler.__init__(self)
+        self._out = _outputwrapper(out,encoding)
+        self._ns_contexts = [{}] # contains uri -> prefix dicts
+        self._current_context = self._ns_contexts[-1]
+        self._undeclared_ns_maps = []
+        self._encoding = encoding
+        self._generated_prefix_ctr = 0
+        return
+
+    # ContentHandler methods
+
+    def startDocument(self):
+        self._out.write('<?xml version="1.0" encoding="%s"?>\n' %
+                        self._encoding)
+
+    def startPrefixMapping(self, prefix, uri):
+        self._ns_contexts.append(self._current_context.copy())
+        self._current_context[uri] = prefix
+        self._undeclared_ns_maps.append((prefix, uri))
+
+    def endPrefixMapping(self, prefix):
+        self._current_context = self._ns_contexts[-1]
+        del self._ns_contexts[-1]
+
+    def startElement(self, name, attrs):
+        self._out.write('<' + name)
+        for (name, value) in attrs.items():
+            self._out.write(' %s=' % name)
+            writeattr(self._out, value)
+        self._out.write('>')
+
+    def endElement(self, name):
+        self._out.write('</%s>' % name)
+
+    def startElementNS(self, name, qname, attrs):
+        if name[0] is None:
+            name = name[1]
+        elif self._current_context[name[0]] is None:
+            # default namespace
+            name = name[1]
+        else:
+            name = self._current_context[name[0]] + ":" + name[1]
+        self._out.write('<' + name)
+
+        for k,v in self._undeclared_ns_maps:
+            if k is None:
+                self._out.write(' xmlns="%s"' % (v or ''))
+            else:
+                self._out.write(' xmlns:%s="%s"' % (k,v))
+        self._undeclared_ns_maps = []
+
+        for (name, value) in attrs.items():
+            if name[0] is None:
+                name = name[1]
+            elif self._current_context[name[0]] is None:
+                # default namespace
+                #If an attribute has a nsuri but not a prefix, we must
+                #create a prefix and add a nsdecl
+                prefix = self.GENERATED_PREFIX % self._generated_prefix_ctr
+                self._generated_prefix_ctr = self._generated_prefix_ctr + 1
+                name = prefix + ':' + name[1]
+                self._out.write(' xmlns:%s=%s' % (prefix, quoteattr(name[0])))
+                self._current_context[name[0]] = prefix
+            else:
+                name = self._current_context[name[0]] + ":" + name[1]
+            self._out.write(' %s=' % name)
+            writeattr(self._out, value)
+        self._out.write('>')
+
+    def endElementNS(self, name, qname):
+        # XXX: if qname is not None, we better use it.
+        # Python 2.0b2 requires us to use the recorded prefix for
+        # name[0], though
+        if name[0] is None:
+            qname = name[1]
+        elif self._current_context[name[0]] is None:
+            qname = name[1]
+        else:
+            qname = self._current_context[name[0]] + ":" + name[1]
+        self._out.write('</%s>' % qname)
+
+    def characters(self, content):
+        writetext(self._out, content)
+
+    def ignorableWhitespace(self, content):
+        self._out.write(content)
+
+    def processingInstruction(self, target, data):
+        self._out.write('<?%s %s?>' % (target, data))
+
+
+class LexicalXMLGenerator(XMLGenerator, saxlib.LexicalHandler):
+    """A XMLGenerator that also supports the LexicalHandler interface"""
+
+    def __init__(self, out=None, encoding="iso-8859-1"):
+        XMLGenerator.__init__(self, out, encoding)
+        self._in_cdata = 0
+
+    def characters(self, content):
+        if self._in_cdata:
+            self._out.write(content.replace(']]>', ']]>]]&gt;<![CDATA['))
+        else:
+            self._out.write(escape(content))
+
+    # LexicalHandler methods
+    # (we only support the most important ones and inherit the rest)
+
+    def startDTD(self, name, public_id, system_id):
+        self._out.write('<!DOCTYPE %s' % name)
+        if public_id:
+            self._out.write(' PUBLIC %s %s' % (
+                quoteattr(public_id or ""), quoteattr(system_id or "")
+            ))
+        elif system_id:
+            self._out.write(' SYSTEM %s' % quoteattr(system_id or ""))
+
+    def endDTD(self):
+        self._out.write('>')
+
+    def comment(self, content):
+        self._out.write('<!--')
+        self._out.write(content)
+        self._out.write('-->')
+
+    def startCDATA(self):
+        self._in_cdata = 1
+        self._out.write('<![CDATA[')
+
+    def endCDATA(self):
+        self._in_cdata = 0
+        self._out.write(']]>')
+
+
+# --- ContentGenerator is the SAX1 DocumentHandler for writing back XML
+class ContentGenerator(XMLGenerator):
+
+    def characters(self, str, start, end):
+        # In SAX1, characters receives start and end; in SAX2, it receives
+        # a string. For plain strings, we may want to use a buffer object.
+        return XMLGenerator.characters(self, str[start:start+end])
+
+# --- XMLFilterImpl
+class XMLFilterBase(saxlib.XMLFilter):
+    """This class is designed to sit between an XMLReader and the
+    client application's event handlers.  By default, it does nothing
+    but pass requests up to the reader and events on to the handlers
+    unmodified, but subclasses can override specific methods to modify
+    the event stream or the configuration requests as they pass
+    through."""
+
+    # ErrorHandler methods
+
+    def error(self, exception):
+        self._err_handler.error(exception)
+
+    def fatalError(self, exception):
+        self._err_handler.fatalError(exception)
+
+    def warning(self, exception):
+        self._err_handler.warning(exception)
+
+    # ContentHandler methods
+
+    def setDocumentLocator(self, locator):
+        self._cont_handler.setDocumentLocator(locator)
+
+    def startDocument(self):
+        self._cont_handler.startDocument()
+
+    def endDocument(self):
+        self._cont_handler.endDocument()
+
+    def startPrefixMapping(self, prefix, uri):
+        self._cont_handler.startPrefixMapping(prefix, uri)
+
+    def endPrefixMapping(self, prefix):
+        self._cont_handler.endPrefixMapping(prefix)
+
+    def startElement(self, name, attrs):
+        self._cont_handler.startElement(name, attrs)
+
+    def endElement(self, name):
+        self._cont_handler.endElement(name)
+
+    def startElementNS(self, name, qname, attrs):
+        self._cont_handler.startElementNS(name, qname, attrs)
+
+    def endElementNS(self, name, qname):
+        self._cont_handler.endElementNS(name, qname)
+
+    def characters(self, content):
+        self._cont_handler.characters(content)
+
+    def ignorableWhitespace(self, chars):
+        self._cont_handler.ignorableWhitespace(chars)
+
+    def processingInstruction(self, target, data):
+        self._cont_handler.processingInstruction(target, data)
+
+    def skippedEntity(self, name):
+        self._cont_handler.skippedEntity(name)
+
+    # DTDHandler methods
+
+    def notationDecl(self, name, publicId, systemId):
+        self._dtd_handler.notationDecl(name, publicId, systemId)
+
+    def unparsedEntityDecl(self, name, publicId, systemId, ndata):
+        self._dtd_handler.unparsedEntityDecl(name, publicId, systemId, ndata)
+
+    # EntityResolver methods
+
+    def resolveEntity(self, publicId, systemId):
+        return self._ent_handler.resolveEntity(publicId, systemId)
+
+    # XMLReader methods
+
+    def parse(self, source):
+        self._parent.setContentHandler(self)
+        self._parent.setErrorHandler(self)
+        self._parent.setEntityResolver(self)
+        self._parent.setDTDHandler(self)
+        self._parent.parse(source)
+
+    def setLocale(self, locale):
+        self._parent.setLocale(locale)
+
+    def getFeature(self, name):
+        return self._parent.getFeature(name)
+
+    def setFeature(self, name, state):
+        self._parent.setFeature(name, state)
+
+    def getProperty(self, name):
+        return self._parent.getProperty(name)
+
+    def setProperty(self, name, value):
+        self._parent.setProperty(name, value)
+
+# FIXME: remove this backward compatibility hack when not needed anymore
+XMLFilterImpl = XMLFilterBase
+
+# --- BaseIncrementalParser
+
+class BaseIncrementalParser(xmlreader.IncrementalParser):
+    """This class implements the parse method of the XMLReader
+    interface using the feed, close and reset methods of the
+    IncrementalParser interface as a convenience to SAX 2.0 driver
+    writers."""
+
+    def parse(self, source):
+        source = prepare_input_source(source)
+        self.prepareParser(source)
+
+        self._cont_handler.startDocument()
+
+        # FIXME: what about char-stream?
+        inf = source.getByteStream()
+        buffer = inf.read(16384)
+        while buffer != "":
+            self.feed(buffer)
+            buffer = inf.read(16384)
+
+        self.close()
+        self.reset()
+
+        self._cont_handler.endDocument()
+
+    def prepareParser(self, source):
+        """This method is called by the parse implementation to allow
+        the SAX 2.0 driver to prepare itself for parsing."""
+        raise NotImplementedError("prepareParser must be overridden!")
+
+# --- Utility functions
+
+def prepare_input_source(source, base = ""):
+    """This function takes an InputSource and an optional base URL and
+    returns a fully resolved InputSource object ready for reading."""
+
+    if type(source) in _StringTypes:
+        source = xmlreader.InputSource(source)
+    elif hasattr(source, "read"):
+        f = source
+        source = xmlreader.InputSource()
+        source.setByteStream(f)
+        if hasattr(f, "name"):
+            source.setSystemId(absolute_system_id(f.name, base))
+
+    if source.getByteStream() is None:
+        sysid = absolute_system_id(source.getSystemId(), base)
+        source.setSystemId(sysid)
+        f = urllib2.urlopen(sysid)
+        source.setByteStream(f)
+
+    return source
+
+
+def absolute_system_id(sysid, base=''):
+    if os.path.exists(sysid):
+        sysid = 'file:%s' % os.path.abspath(sysid)
+    elif base:
+        sysid = Absolutize(sysid, base)
+    assert IsAbsolute(sysid)
+    return MakeUrllibSafe(sysid)
+
+# ===========================================================================
+#
+# DEPRECATED SAX 1.0 CLASSES
+#
+# ===========================================================================
+
+# --- AttributeMap
+
+class AttributeMap:
+    """An implementation of AttributeList that takes an (attr,val) hash
+    and uses it to implement the AttributeList interface."""
+
+    def __init__(self, map):
+        self.map=map
+
+    def getLength(self):
+        return len(self.map.keys())
+
+    def getName(self, i):
+        try:
+            return self.map.keys()[i]
+        except IndexError,e:
+            return None
+
+    def getType(self, i):
+        return "CDATA"
+
+    def getValue(self, i):
+        try:
+            if type(i)==types.IntType:
+                return self.map[self.getName(i)]
+            else:
+                return self.map[i]
+        except KeyError,e:
+            return None
+
+    def __len__(self):
+        return len(self.map)
+
+    def __getitem__(self, key):
+        if type(key)==types.IntType:
+            return self.map.keys()[key]
+        else:
+            return self.map[key]
+
+    def items(self):
+        return self.map.items()
+
+    def keys(self):
+        return self.map.keys()
+
+    def has_key(self,key):
+        return self.map.has_key(key)
+
+    def get(self, key, alternative=None):
+        return self.map.get(key, alternative)
+
+    def copy(self):
+        return AttributeMap(self.map.copy())
+
+    def values(self):
+        return self.map.values()
+
+# --- Event broadcasting object
+
+class EventBroadcaster:
+    """Takes a list of objects and forwards any method calls received
+    to all objects in the list. The attribute list holds the list and
+    can freely be modified by clients."""
+
+    class Event:
+        "Helper objects that represent event methods."
+
+        def __init__(self,list,name):
+            self.list=list
+            self.name=name
+
+        def __call__(self,*rest):
+            for obj in self.list:
+                apply(getattr(obj,self.name), rest)
+
+    def __init__(self,list):
+        self.list=list
+
+    def __getattr__(self,name):
+        return self.Event(self.list,name)
+
+    def __repr__(self):
+        return "<EventBroadcaster instance at %d>" % id(self)
+
+# --- ESIS document handler
+import saxlib
+class ESISDocHandler(saxlib.HandlerBase):
+    "A SAX document handler that produces naive ESIS output."
+
+    def __init__(self,writer=sys.stdout):
+        self.writer=writer
+
+    def processingInstruction (self,target, remainder):
+        """Receive an event signalling that a processing instruction
+        has been found."""
+        self.writer.write("?"+target+" "+remainder+"\n")
+
+    def startElement(self,name,amap):
+        "Receive an event signalling the start of an element."
+        self.writer.write("("+name+"\n")
+        for a_name in amap.keys():
+            self.writer.write("A"+a_name+" "+amap[a_name]+"\n")
+
+    def endElement(self,name):
+        "Receive an event signalling the end of an element."
+        self.writer.write(")"+name+"\n")
+
+    def characters(self,data,start_ix,length):
+        "Receive an event signalling that character data has been found."
+        self.writer.write("-"+data[start_ix:start_ix+length]+"\n")
+
+# --- XML canonizer
+
+class Canonizer(saxlib.HandlerBase):
+    "A SAX document handler that produces canonized XML output."
+
+    def __init__(self,writer=sys.stdout):
+        self.elem_level=0
+        self.writer=writer
+
+    def processingInstruction (self,target, remainder):
+        if not target=="xml":
+            self.writer.write("<?"+target+" "+remainder+"?>")
+
+    def startElement(self,name,amap):
+        self.writer.write("<"+name)
+
+        a_names=amap.keys()
+        a_names.sort()
+
+        for a_name in a_names:
+            self.writer.write(" "+a_name+"=\"")
+            self.write_data(amap[a_name])
+            self.writer.write("\"")
+        self.writer.write(">")
+        self.elem_level=self.elem_level+1
+
+    def endElement(self,name):
+        self.writer.write("</"+name+">")
+        self.elem_level=self.elem_level-1
+
+    def ignorableWhitespace(self,data,start_ix,length):
+        self.characters(data,start_ix,length)
+
+    def characters(self,data,start_ix,length):
+        if self.elem_level>0:
+            self.write_data(data[start_ix:start_ix+length])
+
+    def write_data(self,data):
+        "Writes datachars to writer."
+        data=data.replace("&","&amp;")
+        data=data.replace("<","&lt;")
+        data=data.replace("\"","&quot;")
+        data=data.replace(">","&gt;")
+        data=data.replace(chr(9),"&#9;")
+        data=data.replace(chr(10),"&#10;")
+        data=data.replace(chr(13),"&#13;")
+        self.writer.write(data)
+
+# --- mllib
+
+class mllib:
+    """A re-implementation of the htmllib, sgmllib and xmllib interfaces as a
+    SAX DocumentHandler."""
+
+# Unsupported:
+# - setnomoretags
+# - setliteral
+# - translate_references
+# - handle_xml
+# - handle_doctype
+# - handle_charref
+# - handle_entityref
+# - handle_comment
+# - handle_cdata
+# - tag_attributes
+
+    def __init__(self):
+        self.reset()
+
+    def reset(self):
+        import saxexts # only used here
+        self.parser=saxexts.XMLParserFactory.make_parser()
+        self.handler=mllib.Handler(self.parser,self)
+        self.handler.reset()
+
+    def feed(self,data):
+        self.parser.feed(data)
+
+    def close(self):
+        self.parser.close()
+
+    def get_stack(self):
+        return self.handler.get_stack()
+
+    # --- Handler methods (to be overridden)
+
+    def handle_starttag(self,name,method,atts):
+        method(atts)
+
+    def handle_endtag(self,name,method):
+        method()
+
+    def handle_data(self,data):
+        pass
+
+    def handle_proc(self,target,data):
+        pass
+
+    def unknown_starttag(self,name,atts):
+        pass
+
+    def unknown_endtag(self,name):
+        pass
+
+    def syntax_error(self,message):
+        pass
+
+    # --- The internal handler class
+
+    class Handler(saxlib.DocumentHandler,saxlib.ErrorHandler):
+        """An internal class to handle SAX events and translate them to mllib
+        events."""
+
+        def __init__(self,driver,handler):
+            self.driver=driver
+            self.driver.setDocumentHandler(self)
+            self.driver.setErrorHandler(self)
+            self.handler=handler
+            self.reset()
+
+        def get_stack(self):
+            return self.stack
+
+        def reset(self):
+            self.stack=[]
+
+        # --- DocumentHandler methods
+
+        def characters(self, ch, start, length):
+            self.handler.handle_data(ch[start:start+length])
+
+        def endElement(self, name):
+            if hasattr(self.handler,"end_"+name):
+                self.handler.handle_endtag(name,
+                                          getattr(self.handler,"end_"+name))
+            else:
+                self.handler.unknown_endtag(name)
+
+            del self.stack[-1]
+
+        def ignorableWhitespace(self, ch, start, length):
+            self.handler.handle_data(ch[start:start+length])
+
+        def processingInstruction(self, target, data):
+            self.handler.handle_proc(target,data)
+
+        def startElement(self, name, atts):
+            self.stack.append(name)
+
+            if hasattr(self.handler,"start_"+name):
+                self.handler.handle_starttag(name,
+                                            getattr(self.handler,
+                                                    "start_"+name),
+                                             atts)
+            else:
+                self.handler.unknown_starttag(name,atts)
+
+        # --- ErrorHandler methods
+
+        def error(self, exception):
+            self.handler.syntax_error(str(exception))
+
+        def fatalError(self, exception):
+            raise RuntimeError(str(exception))
diff --git a/src/main/resources/PythonLibs/xml/sax/xmlreader.py b/src/main/resources/PythonLibs/xml/sax/xmlreader.py
new file mode 100644
index 0000000000000000000000000000000000000000..f1c9d9db2ed26a6abc9b9ee307a64fbcd86d7169
--- /dev/null
+++ b/src/main/resources/PythonLibs/xml/sax/xmlreader.py
@@ -0,0 +1,378 @@
+"""An XML Reader is the SAX 2 name for an XML parser. XML Parsers
+should be based on this code. """
+
+import handler
+
+from _exceptions import SAXNotSupportedException, SAXNotRecognizedException
+
+
+# ===== XMLREADER =====
+
+class XMLReader:
+    """Interface for reading an XML document using callbacks.
+
+    XMLReader is the interface that an XML parser's SAX2 driver must
+    implement. This interface allows an application to set and query
+    features and properties in the parser, to register event handlers
+    for document processing, and to initiate a document parse.
+
+    All SAX interfaces are assumed to be synchronous: the parse
+    methods must not return until parsing is complete, and readers
+    must wait for an event-handler callback to return before reporting
+    the next event."""
+
+    def __init__(self):
+        self._cont_handler = handler.ContentHandler()
+        self._dtd_handler = handler.DTDHandler()
+        self._ent_handler = handler.EntityResolver()
+        self._err_handler = handler.ErrorHandler()
+
+    def parse(self, source):
+        "Parse an XML document from a system identifier or an InputSource."
+        raise NotImplementedError("This method must be implemented!")
+
+    def getContentHandler(self):
+        "Returns the current ContentHandler."
+        return self._cont_handler
+
+    def setContentHandler(self, handler):
+        "Registers a new object to receive document content events."
+        self._cont_handler = handler
+
+    def getDTDHandler(self):
+        "Returns the current DTD handler."
+        return self._dtd_handler
+
+    def setDTDHandler(self, handler):
+        "Register an object to receive basic DTD-related events."
+        self._dtd_handler = handler
+
+    def getEntityResolver(self):
+        "Returns the current EntityResolver."
+        return self._ent_handler
+
+    def setEntityResolver(self, resolver):
+        "Register an object to resolve external entities."
+        self._ent_handler = resolver
+
+    def getErrorHandler(self):
+        "Returns the current ErrorHandler."
+        return self._err_handler
+
+    def setErrorHandler(self, handler):
+        "Register an object to receive error-message events."
+        self._err_handler = handler
+
+    def setLocale(self, locale):
+        """Allow an application to set the locale for errors and warnings.
+
+        SAX parsers are not required to provide localization for errors
+        and warnings; if they cannot support the requested locale,
+        however, they must throw a SAX exception. Applications may
+        request a locale change in the middle of a parse."""
+        raise SAXNotSupportedException("Locale support not implemented")
+
+    def getFeature(self, name):
+        "Looks up and returns the state of a SAX2 feature."
+        raise SAXNotRecognizedException("Feature '%s' not recognized" % name)
+
+    def setFeature(self, name, state):
+        "Sets the state of a SAX2 feature."
+        raise SAXNotRecognizedException("Feature '%s' not recognized" % name)
+
+    def getProperty(self, name):
+        "Looks up and returns the value of a SAX2 property."
+        raise SAXNotRecognizedException("Property '%s' not recognized" % name)
+
+    def setProperty(self, name, value):
+        "Sets the value of a SAX2 property."
+        raise SAXNotRecognizedException("Property '%s' not recognized" % name)
+
+class IncrementalParser(XMLReader):
+    """This interface adds three extra methods to the XMLReader
+    interface that allow XML parsers to support incremental
+    parsing. Support for this interface is optional, since not all
+    underlying XML parsers support this functionality.
+
+    When the parser is instantiated it is ready to begin accepting
+    data from the feed method immediately. After parsing has been
+    finished with a call to close the reset method must be called to
+    make the parser ready to accept new data, either from feed or
+    using the parse method.
+
+    Note that these methods must _not_ be called during parsing, that
+    is, after parse has been called and before it returns.
+
+    By default, the class also implements the parse method of the XMLReader
+    interface using the feed, close and reset methods of the
+    IncrementalParser interface as a convenience to SAX 2.0 driver
+    writers."""
+
+    def __init__(self, bufsize=2**16):
+        self._bufsize = bufsize
+        XMLReader.__init__(self)
+
+    def parse(self, source):
+        import saxutils
+        source = saxutils.prepare_input_source(source)
+
+        self.prepareParser(source)
+        file = source.getByteStream()
+        buffer = file.read(self._bufsize)
+        while buffer != "":
+            self.feed(buffer)
+            buffer = file.read(self._bufsize)
+        self.close()
+
+    def feed(self, data):
+        """This method gives the raw XML data in the data parameter to
+        the parser and makes it parse the data, emitting the
+        corresponding events. It is allowed for XML constructs to be
+        split across several calls to feed.
+
+        feed may raise SAXException."""
+        raise NotImplementedError("This method must be implemented!")
+
+    def prepareParser(self, source):
+        """This method is called by the parse implementation to allow
+        the SAX 2.0 driver to prepare itself for parsing."""
+        raise NotImplementedError("prepareParser must be overridden!")
+
+    def close(self):
+        """This method is called when the entire XML document has been
+        passed to the parser through the feed method, to notify the
+        parser that there are no more data. This allows the parser to
+        do the final checks on the document and empty the internal
+        data buffer.
+
+        The parser will not be ready to parse another document until
+        the reset method has been called.
+
+        close may raise SAXException."""
+        raise NotImplementedError("This method must be implemented!")
+
+    def reset(self):
+        """This method is called after close has been called to reset
+        the parser so that it is ready to parse new documents. The
+        results of calling parse or feed after close without calling
+        reset are undefined."""
+        raise NotImplementedError("This method must be implemented!")
+
+# ===== LOCATOR =====
+
+class Locator:
+    """Interface for associating a SAX event with a document
+    location. A locator object will return valid results only during
+    calls to DocumentHandler methods; at any other time, the
+    results are unpredictable."""
+
+    def getColumnNumber(self):
+        "Return the column number where the current event ends."
+        return -1
+
+    def getLineNumber(self):
+        "Return the line number where the current event ends."
+        return -1
+
+    def getPublicId(self):
+        "Return the public identifier for the current event."
+        return None
+
+    def getSystemId(self):
+        "Return the system identifier for the current event."
+        return None
+
+# ===== INPUTSOURCE =====
+
+class InputSource:
+    """Encapsulation of the information needed by the XMLReader to
+    read entities.
+
+    This class may include information about the public identifier,
+    system identifier, byte stream (possibly with character encoding
+    information) and/or the character stream of an entity.
+
+    Applications will create objects of this class for use in the
+    XMLReader.parse method and for returning from
+    EntityResolver.resolveEntity.
+
+    An InputSource belongs to the application, the XMLReader is not
+    allowed to modify InputSource objects passed to it from the
+    application, although it may make copies and modify those."""
+
+    def __init__(self, system_id = None):
+        self.__system_id = system_id
+        self.__public_id = None
+        self.__encoding  = None
+        self.__bytefile  = None
+        self.__charfile  = None
+
+    def setPublicId(self, public_id):
+        "Sets the public identifier of this InputSource."
+        self.__public_id = public_id
+
+    def getPublicId(self):
+        "Returns the public identifier of this InputSource."
+        return self.__public_id
+
+    def setSystemId(self, system_id):
+        "Sets the system identifier of this InputSource."
+        self.__system_id = system_id
+
+    def getSystemId(self):
+        "Returns the system identifier of this InputSource."
+        return self.__system_id
+
+    def setEncoding(self, encoding):
+        """Sets the character encoding of this InputSource.
+
+        The encoding must be a string acceptable for an XML encoding
+        declaration (see section 4.3.3 of the XML recommendation).
+
+        The encoding attribute of the InputSource is ignored if the
+        InputSource also contains a character stream."""
+        self.__encoding = encoding
+
+    def getEncoding(self):
+        "Get the character encoding of this InputSource."
+        return self.__encoding
+
+    def setByteStream(self, bytefile):
+        """Set the byte stream (a Python file-like object which does
+        not perform byte-to-character conversion) for this input
+        source.
+
+        The SAX parser will ignore this if there is also a character
+        stream specified, but it will use a byte stream in preference
+        to opening a URI connection itself.
+
+        If the application knows the character encoding of the byte
+        stream, it should set it with the setEncoding method."""
+        self.__bytefile = bytefile
+
+    def getByteStream(self):
+        """Get the byte stream for this input source.
+
+        The getEncoding method will return the character encoding for
+        this byte stream, or None if unknown."""
+        return self.__bytefile
+
+    def setCharacterStream(self, charfile):
+        """Set the character stream for this input source. (The stream
+        must be a Python 2.0 Unicode-wrapped file-like that performs
+        conversion to Unicode strings.)
+
+        If there is a character stream specified, the SAX parser will
+        ignore any byte stream and will not attempt to open a URI
+        connection to the system identifier."""
+        self.__charfile = charfile
+
+    def getCharacterStream(self):
+        "Get the character stream for this input source."
+        return self.__charfile
+
+# ===== ATTRIBUTESIMPL =====
+
+class AttributesImpl:
+
+    def __init__(self, attrs):
+        """Non-NS-aware implementation.
+
+        attrs should be of the form {name : value}."""
+        self._attrs = attrs
+
+    def getLength(self):
+        return len(self._attrs)
+
+    def getType(self, name):
+        return "CDATA"
+
+    def getValue(self, name):
+        return self._attrs[name]
+
+    def getValueByQName(self, name):
+        return self._attrs[name]
+
+    def getNameByQName(self, name):
+        if not self._attrs.has_key(name):
+            raise KeyError, name
+        return name
+
+    def getQNameByName(self, name):
+        if not self._attrs.has_key(name):
+            raise KeyError, name
+        return name
+
+    def getNames(self):
+        return self._attrs.keys()
+
+    def getQNames(self):
+        return self._attrs.keys()
+
+    def __len__(self):
+        return len(self._attrs)
+
+    def __getitem__(self, name):
+        return self._attrs[name]
+
+    def keys(self):
+        return self._attrs.keys()
+
+    def has_key(self, name):
+        return self._attrs.has_key(name)
+
+    def get(self, name, alternative=None):
+        return self._attrs.get(name, alternative)
+
+    def copy(self):
+        return self.__class__(self._attrs)
+
+    def items(self):
+        return self._attrs.items()
+
+    def values(self):
+        return self._attrs.values()
+
+# ===== ATTRIBUTESNSIMPL =====
+
+class AttributesNSImpl(AttributesImpl):
+
+    def __init__(self, attrs, qnames):
+        """NS-aware implementation.
+
+        attrs should be of the form {(ns_uri, lname): value, ...}.
+        qnames of the form {(ns_uri, lname): qname, ...}."""
+        self._attrs = attrs
+        self._qnames = qnames
+
+    def getValueByQName(self, name):
+        for (nsname, qname) in self._qnames.items():
+            if qname == name:
+                return self._attrs[nsname]
+
+        raise KeyError, name
+
+    def getNameByQName(self, name):
+        for (nsname, qname) in self._qnames.items():
+            if qname == name:
+                return nsname
+
+        raise KeyError, name
+
+    def getQNameByName(self, name):
+        return self._qnames[name]
+
+    def getQNames(self):
+        return self._qnames.values()
+
+    def copy(self):
+        return self.__class__(self._attrs, self._qnames)
+
+
+def _test():
+    XMLReader()
+    IncrementalParser()
+    Locator()
+
+if __name__ == "__main__":
+    _test()
diff --git a/src/main/resources/PythonLibs/xmllib.py b/src/main/resources/PythonLibs/xmllib.py
new file mode 100644
index 0000000000000000000000000000000000000000..96ee8411e7a74a347a9b2935fc8b3760d0a7491a
--- /dev/null
+++ b/src/main/resources/PythonLibs/xmllib.py
@@ -0,0 +1,930 @@
+"""A parser for XML, using the derived class as static DTD."""
+
+# Author: Sjoerd Mullender.
+
+import re
+import string
+
+import warnings
+warnings.warn("The xmllib module is obsolete.  Use xml.sax instead.",
+              DeprecationWarning, 2)
+del warnings
+
+version = '0.3'
+
+class Error(RuntimeError):
+    pass
+
+# Regular expressions used for parsing
+
+_S = '[ \t\r\n]+'                       # white space
+_opS = '[ \t\r\n]*'                     # optional white space
+_Name = '[a-zA-Z_:][-a-zA-Z0-9._:]*'    # valid XML name
+_QStr = "(?:'[^']*'|\"[^\"]*\")"        # quoted XML string
+illegal = re.compile('[^\t\r\n -\176\240-\377]') # illegal chars in content
+interesting = re.compile('[]&<]')
+
+amp = re.compile('&')
+ref = re.compile('&(' + _Name + '|#[0-9]+|#x[0-9a-fA-F]+)[^-a-zA-Z0-9._:]')
+entityref = re.compile('&(?P<name>' + _Name + ')[^-a-zA-Z0-9._:]')
+charref = re.compile('&#(?P<char>[0-9]+[^0-9]|x[0-9a-fA-F]+[^0-9a-fA-F])')
+space = re.compile(_S + '$')
+newline = re.compile('\n')
+
+attrfind = re.compile(
+    _S + '(?P<name>' + _Name + ')'
+    '(' + _opS + '=' + _opS +
+    '(?P<value>'+_QStr+'|[-a-zA-Z0-9.:+*%?!\(\)_#=~]+))?')
+starttagopen = re.compile('<' + _Name)
+starttagend = re.compile(_opS + '(?P<slash>/?)>')
+starttagmatch = re.compile('<(?P<tagname>'+_Name+')'
+                      '(?P<attrs>(?:'+attrfind.pattern+')*)'+
+                      starttagend.pattern)
+endtagopen = re.compile('</')
+endbracket = re.compile(_opS + '>')
+endbracketfind = re.compile('(?:[^>\'"]|'+_QStr+')*>')
+tagfind = re.compile(_Name)
+cdataopen = re.compile(r'<!\[CDATA\[')
+cdataclose = re.compile(r'\]\]>')
+# this matches one of the following:
+# SYSTEM SystemLiteral
+# PUBLIC PubidLiteral SystemLiteral
+_SystemLiteral = '(?P<%s>'+_QStr+')'
+_PublicLiteral = '(?P<%s>"[-\'\(\)+,./:=?;!*#@$_%% \n\ra-zA-Z0-9]*"|' \
+                        "'[-\(\)+,./:=?;!*#@$_%% \n\ra-zA-Z0-9]*')"
+_ExternalId = '(?:SYSTEM|' \
+                 'PUBLIC'+_S+_PublicLiteral%'pubid'+ \
+              ')'+_S+_SystemLiteral%'syslit'
+doctype = re.compile('<!DOCTYPE'+_S+'(?P<name>'+_Name+')'
+                     '(?:'+_S+_ExternalId+')?'+_opS)
+xmldecl = re.compile('<\?xml'+_S+
+                     'version'+_opS+'='+_opS+'(?P<version>'+_QStr+')'+
+                     '(?:'+_S+'encoding'+_opS+'='+_opS+
+                        "(?P<encoding>'[A-Za-z][-A-Za-z0-9._]*'|"
+                        '"[A-Za-z][-A-Za-z0-9._]*"))?'
+                     '(?:'+_S+'standalone'+_opS+'='+_opS+
+                        '(?P<standalone>\'(?:yes|no)\'|"(?:yes|no)"))?'+
+                     _opS+'\?>')
+procopen = re.compile(r'<\?(?P<proc>' + _Name + ')' + _opS)
+procclose = re.compile(_opS + r'\?>')
+commentopen = re.compile('<!--')
+commentclose = re.compile('-->')
+doubledash = re.compile('--')
+attrtrans = string.maketrans(' \r\n\t', '    ')
+
+# definitions for XML namespaces
+_NCName = '[a-zA-Z_][-a-zA-Z0-9._]*'    # XML Name, minus the ":"
+ncname = re.compile(_NCName + '$')
+qname = re.compile('(?:(?P<prefix>' + _NCName + '):)?' # optional prefix
+                   '(?P<local>' + _NCName + ')$')
+
+xmlns = re.compile('xmlns(?::(?P<ncname>'+_NCName+'))?$')
+
+# XML parser base class -- find tags and call handler functions.
+# Usage: p = XMLParser(); p.feed(data); ...; p.close().
+# The dtd is defined by deriving a class which defines methods with
+# special names to handle tags: start_foo and end_foo to handle <foo>
+# and </foo>, respectively.  The data between tags is passed to the
+# parser by calling self.handle_data() with some data as argument (the
+# data may be split up in arbitrary chunks).
+
+class XMLParser:
+    attributes = {}                     # default, to be overridden
+    elements = {}                       # default, to be overridden
+
+    # parsing options, settable using keyword args in __init__
+    __accept_unquoted_attributes = 0
+    __accept_missing_endtag_name = 0
+    __map_case = 0
+    __accept_utf8 = 0
+    __translate_attribute_references = 1
+
+    # Interface -- initialize and reset this instance
+    def __init__(self, **kw):
+        self.__fixed = 0
+        if 'accept_unquoted_attributes' in kw:
+            self.__accept_unquoted_attributes = kw['accept_unquoted_attributes']
+        if 'accept_missing_endtag_name' in kw:
+            self.__accept_missing_endtag_name = kw['accept_missing_endtag_name']
+        if 'map_case' in kw:
+            self.__map_case = kw['map_case']
+        if 'accept_utf8' in kw:
+            self.__accept_utf8 = kw['accept_utf8']
+        if 'translate_attribute_references' in kw:
+            self.__translate_attribute_references = kw['translate_attribute_references']
+        self.reset()
+
+    def __fixelements(self):
+        self.__fixed = 1
+        self.elements = {}
+        self.__fixdict(self.__dict__)
+        self.__fixclass(self.__class__)
+
+    def __fixclass(self, kl):
+        self.__fixdict(kl.__dict__)
+        for k in kl.__bases__:
+            self.__fixclass(k)
+
+    def __fixdict(self, dict):
+        for key in dict.keys():
+            if key[:6] == 'start_':
+                tag = key[6:]
+                start, end = self.elements.get(tag, (None, None))
+                if start is None:
+                    self.elements[tag] = getattr(self, key), end
+            elif key[:4] == 'end_':
+                tag = key[4:]
+                start, end = self.elements.get(tag, (None, None))
+                if end is None:
+                    self.elements[tag] = start, getattr(self, key)
+
+    # Interface -- reset this instance.  Loses all unprocessed data
+    def reset(self):
+        self.rawdata = ''
+        self.stack = []
+        self.nomoretags = 0
+        self.literal = 0
+        self.lineno = 1
+        self.__at_start = 1
+        self.__seen_doctype = None
+        self.__seen_starttag = 0
+        self.__use_namespaces = 0
+        self.__namespaces = {'xml':None}   # xml is implicitly declared
+        # backward compatibility hack: if elements not overridden,
+        # fill it in ourselves
+        if self.elements is XMLParser.elements:
+            self.__fixelements()
+
+    # For derived classes only -- enter literal mode (CDATA) till EOF
+    def setnomoretags(self):
+        self.nomoretags = self.literal = 1
+
+    # For derived classes only -- enter literal mode (CDATA)
+    def setliteral(self, *args):
+        self.literal = 1
+
+    # Interface -- feed some data to the parser.  Call this as
+    # often as you want, with as little or as much text as you
+    # want (may include '\n').  (This just saves the text, all the
+    # processing is done by goahead().)
+    def feed(self, data):
+        self.rawdata = self.rawdata + data
+        self.goahead(0)
+
+    # Interface -- handle the remaining data
+    def close(self):
+        self.goahead(1)
+        if self.__fixed:
+            self.__fixed = 0
+            # remove self.elements so that we don't leak
+            del self.elements
+
+    # Interface -- translate references
+    def translate_references(self, data, all = 1):
+        if not self.__translate_attribute_references:
+            return data
+        i = 0
+        while 1:
+            res = amp.search(data, i)
+            if res is None:
+                return data
+            s = res.start(0)
+            res = ref.match(data, s)
+            if res is None:
+                self.syntax_error("bogus `&'")
+                i = s+1
+                continue
+            i = res.end(0)
+            str = res.group(1)
+            rescan = 0
+            if str[0] == '#':
+                if str[1] == 'x':
+                    str = chr(int(str[2:], 16))
+                else:
+                    str = chr(int(str[1:]))
+                if data[i - 1] != ';':
+                    self.syntax_error("`;' missing after char reference")
+                    i = i-1
+            elif all:
+                if str in self.entitydefs:
+                    str = self.entitydefs[str]
+                    rescan = 1
+                elif data[i - 1] != ';':
+                    self.syntax_error("bogus `&'")
+                    i = s + 1 # just past the &
+                    continue
+                else:
+                    self.syntax_error("reference to unknown entity `&%s;'" % str)
+                    str = '&' + str + ';'
+            elif data[i - 1] != ';':
+                self.syntax_error("bogus `&'")
+                i = s + 1 # just past the &
+                continue
+
+            # when we get here, str contains the translated text and i points
+            # to the end of the string that is to be replaced
+            data = data[:s] + str + data[i:]
+            if rescan:
+                i = s
+            else:
+                i = s + len(str)
+
+    # Interface - return a dictionary of all namespaces currently valid
+    def getnamespace(self):
+        nsdict = {}
+        for t, d, nst in self.stack:
+            nsdict.update(d)
+        return nsdict
+
+    # Internal -- handle data as far as reasonable.  May leave state
+    # and data to be processed by a subsequent call.  If 'end' is
+    # true, force handling all data as if followed by EOF marker.
+    def goahead(self, end):
+        rawdata = self.rawdata
+        i = 0
+        n = len(rawdata)
+        while i < n:
+            if i > 0:
+                self.__at_start = 0
+            if self.nomoretags:
+                data = rawdata[i:n]
+                self.handle_data(data)
+                self.lineno = self.lineno + data.count('\n')
+                i = n
+                break
+            res = interesting.search(rawdata, i)
+            if res:
+                j = res.start(0)
+            else:
+                j = n
+            if i < j:
+                data = rawdata[i:j]
+                if self.__at_start and space.match(data) is None:
+                    self.syntax_error('illegal data at start of file')
+                self.__at_start = 0
+                if not self.stack and space.match(data) is None:
+                    self.syntax_error('data not in content')
+                if not self.__accept_utf8 and illegal.search(data):
+                    self.syntax_error('illegal character in content')
+                self.handle_data(data)
+                self.lineno = self.lineno + data.count('\n')
+            i = j
+            if i == n: break
+            if rawdata[i] == '<':
+                if starttagopen.match(rawdata, i):
+                    if self.literal:
+                        data = rawdata[i]
+                        self.handle_data(data)
+                        self.lineno = self.lineno + data.count('\n')
+                        i = i+1
+                        continue
+                    k = self.parse_starttag(i)
+                    if k < 0: break
+                    self.__seen_starttag = 1
+                    self.lineno = self.lineno + rawdata[i:k].count('\n')
+                    i = k
+                    continue
+                if endtagopen.match(rawdata, i):
+                    k = self.parse_endtag(i)
+                    if k < 0: break
+                    self.lineno = self.lineno + rawdata[i:k].count('\n')
+                    i =  k
+                    continue
+                if commentopen.match(rawdata, i):
+                    if self.literal:
+                        data = rawdata[i]
+                        self.handle_data(data)
+                        self.lineno = self.lineno + data.count('\n')
+                        i = i+1
+                        continue
+                    k = self.parse_comment(i)
+                    if k < 0: break
+                    self.lineno = self.lineno + rawdata[i:k].count('\n')
+                    i = k
+                    continue
+                if cdataopen.match(rawdata, i):
+                    k = self.parse_cdata(i)
+                    if k < 0: break
+                    self.lineno = self.lineno + rawdata[i:k].count('\n')
+                    i = k
+                    continue
+                res = xmldecl.match(rawdata, i)
+                if res:
+                    if not self.__at_start:
+                        self.syntax_error("<?xml?> declaration not at start of document")
+                    version, encoding, standalone = res.group('version',
+                                                              'encoding',
+                                                              'standalone')
+                    if version[1:-1] != '1.0':
+                        raise Error('only XML version 1.0 supported')
+                    if encoding: encoding = encoding[1:-1]
+                    if standalone: standalone = standalone[1:-1]
+                    self.handle_xml(encoding, standalone)
+                    i = res.end(0)
+                    continue
+                res = procopen.match(rawdata, i)
+                if res:
+                    k = self.parse_proc(i)
+                    if k < 0: break
+                    self.lineno = self.lineno + rawdata[i:k].count('\n')
+                    i = k
+                    continue
+                res = doctype.match(rawdata, i)
+                if res:
+                    if self.literal:
+                        data = rawdata[i]
+                        self.handle_data(data)
+                        self.lineno = self.lineno + data.count('\n')
+                        i = i+1
+                        continue
+                    if self.__seen_doctype:
+                        self.syntax_error('multiple DOCTYPE elements')
+                    if self.__seen_starttag:
+                        self.syntax_error('DOCTYPE not at beginning of document')
+                    k = self.parse_doctype(res)
+                    if k < 0: break
+                    self.__seen_doctype = res.group('name')
+                    if self.__map_case:
+                        self.__seen_doctype = self.__seen_doctype.lower()
+                    self.lineno = self.lineno + rawdata[i:k].count('\n')
+                    i = k
+                    continue
+            elif rawdata[i] == '&':
+                if self.literal:
+                    data = rawdata[i]
+                    self.handle_data(data)
+                    i = i+1
+                    continue
+                res = charref.match(rawdata, i)
+                if res is not None:
+                    i = res.end(0)
+                    if rawdata[i-1] != ';':
+                        self.syntax_error("`;' missing in charref")
+                        i = i-1
+                    if not self.stack:
+                        self.syntax_error('data not in content')
+                    self.handle_charref(res.group('char')[:-1])
+                    self.lineno = self.lineno + res.group(0).count('\n')
+                    continue
+                res = entityref.match(rawdata, i)
+                if res is not None:
+                    i = res.end(0)
+                    if rawdata[i-1] != ';':
+                        self.syntax_error("`;' missing in entityref")
+                        i = i-1
+                    name = res.group('name')
+                    if self.__map_case:
+                        name = name.lower()
+                    if name in self.entitydefs:
+                        self.rawdata = rawdata = rawdata[:res.start(0)] + self.entitydefs[name] + rawdata[i:]
+                        n = len(rawdata)
+                        i = res.start(0)
+                    else:
+                        self.unknown_entityref(name)
+                    self.lineno = self.lineno + res.group(0).count('\n')
+                    continue
+            elif rawdata[i] == ']':
+                if self.literal:
+                    data = rawdata[i]
+                    self.handle_data(data)
+                    i = i+1
+                    continue
+                if n-i < 3:
+                    break
+                if cdataclose.match(rawdata, i):
+                    self.syntax_error("bogus `]]>'")
+                self.handle_data(rawdata[i])
+                i = i+1
+                continue
+            else:
+                raise Error('neither < nor & ??')
+            # We get here only if incomplete matches but
+            # nothing else
+            break
+        # end while
+        if i > 0:
+            self.__at_start = 0
+        if end and i < n:
+            data = rawdata[i]
+            self.syntax_error("bogus `%s'" % data)
+            if not self.__accept_utf8 and illegal.search(data):
+                self.syntax_error('illegal character in content')
+            self.handle_data(data)
+            self.lineno = self.lineno + data.count('\n')
+            self.rawdata = rawdata[i+1:]
+            return self.goahead(end)
+        self.rawdata = rawdata[i:]
+        if end:
+            if not self.__seen_starttag:
+                self.syntax_error('no elements in file')
+            if self.stack:
+                self.syntax_error('missing end tags')
+                while self.stack:
+                    self.finish_endtag(self.stack[-1][0])
+
+    # Internal -- parse comment, return length or -1 if not terminated
+    def parse_comment(self, i):
+        rawdata = self.rawdata
+        if rawdata[i:i+4] != '<!--':
+            raise Error('unexpected call to handle_comment')
+        res = commentclose.search(rawdata, i+4)
+        if res is None:
+            return -1
+        if doubledash.search(rawdata, i+4, res.start(0)):
+            self.syntax_error("`--' inside comment")
+        if rawdata[res.start(0)-1] == '-':
+            self.syntax_error('comment cannot end in three dashes')
+        if not self.__accept_utf8 and \
+           illegal.search(rawdata, i+4, res.start(0)):
+            self.syntax_error('illegal character in comment')
+        self.handle_comment(rawdata[i+4: res.start(0)])
+        return res.end(0)
+
+    # Internal -- handle DOCTYPE tag, return length or -1 if not terminated
+    def parse_doctype(self, res):
+        rawdata = self.rawdata
+        n = len(rawdata)
+        name = res.group('name')
+        if self.__map_case:
+            name = name.lower()
+        pubid, syslit = res.group('pubid', 'syslit')
+        if pubid is not None:
+            pubid = pubid[1:-1]         # remove quotes
+            pubid = ' '.join(pubid.split()) # normalize
+        if syslit is not None: syslit = syslit[1:-1] # remove quotes
+        j = k = res.end(0)
+        if k >= n:
+            return -1
+        if rawdata[k] == '[':
+            level = 0
+            k = k+1
+            dq = sq = 0
+            while k < n:
+                c = rawdata[k]
+                if not sq and c == '"':
+                    dq = not dq
+                elif not dq and c == "'":
+                    sq = not sq
+                elif sq or dq:
+                    pass
+                elif level <= 0 and c == ']':
+                    res = endbracket.match(rawdata, k+1)
+                    if res is None:
+                        return -1
+                    self.handle_doctype(name, pubid, syslit, rawdata[j+1:k])
+                    return res.end(0)
+                elif c == '<':
+                    level = level + 1
+                elif c == '>':
+                    level = level - 1
+                    if level < 0:
+                        self.syntax_error("bogus `>' in DOCTYPE")
+                k = k+1
+        res = endbracketfind.match(rawdata, k)
+        if res is None:
+            return -1
+        if endbracket.match(rawdata, k) is None:
+            self.syntax_error('garbage in DOCTYPE')
+        self.handle_doctype(name, pubid, syslit, None)
+        return res.end(0)
+
+    # Internal -- handle CDATA tag, return length or -1 if not terminated
+    def parse_cdata(self, i):
+        rawdata = self.rawdata
+        if rawdata[i:i+9] != '<![CDATA[':
+            raise Error('unexpected call to parse_cdata')
+        res = cdataclose.search(rawdata, i+9)
+        if res is None:
+            return -1
+        if not self.__accept_utf8 and \
+           illegal.search(rawdata, i+9, res.start(0)):
+            self.syntax_error('illegal character in CDATA')
+        if not self.stack:
+            self.syntax_error('CDATA not in content')
+        self.handle_cdata(rawdata[i+9:res.start(0)])
+        return res.end(0)
+
+    __xml_namespace_attributes = {'ns':None, 'src':None, 'prefix':None}
+    # Internal -- handle a processing instruction tag
+    def parse_proc(self, i):
+        rawdata = self.rawdata
+        end = procclose.search(rawdata, i)
+        if end is None:
+            return -1
+        j = end.start(0)
+        if not self.__accept_utf8 and illegal.search(rawdata, i+2, j):
+            self.syntax_error('illegal character in processing instruction')
+        res = tagfind.match(rawdata, i+2)
+        if res is None:
+            raise Error('unexpected call to parse_proc')
+        k = res.end(0)
+        name = res.group(0)
+        if self.__map_case:
+            name = name.lower()
+        if name == 'xml:namespace':
+            self.syntax_error('old-fashioned namespace declaration')
+            self.__use_namespaces = -1
+            # namespace declaration
+            # this must come after the <?xml?> declaration (if any)
+            # and before the <!DOCTYPE> (if any).
+            if self.__seen_doctype or self.__seen_starttag:
+                self.syntax_error('xml:namespace declaration too late in document')
+            attrdict, namespace, k = self.parse_attributes(name, k, j)
+            if namespace:
+                self.syntax_error('namespace declaration inside namespace declaration')
+            for attrname in attrdict.keys():
+                if not attrname in self.__xml_namespace_attributes:
+                    self.syntax_error("unknown attribute `%s' in xml:namespace tag" % attrname)
+            if not 'ns' in attrdict or not 'prefix' in attrdict:
+                self.syntax_error('xml:namespace without required attributes')
+            prefix = attrdict.get('prefix')
+            if ncname.match(prefix) is None:
+                self.syntax_error('xml:namespace illegal prefix value')
+                return end.end(0)
+            if prefix in self.__namespaces:
+                self.syntax_error('xml:namespace prefix not unique')
+            self.__namespaces[prefix] = attrdict['ns']
+        else:
+            if name.lower() == 'xml':
+                self.syntax_error('illegal processing instruction target name')
+            self.handle_proc(name, rawdata[k:j])
+        return end.end(0)
+
+    # Internal -- parse attributes between i and j
+    def parse_attributes(self, tag, i, j):
+        rawdata = self.rawdata
+        attrdict = {}
+        namespace = {}
+        while i < j:
+            res = attrfind.match(rawdata, i)
+            if res is None:
+                break
+            attrname, attrvalue = res.group('name', 'value')
+            if self.__map_case:
+                attrname = attrname.lower()
+            i = res.end(0)
+            if attrvalue is None:
+                self.syntax_error("no value specified for attribute `%s'" % attrname)
+                attrvalue = attrname
+            elif attrvalue[:1] == "'" == attrvalue[-1:] or \
+                 attrvalue[:1] == '"' == attrvalue[-1:]:
+                attrvalue = attrvalue[1:-1]
+            elif not self.__accept_unquoted_attributes:
+                self.syntax_error("attribute `%s' value not quoted" % attrname)
+            res = xmlns.match(attrname)
+            if res is not None:
+                # namespace declaration
+                ncname = res.group('ncname')
+                namespace[ncname or ''] = attrvalue or None
+                if not self.__use_namespaces:
+                    self.__use_namespaces = len(self.stack)+1
+                continue
+            if '<' in attrvalue:
+                self.syntax_error("`<' illegal in attribute value")
+            if attrname in attrdict:
+                self.syntax_error("attribute `%s' specified twice" % attrname)
+            attrvalue = attrvalue.translate(attrtrans)
+            attrdict[attrname] = self.translate_references(attrvalue)
+        return attrdict, namespace, i
+
+    # Internal -- handle starttag, return length or -1 if not terminated
+    def parse_starttag(self, i):
+        rawdata = self.rawdata
+        # i points to start of tag
+        end = endbracketfind.match(rawdata, i+1)
+        if end is None:
+            return -1
+        tag = starttagmatch.match(rawdata, i)
+        if tag is None or tag.end(0) != end.end(0):
+            self.syntax_error('garbage in starttag')
+            return end.end(0)
+        nstag = tagname = tag.group('tagname')
+        if self.__map_case:
+            nstag = tagname = nstag.lower()
+        if not self.__seen_starttag and self.__seen_doctype and \
+           tagname != self.__seen_doctype:
+            self.syntax_error('starttag does not match DOCTYPE')
+        if self.__seen_starttag and not self.stack:
+            self.syntax_error('multiple elements on top level')
+        k, j = tag.span('attrs')
+        attrdict, nsdict, k = self.parse_attributes(tagname, k, j)
+        self.stack.append((tagname, nsdict, nstag))
+        if self.__use_namespaces:
+            res = qname.match(tagname)
+        else:
+            res = None
+        if res is not None:
+            prefix, nstag = res.group('prefix', 'local')
+            if prefix is None:
+                prefix = ''
+            ns = None
+            for t, d, nst in self.stack:
+                if prefix in d:
+                    ns = d[prefix]
+            if ns is None and prefix != '':
+                ns = self.__namespaces.get(prefix)
+            if ns is not None:
+                nstag = ns + ' ' + nstag
+            elif prefix != '':
+                nstag = prefix + ':' + nstag # undo split
+            self.stack[-1] = tagname, nsdict, nstag
+        # translate namespace of attributes
+        attrnamemap = {} # map from new name to old name (used for error reporting)
+        for key in attrdict.keys():
+            attrnamemap[key] = key
+        if self.__use_namespaces:
+            nattrdict = {}
+            for key, val in attrdict.items():
+                okey = key
+                res = qname.match(key)
+                if res is not None:
+                    aprefix, key = res.group('prefix', 'local')
+                    if self.__map_case:
+                        key = key.lower()
+                    if aprefix is not None:
+                        ans = None
+                        for t, d, nst in self.stack:
+                            if aprefix in d:
+                                ans = d[aprefix]
+                        if ans is None:
+                            ans = self.__namespaces.get(aprefix)
+                        if ans is not None:
+                            key = ans + ' ' + key
+                        else:
+                            key = aprefix + ':' + key
+                nattrdict[key] = val
+                attrnamemap[key] = okey
+            attrdict = nattrdict
+        attributes = self.attributes.get(nstag)
+        if attributes is not None:
+            for key in attrdict.keys():
+                if not key in attributes:
+                    self.syntax_error("unknown attribute `%s' in tag `%s'" % (attrnamemap[key], tagname))
+            for key, val in attributes.items():
+                if val is not None and not key in attrdict:
+                    attrdict[key] = val
+        method = self.elements.get(nstag, (None, None))[0]
+        self.finish_starttag(nstag, attrdict, method)
+        if tag.group('slash') == '/':
+            self.finish_endtag(tagname)
+        return tag.end(0)
+
+    # Internal -- parse endtag
+    def parse_endtag(self, i):
+        rawdata = self.rawdata
+        end = endbracketfind.match(rawdata, i+1)
+        if end is None:
+            return -1
+        res = tagfind.match(rawdata, i+2)
+        if res is None:
+            if self.literal:
+                self.handle_data(rawdata[i])
+                return i+1
+            if not self.__accept_missing_endtag_name:
+                self.syntax_error('no name specified in end tag')
+            tag = self.stack[-1][0]
+            k = i+2
+        else:
+            tag = res.group(0)
+            if self.__map_case:
+                tag = tag.lower()
+            if self.literal:
+                if not self.stack or tag != self.stack[-1][0]:
+                    self.handle_data(rawdata[i])
+                    return i+1
+            k = res.end(0)
+        if endbracket.match(rawdata, k) is None:
+            self.syntax_error('garbage in end tag')
+        self.finish_endtag(tag)
+        return end.end(0)
+
+    # Internal -- finish processing of start tag
+    def finish_starttag(self, tagname, attrdict, method):
+        if method is not None:
+            self.handle_starttag(tagname, method, attrdict)
+        else:
+            self.unknown_starttag(tagname, attrdict)
+
+    # Internal -- finish processing of end tag
+    def finish_endtag(self, tag):
+        self.literal = 0
+        if not tag:
+            self.syntax_error('name-less end tag')
+            found = len(self.stack) - 1
+            if found < 0:
+                self.unknown_endtag(tag)
+                return
+        else:
+            found = -1
+            for i in range(len(self.stack)):
+                if tag == self.stack[i][0]:
+                    found = i
+            if found == -1:
+                self.syntax_error('unopened end tag')
+                return
+        while len(self.stack) > found:
+            if found < len(self.stack) - 1:
+                self.syntax_error('missing close tag for %s' % self.stack[-1][2])
+            nstag = self.stack[-1][2]
+            method = self.elements.get(nstag, (None, None))[1]
+            if method is not None:
+                self.handle_endtag(nstag, method)
+            else:
+                self.unknown_endtag(nstag)
+            if self.__use_namespaces == len(self.stack):
+                self.__use_namespaces = 0
+            del self.stack[-1]
+
+    # Overridable -- handle xml processing instruction
+    def handle_xml(self, encoding, standalone):
+        pass
+
+    # Overridable -- handle DOCTYPE
+    def handle_doctype(self, tag, pubid, syslit, data):
+        pass
+
+    # Overridable -- handle start tag
+    def handle_starttag(self, tag, method, attrs):
+        method(attrs)
+
+    # Overridable -- handle end tag
+    def handle_endtag(self, tag, method):
+        method()
+
+    # Example -- handle character reference, no need to override
+    def handle_charref(self, name):
+        try:
+            if name[0] == 'x':
+                n = int(name[1:], 16)
+            else:
+                n = int(name)
+        except ValueError:
+            self.unknown_charref(name)
+            return
+        if not 0 <= n <= 255:
+            self.unknown_charref(name)
+            return
+        self.handle_data(chr(n))
+
+    # Definition of entities -- derived classes may override
+    entitydefs = {'lt': '&#60;',        # must use charref
+                  'gt': '&#62;',
+                  'amp': '&#38;',       # must use charref
+                  'quot': '&#34;',
+                  'apos': '&#39;',
+                  }
+
+    # Example -- handle data, should be overridden
+    def handle_data(self, data):
+        pass
+
+    # Example -- handle cdata, could be overridden
+    def handle_cdata(self, data):
+        pass
+
+    # Example -- handle comment, could be overridden
+    def handle_comment(self, data):
+        pass
+
+    # Example -- handle processing instructions, could be overridden
+    def handle_proc(self, name, data):
+        pass
+
+    # Example -- handle relatively harmless syntax errors, could be overridden
+    def syntax_error(self, message):
+        raise Error('Syntax error at line %d: %s' % (self.lineno, message))
+
+    # To be overridden -- handlers for unknown objects
+    def unknown_starttag(self, tag, attrs): pass
+    def unknown_endtag(self, tag): pass
+    def unknown_charref(self, ref): pass
+    def unknown_entityref(self, name):
+        self.syntax_error("reference to unknown entity `&%s;'" % name)
+
+
+class TestXMLParser(XMLParser):
+
+    def __init__(self, **kw):
+        self.testdata = ""
+        XMLParser.__init__(self, **kw)
+
+    def handle_xml(self, encoding, standalone):
+        self.flush()
+        print 'xml: encoding =',encoding,'standalone =',standalone
+
+    def handle_doctype(self, tag, pubid, syslit, data):
+        self.flush()
+        print 'DOCTYPE:',tag, repr(data)
+
+    def handle_data(self, data):
+        self.testdata = self.testdata + data
+        if len(repr(self.testdata)) >= 70:
+            self.flush()
+
+    def flush(self):
+        data = self.testdata
+        if data:
+            self.testdata = ""
+            print 'data:', repr(data)
+
+    def handle_cdata(self, data):
+        self.flush()
+        print 'cdata:', repr(data)
+
+    def handle_proc(self, name, data):
+        self.flush()
+        print 'processing:',name,repr(data)
+
+    def handle_comment(self, data):
+        self.flush()
+        r = repr(data)
+        if len(r) > 68:
+            r = r[:32] + '...' + r[-32:]
+        print 'comment:', r
+
+    def syntax_error(self, message):
+        print 'error at line %d:' % self.lineno, message
+
+    def unknown_starttag(self, tag, attrs):
+        self.flush()
+        if not attrs:
+            print 'start tag: <' + tag + '>'
+        else:
+            print 'start tag: <' + tag,
+            for name, value in attrs.items():
+                print name + '=' + '"' + value + '"',
+            print '>'
+
+    def unknown_endtag(self, tag):
+        self.flush()
+        print 'end tag: </' + tag + '>'
+
+    def unknown_entityref(self, ref):
+        self.flush()
+        print '*** unknown entity ref: &' + ref + ';'
+
+    def unknown_charref(self, ref):
+        self.flush()
+        print '*** unknown char ref: &#' + ref + ';'
+
+    def close(self):
+        XMLParser.close(self)
+        self.flush()
+
+def test(args = None):
+    import sys, getopt
+    from time import time
+
+    if not args:
+        args = sys.argv[1:]
+
+    opts, args = getopt.getopt(args, 'st')
+    klass = TestXMLParser
+    do_time = 0
+    for o, a in opts:
+        if o == '-s':
+            klass = XMLParser
+        elif o == '-t':
+            do_time = 1
+
+    if args:
+        file = args[0]
+    else:
+        file = 'test.xml'
+
+    if file == '-':
+        f = sys.stdin
+    else:
+        try:
+            f = open(file, 'r')
+        except IOError, msg:
+            print file, ":", msg
+            sys.exit(1)
+
+    data = f.read()
+    if f is not sys.stdin:
+        f.close()
+
+    x = klass()
+    t0 = time()
+    try:
+        if do_time:
+            x.feed(data)
+            x.close()
+        else:
+            for c in data:
+                x.feed(c)
+            x.close()
+    except Error, msg:
+        t1 = time()
+        print msg
+        if do_time:
+            print 'total time: %g' % (t1-t0)
+        sys.exit(1)
+    t1 = time()
+    if do_time:
+        print 'total time: %g' % (t1-t0)
+
+
+if __name__ == '__main__':
+    test()
diff --git a/src/main/resources/PythonLibs/xmlrpclib.py b/src/main/resources/PythonLibs/xmlrpclib.py
new file mode 100644
index 0000000000000000000000000000000000000000..b93ea23b929750c43d737de3d9aca8ccc4da5062
--- /dev/null
+++ b/src/main/resources/PythonLibs/xmlrpclib.py
@@ -0,0 +1,1639 @@
+#
+# XML-RPC CLIENT LIBRARY
+# $Id$
+#
+# an XML-RPC client interface for Python.
+#
+# the marshalling and response parser code can also be used to
+# implement XML-RPC servers.
+#
+# Notes:
+# this version is designed to work with Python 2.1 or newer.
+#
+# History:
+# 1999-01-14 fl  Created
+# 1999-01-15 fl  Changed dateTime to use localtime
+# 1999-01-16 fl  Added Binary/base64 element, default to RPC2 service
+# 1999-01-19 fl  Fixed array data element (from Skip Montanaro)
+# 1999-01-21 fl  Fixed dateTime constructor, etc.
+# 1999-02-02 fl  Added fault handling, handle empty sequences, etc.
+# 1999-02-10 fl  Fixed problem with empty responses (from Skip Montanaro)
+# 1999-06-20 fl  Speed improvements, pluggable parsers/transports (0.9.8)
+# 2000-11-28 fl  Changed boolean to check the truth value of its argument
+# 2001-02-24 fl  Added encoding/Unicode/SafeTransport patches
+# 2001-02-26 fl  Added compare support to wrappers (0.9.9/1.0b1)
+# 2001-03-28 fl  Make sure response tuple is a singleton
+# 2001-03-29 fl  Don't require empty params element (from Nicholas Riley)
+# 2001-06-10 fl  Folded in _xmlrpclib accelerator support (1.0b2)
+# 2001-08-20 fl  Base xmlrpclib.Error on built-in Exception (from Paul Prescod)
+# 2001-09-03 fl  Allow Transport subclass to override getparser
+# 2001-09-10 fl  Lazy import of urllib, cgi, xmllib (20x import speedup)
+# 2001-10-01 fl  Remove containers from memo cache when done with them
+# 2001-10-01 fl  Use faster escape method (80% dumps speedup)
+# 2001-10-02 fl  More dumps microtuning
+# 2001-10-04 fl  Make sure import expat gets a parser (from Guido van Rossum)
+# 2001-10-10 sm  Allow long ints to be passed as ints if they don't overflow
+# 2001-10-17 sm  Test for int and long overflow (allows use on 64-bit systems)
+# 2001-11-12 fl  Use repr() to marshal doubles (from Paul Felix)
+# 2002-03-17 fl  Avoid buffered read when possible (from James Rucker)
+# 2002-04-07 fl  Added pythondoc comments
+# 2002-04-16 fl  Added __str__ methods to datetime/binary wrappers
+# 2002-05-15 fl  Added error constants (from Andrew Kuchling)
+# 2002-06-27 fl  Merged with Python CVS version
+# 2002-10-22 fl  Added basic authentication (based on code from Phillip Eby)
+# 2003-01-22 sm  Add support for the bool type
+# 2003-02-27 gvr Remove apply calls
+# 2003-04-24 sm  Use cStringIO if available
+# 2003-04-25 ak  Add support for nil
+# 2003-06-15 gn  Add support for time.struct_time
+# 2003-07-12 gp  Correct marshalling of Faults
+# 2003-10-31 mvl Add multicall support
+# 2004-08-20 mvl Bump minimum supported Python version to 2.1
+#
+# Copyright (c) 1999-2002 by Secret Labs AB.
+# Copyright (c) 1999-2002 by Fredrik Lundh.
+#
+# info@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The XML-RPC client interface is
+#
+# Copyright (c) 1999-2002 by Secret Labs AB
+# Copyright (c) 1999-2002 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+#
+# things to look into some day:
+
+# TODO: sort out True/False/boolean issues for Python 2.3
+
+"""
+An XML-RPC client interface for Python.
+
+The marshalling and response parser code can also be used to
+implement XML-RPC servers.
+
+Exported exceptions:
+
+  Error          Base class for client errors
+  ProtocolError  Indicates an HTTP protocol error
+  ResponseError  Indicates a broken response package
+  Fault          Indicates an XML-RPC fault package
+
+Exported classes:
+
+  ServerProxy    Represents a logical connection to an XML-RPC server
+
+  MultiCall      Executor of boxcared xmlrpc requests
+  Boolean        boolean wrapper to generate a "boolean" XML-RPC value
+  DateTime       dateTime wrapper for an ISO 8601 string or time tuple or
+                 localtime integer value to generate a "dateTime.iso8601"
+                 XML-RPC value
+  Binary         binary data wrapper
+
+  SlowParser     Slow but safe standard parser (based on xmllib)
+  Marshaller     Generate an XML-RPC params chunk from a Python data structure
+  Unmarshaller   Unmarshal an XML-RPC response from incoming XML event message
+  Transport      Handles an HTTP transaction to an XML-RPC server
+  SafeTransport  Handles an HTTPS transaction to an XML-RPC server
+
+Exported constants:
+
+  True
+  False
+
+Exported functions:
+
+  boolean        Convert any Python value to an XML-RPC boolean
+  getparser      Create instance of the fastest available parser & attach
+                 to an unmarshalling object
+  dumps          Convert an argument tuple or a Fault instance to an XML-RPC
+                 request (or response, if the methodresponse option is used).
+  loads          Convert an XML-RPC packet to unmarshalled data plus a method
+                 name (None if not present).
+"""
+
+import re, string, time, operator
+
+from types import *
+import socket
+import errno
+import httplib
+try:
+    import gzip
+except ImportError:
+    gzip = None #python can be built without zlib/gzip support
+
+# --------------------------------------------------------------------
+# Internal stuff
+
+try:
+    unicode
+except NameError:
+    unicode = None # unicode support not available
+
+try:
+    import datetime
+except ImportError:
+    datetime = None
+
+try:
+    _bool_is_builtin = False.__class__.__name__ == "bool"
+except NameError:
+    _bool_is_builtin = 0
+
+def _decode(data, encoding, is8bit=re.compile("[\x80-\xff]").search):
+    # decode non-ascii string (if possible)
+    if unicode and encoding and is8bit(data):
+        data = unicode(data, encoding)
+    return data
+
+def escape(s, replace=string.replace):
+    s = replace(s, "&", "&amp;")
+    s = replace(s, "<", "&lt;")
+    return replace(s, ">", "&gt;",)
+
+if unicode:
+    def _stringify(string):
+        # convert to 7-bit ascii if possible
+        try:
+            return string.encode("ascii")
+        except UnicodeError:
+            return string
+else:
+    def _stringify(string):
+        return string
+
+__version__ = "1.0.1"
+
+# xmlrpc integer limits
+MAXINT =  2L**31-1
+MININT = -2L**31
+
+# --------------------------------------------------------------------
+# Error constants (from Dan Libby's specification at
+# http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php)
+
+# Ranges of errors
+PARSE_ERROR       = -32700
+SERVER_ERROR      = -32600
+APPLICATION_ERROR = -32500
+SYSTEM_ERROR      = -32400
+TRANSPORT_ERROR   = -32300
+
+# Specific errors
+NOT_WELLFORMED_ERROR  = -32700
+UNSUPPORTED_ENCODING  = -32701
+INVALID_ENCODING_CHAR = -32702
+INVALID_XMLRPC        = -32600
+METHOD_NOT_FOUND      = -32601
+INVALID_METHOD_PARAMS = -32602
+INTERNAL_ERROR        = -32603
+
+# --------------------------------------------------------------------
+# Exceptions
+
+##
+# Base class for all kinds of client-side errors.
+
+class Error(Exception):
+    """Base class for client errors."""
+    def __str__(self):
+        return repr(self)
+
+##
+# Indicates an HTTP-level protocol error.  This is raised by the HTTP
+# transport layer, if the server returns an error code other than 200
+# (OK).
+#
+# @param url The target URL.
+# @param errcode The HTTP error code.
+# @param errmsg The HTTP error message.
+# @param headers The HTTP header dictionary.
+
+class ProtocolError(Error):
+    """Indicates an HTTP protocol error."""
+    def __init__(self, url, errcode, errmsg, headers):
+        Error.__init__(self)
+        self.url = url
+        self.errcode = errcode
+        self.errmsg = errmsg
+        self.headers = headers
+    def __repr__(self):
+        return (
+            "<ProtocolError for %s: %s %s>" %
+            (self.url, self.errcode, self.errmsg)
+            )
+
+##
+# Indicates a broken XML-RPC response package.  This exception is
+# raised by the unmarshalling layer, if the XML-RPC response is
+# malformed.
+
+class ResponseError(Error):
+    """Indicates a broken response package."""
+    pass
+
+##
+# Indicates an XML-RPC fault response package.  This exception is
+# raised by the unmarshalling layer, if the XML-RPC response contains
+# a fault string.  This exception can also used as a class, to
+# generate a fault XML-RPC message.
+#
+# @param faultCode The XML-RPC fault code.
+# @param faultString The XML-RPC fault string.
+
+class Fault(Error):
+    """Indicates an XML-RPC fault package."""
+    def __init__(self, faultCode, faultString, **extra):
+        Error.__init__(self)
+        self.faultCode = faultCode
+        self.faultString = faultString
+    def __repr__(self):
+        return (
+            "<Fault %s: %s>" %
+            (self.faultCode, repr(self.faultString))
+            )
+
+# --------------------------------------------------------------------
+# Special values
+
+##
+# Wrapper for XML-RPC boolean values.  Use the xmlrpclib.True and
+# xmlrpclib.False constants, or the xmlrpclib.boolean() function, to
+# generate boolean XML-RPC values.
+#
+# @param value A boolean value.  Any true value is interpreted as True,
+#              all other values are interpreted as False.
+
+from sys import modules
+mod_dict = modules[__name__].__dict__
+if _bool_is_builtin:
+    boolean = Boolean = bool
+    # to avoid breaking code which references xmlrpclib.{True,False}
+    mod_dict['True'] = True
+    mod_dict['False'] = False
+else:
+    class Boolean:
+        """Boolean-value wrapper.
+
+        Use True or False to generate a "boolean" XML-RPC value.
+        """
+
+        def __init__(self, value = 0):
+            self.value = operator.truth(value)
+
+        def encode(self, out):
+            out.write("<value><boolean>%d</boolean></value>\n" % self.value)
+
+        def __cmp__(self, other):
+            if isinstance(other, Boolean):
+                other = other.value
+            return cmp(self.value, other)
+
+        def __repr__(self):
+            if self.value:
+                return "<Boolean True at %x>" % id(self)
+            else:
+                return "<Boolean False at %x>" % id(self)
+
+        def __int__(self):
+            return self.value
+
+        def __nonzero__(self):
+            return self.value
+
+    mod_dict['True'] = Boolean(1)
+    mod_dict['False'] = Boolean(0)
+
+    ##
+    # Map true or false value to XML-RPC boolean values.
+    #
+    # @def boolean(value)
+    # @param value A boolean value.  Any true value is mapped to True,
+    #              all other values are mapped to False.
+    # @return xmlrpclib.True or xmlrpclib.False.
+    # @see Boolean
+    # @see True
+    # @see False
+
+    def boolean(value, _truefalse=(False, True)):
+        """Convert any Python value to XML-RPC 'boolean'."""
+        return _truefalse[operator.truth(value)]
+
+del modules, mod_dict
+
+##
+# Wrapper for XML-RPC DateTime values.  This converts a time value to
+# the format used by XML-RPC.
+# <p>
+# The value can be given as a string in the format
+# "yyyymmddThh:mm:ss", as a 9-item time tuple (as returned by
+# time.localtime()), or an integer value (as returned by time.time()).
+# The wrapper uses time.localtime() to convert an integer to a time
+# tuple.
+#
+# @param value The time, given as an ISO 8601 string, a time
+#              tuple, or a integer time value.
+
+def _strftime(value):
+    if datetime:
+        if isinstance(value, datetime.datetime):
+            return "%04d%02d%02dT%02d:%02d:%02d" % (
+                value.year, value.month, value.day,
+                value.hour, value.minute, value.second)
+
+    if not isinstance(value, (TupleType, time.struct_time)):
+        if value == 0:
+            value = time.time()
+        value = time.localtime(value)
+
+    return "%04d%02d%02dT%02d:%02d:%02d" % value[:6]
+
+class DateTime:
+    """DateTime wrapper for an ISO 8601 string or time tuple or
+    localtime integer value to generate 'dateTime.iso8601' XML-RPC
+    value.
+    """
+
+    def __init__(self, value=0):
+        if isinstance(value, StringType):
+            self.value = value
+        else:
+            self.value = _strftime(value)
+
+    def make_comparable(self, other):
+        if isinstance(other, DateTime):
+            s = self.value
+            o = other.value
+        elif datetime and isinstance(other, datetime.datetime):
+            s = self.value
+            o = other.strftime("%Y%m%dT%H:%M:%S")
+        elif isinstance(other, (str, unicode)):
+            s = self.value
+            o = other
+        elif hasattr(other, "timetuple"):
+            s = self.timetuple()
+            o = other.timetuple()
+        else:
+            otype = (hasattr(other, "__class__")
+                     and other.__class__.__name__
+                     or type(other))
+            raise TypeError("Can't compare %s and %s" %
+                            (self.__class__.__name__, otype))
+        return s, o
+
+    def __lt__(self, other):
+        s, o = self.make_comparable(other)
+        return s < o
+
+    def __le__(self, other):
+        s, o = self.make_comparable(other)
+        return s <= o
+
+    def __gt__(self, other):
+        s, o = self.make_comparable(other)
+        return s > o
+
+    def __ge__(self, other):
+        s, o = self.make_comparable(other)
+        return s >= o
+
+    def __eq__(self, other):
+        s, o = self.make_comparable(other)
+        return s == o
+
+    def __ne__(self, other):
+        s, o = self.make_comparable(other)
+        return s != o
+
+    def timetuple(self):
+        return time.strptime(self.value, "%Y%m%dT%H:%M:%S")
+
+    def __cmp__(self, other):
+        s, o = self.make_comparable(other)
+        return cmp(s, o)
+
+    ##
+    # Get date/time value.
+    #
+    # @return Date/time value, as an ISO 8601 string.
+
+    def __str__(self):
+        return self.value
+
+    def __repr__(self):
+        return "<DateTime %s at %x>" % (repr(self.value), id(self))
+
+    def decode(self, data):
+        data = str(data)
+        self.value = string.strip(data)
+
+    def encode(self, out):
+        out.write("<value><dateTime.iso8601>")
+        out.write(self.value)
+        out.write("</dateTime.iso8601></value>\n")
+
+def _datetime(data):
+    # decode xml element contents into a DateTime structure.
+    value = DateTime()
+    value.decode(data)
+    return value
+
+def _datetime_type(data):
+    t = time.strptime(data, "%Y%m%dT%H:%M:%S")
+    return datetime.datetime(*tuple(t)[:6])
+
+##
+# Wrapper for binary data.  This can be used to transport any kind
+# of binary data over XML-RPC, using BASE64 encoding.
+#
+# @param data An 8-bit string containing arbitrary data.
+
+import base64
+try:
+    import cStringIO as StringIO
+except ImportError:
+    import StringIO
+
+class Binary:
+    """Wrapper for binary data."""
+
+    def __init__(self, data=None):
+        self.data = data
+
+    ##
+    # Get buffer contents.
+    #
+    # @return Buffer contents, as an 8-bit string.
+
+    def __str__(self):
+        return self.data or ""
+
+    def __cmp__(self, other):
+        if isinstance(other, Binary):
+            other = other.data
+        return cmp(self.data, other)
+
+    def decode(self, data):
+        self.data = base64.decodestring(data)
+
+    def encode(self, out):
+        out.write("<value><base64>\n")
+        base64.encode(StringIO.StringIO(self.data), out)
+        out.write("</base64></value>\n")
+
+def _binary(data):
+    # decode xml element contents into a Binary structure
+    value = Binary()
+    value.decode(data)
+    return value
+
+WRAPPERS = (DateTime, Binary)
+if not _bool_is_builtin:
+    WRAPPERS = WRAPPERS + (Boolean,)
+
+# --------------------------------------------------------------------
+# XML parsers
+
+try:
+    # optional xmlrpclib accelerator
+    import _xmlrpclib
+    FastParser = _xmlrpclib.Parser
+    FastUnmarshaller = _xmlrpclib.Unmarshaller
+except (AttributeError, ImportError):
+    FastParser = FastUnmarshaller = None
+
+try:
+    import _xmlrpclib
+    FastMarshaller = _xmlrpclib.Marshaller
+except (AttributeError, ImportError):
+    FastMarshaller = None
+
+try:
+    from xml.parsers import expat
+    if not hasattr(expat, "ParserCreate"):
+        raise ImportError
+except ImportError:
+    ExpatParser = None # expat not available
+else:
+    class ExpatParser:
+        # fast expat parser for Python 2.0 and later.
+        def __init__(self, target):
+            self._parser = parser = expat.ParserCreate(None, None)
+            self._target = target
+            parser.StartElementHandler = target.start
+            parser.EndElementHandler = target.end
+            parser.CharacterDataHandler = target.data
+            encoding = None
+            if not parser.returns_unicode:
+                encoding = "utf-8"
+            target.xml(encoding, None)
+
+        def feed(self, data):
+            self._parser.Parse(data, 0)
+
+        def close(self):
+            self._parser.Parse("", 1) # end of data
+            del self._target, self._parser # get rid of circular references
+
+class SlowParser:
+    """Default XML parser (based on xmllib.XMLParser)."""
+    # this is the slowest parser.
+    def __init__(self, target):
+        import xmllib # lazy subclassing (!)
+        if xmllib.XMLParser not in SlowParser.__bases__:
+            SlowParser.__bases__ = (xmllib.XMLParser,)
+        self.handle_xml = target.xml
+        self.unknown_starttag = target.start
+        self.handle_data = target.data
+        self.handle_cdata = target.data
+        self.unknown_endtag = target.end
+        try:
+            xmllib.XMLParser.__init__(self, accept_utf8=1)
+        except TypeError:
+            xmllib.XMLParser.__init__(self) # pre-2.0
+
+# --------------------------------------------------------------------
+# XML-RPC marshalling and unmarshalling code
+
+##
+# XML-RPC marshaller.
+#
+# @param encoding Default encoding for 8-bit strings.  The default
+#     value is None (interpreted as UTF-8).
+# @see dumps
+
+class Marshaller:
+    """Generate an XML-RPC params chunk from a Python data structure.
+
+    Create a Marshaller instance for each set of parameters, and use
+    the "dumps" method to convert your data (represented as a tuple)
+    to an XML-RPC params chunk.  To write a fault response, pass a
+    Fault instance instead.  You may prefer to use the "dumps" module
+    function for this purpose.
+    """
+
+    # by the way, if you don't understand what's going on in here,
+    # that's perfectly ok.
+
+    def __init__(self, encoding=None, allow_none=0):
+        self.memo = {}
+        self.data = None
+        self.encoding = encoding
+        self.allow_none = allow_none
+
+    dispatch = {}
+
+    def dumps(self, values):
+        out = []
+        write = out.append
+        dump = self.__dump
+        if isinstance(values, Fault):
+            # fault instance
+            write("<fault>\n")
+            dump({'faultCode': values.faultCode,
+                  'faultString': values.faultString},
+                 write)
+            write("</fault>\n")
+        else:
+            # parameter block
+            # FIXME: the xml-rpc specification allows us to leave out
+            # the entire <params> block if there are no parameters.
+            # however, changing this may break older code (including
+            # old versions of xmlrpclib.py), so this is better left as
+            # is for now.  See @XMLRPC3 for more information. /F
+            write("<params>\n")
+            for v in values:
+                write("<param>\n")
+                dump(v, write)
+                write("</param>\n")
+            write("</params>\n")
+        result = string.join(out, "")
+        return result
+
+    def __dump(self, value, write):
+        try:
+            f = self.dispatch[type(value)]
+        except KeyError:
+            # check if this object can be marshalled as a structure
+            try:
+                value.__dict__
+            except:
+                raise TypeError, "cannot marshal %s objects" % type(value)
+            # check if this class is a sub-class of a basic type,
+            # because we don't know how to marshal these types
+            # (e.g. a string sub-class)
+            for type_ in type(value).__mro__:
+                if type_ in self.dispatch.keys():
+                    raise TypeError, "cannot marshal %s objects" % type(value)
+            f = self.dispatch[InstanceType]
+        f(self, value, write)
+
+    def dump_nil (self, value, write):
+        if not self.allow_none:
+            raise TypeError, "cannot marshal None unless allow_none is enabled"
+        write("<value><nil/></value>")
+    dispatch[NoneType] = dump_nil
+
+    def dump_int(self, value, write):
+        # in case ints are > 32 bits
+        if value > MAXINT or value < MININT:
+            raise OverflowError, "int exceeds XML-RPC limits"
+        write("<value><int>")
+        write(str(value))
+        write("</int></value>\n")
+    dispatch[IntType] = dump_int
+
+    if _bool_is_builtin:
+        def dump_bool(self, value, write):
+            write("<value><boolean>")
+            write(value and "1" or "0")
+            write("</boolean></value>\n")
+        dispatch[bool] = dump_bool
+
+    def dump_long(self, value, write):
+        if value > MAXINT or value < MININT:
+            raise OverflowError, "long int exceeds XML-RPC limits"
+        write("<value><int>")
+        write(str(int(value)))
+        write("</int></value>\n")
+    dispatch[LongType] = dump_long
+
+    def dump_double(self, value, write):
+        write("<value><double>")
+        write(repr(value))
+        write("</double></value>\n")
+    dispatch[FloatType] = dump_double
+
+    def dump_string(self, value, write, escape=escape):
+        write("<value><string>")
+        write(escape(value))
+        write("</string></value>\n")
+    dispatch[StringType] = dump_string
+
+    if unicode:
+        def dump_unicode(self, value, write, escape=escape):
+            value = value.encode(self.encoding)
+            write("<value><string>")
+            write(escape(value))
+            write("</string></value>\n")
+        dispatch[UnicodeType] = dump_unicode
+
+    def dump_array(self, value, write):
+        i = id(value)
+        if i in self.memo:
+            raise TypeError, "cannot marshal recursive sequences"
+        self.memo[i] = None
+        dump = self.__dump
+        write("<value><array><data>\n")
+        for v in value:
+            dump(v, write)
+        write("</data></array></value>\n")
+        del self.memo[i]
+    dispatch[TupleType] = dump_array
+    dispatch[ListType] = dump_array
+
+    def dump_struct(self, value, write, escape=escape):
+        i = id(value)
+        if i in self.memo:
+            raise TypeError, "cannot marshal recursive dictionaries"
+        self.memo[i] = None
+        dump = self.__dump
+        write("<value><struct>\n")
+        for k, v in value.items():
+            write("<member>\n")
+            if type(k) is not StringType:
+                if unicode and type(k) is UnicodeType:
+                    k = k.encode(self.encoding)
+                else:
+                    raise TypeError, "dictionary key must be string"
+            write("<name>%s</name>\n" % escape(k))
+            dump(v, write)
+            write("</member>\n")
+        write("</struct></value>\n")
+        del self.memo[i]
+    dispatch[DictType] = dump_struct
+
+    if datetime:
+        def dump_datetime(self, value, write):
+            write("<value><dateTime.iso8601>")
+            write(_strftime(value))
+            write("</dateTime.iso8601></value>\n")
+        dispatch[datetime.datetime] = dump_datetime
+
+    def dump_instance(self, value, write):
+        # check for special wrappers
+        if value.__class__ in WRAPPERS:
+            self.write = write
+            value.encode(self)
+            del self.write
+        else:
+            # store instance attributes as a struct (really?)
+            self.dump_struct(value.__dict__, write)
+    dispatch[InstanceType] = dump_instance
+
+##
+# XML-RPC unmarshaller.
+#
+# @see loads
+
+class Unmarshaller:
+    """Unmarshal an XML-RPC response, based on incoming XML event
+    messages (start, data, end).  Call close() to get the resulting
+    data structure.
+
+    Note that this reader is fairly tolerant, and gladly accepts bogus
+    XML-RPC data without complaining (but not bogus XML).
+    """
+
+    # and again, if you don't understand what's going on in here,
+    # that's perfectly ok.
+
+    def __init__(self, use_datetime=0):
+        self._type = None
+        self._stack = []
+        self._marks = []
+        self._data = []
+        self._methodname = None
+        self._encoding = "utf-8"
+        self.append = self._stack.append
+        self._use_datetime = use_datetime
+        if use_datetime and not datetime:
+            raise ValueError, "the datetime module is not available"
+
+    def close(self):
+        # return response tuple and target method
+        if self._type is None or self._marks:
+            raise ResponseError()
+        if self._type == "fault":
+            raise Fault(**self._stack[0])
+        return tuple(self._stack)
+
+    def getmethodname(self):
+        return self._methodname
+
+    #
+    # event handlers
+
+    def xml(self, encoding, standalone):
+        self._encoding = encoding
+        # FIXME: assert standalone == 1 ???
+
+    def start(self, tag, attrs):
+        # prepare to handle this element
+        if tag == "array" or tag == "struct":
+            self._marks.append(len(self._stack))
+        self._data = []
+        self._value = (tag == "value")
+
+    def data(self, text):
+        self._data.append(text)
+
+    def end(self, tag, join=string.join):
+        # call the appropriate end tag handler
+        try:
+            f = self.dispatch[tag]
+        except KeyError:
+            pass # unknown tag ?
+        else:
+            return f(self, join(self._data, ""))
+
+    #
+    # accelerator support
+
+    def end_dispatch(self, tag, data):
+        # dispatch data
+        try:
+            f = self.dispatch[tag]
+        except KeyError:
+            pass # unknown tag ?
+        else:
+            return f(self, data)
+
+    #
+    # element decoders
+
+    dispatch = {}
+
+    def end_nil (self, data):
+        self.append(None)
+        self._value = 0
+    dispatch["nil"] = end_nil
+
+    def end_boolean(self, data):
+        if data == "0":
+            self.append(False)
+        elif data == "1":
+            self.append(True)
+        else:
+            raise TypeError, "bad boolean value"
+        self._value = 0
+    dispatch["boolean"] = end_boolean
+
+    def end_int(self, data):
+        self.append(int(data))
+        self._value = 0
+    dispatch["i4"] = end_int
+    dispatch["i8"] = end_int
+    dispatch["int"] = end_int
+
+    def end_double(self, data):
+        self.append(float(data))
+        self._value = 0
+    dispatch["double"] = end_double
+
+    def end_string(self, data):
+        if self._encoding:
+            data = _decode(data, self._encoding)
+        self.append(_stringify(data))
+        self._value = 0
+    dispatch["string"] = end_string
+    dispatch["name"] = end_string # struct keys are always strings
+
+    def end_array(self, data):
+        mark = self._marks.pop()
+        # map arrays to Python lists
+        self._stack[mark:] = [self._stack[mark:]]
+        self._value = 0
+    dispatch["array"] = end_array
+
+    def end_struct(self, data):
+        mark = self._marks.pop()
+        # map structs to Python dictionaries
+        dict = {}
+        items = self._stack[mark:]
+        for i in range(0, len(items), 2):
+            dict[_stringify(items[i])] = items[i+1]
+        self._stack[mark:] = [dict]
+        self._value = 0
+    dispatch["struct"] = end_struct
+
+    def end_base64(self, data):
+        value = Binary()
+        value.decode(data)
+        self.append(value)
+        self._value = 0
+    dispatch["base64"] = end_base64
+
+    def end_dateTime(self, data):
+        value = DateTime()
+        value.decode(data)
+        if self._use_datetime:
+            value = _datetime_type(data)
+        self.append(value)
+    dispatch["dateTime.iso8601"] = end_dateTime
+
+    def end_value(self, data):
+        # if we stumble upon a value element with no internal
+        # elements, treat it as a string element
+        if self._value:
+            self.end_string(data)
+    dispatch["value"] = end_value
+
+    def end_params(self, data):
+        self._type = "params"
+    dispatch["params"] = end_params
+
+    def end_fault(self, data):
+        self._type = "fault"
+    dispatch["fault"] = end_fault
+
+    def end_methodName(self, data):
+        if self._encoding:
+            data = _decode(data, self._encoding)
+        self._methodname = data
+        self._type = "methodName" # no params
+    dispatch["methodName"] = end_methodName
+
+## Multicall support
+#
+
+class _MultiCallMethod:
+    # some lesser magic to store calls made to a MultiCall object
+    # for batch execution
+    def __init__(self, call_list, name):
+        self.__call_list = call_list
+        self.__name = name
+    def __getattr__(self, name):
+        return _MultiCallMethod(self.__call_list, "%s.%s" % (self.__name, name))
+    def __call__(self, *args):
+        self.__call_list.append((self.__name, args))
+
+class MultiCallIterator:
+    """Iterates over the results of a multicall. Exceptions are
+    raised in response to xmlrpc faults."""
+
+    def __init__(self, results):
+        self.results = results
+
+    def __getitem__(self, i):
+        item = self.results[i]
+        if type(item) == type({}):
+            raise Fault(item['faultCode'], item['faultString'])
+        elif type(item) == type([]):
+            return item[0]
+        else:
+            raise ValueError,\
+                  "unexpected type in multicall result"
+
+class MultiCall:
+    """server -> a object used to boxcar method calls
+
+    server should be a ServerProxy object.
+
+    Methods can be added to the MultiCall using normal
+    method call syntax e.g.:
+
+    multicall = MultiCall(server_proxy)
+    multicall.add(2,3)
+    multicall.get_address("Guido")
+
+    To execute the multicall, call the MultiCall object e.g.:
+
+    add_result, address = multicall()
+    """
+
+    def __init__(self, server):
+        self.__server = server
+        self.__call_list = []
+
+    def __repr__(self):
+        return "<MultiCall at %x>" % id(self)
+
+    __str__ = __repr__
+
+    def __getattr__(self, name):
+        return _MultiCallMethod(self.__call_list, name)
+
+    def __call__(self):
+        marshalled_list = []
+        for name, args in self.__call_list:
+            marshalled_list.append({'methodName' : name, 'params' : args})
+
+        return MultiCallIterator(self.__server.system.multicall(marshalled_list))
+
+# --------------------------------------------------------------------
+# convenience functions
+
+##
+# Create a parser object, and connect it to an unmarshalling instance.
+# This function picks the fastest available XML parser.
+#
+# return A (parser, unmarshaller) tuple.
+
+def getparser(use_datetime=0):
+    """getparser() -> parser, unmarshaller
+
+    Create an instance of the fastest available parser, and attach it
+    to an unmarshalling object.  Return both objects.
+    """
+    if use_datetime and not datetime:
+        raise ValueError, "the datetime module is not available"
+    if FastParser and FastUnmarshaller:
+        if use_datetime:
+            mkdatetime = _datetime_type
+        else:
+            mkdatetime = _datetime
+        target = FastUnmarshaller(True, False, _binary, mkdatetime, Fault)
+        parser = FastParser(target)
+    else:
+        target = Unmarshaller(use_datetime=use_datetime)
+        if FastParser:
+            parser = FastParser(target)
+        elif ExpatParser:
+            parser = ExpatParser(target)
+        else:
+            parser = SlowParser(target)
+    return parser, target
+
+##
+# Convert a Python tuple or a Fault instance to an XML-RPC packet.
+#
+# @def dumps(params, **options)
+# @param params A tuple or Fault instance.
+# @keyparam methodname If given, create a methodCall request for
+#     this method name.
+# @keyparam methodresponse If given, create a methodResponse packet.
+#     If used with a tuple, the tuple must be a singleton (that is,
+#     it must contain exactly one element).
+# @keyparam encoding The packet encoding.
+# @return A string containing marshalled data.
+
+def dumps(params, methodname=None, methodresponse=None, encoding=None,
+          allow_none=0):
+    """data [,options] -> marshalled data
+
+    Convert an argument tuple or a Fault instance to an XML-RPC
+    request (or response, if the methodresponse option is used).
+
+    In addition to the data object, the following options can be given
+    as keyword arguments:
+
+        methodname: the method name for a methodCall packet
+
+        methodresponse: true to create a methodResponse packet.
+        If this option is used with a tuple, the tuple must be
+        a singleton (i.e. it can contain only one element).
+
+        encoding: the packet encoding (default is UTF-8)
+
+    All 8-bit strings in the data structure are assumed to use the
+    packet encoding.  Unicode strings are automatically converted,
+    where necessary.
+    """
+
+    assert isinstance(params, TupleType) or isinstance(params, Fault),\
+           "argument must be tuple or Fault instance"
+
+    if isinstance(params, Fault):
+        methodresponse = 1
+    elif methodresponse and isinstance(params, TupleType):
+        assert len(params) == 1, "response tuple must be a singleton"
+
+    if not encoding:
+        encoding = "utf-8"
+
+    if FastMarshaller:
+        m = FastMarshaller(encoding)
+    else:
+        m = Marshaller(encoding, allow_none)
+
+    data = m.dumps(params)
+
+    if encoding != "utf-8":
+        xmlheader = "<?xml version='1.0' encoding='%s'?>\n" % str(encoding)
+    else:
+        xmlheader = "<?xml version='1.0'?>\n" # utf-8 is default
+
+    # standard XML-RPC wrappings
+    if methodname:
+        # a method call
+        if not isinstance(methodname, StringType):
+            methodname = methodname.encode(encoding)
+        data = (
+            xmlheader,
+            "<methodCall>\n"
+            "<methodName>", methodname, "</methodName>\n",
+            data,
+            "</methodCall>\n"
+            )
+    elif methodresponse:
+        # a method response, or a fault structure
+        data = (
+            xmlheader,
+            "<methodResponse>\n",
+            data,
+            "</methodResponse>\n"
+            )
+    else:
+        return data # return as is
+    return string.join(data, "")
+
+##
+# Convert an XML-RPC packet to a Python object.  If the XML-RPC packet
+# represents a fault condition, this function raises a Fault exception.
+#
+# @param data An XML-RPC packet, given as an 8-bit string.
+# @return A tuple containing the unpacked data, and the method name
+#     (None if not present).
+# @see Fault
+
+def loads(data, use_datetime=0):
+    """data -> unmarshalled data, method name
+
+    Convert an XML-RPC packet to unmarshalled data plus a method
+    name (None if not present).
+
+    If the XML-RPC packet represents a fault condition, this function
+    raises a Fault exception.
+    """
+    p, u = getparser(use_datetime=use_datetime)
+    p.feed(data)
+    p.close()
+    return u.close(), u.getmethodname()
+
+##
+# Encode a string using the gzip content encoding such as specified by the
+# Content-Encoding: gzip
+# in the HTTP header, as described in RFC 1952
+#
+# @param data the unencoded data
+# @return the encoded data
+
+def gzip_encode(data):
+    """data -> gzip encoded data
+
+    Encode data using the gzip content encoding as described in RFC 1952
+    """
+    if not gzip:
+        raise NotImplementedError
+    f = StringIO.StringIO()
+    gzf = gzip.GzipFile(mode="wb", fileobj=f, compresslevel=1)
+    gzf.write(data)
+    gzf.close()
+    encoded = f.getvalue()
+    f.close()
+    return encoded
+
+##
+# Decode a string using the gzip content encoding such as specified by the
+# Content-Encoding: gzip
+# in the HTTP header, as described in RFC 1952
+#
+# @param data The encoded data
+# @return the unencoded data
+# @raises ValueError if data is not correctly coded.
+
+def gzip_decode(data):
+    """gzip encoded data -> unencoded data
+
+    Decode data using the gzip content encoding as described in RFC 1952
+    """
+    if not gzip:
+        raise NotImplementedError
+    f = StringIO.StringIO(data)
+    gzf = gzip.GzipFile(mode="rb", fileobj=f)
+    try:
+        decoded = gzf.read()
+    except IOError:
+        raise ValueError("invalid data")
+    f.close()
+    gzf.close()
+    return decoded
+
+##
+# Return a decoded file-like object for the gzip encoding
+# as described in RFC 1952.
+#
+# @param response A stream supporting a read() method
+# @return a file-like object that the decoded data can be read() from
+
+class GzipDecodedResponse(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):
+        #response doesn't support tell() and read(), required by
+        #GzipFile
+        if not gzip:
+            raise NotImplementedError
+        self.stringio = StringIO.StringIO(response.read())
+        gzip.GzipFile.__init__(self, mode="rb", fileobj=self.stringio)
+
+    def close(self):
+        gzip.GzipFile.close(self)
+        self.stringio.close()
+
+
+# --------------------------------------------------------------------
+# request dispatcher
+
+class _Method:
+    # some magic to bind an XML-RPC method to an RPC server.
+    # supports "nested" methods (e.g. examples.getStateName)
+    def __init__(self, send, name):
+        self.__send = send
+        self.__name = name
+    def __getattr__(self, name):
+        return _Method(self.__send, "%s.%s" % (self.__name, name))
+    def __call__(self, *args):
+        return self.__send(self.__name, args)
+
+##
+# Standard transport class for XML-RPC over HTTP.
+# <p>
+# You can create custom transports by subclassing this method, and
+# overriding selected methods.
+
+class Transport:
+    """Handles an HTTP transaction to an XML-RPC server."""
+
+    # client identifier (may be overridden)
+    user_agent = "xmlrpclib.py/%s (by www.pythonware.com)" % __version__
+
+    #if true, we'll request gzip encoding
+    accept_gzip_encoding = True
+
+    # if positive, encode request using gzip if it exceeds this threshold
+    # note that many server will get confused, so only use it if you know
+    # that they can decode such a request
+    encode_threshold = None #None = don't encode
+
+    def __init__(self, use_datetime=0):
+        self._use_datetime = use_datetime
+        self._connection = (None, None)
+        self._extra_headers = []
+    ##
+    # Send a complete request, and parse the response.
+    # Retry request if a cached connection has disconnected.
+    #
+    # @param host Target host.
+    # @param handler Target PRC handler.
+    # @param request_body XML-RPC request body.
+    # @param verbose Debugging flag.
+    # @return Parsed response.
+
+    def request(self, host, handler, request_body, verbose=0):
+        #retry request once if cached connection has gone cold
+        for i in (0, 1):
+            try:
+                return self.single_request(host, handler, request_body, verbose)
+            except socket.error, e:
+                if i or e.errno not in (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE):
+                    raise
+            except httplib.BadStatusLine: #close after we sent request
+                if i:
+                    raise
+
+    ##
+    # Send a complete request, and parse the response.
+    #
+    # @param host Target host.
+    # @param handler Target PRC handler.
+    # @param request_body XML-RPC request body.
+    # @param verbose Debugging flag.
+    # @return Parsed response.
+
+    def single_request(self, host, handler, request_body, verbose=0):
+        # issue XML-RPC request
+
+        h = self.make_connection(host)
+        if verbose:
+            h.set_debuglevel(1)
+
+        try:
+            self.send_request(h, handler, request_body)
+            self.send_host(h, host)
+            self.send_user_agent(h)
+            self.send_content(h, request_body)
+
+            response = h.getresponse(buffering=True)
+            if response.status == 200:
+                self.verbose = verbose
+                return self.parse_response(response)
+        except Fault:
+            raise
+        except Exception:
+            # All unexpected errors leave connection in
+            # a strange state, so we clear it.
+            self.close()
+            raise
+
+        #discard any response data and raise exception
+        if (response.getheader("content-length", 0)):
+            response.read()
+        raise ProtocolError(
+            host + handler,
+            response.status, response.reason,
+            response.msg,
+            )
+
+    ##
+    # Create parser.
+    #
+    # @return A 2-tuple containing a parser and a unmarshaller.
+
+    def getparser(self):
+        # get parser and unmarshaller
+        return getparser(use_datetime=self._use_datetime)
+
+    ##
+    # Get authorization info from host parameter
+    # Host may be a string, or a (host, x509-dict) tuple; if a string,
+    # it is checked for a "user:pw@host" format, and a "Basic
+    # Authentication" header is added if appropriate.
+    #
+    # @param host Host descriptor (URL or (URL, x509 info) tuple).
+    # @return A 3-tuple containing (actual host, extra headers,
+    #     x509 info).  The header and x509 fields may be None.
+
+    def get_host_info(self, host):
+
+        x509 = {}
+        if isinstance(host, TupleType):
+            host, x509 = host
+
+        import urllib
+        auth, host = urllib.splituser(host)
+
+        if auth:
+            import base64
+            auth = base64.encodestring(urllib.unquote(auth))
+            auth = string.join(string.split(auth), "") # get rid of whitespace
+            extra_headers = [
+                ("Authorization", "Basic " + auth)
+                ]
+        else:
+            extra_headers = None
+
+        return host, extra_headers, x509
+
+    ##
+    # Connect to server.
+    #
+    # @param host Target host.
+    # @return A connection handle.
+
+    def make_connection(self, host):
+        #return an existing connection if possible.  This allows
+        #HTTP/1.1 keep-alive.
+        if self._connection and host == self._connection[0]:
+            return self._connection[1]
+
+        # create a HTTP connection object from a host descriptor
+        chost, self._extra_headers, x509 = self.get_host_info(host)
+        #store the host argument along with the connection object
+        self._connection = host, httplib.HTTPConnection(chost)
+        return self._connection[1]
+
+    ##
+    # Clear any cached connection object.
+    # Used in the event of socket errors.
+    #
+    def close(self):
+        if self._connection[1]:
+            self._connection[1].close()
+            self._connection = (None, None)
+
+    ##
+    # Send request header.
+    #
+    # @param connection Connection handle.
+    # @param handler Target RPC handler.
+    # @param request_body XML-RPC body.
+
+    def send_request(self, connection, handler, request_body):
+        if (self.accept_gzip_encoding and gzip):
+            connection.putrequest("POST", handler, skip_accept_encoding=True)
+            connection.putheader("Accept-Encoding", "gzip")
+        else:
+            connection.putrequest("POST", handler)
+
+    ##
+    # Send host name.
+    #
+    # @param connection Connection handle.
+    # @param host Host name.
+    #
+    # Note: This function doesn't actually add the "Host"
+    # header anymore, it is done as part of the connection.putrequest() in
+    # send_request() above.
+
+    def send_host(self, connection, host):
+        extra_headers = self._extra_headers
+        if extra_headers:
+            if isinstance(extra_headers, DictType):
+                extra_headers = extra_headers.items()
+            for key, value in extra_headers:
+                connection.putheader(key, value)
+
+    ##
+    # Send user-agent identifier.
+    #
+    # @param connection Connection handle.
+
+    def send_user_agent(self, connection):
+        connection.putheader("User-Agent", self.user_agent)
+
+    ##
+    # Send request body.
+    #
+    # @param connection Connection handle.
+    # @param request_body XML-RPC request body.
+
+    def send_content(self, connection, request_body):
+        connection.putheader("Content-Type", "text/xml")
+
+        #optionally encode the request
+        if (self.encode_threshold is not None and
+            self.encode_threshold < len(request_body) and
+            gzip):
+            connection.putheader("Content-Encoding", "gzip")
+            request_body = gzip_encode(request_body)
+
+        connection.putheader("Content-Length", str(len(request_body)))
+        connection.endheaders(request_body)
+
+    ##
+    # Parse response.
+    #
+    # @param file Stream.
+    # @return Response tuple and target method.
+
+    def parse_response(self, response):
+        # read response data from httpresponse, and parse it
+
+        # Check for new http response object, else it is a file object
+        if hasattr(response,'getheader'):
+            if response.getheader("Content-Encoding", "") == "gzip":
+                stream = GzipDecodedResponse(response)
+            else:
+                stream = response
+        else:
+            stream = response
+
+        p, u = self.getparser()
+
+        while 1:
+            data = stream.read(1024)
+            if not data:
+                break
+            if self.verbose:
+                print "body:", repr(data)
+            p.feed(data)
+
+        if stream is not response:
+            stream.close()
+        p.close()
+
+        return u.close()
+
+##
+# Standard transport class for XML-RPC over HTTPS.
+
+class SafeTransport(Transport):
+    """Handles an HTTPS transaction to an XML-RPC server."""
+
+    # FIXME: mostly untested
+
+    def make_connection(self, host):
+        if self._connection and host == self._connection[0]:
+            return self._connection[1]
+        # create a HTTPS connection object from a host descriptor
+        # host may be a string, or a (host, x509-dict) tuple
+        try:
+            HTTPS = httplib.HTTPSConnection
+        except AttributeError:
+            raise NotImplementedError(
+                "your version of httplib doesn't support HTTPS"
+                )
+        else:
+            chost, self._extra_headers, x509 = self.get_host_info(host)
+            self._connection = host, HTTPS(chost, None, **(x509 or {}))
+            return self._connection[1]
+
+##
+# Standard server proxy.  This class establishes a virtual connection
+# to an XML-RPC server.
+# <p>
+# This class is available as ServerProxy and Server.  New code should
+# use ServerProxy, to avoid confusion.
+#
+# @def ServerProxy(uri, **options)
+# @param uri The connection point on the server.
+# @keyparam transport A transport factory, compatible with the
+#    standard transport class.
+# @keyparam encoding The default encoding used for 8-bit strings
+#    (default is UTF-8).
+# @keyparam verbose Use a true value to enable debugging output.
+#    (printed to standard output).
+# @see Transport
+
+class ServerProxy:
+    """uri [,options] -> a logical connection to an XML-RPC server
+
+    uri is the connection point on the server, given as
+    scheme://host/target.
+
+    The standard implementation always supports the "http" scheme.  If
+    SSL socket support is available (Python 2.0), it also supports
+    "https".
+
+    If the target part and the slash preceding it are both omitted,
+    "/RPC2" is assumed.
+
+    The following options can be given as keyword arguments:
+
+        transport: a transport factory
+        encoding: the request encoding (default is UTF-8)
+
+    All 8-bit strings passed to the server proxy are assumed to use
+    the given encoding.
+    """
+
+    def __init__(self, uri, transport=None, encoding=None, verbose=0,
+                 allow_none=0, use_datetime=0):
+        # establish a "logical" server connection
+
+        if isinstance(uri, unicode):
+            uri = uri.encode('ISO-8859-1')
+
+        # get the url
+        import urllib
+        type, uri = urllib.splittype(uri)
+        if type not in ("http", "https"):
+            raise IOError, "unsupported XML-RPC protocol"
+        self.__host, self.__handler = urllib.splithost(uri)
+        if not self.__handler:
+            self.__handler = "/RPC2"
+
+        if transport is None:
+            if type == "https":
+                transport = SafeTransport(use_datetime=use_datetime)
+            else:
+                transport = Transport(use_datetime=use_datetime)
+        self.__transport = transport
+
+        self.__encoding = encoding
+        self.__verbose = verbose
+        self.__allow_none = allow_none
+
+    def __close(self):
+        self.__transport.close()
+
+    def __request(self, methodname, params):
+        # call a method on the remote server
+
+        request = dumps(params, methodname, encoding=self.__encoding,
+                        allow_none=self.__allow_none)
+
+        response = self.__transport.request(
+            self.__host,
+            self.__handler,
+            request,
+            verbose=self.__verbose
+            )
+
+        if len(response) == 1:
+            response = response[0]
+
+        return response
+
+    def __repr__(self):
+        return (
+            "<ServerProxy for %s%s>" %
+            (self.__host, self.__handler)
+            )
+
+    __str__ = __repr__
+
+    def __getattr__(self, name):
+        # magic method dispatcher
+        return _Method(self.__request, name)
+
+    # note: to call a remote object with an non-standard name, use
+    # result getattr(server, "strange-python-name")(args)
+
+    def __call__(self, attr):
+        """A workaround to get special attributes on the ServerProxy
+           without interfering with the magic __getattr__
+        """
+        if attr == "close":
+            return self.__close
+        elif attr == "transport":
+            return self.__transport
+        raise AttributeError("Attribute %r not found" % (attr,))
+
+# compatibility
+
+Server = ServerProxy
+
+# --------------------------------------------------------------------
+# test code
+
+if __name__ == "__main__":
+
+    # simple test program (from the XML-RPC specification)
+
+    # server = ServerProxy("http://localhost:8000") # local server
+    server = ServerProxy("http://time.xmlrpc.com/RPC2")
+
+    print server
+
+    try:
+        print server.currentTime.getCurrentTime()
+    except Error, v:
+        print "ERROR", v
+
+    multi = MultiCall(server)
+    multi.currentTime.getCurrentTime()
+    multi.currentTime.getCurrentTime()
+    try:
+        for response in multi():
+            print response
+    except Error, v:
+        print "ERROR", v
diff --git a/src/main/resources/PythonLibs/zipfile.py b/src/main/resources/PythonLibs/zipfile.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca2a0bbb045bf7621358b690663df5e3eb4248ac
--- /dev/null
+++ b/src/main/resources/PythonLibs/zipfile.py
@@ -0,0 +1,1439 @@
+"""
+Read and write ZIP files.
+"""
+import struct, os, time, sys, shutil
+import binascii, cStringIO, stat
+import io
+import re
+
+try:
+    import zlib # We may need its compression method
+    crc32 = zlib.crc32
+except ImportError:
+    zlib = None
+    crc32 = binascii.crc32
+
+__all__ = ["BadZipfile", "error", "ZIP_STORED", "ZIP_DEFLATED", "is_zipfile",
+           "ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile" ]
+
+is_jython = sys.platform.startswith('java')
+
+class BadZipfile(Exception):
+    pass
+
+
+class LargeZipFile(Exception):
+    """
+    Raised when writing a zipfile, the zipfile requires ZIP64 extensions
+    and those extensions are disabled.
+    """
+
+error = BadZipfile      # The exception raised by this module
+
+ZIP64_LIMIT = (1 << 31) - 1
+ZIP_FILECOUNT_LIMIT = 1 << 16
+ZIP_MAX_COMMENT = (1 << 16) - 1
+
+# constants for Zip file compression methods
+ZIP_STORED = 0
+ZIP_DEFLATED = 8
+# Other ZIP compression methods not supported
+
+# Below are some formats and associated data for reading/writing headers using
+# the struct module.  The names and structures of headers/records are those used
+# in the PKWARE description of the ZIP file format:
+#     http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+# (URL valid as of January 2008)
+
+# The "end of central directory" structure, magic number, size, and indices
+# (section V.I in the format document)
+structEndArchive = "<4s4H2LH"
+stringEndArchive = "PK\005\006"
+sizeEndCentDir = struct.calcsize(structEndArchive)
+
+_ECD_SIGNATURE = 0
+_ECD_DISK_NUMBER = 1
+_ECD_DISK_START = 2
+_ECD_ENTRIES_THIS_DISK = 3
+_ECD_ENTRIES_TOTAL = 4
+_ECD_SIZE = 5
+_ECD_OFFSET = 6
+_ECD_COMMENT_SIZE = 7
+# These last two indices are not part of the structure as defined in the
+# spec, but they are used internally by this module as a convenience
+_ECD_COMMENT = 8
+_ECD_LOCATION = 9
+
+# The "central directory" structure, magic number, size, and indices
+# of entries in the structure (section V.F in the format document)
+structCentralDir = "<4s4B4HL2L5H2L"
+stringCentralDir = "PK\001\002"
+sizeCentralDir = struct.calcsize(structCentralDir)
+
+# indexes of entries in the central directory structure
+_CD_SIGNATURE = 0
+_CD_CREATE_VERSION = 1
+_CD_CREATE_SYSTEM = 2
+_CD_EXTRACT_VERSION = 3
+_CD_EXTRACT_SYSTEM = 4
+_CD_FLAG_BITS = 5
+_CD_COMPRESS_TYPE = 6
+_CD_TIME = 7
+_CD_DATE = 8
+_CD_CRC = 9
+_CD_COMPRESSED_SIZE = 10
+_CD_UNCOMPRESSED_SIZE = 11
+_CD_FILENAME_LENGTH = 12
+_CD_EXTRA_FIELD_LENGTH = 13
+_CD_COMMENT_LENGTH = 14
+_CD_DISK_NUMBER_START = 15
+_CD_INTERNAL_FILE_ATTRIBUTES = 16
+_CD_EXTERNAL_FILE_ATTRIBUTES = 17
+_CD_LOCAL_HEADER_OFFSET = 18
+
+# The "local file header" structure, magic number, size, and indices
+# (section V.A in the format document)
+structFileHeader = "<4s2B4HL2L2H"
+stringFileHeader = "PK\003\004"
+sizeFileHeader = struct.calcsize(structFileHeader)
+
+_FH_SIGNATURE = 0
+_FH_EXTRACT_VERSION = 1
+_FH_EXTRACT_SYSTEM = 2
+_FH_GENERAL_PURPOSE_FLAG_BITS = 3
+_FH_COMPRESSION_METHOD = 4
+_FH_LAST_MOD_TIME = 5
+_FH_LAST_MOD_DATE = 6
+_FH_CRC = 7
+_FH_COMPRESSED_SIZE = 8
+_FH_UNCOMPRESSED_SIZE = 9
+_FH_FILENAME_LENGTH = 10
+_FH_EXTRA_FIELD_LENGTH = 11
+
+# The "Zip64 end of central directory locator" structure, magic number, and size
+structEndArchive64Locator = "<4sLQL"
+stringEndArchive64Locator = "PK\x06\x07"
+sizeEndCentDir64Locator = struct.calcsize(structEndArchive64Locator)
+
+# The "Zip64 end of central directory" record, magic number, size, and indices
+# (section V.G in the format document)
+structEndArchive64 = "<4sQ2H2L4Q"
+stringEndArchive64 = "PK\x06\x06"
+sizeEndCentDir64 = struct.calcsize(structEndArchive64)
+
+_CD64_SIGNATURE = 0
+_CD64_DIRECTORY_RECSIZE = 1
+_CD64_CREATE_VERSION = 2
+_CD64_EXTRACT_VERSION = 3
+_CD64_DISK_NUMBER = 4
+_CD64_DISK_NUMBER_START = 5
+_CD64_NUMBER_ENTRIES_THIS_DISK = 6
+_CD64_NUMBER_ENTRIES_TOTAL = 7
+_CD64_DIRECTORY_SIZE = 8
+_CD64_OFFSET_START_CENTDIR = 9
+
+def _check_zipfile(fp):
+    try:
+        if _EndRecData(fp):
+            return True         # file has correct magic number
+    except IOError:
+        pass
+    return False
+
+def is_zipfile(filename):
+    """Quickly see if a file is a ZIP file by checking the magic number.
+
+    The filename argument may be a file or file-like object too.
+    """
+    result = False
+    try:
+        if hasattr(filename, "read"):
+            result = _check_zipfile(fp=filename)
+        else:
+            with open(filename, "rb") as fp:
+                result = _check_zipfile(fp)
+    except IOError:
+        pass
+    return result
+
+def _EndRecData64(fpin, offset, endrec):
+    """
+    Read the ZIP64 end-of-archive records and use that to update endrec
+    """
+    try:
+        fpin.seek(offset - sizeEndCentDir64Locator, 2)
+    except IOError:
+        # If the seek fails, the file is not large enough to contain a ZIP64
+        # end-of-archive record, so just return the end record we were given.
+        return endrec
+
+    data = fpin.read(sizeEndCentDir64Locator)
+    sig, diskno, reloff, disks = struct.unpack(structEndArchive64Locator, data)
+    if sig != stringEndArchive64Locator:
+        return endrec
+
+    if diskno != 0 or disks != 1:
+        raise BadZipfile("zipfiles that span multiple disks are not supported")
+
+    # Assume no 'zip64 extensible data'
+    fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2)
+    data = fpin.read(sizeEndCentDir64)
+    sig, sz, create_version, read_version, disk_num, disk_dir, \
+            dircount, dircount2, dirsize, diroffset = \
+            struct.unpack(structEndArchive64, data)
+    if sig != stringEndArchive64:
+        return endrec
+
+    # Update the original endrec using data from the ZIP64 record
+    endrec[_ECD_SIGNATURE] = sig
+    endrec[_ECD_DISK_NUMBER] = disk_num
+    endrec[_ECD_DISK_START] = disk_dir
+    endrec[_ECD_ENTRIES_THIS_DISK] = dircount
+    endrec[_ECD_ENTRIES_TOTAL] = dircount2
+    endrec[_ECD_SIZE] = dirsize
+    endrec[_ECD_OFFSET] = diroffset
+    return endrec
+
+
+def _EndRecData(fpin):
+    """Return data from the "End of Central Directory" record, or None.
+
+    The data is a list of the nine items in the ZIP "End of central dir"
+    record followed by a tenth item, the file seek offset of this record."""
+
+    # Determine file size
+    fpin.seek(0, 2)
+    filesize = fpin.tell()
+
+    # Check to see if this is ZIP file with no archive comment (the
+    # "end of central directory" structure should be the last item in the
+    # file if this is the case).
+    try:
+        fpin.seek(-sizeEndCentDir, 2)
+    except IOError:
+        return None
+    data = fpin.read()
+    if data[0:4] == stringEndArchive and data[-2:] == "\000\000":
+        # the signature is correct and there's no comment, unpack structure
+        endrec = struct.unpack(structEndArchive, data)
+        endrec=list(endrec)
+
+        # Append a blank comment and record start offset
+        endrec.append("")
+        endrec.append(filesize - sizeEndCentDir)
+
+        # Try to read the "Zip64 end of central directory" structure
+        return _EndRecData64(fpin, -sizeEndCentDir, endrec)
+
+    # Either this is not a ZIP file, or it is a ZIP file with an archive
+    # comment.  Search the end of the file for the "end of central directory"
+    # record signature. The comment is the last item in the ZIP file and may be
+    # up to 64K long.  It is assumed that the "end of central directory" magic
+    # number does not appear in the comment.
+    maxCommentStart = max(filesize - (1 << 16) - sizeEndCentDir, 0)
+    fpin.seek(maxCommentStart, 0)
+    data = fpin.read()
+    start = data.rfind(stringEndArchive)
+    if start >= 0:
+        # found the magic number; attempt to unpack and interpret
+        recData = data[start:start+sizeEndCentDir]
+        endrec = list(struct.unpack(structEndArchive, recData))
+        comment = data[start+sizeEndCentDir:]
+        # check that comment length is correct
+        if endrec[_ECD_COMMENT_SIZE] == len(comment):
+            # Append the archive comment and start offset
+            endrec.append(comment)
+            endrec.append(maxCommentStart + start)
+
+            # Try to read the "Zip64 end of central directory" structure
+            return _EndRecData64(fpin, maxCommentStart + start - filesize,
+                                 endrec)
+
+    # Unable to find a valid end of central directory structure
+    return
+
+
+class ZipInfo (object):
+    """Class with attributes describing each file in the ZIP archive."""
+
+    __slots__ = (
+            'orig_filename',
+            'filename',
+            'date_time',
+            'compress_type',
+            'comment',
+            'extra',
+            'create_system',
+            'create_version',
+            'extract_version',
+            'reserved',
+            'flag_bits',
+            'volume',
+            'internal_attr',
+            'external_attr',
+            'header_offset',
+            'CRC',
+            'compress_size',
+            'file_size',
+            '_raw_time',
+        )
+
+    def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
+        self.orig_filename = filename   # Original file name in archive
+
+        # Terminate the file name at the first null byte.  Null bytes in file
+        # names are used as tricks by viruses in archives.
+        null_byte = filename.find(chr(0))
+        if null_byte >= 0:
+            filename = filename[0:null_byte]
+        # This is used to ensure paths in generated ZIP files always use
+        # forward slashes as the directory separator, as required by the
+        # ZIP format specification.
+        if os.sep != "/" and os.sep in filename:
+            filename = filename.replace(os.sep, "/")
+
+        self.filename = filename        # Normalized file name
+        self.date_time = date_time      # year, month, day, hour, min, sec
+        # Standard values:
+        self.compress_type = ZIP_STORED # Type of compression for the file
+        self.comment = ""               # Comment for each file
+        self.extra = ""                 # ZIP extra data
+        if sys.platform == 'win32':
+            self.create_system = 0          # System which created ZIP archive
+        else:
+            # Assume everything else is unix-y
+            self.create_system = 3          # System which created ZIP archive
+        self.create_version = 20        # Version which created ZIP archive
+        self.extract_version = 20       # Version needed to extract archive
+        self.reserved = 0               # Must be zero
+        self.flag_bits = 0              # ZIP flag bits
+        self.volume = 0                 # Volume number of file header
+        self.internal_attr = 0          # Internal attributes
+        self.external_attr = 0          # External file attributes
+        # Other attributes are set by class ZipFile:
+        # header_offset         Byte offset to the file header
+        # CRC                   CRC-32 of the uncompressed file
+        # compress_size         Size of the compressed file
+        # file_size             Size of the uncompressed file
+
+    def FileHeader(self):
+        """Return the per-file header as a string."""
+        dt = self.date_time
+        dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
+        dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
+        if self.flag_bits & 0x08:
+            # Set these to zero because we write them after the file data
+            CRC = compress_size = file_size = 0
+        else:
+            CRC = self.CRC
+            compress_size = self.compress_size
+            file_size = self.file_size
+
+        extra = self.extra
+
+        if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
+            # File is larger than what fits into a 4 byte integer,
+            # fall back to the ZIP64 extension
+            fmt = '<HHQQ'
+            extra = extra + struct.pack(fmt,
+                    1, struct.calcsize(fmt)-4, file_size, compress_size)
+            file_size = 0xffffffff
+            compress_size = 0xffffffff
+            self.extract_version = max(45, self.extract_version)
+            self.create_version = max(45, self.extract_version)
+
+        filename, flag_bits = self._encodeFilenameFlags()
+        header = struct.pack(structFileHeader, stringFileHeader,
+                 self.extract_version, self.reserved, flag_bits,
+                 self.compress_type, dostime, dosdate, CRC,
+                 compress_size, file_size,
+                 len(filename), len(extra))
+        return header + filename + extra
+
+    def _encodeFilenameFlags(self):
+        if isinstance(self.filename, unicode):
+            try:
+                return self.filename.encode('ascii'), self.flag_bits
+            except UnicodeEncodeError:
+                return self.filename.encode('utf-8'), self.flag_bits | 0x800
+        else:
+            return self.filename, self.flag_bits
+
+    def _decodeFilename(self):
+        if self.flag_bits & 0x800:
+            return self.filename.decode('utf-8')
+        else:
+            return self.filename
+
+    def _decodeExtra(self):
+        # Try to decode the extra field.
+        extra = self.extra
+        unpack = struct.unpack
+        while extra:
+            tp, ln = unpack('<HH', extra[:4])
+            if tp == 1:
+                if ln >= 24:
+                    counts = unpack('<QQQ', extra[4:28])
+                elif ln == 16:
+                    counts = unpack('<QQ', extra[4:20])
+                elif ln == 8:
+                    counts = unpack('<Q', extra[4:12])
+                elif ln == 0:
+                    counts = ()
+                else:
+                    raise RuntimeError, "Corrupt extra field %s"%(ln,)
+
+                idx = 0
+
+                # ZIP64 extension (large files and/or large archives)
+                if self.file_size in (0xffffffffffffffffL, 0xffffffffL):
+                    self.file_size = counts[idx]
+                    idx += 1
+
+                if self.compress_size == 0xFFFFFFFFL:
+                    self.compress_size = counts[idx]
+                    idx += 1
+
+                if self.header_offset == 0xffffffffL:
+                    old = self.header_offset
+                    self.header_offset = counts[idx]
+                    idx+=1
+
+            extra = extra[ln+4:]
+
+
+class _ZipDecrypter:
+    """Class to handle decryption of files stored within a ZIP archive.
+
+    ZIP supports a password-based form of encryption. Even though known
+    plaintext attacks have been found against it, it is still useful
+    to be able to get data out of such a file.
+
+    Usage:
+        zd = _ZipDecrypter(mypwd)
+        plain_char = zd(cypher_char)
+        plain_text = map(zd, cypher_text)
+    """
+
+    def _GenerateCRCTable():
+        """Generate a CRC-32 table.
+
+        ZIP encryption uses the CRC32 one-byte primitive for scrambling some
+        internal keys. We noticed that a direct implementation is faster than
+        relying on binascii.crc32().
+        """
+        poly = 0xedb88320
+        table = [0] * 256
+        for i in range(256):
+            crc = i
+            for j in range(8):
+                if crc & 1:
+                    crc = ((crc >> 1) & 0x7FFFFFFF) ^ poly
+                else:
+                    crc = ((crc >> 1) & 0x7FFFFFFF)
+            table[i] = crc
+        return table
+    crctable = _GenerateCRCTable()
+
+    def _crc32(self, ch, crc):
+        """Compute the CRC32 primitive on one byte."""
+        return ((crc >> 8) & 0xffffff) ^ self.crctable[(crc ^ ord(ch)) & 0xff]
+
+    def __init__(self, pwd):
+        self.key0 = 305419896
+        self.key1 = 591751049
+        self.key2 = 878082192
+        for p in pwd:
+            self._UpdateKeys(p)
+
+    def _UpdateKeys(self, c):
+        self.key0 = self._crc32(c, self.key0)
+        self.key1 = (self.key1 + (self.key0 & 255)) & 4294967295
+        self.key1 = (self.key1 * 134775813 + 1) & 4294967295
+        self.key2 = self._crc32(chr((self.key1 >> 24) & 255), self.key2)
+
+    def __call__(self, c):
+        """Decrypt a single character."""
+        c = ord(c)
+        k = self.key2 | 2
+        c = c ^ (((k * (k^1)) >> 8) & 255)
+        c = chr(c)
+        self._UpdateKeys(c)
+        return c
+
+class ZipExtFile(io.BufferedIOBase):
+    """File-like object for reading an archive member.
+       Is returned by ZipFile.open().
+    """
+
+    # Max size supported by decompressor.
+    MAX_N = 1 << 31 - 1
+
+    # Read from compressed files in 4k blocks.
+    MIN_READ_SIZE = 4096
+
+    # Search for universal newlines or line chunks.
+    PATTERN = re.compile(r'^(?P<chunk>[^\r\n]+)|(?P<newline>\n|\r\n?)')
+
+    def __init__(self, fileobj, mode, zipinfo, decrypter=None):
+        self._fileobj = fileobj
+        self._decrypter = decrypter
+
+        self._compress_type = zipinfo.compress_type
+        self._compress_size = zipinfo.compress_size
+        self._compress_left = zipinfo.compress_size
+
+        if self._compress_type == ZIP_DEFLATED:
+            self._decompressor = zlib.decompressobj(-15)
+        self._unconsumed = ''
+
+        self._readbuffer = ''
+        self._offset = 0
+
+        self._universal = 'U' in mode
+        self.newlines = None
+
+        # Adjust read size for encrypted files since the first 12 bytes
+        # are for the encryption/password information.
+        if self._decrypter is not None:
+            self._compress_left -= 12
+
+        self.mode = mode
+        self.name = zipinfo.filename
+
+        if hasattr(zipinfo, 'CRC'):
+            self._expected_crc = zipinfo.CRC
+            self._running_crc = crc32(b'') & 0xffffffff
+        else:
+            self._expected_crc = None
+
+    def readline(self, limit=-1):
+        """Read and return a line from the stream.
+
+        If limit is specified, at most limit bytes will be read.
+        """
+
+        if not self._universal and limit < 0:
+            # Shortcut common case - newline found in buffer.
+            i = self._readbuffer.find('\n', self._offset) + 1
+            if i > 0:
+                line = self._readbuffer[self._offset: i]
+                self._offset = i
+                return line
+
+        if not self._universal:
+            return io.BufferedIOBase.readline(self, limit)
+
+        line = ''
+        while limit < 0 or len(line) < limit:
+            readahead = self.peek(2)
+            if readahead == '':
+                return line
+
+            #
+            # Search for universal newlines or line chunks.
+            #
+            # The pattern returns either a line chunk or a newline, but not
+            # both. Combined with peek(2), we are assured that the sequence
+            # '\r\n' is always retrieved completely and never split into
+            # separate newlines - '\r', '\n' due to coincidental readaheads.
+            #
+            match = self.PATTERN.search(readahead)
+            newline = match.group('newline')
+            if newline is not None:
+                if self.newlines is None:
+                    self.newlines = []
+                if newline not in self.newlines:
+                    self.newlines.append(newline)
+                self._offset += len(newline)
+                return line + '\n'
+
+            chunk = match.group('chunk')
+            if limit >= 0:
+                chunk = chunk[: limit - len(line)]
+
+            self._offset += len(chunk)
+            line += chunk
+
+        return line
+
+    def peek(self, n=1):
+        """Returns buffered bytes without advancing the position."""
+        if n > len(self._readbuffer) - self._offset:
+            chunk = self.read(n)
+            self._offset -= len(chunk)
+
+        # Return up to 512 bytes to reduce allocation overhead for tight loops.
+        return self._readbuffer[self._offset: self._offset + 512]
+
+    def readable(self):
+        return True
+
+    def read(self, n=-1):
+        """Read and return up to n bytes.
+        If the argument is omitted, None, or negative, data is read and returned until EOF is reached..
+        """
+        buf = ''
+        if n is None:
+            n = -1
+        while True:
+            if n < 0:
+                data = self.read1(n)
+            elif n > len(buf):
+                data = self.read1(n - len(buf))
+            else:
+                return buf
+            if len(data) == 0:
+                return buf
+            buf += data
+
+    def _update_crc(self, newdata, eof):
+        # Update the CRC using the given data.
+        if self._expected_crc is None:
+            # No need to compute the CRC if we don't have a reference value
+            return
+        self._running_crc = crc32(newdata, self._running_crc) & 0xffffffff
+        # Check the CRC if we're at the end of the file
+        if eof and self._running_crc != self._expected_crc:
+            raise BadZipfile("Bad CRC-32 for file %r" % self.name)
+
+    def read1(self, n):
+        """Read up to n bytes with at most one read() system call."""
+
+        # Simplify algorithm (branching) by transforming negative n to large n.
+        if n < 0 or n is None:
+            n = self.MAX_N
+
+        # Bytes available in read buffer.
+        len_readbuffer = len(self._readbuffer) - self._offset
+
+        # Read from file.
+        if self._compress_left > 0 and n > len_readbuffer + len(self._unconsumed):
+            nbytes = n - len_readbuffer - len(self._unconsumed)
+            nbytes = max(nbytes, self.MIN_READ_SIZE)
+            nbytes = min(nbytes, self._compress_left)
+
+            data = self._fileobj.read(nbytes)
+            self._compress_left -= len(data)
+
+            if data and self._decrypter is not None:
+                data = ''.join(map(self._decrypter, data))
+
+            if self._compress_type == ZIP_STORED:
+                self._update_crc(data, eof=(self._compress_left==0))
+                self._readbuffer = self._readbuffer[self._offset:] + data
+                self._offset = 0
+            else:
+                # Prepare deflated bytes for decompression.
+                self._unconsumed += data
+
+        # Handle unconsumed data.
+        if (len(self._unconsumed) > 0 and n > len_readbuffer and
+            self._compress_type == ZIP_DEFLATED):
+            data = self._decompressor.decompress(
+                self._unconsumed,
+                max(n - len_readbuffer, self.MIN_READ_SIZE)
+            )
+
+            self._unconsumed = self._decompressor.unconsumed_tail
+            eof = len(self._unconsumed) == 0 and self._compress_left == 0
+            if eof:
+                data += self._decompressor.flush()
+
+            self._update_crc(data, eof=eof)
+            self._readbuffer = self._readbuffer[self._offset:] + data
+            self._offset = 0
+
+        # Read from buffer.
+        data = self._readbuffer[self._offset: self._offset + n]
+        self._offset += len(data)
+        return data
+
+
+
+class ZipFile:
+    """ Class with methods to open, read, write, close, list zip files.
+
+    z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False)
+
+    file: Either the path to the file, or a file-like object.
+          If it is a path, the file will be opened and closed by ZipFile.
+    mode: The mode can be either read "r", write "w" or append "a".
+    compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib).
+    allowZip64: if True ZipFile will create files with ZIP64 extensions when
+                needed, otherwise it will raise an exception when this would
+                be necessary.
+
+    """
+
+    fp = None                   # Set here since __del__ checks it
+
+    def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False):
+        """Open the ZIP file with mode read "r", write "w" or append "a"."""
+        if mode not in ("r", "w", "a"):
+            raise RuntimeError('ZipFile() requires mode "r", "w", or "a"')
+
+        if compression == ZIP_STORED:
+            pass
+        elif compression == ZIP_DEFLATED:
+            if not zlib:
+                raise RuntimeError,\
+                      "Compression requires the (missing) zlib module"
+        else:
+            raise RuntimeError, "That compression method is not supported"
+
+        self._allowZip64 = allowZip64
+        self._didModify = False
+        self.debug = 0  # Level of printing: 0 through 3
+        self.NameToInfo = {}    # Find file info given name
+        self.filelist = []      # List of ZipInfo instances for archive
+        self.compression = compression  # Method of compression
+        self.mode = key = mode.replace('b', '')[0]
+        self.pwd = None
+        self.comment = ''
+
+        # Check if we were passed a file-like object
+        if isinstance(file, basestring):
+            self._filePassed = 0
+            self.filename = file
+            modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
+            try:
+                self.fp = open(file, modeDict[mode])
+            except IOError:
+                if mode == 'a':
+                    mode = key = 'w'
+                    self.fp = open(file, modeDict[mode])
+                else:
+                    raise
+        else:
+            self._filePassed = 1
+            self.fp = file
+            self.filename = getattr(file, 'name', None)
+
+        if key == 'r':
+            self._GetContents()
+        elif key == 'w':
+            # set the modified flag so central directory gets written
+            # even if no files are added to the archive
+            self._didModify = True
+        elif key == 'a':
+            try:
+                # See if file is a zip file
+                self._RealGetContents()
+                # seek to start of directory and overwrite
+                self.fp.seek(self.start_dir, 0)
+            except BadZipfile:
+                # file is not a zip file, just append
+                self.fp.seek(0, 2)
+
+                # set the modified flag so central directory gets written
+                # even if no files are added to the archive
+                self._didModify = True
+        else:
+            if not self._filePassed:
+                self.fp.close()
+                self.fp = None
+            raise RuntimeError, 'Mode must be "r", "w" or "a"'
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.close()
+
+    def _GetContents(self):
+        """Read the directory, making sure we close the file if the format
+        is bad."""
+        try:
+            self._RealGetContents()
+        except BadZipfile:
+            if not self._filePassed:
+                self.fp.close()
+                self.fp = None
+            raise
+
+    def _RealGetContents(self):
+        """Read in the table of contents for the ZIP file."""
+        fp = self.fp
+        try:
+            endrec = _EndRecData(fp)
+        except IOError:
+            raise BadZipfile("File is not a zip file")
+        if not endrec:
+            raise BadZipfile, "File is not a zip file"
+        if self.debug > 1:
+            print endrec
+        size_cd = endrec[_ECD_SIZE]             # bytes in central directory
+        offset_cd = endrec[_ECD_OFFSET]         # offset of central directory
+        self.comment = endrec[_ECD_COMMENT]     # archive comment
+
+        # "concat" is zero, unless zip was concatenated to another file
+        concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
+        if endrec[_ECD_SIGNATURE] == stringEndArchive64:
+            # If Zip64 extension structures are present, account for them
+            concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)
+
+        if self.debug > 2:
+            inferred = concat + offset_cd
+            print "given, inferred, offset", offset_cd, inferred, concat
+        # self.start_dir:  Position of start of central directory
+        self.start_dir = offset_cd + concat
+        fp.seek(self.start_dir, 0)
+        data = fp.read(size_cd)
+        fp = cStringIO.StringIO(data)
+        total = 0
+        while total < size_cd:
+            centdir = fp.read(sizeCentralDir)
+            if centdir[0:4] != stringCentralDir:
+                raise BadZipfile, "Bad magic number for central directory"
+            centdir = struct.unpack(structCentralDir, centdir)
+            if self.debug > 2:
+                print centdir
+            filename = fp.read(centdir[_CD_FILENAME_LENGTH])
+            # Create ZipInfo instance to store file information
+            x = ZipInfo(filename)
+            x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
+            x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
+            x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
+            (x.create_version, x.create_system, x.extract_version, x.reserved,
+                x.flag_bits, x.compress_type, t, d,
+                x.CRC, x.compress_size, x.file_size) = centdir[1:12]
+            x.volume, x.internal_attr, x.external_attr = centdir[15:18]
+            # Convert date/time code to (year, month, day, hour, min, sec)
+            x._raw_time = t
+            x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F,
+                                     t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
+
+            x._decodeExtra()
+            x.header_offset = x.header_offset + concat
+            x.filename = x._decodeFilename()
+            self.filelist.append(x)
+            self.NameToInfo[x.filename] = x
+
+            # update total bytes read from central directory
+            total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH]
+                     + centdir[_CD_EXTRA_FIELD_LENGTH]
+                     + centdir[_CD_COMMENT_LENGTH])
+
+            if self.debug > 2:
+                print "total", total
+
+
+    def namelist(self):
+        """Return a list of file names in the archive."""
+        l = []
+        for data in self.filelist:
+            l.append(data.filename)
+        return l
+
+    def infolist(self):
+        """Return a list of class ZipInfo instances for files in the
+        archive."""
+        return self.filelist
+
+    def printdir(self):
+        """Print a table of contents for the zip file."""
+        print "%-46s %19s %12s" % ("File Name", "Modified    ", "Size")
+        for zinfo in self.filelist:
+            date = "%d-%02d-%02d %02d:%02d:%02d" % zinfo.date_time[:6]
+            print "%-46s %s %12d" % (zinfo.filename, date, zinfo.file_size)
+
+    def testzip(self):
+        """Read all the files and check the CRC."""
+        chunk_size = 2 ** 20
+        for zinfo in self.filelist:
+            try:
+                # Read by chunks, to avoid an OverflowError or a
+                # MemoryError with very large embedded files.
+                f = self.open(zinfo.filename, "r")
+                while f.read(chunk_size):     # Check CRC-32
+                    pass
+            except BadZipfile:
+                return zinfo.filename
+
+    def getinfo(self, name):
+        """Return the instance of ZipInfo given 'name'."""
+        info = self.NameToInfo.get(name)
+        if info is None:
+            raise KeyError(
+                'There is no item named %r in the archive' % name)
+
+        return info
+
+    def setpassword(self, pwd):
+        """Set default password for encrypted files."""
+        self.pwd = pwd
+
+    def read(self, name, pwd=None):
+        """Return file bytes (as a string) for name."""
+        return self.open(name, "r", pwd).read()
+
+    def open(self, name, mode="r", pwd=None):
+        """Return file-like object for 'name'."""
+        if mode not in ("r", "U", "rU"):
+            raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
+        if not self.fp:
+            raise RuntimeError, \
+                  "Attempt to read ZIP archive that was already closed"
+
+        # Only open a new file for instances where we were not
+        # given a file object in the constructor
+        if self._filePassed:
+            zef_file = self.fp
+        else:
+            zef_file = open(self.filename, 'rb')
+
+        # Make sure we have an info object
+        if isinstance(name, ZipInfo):
+            # 'name' is already an info object
+            zinfo = name
+        else:
+            # Get info object for name
+            zinfo = self.getinfo(name)
+
+        zef_file.seek(zinfo.header_offset, 0)
+
+        # Skip the file header:
+        fheader = zef_file.read(sizeFileHeader)
+        if fheader[0:4] != stringFileHeader:
+            raise BadZipfile, "Bad magic number for file header"
+
+        fheader = struct.unpack(structFileHeader, fheader)
+        fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
+        if fheader[_FH_EXTRA_FIELD_LENGTH]:
+            zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
+
+        if fname != zinfo.orig_filename:
+            raise BadZipfile, \
+                      'File name in directory "%s" and header "%s" differ.' % (
+                          zinfo.orig_filename, fname)
+
+        # check for encrypted flag & handle password
+        is_encrypted = zinfo.flag_bits & 0x1
+        zd = None
+        if is_encrypted:
+            if not pwd:
+                pwd = self.pwd
+            if not pwd:
+                raise RuntimeError, "File %s is encrypted, " \
+                      "password required for extraction" % name
+
+            zd = _ZipDecrypter(pwd)
+            # The first 12 bytes in the cypher stream is an encryption header
+            #  used to strengthen the algorithm. The first 11 bytes are
+            #  completely random, while the 12th contains the MSB of the CRC,
+            #  or the MSB of the file time depending on the header type
+            #  and is used to check the correctness of the password.
+            bytes = zef_file.read(12)
+            h = map(zd, bytes[0:12])
+            if zinfo.flag_bits & 0x8:
+                # compare against the file type from extended local headers
+                check_byte = (zinfo._raw_time >> 8) & 0xff
+            else:
+                # compare against the CRC otherwise
+                check_byte = (zinfo.CRC >> 24) & 0xff
+            if ord(h[11]) != check_byte:
+                raise RuntimeError("Bad password for file", name)
+
+        return  ZipExtFile(zef_file, mode, zinfo, zd)
+
+    def extract(self, member, path=None, pwd=None):
+        """Extract a member from the archive to the current working directory,
+           using its full name. Its file information is extracted as accurately
+           as possible. `member' may be a filename or a ZipInfo object. You can
+           specify a different directory using `path'.
+        """
+        if not isinstance(member, ZipInfo):
+            member = self.getinfo(member)
+
+        if path is None:
+            path = os.getcwd()
+
+        return self._extract_member(member, path, pwd)
+
+    def extractall(self, path=None, members=None, pwd=None):
+        """Extract all members from the archive to the current working
+           directory. `path' specifies a different directory to extract to.
+           `members' is optional and must be a subset of the list returned
+           by namelist().
+        """
+        if members is None:
+            members = self.namelist()
+
+        for zipinfo in members:
+            self.extract(zipinfo, path, pwd)
+
+    def _extract_member(self, member, targetpath, pwd):
+        """Extract the ZipInfo object 'member' to a physical
+           file on the path targetpath.
+        """
+        # build the destination pathname, replacing
+        # forward slashes to platform specific separators.
+        # Strip trailing path separator, unless it represents the root.
+        if (targetpath[-1:] in (os.path.sep, os.path.altsep)
+            and len(os.path.splitdrive(targetpath)[1]) > 1):
+            targetpath = targetpath[:-1]
+
+        # don't include leading "/" from file name if present
+        if member.filename[0] == '/':
+            targetpath = os.path.join(targetpath, member.filename[1:])
+        else:
+            targetpath = os.path.join(targetpath, member.filename)
+
+        targetpath = os.path.normpath(targetpath)
+
+        # Create all upper directories if necessary.
+        upperdirs = os.path.dirname(targetpath)
+        if upperdirs and not os.path.exists(upperdirs):
+            os.makedirs(upperdirs)
+
+        if member.filename[-1] == '/':
+            if not os.path.isdir(targetpath):
+                os.mkdir(targetpath)
+            return targetpath
+
+        source = self.open(member, pwd=pwd)
+        target = file(targetpath, "wb")
+        shutil.copyfileobj(source, target)
+        source.close()
+        target.close()
+
+        return targetpath
+
+    def _writecheck(self, zinfo):
+        """Check for errors before writing a file to the archive."""
+        if zinfo.filename in self.NameToInfo:
+            if self.debug:      # Warning for duplicate names
+                print "Duplicate name:", zinfo.filename
+        if self.mode not in ("w", "a"):
+            raise RuntimeError, 'write() requires mode "w" or "a"'
+        if not self.fp:
+            raise RuntimeError, \
+                  "Attempt to write ZIP archive that was already closed"
+        if zinfo.compress_type == ZIP_DEFLATED and not zlib:
+            raise RuntimeError, \
+                  "Compression requires the (missing) zlib module"
+        if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED):
+            raise RuntimeError, \
+                  "That compression method is not supported"
+        if zinfo.file_size > ZIP64_LIMIT:
+            if not self._allowZip64:
+                raise LargeZipFile("Filesize would require ZIP64 extensions")
+        if zinfo.header_offset > ZIP64_LIMIT:
+            if not self._allowZip64:
+                raise LargeZipFile("Zipfile size would require ZIP64 extensions")
+
+    def write(self, filename, arcname=None, compress_type=None):
+        """Put the bytes from filename into the archive under the name
+        arcname."""
+        if not self.fp:
+            raise RuntimeError(
+                  "Attempt to write to ZIP archive that was already closed")
+
+        st = os.stat(filename)
+        isdir = stat.S_ISDIR(st.st_mode)
+        mtime = time.localtime(st.st_mtime)
+        date_time = mtime[0:6]
+        # Create ZipInfo instance to store file information
+        if arcname is None:
+            arcname = filename
+        arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
+        while arcname[0] in (os.sep, os.altsep):
+            arcname = arcname[1:]
+        if isdir:
+            arcname += '/'
+        zinfo = ZipInfo(arcname, date_time)
+        zinfo.external_attr = (st[0] & 0xFFFF) << 16L      # Unix attributes
+        if compress_type is None:
+            zinfo.compress_type = self.compression
+        else:
+            zinfo.compress_type = compress_type
+
+        zinfo.file_size = st.st_size
+        zinfo.flag_bits = 0x00
+        zinfo.header_offset = self.fp.tell()    # Start of header bytes
+
+        self._writecheck(zinfo)
+        self._didModify = True
+
+        if isdir:
+            zinfo.file_size = 0
+            zinfo.compress_size = 0
+            zinfo.CRC = 0
+            self.filelist.append(zinfo)
+            self.NameToInfo[zinfo.filename] = zinfo
+            self.fp.write(zinfo.FileHeader())
+            return
+
+        with open(filename, "rb") as fp:
+            # Must overwrite CRC and sizes with correct data later
+            zinfo.CRC = CRC = 0
+            zinfo.compress_size = compress_size = 0
+            zinfo.file_size = file_size = 0
+            self.fp.write(zinfo.FileHeader())
+            if zinfo.compress_type == ZIP_DEFLATED:
+                cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
+                     zlib.DEFLATED, -15)
+            else:
+                cmpr = None
+            while 1:
+                buf = fp.read(1024 * 8)
+                if not buf:
+                    break
+                file_size = file_size + len(buf)
+                CRC = crc32(buf, CRC) & 0xffffffff
+                if cmpr:
+                    buf = cmpr.compress(buf)
+                    compress_size = compress_size + len(buf)
+                self.fp.write(buf)
+        if cmpr:
+            buf = cmpr.flush()
+            compress_size = compress_size + len(buf)
+            self.fp.write(buf)
+            zinfo.compress_size = compress_size
+        else:
+            zinfo.compress_size = file_size
+        zinfo.CRC = CRC
+        zinfo.file_size = file_size
+        # Seek backwards and write CRC and file sizes
+        position = self.fp.tell()       # Preserve current position in file
+        self.fp.seek(zinfo.header_offset + 14, 0)
+        self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
+              zinfo.file_size))
+        self.fp.seek(position, 0)
+        self.filelist.append(zinfo)
+        self.NameToInfo[zinfo.filename] = zinfo
+
+    def writestr(self, zinfo_or_arcname, bytes, compress_type=None):
+        """Write a file into the archive.  The contents is the string
+        'bytes'.  'zinfo_or_arcname' is either a ZipInfo instance or
+        the name of the file in the archive."""
+        if not isinstance(zinfo_or_arcname, ZipInfo):
+            zinfo = ZipInfo(filename=zinfo_or_arcname,
+                            date_time=time.localtime(time.time())[:6])
+
+            zinfo.compress_type = self.compression
+            zinfo.external_attr = 0600 << 16
+        else:
+            zinfo = zinfo_or_arcname
+
+        if not self.fp:
+            raise RuntimeError(
+                  "Attempt to write to ZIP archive that was already closed")
+
+        if compress_type is not None:
+            zinfo.compress_type = compress_type
+
+        zinfo.file_size = len(bytes)            # Uncompressed size
+        zinfo.header_offset = self.fp.tell()    # Start of header bytes
+        self._writecheck(zinfo)
+        self._didModify = True
+        zinfo.CRC = crc32(bytes) & 0xffffffff       # CRC-32 checksum
+        if zinfo.compress_type == ZIP_DEFLATED:
+            co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
+                 zlib.DEFLATED, -15)
+            bytes = co.compress(bytes) + co.flush()
+            zinfo.compress_size = len(bytes)    # Compressed size
+        else:
+            zinfo.compress_size = zinfo.file_size
+        zinfo.header_offset = self.fp.tell()    # Start of header bytes
+        self.fp.write(zinfo.FileHeader())
+        self.fp.write(bytes)
+        self.fp.flush()
+        if zinfo.flag_bits & 0x08:
+            # Write CRC and file sizes after the file data
+            self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
+                  zinfo.file_size))
+        self.filelist.append(zinfo)
+        self.NameToInfo[zinfo.filename] = zinfo
+
+    def __del__(self):
+        """Call the "close()" method in case the user forgot."""
+        self.close()
+
+    def close(self):
+        """Close the file, and for mode "w" and "a" write the ending
+        records."""
+        if self.fp is None:
+            return
+
+        if self.mode in ("w", "a") and self._didModify: # write ending records
+            count = 0
+            pos1 = self.fp.tell()
+            for zinfo in self.filelist:         # write central directory
+                count = count + 1
+                dt = zinfo.date_time
+                dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
+                dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
+                extra = []
+                if zinfo.file_size > ZIP64_LIMIT \
+                        or zinfo.compress_size > ZIP64_LIMIT:
+                    extra.append(zinfo.file_size)
+                    extra.append(zinfo.compress_size)
+                    file_size = 0xffffffff
+                    compress_size = 0xffffffff
+                else:
+                    file_size = zinfo.file_size
+                    compress_size = zinfo.compress_size
+
+                if zinfo.header_offset > ZIP64_LIMIT:
+                    extra.append(zinfo.header_offset)
+                    header_offset = 0xffffffffL
+                else:
+                    header_offset = zinfo.header_offset
+
+                extra_data = zinfo.extra
+                if extra:
+                    # Append a ZIP64 field to the extra's
+                    extra_data = struct.pack(
+                            '<HH' + 'Q'*len(extra),
+                            1, 8*len(extra), *extra) + extra_data
+
+                    extract_version = max(45, zinfo.extract_version)
+                    create_version = max(45, zinfo.create_version)
+                else:
+                    extract_version = zinfo.extract_version
+                    create_version = zinfo.create_version
+
+                try:
+                    filename, flag_bits = zinfo._encodeFilenameFlags()
+                    centdir = struct.pack(structCentralDir,
+                     stringCentralDir, create_version,
+                     zinfo.create_system, extract_version, zinfo.reserved,
+                     flag_bits, zinfo.compress_type, dostime, dosdate,
+                     zinfo.CRC, compress_size, file_size,
+                     len(filename), len(extra_data), len(zinfo.comment),
+                     0, zinfo.internal_attr, zinfo.external_attr,
+                     header_offset)
+                except DeprecationWarning:
+                    print >>sys.stderr, (structCentralDir,
+                     stringCentralDir, create_version,
+                     zinfo.create_system, extract_version, zinfo.reserved,
+                     zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
+                     zinfo.CRC, compress_size, file_size,
+                     len(zinfo.filename), len(extra_data), len(zinfo.comment),
+                     0, zinfo.internal_attr, zinfo.external_attr,
+                     header_offset)
+                    raise
+                self.fp.write(centdir)
+                self.fp.write(filename)
+                self.fp.write(extra_data)
+                self.fp.write(zinfo.comment)
+
+            pos2 = self.fp.tell()
+            # Write end-of-zip-archive record
+            centDirCount = count
+            centDirSize = pos2 - pos1
+            centDirOffset = pos1
+            if (centDirCount >= ZIP_FILECOUNT_LIMIT or
+                centDirOffset > ZIP64_LIMIT or
+                centDirSize > ZIP64_LIMIT):
+                # Need to write the ZIP64 end-of-archive records
+                zip64endrec = struct.pack(
+                        structEndArchive64, stringEndArchive64,
+                        44, 45, 45, 0, 0, centDirCount, centDirCount,
+                        centDirSize, centDirOffset)
+                self.fp.write(zip64endrec)
+
+                zip64locrec = struct.pack(
+                        structEndArchive64Locator,
+                        stringEndArchive64Locator, 0, pos2, 1)
+                self.fp.write(zip64locrec)
+                centDirCount = min(centDirCount, 0xFFFF)
+                centDirSize = min(centDirSize, 0xFFFFFFFF)
+                centDirOffset = min(centDirOffset, 0xFFFFFFFF)
+
+            # check for valid comment length
+            if len(self.comment) >= ZIP_MAX_COMMENT:
+                if self.debug > 0:
+                    msg = 'Archive comment is too long; truncating to %d bytes' \
+                          % ZIP_MAX_COMMENT
+                self.comment = self.comment[:ZIP_MAX_COMMENT]
+
+            endrec = struct.pack(structEndArchive, stringEndArchive,
+                                 0, 0, centDirCount, centDirCount,
+                                 centDirSize, centDirOffset, len(self.comment))
+            self.fp.write(endrec)
+            self.fp.write(self.comment)
+            self.fp.flush()
+
+        if not self._filePassed:
+            self.fp.close()
+        self.fp = None
+
+
+class PyZipFile(ZipFile):
+    """Class to create ZIP archives with Python library files and packages."""
+
+    def writepy(self, pathname, basename = ""):
+        """Add all files from "pathname" to the ZIP archive.
+
+        If pathname is a package directory, search the directory and
+        all package subdirectories recursively for all *.py and enter
+        the modules into the archive.  If pathname is a plain
+        directory, listdir *.py and enter all modules.  Else, pathname
+        must be a Python *.py file and the module will be put into the
+        archive.  Added modules are always module.pyo or module.pyc.
+        This method will compile the module.py into module.pyc if
+        necessary.
+        """
+        dir, name = os.path.split(pathname)
+        if os.path.isdir(pathname):
+            initname = os.path.join(pathname, "__init__.py")
+            if os.path.isfile(initname):
+                # This is a package directory, add it
+                if basename:
+                    basename = "%s/%s" % (basename, name)
+                else:
+                    basename = name
+                if self.debug:
+                    print "Adding package in", pathname, "as", basename
+                fname, arcname = self._get_codename(initname[0:-3], basename)
+                if self.debug:
+                    print "Adding", arcname
+                self.write(fname, arcname)
+                dirlist = os.listdir(pathname)
+                dirlist.remove("__init__.py")
+                # Add all *.py files and package subdirectories
+                for filename in dirlist:
+                    path = os.path.join(pathname, filename)
+                    root, ext = os.path.splitext(filename)
+                    if os.path.isdir(path):
+                        if os.path.isfile(os.path.join(path, "__init__.py")):
+                            # This is a package directory, add it
+                            self.writepy(path, basename)  # Recursive call
+                    elif ext == ".py":
+                        fname, arcname = self._get_codename(path[0:-3],
+                                         basename)
+                        if self.debug:
+                            print "Adding", arcname
+                        self.write(fname, arcname)
+            else:
+                # This is NOT a package directory, add its files at top level
+                if self.debug:
+                    print "Adding files from directory", pathname
+                for filename in os.listdir(pathname):
+                    path = os.path.join(pathname, filename)
+                    root, ext = os.path.splitext(filename)
+                    if ext == ".py":
+                        fname, arcname = self._get_codename(path[0:-3],
+                                         basename)
+                        if self.debug:
+                            print "Adding", arcname
+                        self.write(fname, arcname)
+        else:
+            if pathname[-3:] != ".py":
+                raise RuntimeError, \
+                      'Files added with writepy() must end with ".py"'
+            fname, arcname = self._get_codename(pathname[0:-3], basename)
+            if self.debug:
+                print "Adding file", arcname
+            self.write(fname, arcname)
+
+    def _get_codename(self, pathname, basename):
+        """Return (filename, archivename) for the path.
+
+        Given a module name path, return the correct file path and
+        archive name, compiling if necessary.  For example, given
+        /python/lib/string, return (/python/lib/string.pyc, string).
+        """
+        file_py  = pathname + ".py"
+        file_pyc = pathname + (".pyc" if not is_jython else "$py.class")
+        file_pyo = pathname + ".pyo"
+        if os.path.isfile(file_pyo) and \
+                            os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime:
+            fname = file_pyo    # Use .pyo file
+        elif not os.path.isfile(file_pyc) or \
+             os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime:
+            import py_compile
+            if self.debug:
+                print "Compiling", file_py
+            try:
+                py_compile.compile(file_py, file_pyc, None, True)
+            except py_compile.PyCompileError,err:
+                print err.msg
+            fname = file_pyc
+        else:
+            fname = file_pyc
+        archivename = os.path.split(fname)[1]
+        if basename:
+            archivename = "%s/%s" % (basename, archivename)
+        return (fname, archivename)
+
+
+def main(args = None):
+    import textwrap
+    USAGE=textwrap.dedent("""\
+        Usage:
+            zipfile.py -l zipfile.zip        # Show listing of a zipfile
+            zipfile.py -t zipfile.zip        # Test if a zipfile is valid
+            zipfile.py -e zipfile.zip target # Extract zipfile into target dir
+            zipfile.py -c zipfile.zip src ... # Create zipfile from sources
+        """)
+    if args is None:
+        args = sys.argv[1:]
+
+    if not args or args[0] not in ('-l', '-c', '-e', '-t'):
+        print USAGE
+        sys.exit(1)
+
+    if args[0] == '-l':
+        if len(args) != 2:
+            print USAGE
+            sys.exit(1)
+        zf = ZipFile(args[1], 'r')
+        zf.printdir()
+        zf.close()
+
+    elif args[0] == '-t':
+        if len(args) != 2:
+            print USAGE
+            sys.exit(1)
+        zf = ZipFile(args[1], 'r')
+        badfile = zf.testzip()
+        if badfile:
+            print("The following enclosed file is corrupted: {!r}".format(badfile))
+        print "Done testing"
+
+    elif args[0] == '-e':
+        if len(args) != 3:
+            print USAGE
+            sys.exit(1)
+
+        zf = ZipFile(args[1], 'r')
+        out = args[2]
+        for path in zf.namelist():
+            if path.startswith('./'):
+                tgt = os.path.join(out, path[2:])
+            else:
+                tgt = os.path.join(out, path)
+
+            tgtdir = os.path.dirname(tgt)
+            if not os.path.exists(tgtdir):
+                os.makedirs(tgtdir)
+            with open(tgt, 'wb') as fp:
+                fp.write(zf.read(path))
+        zf.close()
+
+    elif args[0] == '-c':
+        if len(args) < 3:
+            print USAGE
+            sys.exit(1)
+
+        def addToZip(zf, path, zippath):
+            if os.path.isfile(path):
+                zf.write(path, zippath, ZIP_DEFLATED)
+            elif os.path.isdir(path):
+                for nm in os.listdir(path):
+                    addToZip(zf,
+                            os.path.join(path, nm), os.path.join(zippath, nm))
+            # else: ignore
+
+        zf = ZipFile(args[1], 'w', allowZip64=True)
+        for src in args[2:]:
+            addToZip(zf, src, os.path.basename(src))
+
+        zf.close()
+
+if __name__ == "__main__":
+    main()
diff --git a/src/main/resources/PythonLibs/zlib.py b/src/main/resources/PythonLibs/zlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..1aacd0d3445d065ffbc454ae70b1e2338c72e1e6
--- /dev/null
+++ b/src/main/resources/PythonLibs/zlib.py
@@ -0,0 +1,195 @@
+"""
+The functions in this module allow compression and decompression using the
+zlib library, which is based on GNU zip.
+
+adler32(string[, start]) -- Compute an Adler-32 checksum.
+compress(string[, level]) -- Compress string, with compression level in 1-9.
+compressobj([level]) -- Return a compressor object.
+crc32(string[, start]) -- Compute a CRC-32 checksum.
+decompress(string,[wbits],[bufsize]) -- Decompresses a compressed string.
+decompressobj([wbits]) -- Return a decompressor object.
+
+'wbits' is window buffer size.
+Compressor objects support compress() and flush() methods; decompressor
+objects support decompress() and flush().
+"""
+import array
+import binascii
+import jarray
+
+from java.util.zip import Adler32, Deflater, Inflater, DataFormatException
+from java.lang import Long, String
+
+from cStringIO import StringIO
+
+class error(Exception):
+    pass
+
+
+DEFLATED = 8
+MAX_WBITS = 15
+DEF_MEM_LEVEL = 8
+ZLIB_VERSION = "1.1.3"
+Z_BEST_COMPRESSION = 9
+Z_BEST_SPEED = 1
+
+Z_FILTERED = 1
+Z_HUFFMAN_ONLY = 2
+
+Z_DEFAULT_COMPRESSION = -1
+Z_DEFAULT_STRATEGY = 0
+
+# Most options are removed because java does not support them
+# Z_NO_FLUSH = 0
+# Z_SYNC_FLUSH = 2
+# Z_FULL_FLUSH = 3
+Z_FINISH = 4
+_valid_flush_modes = (Z_FINISH,)
+
+def adler32(s, value=1):
+    if value != 1:
+        raise ValueError, "adler32 only support start value of 1"
+    checksum = Adler32()
+    checksum.update(String.getBytes(s, 'iso-8859-1'))
+    return Long(checksum.getValue()).intValue()
+
+def crc32(string, value=0):
+    return binascii.crc32(string, value)
+
+
+def compress(string, level=6):
+    if level < Z_BEST_SPEED or level > Z_BEST_COMPRESSION:
+        raise error, "Bad compression level"
+    deflater = Deflater(level, 0)
+    try:
+        string = _to_input(string)
+        deflater.setInput(string, 0, len(string))
+        deflater.finish()
+        return _get_deflate_data(deflater)
+    finally:
+        deflater.end()
+
+def decompress(string, wbits=0, bufsize=16384):
+    inflater = Inflater(wbits < 0)
+    try:
+        inflater.setInput(_to_input(string))
+        return _get_inflate_data(inflater)
+    finally:
+        inflater.end()
+
+class compressobj:
+    # all jython uses wbits for is deciding whether to skip the header if it's negative
+    def __init__(self, level=6, method=DEFLATED, wbits=MAX_WBITS,
+                       memLevel=0, strategy=0):
+        if abs(wbits) > MAX_WBITS or abs(wbits) < 8:
+            raise ValueError, "Invalid initialization option"
+        self.deflater = Deflater(level, wbits < 0)
+        self.deflater.setStrategy(strategy)
+        if wbits < 0:
+            _get_deflate_data(self.deflater)
+        self._ended = False
+
+    def compress(self, string):
+        if self._ended:
+            raise error("compressobj may not be used after flush(Z_FINISH)")
+        string = _to_input(string)
+        self.deflater.setInput(string, 0, len(string))
+        return _get_deflate_data(self.deflater)
+
+    def flush(self, mode=Z_FINISH):
+        if self._ended:
+            raise error("compressobj may not be used after flush(Z_FINISH)")
+        if mode not in _valid_flush_modes:
+            raise ValueError, "Invalid flush option"
+        self.deflater.finish()
+        last = _get_deflate_data(self.deflater)
+        if mode == Z_FINISH:
+            self.deflater.end()
+            self._ended = True
+        return last
+
+class decompressobj:
+    # all jython uses wbits for is deciding whether to skip the header if it's negative
+    def __init__(self, wbits=MAX_WBITS):
+        if abs(wbits) > MAX_WBITS or abs(wbits) < 8:
+            raise ValueError, "Invalid initialization option"
+        self.inflater = Inflater(wbits < 0)
+        self.unused_data = ""
+        self._ended = False
+
+    def decompress(self, string, max_length=0):
+        if self._ended:
+            raise error("decompressobj may not be used after flush()")
+
+        # unused_data is always "" until inflation is finished; then it is
+        # the unused bytes of the input;
+        # unconsumed_tail is whatever input was not used because max_length
+        # was exceeded before inflation finished.
+        # Thus, at most one of {unused_data, unconsumed_tail} may be non-empty.
+        self.unused_data = ""
+        self.unconsumed_tail = ""
+
+        if max_length < 0:
+            raise ValueError("max_length must be a positive integer")
+
+        string = _to_input(string)
+        self.inflater.setInput(string)
+        inflated = _get_inflate_data(self.inflater, max_length)
+
+        r = self.inflater.getRemaining()
+        if r:
+            if max_length:
+                self.unconsumed_tail = string[-r:]
+            else:
+                self.unused_data = string[-r:]
+
+        return inflated
+
+    def flush(self, length=None):
+        if self._ended:
+            raise error("decompressobj may not be used after flush()")
+        if length is None:
+            length = 0
+        elif length <= 0:
+            raise ValueError('length must be greater than zero')
+        last = _get_inflate_data(self.inflater, length)
+        self.inflater.end()
+        return last
+
+def _to_input(string):
+    return string.tostring() if isinstance(string, array.array) else string
+
+def _get_deflate_data(deflater):
+    buf = jarray.zeros(1024, 'b')
+    s = StringIO()
+    while not deflater.finished():
+        l = deflater.deflate(buf)
+
+        if l == 0:
+            break
+        s.write(String(buf, 0, 0, l))
+    s.seek(0)
+    return s.read()
+
+def _get_inflate_data(inflater, max_length=0):
+    buf = jarray.zeros(1024, 'b')
+    s = StringIO()
+    total = 0
+    while not inflater.finished():
+        try:
+            if max_length:
+                l = inflater.inflate(buf, 0, min(1024, max_length - total))
+            else:
+                l = inflater.inflate(buf)
+        except DataFormatException, e:
+            raise error(str(e))
+
+        if l == 0:
+            break
+
+        total += l
+        s.write(String(buf, 0, 0, l))
+        if max_length and total == max_length:
+            break
+    s.seek(0)
+    return s.read()
diff --git a/src/main/resources/com/google/common/base/package-info.class b/src/main/resources/com/google/common/base/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ec2c4e11872c8883d7e4e01828cdad475d25458
Binary files /dev/null and b/src/main/resources/com/google/common/base/package-info.class differ
diff --git a/src/main/resources/com/google/common/cache/package-info.class b/src/main/resources/com/google/common/cache/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..5bdeb67b7a7102c916207a00be4e16fa2abebf29
Binary files /dev/null and b/src/main/resources/com/google/common/cache/package-info.class differ
diff --git a/src/main/resources/com/google/common/collect/package-info.class b/src/main/resources/com/google/common/collect/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3921ab3645489b0524758c0bda34eb5dc1bf6a4
Binary files /dev/null and b/src/main/resources/com/google/common/collect/package-info.class differ
diff --git a/src/main/resources/com/google/common/hash/package-info.class b/src/main/resources/com/google/common/hash/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed13122d495070cd3582e573b543cf471dfba187
Binary files /dev/null and b/src/main/resources/com/google/common/hash/package-info.class differ
diff --git a/src/main/resources/com/google/common/io/package-info.class b/src/main/resources/com/google/common/io/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6d6bb7f9d4772259d3c86f7c509c26ad272646d
Binary files /dev/null and b/src/main/resources/com/google/common/io/package-info.class differ
diff --git a/src/main/resources/com/google/common/math/package-info.class b/src/main/resources/com/google/common/math/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d084e1eb415ffa14856e6f26317cabf8893088f
Binary files /dev/null and b/src/main/resources/com/google/common/math/package-info.class differ
diff --git a/src/main/resources/com/google/common/net/package-info.class b/src/main/resources/com/google/common/net/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2d488216574e0c83759077b35daee80722f5000
Binary files /dev/null and b/src/main/resources/com/google/common/net/package-info.class differ
diff --git a/src/main/resources/com/google/common/primitives/package-info.class b/src/main/resources/com/google/common/primitives/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..0785e5e102346ba9775bd3d8b93dc47ebfb8ca5c
Binary files /dev/null and b/src/main/resources/com/google/common/primitives/package-info.class differ
diff --git a/src/main/resources/com/google/common/reflect/package-info.class b/src/main/resources/com/google/common/reflect/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..0281da1f800106722f58c95cccf04e742a2edee6
Binary files /dev/null and b/src/main/resources/com/google/common/reflect/package-info.class differ
diff --git a/src/main/resources/com/google/common/util/concurrent/package-info.class b/src/main/resources/com/google/common/util/concurrent/package-info.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2199f5998c70c9580109a9df9e577ecfc108a8a
Binary files /dev/null and b/src/main/resources/com/google/common/util/concurrent/package-info.class differ
diff --git a/src/main/resources/com/kenai/constantine/Constant.class b/src/main/resources/com/kenai/constantine/Constant.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5df45d6b41d67c13b71c83f3ad6e7670ae4e739
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/Constant.class differ
diff --git a/src/main/resources/com/kenai/constantine/ConstantSet$ConstantImpl.class b/src/main/resources/com/kenai/constantine/ConstantSet$ConstantImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8553042d5fe18ce74356702df1ebab82ce6e819
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/ConstantSet$ConstantImpl.class differ
diff --git a/src/main/resources/com/kenai/constantine/ConstantSet$ConstantIterator.class b/src/main/resources/com/kenai/constantine/ConstantSet$ConstantIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbfbec3f854f843f49f2dd60c927d8eb8940ec61
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/ConstantSet$ConstantIterator.class differ
diff --git a/src/main/resources/com/kenai/constantine/ConstantSet.class b/src/main/resources/com/kenai/constantine/ConstantSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..88caf376c853ee31f8de4c44405e0b87d35e40b1
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/ConstantSet.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/AddressFamily.class b/src/main/resources/com/kenai/constantine/platform/AddressFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..310bdacc170d155f9a95e01778c84e5a9842c917
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/AddressFamily.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/ConstantResolver$UnknownConstant.class b/src/main/resources/com/kenai/constantine/platform/ConstantResolver$UnknownConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..73fdff8ea232395f7160a92738f35affe5ed0f30
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/ConstantResolver$UnknownConstant.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/ConstantResolver.class b/src/main/resources/com/kenai/constantine/platform/ConstantResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc77855cec66e2af129b86bced1e36c65df6a0ca
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/ConstantResolver.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/Errno.class b/src/main/resources/com/kenai/constantine/platform/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..c610c95f36505d4f2b7f3f35d75bb37d07d2c11c
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/Errno.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/Fcntl.class b/src/main/resources/com/kenai/constantine/platform/Fcntl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8677a6cd77d39025b01abc3956e3051e3e917b08
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/Fcntl.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/INAddr.class b/src/main/resources/com/kenai/constantine/platform/INAddr.class
new file mode 100644
index 0000000000000000000000000000000000000000..a20cd12d8a8de27420da49d35e7ed13c9d523c9a
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/INAddr.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/IPProto.class b/src/main/resources/com/kenai/constantine/platform/IPProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..77b8bbee1b193908745ee8aba19755feb0e8835f
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/IPProto.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/NameInfo.class b/src/main/resources/com/kenai/constantine/platform/NameInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f2a832765c17f7d65da8fc7423c8050960b3c2b
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/NameInfo.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/OpenFlags.class b/src/main/resources/com/kenai/constantine/platform/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..d1e568a05b06cca74cfa93ecf091e0571714ed24
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/OpenFlags.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/PRIO.class b/src/main/resources/com/kenai/constantine/platform/PRIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..66045aed86a50c8738cf6c8697a03a418322dbe3
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/PRIO.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/ProtocolFamily.class b/src/main/resources/com/kenai/constantine/platform/ProtocolFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..22bfd53a62fc00f9bf7568dae8cb9b936d7f1d66
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/ProtocolFamily.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/RLIM.class b/src/main/resources/com/kenai/constantine/platform/RLIM.class
new file mode 100644
index 0000000000000000000000000000000000000000..274ded9968deb5889f2a8e9f1b66c9fab553838f
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/RLIM.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/RLIMIT.class b/src/main/resources/com/kenai/constantine/platform/RLIMIT.class
new file mode 100644
index 0000000000000000000000000000000000000000..84cf2535cf038a0704575d88c89909347eb17fb9
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/RLIMIT.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/Shutdown.class b/src/main/resources/com/kenai/constantine/platform/Shutdown.class
new file mode 100644
index 0000000000000000000000000000000000000000..14b4435a59e8a2fa87737069d87ac4f6dbc5a2bf
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/Shutdown.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/Signal.class b/src/main/resources/com/kenai/constantine/platform/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..26dca7b1a858d7e169ca09bf2366213c3c759077
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/Signal.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/Sock.class b/src/main/resources/com/kenai/constantine/platform/Sock.class
new file mode 100644
index 0000000000000000000000000000000000000000..62b7c8815f467bfb61a7a1c06888a8fb6ead3a67
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/Sock.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/SocketLevel.class b/src/main/resources/com/kenai/constantine/platform/SocketLevel.class
new file mode 100644
index 0000000000000000000000000000000000000000..76c18c91b78523da8eeaf3152d2ffb5aca57681f
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/SocketLevel.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/SocketOption.class b/src/main/resources/com/kenai/constantine/platform/SocketOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..40d285c583892602141b25aa8f73d58e4b757b48
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/SocketOption.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/Sysconf.class b/src/main/resources/com/kenai/constantine/platform/Sysconf.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fb827bfdc9cbcd5d8359d9b95576f8587ced49e
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/Sysconf.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/TCP.class b/src/main/resources/com/kenai/constantine/platform/TCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ebf470a277a798be45e39c24c6dce3017b3130a
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/TCP.class differ
diff --git a/src/main/resources/com/kenai/constantine/platform/WaitFlags.class b/src/main/resources/com/kenai/constantine/platform/WaitFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..36af8c541f4eead7a6a392ff3e2dd1a350745e60
Binary files /dev/null and b/src/main/resources/com/kenai/constantine/platform/WaitFlags.class differ
diff --git a/src/main/resources/com/kenai/jffi/Aggregate.class b/src/main/resources/com/kenai/jffi/Aggregate.class
new file mode 100644
index 0000000000000000000000000000000000000000..06fc549c3e5852b3c41862521191ab657a0b0415
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Aggregate.class differ
diff --git a/src/main/resources/com/kenai/jffi/Array.class b/src/main/resources/com/kenai/jffi/Array.class
new file mode 100644
index 0000000000000000000000000000000000000000..78b758bdd73de0001d75fceca7a6177dfa2216b7
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Array.class differ
diff --git a/src/main/resources/com/kenai/jffi/ArrayFlags.class b/src/main/resources/com/kenai/jffi/ArrayFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..f851ed21266b1eac0ec666e294b0e063d37d1e77
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ArrayFlags.class differ
diff --git a/src/main/resources/com/kenai/jffi/CallContext.class b/src/main/resources/com/kenai/jffi/CallContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..2570d0f9ade44f98b4ef82ff7aa8a67e7d253bfe
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/CallContext.class differ
diff --git a/src/main/resources/com/kenai/jffi/CallContextCache$1.class b/src/main/resources/com/kenai/jffi/CallContextCache$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc5f3efec1924e9d04aa66c1fad5ab067f39f220
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/CallContextCache$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/CallContextCache$CallContextRef.class b/src/main/resources/com/kenai/jffi/CallContextCache$CallContextRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f858a046d62be8cd3cd9e0eec0486ea91033d84
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/CallContextCache$CallContextRef.class differ
diff --git a/src/main/resources/com/kenai/jffi/CallContextCache$Signature.class b/src/main/resources/com/kenai/jffi/CallContextCache$Signature.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e9697dfc03f367e93239e4815589d331560c003
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/CallContextCache$Signature.class differ
diff --git a/src/main/resources/com/kenai/jffi/CallContextCache$SingletonHolder.class b/src/main/resources/com/kenai/jffi/CallContextCache$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4845f4efe41362676d2c181bd450ded45301271
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/CallContextCache$SingletonHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/CallContextCache.class b/src/main/resources/com/kenai/jffi/CallContextCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..d302b981771fc36631387b5f82d4e60745d5736b
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/CallContextCache.class differ
diff --git a/src/main/resources/com/kenai/jffi/CallingConvention.class b/src/main/resources/com/kenai/jffi/CallingConvention.class
new file mode 100644
index 0000000000000000000000000000000000000000..f599503c4f1dae64ac92522c16abcc8eb3bd7c73
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/CallingConvention.class differ
diff --git a/src/main/resources/com/kenai/jffi/Closure$Buffer.class b/src/main/resources/com/kenai/jffi/Closure$Buffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3f973003c77f54c9142f5a608af4b3ad58a6bda
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Closure$Buffer.class differ
diff --git a/src/main/resources/com/kenai/jffi/Closure$Handle.class b/src/main/resources/com/kenai/jffi/Closure$Handle.class
new file mode 100644
index 0000000000000000000000000000000000000000..a93ad9d7ac8552f5d077780b07a882fbe6e344ed
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Closure$Handle.class differ
diff --git a/src/main/resources/com/kenai/jffi/Closure.class b/src/main/resources/com/kenai/jffi/Closure.class
new file mode 100644
index 0000000000000000000000000000000000000000..32956c7ed97c2d6df8ae88ba75eddae5edd2cb65
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Closure.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosureMagazine$1.class b/src/main/resources/com/kenai/jffi/ClosureMagazine$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcfabd014dfb269ed74623b5286b829afc29e401
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosureMagazine$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosureMagazine$Handle.class b/src/main/resources/com/kenai/jffi/ClosureMagazine$Handle.class
new file mode 100644
index 0000000000000000000000000000000000000000..409e5a8a9595ef02c10da927c052f818ad8b827b
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosureMagazine$Handle.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosureMagazine.class b/src/main/resources/com/kenai/jffi/ClosureMagazine.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bec8da956aa48bb49f33d6c6b414c62a812d144
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosureMagazine.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosureManager$1.class b/src/main/resources/com/kenai/jffi/ClosureManager$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..845aa84b714a9d925f103fd88466fca9c14b5009
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosureManager$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosureManager$SingletonHolder.class b/src/main/resources/com/kenai/jffi/ClosureManager$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c2147b27914067b4a446d60076e5f8f09c06a3c
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosureManager$SingletonHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosureManager.class b/src/main/resources/com/kenai/jffi/ClosureManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..17e6d719e625f4ccb5eb15aa86a8705d146df614
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosureManager.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosurePool$1.class b/src/main/resources/com/kenai/jffi/ClosurePool$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f396d601f1cd43a94afb7b391660c9cc865d4505
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosurePool$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosurePool$Handle.class b/src/main/resources/com/kenai/jffi/ClosurePool$Handle.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ad7501a080ed4493b6a6c4eddae6715c245600b
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosurePool$Handle.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosurePool$Magazine$Slot.class b/src/main/resources/com/kenai/jffi/ClosurePool$Magazine$Slot.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bbde8cf0873781a9693e0dac66830686b2dbec4
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosurePool$Magazine$Slot.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosurePool$Magazine.class b/src/main/resources/com/kenai/jffi/ClosurePool$Magazine.class
new file mode 100644
index 0000000000000000000000000000000000000000..e178f12be2e734853330bdef0c90bda08d2588fb
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosurePool$Magazine.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosurePool$MagazineHolder.class b/src/main/resources/com/kenai/jffi/ClosurePool$MagazineHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..51c32aaa33590a47ad559a386089d076376e8182
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosurePool$MagazineHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosurePool$Proxy.class b/src/main/resources/com/kenai/jffi/ClosurePool$Proxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..751968f5a46626e17c314f9ff720b1132c162567
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosurePool$Proxy.class differ
diff --git a/src/main/resources/com/kenai/jffi/ClosurePool.class b/src/main/resources/com/kenai/jffi/ClosurePool.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a0b3f30d2a46a54476fe3ef75f3893b5272fd61
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ClosurePool.class differ
diff --git a/src/main/resources/com/kenai/jffi/DirectClosureBuffer$1.class b/src/main/resources/com/kenai/jffi/DirectClosureBuffer$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1f20a444058bfcf4ef355e77a3a70f0eb4c0ba4
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/DirectClosureBuffer$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO.class b/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..dee6606371e1869f7d781959df12a0f83fafa734
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO32.class b/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO32.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c65cff68a9c15663ddbd478da1843fa981269ea
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO32.class differ
diff --git a/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO64.class b/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO64.class
new file mode 100644
index 0000000000000000000000000000000000000000..3104a6f7302e042f4f9bc76a5c62a670d4740be2
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/DirectClosureBuffer$NativeWordIO64.class differ
diff --git a/src/main/resources/com/kenai/jffi/DirectClosureBuffer.class b/src/main/resources/com/kenai/jffi/DirectClosureBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3108f01e2485d03462efa84fd87bcbe88ee40a85
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/DirectClosureBuffer.class differ
diff --git a/src/main/resources/com/kenai/jffi/DirectObjectParameterStrategy.class b/src/main/resources/com/kenai/jffi/DirectObjectParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0e6867c55522e52b60b8cbd55abbd41bbcf83a4
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/DirectObjectParameterStrategy.class differ
diff --git a/src/main/resources/com/kenai/jffi/Foreign$1.class b/src/main/resources/com/kenai/jffi/Foreign$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..63ebd8fa0f541ba7c67b47ede832d5e1d533498c
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Foreign$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/Foreign$InValidInstanceHolder.class b/src/main/resources/com/kenai/jffi/Foreign$InValidInstanceHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..80b1d73066873a1e47edfd4f73a147c4835271e1
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Foreign$InValidInstanceHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/Foreign$InstanceHolder.class b/src/main/resources/com/kenai/jffi/Foreign$InstanceHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..57e2e6b69f2804aef7df3559b343375e318b60a5
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Foreign$InstanceHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/Foreign$ValidInstanceHolder.class b/src/main/resources/com/kenai/jffi/Foreign$ValidInstanceHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b9b5b683f62934f9b1799c362ba9feea0548831
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Foreign$ValidInstanceHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/Foreign.class b/src/main/resources/com/kenai/jffi/Foreign.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6119ebe7b20e3699605854ffdc2197d99c25e4d
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Foreign.class differ
diff --git a/src/main/resources/com/kenai/jffi/Function.class b/src/main/resources/com/kenai/jffi/Function.class
new file mode 100644
index 0000000000000000000000000000000000000000..638db7ffbce7247a8b1b0fb8842e0878e1464cbe
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Function.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$1.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..147f2ba1d82751774dfb253609c4edc1a0583e7f
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$ArrayIO.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5660a5cc166855eea8a0aef63a1db60f5497ffa
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$ArrayIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BE32ArrayIO.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BE32ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..f307cd5bc05c07953a2e32b3e9e6f81b3f80d5ef
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BE32ArrayIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BE64ArrayIO.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BE64ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..eff366a0676ad9c0c1fe2af392b7b471368b8dab
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BE64ArrayIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BigEndianArrayIO.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BigEndianArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..6509938e20ae1ad68adf09d08ac7afe3f0390519
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$BigEndianArrayIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$DefaultEncoder.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$DefaultEncoder.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6e4f1540402d19c86d9b016d74a1fa1e6753f4c
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$DefaultEncoder.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$Encoder.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$Encoder.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa63c0dea59c6848948308a10a83d45ec9794302
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$Encoder.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$I386RawEncoder.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$I386RawEncoder.class
new file mode 100644
index 0000000000000000000000000000000000000000..2586e9bbcd775d807f41c8dee139b23d9ef64c42
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$I386RawEncoder.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LE32ArrayIO.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LE32ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..11e2c3c40366da7c09cf262c2ac6d8d0b9a31a32
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LE32ArrayIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LE64ArrayIO.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LE64ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..091c6958601c8affe83c564d01c2101c1d2812f6
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LE64ArrayIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LittleEndianArrayIO.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LittleEndianArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..d286ad1c022d6d00687cac0eabcd3c707ea8de47
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$LittleEndianArrayIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$RawEncoder.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$RawEncoder.class
new file mode 100644
index 0000000000000000000000000000000000000000..751212afd0037be19cea5b512490067a3417568c
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer$RawEncoder.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapInvocationBuffer.class b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..14b355e2efd0b5f206d9cb2883a51a1555f13410
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapInvocationBuffer.class differ
diff --git a/src/main/resources/com/kenai/jffi/HeapObjectParameterInvoker.class b/src/main/resources/com/kenai/jffi/HeapObjectParameterInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..753d23c11d2d9a61e7c20fb08bad6774e89e19d3
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/HeapObjectParameterInvoker.class differ
diff --git a/src/main/resources/com/kenai/jffi/Init.class b/src/main/resources/com/kenai/jffi/Init.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb841627c01f67cb8048f6dbcd8b13296790c15e
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Init.class differ
diff --git a/src/main/resources/com/kenai/jffi/Internals.class b/src/main/resources/com/kenai/jffi/Internals.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd378c01d9496cc1e31bae3e0c1de67e173382ec
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Internals.class differ
diff --git a/src/main/resources/com/kenai/jffi/InvocationBuffer.class b/src/main/resources/com/kenai/jffi/InvocationBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..96ff5e11634fdead8bc0c89e6ea3b15837ffd073
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/InvocationBuffer.class differ
diff --git a/src/main/resources/com/kenai/jffi/InvokeDynamicSupport$Invoker.class b/src/main/resources/com/kenai/jffi/InvokeDynamicSupport$Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d1bf9c615e721172313d04804fbee1d7c0864bf
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/InvokeDynamicSupport$Invoker.class differ
diff --git a/src/main/resources/com/kenai/jffi/InvokeDynamicSupport$JSR292.class b/src/main/resources/com/kenai/jffi/InvokeDynamicSupport$JSR292.class
new file mode 100644
index 0000000000000000000000000000000000000000..94f6ac63820190a2c37d1ac747929663c7f16ae2
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/InvokeDynamicSupport$JSR292.class differ
diff --git a/src/main/resources/com/kenai/jffi/InvokeDynamicSupport.class b/src/main/resources/com/kenai/jffi/InvokeDynamicSupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8f4a294ad6337d58376f3b010552733930ce6e9
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/InvokeDynamicSupport.class differ
diff --git a/src/main/resources/com/kenai/jffi/Invoker$1.class b/src/main/resources/com/kenai/jffi/Invoker$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..eff1ac90b2f89d47f1c328f0e66746e012158b53
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Invoker$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/Invoker$ILP32.class b/src/main/resources/com/kenai/jffi/Invoker$ILP32.class
new file mode 100644
index 0000000000000000000000000000000000000000..4893bf4039bdb144467c012240195ce5e29f362a
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Invoker$ILP32.class differ
diff --git a/src/main/resources/com/kenai/jffi/Invoker$LP64.class b/src/main/resources/com/kenai/jffi/Invoker$LP64.class
new file mode 100644
index 0000000000000000000000000000000000000000..2128a024edfe43b221a7df1e672e2f728fc79728
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Invoker$LP64.class differ
diff --git a/src/main/resources/com/kenai/jffi/Invoker$SingletonHolder.class b/src/main/resources/com/kenai/jffi/Invoker$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee631e74f5230677a3e9d277b53de06a0da20e81
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Invoker$SingletonHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/Invoker.class b/src/main/resources/com/kenai/jffi/Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c276ca2bcb902ed67f1c4bf636ab43525223474
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Invoker.class differ
diff --git a/src/main/resources/com/kenai/jffi/LastError$1.class b/src/main/resources/com/kenai/jffi/LastError$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3bc32ee544919ac27de3732855f995aaf753aff
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/LastError$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/LastError$SingletonHolder.class b/src/main/resources/com/kenai/jffi/LastError$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..425f47a8176620bed0b7fb3cf131f8fba1340aaf
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/LastError$SingletonHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/LastError.class b/src/main/resources/com/kenai/jffi/LastError.class
new file mode 100644
index 0000000000000000000000000000000000000000..b519da2cdcbb8c13c2f930a9ab70086f11da8034
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/LastError.class differ
diff --git a/src/main/resources/com/kenai/jffi/Library$DefaultLibrary.class b/src/main/resources/com/kenai/jffi/Library$DefaultLibrary.class
new file mode 100644
index 0000000000000000000000000000000000000000..2374f7f401570ac63e6dd4ff42396ba2b66b8a02
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Library$DefaultLibrary.class differ
diff --git a/src/main/resources/com/kenai/jffi/Library.class b/src/main/resources/com/kenai/jffi/Library.class
new file mode 100644
index 0000000000000000000000000000000000000000..a77f9f4db79bee82720c079b0f46f9f22c8f326d
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Library.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO$1.class b/src/main/resources/com/kenai/jffi/MemoryIO$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..384f5f71fa6b078ecbe4960dadf91dbd140cfa27
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl.class b/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..65910d5cb94c9ab865745675344746f007565a42
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl32.class b/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl32.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcf8d369c6b49d53698be4a2343294a22ffbc6f3
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl32.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl64.class b/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl64.class
new file mode 100644
index 0000000000000000000000000000000000000000..e909eb1580dc3ec8c8d49649a0116a57777273d7
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO$NativeImpl64.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO$SingletonHolder.class b/src/main/resources/com/kenai/jffi/MemoryIO$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..352a21a3c19057c8eb7e2a0e7e171914ee5d57e9
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO$SingletonHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl.class b/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3019ff57964ac86fda9671593e4558064a59ba46
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl32.class b/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl32.class
new file mode 100644
index 0000000000000000000000000000000000000000..51f3800cf30f982cb5dba38093c59e9feb2df214
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl32.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl64.class b/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl64.class
new file mode 100644
index 0000000000000000000000000000000000000000..161817aee5806c4f169cac4701e120a900e1ff13
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO$UnsafeImpl64.class differ
diff --git a/src/main/resources/com/kenai/jffi/MemoryIO.class b/src/main/resources/com/kenai/jffi/MemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..e85c07dd66bbe831ef551013f260d0ff0fd7228e
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/MemoryIO.class differ
diff --git a/src/main/resources/com/kenai/jffi/NativeMethod.class b/src/main/resources/com/kenai/jffi/NativeMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4c8b6f09bbb1e9709245167a0abd9df3586a7d0
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/NativeMethod.class differ
diff --git a/src/main/resources/com/kenai/jffi/NativeMethods$ResourceHolder.class b/src/main/resources/com/kenai/jffi/NativeMethods$ResourceHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..59fdd063e37949f474d7eefbb336826e17013369
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/NativeMethods$ResourceHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/NativeMethods.class b/src/main/resources/com/kenai/jffi/NativeMethods.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c4f23fee359257b29c7c8e2f941b9a6134923fc
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/NativeMethods.class differ
diff --git a/src/main/resources/com/kenai/jffi/NativeObjectParameterInvoker.class b/src/main/resources/com/kenai/jffi/NativeObjectParameterInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa51cc5b7efd80d677fb09fbb8ecdb2d53302e5d
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/NativeObjectParameterInvoker.class differ
diff --git a/src/main/resources/com/kenai/jffi/NativeType.class b/src/main/resources/com/kenai/jffi/NativeType.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ab49b0b6ee856caebe5b74ed1ab51ecaf8680f2
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/NativeType.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectBuffer.class b/src/main/resources/com/kenai/jffi/ObjectBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb77dedc31f3f30a117b3536c17d432c8b61d56b
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectBuffer.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterInfo$ComponentType.class b/src/main/resources/com/kenai/jffi/ObjectParameterInfo$ComponentType.class
new file mode 100644
index 0000000000000000000000000000000000000000..61b848c4132c663d8660e6edf84d97e78bcccab1
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterInfo$ComponentType.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterInfo$ObjectType.class b/src/main/resources/com/kenai/jffi/ObjectParameterInfo$ObjectType.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbb1e54c02082df2d3a11c13e0db79d60137edde
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterInfo$ObjectType.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterInfo.class b/src/main/resources/com/kenai/jffi/ObjectParameterInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..26e3c7a0368c2bdcdfbd0035c7288231a286e2ce
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterInfo.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterInvoker$SingletonHolder.class b/src/main/resources/com/kenai/jffi/ObjectParameterInvoker$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..c725089f234bab606c5744cca62b0a47cc41dfa2
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterInvoker$SingletonHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterInvoker.class b/src/main/resources/com/kenai/jffi/ObjectParameterInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..2892936aeddccbc5ca31208abbc6687a69a7c408
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterInvoker.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterStrategy$StrategyType.class b/src/main/resources/com/kenai/jffi/ObjectParameterStrategy$StrategyType.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3998f2fbc71133587a895b2eff093e7e40213fd
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterStrategy$StrategyType.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterStrategy.class b/src/main/resources/com/kenai/jffi/ObjectParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..33223087b5e193b2f01e5154421b86474b4c6419
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterStrategy.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterType$ComponentType.class b/src/main/resources/com/kenai/jffi/ObjectParameterType$ComponentType.class
new file mode 100644
index 0000000000000000000000000000000000000000..3007287a3df6bdad513dc5263e7f12799b2d8d63
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterType$ComponentType.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterType$ObjectType.class b/src/main/resources/com/kenai/jffi/ObjectParameterType$ObjectType.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bd3032c52162ddb087bb56300f2bdf5ef24506e
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterType$ObjectType.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterType$TypeCache.class b/src/main/resources/com/kenai/jffi/ObjectParameterType$TypeCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..680c4219754a05b678b5925fe7e34b2b08320ff7
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterType$TypeCache.class differ
diff --git a/src/main/resources/com/kenai/jffi/ObjectParameterType.class b/src/main/resources/com/kenai/jffi/ObjectParameterType.class
new file mode 100644
index 0000000000000000000000000000000000000000..43ed4a070bafccc639ac6efb93f007d43e90baeb
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/ObjectParameterType.class differ
diff --git a/src/main/resources/com/kenai/jffi/PageManager$SingletonHolder.class b/src/main/resources/com/kenai/jffi/PageManager$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..b22c9add759bc5cca49bc1e85f68a27f164afdb8
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/PageManager$SingletonHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/PageManager$Unix.class b/src/main/resources/com/kenai/jffi/PageManager$Unix.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d1c8cbf6b83a45e3d4dadb6ffce9535032904ed
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/PageManager$Unix.class differ
diff --git a/src/main/resources/com/kenai/jffi/PageManager$Windows.class b/src/main/resources/com/kenai/jffi/PageManager$Windows.class
new file mode 100644
index 0000000000000000000000000000000000000000..f27873c9442da99020883120c0da89de6675820c
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/PageManager$Windows.class differ
diff --git a/src/main/resources/com/kenai/jffi/PageManager.class b/src/main/resources/com/kenai/jffi/PageManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..0eb4efa34936ccbd6b829837722f660477da6c15
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/PageManager.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform$1.class b/src/main/resources/com/kenai/jffi/Platform$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab88adfdb64a07208333f88b566f70ebb3b00878
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform$ArchHolder.class b/src/main/resources/com/kenai/jffi/Platform$ArchHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..6776d73c7c100ffb9b354d00405e50d9cce111a8
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform$ArchHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform$CPU.class b/src/main/resources/com/kenai/jffi/Platform$CPU.class
new file mode 100644
index 0000000000000000000000000000000000000000..989869bd52aebbe7ffa5593c95585d7eea7ae9c2
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform$CPU.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform$Darwin.class b/src/main/resources/com/kenai/jffi/Platform$Darwin.class
new file mode 100644
index 0000000000000000000000000000000000000000..d428af62909ad022e4074a0b2d74d9c4814f0201
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform$Darwin.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform$Default.class b/src/main/resources/com/kenai/jffi/Platform$Default.class
new file mode 100644
index 0000000000000000000000000000000000000000..84a5c5b4e4eebafa733b49ae2853a0fcf1ec7a77
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform$Default.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform$OS.class b/src/main/resources/com/kenai/jffi/Platform$OS.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fe83827ac026255478aa1276db79d9f44c54b4d
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform$OS.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform$SingletonHolder.class b/src/main/resources/com/kenai/jffi/Platform$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..393e5d761ed1672b9cc8d4806ff5cb170038c354
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform$SingletonHolder.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform$Windows.class b/src/main/resources/com/kenai/jffi/Platform$Windows.class
new file mode 100644
index 0000000000000000000000000000000000000000..c431273837ad0487144b4699afc29aac26356c05
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform$Windows.class differ
diff --git a/src/main/resources/com/kenai/jffi/Platform.class b/src/main/resources/com/kenai/jffi/Platform.class
new file mode 100644
index 0000000000000000000000000000000000000000..dfdb8ca72575f84c85e9c1b50a97dd41282bed71
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Platform.class differ
diff --git a/src/main/resources/com/kenai/jffi/Struct$1.class b/src/main/resources/com/kenai/jffi/Struct$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..989754dae68a20cf75d941c63a35fa915eda7a7c
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Struct$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/Struct$StructReference.class b/src/main/resources/com/kenai/jffi/Struct$StructReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..b39fcb7a256aabd5ce76c664fb5c884c777a0ad6
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Struct$StructReference.class differ
diff --git a/src/main/resources/com/kenai/jffi/Struct.class b/src/main/resources/com/kenai/jffi/Struct.class
new file mode 100644
index 0000000000000000000000000000000000000000..83e3de84acae77bcadc511609df177c5675f0e45
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Struct.class differ
diff --git a/src/main/resources/com/kenai/jffi/Type$1.class b/src/main/resources/com/kenai/jffi/Type$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1c9331ad8a826072b6a78b32421a359978d2faa
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Type$1.class differ
diff --git a/src/main/resources/com/kenai/jffi/Type$Builtin.class b/src/main/resources/com/kenai/jffi/Type$Builtin.class
new file mode 100644
index 0000000000000000000000000000000000000000..826c5a60764a06a3c32a4ba0a51254832f7ec596
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Type$Builtin.class differ
diff --git a/src/main/resources/com/kenai/jffi/Type$BuiltinTypeInfo.class b/src/main/resources/com/kenai/jffi/Type$BuiltinTypeInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..32d8518cc9bebbad34c549bbe290baa27381723e
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Type$BuiltinTypeInfo.class differ
diff --git a/src/main/resources/com/kenai/jffi/Type$InvalidLookupTable.class b/src/main/resources/com/kenai/jffi/Type$InvalidLookupTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..853af655cd18eda42978965cc68801ea6eb1be0c
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Type$InvalidLookupTable.class differ
diff --git a/src/main/resources/com/kenai/jffi/Type$LookupTable.class b/src/main/resources/com/kenai/jffi/Type$LookupTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..1961663d360c1360e0107a51e01e9f1fe3f43353
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Type$LookupTable.class differ
diff --git a/src/main/resources/com/kenai/jffi/Type$NativeLookupTable.class b/src/main/resources/com/kenai/jffi/Type$NativeLookupTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..af68c7e07a6fde33227db7057772e50ca58d86d8
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Type$NativeLookupTable.class differ
diff --git a/src/main/resources/com/kenai/jffi/Type.class b/src/main/resources/com/kenai/jffi/Type.class
new file mode 100644
index 0000000000000000000000000000000000000000..1cc18d52b4cf67df1f5e95f6a4f405bf538802d8
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Type.class differ
diff --git a/src/main/resources/com/kenai/jffi/Union.class b/src/main/resources/com/kenai/jffi/Union.class
new file mode 100644
index 0000000000000000000000000000000000000000..902925841d93de87f2864dc46a88581f33df422a
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Union.class differ
diff --git a/src/main/resources/com/kenai/jffi/Version.class b/src/main/resources/com/kenai/jffi/Version.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ee6f376b305128f563aaf7fa5a1c37681c56bc7
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/Version.class differ
diff --git a/src/main/resources/com/kenai/jffi/internal/StubLoader$CPU.class b/src/main/resources/com/kenai/jffi/internal/StubLoader$CPU.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c84992a16ebcaa56759a137170a00d87f07b75f
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/internal/StubLoader$CPU.class differ
diff --git a/src/main/resources/com/kenai/jffi/internal/StubLoader$OS.class b/src/main/resources/com/kenai/jffi/internal/StubLoader$OS.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6cdab0d5df86e214429dc15abe8be54e2f603b8
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/internal/StubLoader$OS.class differ
diff --git a/src/main/resources/com/kenai/jffi/internal/StubLoader.class b/src/main/resources/com/kenai/jffi/internal/StubLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..f97df4a38a626e8971d87162930e98ab27b0a1e7
Binary files /dev/null and b/src/main/resources/com/kenai/jffi/internal/StubLoader.class differ
diff --git a/src/main/resources/com/xhaus/modjy/ModjyJServlet.class b/src/main/resources/com/xhaus/modjy/ModjyJServlet.class
new file mode 100644
index 0000000000000000000000000000000000000000..304b000283b2ab6a47c7083970668db173dd20df
Binary files /dev/null and b/src/main/resources/com/xhaus/modjy/ModjyJServlet.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/ConnectionFunc.class b/src/main/resources/com/ziclix/python/sql/ConnectionFunc.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e7bc8a4ab6b7442f9e87711673009e6bc52b7ba
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/ConnectionFunc.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/CursorFunc.class b/src/main/resources/com/ziclix/python/sql/CursorFunc.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ea7989e388593c3fb546d8eecca507eab6f9932
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/CursorFunc.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/DBApiType.class b/src/main/resources/com/ziclix/python/sql/DBApiType.class
new file mode 100644
index 0000000000000000000000000000000000000000..6617e7198620ec6cb08a7ed00b94654f0b69f6f3
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/DBApiType.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/DataHandler.class b/src/main/resources/com/ziclix/python/sql/DataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..f106a476193ec16e202e213dad3998b957f6059b
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/DataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/DataHandlerTest$DefaultReturnHandler.class b/src/main/resources/com/ziclix/python/sql/DataHandlerTest$DefaultReturnHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8f0d33603ccdf49bd569e2a0a3ef8352ba850ea
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/DataHandlerTest$DefaultReturnHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/DataHandlerTest.class b/src/main/resources/com/ziclix/python/sql/DataHandlerTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..2cf6164abb897d77b210dc4e7e669b544573242c
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/DataHandlerTest.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/DateFactory.class b/src/main/resources/com/ziclix/python/sql/DateFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..a136d0a4f1ec4bbbcd2c4a8e1faa305c0f61835a
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/DateFactory.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/DynamicFetch.class b/src/main/resources/com/ziclix/python/sql/DynamicFetch.class
new file mode 100644
index 0000000000000000000000000000000000000000..09d0874683b50a60369f8cfb2dd149239110aae0
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/DynamicFetch.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/ExtendedCursorFunc.class b/src/main/resources/com/ziclix/python/sql/ExtendedCursorFunc.class
new file mode 100644
index 0000000000000000000000000000000000000000..336dae44f6a83e7eb0b18b8e1c0b4a70c8710365
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/ExtendedCursorFunc.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/Fetch.class b/src/main/resources/com/ziclix/python/sql/Fetch.class
new file mode 100644
index 0000000000000000000000000000000000000000..179d4160fe7e86dc19ae29b3028b528b26c5dc33
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/Fetch.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/FilterDataHandler.class b/src/main/resources/com/ziclix/python/sql/FilterDataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1a287612ed29b3daecd76e85a7b89d8537c0dd5
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/FilterDataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/JDBC20DataHandler.class b/src/main/resources/com/ziclix/python/sql/JDBC20DataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..417c8faad7205e39e4b51769e43cb1dc94f52459
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/JDBC20DataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/JDBC30DataHandler.class b/src/main/resources/com/ziclix/python/sql/JDBC30DataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc0a548dda04ed13e7d8193425153238c60ebe0e
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/JDBC30DataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/JavaDateFactory.class b/src/main/resources/com/ziclix/python/sql/JavaDateFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c8cb6561c3d17fb55ddd6cd9f135a7b4b4fd3ee
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/JavaDateFactory.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/Jython22DataHandler.class b/src/main/resources/com/ziclix/python/sql/Jython22DataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..da8e81173afe0456df5ae6a40ae173853a29d8ee
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/Jython22DataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/Procedure.class b/src/main/resources/com/ziclix/python/sql/Procedure.class
new file mode 100644
index 0000000000000000000000000000000000000000..af471c36e7e14f235f1de28554d9f6fadc5bd9dc
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/Procedure.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/PyConnection.class b/src/main/resources/com/ziclix/python/sql/PyConnection.class
new file mode 100644
index 0000000000000000000000000000000000000000..be4cc473bd21eafbe0669eaf373c6acf40ecc57d
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/PyConnection.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/PyCursor.class b/src/main/resources/com/ziclix/python/sql/PyCursor.class
new file mode 100644
index 0000000000000000000000000000000000000000..261ad6c163939290995694a14ae6deb6d67ef155
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/PyCursor.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/PyExtendedCursor.class b/src/main/resources/com/ziclix/python/sql/PyExtendedCursor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1c77d05b075054a7407bccfcb3d98b565c46a2a
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/PyExtendedCursor.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/PyStatement.class b/src/main/resources/com/ziclix/python/sql/PyStatement.class
new file mode 100644
index 0000000000000000000000000000000000000000..b19f0f6bdc5fd6e82020ad67a5959e24dadb6a11
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/PyStatement.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/StaticFetch.class b/src/main/resources/com/ziclix/python/sql/StaticFetch.class
new file mode 100644
index 0000000000000000000000000000000000000000..699bfe06050ae976c157a4007ba9e088caf05ebc
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/StaticFetch.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/WarningEvent.class b/src/main/resources/com/ziclix/python/sql/WarningEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c49be6d4aaf9f323d5285bb1b39981337e7c529
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/WarningEvent.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/WarningListener.class b/src/main/resources/com/ziclix/python/sql/WarningListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a104922f95a6cb168b795cd0d59d1d4fba68866
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/WarningListener.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/connect/Connect.class b/src/main/resources/com/ziclix/python/sql/connect/Connect.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae50dde683664839957f8aa5e6753a1d74531aa8
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/connect/Connect.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/connect/Connectx.class b/src/main/resources/com/ziclix/python/sql/connect/Connectx.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4554beca7b4f75f8fd989e86cc25c1ac326ea75
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/connect/Connectx.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/connect/Lookup.class b/src/main/resources/com/ziclix/python/sql/connect/Lookup.class
new file mode 100644
index 0000000000000000000000000000000000000000..67ee071401e75bf28acae2ceedf9b0a722ea422a
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/connect/Lookup.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/handler/MySQLDataHandler.class b/src/main/resources/com/ziclix/python/sql/handler/MySQLDataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ebd866dcc5273df37937babe51517d50befcedf
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/handler/MySQLDataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/handler/PostgresqlDataHandler.class b/src/main/resources/com/ziclix/python/sql/handler/PostgresqlDataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e590ef3baa847c76be496afbd58977b36818570
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/handler/PostgresqlDataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/handler/RowIdHandler.class b/src/main/resources/com/ziclix/python/sql/handler/RowIdHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..4359710093c62bd96f034cf2f3a0cedc60a96fb7
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/handler/RowIdHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/handler/SQLServerDataHandler.class b/src/main/resources/com/ziclix/python/sql/handler/SQLServerDataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd742fc4a464f50fd524dde6fd8894b2576b92c5
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/handler/SQLServerDataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/handler/UpdateCountDataHandler.class b/src/main/resources/com/ziclix/python/sql/handler/UpdateCountDataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbd78cf62dfa6d213fac8a0ceff7c4a1f3ec29a2
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/handler/UpdateCountDataHandler.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/Pipe.class b/src/main/resources/com/ziclix/python/sql/pipe/Pipe.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f9ab9febfbf8e030fa18cfdf19ee5d9a6544133
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/Pipe.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/PipeRunner.class b/src/main/resources/com/ziclix/python/sql/pipe/PipeRunner.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d99059d165fc4e03db8cec6c6a846d1536d5466
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/PipeRunner.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/Sink.class b/src/main/resources/com/ziclix/python/sql/pipe/Sink.class
new file mode 100644
index 0000000000000000000000000000000000000000..037981257bab28063b23229103854590d1d6649c
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/Sink.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/SinkRunner.class b/src/main/resources/com/ziclix/python/sql/pipe/SinkRunner.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7c395338d010f057b8915ad77dfe2e7f4f5adc0
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/SinkRunner.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/Source.class b/src/main/resources/com/ziclix/python/sql/pipe/Source.class
new file mode 100644
index 0000000000000000000000000000000000000000..3372c664a19c06fdb658ab27048a76a7531ac655
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/Source.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/SourceRunner.class b/src/main/resources/com/ziclix/python/sql/pipe/SourceRunner.class
new file mode 100644
index 0000000000000000000000000000000000000000..dfc59b56b259ddf6157c4dda8833126bda441ba6
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/SourceRunner.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/csv/CSVSink.class b/src/main/resources/com/ziclix/python/sql/pipe/csv/CSVSink.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea0e241790d388d84d409d9bfe3fea1454df4fec
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/csv/CSVSink.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/csv/CSVString.class b/src/main/resources/com/ziclix/python/sql/pipe/csv/CSVString.class
new file mode 100644
index 0000000000000000000000000000000000000000..34ee16cf78005a7c0e188f768d443b90d96ab4fa
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/csv/CSVString.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/db/BaseDB.class b/src/main/resources/com/ziclix/python/sql/pipe/db/BaseDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c969fb442a47bd537b01e57f2f0cee9d2adb517
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/db/BaseDB.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/db/DBSink.class b/src/main/resources/com/ziclix/python/sql/pipe/db/DBSink.class
new file mode 100644
index 0000000000000000000000000000000000000000..29e44e794da6234f2554c4e63dfe587e0b498605
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/db/DBSink.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/pipe/db/DBSource.class b/src/main/resources/com/ziclix/python/sql/pipe/db/DBSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3381c7eb245e6197218ab51671222f402e20294
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/pipe/db/DBSource.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/procedure/SQLServerProcedure.class b/src/main/resources/com/ziclix/python/sql/procedure/SQLServerProcedure.class
new file mode 100644
index 0000000000000000000000000000000000000000..50fd6cb0f7f72110dd654ae7cf050428da990866
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/procedure/SQLServerProcedure.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/resource/zxJDBCMessages.properties b/src/main/resources/com/ziclix/python/sql/resource/zxJDBCMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..23de55dc48ea5e8e23ee7ee70b91ec36063a7a88
--- /dev/null
+++ b/src/main/resources/com/ziclix/python/sql/resource/zxJDBCMessages.properties
@@ -0,0 +1,101 @@
+
+# doc strings
+Error=Exception that is the base class of all other error exceptions.
+
+Warning=Exception raised for important warnings like data truncations \
+while inserting, etc.
+
+InterfaceError=Exception raised for errors that are related to the database \
+interface rather than the database itself.
+
+DatabaseError=Exception raised for errors that are related to the database.
+
+InternalError=Exception raised when the database encounters an internal error, \
+e.g. the cursor is not valid anymore, the transaction is out of sync, etc.
+
+OperationalError=Exception raised for errors that are related to the database's \
+operation and not necessarily under the control of the programmer, e.g. an \
+unexpected disconnect occurs, the data source name is not found, a transaction \
+could not be processed, a memory allocation error occurred during processing, etc.
+
+ProgrammingError=Exception raised for programming errors, e.g. table not found or \
+already exists, syntax error in the SQL statement, wrong number of parameters \
+specified, etc.
+
+IntegrityError=Exception raised when the relational integrity of the database is \
+affected, e.g. a foreign key check fails.
+
+DataError=Exception raised for errors that are due to problems with the processed \
+data like division by zero, numeric value out of range, etc.
+
+NotSupportedError=Exception raised in case a method or database API was used which \
+is not supported by the database, e.g. requesting a .rollback() on a connection that \
+does not support transaction or has transactions turned off.
+
+# BCP
+bcp.0=bcp(table, [where=None, params=None, include=None, exclude=None, toTable=None, bindings=None])
+bcp.1=\ Copies data resulting from a query on the source to the appropriate table on the \
+destination.  Returns the count of the total number of rows bulk copied or -1 if the \
+query on the source returned no rows.  If the destination excludes all the columns an \
+Error will be raised.
+bcp.2=\ table    - the table to query on the source database
+bcp.3=\ where    - an optional where clause, defaults to (1=1) if None
+bcp.4=\ params   - optional params to substituted in the where clause
+bcp.5=\ include  - the columns to be queried from the source, * if None
+bcp.6=\ exclude  - the columns to be excluded from insertion on the destination, all if None
+bcp.7=\ toTable  - if non-None, the table in the destination db, otherwise the same table as the source
+bcp.8=\ bindings - the optional bindings for the destination, this allows morphing of types during the copy
+
+batchsize=the batch interval for inserts
+queuesize=the maximum number of objects the queue can hold, 0 means unbounded (the default)
+
+# PyConnection
+
+close.0=Close the connection now (rather than whenever __del__ is called).
+close.1=The connection will be unusable from this point forward; an Error \
+(or subclass) exception will be raised if any operation is attempted \
+with the connection. The same applies to all cursor objects trying \
+to use the connection.
+
+commit.0=Commit any pending transaction to the database.
+commit.1=Note that if the database supports an auto-commit feature, this \
+must be initially off. An interface method may be provided to turn it back on.
+
+cursor.0=cursor([dynamic=0])
+cursor.1=\ Return a new Cursor Object using the connection.
+cursor.2=\ dynamic - If non-zero, return a Cursor that does NOT iterate the results immediately.
+cursor.3=\           This greatly increases the performance of large result sets, but fails to
+cursor.4=\           set the .rowcount attribute on the Cursor.
+cursor.5=If the database does not provide a direct cursor concept, the module \
+will have to emulate cursors using other means to the extent needed by this \
+specification.
+
+rollback.0=This method is optional since not all databases provide transaction support.
+rollback.1=In case a database does provide transactions this method causes the database \
+to roll back to the start of any pending transaction. Closing a connection \
+without committing the changes first will cause an implicit rollback to be \
+performed.
+
+nativesql.0=Converts the given SQL statement into the system's native SQL grammar.
+nativesql.1=A driver may convert the JDBC sql grammar into its system's native SQL \
+grammar prior to sending it; this method returns the native form of the statement \
+that the driver would have sent.
+
+updateCountDeprecation=The use of UpdateCountDataHandler is deprecated in favor of \
+the .updatecount attribute on a cursor.
+
+# exception messages
+noStoredProc=stored procedures not implemented in db
+optionalSecond=optional second argument must be a list or tuple
+bindingValue=binding value must be a valid integer type from java.sql.Types
+onlyOneResultSet=dynamic fetch allows only one result set
+inconsistentRowCount=number of rows queried [{0,integer}] does not match number of rows inserted [{1,integer}]
+invalidCons=invalid constructor for class [{0}]
+noColInfo=unable to obtain column info
+excludedAllCols=excluded all columns
+invalidTableName=invalid table name [None]
+unsupportedTypeForColumn=type [{0}] is not supported for column index: {1}
+maybeCallproc=use .callproc() for stored procedures
+nodynamiccursors=this version of jdbc does not support dynamic cursors
+nocallprocsupport=dynamic cursor does not support .callproc; use static cursors instead
+
diff --git a/src/main/resources/com/ziclix/python/sql/util/BCP.class b/src/main/resources/com/ziclix/python/sql/util/BCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd66e781d107fe722052a0c82c33fe5514c76ae0
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/util/BCP.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/util/BCPFunc.class b/src/main/resources/com/ziclix/python/sql/util/BCPFunc.class
new file mode 100644
index 0000000000000000000000000000000000000000..77591b8346f02fc2fd2017d19a2933836eb87fd1
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/util/BCPFunc.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/util/PyArgParser.class b/src/main/resources/com/ziclix/python/sql/util/PyArgParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..7cf67969eaa60ab651add4a4383e204d3a30795f
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/util/PyArgParser.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/util/Queue.class b/src/main/resources/com/ziclix/python/sql/util/Queue.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c8203f4cfbb66104489d370847eb2a342bac80f
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/util/Queue.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/util/QueueClosedException.class b/src/main/resources/com/ziclix/python/sql/util/QueueClosedException.class
new file mode 100644
index 0000000000000000000000000000000000000000..a99e4940a03e92a63706784790e8fc81aa6d4736
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/util/QueueClosedException.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/zxJDBC.class b/src/main/resources/com/ziclix/python/sql/zxJDBC.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbcc29b8e161eeb26947da0d1f271148353afef7
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/zxJDBC.class differ
diff --git a/src/main/resources/com/ziclix/python/sql/zxJDBCFunc.class b/src/main/resources/com/ziclix/python/sql/zxJDBCFunc.class
new file mode 100644
index 0000000000000000000000000000000000000000..746bddd344ea4f147a897763d77f76b8c275ef6e
Binary files /dev/null and b/src/main/resources/com/ziclix/python/sql/zxJDBCFunc.class differ
diff --git a/src/main/resources/javax/xml/XMLConstants.class b/src/main/resources/javax/xml/XMLConstants.class
new file mode 100644
index 0000000000000000000000000000000000000000..96d5f592466707bf81f73a84c9546914ba267850
Binary files /dev/null and b/src/main/resources/javax/xml/XMLConstants.class differ
diff --git a/src/main/resources/javax/xml/datatype/DatatypeConfigurationException.class b/src/main/resources/javax/xml/datatype/DatatypeConfigurationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..54492507ad54c82ee219243e0914703ae6514b01
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/DatatypeConfigurationException.class differ
diff --git a/src/main/resources/javax/xml/datatype/DatatypeConstants$1.class b/src/main/resources/javax/xml/datatype/DatatypeConstants$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..319b6e1b3a85277670726400c86bac6e7ae49e46
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/DatatypeConstants$1.class differ
diff --git a/src/main/resources/javax/xml/datatype/DatatypeConstants$Field.class b/src/main/resources/javax/xml/datatype/DatatypeConstants$Field.class
new file mode 100644
index 0000000000000000000000000000000000000000..db01a7d6af47284204643b3ce729919230a7d2de
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/DatatypeConstants$Field.class differ
diff --git a/src/main/resources/javax/xml/datatype/DatatypeConstants.class b/src/main/resources/javax/xml/datatype/DatatypeConstants.class
new file mode 100644
index 0000000000000000000000000000000000000000..aae3192a1f83b3a5174c87c429bfd124edf518af
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/DatatypeConstants.class differ
diff --git a/src/main/resources/javax/xml/datatype/DatatypeFactory.class b/src/main/resources/javax/xml/datatype/DatatypeFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..ace6f17900a30c263124119e8dd9831f728b09d0
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/DatatypeFactory.class differ
diff --git a/src/main/resources/javax/xml/datatype/Duration.class b/src/main/resources/javax/xml/datatype/Duration.class
new file mode 100644
index 0000000000000000000000000000000000000000..81b4b28f180408f53056727971e203143daadc2c
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/Duration.class differ
diff --git a/src/main/resources/javax/xml/datatype/FactoryFinder$ConfigurationError.class b/src/main/resources/javax/xml/datatype/FactoryFinder$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..b657fbcb1f7ca54838aed56fcc6dc3066c7de22d
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/FactoryFinder$ConfigurationError.class differ
diff --git a/src/main/resources/javax/xml/datatype/FactoryFinder.class b/src/main/resources/javax/xml/datatype/FactoryFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..59b1df33a08252233b60581072c7bc4f95e84819
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/FactoryFinder.class differ
diff --git a/src/main/resources/javax/xml/datatype/SecuritySupport$1.class b/src/main/resources/javax/xml/datatype/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d666e12d6e9bb465dcc643b8465139650e9cef49
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/SecuritySupport$1.class differ
diff --git a/src/main/resources/javax/xml/datatype/SecuritySupport$2.class b/src/main/resources/javax/xml/datatype/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..5494be0910f5a9dbb69a2f6758425fda83b168b2
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/SecuritySupport$2.class differ
diff --git a/src/main/resources/javax/xml/datatype/SecuritySupport$3.class b/src/main/resources/javax/xml/datatype/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f12720599d659c49e7ebbe3bea08a170bcc7e9c
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/SecuritySupport$3.class differ
diff --git a/src/main/resources/javax/xml/datatype/SecuritySupport$4.class b/src/main/resources/javax/xml/datatype/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..814c647d731965d68b7932666d0194d56bd32e52
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/SecuritySupport$4.class differ
diff --git a/src/main/resources/javax/xml/datatype/SecuritySupport$5.class b/src/main/resources/javax/xml/datatype/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a70d91d0b1eb4768809e2a917b12025c1c50cb2
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/SecuritySupport$5.class differ
diff --git a/src/main/resources/javax/xml/datatype/SecuritySupport.class b/src/main/resources/javax/xml/datatype/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..674549afbf769ae9c8c1624f6f8e90b4cb3734c8
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/SecuritySupport.class differ
diff --git a/src/main/resources/javax/xml/datatype/XMLGregorianCalendar.class b/src/main/resources/javax/xml/datatype/XMLGregorianCalendar.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1b3f45a77e32661b72b4a62c7a2fb6023e90228
Binary files /dev/null and b/src/main/resources/javax/xml/datatype/XMLGregorianCalendar.class differ
diff --git a/src/main/resources/javax/xml/namespace/NamespaceContext.class b/src/main/resources/javax/xml/namespace/NamespaceContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..0590aaf6943bef5a1191e6bbfefc96f77c7c9e29
Binary files /dev/null and b/src/main/resources/javax/xml/namespace/NamespaceContext.class differ
diff --git a/src/main/resources/javax/xml/namespace/QName$1.class b/src/main/resources/javax/xml/namespace/QName$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d679b3b3ccfa62104322919c269d989cebffc066
Binary files /dev/null and b/src/main/resources/javax/xml/namespace/QName$1.class differ
diff --git a/src/main/resources/javax/xml/namespace/QName.class b/src/main/resources/javax/xml/namespace/QName.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9dafe71eeea4a7ac8ba109cf5c819321a2905c2
Binary files /dev/null and b/src/main/resources/javax/xml/namespace/QName.class differ
diff --git a/src/main/resources/javax/xml/parsers/DocumentBuilder.class b/src/main/resources/javax/xml/parsers/DocumentBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..db3e7fcd7470d5085f9b1bde697e96839eb24937
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/DocumentBuilder.class differ
diff --git a/src/main/resources/javax/xml/parsers/DocumentBuilderFactory.class b/src/main/resources/javax/xml/parsers/DocumentBuilderFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8e00f430de96a61e655bbfc21011036e1947b0c
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/DocumentBuilderFactory.class differ
diff --git a/src/main/resources/javax/xml/parsers/FactoryConfigurationError.class b/src/main/resources/javax/xml/parsers/FactoryConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..523be853c02f0e11d772ea1e28085f9668ebc2c4
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/FactoryConfigurationError.class differ
diff --git a/src/main/resources/javax/xml/parsers/FactoryFinder$ConfigurationError.class b/src/main/resources/javax/xml/parsers/FactoryFinder$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..8de4fbd37e149c16b1dfd7e4eae8d2fcf8963c40
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/FactoryFinder$ConfigurationError.class differ
diff --git a/src/main/resources/javax/xml/parsers/FactoryFinder.class b/src/main/resources/javax/xml/parsers/FactoryFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..23feb470ee3b15e435b0eac24833cbd80a81abee
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/FactoryFinder.class differ
diff --git a/src/main/resources/javax/xml/parsers/FilePathToURI.class b/src/main/resources/javax/xml/parsers/FilePathToURI.class
new file mode 100644
index 0000000000000000000000000000000000000000..00dfe796d35abc52f45ed548007595a2572926c4
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/FilePathToURI.class differ
diff --git a/src/main/resources/javax/xml/parsers/ParserConfigurationException.class b/src/main/resources/javax/xml/parsers/ParserConfigurationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..28d3ea9c63cc92cdf9fe2ae0ab5b8070fada157f
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/ParserConfigurationException.class differ
diff --git a/src/main/resources/javax/xml/parsers/SAXParser.class b/src/main/resources/javax/xml/parsers/SAXParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..ddbbe625b98be21a093544ae7884db49c1f7ebea
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/SAXParser.class differ
diff --git a/src/main/resources/javax/xml/parsers/SAXParserFactory.class b/src/main/resources/javax/xml/parsers/SAXParserFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..790ea36c955098f7d0e3251a58d72618382446d9
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/SAXParserFactory.class differ
diff --git a/src/main/resources/javax/xml/parsers/SecuritySupport$1.class b/src/main/resources/javax/xml/parsers/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd637c9da779ab716e02f3022af56c6fab76dfb7
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/SecuritySupport$1.class differ
diff --git a/src/main/resources/javax/xml/parsers/SecuritySupport$2.class b/src/main/resources/javax/xml/parsers/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c8c17049dfe028178bc75a58dc7f97691b4ab4b
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/SecuritySupport$2.class differ
diff --git a/src/main/resources/javax/xml/parsers/SecuritySupport$3.class b/src/main/resources/javax/xml/parsers/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..616092d8411583c7566084f63f41899416d4a99d
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/SecuritySupport$3.class differ
diff --git a/src/main/resources/javax/xml/parsers/SecuritySupport$4.class b/src/main/resources/javax/xml/parsers/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..d23e59f41e22022a3daf676342343d79ecd74953
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/SecuritySupport$4.class differ
diff --git a/src/main/resources/javax/xml/parsers/SecuritySupport$5.class b/src/main/resources/javax/xml/parsers/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..a92aeb00a38370fb29e2db6992b22f3b73e44283
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/SecuritySupport$5.class differ
diff --git a/src/main/resources/javax/xml/parsers/SecuritySupport.class b/src/main/resources/javax/xml/parsers/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..e13578b8506387ca3753b876dfd3c926a05f7e0e
Binary files /dev/null and b/src/main/resources/javax/xml/parsers/SecuritySupport.class differ
diff --git a/src/main/resources/javax/xml/stream/EventFilter.class b/src/main/resources/javax/xml/stream/EventFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..600e73c8b47924e0295afee4579de7ba61fd4c16
Binary files /dev/null and b/src/main/resources/javax/xml/stream/EventFilter.class differ
diff --git a/src/main/resources/javax/xml/stream/FactoryConfigurationError.class b/src/main/resources/javax/xml/stream/FactoryConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..01734f1da6bbb953c73a1c887969d83ca7738b0f
Binary files /dev/null and b/src/main/resources/javax/xml/stream/FactoryConfigurationError.class differ
diff --git a/src/main/resources/javax/xml/stream/FactoryFinder$ConfigurationError.class b/src/main/resources/javax/xml/stream/FactoryFinder$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..48d9c5fe6b1ee3ba755f35f4720b44a3159e7df3
Binary files /dev/null and b/src/main/resources/javax/xml/stream/FactoryFinder$ConfigurationError.class differ
diff --git a/src/main/resources/javax/xml/stream/FactoryFinder.class b/src/main/resources/javax/xml/stream/FactoryFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..065ef07abd6b9918beb12c3b25bb4a8f56270f3a
Binary files /dev/null and b/src/main/resources/javax/xml/stream/FactoryFinder.class differ
diff --git a/src/main/resources/javax/xml/stream/Location.class b/src/main/resources/javax/xml/stream/Location.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd6c6a7714b9b95d46cd0ceb32146979cc336065
Binary files /dev/null and b/src/main/resources/javax/xml/stream/Location.class differ
diff --git a/src/main/resources/javax/xml/stream/SecuritySupport$1.class b/src/main/resources/javax/xml/stream/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0f2f14b78c780f924066b795e31acca37119819
Binary files /dev/null and b/src/main/resources/javax/xml/stream/SecuritySupport$1.class differ
diff --git a/src/main/resources/javax/xml/stream/SecuritySupport$2.class b/src/main/resources/javax/xml/stream/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..85fb2c17877b9171be3d37ead9f340b41c6e6a8e
Binary files /dev/null and b/src/main/resources/javax/xml/stream/SecuritySupport$2.class differ
diff --git a/src/main/resources/javax/xml/stream/SecuritySupport$3.class b/src/main/resources/javax/xml/stream/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc44e41092579c99de2a030edad6e7f9a47aa866
Binary files /dev/null and b/src/main/resources/javax/xml/stream/SecuritySupport$3.class differ
diff --git a/src/main/resources/javax/xml/stream/SecuritySupport$4.class b/src/main/resources/javax/xml/stream/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..66cf49616310afd1035dcd47bb818f711f747e6c
Binary files /dev/null and b/src/main/resources/javax/xml/stream/SecuritySupport$4.class differ
diff --git a/src/main/resources/javax/xml/stream/SecuritySupport$5.class b/src/main/resources/javax/xml/stream/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..f57251cab727e8d4a3707df6c75d76f3284d0adf
Binary files /dev/null and b/src/main/resources/javax/xml/stream/SecuritySupport$5.class differ
diff --git a/src/main/resources/javax/xml/stream/SecuritySupport.class b/src/main/resources/javax/xml/stream/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd65fb84dbc0a97674894724904dd6615b4f456c
Binary files /dev/null and b/src/main/resources/javax/xml/stream/SecuritySupport.class differ
diff --git a/src/main/resources/javax/xml/stream/StreamFilter.class b/src/main/resources/javax/xml/stream/StreamFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..039815d42c765f052d02a4ad66ed2b968d42f57b
Binary files /dev/null and b/src/main/resources/javax/xml/stream/StreamFilter.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLEventFactory.class b/src/main/resources/javax/xml/stream/XMLEventFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a5d772660445d0d99f6dcfee5b3e8614d03a262
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLEventFactory.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLEventReader.class b/src/main/resources/javax/xml/stream/XMLEventReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..539ff5bcf337f2d002059c0270c59e7edddccb29
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLEventReader.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLEventWriter.class b/src/main/resources/javax/xml/stream/XMLEventWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed1279d81e4b6d302572501b7857b35c5e42be85
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLEventWriter.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLInputFactory.class b/src/main/resources/javax/xml/stream/XMLInputFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..b0790ef64bce7befaf0e06a6832d4774758953dd
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLInputFactory.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLOutputFactory.class b/src/main/resources/javax/xml/stream/XMLOutputFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..18fd604b361310f902c6efd9619d072b77020879
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLOutputFactory.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLReporter.class b/src/main/resources/javax/xml/stream/XMLReporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c7afeb68d9c8bc4e495724bbb2aea2e00b24f5c
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLReporter.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLResolver.class b/src/main/resources/javax/xml/stream/XMLResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..1836f494e7489cf6e884cbf86ce36fda77d2c533
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLResolver.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLStreamConstants.class b/src/main/resources/javax/xml/stream/XMLStreamConstants.class
new file mode 100644
index 0000000000000000000000000000000000000000..e47129b2e28e8c998aaf8ffe8f1cdb7856139838
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLStreamConstants.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLStreamException.class b/src/main/resources/javax/xml/stream/XMLStreamException.class
new file mode 100644
index 0000000000000000000000000000000000000000..caf330ce26f961f1d095746784ca3d79bb52a925
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLStreamException.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLStreamReader.class b/src/main/resources/javax/xml/stream/XMLStreamReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b091f0c24234b5a9059d62fea2bb9cc0f568a35
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLStreamReader.class differ
diff --git a/src/main/resources/javax/xml/stream/XMLStreamWriter.class b/src/main/resources/javax/xml/stream/XMLStreamWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..187f138db0e3419b99361d62436205b7144f065b
Binary files /dev/null and b/src/main/resources/javax/xml/stream/XMLStreamWriter.class differ
diff --git a/src/main/resources/javax/xml/stream/events/Attribute.class b/src/main/resources/javax/xml/stream/events/Attribute.class
new file mode 100644
index 0000000000000000000000000000000000000000..0059785fc9e81198fc1efd0273bf842bcfdf8551
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/Attribute.class differ
diff --git a/src/main/resources/javax/xml/stream/events/Characters.class b/src/main/resources/javax/xml/stream/events/Characters.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ffb1c284589d6a0afbdfed2d39b4e1fd937406f
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/Characters.class differ
diff --git a/src/main/resources/javax/xml/stream/events/Comment.class b/src/main/resources/javax/xml/stream/events/Comment.class
new file mode 100644
index 0000000000000000000000000000000000000000..c339cb7e297dffdd77aaaa3f754f7f47f98c34c2
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/Comment.class differ
diff --git a/src/main/resources/javax/xml/stream/events/DTD.class b/src/main/resources/javax/xml/stream/events/DTD.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc4e89e2b88b198cbaf919b0242af4dfbb65c70c
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/DTD.class differ
diff --git a/src/main/resources/javax/xml/stream/events/EndDocument.class b/src/main/resources/javax/xml/stream/events/EndDocument.class
new file mode 100644
index 0000000000000000000000000000000000000000..49a23960c4504baa176e047f9644face918c6e03
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/EndDocument.class differ
diff --git a/src/main/resources/javax/xml/stream/events/EndElement.class b/src/main/resources/javax/xml/stream/events/EndElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..28f6568a3c2bd554a70b46aef198583a8b5dc2ff
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/EndElement.class differ
diff --git a/src/main/resources/javax/xml/stream/events/EntityDeclaration.class b/src/main/resources/javax/xml/stream/events/EntityDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..745219598009d9b9c39f18a4607cf7886d096788
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/EntityDeclaration.class differ
diff --git a/src/main/resources/javax/xml/stream/events/EntityReference.class b/src/main/resources/javax/xml/stream/events/EntityReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b55e22818b784dd3102a6274b62f62bbd615117
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/EntityReference.class differ
diff --git a/src/main/resources/javax/xml/stream/events/Namespace.class b/src/main/resources/javax/xml/stream/events/Namespace.class
new file mode 100644
index 0000000000000000000000000000000000000000..e66f157bb1a2501ad926b74d2096b391d3304159
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/Namespace.class differ
diff --git a/src/main/resources/javax/xml/stream/events/NotationDeclaration.class b/src/main/resources/javax/xml/stream/events/NotationDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..787a2be570025d445d74a3b22c5c28b1eec8d521
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/NotationDeclaration.class differ
diff --git a/src/main/resources/javax/xml/stream/events/ProcessingInstruction.class b/src/main/resources/javax/xml/stream/events/ProcessingInstruction.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae760e33af73ff07a6ad549cd0e78357675dd3bc
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/ProcessingInstruction.class differ
diff --git a/src/main/resources/javax/xml/stream/events/StartDocument.class b/src/main/resources/javax/xml/stream/events/StartDocument.class
new file mode 100644
index 0000000000000000000000000000000000000000..50d3130ef7b9af453a08c29c72f281fa7fd6bbbf
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/StartDocument.class differ
diff --git a/src/main/resources/javax/xml/stream/events/StartElement.class b/src/main/resources/javax/xml/stream/events/StartElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..9660155b4b67a35101c038bcc5f336e504aa7843
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/StartElement.class differ
diff --git a/src/main/resources/javax/xml/stream/events/XMLEvent.class b/src/main/resources/javax/xml/stream/events/XMLEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..1582aeaa9696aa8a6d2505eef221cc7cd505bcaf
Binary files /dev/null and b/src/main/resources/javax/xml/stream/events/XMLEvent.class differ
diff --git a/src/main/resources/javax/xml/stream/util/EventReaderDelegate.class b/src/main/resources/javax/xml/stream/util/EventReaderDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bc4cb2c434d1d80357e4076e610cdea8d096d67
Binary files /dev/null and b/src/main/resources/javax/xml/stream/util/EventReaderDelegate.class differ
diff --git a/src/main/resources/javax/xml/stream/util/StreamReaderDelegate.class b/src/main/resources/javax/xml/stream/util/StreamReaderDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..cbc7df5d915e212fd732f49ee607946752c6009f
Binary files /dev/null and b/src/main/resources/javax/xml/stream/util/StreamReaderDelegate.class differ
diff --git a/src/main/resources/javax/xml/stream/util/XMLEventAllocator.class b/src/main/resources/javax/xml/stream/util/XMLEventAllocator.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3699fed2c3bc03b4d1aae06b8281fa7033f5f8f
Binary files /dev/null and b/src/main/resources/javax/xml/stream/util/XMLEventAllocator.class differ
diff --git a/src/main/resources/javax/xml/stream/util/XMLEventConsumer.class b/src/main/resources/javax/xml/stream/util/XMLEventConsumer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e145f6cf8f2ec8eb474c76677f3a1eb59797743
Binary files /dev/null and b/src/main/resources/javax/xml/stream/util/XMLEventConsumer.class differ
diff --git a/src/main/resources/javax/xml/transform/ErrorListener.class b/src/main/resources/javax/xml/transform/ErrorListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6b144739ae1fdb501ba7be2cf1cd2dddf72e2f2
Binary files /dev/null and b/src/main/resources/javax/xml/transform/ErrorListener.class differ
diff --git a/src/main/resources/javax/xml/transform/FactoryFinder$ConfigurationError.class b/src/main/resources/javax/xml/transform/FactoryFinder$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..fcf73c1b750d3110cb050f1a22cb87acef89f1c2
Binary files /dev/null and b/src/main/resources/javax/xml/transform/FactoryFinder$ConfigurationError.class differ
diff --git a/src/main/resources/javax/xml/transform/FactoryFinder.class b/src/main/resources/javax/xml/transform/FactoryFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..059979f79b008d44b61164ff856029956f873753
Binary files /dev/null and b/src/main/resources/javax/xml/transform/FactoryFinder.class differ
diff --git a/src/main/resources/javax/xml/transform/OutputKeys.class b/src/main/resources/javax/xml/transform/OutputKeys.class
new file mode 100644
index 0000000000000000000000000000000000000000..ead9bae2bdb989022c0fce39efb724890128cb4f
Binary files /dev/null and b/src/main/resources/javax/xml/transform/OutputKeys.class differ
diff --git a/src/main/resources/javax/xml/transform/Result.class b/src/main/resources/javax/xml/transform/Result.class
new file mode 100644
index 0000000000000000000000000000000000000000..7629411871ccaeabb7598f926d8242f3b1e1dcdb
Binary files /dev/null and b/src/main/resources/javax/xml/transform/Result.class differ
diff --git a/src/main/resources/javax/xml/transform/SecuritySupport$1.class b/src/main/resources/javax/xml/transform/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7f2e7be4ea65d03e972d78d0c29d1d248262ad0
Binary files /dev/null and b/src/main/resources/javax/xml/transform/SecuritySupport$1.class differ
diff --git a/src/main/resources/javax/xml/transform/SecuritySupport$2.class b/src/main/resources/javax/xml/transform/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ffff417bbc723aacdd531fd4b5cda1e240b9b22
Binary files /dev/null and b/src/main/resources/javax/xml/transform/SecuritySupport$2.class differ
diff --git a/src/main/resources/javax/xml/transform/SecuritySupport$3.class b/src/main/resources/javax/xml/transform/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e4426f821dab9a1bfe75d90d35057ac3f5dd874
Binary files /dev/null and b/src/main/resources/javax/xml/transform/SecuritySupport$3.class differ
diff --git a/src/main/resources/javax/xml/transform/SecuritySupport$4.class b/src/main/resources/javax/xml/transform/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..98629e94dd3274e2f7c15176e2e43e1ae8ceb784
Binary files /dev/null and b/src/main/resources/javax/xml/transform/SecuritySupport$4.class differ
diff --git a/src/main/resources/javax/xml/transform/SecuritySupport$5.class b/src/main/resources/javax/xml/transform/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ac7f61135f8c80f425c3f9cd617081c9ab29c67
Binary files /dev/null and b/src/main/resources/javax/xml/transform/SecuritySupport$5.class differ
diff --git a/src/main/resources/javax/xml/transform/SecuritySupport.class b/src/main/resources/javax/xml/transform/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..2226b0a6340e347fcf577082aabe8085c9bb4332
Binary files /dev/null and b/src/main/resources/javax/xml/transform/SecuritySupport.class differ
diff --git a/src/main/resources/javax/xml/transform/Source.class b/src/main/resources/javax/xml/transform/Source.class
new file mode 100644
index 0000000000000000000000000000000000000000..91aab52b89f13c38340a7d64e3e36ce4d1812f50
Binary files /dev/null and b/src/main/resources/javax/xml/transform/Source.class differ
diff --git a/src/main/resources/javax/xml/transform/SourceLocator.class b/src/main/resources/javax/xml/transform/SourceLocator.class
new file mode 100644
index 0000000000000000000000000000000000000000..e61566a7b0793539151bbe90e16e6e697b8cb407
Binary files /dev/null and b/src/main/resources/javax/xml/transform/SourceLocator.class differ
diff --git a/src/main/resources/javax/xml/transform/Templates.class b/src/main/resources/javax/xml/transform/Templates.class
new file mode 100644
index 0000000000000000000000000000000000000000..588d0f8e1ebad4ddbb03dd70f64291178ac41440
Binary files /dev/null and b/src/main/resources/javax/xml/transform/Templates.class differ
diff --git a/src/main/resources/javax/xml/transform/Transformer.class b/src/main/resources/javax/xml/transform/Transformer.class
new file mode 100644
index 0000000000000000000000000000000000000000..46ef386a5f7b7cc665c7c532fcdbbc2928803da4
Binary files /dev/null and b/src/main/resources/javax/xml/transform/Transformer.class differ
diff --git a/src/main/resources/javax/xml/transform/TransformerConfigurationException.class b/src/main/resources/javax/xml/transform/TransformerConfigurationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e6f931b238c45b9bde439b773b6df08335f37e0
Binary files /dev/null and b/src/main/resources/javax/xml/transform/TransformerConfigurationException.class differ
diff --git a/src/main/resources/javax/xml/transform/TransformerException.class b/src/main/resources/javax/xml/transform/TransformerException.class
new file mode 100644
index 0000000000000000000000000000000000000000..67f1f9fa405691c72f5b3302e86b60b19de27b77
Binary files /dev/null and b/src/main/resources/javax/xml/transform/TransformerException.class differ
diff --git a/src/main/resources/javax/xml/transform/TransformerFactory.class b/src/main/resources/javax/xml/transform/TransformerFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..af8bd0fb7aecf2a77e25e853071de79b7812e1a5
Binary files /dev/null and b/src/main/resources/javax/xml/transform/TransformerFactory.class differ
diff --git a/src/main/resources/javax/xml/transform/TransformerFactoryConfigurationError.class b/src/main/resources/javax/xml/transform/TransformerFactoryConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..80b00e92601d17548e38e21afa938f76dd29a030
Binary files /dev/null and b/src/main/resources/javax/xml/transform/TransformerFactoryConfigurationError.class differ
diff --git a/src/main/resources/javax/xml/transform/URIResolver.class b/src/main/resources/javax/xml/transform/URIResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..0fd1d4808702d8cdf86acee980f11ecdadbdee94
Binary files /dev/null and b/src/main/resources/javax/xml/transform/URIResolver.class differ
diff --git a/src/main/resources/javax/xml/transform/dom/DOMLocator.class b/src/main/resources/javax/xml/transform/dom/DOMLocator.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b52c107be30ce690a8d04fb8f1501d818fda9a3
Binary files /dev/null and b/src/main/resources/javax/xml/transform/dom/DOMLocator.class differ
diff --git a/src/main/resources/javax/xml/transform/dom/DOMResult.class b/src/main/resources/javax/xml/transform/dom/DOMResult.class
new file mode 100644
index 0000000000000000000000000000000000000000..d34a870802ad09a86c54dd2543d94d1aec64251b
Binary files /dev/null and b/src/main/resources/javax/xml/transform/dom/DOMResult.class differ
diff --git a/src/main/resources/javax/xml/transform/dom/DOMSource.class b/src/main/resources/javax/xml/transform/dom/DOMSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..38fc17f7dc5ca7490aadb74c4ed2f2ff77e400e0
Binary files /dev/null and b/src/main/resources/javax/xml/transform/dom/DOMSource.class differ
diff --git a/src/main/resources/javax/xml/transform/sax/SAXResult.class b/src/main/resources/javax/xml/transform/sax/SAXResult.class
new file mode 100644
index 0000000000000000000000000000000000000000..452b3b726d10abb4ba43a2fc5ddbf450c3f09adc
Binary files /dev/null and b/src/main/resources/javax/xml/transform/sax/SAXResult.class differ
diff --git a/src/main/resources/javax/xml/transform/sax/SAXSource.class b/src/main/resources/javax/xml/transform/sax/SAXSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..80e758ff867c18c918aae4b0bdba9c2c54f6b6c6
Binary files /dev/null and b/src/main/resources/javax/xml/transform/sax/SAXSource.class differ
diff --git a/src/main/resources/javax/xml/transform/sax/SAXTransformerFactory.class b/src/main/resources/javax/xml/transform/sax/SAXTransformerFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef540678abb92a9e8e4bbfdcc3e996d6db142af2
Binary files /dev/null and b/src/main/resources/javax/xml/transform/sax/SAXTransformerFactory.class differ
diff --git a/src/main/resources/javax/xml/transform/sax/TemplatesHandler.class b/src/main/resources/javax/xml/transform/sax/TemplatesHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..496f8da3d72b42c2b9e356744a5d5e0a4f856fc1
Binary files /dev/null and b/src/main/resources/javax/xml/transform/sax/TemplatesHandler.class differ
diff --git a/src/main/resources/javax/xml/transform/sax/TransformerHandler.class b/src/main/resources/javax/xml/transform/sax/TransformerHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ea18c285b4149a7ad9c1972c35ba3379b483686
Binary files /dev/null and b/src/main/resources/javax/xml/transform/sax/TransformerHandler.class differ
diff --git a/src/main/resources/javax/xml/transform/stax/StAXResult.class b/src/main/resources/javax/xml/transform/stax/StAXResult.class
new file mode 100644
index 0000000000000000000000000000000000000000..f953e8652ea911b482efc21594bd9b3c92148dd1
Binary files /dev/null and b/src/main/resources/javax/xml/transform/stax/StAXResult.class differ
diff --git a/src/main/resources/javax/xml/transform/stax/StAXSource.class b/src/main/resources/javax/xml/transform/stax/StAXSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..2615a333d528afa7357968cb6a7fd9f089329efb
Binary files /dev/null and b/src/main/resources/javax/xml/transform/stax/StAXSource.class differ
diff --git a/src/main/resources/javax/xml/transform/stream/FilePathToURI.class b/src/main/resources/javax/xml/transform/stream/FilePathToURI.class
new file mode 100644
index 0000000000000000000000000000000000000000..65bb288a3a935ef45120c38438be5de713cda1fa
Binary files /dev/null and b/src/main/resources/javax/xml/transform/stream/FilePathToURI.class differ
diff --git a/src/main/resources/javax/xml/transform/stream/StreamResult.class b/src/main/resources/javax/xml/transform/stream/StreamResult.class
new file mode 100644
index 0000000000000000000000000000000000000000..593bd86c5bae269b812708f3758fbeb7582b9833
Binary files /dev/null and b/src/main/resources/javax/xml/transform/stream/StreamResult.class differ
diff --git a/src/main/resources/javax/xml/transform/stream/StreamSource.class b/src/main/resources/javax/xml/transform/stream/StreamSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..c39adb100e75a5d1542e554d3eeee1da8ca7f230
Binary files /dev/null and b/src/main/resources/javax/xml/transform/stream/StreamSource.class differ
diff --git a/src/main/resources/javax/xml/validation/Schema.class b/src/main/resources/javax/xml/validation/Schema.class
new file mode 100644
index 0000000000000000000000000000000000000000..85ceda1ed80e54c2ca79e027171b07a65c67cc11
Binary files /dev/null and b/src/main/resources/javax/xml/validation/Schema.class differ
diff --git a/src/main/resources/javax/xml/validation/SchemaFactory.class b/src/main/resources/javax/xml/validation/SchemaFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9c17d4a8e2c310d02c82237e4911ef6f579e52b
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SchemaFactory.class differ
diff --git a/src/main/resources/javax/xml/validation/SchemaFactoryFinder$1.class b/src/main/resources/javax/xml/validation/SchemaFactoryFinder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6edfa086f9ba57465da770c1ef12a4463b2d4255
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SchemaFactoryFinder$1.class differ
diff --git a/src/main/resources/javax/xml/validation/SchemaFactoryFinder$2.class b/src/main/resources/javax/xml/validation/SchemaFactoryFinder$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..42492faa78af82a361bba27fef77338a01a6a711
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SchemaFactoryFinder$2.class differ
diff --git a/src/main/resources/javax/xml/validation/SchemaFactoryFinder$SingleIterator.class b/src/main/resources/javax/xml/validation/SchemaFactoryFinder$SingleIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..159b25a24a9b09ed2d670a680cfbfceff655cbbe
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SchemaFactoryFinder$SingleIterator.class differ
diff --git a/src/main/resources/javax/xml/validation/SchemaFactoryFinder.class b/src/main/resources/javax/xml/validation/SchemaFactoryFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ccda8fa6b6f68419f352a0be1df3782e6f38051
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SchemaFactoryFinder.class differ
diff --git a/src/main/resources/javax/xml/validation/SchemaFactoryLoader.class b/src/main/resources/javax/xml/validation/SchemaFactoryLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..c08e7da45d9e0c90e2b325d571c42a001e69c8bc
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SchemaFactoryLoader.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport$1.class b/src/main/resources/javax/xml/validation/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bc4248c0851e8adc3f4785efe72d325047c4a58
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport$1.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport$2.class b/src/main/resources/javax/xml/validation/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2172b2ef9f45dde425f0b3d1e50e9307cfe1f73
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport$2.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport$3.class b/src/main/resources/javax/xml/validation/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..64e2fd30da34662c9d9ab80abefb3861dcb6c9a2
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport$3.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport$4.class b/src/main/resources/javax/xml/validation/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ffbce4b4744c558ac4d144f35f5f332554533cb
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport$4.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport$5.class b/src/main/resources/javax/xml/validation/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..3220a0769f5e92d789fe098868e5f130be8ccdf2
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport$5.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport$6.class b/src/main/resources/javax/xml/validation/SecuritySupport$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba79e74ba1c57607b1cd6a8c605f2015951dc775
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport$6.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport$7.class b/src/main/resources/javax/xml/validation/SecuritySupport$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c0bacf98149af0b367d5a64112bd8f818ad6c3d
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport$7.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport$8.class b/src/main/resources/javax/xml/validation/SecuritySupport$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..119fb03dae90d3b44989b010d7fbb1c1ced12730
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport$8.class differ
diff --git a/src/main/resources/javax/xml/validation/SecuritySupport.class b/src/main/resources/javax/xml/validation/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..51a5d80a088e6c92ca68b9611c884aba980d21f1
Binary files /dev/null and b/src/main/resources/javax/xml/validation/SecuritySupport.class differ
diff --git a/src/main/resources/javax/xml/validation/TypeInfoProvider.class b/src/main/resources/javax/xml/validation/TypeInfoProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..b387ea752febe9018d26e80c4b70148865000da5
Binary files /dev/null and b/src/main/resources/javax/xml/validation/TypeInfoProvider.class differ
diff --git a/src/main/resources/javax/xml/validation/Validator.class b/src/main/resources/javax/xml/validation/Validator.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dbd541b3539351bc24df6f8911ac61e2f18b67f
Binary files /dev/null and b/src/main/resources/javax/xml/validation/Validator.class differ
diff --git a/src/main/resources/javax/xml/validation/ValidatorHandler.class b/src/main/resources/javax/xml/validation/ValidatorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..7aafd295a4d9d156b1fa49819972eed24b54e6ab
Binary files /dev/null and b/src/main/resources/javax/xml/validation/ValidatorHandler.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport$1.class b/src/main/resources/javax/xml/xpath/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad9e2317fb9a83cad46e8727e9e4626c551a46ec
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport$1.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport$2.class b/src/main/resources/javax/xml/xpath/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..4794dc237b2fd2a2fd3b76fc6de333b34b878ed3
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport$2.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport$3.class b/src/main/resources/javax/xml/xpath/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..1667148379459e3804d6df1cab002394d529a452
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport$3.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport$4.class b/src/main/resources/javax/xml/xpath/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0f47f573399f04859a08c7df9a3f0498561e823
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport$4.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport$5.class b/src/main/resources/javax/xml/xpath/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcb277ac04439e3edeef26d132149abcc647d613
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport$5.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport$6.class b/src/main/resources/javax/xml/xpath/SecuritySupport$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..47dd888f24c5083fc7399eb35ad5bf466465bc9e
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport$6.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport$7.class b/src/main/resources/javax/xml/xpath/SecuritySupport$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..428695241069ed8cf6ce57a0b198819daf47843b
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport$7.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport$8.class b/src/main/resources/javax/xml/xpath/SecuritySupport$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..c904cc6908cfce489d2dfc20e963e0b9184f1d8f
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport$8.class differ
diff --git a/src/main/resources/javax/xml/xpath/SecuritySupport.class b/src/main/resources/javax/xml/xpath/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6451616ddba62a9f33fd1d515d943ce74438073
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/SecuritySupport.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPath.class b/src/main/resources/javax/xml/xpath/XPath.class
new file mode 100644
index 0000000000000000000000000000000000000000..7520d0d796119bcd0bdbf7f076af9890fc699919
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPath.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathConstants.class b/src/main/resources/javax/xml/xpath/XPathConstants.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4aa782228dcea9b6583d7426b8c4405cb7308a6
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathConstants.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathException.class b/src/main/resources/javax/xml/xpath/XPathException.class
new file mode 100644
index 0000000000000000000000000000000000000000..97ec99d4804ba6511cf30dda138dcee3012aa8e8
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathException.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathExpression.class b/src/main/resources/javax/xml/xpath/XPathExpression.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6b990e0d24e3f9e027353cfe4abf759e42994f7
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathExpression.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathExpressionException.class b/src/main/resources/javax/xml/xpath/XPathExpressionException.class
new file mode 100644
index 0000000000000000000000000000000000000000..33955d1633ae4eeeeb99d720fc1e65b08806d9a9
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathExpressionException.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFactory.class b/src/main/resources/javax/xml/xpath/XPathFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f6bd22a76f03a27eeed1c12ed36aaeae423b431
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFactory.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFactoryConfigurationException.class b/src/main/resources/javax/xml/xpath/XPathFactoryConfigurationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..c19e010634e31a9cb90e980f7b86962d8f9f4e66
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFactoryConfigurationException.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFactoryFinder$1.class b/src/main/resources/javax/xml/xpath/XPathFactoryFinder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e3b4e9ef28b779993f7ad5fb7581045b84875a1
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFactoryFinder$1.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFactoryFinder$2.class b/src/main/resources/javax/xml/xpath/XPathFactoryFinder$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..d84843a89d61b2cfca518f7be02f1de1f6999ea2
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFactoryFinder$2.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFactoryFinder$SingleIterator.class b/src/main/resources/javax/xml/xpath/XPathFactoryFinder$SingleIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b6e2cb16a8388b93e8644bc259142f34e06fa32
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFactoryFinder$SingleIterator.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFactoryFinder.class b/src/main/resources/javax/xml/xpath/XPathFactoryFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc856138192c67f3b7a9ec934bfe91ff6f10ba16
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFactoryFinder.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFunction.class b/src/main/resources/javax/xml/xpath/XPathFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2744af7551b361fde2aec4a65199c288af6e47f
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFunction.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFunctionException.class b/src/main/resources/javax/xml/xpath/XPathFunctionException.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ffe4fb0e49f053d0f5b4bc8eb8c0a8dcf6b6e9e
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFunctionException.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathFunctionResolver.class b/src/main/resources/javax/xml/xpath/XPathFunctionResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..28c831a522ddb5ab20c2d04b1c102f0c481205d4
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathFunctionResolver.class differ
diff --git a/src/main/resources/javax/xml/xpath/XPathVariableResolver.class b/src/main/resources/javax/xml/xpath/XPathVariableResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc0bdcda2a9aa195a6f4fc7e4f8e4fc1e72be92f
Binary files /dev/null and b/src/main/resources/javax/xml/xpath/XPathVariableResolver.class differ
diff --git a/src/main/resources/jline/ANSIBuffer$ANSICodes.class b/src/main/resources/jline/ANSIBuffer$ANSICodes.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cbd22073f0c372a580466dd31e6840e70c93534
Binary files /dev/null and b/src/main/resources/jline/ANSIBuffer$ANSICodes.class differ
diff --git a/src/main/resources/jline/ANSIBuffer.class b/src/main/resources/jline/ANSIBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..28cf5e637a130fd75e179d14193744e7576a4073
Binary files /dev/null and b/src/main/resources/jline/ANSIBuffer.class differ
diff --git a/src/main/resources/jline/ArgumentCompletor$AbstractArgumentDelimiter.class b/src/main/resources/jline/ArgumentCompletor$AbstractArgumentDelimiter.class
new file mode 100644
index 0000000000000000000000000000000000000000..b55b776993300a12c76c1aa3527461ecde5de5dd
Binary files /dev/null and b/src/main/resources/jline/ArgumentCompletor$AbstractArgumentDelimiter.class differ
diff --git a/src/main/resources/jline/ArgumentCompletor$ArgumentDelimiter.class b/src/main/resources/jline/ArgumentCompletor$ArgumentDelimiter.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ab236958c01c7411d336ffc7998eb795c979236
Binary files /dev/null and b/src/main/resources/jline/ArgumentCompletor$ArgumentDelimiter.class differ
diff --git a/src/main/resources/jline/ArgumentCompletor$ArgumentList.class b/src/main/resources/jline/ArgumentCompletor$ArgumentList.class
new file mode 100644
index 0000000000000000000000000000000000000000..21053fc7bacfa23831e81d797a50e71d1b4a6a95
Binary files /dev/null and b/src/main/resources/jline/ArgumentCompletor$ArgumentList.class differ
diff --git a/src/main/resources/jline/ArgumentCompletor$WhitespaceArgumentDelimiter.class b/src/main/resources/jline/ArgumentCompletor$WhitespaceArgumentDelimiter.class
new file mode 100644
index 0000000000000000000000000000000000000000..be0181f16bdbc58ecf7679cb049b36a1cd6bdc56
Binary files /dev/null and b/src/main/resources/jline/ArgumentCompletor$WhitespaceArgumentDelimiter.class differ
diff --git a/src/main/resources/jline/ArgumentCompletor.class b/src/main/resources/jline/ArgumentCompletor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b74e8562967244fe19cd5b63582c0baaf0e8bbde
Binary files /dev/null and b/src/main/resources/jline/ArgumentCompletor.class differ
diff --git a/src/main/resources/jline/CandidateCycleCompletionHandler.class b/src/main/resources/jline/CandidateCycleCompletionHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..8404befea06c0f20ab6f2c168445b597c8d8a819
Binary files /dev/null and b/src/main/resources/jline/CandidateCycleCompletionHandler.class differ
diff --git a/src/main/resources/jline/CandidateListCompletionHandler.class b/src/main/resources/jline/CandidateListCompletionHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..74ad124bb5eddf86be161076c1ca4c39e3b93488
Binary files /dev/null and b/src/main/resources/jline/CandidateListCompletionHandler.class differ
diff --git a/src/main/resources/jline/CandidateListCompletionHandler.properties b/src/main/resources/jline/CandidateListCompletionHandler.properties
new file mode 100644
index 0000000000000000000000000000000000000000..18ee221cc9ea8b68911aa28d5cbd4394c31ae020
--- /dev/null
+++ b/src/main/resources/jline/CandidateListCompletionHandler.properties
@@ -0,0 +1,5 @@
+display-candidates: Display all {0} possibilities? (y or n)
+display-candidates-yes: y
+display-candidates-no: n
+display-more: --More--
+
diff --git a/src/main/resources/jline/ClassNameCompletor.class b/src/main/resources/jline/ClassNameCompletor.class
new file mode 100644
index 0000000000000000000000000000000000000000..124ae422738499d3a029f1efad626cef6a210e38
Binary files /dev/null and b/src/main/resources/jline/ClassNameCompletor.class differ
diff --git a/src/main/resources/jline/CompletionHandler.class b/src/main/resources/jline/CompletionHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..638ddf0186fdd0b6a73c58bbab3b48552efd0dd8
Binary files /dev/null and b/src/main/resources/jline/CompletionHandler.class differ
diff --git a/src/main/resources/jline/Completor.class b/src/main/resources/jline/Completor.class
new file mode 100644
index 0000000000000000000000000000000000000000..554001585b6151bd65df91e4af4c79bd0f4ee8af
Binary files /dev/null and b/src/main/resources/jline/Completor.class differ
diff --git a/src/main/resources/jline/ConsoleOperations.class b/src/main/resources/jline/ConsoleOperations.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d19b18ab99d44640b323f204807cdbfa04dfb90
Binary files /dev/null and b/src/main/resources/jline/ConsoleOperations.class differ
diff --git a/src/main/resources/jline/ConsoleReader.class b/src/main/resources/jline/ConsoleReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..1769da4afdb88aebb9d03e309b36ed3ad4b0adb9
Binary files /dev/null and b/src/main/resources/jline/ConsoleReader.class differ
diff --git a/src/main/resources/jline/ConsoleReaderInputStream$ConsoleEnumeration.class b/src/main/resources/jline/ConsoleReaderInputStream$ConsoleEnumeration.class
new file mode 100644
index 0000000000000000000000000000000000000000..72d744d5e584286f8355c11aa38d3f957152527b
Binary files /dev/null and b/src/main/resources/jline/ConsoleReaderInputStream$ConsoleEnumeration.class differ
diff --git a/src/main/resources/jline/ConsoleReaderInputStream$ConsoleLineInputStream.class b/src/main/resources/jline/ConsoleReaderInputStream$ConsoleLineInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9a267d73e05b7dfc6c395b0104d7c72f0ab5bbf
Binary files /dev/null and b/src/main/resources/jline/ConsoleReaderInputStream$ConsoleLineInputStream.class differ
diff --git a/src/main/resources/jline/ConsoleReaderInputStream.class b/src/main/resources/jline/ConsoleReaderInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..764e0b369d6e546e229df3ce486c8e9f8fb217e2
Binary files /dev/null and b/src/main/resources/jline/ConsoleReaderInputStream.class differ
diff --git a/src/main/resources/jline/ConsoleRunner.class b/src/main/resources/jline/ConsoleRunner.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f22115e1c3817dc0c62464e0a3f9993853c73f7
Binary files /dev/null and b/src/main/resources/jline/ConsoleRunner.class differ
diff --git a/src/main/resources/jline/CursorBuffer.class b/src/main/resources/jline/CursorBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb86db98145ca141229848a4b036fa5db0ed1c1a
Binary files /dev/null and b/src/main/resources/jline/CursorBuffer.class differ
diff --git a/src/main/resources/jline/FileNameCompletor.class b/src/main/resources/jline/FileNameCompletor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b65985ac6ea0b49af709087f07e1bdf109f3393
Binary files /dev/null and b/src/main/resources/jline/FileNameCompletor.class differ
diff --git a/src/main/resources/jline/History.class b/src/main/resources/jline/History.class
new file mode 100644
index 0000000000000000000000000000000000000000..592827a2fbef2918ded33c3704baa5c1d9cef6e4
Binary files /dev/null and b/src/main/resources/jline/History.class differ
diff --git a/src/main/resources/jline/MultiCompletor.class b/src/main/resources/jline/MultiCompletor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e127b35d0717b10f37a10895ae23363eb56f9ae
Binary files /dev/null and b/src/main/resources/jline/MultiCompletor.class differ
diff --git a/src/main/resources/jline/NullCompletor.class b/src/main/resources/jline/NullCompletor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e469db0aa4b3d63e7eff40b7507ba2770f400db
Binary files /dev/null and b/src/main/resources/jline/NullCompletor.class differ
diff --git a/src/main/resources/jline/SimpleCompletor$NoOpFilter.class b/src/main/resources/jline/SimpleCompletor$NoOpFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb85d04f512767457d298936b25341ac33ef3d77
Binary files /dev/null and b/src/main/resources/jline/SimpleCompletor$NoOpFilter.class differ
diff --git a/src/main/resources/jline/SimpleCompletor$SimpleCompletorFilter.class b/src/main/resources/jline/SimpleCompletor$SimpleCompletorFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4f45dc49729431983bb719aaf4e67a0ae604c5a
Binary files /dev/null and b/src/main/resources/jline/SimpleCompletor$SimpleCompletorFilter.class differ
diff --git a/src/main/resources/jline/SimpleCompletor.class b/src/main/resources/jline/SimpleCompletor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0422562841c395a1477c08379e1a470699292ed9
Binary files /dev/null and b/src/main/resources/jline/SimpleCompletor.class differ
diff --git a/src/main/resources/jline/Terminal.class b/src/main/resources/jline/Terminal.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a05ee4af2ea2c3baac179b19c93f2093be3f648
Binary files /dev/null and b/src/main/resources/jline/Terminal.class differ
diff --git a/src/main/resources/jline/UnixTerminal$1.class b/src/main/resources/jline/UnixTerminal$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..11f96732fbe9776adac0a44e4385eb7457a24ac4
Binary files /dev/null and b/src/main/resources/jline/UnixTerminal$1.class differ
diff --git a/src/main/resources/jline/UnixTerminal$ReplayPrefixOneCharInputStream.class b/src/main/resources/jline/UnixTerminal$ReplayPrefixOneCharInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab860f2fcbb4129c749e77943f0c6ce870865603
Binary files /dev/null and b/src/main/resources/jline/UnixTerminal$ReplayPrefixOneCharInputStream.class differ
diff --git a/src/main/resources/jline/UnixTerminal.class b/src/main/resources/jline/UnixTerminal.class
new file mode 100644
index 0000000000000000000000000000000000000000..5485036ab53e67a2bff1c5874af3f4e5d57ffba1
Binary files /dev/null and b/src/main/resources/jline/UnixTerminal.class differ
diff --git a/src/main/resources/jline/UnsupportedTerminal$1.class b/src/main/resources/jline/UnsupportedTerminal$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..62e3b2277e1e314b92240fc58324a975378d4d5b
Binary files /dev/null and b/src/main/resources/jline/UnsupportedTerminal$1.class differ
diff --git a/src/main/resources/jline/UnsupportedTerminal.class b/src/main/resources/jline/UnsupportedTerminal.class
new file mode 100644
index 0000000000000000000000000000000000000000..eda00168ac30b9f94ceaa62a2c4d1a032d2a10b3
Binary files /dev/null and b/src/main/resources/jline/UnsupportedTerminal.class differ
diff --git a/src/main/resources/jline/WindowsTerminal$1.class b/src/main/resources/jline/WindowsTerminal$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6ffc6e35408e3f35eef9f6ff901ab4f405c43ad
Binary files /dev/null and b/src/main/resources/jline/WindowsTerminal$1.class differ
diff --git a/src/main/resources/jline/WindowsTerminal$ReplayPrefixOneCharInputStream.class b/src/main/resources/jline/WindowsTerminal$ReplayPrefixOneCharInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..072fa7db092d4ff87009609b961db76fd3017aa9
Binary files /dev/null and b/src/main/resources/jline/WindowsTerminal$ReplayPrefixOneCharInputStream.class differ
diff --git a/src/main/resources/jline/WindowsTerminal.class b/src/main/resources/jline/WindowsTerminal.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad677f02b9d08434facc88c7243f08292cb755a8
Binary files /dev/null and b/src/main/resources/jline/WindowsTerminal.class differ
diff --git a/src/main/resources/jline/jline32.dll b/src/main/resources/jline/jline32.dll
new file mode 100644
index 0000000000000000000000000000000000000000..a0d3b117ce19afe904437b62468253902db276c8
Binary files /dev/null and b/src/main/resources/jline/jline32.dll differ
diff --git a/src/main/resources/jline/jline64.dll b/src/main/resources/jline/jline64.dll
new file mode 100644
index 0000000000000000000000000000000000000000..922d6b01c5f51bccd690efd5dc8bbe78d44c37ce
Binary files /dev/null and b/src/main/resources/jline/jline64.dll differ
diff --git a/src/main/resources/jline/keybindings-mac.properties b/src/main/resources/jline/keybindings-mac.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6f13615d84c8addc4eee18e37d4b79dd390bdc4e
--- /dev/null
+++ b/src/main/resources/jline/keybindings-mac.properties
@@ -0,0 +1,62 @@
+# Keybinding mapping for JLine. The format is:
+#    [key code]: [logical operation]
+
+# CTRL-B: move to the previous character
+2: PREV_CHAR
+
+# CTRL-G: move to the previous word
+7: PREV_WORD
+
+# CTRL-F: move to the next character
+6: NEXT_CHAR
+
+# CTRL-A: move to the beginning of the line
+1: MOVE_TO_BEG
+
+# CTRL-D: close out the input stream
+4: EXIT
+
+# CTRL-E: move the cursor to the end of the line
+5: MOVE_TO_END
+
+# BACKSPACE, CTRL-H: delete the previous character
+# 8 is the ASCII code for backspace and therefor
+# deleting the previous character
+8: DELETE_PREV_CHAR
+
+# TAB, CTRL-I: signal that console completion should be attempted
+9: COMPLETE
+
+# CTRL-J, CTRL-M: newline
+10: NEWLINE
+
+# CTRL-K: erase the current line
+11: KILL_LINE
+
+# ENTER: newline
+13: NEWLINE
+
+# CTRL-L: clear screen
+12: CLEAR_SCREEN
+
+# CTRL-N: scroll to the next element in the history buffer
+14: NEXT_HISTORY
+
+# CTRL-P: scroll to the previous element in the history buffer
+16: PREV_HISTORY
+
+# CTRL-R: redraw the current line
+18: REDISPLAY
+
+# CTRL-U: delete all the characters before the cursor position
+21: KILL_LINE_PREV
+
+# CTRL-V: paste the contents of the clipboard (useful for Windows terminal)
+22: PASTE
+
+# CTRL-W: delete the word directly before the cursor
+23: DELETE_PREV_WORD
+
+# DELETE, CTRL-?: delete the previous character
+# 127 is the ASCII code for delete
+127: DELETE_PREV_CHAR
diff --git a/src/main/resources/jline/keybindings.properties b/src/main/resources/jline/keybindings.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9585e3a8ddd129fcc7182aa109cf8b8f0d945df7
--- /dev/null
+++ b/src/main/resources/jline/keybindings.properties
@@ -0,0 +1,68 @@
+# Keybinding mapping for JLine. The format is:
+#    [key code]: [logical operation]
+
+# CTRL-A: move to the beginning of the line
+1: MOVE_TO_BEG
+
+# CTRL-B: move to the previous character
+2: PREV_CHAR
+
+# CTRL-D: close out the input stream
+4: EXIT
+
+# CTRL-E: move the cursor to the end of the line
+5: MOVE_TO_END
+
+# CTRL-F: move to the next character
+6: NEXT_CHAR
+
+# CTRL-G: move to the previous word
+7: ABORT
+
+# BACKSPACE, CTRL-H: delete the previous character
+# 8 is the ASCII code for backspace and therefor
+# deleting the previous character
+8: DELETE_PREV_CHAR
+
+# TAB, CTRL-I: signal that console completion should be attempted
+9: COMPLETE
+
+# CTRL-J, CTRL-M: newline
+10: NEWLINE
+
+# CTRL-K: erase the current line
+11: KILL_LINE
+
+# CTRL-L: clear screen
+12: CLEAR_SCREEN
+
+# ENTER: newline
+13: NEWLINE
+
+# CTRL-N: scroll to the next element in the history buffer
+14: NEXT_HISTORY
+
+# CTRL-P: scroll to the previous element in the history buffer
+16: PREV_HISTORY
+
+# CTRL-R: redraw the current line
+18: SEARCH_PREV
+
+# CTRL-U: delete all the characters before the cursor position
+21: KILL_LINE_PREV
+
+# CTRL-V: paste the contents of the clipboard (useful for Windows terminal)
+22: PASTE
+
+# CTRL-W: delete the word directly before the cursor
+23: DELETE_PREV_WORD
+
+# CTRL-X: temporary location for PREV_WORD to make tests pass
+24: PREV_WORD
+
+# ESCAPE probably not intended this way, but it does the right thing for now 
+27: REDISPLAY
+
+# DELETE, CTRL-?: delete the next character
+# 127 is the ASCII code for delete
+127: DELETE_NEXT_CHAR
diff --git a/src/main/resources/jline/windowsbindings.properties b/src/main/resources/jline/windowsbindings.properties
new file mode 100644
index 0000000000000000000000000000000000000000..d599c694ae77f4e0eb3b6f85119664911f0f469b
--- /dev/null
+++ b/src/main/resources/jline/windowsbindings.properties
@@ -0,0 +1,68 @@
+# Keybinding mapping for JLine. The format is:
+#    [key code]: [logical operation]
+
+# CTRL-A: move to the beginning of the line
+1: MOVE_TO_BEG
+
+# CTRL-B: move to the previous character
+2: PREV_CHAR
+
+# CTRL-C: toggle overtype mode (frankly, I wasn't sure where to bind this)
+3: INSERT
+
+# CTRL-D: close out the input stream
+4: EXIT
+
+# CTRL-E: move the cursor to the end of the line
+5: MOVE_TO_END
+
+# CTRL-F: move to the next character
+6: NEXT_CHAR
+
+# CTRL-G: move to the previous word
+7: ABORT
+
+# CTRL-H: delete the previous character
+8: DELETE_PREV_CHAR
+
+# TAB, CTRL-I: signal that console completion should be attempted
+9: COMPLETE
+
+# CTRL-J, CTRL-M: newline
+10: NEWLINE
+
+# CTRL-K: Vertical tab - on windows we'll move to the start of the history
+11: START_OF_HISTORY
+
+# CTRL-L: Form feed - on windows, we'll move to the end of the history
+12: END_OF_HISTORY
+
+# ENTER: newline
+13: NEWLINE
+
+# CTRL-N: scroll to the next element in the history buffer
+14: NEXT_HISTORY
+
+# CTRL-P: scroll to the previous element in the history buffer
+16: PREV_HISTORY
+
+# CTRL-R: search backwards in history
+18: SEARCH_PREV
+
+# CTRL-U: delete all the characters before the cursor position
+21: KILL_LINE_PREV
+
+# CTRL-V: paste the contents of the clipboard (useful for Windows terminal)
+22: PASTE
+
+# CTRL-W: delete the word directly before the cursor
+23: DELETE_PREV_WORD
+
+# CTRL-X: temporary location for PREV_WORD to make tests pass
+24: PREV_WORD
+
+# CTRL-[: escape - clear the current line.
+27: CLEAR_LINE
+
+# CTRL-?: delete the previous character
+127: DELETE_NEXT_CHAR
diff --git a/src/main/resources/jni/Darwin/libjffi-1.2.jnilib b/src/main/resources/jni/Darwin/libjffi-1.2.jnilib
new file mode 100644
index 0000000000000000000000000000000000000000..cf5d35645ca6d84587cef474eb1252d71e93e87b
Binary files /dev/null and b/src/main/resources/jni/Darwin/libjffi-1.2.jnilib differ
diff --git a/src/main/resources/jni/arm-Linux/libjffi-1.2.so b/src/main/resources/jni/arm-Linux/libjffi-1.2.so
new file mode 100644
index 0000000000000000000000000000000000000000..768b48931774e05fef2f2eca1ff0b5e2239d7e6c
Binary files /dev/null and b/src/main/resources/jni/arm-Linux/libjffi-1.2.so differ
diff --git a/src/main/resources/jni/i386-Linux/libjffi-1.2.so b/src/main/resources/jni/i386-Linux/libjffi-1.2.so
new file mode 100644
index 0000000000000000000000000000000000000000..bec318991111ec672de56d9c7b0bd99e4d299434
Binary files /dev/null and b/src/main/resources/jni/i386-Linux/libjffi-1.2.so differ
diff --git a/src/main/resources/jni/i386-SunOS/libjffi-1.2.so b/src/main/resources/jni/i386-SunOS/libjffi-1.2.so
new file mode 100644
index 0000000000000000000000000000000000000000..70a45a33edaea8d74b61d4e56a4a3a145c509c68
Binary files /dev/null and b/src/main/resources/jni/i386-SunOS/libjffi-1.2.so differ
diff --git a/src/main/resources/jni/i386-Windows/jffi-1.2.dll b/src/main/resources/jni/i386-Windows/jffi-1.2.dll
new file mode 100644
index 0000000000000000000000000000000000000000..1795623c44e72c0875728ff057ec4c8bdba502b0
Binary files /dev/null and b/src/main/resources/jni/i386-Windows/jffi-1.2.dll differ
diff --git a/src/main/resources/jni/sparcv9-SunOS/libjffi-1.2.so b/src/main/resources/jni/sparcv9-SunOS/libjffi-1.2.so
new file mode 100644
index 0000000000000000000000000000000000000000..4e0f92aab584207f1f278a93862c0c9d319186b2
Binary files /dev/null and b/src/main/resources/jni/sparcv9-SunOS/libjffi-1.2.so differ
diff --git a/src/main/resources/jni/x86_64-FreeBSD/libjffi-1.2.so b/src/main/resources/jni/x86_64-FreeBSD/libjffi-1.2.so
new file mode 100644
index 0000000000000000000000000000000000000000..516acb096950e9832d7ae722a78e05ecc19368bc
Binary files /dev/null and b/src/main/resources/jni/x86_64-FreeBSD/libjffi-1.2.so differ
diff --git a/src/main/resources/jni/x86_64-Linux/libjffi-1.2.so b/src/main/resources/jni/x86_64-Linux/libjffi-1.2.so
new file mode 100644
index 0000000000000000000000000000000000000000..c61095c8dfddffd9e3f50e3a06da714af4eaee99
Binary files /dev/null and b/src/main/resources/jni/x86_64-Linux/libjffi-1.2.so differ
diff --git a/src/main/resources/jni/x86_64-SunOS/libjffi-1.2.so b/src/main/resources/jni/x86_64-SunOS/libjffi-1.2.so
new file mode 100644
index 0000000000000000000000000000000000000000..48477ea4d6e93d00874117bea8890489ce7024be
Binary files /dev/null and b/src/main/resources/jni/x86_64-SunOS/libjffi-1.2.so differ
diff --git a/src/main/resources/jni/x86_64-Windows/jffi-1.2.dll b/src/main/resources/jni/x86_64-Windows/jffi-1.2.dll
new file mode 100644
index 0000000000000000000000000000000000000000..9316aacbcfc8bc447d41ef7952d9bca25433105e
Binary files /dev/null and b/src/main/resources/jni/x86_64-Windows/jffi-1.2.dll differ
diff --git a/src/main/resources/jnr/constants/Constant.class b/src/main/resources/jnr/constants/Constant.class
new file mode 100644
index 0000000000000000000000000000000000000000..c19e705bd50dbfb0a447074243a34c83cb852810
Binary files /dev/null and b/src/main/resources/jnr/constants/Constant.class differ
diff --git a/src/main/resources/jnr/constants/ConstantSet$ConstantIterator.class b/src/main/resources/jnr/constants/ConstantSet$ConstantIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a67731ba3428b2184822fd36506e36dc73b8798
Binary files /dev/null and b/src/main/resources/jnr/constants/ConstantSet$ConstantIterator.class differ
diff --git a/src/main/resources/jnr/constants/ConstantSet.class b/src/main/resources/jnr/constants/ConstantSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..9270af0ff4adb6ad02c7fdc776c0ceba534d79e7
Binary files /dev/null and b/src/main/resources/jnr/constants/ConstantSet.class differ
diff --git a/src/main/resources/jnr/constants/Platform$1.class b/src/main/resources/jnr/constants/Platform$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..14a5e99bfca3cc27ebbba01873a9c5b5c691ce00
Binary files /dev/null and b/src/main/resources/jnr/constants/Platform$1.class differ
diff --git a/src/main/resources/jnr/constants/Platform$2.class b/src/main/resources/jnr/constants/Platform$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..58aa3d4148acd60b389a9b5910fb4c19923d28c4
Binary files /dev/null and b/src/main/resources/jnr/constants/Platform$2.class differ
diff --git a/src/main/resources/jnr/constants/Platform$PackageNameResolver.class b/src/main/resources/jnr/constants/Platform$PackageNameResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7d40974d68ab4d0ffcc099962a3522db49c54b0
Binary files /dev/null and b/src/main/resources/jnr/constants/Platform$PackageNameResolver.class differ
diff --git a/src/main/resources/jnr/constants/Platform.class b/src/main/resources/jnr/constants/Platform.class
new file mode 100644
index 0000000000000000000000000000000000000000..da37aef2724ad180498a1e6679219ec09cf8d379
Binary files /dev/null and b/src/main/resources/jnr/constants/Platform.class differ
diff --git a/src/main/resources/jnr/constants/platform/AddressFamily.class b/src/main/resources/jnr/constants/platform/AddressFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecc6a2e52ad7e9e1ebc591d0b35b88f9e0936615
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/AddressFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/ConstantResolver$UnknownConstant.class b/src/main/resources/jnr/constants/platform/ConstantResolver$UnknownConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..eeb90add0d39a4ae5ae3bae48f5038ec3d2c7289
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/ConstantResolver$UnknownConstant.class differ
diff --git a/src/main/resources/jnr/constants/platform/ConstantResolver.class b/src/main/resources/jnr/constants/platform/ConstantResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..670ab1b34bb0e7173cb159b9dd13983f0338580a
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/ConstantResolver.class differ
diff --git a/src/main/resources/jnr/constants/platform/Errno.class b/src/main/resources/jnr/constants/platform/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..b96bf4c5c54f8739f57da2b72aa5947cd852f1a5
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/Errno.class differ
diff --git a/src/main/resources/jnr/constants/platform/Fcntl.class b/src/main/resources/jnr/constants/platform/Fcntl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8b129bef11d247f9223ca558a5bb11120b0466a
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/Fcntl.class differ
diff --git a/src/main/resources/jnr/constants/platform/INAddr.class b/src/main/resources/jnr/constants/platform/INAddr.class
new file mode 100644
index 0000000000000000000000000000000000000000..b54dd5673310fbffdff5e843b6d5de14c38bf3b3
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/INAddr.class differ
diff --git a/src/main/resources/jnr/constants/platform/IPProto.class b/src/main/resources/jnr/constants/platform/IPProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..7769df9617492816ee7bbea2644d0d5300c0fb92
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/IPProto.class differ
diff --git a/src/main/resources/jnr/constants/platform/NameInfo.class b/src/main/resources/jnr/constants/platform/NameInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..474edba6ae672c27f9fd3c5abc2c6617afc4b0a1
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/NameInfo.class differ
diff --git a/src/main/resources/jnr/constants/platform/OpenFlags.class b/src/main/resources/jnr/constants/platform/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe8e41b4e57f10a188a177dc08389b2bd2dd5649
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/OpenFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/PRIO.class b/src/main/resources/jnr/constants/platform/PRIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..090a4ab764e03c5880bc66d58e8bc8d6b96bddc9
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/PRIO.class differ
diff --git a/src/main/resources/jnr/constants/platform/ProtocolFamily.class b/src/main/resources/jnr/constants/platform/ProtocolFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..46745278f9259555385fee7b9f306fcb70b78110
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/ProtocolFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/RLIM.class b/src/main/resources/jnr/constants/platform/RLIM.class
new file mode 100644
index 0000000000000000000000000000000000000000..d46ec63dd3822e36d3648bed1232c2ea7a9d8d7d
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/RLIM.class differ
diff --git a/src/main/resources/jnr/constants/platform/RLIMIT.class b/src/main/resources/jnr/constants/platform/RLIMIT.class
new file mode 100644
index 0000000000000000000000000000000000000000..4376afd4f5e7a137b11c2b9d3560087b3a8d686f
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/RLIMIT.class differ
diff --git a/src/main/resources/jnr/constants/platform/Shutdown.class b/src/main/resources/jnr/constants/platform/Shutdown.class
new file mode 100644
index 0000000000000000000000000000000000000000..958c12fad15c298cde1317cf591cbaa6aa4785c2
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/Shutdown.class differ
diff --git a/src/main/resources/jnr/constants/platform/Signal.class b/src/main/resources/jnr/constants/platform/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..80609ef14bc40c015de06a2482f7a23dc6a73d74
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/Signal.class differ
diff --git a/src/main/resources/jnr/constants/platform/Sock.class b/src/main/resources/jnr/constants/platform/Sock.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3eb19aa5c3f9aced5bf734b8bc633f5cb918d10
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/Sock.class differ
diff --git a/src/main/resources/jnr/constants/platform/SocketLevel.class b/src/main/resources/jnr/constants/platform/SocketLevel.class
new file mode 100644
index 0000000000000000000000000000000000000000..5afa0e2739b0838830a0bb68e0b085be6c2eccb2
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/SocketLevel.class differ
diff --git a/src/main/resources/jnr/constants/platform/SocketOption.class b/src/main/resources/jnr/constants/platform/SocketOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..48cefc3ec92982eceadc77ae5b53750d3c2c88a4
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/SocketOption.class differ
diff --git a/src/main/resources/jnr/constants/platform/Sysconf.class b/src/main/resources/jnr/constants/platform/Sysconf.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6af4497f8abd5983dfa5a2b33fb427ba3cdcc84
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/Sysconf.class differ
diff --git a/src/main/resources/jnr/constants/platform/TCP.class b/src/main/resources/jnr/constants/platform/TCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..860cc10b75f55cc316d8d872e51ec7d4ffe98810
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/TCP.class differ
diff --git a/src/main/resources/jnr/constants/platform/WaitFlags.class b/src/main/resources/jnr/constants/platform/WaitFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..439f139e6e3bf8e549767cdad3ad4dfd15da20c9
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/WaitFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/AddressFamily.class b/src/main/resources/jnr/constants/platform/darwin/AddressFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..43bfd2116e2d82fa5a483b5137279ab8198cd04b
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/AddressFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/Errno$StringTable.class b/src/main/resources/jnr/constants/platform/darwin/Errno$StringTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..577c895f2d09d5b00490322b428308ea0f361579
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/Errno$StringTable.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/Errno.class b/src/main/resources/jnr/constants/platform/darwin/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..f341b829f57ec06340b7d1a0265921fba839fa60
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/Errno.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/Fcntl.class b/src/main/resources/jnr/constants/platform/darwin/Fcntl.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ff6be3437be6131db1f2c2226379387d5b42031
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/Fcntl.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/INAddr.class b/src/main/resources/jnr/constants/platform/darwin/INAddr.class
new file mode 100644
index 0000000000000000000000000000000000000000..3288890f403630ff049e6fcacd2c8f92c0f80810
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/INAddr.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/IPProto.class b/src/main/resources/jnr/constants/platform/darwin/IPProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..accf8e631a99d4502caab6bb3f64fe0edf246acf
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/IPProto.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/NameInfo.class b/src/main/resources/jnr/constants/platform/darwin/NameInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..55ad81e4e5aca96b681a02d80c4d62b1d0888d74
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/NameInfo.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/OpenFlags.class b/src/main/resources/jnr/constants/platform/darwin/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..af72c1715566e1204e2b2d4bd13902baabbea15f
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/OpenFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/PRIO.class b/src/main/resources/jnr/constants/platform/darwin/PRIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3c166edeefa0a7de79baee02864b63ea1371375
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/PRIO.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/ProtocolFamily.class b/src/main/resources/jnr/constants/platform/darwin/ProtocolFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..de90a4582140ac9f36ba90a14904c480eeab4ca4
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/ProtocolFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/RLIM.class b/src/main/resources/jnr/constants/platform/darwin/RLIM.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf5ea7d2456ba94ccaf9ecabf43b0f07a82422d0
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/RLIM.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/RLIMIT.class b/src/main/resources/jnr/constants/platform/darwin/RLIMIT.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa483112325dcfc6ba99f10ea34477764c5165dd
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/RLIMIT.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/Shutdown.class b/src/main/resources/jnr/constants/platform/darwin/Shutdown.class
new file mode 100644
index 0000000000000000000000000000000000000000..570b44fe2973d57ef3646dd5ba243c6fb400fe64
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/Shutdown.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/Signal.class b/src/main/resources/jnr/constants/platform/darwin/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4730e3d3203225860a3024f3d0059aeff3d2ad8
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/Signal.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/Sock.class b/src/main/resources/jnr/constants/platform/darwin/Sock.class
new file mode 100644
index 0000000000000000000000000000000000000000..3dcf7036e955521fdda60799ed3f348fac0ae1fa
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/Sock.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/SocketLevel.class b/src/main/resources/jnr/constants/platform/darwin/SocketLevel.class
new file mode 100644
index 0000000000000000000000000000000000000000..b29d88f58062748aeefde3fda25501402cb56944
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/SocketLevel.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/SocketOption.class b/src/main/resources/jnr/constants/platform/darwin/SocketOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..09e80da0e5ca54bcf94831a670e94d97e68f4705
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/SocketOption.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/Sysconf.class b/src/main/resources/jnr/constants/platform/darwin/Sysconf.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f4b5fff38a55e56a4eda657d94c26cfdeee1dab
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/Sysconf.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/TCP.class b/src/main/resources/jnr/constants/platform/darwin/TCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c1ff470a8c65491e5ca0ca544aafcaf8658950a
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/TCP.class differ
diff --git a/src/main/resources/jnr/constants/platform/darwin/WaitFlags.class b/src/main/resources/jnr/constants/platform/darwin/WaitFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ba4dec54230685f999a908db35059f00998ec23
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/darwin/WaitFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/AddressFamily.class b/src/main/resources/jnr/constants/platform/fake/AddressFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..93a1e8febd3cfd6c729138bf896d5741a03337a7
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/AddressFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/Errno.class b/src/main/resources/jnr/constants/platform/fake/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..a473782e9c0bdedf63e026d5acaf958665f3c9dd
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/Errno.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/Fcntl.class b/src/main/resources/jnr/constants/platform/fake/Fcntl.class
new file mode 100644
index 0000000000000000000000000000000000000000..275de74e49716e061f5e607e596d12f611b5311d
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/Fcntl.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/INAddr.class b/src/main/resources/jnr/constants/platform/fake/INAddr.class
new file mode 100644
index 0000000000000000000000000000000000000000..da7d4001abbde2a2a93e1e7eb26f2a4b51509407
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/INAddr.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/IPProto.class b/src/main/resources/jnr/constants/platform/fake/IPProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a2d2610229101798c0fb03d7e85b941a55f8e4f
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/IPProto.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/NameInfo.class b/src/main/resources/jnr/constants/platform/fake/NameInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..de6c9eb925992db8b6f1f63c50c619581ebe8aff
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/NameInfo.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/OpenFlags.class b/src/main/resources/jnr/constants/platform/fake/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e179368601ccb095153088cf42d32193bd96299
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/OpenFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/PRIO.class b/src/main/resources/jnr/constants/platform/fake/PRIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..763e9b58d6b6ec4e0c88f1da1b8ee898057a2ff1
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/PRIO.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/ProtocolFamily.class b/src/main/resources/jnr/constants/platform/fake/ProtocolFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae8dc0cb5dbc52e24379679cf03042b8fd86b0ad
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/ProtocolFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/RLIM.class b/src/main/resources/jnr/constants/platform/fake/RLIM.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5d0b6008301f72e3aa3e0c2bfa6eb52e2e77840
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/RLIM.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/RLIMIT.class b/src/main/resources/jnr/constants/platform/fake/RLIMIT.class
new file mode 100644
index 0000000000000000000000000000000000000000..2193059c86a3aba4a0c41d92d0e5f4281c7ed03f
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/RLIMIT.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/Shutdown.class b/src/main/resources/jnr/constants/platform/fake/Shutdown.class
new file mode 100644
index 0000000000000000000000000000000000000000..d728697ed1f60cadaf70300435a68b7919b37eeb
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/Shutdown.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/Signal.class b/src/main/resources/jnr/constants/platform/fake/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ad94ea6e9561c67201c3f835fd5fe5e5c0ec662
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/Signal.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/Sock.class b/src/main/resources/jnr/constants/platform/fake/Sock.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e27d4c0c978b7f1edcb0c9bdbe1ee96430e4bb7
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/Sock.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/SocketLevel.class b/src/main/resources/jnr/constants/platform/fake/SocketLevel.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b18a4594835712178c3389006c5b624c9c3afbd
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/SocketLevel.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/SocketOption.class b/src/main/resources/jnr/constants/platform/fake/SocketOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..12dbb819ecc3d916349339a49ce15ed592460b98
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/SocketOption.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/Sysconf.class b/src/main/resources/jnr/constants/platform/fake/Sysconf.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c06f1961836685e1d39d8f50de86fadd62a5771
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/Sysconf.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/TCP.class b/src/main/resources/jnr/constants/platform/fake/TCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..c200bb315a7bc6faaeec5441aa7c6ab415db5ad6
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/TCP.class differ
diff --git a/src/main/resources/jnr/constants/platform/fake/WaitFlags.class b/src/main/resources/jnr/constants/platform/fake/WaitFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..8104e73830719bb542b90dcdd41160f0eec66b52
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/fake/WaitFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/AddressFamily.class b/src/main/resources/jnr/constants/platform/freebsd/AddressFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e1b40b7a2c235c2f37d9b4efe3749751bbb0f2d
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/AddressFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/Errno$StringTable.class b/src/main/resources/jnr/constants/platform/freebsd/Errno$StringTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..432458b1eaf70706542fbb6e674220add2343f50
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/Errno$StringTable.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/Errno.class b/src/main/resources/jnr/constants/platform/freebsd/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..61a7a0a178d28b8295fd0bfdd5830c834646501a
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/Errno.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/Fcntl.class b/src/main/resources/jnr/constants/platform/freebsd/Fcntl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff11a786c8da7d7b538e8deff07143c8d0a9d0f3
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/Fcntl.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/INAddr.class b/src/main/resources/jnr/constants/platform/freebsd/INAddr.class
new file mode 100644
index 0000000000000000000000000000000000000000..093f6ca602337ae2a2a9366a29bc7718b7aa4bfc
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/INAddr.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/IPProto.class b/src/main/resources/jnr/constants/platform/freebsd/IPProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..3576fb7ab92ea90fcab3b3aaf10c30d603d58bfe
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/IPProto.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/NameInfo.class b/src/main/resources/jnr/constants/platform/freebsd/NameInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..0dedeb106ad9c91950f04335ca72de6e5297b415
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/NameInfo.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/OpenFlags.class b/src/main/resources/jnr/constants/platform/freebsd/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..5bd34ee49ac3ecc1f89293613c5cda690d381b62
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/OpenFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/PRIO.class b/src/main/resources/jnr/constants/platform/freebsd/PRIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..934b760d0d4c2ab38779bf1fbec9f5d004357478
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/PRIO.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/ProtocolFamily.class b/src/main/resources/jnr/constants/platform/freebsd/ProtocolFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f997c514ab05c76b6fd6856f238654579eea6be
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/ProtocolFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/RLIM.class b/src/main/resources/jnr/constants/platform/freebsd/RLIM.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d091d2971af55d5ee420c53b56795d94ba40b59
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/RLIM.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/RLIMIT.class b/src/main/resources/jnr/constants/platform/freebsd/RLIMIT.class
new file mode 100644
index 0000000000000000000000000000000000000000..b309d1a65aeb620e4d1405e2b7745371d4601203
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/RLIMIT.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/Shutdown.class b/src/main/resources/jnr/constants/platform/freebsd/Shutdown.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c3941f392f986045a2658f74c024671d27447a5
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/Shutdown.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/Signal.class b/src/main/resources/jnr/constants/platform/freebsd/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..87a244cacd678d57216238db89f8f365a08e440e
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/Signal.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/Sock.class b/src/main/resources/jnr/constants/platform/freebsd/Sock.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb7059d1c36ee2803a33da0a15a6e46a0d27d329
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/Sock.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/SocketLevel.class b/src/main/resources/jnr/constants/platform/freebsd/SocketLevel.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f82cb910130fc0b3e627abe78f229de7cd08000
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/SocketLevel.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/SocketOption.class b/src/main/resources/jnr/constants/platform/freebsd/SocketOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..91d6a212256ed2dc31bc073733e908f58b266678
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/SocketOption.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/Sysconf.class b/src/main/resources/jnr/constants/platform/freebsd/Sysconf.class
new file mode 100644
index 0000000000000000000000000000000000000000..525589dcd28b974df9f0dae6f170156468bd3c2e
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/Sysconf.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/TCP.class b/src/main/resources/jnr/constants/platform/freebsd/TCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae26e03e892e3bf8af303e111f09b5cdf8255bd8
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/TCP.class differ
diff --git a/src/main/resources/jnr/constants/platform/freebsd/WaitFlags.class b/src/main/resources/jnr/constants/platform/freebsd/WaitFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0f9e532b4599bd8e5e439f3e21cb7d0caeb18e5
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/freebsd/WaitFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/AddressFamily.class b/src/main/resources/jnr/constants/platform/linux/AddressFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..8eb4d087265790027e71586a042eb5a1c1b7c7de
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/AddressFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/Errno$StringTable.class b/src/main/resources/jnr/constants/platform/linux/Errno$StringTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..58b6171b01921320d75302e185c0794664ff9e7c
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/Errno$StringTable.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/Errno.class b/src/main/resources/jnr/constants/platform/linux/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f1e6884566ca44004a4e11fba9975c651665022
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/Errno.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/Fcntl.class b/src/main/resources/jnr/constants/platform/linux/Fcntl.class
new file mode 100644
index 0000000000000000000000000000000000000000..f24cff8bd3975452c3ee8644228d0a227528a514
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/Fcntl.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/INAddr.class b/src/main/resources/jnr/constants/platform/linux/INAddr.class
new file mode 100644
index 0000000000000000000000000000000000000000..30dc12d5471427b309d05e6b0c93937296045f54
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/INAddr.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/IPProto.class b/src/main/resources/jnr/constants/platform/linux/IPProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..29c2ecb0dbf805da15914e14525453788e486afa
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/IPProto.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/NameInfo.class b/src/main/resources/jnr/constants/platform/linux/NameInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..234b6a7e21b1832cc8ad824ab48a66b244c67b48
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/NameInfo.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/OpenFlags.class b/src/main/resources/jnr/constants/platform/linux/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bebd768a1f77b6cb1cfeb95938926a25158bc77
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/OpenFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/PRIO.class b/src/main/resources/jnr/constants/platform/linux/PRIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a8bc04b5422917e803beefaac5197d82b401fc1
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/PRIO.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/ProtocolFamily.class b/src/main/resources/jnr/constants/platform/linux/ProtocolFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c09183a91100203af50bfece3061910c8123ed2
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/ProtocolFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/RLIM.class b/src/main/resources/jnr/constants/platform/linux/RLIM.class
new file mode 100644
index 0000000000000000000000000000000000000000..a79690dc21d85585baa72f5bb463146bbc2a2d39
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/RLIM.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/RLIMIT.class b/src/main/resources/jnr/constants/platform/linux/RLIMIT.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b071133f2bb272f7297ca53a7f68b1e163d93bf
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/RLIMIT.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/Shutdown.class b/src/main/resources/jnr/constants/platform/linux/Shutdown.class
new file mode 100644
index 0000000000000000000000000000000000000000..6945a19f3f9691206a5bd3593023c04237b8b037
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/Shutdown.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/Signal.class b/src/main/resources/jnr/constants/platform/linux/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..104ef308010c297c260f07bdbc16d38557ca829b
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/Signal.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/Sock.class b/src/main/resources/jnr/constants/platform/linux/Sock.class
new file mode 100644
index 0000000000000000000000000000000000000000..9656be4f192bd6048bbab1e1fbfec78ac966dfa9
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/Sock.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/SocketLevel.class b/src/main/resources/jnr/constants/platform/linux/SocketLevel.class
new file mode 100644
index 0000000000000000000000000000000000000000..da017b60b018096dc6a24f8e9dd4a0fd0a95ab66
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/SocketLevel.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/SocketOption.class b/src/main/resources/jnr/constants/platform/linux/SocketOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..a250b7e09f385c885e4ab9e3012067370b8c9976
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/SocketOption.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/Sysconf.class b/src/main/resources/jnr/constants/platform/linux/Sysconf.class
new file mode 100644
index 0000000000000000000000000000000000000000..64a4b49ef54f62ce45494596f99187dd2eaf2948
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/Sysconf.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/TCP.class b/src/main/resources/jnr/constants/platform/linux/TCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..e082457f9c3b86fd0ba38b9378b057b061f92fc5
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/TCP.class differ
diff --git a/src/main/resources/jnr/constants/platform/linux/WaitFlags.class b/src/main/resources/jnr/constants/platform/linux/WaitFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c0fade016906decfd453d42cb75e23f9d599d5f
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/linux/WaitFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/AddressFamily.class b/src/main/resources/jnr/constants/platform/openbsd/AddressFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..161feab7273ee032e2561bc829d12d704644e213
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/AddressFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/Errno$StringTable.class b/src/main/resources/jnr/constants/platform/openbsd/Errno$StringTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..adccbf2b85cef649856e809a9390ff714efa688e
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/Errno$StringTable.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/Errno.class b/src/main/resources/jnr/constants/platform/openbsd/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb8a5c18d5e4656b812f8c482159868c706556a9
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/Errno.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/Fcntl.class b/src/main/resources/jnr/constants/platform/openbsd/Fcntl.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc8b5664ad0d869384d99077e383d49e85b4adb7
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/Fcntl.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/INAddr.class b/src/main/resources/jnr/constants/platform/openbsd/INAddr.class
new file mode 100644
index 0000000000000000000000000000000000000000..345443fdffe1fb030bdd7de10300e96784ac929b
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/INAddr.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/IPProto.class b/src/main/resources/jnr/constants/platform/openbsd/IPProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5fff1d1cdf605f5fb796ddcaeaeb149db37ad54
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/IPProto.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/NameInfo.class b/src/main/resources/jnr/constants/platform/openbsd/NameInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a5b32ece48fca92321b086d88227cf890d6929f
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/NameInfo.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/OpenFlags.class b/src/main/resources/jnr/constants/platform/openbsd/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..87f7702bb78aded5ca8eed7ffbfd880d20d5ae0d
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/OpenFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/PRIO.class b/src/main/resources/jnr/constants/platform/openbsd/PRIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..fce2c4d4719362a1f2c1941fdbb1f126db17d7e3
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/PRIO.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/ProtocolFamily.class b/src/main/resources/jnr/constants/platform/openbsd/ProtocolFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6d42113e95361cd24b9100db9da36c0de22fc5f
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/ProtocolFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/RLIM.class b/src/main/resources/jnr/constants/platform/openbsd/RLIM.class
new file mode 100644
index 0000000000000000000000000000000000000000..57193c3ccaafb1c30e73534f3c1b5a8ef60074e8
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/RLIM.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/RLIMIT.class b/src/main/resources/jnr/constants/platform/openbsd/RLIMIT.class
new file mode 100644
index 0000000000000000000000000000000000000000..16e67f1f37c791f749694241a9998ed00a85bf54
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/RLIMIT.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/Shutdown.class b/src/main/resources/jnr/constants/platform/openbsd/Shutdown.class
new file mode 100644
index 0000000000000000000000000000000000000000..e003e53fe99b2e0c9041f1b22c193e0cc97fff4c
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/Shutdown.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/Signal.class b/src/main/resources/jnr/constants/platform/openbsd/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..68c3d3109cccd44f733fd9cb3cf852ae0db23a72
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/Signal.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/Sock.class b/src/main/resources/jnr/constants/platform/openbsd/Sock.class
new file mode 100644
index 0000000000000000000000000000000000000000..476d5335519726f3599eec61bbb90473fa4926a9
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/Sock.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/SocketLevel.class b/src/main/resources/jnr/constants/platform/openbsd/SocketLevel.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed28c0d65ec9d7ed98109e7ee5e2b935fc4b00f0
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/SocketLevel.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/SocketOption.class b/src/main/resources/jnr/constants/platform/openbsd/SocketOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e5302c57a8d4452a36a2a9cdc0412fd4a431cfe
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/SocketOption.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/Sysconf.class b/src/main/resources/jnr/constants/platform/openbsd/Sysconf.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3bb34f619629b405d406d9ddc9178ce898a56b6
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/Sysconf.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/TCP.class b/src/main/resources/jnr/constants/platform/openbsd/TCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcea7326ef9d7678dcac1cb38bfbfe4aa1967871
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/TCP.class differ
diff --git a/src/main/resources/jnr/constants/platform/openbsd/WaitFlags.class b/src/main/resources/jnr/constants/platform/openbsd/WaitFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..05909a74f78d37e68329cfdcec2a527ba769f2a8
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/openbsd/WaitFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/AddressFamily.class b/src/main/resources/jnr/constants/platform/sunos/AddressFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd831664a92c91f714cd9caa271d78826d8ab885
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/AddressFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/Errno$StringTable.class b/src/main/resources/jnr/constants/platform/sunos/Errno$StringTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6bfa209c84eeff01be8c36cc84c36e1df0fb76c
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/Errno$StringTable.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/Errno.class b/src/main/resources/jnr/constants/platform/sunos/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac86cf7c9bc4d393088e88a52475f7e5a18d04e5
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/Errno.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/Fcntl.class b/src/main/resources/jnr/constants/platform/sunos/Fcntl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ea7f65b8a5c45967abe643720c20b6b6d089bd8
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/Fcntl.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/INAddr.class b/src/main/resources/jnr/constants/platform/sunos/INAddr.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ae5ee8171f8aa629136c115d8f5bb920eea222c
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/INAddr.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/IPProto.class b/src/main/resources/jnr/constants/platform/sunos/IPProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..c44d49dd28dd6e0ed12657300da76f85d79e8b06
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/IPProto.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/NameInfo.class b/src/main/resources/jnr/constants/platform/sunos/NameInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..b73fa7e1a49a4a3f581ecbccfb4bcd41f8080511
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/NameInfo.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/OpenFlags.class b/src/main/resources/jnr/constants/platform/sunos/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..d14eeb645c0529e27d067821ea06d1b38b65e922
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/OpenFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/PRIO.class b/src/main/resources/jnr/constants/platform/sunos/PRIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..b007586773e3d56476f2c2f0042d4d7e490e49b7
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/PRIO.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/ProtocolFamily.class b/src/main/resources/jnr/constants/platform/sunos/ProtocolFamily.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b739a6ccdd5f2c5233dcc82e54430b11469b575
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/ProtocolFamily.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/RLIM.class b/src/main/resources/jnr/constants/platform/sunos/RLIM.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc0a5d0bf6cf7e553e90a37e4a565b575cf2cfd2
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/RLIM.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/RLIMIT.class b/src/main/resources/jnr/constants/platform/sunos/RLIMIT.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2e82ac42bf1a5e8c4130794b7dc4a1f40d54bf1
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/RLIMIT.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/Shutdown.class b/src/main/resources/jnr/constants/platform/sunos/Shutdown.class
new file mode 100644
index 0000000000000000000000000000000000000000..b01240c074971128807e100a7b27606195bd329d
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/Shutdown.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/Signal.class b/src/main/resources/jnr/constants/platform/sunos/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..a29b6ddef47b37684d9092a03c2b2a586c125159
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/Signal.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/Sock.class b/src/main/resources/jnr/constants/platform/sunos/Sock.class
new file mode 100644
index 0000000000000000000000000000000000000000..1aa204e6c770648bf48e3755094549ae0f2c16e7
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/Sock.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/SocketLevel.class b/src/main/resources/jnr/constants/platform/sunos/SocketLevel.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5def8be682ba4d0763adbbf79c32896b2f06978
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/SocketLevel.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/SocketOption.class b/src/main/resources/jnr/constants/platform/sunos/SocketOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..3587595f06798437bd1df3f11807d160e2833fa1
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/SocketOption.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/Sysconf.class b/src/main/resources/jnr/constants/platform/sunos/Sysconf.class
new file mode 100644
index 0000000000000000000000000000000000000000..df3907e3ae42e2377ab5aa802320f57c31aa2100
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/Sysconf.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/TCP.class b/src/main/resources/jnr/constants/platform/sunos/TCP.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa848ca5617ce71cd5a2536e898d3ec7af8e589f
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/TCP.class differ
diff --git a/src/main/resources/jnr/constants/platform/sunos/WaitFlags.class b/src/main/resources/jnr/constants/platform/sunos/WaitFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..f43ccf9632c7b559dcccef7974ca4e91b8882af0
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/sunos/WaitFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/windows/Errno$StringTable.class b/src/main/resources/jnr/constants/platform/windows/Errno$StringTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2ff1d552198b10fc94b4c2132f67a47d4927c5c
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/windows/Errno$StringTable.class differ
diff --git a/src/main/resources/jnr/constants/platform/windows/Errno.class b/src/main/resources/jnr/constants/platform/windows/Errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..d162c052487bb939a1192c8225411a7cb6840f78
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/windows/Errno.class differ
diff --git a/src/main/resources/jnr/constants/platform/windows/LastError$StringTable.class b/src/main/resources/jnr/constants/platform/windows/LastError$StringTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..561c612035c15ef3ba2e253bfc812f85948e6b39
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/windows/LastError$StringTable.class differ
diff --git a/src/main/resources/jnr/constants/platform/windows/LastError.class b/src/main/resources/jnr/constants/platform/windows/LastError.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ce80fe0e9fb61a8eca99fcb96aa2cb737cbc6af
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/windows/LastError.class differ
diff --git a/src/main/resources/jnr/constants/platform/windows/OpenFlags.class b/src/main/resources/jnr/constants/platform/windows/OpenFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3fb5da7c5bddb43ed1524e83094b7031f5b18ca
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/windows/OpenFlags.class differ
diff --git a/src/main/resources/jnr/constants/platform/windows/Signal.class b/src/main/resources/jnr/constants/platform/windows/Signal.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5489cb53093044e6e8b09de1b7ffe5495abeaac
Binary files /dev/null and b/src/main/resources/jnr/constants/platform/windows/Signal.class differ
diff --git a/src/main/resources/jnr/ffi/Address.class b/src/main/resources/jnr/ffi/Address.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7ca963fec1824e101a1cae0482d6a1d745192f0
Binary files /dev/null and b/src/main/resources/jnr/ffi/Address.class differ
diff --git a/src/main/resources/jnr/ffi/CallingConvention.class b/src/main/resources/jnr/ffi/CallingConvention.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f5735982e5a1d1bda07a66fe9f5dc2aadd4727e
Binary files /dev/null and b/src/main/resources/jnr/ffi/CallingConvention.class differ
diff --git a/src/main/resources/jnr/ffi/FFIProvider$SystemProviderSingletonHolder.class b/src/main/resources/jnr/ffi/FFIProvider$SystemProviderSingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..93a91038dda88e5cab6675b9d2851806080123b6
Binary files /dev/null and b/src/main/resources/jnr/ffi/FFIProvider$SystemProviderSingletonHolder.class differ
diff --git a/src/main/resources/jnr/ffi/FFIProvider.class b/src/main/resources/jnr/ffi/FFIProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ad1f39a8a4c96514669e7cfc35a02b1edc5cb38
Binary files /dev/null and b/src/main/resources/jnr/ffi/FFIProvider.class differ
diff --git a/src/main/resources/jnr/ffi/InvalidProvider.class b/src/main/resources/jnr/ffi/InvalidProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..175f6783c307efb3a9f3604d3e85b3e14b80bec7
Binary files /dev/null and b/src/main/resources/jnr/ffi/InvalidProvider.class differ
diff --git a/src/main/resources/jnr/ffi/InvalidRuntime.class b/src/main/resources/jnr/ffi/InvalidRuntime.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e7261c1bc86783b20b598eeb4e060b07c73dd3c
Binary files /dev/null and b/src/main/resources/jnr/ffi/InvalidRuntime.class differ
diff --git a/src/main/resources/jnr/ffi/LastError.class b/src/main/resources/jnr/ffi/LastError.class
new file mode 100644
index 0000000000000000000000000000000000000000..46e59289a935837ef60e57cb483cc40eabb9f1f7
Binary files /dev/null and b/src/main/resources/jnr/ffi/LastError.class differ
diff --git a/src/main/resources/jnr/ffi/Library.class b/src/main/resources/jnr/ffi/Library.class
new file mode 100644
index 0000000000000000000000000000000000000000..08ec52632b701838d18f4c66c7685950f47d8f2c
Binary files /dev/null and b/src/main/resources/jnr/ffi/Library.class differ
diff --git a/src/main/resources/jnr/ffi/LibraryOption.class b/src/main/resources/jnr/ffi/LibraryOption.class
new file mode 100644
index 0000000000000000000000000000000000000000..829e9ed42cd558a45cf1654001e6bedeb85402f4
Binary files /dev/null and b/src/main/resources/jnr/ffi/LibraryOption.class differ
diff --git a/src/main/resources/jnr/ffi/Memory.class b/src/main/resources/jnr/ffi/Memory.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b3b03579d65ce31a4ea966ca7bfdb6d804a71e5
Binary files /dev/null and b/src/main/resources/jnr/ffi/Memory.class differ
diff --git a/src/main/resources/jnr/ffi/NativeLong$Cache.class b/src/main/resources/jnr/ffi/NativeLong$Cache.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f4fb503368f258070b8edb425ae80a20a877126
Binary files /dev/null and b/src/main/resources/jnr/ffi/NativeLong$Cache.class differ
diff --git a/src/main/resources/jnr/ffi/NativeLong.class b/src/main/resources/jnr/ffi/NativeLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..994c4090cd8eb283d22859f0a61baa47d515210e
Binary files /dev/null and b/src/main/resources/jnr/ffi/NativeLong.class differ
diff --git a/src/main/resources/jnr/ffi/NativeType.class b/src/main/resources/jnr/ffi/NativeType.class
new file mode 100644
index 0000000000000000000000000000000000000000..14816499844f47dcfdc074bc66f40eb19d306538
Binary files /dev/null and b/src/main/resources/jnr/ffi/NativeType.class differ
diff --git a/src/main/resources/jnr/ffi/ObjectReferenceManager.class b/src/main/resources/jnr/ffi/ObjectReferenceManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..196703737d95cf5a31f456fca341e80eaf386dfe
Binary files /dev/null and b/src/main/resources/jnr/ffi/ObjectReferenceManager.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$1.class b/src/main/resources/jnr/ffi/Platform$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd2cf8b856e142e870dab72a3954b6e371c5f9cb
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$1.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$CPU.class b/src/main/resources/jnr/ffi/Platform$CPU.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed11f75abb3a7d6b05b1382944837f0afb7b3625
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$CPU.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$Darwin.class b/src/main/resources/jnr/ffi/Platform$Darwin.class
new file mode 100644
index 0000000000000000000000000000000000000000..85421970bc5bdab949d18863489134a34ea208a6
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$Darwin.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$Default.class b/src/main/resources/jnr/ffi/Platform$Default.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f56d0acd0fa6a3d3bf3f65056fb2f37ba6ab9e0
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$Default.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$Linux$1.class b/src/main/resources/jnr/ffi/Platform$Linux$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b6654fa4616957e13361585a3e030723aabf97e
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$Linux$1.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$Linux.class b/src/main/resources/jnr/ffi/Platform$Linux.class
new file mode 100644
index 0000000000000000000000000000000000000000..397bcec429a1b3d1d9e5d0668e0c6b53eb2e06a4
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$Linux.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$OS.class b/src/main/resources/jnr/ffi/Platform$OS.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2862cdec20a1d3c805672531e592cfe725399ff
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$OS.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$SingletonHolder.class b/src/main/resources/jnr/ffi/Platform$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..918723d0eaa871f40170e3d4d01cd01d3ca0dee6
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$Supported.class b/src/main/resources/jnr/ffi/Platform$Supported.class
new file mode 100644
index 0000000000000000000000000000000000000000..aeb960e6632147b2c12e011c0aef1e14adc9af26
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$Supported.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$Unsupported.class b/src/main/resources/jnr/ffi/Platform$Unsupported.class
new file mode 100644
index 0000000000000000000000000000000000000000..de192c6706189ee2b0eb5b505f3c9c9eba9e9c4d
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$Unsupported.class differ
diff --git a/src/main/resources/jnr/ffi/Platform$Windows.class b/src/main/resources/jnr/ffi/Platform$Windows.class
new file mode 100644
index 0000000000000000000000000000000000000000..886c93e1cf3972d18245a775edddf5f84de7f8d3
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform$Windows.class differ
diff --git a/src/main/resources/jnr/ffi/Platform.class b/src/main/resources/jnr/ffi/Platform.class
new file mode 100644
index 0000000000000000000000000000000000000000..90c690f6a904dd6f02204fe5a9c1143d3472b2fa
Binary files /dev/null and b/src/main/resources/jnr/ffi/Platform.class differ
diff --git a/src/main/resources/jnr/ffi/Pointer.class b/src/main/resources/jnr/ffi/Pointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b94be40ee9bc5c027d60c9d5ef728820bc081756
Binary files /dev/null and b/src/main/resources/jnr/ffi/Pointer.class differ
diff --git a/src/main/resources/jnr/ffi/Runtime$SingletonHolder.class b/src/main/resources/jnr/ffi/Runtime$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3434e9aa019a5bea74ddcbe98575cc03055b343
Binary files /dev/null and b/src/main/resources/jnr/ffi/Runtime$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/ffi/Runtime.class b/src/main/resources/jnr/ffi/Runtime.class
new file mode 100644
index 0000000000000000000000000000000000000000..0429ac5461f16bf56d94bdb5979bb989b8b9a1f1
Binary files /dev/null and b/src/main/resources/jnr/ffi/Runtime.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$AbstractBoolean.class b/src/main/resources/jnr/ffi/Struct$AbstractBoolean.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c2138de734f2f92e32a636328a8c744f831cea8
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$AbstractBoolean.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$AbstractMember.class b/src/main/resources/jnr/ffi/Struct$AbstractMember.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f26b7ba489bf845f7fd619fcebf08f2167cb4e2
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$AbstractMember.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Address.class b/src/main/resources/jnr/ffi/Struct$Address.class
new file mode 100644
index 0000000000000000000000000000000000000000..b93b3c46e159e5533d7e220d78a2ae3006e9e87c
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Address.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$AsciiString.class b/src/main/resources/jnr/ffi/Struct$AsciiString.class
new file mode 100644
index 0000000000000000000000000000000000000000..7cab522cda1c0663cbf89269e366027c759a03a6
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$AsciiString.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$AsciiStringRef.class b/src/main/resources/jnr/ffi/Struct$AsciiStringRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..354b5715ce849f63943c8c69f5edc1c9d466c068
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$AsciiStringRef.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Boolean.class b/src/main/resources/jnr/ffi/Struct$Boolean.class
new file mode 100644
index 0000000000000000000000000000000000000000..89ddf5218e65967c7920f06dcea33011538f329c
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Boolean.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Double.class b/src/main/resources/jnr/ffi/Struct$Double.class
new file mode 100644
index 0000000000000000000000000000000000000000..28d56e354df411522b02a4ba5772d8374548d200
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Double.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Enum.class b/src/main/resources/jnr/ffi/Struct$Enum.class
new file mode 100644
index 0000000000000000000000000000000000000000..82e8c19a56c82b39b8af7d11ddd6160eb7632320
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Enum.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Enum16.class b/src/main/resources/jnr/ffi/Struct$Enum16.class
new file mode 100644
index 0000000000000000000000000000000000000000..974bde255b4d202554bddcc54da6788ff9453a93
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Enum16.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Enum32.class b/src/main/resources/jnr/ffi/Struct$Enum32.class
new file mode 100644
index 0000000000000000000000000000000000000000..d76f7c44e762e8a749fca37245bcf712806a21ce
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Enum32.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Enum64.class b/src/main/resources/jnr/ffi/Struct$Enum64.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2e38ec6ed34179d7937cda58c06bbedd10c3174
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Enum64.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Enum8.class b/src/main/resources/jnr/ffi/Struct$Enum8.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d54b5b58e7c27e340658cde4dc32c757e10b750
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Enum8.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$EnumField.class b/src/main/resources/jnr/ffi/Struct$EnumField.class
new file mode 100644
index 0000000000000000000000000000000000000000..73b6d6d98021d6a38ef1657608b98b6b9ba26c4a
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$EnumField.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$EnumLong.class b/src/main/resources/jnr/ffi/Struct$EnumLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..df15dbce1f2f3df44f0f77a1619c3f5feb5fe6f4
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$EnumLong.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Float.class b/src/main/resources/jnr/ffi/Struct$Float.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ffcd511fb7a246720d3806280549bd2bdb25db3
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Float.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Info.class b/src/main/resources/jnr/ffi/Struct$Info.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8cc5f97249df045ea89784c3cc0c4d3421ce7d4
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Info.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$IntegerAlias.class b/src/main/resources/jnr/ffi/Struct$IntegerAlias.class
new file mode 100644
index 0000000000000000000000000000000000000000..06542f218c97ae7959e8d31d326943369a9c4504
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$IntegerAlias.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Member.class b/src/main/resources/jnr/ffi/Struct$Member.class
new file mode 100644
index 0000000000000000000000000000000000000000..26adce470ca624d617bb4e9d33692a7ee4876bf9
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Member.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$NumberField.class b/src/main/resources/jnr/ffi/Struct$NumberField.class
new file mode 100644
index 0000000000000000000000000000000000000000..df6b44dd46d60d0b7467f0f291f96525464af2c4
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$NumberField.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Offset.class b/src/main/resources/jnr/ffi/Struct$Offset.class
new file mode 100644
index 0000000000000000000000000000000000000000..81d0844c0cd8e3c10ad64f432fdf63c1eb0bff21
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Offset.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Padding.class b/src/main/resources/jnr/ffi/Struct$Padding.class
new file mode 100644
index 0000000000000000000000000000000000000000..28aaa0999cc25b460f633b069f0a4798d144e394
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Padding.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Pointer.class b/src/main/resources/jnr/ffi/Struct$Pointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..15d0f78ea50cd8e5be9bf19c6259109c64350114
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Pointer.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Signed16.class b/src/main/resources/jnr/ffi/Struct$Signed16.class
new file mode 100644
index 0000000000000000000000000000000000000000..80e73a7959a1a7f827ff7b216b85149377419431
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Signed16.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Signed32.class b/src/main/resources/jnr/ffi/Struct$Signed32.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8c38674f8a504d31f7d4f2fb87aad79bd6b2d2b
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Signed32.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Signed64.class b/src/main/resources/jnr/ffi/Struct$Signed64.class
new file mode 100644
index 0000000000000000000000000000000000000000..5caf3629d19c55d4b05e7ca7bd90296e07cd3c8a
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Signed64.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Signed8.class b/src/main/resources/jnr/ffi/Struct$Signed8.class
new file mode 100644
index 0000000000000000000000000000000000000000..eeb167afcaa2d68ada4e1cff6cc2ed5484060ffc
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Signed8.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$SignedLong.class b/src/main/resources/jnr/ffi/Struct$SignedLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcf2ad6408efe5bd95b89042bf96c034ae58f7ed
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$SignedLong.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$String.class b/src/main/resources/jnr/ffi/Struct$String.class
new file mode 100644
index 0000000000000000000000000000000000000000..4367918348b52a9ba798e1f7519324b4ae621b02
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$String.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$UTF8String.class b/src/main/resources/jnr/ffi/Struct$UTF8String.class
new file mode 100644
index 0000000000000000000000000000000000000000..7213ad3d9a3d5cedfa43aeaa26647a43499db678
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$UTF8String.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$UTF8StringRef.class b/src/main/resources/jnr/ffi/Struct$UTF8StringRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa010e5385d9eb8b3200db31a4b3740b20a03596
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$UTF8StringRef.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$UTFString.class b/src/main/resources/jnr/ffi/Struct$UTFString.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2a794e4fa1e79903106de39e60dc8a1d07badd3
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$UTFString.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$UTFStringRef.class b/src/main/resources/jnr/ffi/Struct$UTFStringRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba4d3d1ee8d2e121e3e54ab209e9141fe09aaec0
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$UTFStringRef.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Unsigned16.class b/src/main/resources/jnr/ffi/Struct$Unsigned16.class
new file mode 100644
index 0000000000000000000000000000000000000000..1091467d375870566cc09210a846e324faa7810a
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Unsigned16.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Unsigned32.class b/src/main/resources/jnr/ffi/Struct$Unsigned32.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a546adf1a1832b32c03f8db7ab9bf2512656cb4
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Unsigned32.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Unsigned64.class b/src/main/resources/jnr/ffi/Struct$Unsigned64.class
new file mode 100644
index 0000000000000000000000000000000000000000..c783e4053fafae7913a54f6bfd9266cac15d30ef
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Unsigned64.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$Unsigned8.class b/src/main/resources/jnr/ffi/Struct$Unsigned8.class
new file mode 100644
index 0000000000000000000000000000000000000000..a25103ea2ad51a2c7432d427a7bf9232d78047b3
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$Unsigned8.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$UnsignedLong.class b/src/main/resources/jnr/ffi/Struct$UnsignedLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..d35e94cfe8a257d3969c0d5f57a7cec541009e59
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$UnsignedLong.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$WBOOL.class b/src/main/resources/jnr/ffi/Struct$WBOOL.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc06c8dfc1731c87350a4a3f4abe487f79f8b571
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$WBOOL.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$blkcnt_t.class b/src/main/resources/jnr/ffi/Struct$blkcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcc72a43caf44f51cdebf6d91af1de86380ef850
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$blkcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$blksize_t.class b/src/main/resources/jnr/ffi/Struct$blksize_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c355b38c7aefd4a73bee0d1b867520206139e74
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$blksize_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$caddr_t.class b/src/main/resources/jnr/ffi/Struct$caddr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5adf504ac2f18da36dae318b697ba68830cc856
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$caddr_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$clock_t.class b/src/main/resources/jnr/ffi/Struct$clock_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b923d764655638e5972b1bb59e5a4ad0be5adb2
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$clock_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$dev_t.class b/src/main/resources/jnr/ffi/Struct$dev_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..15683a6746991e2117bf5aea9c4bab0c538ebc31
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$dev_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$fsblkcnt_t.class b/src/main/resources/jnr/ffi/Struct$fsblkcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..634abc9a54d3ec1e22188461823aa722a63e9842
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$fsblkcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$fsfilcnt_t.class b/src/main/resources/jnr/ffi/Struct$fsfilcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8e834258c7473e16922aac18469371937924dec
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$fsfilcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$gid_t.class b/src/main/resources/jnr/ffi/Struct$gid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..829ad4c78b4f38d9e9a10c735df34a0daff5e639
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$gid_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$id_t.class b/src/main/resources/jnr/ffi/Struct$id_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c192dce92fe2684f57ad847f60479bbb44b2ca8
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$id_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$in_addr_t.class b/src/main/resources/jnr/ffi/Struct$in_addr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..076d10f84fa26238ac4b6be0914d4fd201c50cc2
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$in_addr_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$in_port_t.class b/src/main/resources/jnr/ffi/Struct$in_port_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a99ef7e210e5be5506ee70d472889cbe20635fe
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$in_port_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$ino64_t.class b/src/main/resources/jnr/ffi/Struct$ino64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..7979b91da10273ac3163b1aaeb3ea58dc9ee8148
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$ino64_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$ino_t.class b/src/main/resources/jnr/ffi/Struct$ino_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..cca5c0f98bddf82fc29830e7af945801aefd1442
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$ino_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$int16_t.class b/src/main/resources/jnr/ffi/Struct$int16_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..344b5f0fba9da1e2b535619ddd6592413d7881d6
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$int16_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$int32_t.class b/src/main/resources/jnr/ffi/Struct$int32_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..e78f26a2e7b43998f137a511a8296f53fd1d1dfd
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$int32_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$int64_t.class b/src/main/resources/jnr/ffi/Struct$int64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7cd8c9adf8aeeedcdff4d3f499c9a19f3595063
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$int64_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$int8_t.class b/src/main/resources/jnr/ffi/Struct$int8_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb1fadc02ccff13eadce996539cd3a7d60051d5c
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$int8_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$intptr_t.class b/src/main/resources/jnr/ffi/Struct$intptr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..53adda2ac6f1bd9af48540f289eebc45caa6f1c3
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$intptr_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$key_t.class b/src/main/resources/jnr/ffi/Struct$key_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0ec7647673a513ae4aa2fe78d33383c1cd20fdd
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$key_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$mode_t.class b/src/main/resources/jnr/ffi/Struct$mode_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c2328c6586a74d5e00ee10ea48cf3aef16ca325
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$mode_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$nlink_t.class b/src/main/resources/jnr/ffi/Struct$nlink_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6810ae208b0b97964ef851d2a4e2f2b04ab7959
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$nlink_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$off_t.class b/src/main/resources/jnr/ffi/Struct$off_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e43e84dfb356ab659de5af8fcd44fcca6931627
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$off_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$pid_t.class b/src/main/resources/jnr/ffi/Struct$pid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..258a296506ecfe330e011edffcbe9265ee034835
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$pid_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$rlim_t.class b/src/main/resources/jnr/ffi/Struct$rlim_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad2d0468242851c606e4ca272ac5bc7746dd68f9
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$rlim_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$sa_family_t.class b/src/main/resources/jnr/ffi/Struct$sa_family_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..9401bd7aba4c719d3a3a1cd09a600f9bd4c6072b
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$sa_family_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$size_t.class b/src/main/resources/jnr/ffi/Struct$size_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..895c543e6c800554470b90dba13ad4537385c72b
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$size_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$socklen_t.class b/src/main/resources/jnr/ffi/Struct$socklen_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..45c7c1adfe04f02b3fe7f491169b411f4bade3af
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$socklen_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$ssize_t.class b/src/main/resources/jnr/ffi/Struct$ssize_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1aaac69fb59dc980039b589b8faccfa054d13fe
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$ssize_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$swblk_t.class b/src/main/resources/jnr/ffi/Struct$swblk_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..6aafa90f286bd75a8892cc570e8bbe19cd81465b
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$swblk_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$time_t.class b/src/main/resources/jnr/ffi/Struct$time_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..daf503c29a9ec4cbdca90316aa29d7019964da33
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$time_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$u_int16_t.class b/src/main/resources/jnr/ffi/Struct$u_int16_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3cd7394f2e52a9cd664c521e6957cc40672d550
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$u_int16_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$u_int32_t.class b/src/main/resources/jnr/ffi/Struct$u_int32_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6ebd703df49d90df0e0dd98024f8fabe321dfe5
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$u_int32_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$u_int64_t.class b/src/main/resources/jnr/ffi/Struct$u_int64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c061b029143779a0c6a0801bc70bd4f6a40c48c
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$u_int64_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$u_int8_t.class b/src/main/resources/jnr/ffi/Struct$u_int8_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfaf77e71854128cf13f417f22ec31c46c5a502f
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$u_int8_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$uid_t.class b/src/main/resources/jnr/ffi/Struct$uid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..9190c3be49806107023fd79eb028504e170a92a7
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$uid_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct$uintptr_t.class b/src/main/resources/jnr/ffi/Struct$uintptr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..b29a3fb564c022959a6ae870f1044def9d77d603
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct$uintptr_t.class differ
diff --git a/src/main/resources/jnr/ffi/Struct.class b/src/main/resources/jnr/ffi/Struct.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ec19fcf4bfe7201b055772ac256648abaa25679
Binary files /dev/null and b/src/main/resources/jnr/ffi/Struct.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$AbstractBoolean.class b/src/main/resources/jnr/ffi/StructLayout$AbstractBoolean.class
new file mode 100644
index 0000000000000000000000000000000000000000..034d0daad237f21637a1d1420df9e9c2559fd831
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$AbstractBoolean.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$AbstractField.class b/src/main/resources/jnr/ffi/StructLayout$AbstractField.class
new file mode 100644
index 0000000000000000000000000000000000000000..d75290e6a147ef56a0d4ad30257a30b01ea68a7d
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$AbstractField.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$AsciiString.class b/src/main/resources/jnr/ffi/StructLayout$AsciiString.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb0a8e8dfb46c9fb7fc75c9b7fbbf1d4c626080e
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$AsciiString.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$AsciiStringRef.class b/src/main/resources/jnr/ffi/StructLayout$AsciiStringRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..9df9f0afb9a16281c1dd86c1f2edf31166a7cdb2
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$AsciiStringRef.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Boolean.class b/src/main/resources/jnr/ffi/StructLayout$Boolean.class
new file mode 100644
index 0000000000000000000000000000000000000000..686e94f1671b9014928d6ebde242cab14ef90f0a
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Boolean.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Double.class b/src/main/resources/jnr/ffi/StructLayout$Double.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d7c2571b80f938a6ed87081a88d17e298749b0f
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Double.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Enum.class b/src/main/resources/jnr/ffi/StructLayout$Enum.class
new file mode 100644
index 0000000000000000000000000000000000000000..88cc81ecac222e75e2b7c91dab5469453ba41342
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Enum.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Enum16.class b/src/main/resources/jnr/ffi/StructLayout$Enum16.class
new file mode 100644
index 0000000000000000000000000000000000000000..7939cba32c0dc77d8d936a76015579aae8d96397
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Enum16.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Enum32.class b/src/main/resources/jnr/ffi/StructLayout$Enum32.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f17002dbf069a38039e9fd5b25153e466d6fb5a
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Enum32.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Enum64.class b/src/main/resources/jnr/ffi/StructLayout$Enum64.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1a8057a2fbc64d8e5904d1fe33245eb54945248
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Enum64.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Enum8.class b/src/main/resources/jnr/ffi/StructLayout$Enum8.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac12a75d450f950f81560c1f0daf28995e326c3d
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Enum8.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$EnumField.class b/src/main/resources/jnr/ffi/StructLayout$EnumField.class
new file mode 100644
index 0000000000000000000000000000000000000000..8da36cf59ac81822ef030245cca62ae8cae33a20
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$EnumField.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$EnumLong.class b/src/main/resources/jnr/ffi/StructLayout$EnumLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..26809d3b313fde80b944dfcca1236f9e79be096d
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$EnumLong.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Field.class b/src/main/resources/jnr/ffi/StructLayout$Field.class
new file mode 100644
index 0000000000000000000000000000000000000000..da9842863b458f3e7333398b11e6f8e5575d593d
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Field.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Float.class b/src/main/resources/jnr/ffi/StructLayout$Float.class
new file mode 100644
index 0000000000000000000000000000000000000000..18405a807a4b819fefa45fe02551c994caa1f888
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Float.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$IntegerAlias.class b/src/main/resources/jnr/ffi/StructLayout$IntegerAlias.class
new file mode 100644
index 0000000000000000000000000000000000000000..2eb3ac800565f8dd323f0cf67f1fea21b995789d
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$IntegerAlias.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$NumberField.class b/src/main/resources/jnr/ffi/StructLayout$NumberField.class
new file mode 100644
index 0000000000000000000000000000000000000000..58a7b1aa8473a9f83f64b7fa09a686a14740a213
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$NumberField.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Padding.class b/src/main/resources/jnr/ffi/StructLayout$Padding.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3955144a3f1d4e4b7fd9c88c93974215b4bf61c
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Padding.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Pointer.class b/src/main/resources/jnr/ffi/StructLayout$Pointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7297bf20b91d3b2bb7770a54efed184099a5e7ce
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Pointer.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Signed16.class b/src/main/resources/jnr/ffi/StructLayout$Signed16.class
new file mode 100644
index 0000000000000000000000000000000000000000..ddda3916d17a3f3fe56a8413ea44ee12425f7425
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Signed16.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Signed32.class b/src/main/resources/jnr/ffi/StructLayout$Signed32.class
new file mode 100644
index 0000000000000000000000000000000000000000..8dd3c8b7b2ed6fbbc714bd5b1e3f49109cc68126
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Signed32.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Signed64.class b/src/main/resources/jnr/ffi/StructLayout$Signed64.class
new file mode 100644
index 0000000000000000000000000000000000000000..47ea2a959b102d4f1b0bc93b6ca5828d4429a8ee
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Signed64.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Signed8.class b/src/main/resources/jnr/ffi/StructLayout$Signed8.class
new file mode 100644
index 0000000000000000000000000000000000000000..f385efb60063c83957179ede2ecb8b913ade99bc
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Signed8.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$SignedLong.class b/src/main/resources/jnr/ffi/StructLayout$SignedLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2822014f8f58fa5f2d266ee690fa7554aead8dc
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$SignedLong.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$String.class b/src/main/resources/jnr/ffi/StructLayout$String.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbc843a707a8474d0637ecc1b556132c13bc8a7e
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$String.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$UTF8String.class b/src/main/resources/jnr/ffi/StructLayout$UTF8String.class
new file mode 100644
index 0000000000000000000000000000000000000000..15b179825fa8b8250363506219304a71e708750b
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$UTF8String.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$UTF8StringRef.class b/src/main/resources/jnr/ffi/StructLayout$UTF8StringRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..53619cf1aee658b4b3f629cf8ff97425533235ac
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$UTF8StringRef.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$UTFString.class b/src/main/resources/jnr/ffi/StructLayout$UTFString.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccd29638eb6fe4f74349775deb25e1fdf986c46b
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$UTFString.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$UTFStringRef.class b/src/main/resources/jnr/ffi/StructLayout$UTFStringRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..12e3d72d512aaa9e91aaedcb373688f20258ba86
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$UTFStringRef.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Unsigned16.class b/src/main/resources/jnr/ffi/StructLayout$Unsigned16.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef7abac17a6d83a5cc6a313fa7cff0b9979dfc0a
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Unsigned16.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Unsigned32.class b/src/main/resources/jnr/ffi/StructLayout$Unsigned32.class
new file mode 100644
index 0000000000000000000000000000000000000000..33ce64f821f438bf5b8aa1e7bad26af0cb7402ab
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Unsigned32.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Unsigned64.class b/src/main/resources/jnr/ffi/StructLayout$Unsigned64.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4795f7ab0ed8d65a48b411f102e753fb559afe3
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Unsigned64.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$Unsigned8.class b/src/main/resources/jnr/ffi/StructLayout$Unsigned8.class
new file mode 100644
index 0000000000000000000000000000000000000000..2713b62a735e681d5bce2365335d29470701ace9
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$Unsigned8.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$UnsignedLong.class b/src/main/resources/jnr/ffi/StructLayout$UnsignedLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..96a0d7ded4426d9f37b54c6e3cf703818ada11ac
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$UnsignedLong.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$WBOOL.class b/src/main/resources/jnr/ffi/StructLayout$WBOOL.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf2c21921fda25bec792c456af32654a3049fe72
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$WBOOL.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$blkcnt_t.class b/src/main/resources/jnr/ffi/StructLayout$blkcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..08b3c003a1956e854e78a7f72e41269a976a62df
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$blkcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$blksize_t.class b/src/main/resources/jnr/ffi/StructLayout$blksize_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..c97a81a99a325c43c0847fbfb1ca85cdc9457317
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$blksize_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$caddr_t.class b/src/main/resources/jnr/ffi/StructLayout$caddr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..04ee3472296e29fde5700649fcfeb11ec2e6438b
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$caddr_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$clock_t.class b/src/main/resources/jnr/ffi/StructLayout$clock_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..76cbca3af1ab233af37eaacf85c2e0b8466da6e3
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$clock_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$dev_t.class b/src/main/resources/jnr/ffi/StructLayout$dev_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbbf4e48474e710d9c2e11ff5d5a83d0418b00b4
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$dev_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$fsblkcnt_t.class b/src/main/resources/jnr/ffi/StructLayout$fsblkcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d3cc031858ccf5b5cfe609f3be890d1350fbaaa
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$fsblkcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$fsfilcnt_t.class b/src/main/resources/jnr/ffi/StructLayout$fsfilcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a9e4e83cbe9aa78ae52c7372f01b5690affa8f8
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$fsfilcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$gid_t.class b/src/main/resources/jnr/ffi/StructLayout$gid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..4df46f55f9e740ebd9e3ae7dc90dacaf6e872469
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$gid_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$id_t.class b/src/main/resources/jnr/ffi/StructLayout$id_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2246afa7c6a4fa57e4931a271978fe0f275c6b3
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$id_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$in_addr_t.class b/src/main/resources/jnr/ffi/StructLayout$in_addr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c80a22712eed7d76ef0fae9ffa103c921615248
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$in_addr_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$in_port_t.class b/src/main/resources/jnr/ffi/StructLayout$in_port_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..b28a4808ae5f5ae03bffdaaecceae6096d1276b2
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$in_port_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$ino64_t.class b/src/main/resources/jnr/ffi/StructLayout$ino64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..63ad10aa94c9be9645fa59c9b1218047742fff18
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$ino64_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$ino_t.class b/src/main/resources/jnr/ffi/StructLayout$ino_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..93592ca4f772f8cb6c22dec5b548aedb6ea02d5f
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$ino_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$int16_t.class b/src/main/resources/jnr/ffi/StructLayout$int16_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..89d24794766d6c24cd7c3e4647ea62a28000ed0b
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$int16_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$int32_t.class b/src/main/resources/jnr/ffi/StructLayout$int32_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f584267038665fd510137ad1d27839f7c6aa98e
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$int32_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$int64_t.class b/src/main/resources/jnr/ffi/StructLayout$int64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd35a931bd6506c34d37a650e8bb2c0f57c89612
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$int64_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$int8_t.class b/src/main/resources/jnr/ffi/StructLayout$int8_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..10352913e8361b0916b880d9ac3f531fdb4d1ee3
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$int8_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$intptr_t.class b/src/main/resources/jnr/ffi/StructLayout$intptr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..110fd17172354c972064bb2a7ca309e5d3110612
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$intptr_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$key_t.class b/src/main/resources/jnr/ffi/StructLayout$key_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..c85f96416a3b439dcae2216495caa1ecf8adee7b
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$key_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$mode_t.class b/src/main/resources/jnr/ffi/StructLayout$mode_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f85b67e3e6d799c758a4838a719991eceeeb0b6
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$mode_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$nlink_t.class b/src/main/resources/jnr/ffi/StructLayout$nlink_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5a392c974c9721919ce06f5c49b5b5861931e65
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$nlink_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$off_t.class b/src/main/resources/jnr/ffi/StructLayout$off_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..39800e88295bf9b411b651fdea2f5bc8988cb6cb
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$off_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$pid_t.class b/src/main/resources/jnr/ffi/StructLayout$pid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..4efcabfce01e9660b4e9ddd408697b2bdb774b3e
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$pid_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$rlim_t.class b/src/main/resources/jnr/ffi/StructLayout$rlim_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c9fb67fd3f815bcbe32fd87726b70abc9caf16f
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$rlim_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$sa_family_t.class b/src/main/resources/jnr/ffi/StructLayout$sa_family_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a048aa71c7f008052254a06b8ac3b62e49f0833
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$sa_family_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$size_t.class b/src/main/resources/jnr/ffi/StructLayout$size_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..429dcf8d821f854d948986025434b1df145d3f11
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$size_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$socklen_t.class b/src/main/resources/jnr/ffi/StructLayout$socklen_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..12a9256de8f87a5f5a08f68660d868a43cb42ed5
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$socklen_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$ssize_t.class b/src/main/resources/jnr/ffi/StructLayout$ssize_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa7b16439650bde5a19f361c6da5f3850c085ba3
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$ssize_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$swblk_t.class b/src/main/resources/jnr/ffi/StructLayout$swblk_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca3b78bc79106811c8b7e3895d0b193e61b4d366
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$swblk_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$time_t.class b/src/main/resources/jnr/ffi/StructLayout$time_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..e00d493dd2eb46bab646011a258f1f619517ac56
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$time_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$u_int16_t.class b/src/main/resources/jnr/ffi/StructLayout$u_int16_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6aef8710074a8313b6ee5ba50afee2281fe7dd4
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$u_int16_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$u_int32_t.class b/src/main/resources/jnr/ffi/StructLayout$u_int32_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..e4e939cfe3a8601b5c11b27760ac7a7f5677285c
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$u_int32_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$u_int64_t.class b/src/main/resources/jnr/ffi/StructLayout$u_int64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..2100de84cbab9908dbed161917895d9a645176f0
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$u_int64_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$u_int8_t.class b/src/main/resources/jnr/ffi/StructLayout$u_int8_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..df621f7719980dc9c99fe9a6f4c74008bab51640
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$u_int8_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$uid_t.class b/src/main/resources/jnr/ffi/StructLayout$uid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..4462be738dda3b6f9c827616b457844b7109b9e3
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$uid_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout$uintptr_t.class b/src/main/resources/jnr/ffi/StructLayout$uintptr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c4734dd97fe6182ba33040a6eb015233a4ee306
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout$uintptr_t.class differ
diff --git a/src/main/resources/jnr/ffi/StructLayout.class b/src/main/resources/jnr/ffi/StructLayout.class
new file mode 100644
index 0000000000000000000000000000000000000000..eafe012ec0cccce658bab3340c23a6edcf862794
Binary files /dev/null and b/src/main/resources/jnr/ffi/StructLayout.class differ
diff --git a/src/main/resources/jnr/ffi/Type.class b/src/main/resources/jnr/ffi/Type.class
new file mode 100644
index 0000000000000000000000000000000000000000..610cf7403678b928792e62b065d1bfe4d423142b
Binary files /dev/null and b/src/main/resources/jnr/ffi/Type.class differ
diff --git a/src/main/resources/jnr/ffi/TypeAlias.class b/src/main/resources/jnr/ffi/TypeAlias.class
new file mode 100644
index 0000000000000000000000000000000000000000..9dc07ab1495a91adafb56603006f24e32e849a64
Binary files /dev/null and b/src/main/resources/jnr/ffi/TypeAlias.class differ
diff --git a/src/main/resources/jnr/ffi/Union.class b/src/main/resources/jnr/ffi/Union.class
new file mode 100644
index 0000000000000000000000000000000000000000..371208f4aed22861ebc5dd30ce832afb4eafc461
Binary files /dev/null and b/src/main/resources/jnr/ffi/Union.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/Clear.class b/src/main/resources/jnr/ffi/annotations/Clear.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7f9c5c4a25dd48da87a35aa231787245d62d08e
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/Clear.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/Delegate.class b/src/main/resources/jnr/ffi/annotations/Delegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..b35b6b2c135a4358607f73ff172eb1069cfd6674
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/Delegate.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/Direct.class b/src/main/resources/jnr/ffi/annotations/Direct.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc2cba55833bf83ee56f3c25dfdd2cd2c0051b3a
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/Direct.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/IgnoreError.class b/src/main/resources/jnr/ffi/annotations/IgnoreError.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e216bb516c0fce1bc83bc495be0c9e3b7324a4b
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/IgnoreError.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/In.class b/src/main/resources/jnr/ffi/annotations/In.class
new file mode 100644
index 0000000000000000000000000000000000000000..e578a61091b45b35915f6237d7c9339ac0ba1337
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/In.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/LongLong.class b/src/main/resources/jnr/ffi/annotations/LongLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a28bf8ba238b89e4fe2cf52e18ef13f2428dd63
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/LongLong.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/NulTerminate.class b/src/main/resources/jnr/ffi/annotations/NulTerminate.class
new file mode 100644
index 0000000000000000000000000000000000000000..79dd7e516054864617460aeeb7624c56703da217
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/NulTerminate.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/Out.class b/src/main/resources/jnr/ffi/annotations/Out.class
new file mode 100644
index 0000000000000000000000000000000000000000..be53df48bec0ed316ea49e5a0929c7a52cec3242
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/Out.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/Pinned.class b/src/main/resources/jnr/ffi/annotations/Pinned.class
new file mode 100644
index 0000000000000000000000000000000000000000..3baef1ccfcdc6aa6d5b11d5834e591c3dae888e4
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/Pinned.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/SaveError.class b/src/main/resources/jnr/ffi/annotations/SaveError.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bc421c7e04e821afc6a3d92ce6c20a3bf924be0
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/SaveError.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/StdCall.class b/src/main/resources/jnr/ffi/annotations/StdCall.class
new file mode 100644
index 0000000000000000000000000000000000000000..96548ee80f68b1b2b64fedf51fcbecea34709668
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/StdCall.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/Synchronized.class b/src/main/resources/jnr/ffi/annotations/Synchronized.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b044744d556ba378e7a94bbf36cf060d5c19396
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/Synchronized.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/Transient.class b/src/main/resources/jnr/ffi/annotations/Transient.class
new file mode 100644
index 0000000000000000000000000000000000000000..099fe639cb9059cd09ec3b6e8f4cfe18b3a1a7b7
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/Transient.class differ
diff --git a/src/main/resources/jnr/ffi/annotations/TypeDefinition.class b/src/main/resources/jnr/ffi/annotations/TypeDefinition.class
new file mode 100644
index 0000000000000000000000000000000000000000..d917bf8a2aa775afb03bace932460e1964dabcc9
Binary files /dev/null and b/src/main/resources/jnr/ffi/annotations/TypeDefinition.class differ
diff --git a/src/main/resources/jnr/ffi/byref/AbstractNumberReference.class b/src/main/resources/jnr/ffi/byref/AbstractNumberReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..24869049d9a87e85d11439734e316f913260833d
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/AbstractNumberReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/AbstractReference.class b/src/main/resources/jnr/ffi/byref/AbstractReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad6a5a59af359791e8b24a3483fb94762bf15f50
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/AbstractReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/AddressByReference.class b/src/main/resources/jnr/ffi/byref/AddressByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..a436a0f4cda4c1d4fc35706d652bc82372f32b3d
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/AddressByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/ByReference.class b/src/main/resources/jnr/ffi/byref/ByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..897021d1964d1d3014ec3bc0e458c345e66eef16
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/ByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/ByteByReference.class b/src/main/resources/jnr/ffi/byref/ByteByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..576e45b11c7facf0593f705f66afece6561df74e
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/ByteByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/DoubleByReference.class b/src/main/resources/jnr/ffi/byref/DoubleByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..97ada4c1b8829f7914297416fea0d82aba13a040
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/DoubleByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/FloatByReference.class b/src/main/resources/jnr/ffi/byref/FloatByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..9046ccda1ac93e092f0203dcf39e3b829736cccd
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/FloatByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/IntByReference.class b/src/main/resources/jnr/ffi/byref/IntByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..7261745e89ebbf766e9d2121269b23784686fbf8
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/IntByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/LongLongByReference.class b/src/main/resources/jnr/ffi/byref/LongLongByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..314da9d6964d52d272e85098a3ab3e216339b06b
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/LongLongByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/NativeLongByReference.class b/src/main/resources/jnr/ffi/byref/NativeLongByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7f5dbda8f5397bb3fdd0b9bc28f5bbdd458aa46
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/NativeLongByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/PointerByReference.class b/src/main/resources/jnr/ffi/byref/PointerByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8febc24134992ac970237227229e8cbffb82a57
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/PointerByReference.class differ
diff --git a/src/main/resources/jnr/ffi/byref/ShortByReference.class b/src/main/resources/jnr/ffi/byref/ShortByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..10768f57ec4ef75a3dc28411eb85861bccf97d6e
Binary files /dev/null and b/src/main/resources/jnr/ffi/byref/ShortByReference.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/AbstractDataConverter.class b/src/main/resources/jnr/ffi/mapper/AbstractDataConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ac855f2e0ebabfe6ffb5ebf89c700550fbebad6
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/AbstractDataConverter.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/DataConverter.class b/src/main/resources/jnr/ffi/mapper/DataConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c42839cf8e36390bcea92524af0bbeee7490e725
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/DataConverter.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/DefaultTypeMapper.class b/src/main/resources/jnr/ffi/mapper/DefaultTypeMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..6df7e4d4ab33de80b76b5aa13dcb7f15fab64ac8
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/DefaultTypeMapper.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/FromNativeContext.class b/src/main/resources/jnr/ffi/mapper/FromNativeContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..080eb0c1e2de4d870c48a5531958b3823214cd41
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/FromNativeContext.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/FromNativeConverter.class b/src/main/resources/jnr/ffi/mapper/FromNativeConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..9583e374d4cfbcb6ec6fca174efd91e3b80abb31
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/FromNativeConverter.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/FunctionMapper$Context.class b/src/main/resources/jnr/ffi/mapper/FunctionMapper$Context.class
new file mode 100644
index 0000000000000000000000000000000000000000..8911f616e06d248878dd9c1ac87b1294fee2ac1d
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/FunctionMapper$Context.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/FunctionMapper.class b/src/main/resources/jnr/ffi/mapper/FunctionMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bf5c5a7abbe51f5fc4820b9876e7125e8c7ba8d
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/FunctionMapper.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/MethodParameterContext.class b/src/main/resources/jnr/ffi/mapper/MethodParameterContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..44d219728da8cdf35513aa71f22d6069bd13098c
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/MethodParameterContext.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/MethodResultContext.class b/src/main/resources/jnr/ffi/mapper/MethodResultContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..35cce2249bc29bbc603ec3c914e50e9700f11ade
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/MethodResultContext.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/ToNativeContext.class b/src/main/resources/jnr/ffi/mapper/ToNativeContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea248d8c8141ccc5c6b52be6a04a1b0e16c85352
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/ToNativeContext.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/ToNativeConverter$PostInvocation.class b/src/main/resources/jnr/ffi/mapper/ToNativeConverter$PostInvocation.class
new file mode 100644
index 0000000000000000000000000000000000000000..337c5f54950030e6732706d1cb075d8a7187f277
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/ToNativeConverter$PostInvocation.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/ToNativeConverter.class b/src/main/resources/jnr/ffi/mapper/ToNativeConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..1727d14d6cfe0f4e1a9b2be96f7f30b075c1d664
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/ToNativeConverter.class differ
diff --git a/src/main/resources/jnr/ffi/mapper/TypeMapper.class b/src/main/resources/jnr/ffi/mapper/TypeMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..9046689d22e95cc332ff34c5b7412902d780747e
Binary files /dev/null and b/src/main/resources/jnr/ffi/mapper/TypeMapper.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$1.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..927da13f22e439ffbdd18fb7ac8ee5630fc818e6
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$ArrayIO.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8e43012414e6d6d2649cc7e42d533319edef4dd
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$ArrayIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BE32ArrayIO.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BE32ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..f74fcb30eca484fbb575208f2faed96a23d6f818
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BE32ArrayIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BE64ArrayIO.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BE64ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe334457e601ae78cf92fcdfdd2b60bb9b5d2f33
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BE64ArrayIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BigEndianArrayIO.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BigEndianArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b96220c2cccf53bf6410c52121629ab258d4717
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$BigEndianArrayIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LE32ArrayIO.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LE32ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..5910e3a02cf8fbf229e4cf2e21c7a7e4eaeaff4e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LE32ArrayIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LE64ArrayIO.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LE64ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..2cae138196c155e15633ae1742bc6ae3d3506692
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LE64ArrayIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LittleEndianArrayIO.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LittleEndianArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..db003f529344fcff309811c11ecc767b051b927a
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO$LittleEndianArrayIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO.class b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..f522003d114114e94bd4adf61e510eec402b78c9
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractArrayMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractBufferMemoryIO.class b/src/main/resources/jnr/ffi/provider/AbstractBufferMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..841f38b35038ad94238e822eb3ba36bbe6c2ef78
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractBufferMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractMemoryIO$1.class b/src/main/resources/jnr/ffi/provider/AbstractMemoryIO$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad4384da26e64ff0358ec1248c6083386d076988
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractMemoryIO$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractMemoryIO.class b/src/main/resources/jnr/ffi/provider/AbstractMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..421f34f33d4b6b2084bcb712ca5373285455de98
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/AbstractRuntime.class b/src/main/resources/jnr/ffi/provider/AbstractRuntime.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ddee27981c3bf3edefccc5d5f52c8eca46e9796
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/AbstractRuntime.class differ
diff --git a/src/main/resources/jnr/ffi/provider/BadType.class b/src/main/resources/jnr/ffi/provider/BadType.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce999021c34d2edb3c09af19df02c52cf9504bf6
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/BadType.class differ
diff --git a/src/main/resources/jnr/ffi/provider/BoundedMemoryIO.class b/src/main/resources/jnr/ffi/provider/BoundedMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..edc92afe484642643d6e94b2a1574d4ea2494f4c
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/BoundedMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/ClosureManager.class b/src/main/resources/jnr/ffi/provider/ClosureManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..217bc6843941d62d5f98117a331fa3e25693de5c
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/ClosureManager.class differ
diff --git a/src/main/resources/jnr/ffi/provider/DefaultObjectReferenceManager$ObjectReference.class b/src/main/resources/jnr/ffi/provider/DefaultObjectReferenceManager$ObjectReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..44e4d7705724a322f1ec40cc13095ac4294147cb
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/DefaultObjectReferenceManager$ObjectReference.class differ
diff --git a/src/main/resources/jnr/ffi/provider/DefaultObjectReferenceManager.class b/src/main/resources/jnr/ffi/provider/DefaultObjectReferenceManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..60db20b95112da9b532ccb0e6bdb14070a3ea169
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/DefaultObjectReferenceManager.class differ
diff --git a/src/main/resources/jnr/ffi/provider/DelegatingMemoryIO.class b/src/main/resources/jnr/ffi/provider/DelegatingMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..069fdea6c4f2fe8265c4d1ca161fb4314d851915
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/DelegatingMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/EnumResultConverter.class b/src/main/resources/jnr/ffi/provider/EnumResultConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..39613279b149e81d98d758c7e70ebb6462c94dce
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/EnumResultConverter.class differ
diff --git a/src/main/resources/jnr/ffi/provider/IdentityFunctionMapper$SingletonHolder.class b/src/main/resources/jnr/ffi/provider/IdentityFunctionMapper$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..e01f3a5c7d6570fc8fb0c4bf72b00033d10e9ee4
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/IdentityFunctionMapper$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/ffi/provider/IdentityFunctionMapper.class b/src/main/resources/jnr/ffi/provider/IdentityFunctionMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0ebec8365707f9258710f4908b2b3139d3504e4
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/IdentityFunctionMapper.class differ
diff --git a/src/main/resources/jnr/ffi/provider/InAccessibleMemoryIO.class b/src/main/resources/jnr/ffi/provider/InAccessibleMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dd646a16566e80ae7fe184e8459f404e42adeaf
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/InAccessibleMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/IntPointer.class b/src/main/resources/jnr/ffi/provider/IntPointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d6ad526d616b068eff1a76f77130a8e89547bc6
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/IntPointer.class differ
diff --git a/src/main/resources/jnr/ffi/provider/InvocationSession$PostInvoke.class b/src/main/resources/jnr/ffi/provider/InvocationSession$PostInvoke.class
new file mode 100644
index 0000000000000000000000000000000000000000..365dcb3b62038e2083689e4ed0a454c3e3adca4e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/InvocationSession$PostInvoke.class differ
diff --git a/src/main/resources/jnr/ffi/provider/InvocationSession.class b/src/main/resources/jnr/ffi/provider/InvocationSession.class
new file mode 100644
index 0000000000000000000000000000000000000000..c78c3e91109c51ab242f1a523eba6658d2e95977
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/InvocationSession.class differ
diff --git a/src/main/resources/jnr/ffi/provider/LoadedLibrary.class b/src/main/resources/jnr/ffi/provider/LoadedLibrary.class
new file mode 100644
index 0000000000000000000000000000000000000000..057f5a8e6efc7fa2fe578bf601e5e8e6b7fa580f
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/LoadedLibrary.class differ
diff --git a/src/main/resources/jnr/ffi/provider/MemoryManager.class b/src/main/resources/jnr/ffi/provider/MemoryManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fab22ea23899b8a135c91dc7ee4270c46a3ae12
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/MemoryManager.class differ
diff --git a/src/main/resources/jnr/ffi/provider/NullMemoryIO.class b/src/main/resources/jnr/ffi/provider/NullMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..06bb1b9ed5734d678501f2cb3b867ecc7e9d65ce
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/NullMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/NullTypeMapper.class b/src/main/resources/jnr/ffi/provider/NullTypeMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..24ea848c70391f9ab04f860f683f10631cdb0b43
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/NullTypeMapper.class differ
diff --git a/src/main/resources/jnr/ffi/provider/ParameterFlags.class b/src/main/resources/jnr/ffi/provider/ParameterFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4c521b918efc7bd88c7ac3df46186ce9f7073e8
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/ParameterFlags.class differ
diff --git a/src/main/resources/jnr/ffi/provider/ShareMemoryIO.class b/src/main/resources/jnr/ffi/provider/ShareMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..108e1b963c48377c4a567a8eaa5f8caeadd8ec80
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/ShareMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AbstractAsmLibraryInterface.class b/src/main/resources/jnr/ffi/provider/jffi/AbstractAsmLibraryInterface.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5734a14f908dd41bd6f5a1cd7ac793e656f21f0
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AbstractAsmLibraryInterface.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AbstractDirectPointerParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/AbstractDirectPointerParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..24df74b27a696c045ebfb111441fd6990f0ae6c9
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AbstractDirectPointerParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AbstractFastNumericMethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/AbstractFastNumericMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..c40ffece79ac6e88fc1f4af5dc6c3d8074347528
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AbstractFastNumericMethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$PageHolder.class b/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$PageHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..195f3c7ae2400ad303b4e38472c4d08085310c40
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$PageHolder.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$StaticDataHolder.class b/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$StaticDataHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8a46d287487ee3335fc5993ee49cae19c350035
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$StaticDataHolder.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$Stub.class b/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$Stub.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e0974e1c2ce57c5ff32587209db7515ef4891e1
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler$Stub.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler.class b/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..309d287d5c95d5908ed3ba259454c66b8660fe2d
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AbstractX86StubCompiler.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AllocatedDirectMemoryIO.class b/src/main/resources/jnr/ffi/provider/jffi/AllocatedDirectMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c8b148e0ad5a964911907e39961a67f51358bf2
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AllocatedDirectMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ArrayMemoryIO.class b/src/main/resources/jnr/ffi/provider/jffi/ArrayMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4f88d400006d2ca479095d55d65b0cc8c0a3fe2
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ArrayMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ArrayMemoryParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/ArrayMemoryParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..1cad591ad78972633bec21815cb61f6b267ecfe3
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ArrayMemoryParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder$ObjectField.class b/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder$ObjectField.class
new file mode 100644
index 0000000000000000000000000000000000000000..570e5e4a65928e5db710ae7e035d8276d1994024
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder$ObjectField.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder$ObjectNameGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder$ObjectNameGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fa4232ca3be537d680e1fa290c0bedc9d5119f1
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder$ObjectNameGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder.class b/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..445d1d1f8d14e2ed8701149c01269d8d10518e66
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmBuilder.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmClassLoader.class b/src/main/resources/jnr/ffi/provider/jffi/AsmClassLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..de49503fa09613adfad163b64d50a8e18278aac0
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmClassLoader.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmLibraryLoader.class b/src/main/resources/jnr/ffi/provider/jffi/AsmLibraryLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c35fd19992c338ad1a2d43fdc89638a83e51fa9
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmLibraryLoader.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$1.class b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c077bb0e726145289b26ca4eb5c9b82cfc7beab8
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$2.class b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..9064c0631059c10b2a1818af210a1b30515d0b69
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$2.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$3.class b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..a041ba679610c833e7f7225dfc957f0967c4b036
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$3.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$4.class b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e70cb981c6494c91a61cac6b8889aa94924c05b
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$4.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$5.class b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef96f3289d3d5795d46b817a19b573b51b364cbf
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$5.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$6.class b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..593ad4af66f47e21dd30f2155040d11846bd81d3
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime$6.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime.class b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime.class
new file mode 100644
index 0000000000000000000000000000000000000000..951169318863e258b63b37f2dcc9818f8bc6b709
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmRuntime.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmUtil$1.class b/src/main/resources/jnr/ffi/provider/jffi/AsmUtil$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b7b7ce894d7d224ea0ad18fb486b83c9bff127a
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmUtil$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/AsmUtil.class b/src/main/resources/jnr/ffi/provider/jffi/AsmUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..88acbdfa6416953537f7994b96c09f29246a4b7b
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/AsmUtil.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/BaseMethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/BaseMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7bf69b54a606e5a0f55497b24b6fbda07253620
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/BaseMethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/BufferMethodGenerator$1.class b/src/main/resources/jnr/ffi/provider/jffi/BufferMethodGenerator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf9a83980a6d92e373d6d3a1b386176b304495a3
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/BufferMethodGenerator$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/BufferMethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/BufferMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fc62577499a01614fce8c9d19df9b6bbb9a8a48
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/BufferMethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ByReferenceParameterConverter.class b/src/main/resources/jnr/ffi/provider/jffi/ByReferenceParameterConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..2517c6db500dd778a758c902d3499e81a99728ed
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ByReferenceParameterConverter.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ByteBufferMemoryIO.class b/src/main/resources/jnr/ffi/provider/jffi/ByteBufferMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bd978130a8466f0571dcb78a3a0456268f41900
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ByteBufferMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ClosureUtil.class b/src/main/resources/jnr/ffi/provider/jffi/ClosureUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..37772262729901317569377ca39353b551fff566
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ClosureUtil.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/CodegenUtils.class b/src/main/resources/jnr/ffi/provider/jffi/CodegenUtils.class
new file mode 100644
index 0000000000000000000000000000000000000000..218f0ef3ed64a99dbc7a8c907be67fbf3affd541
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/CodegenUtils.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/DirectBufferMemoryParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/DirectBufferMemoryParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..b85caf3b0915ab1a0f9b07a62e4468aaa0e63b9c
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/DirectBufferMemoryParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/DirectBufferParameterStrategy$1.class b/src/main/resources/jnr/ffi/provider/jffi/DirectBufferParameterStrategy$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f50892bf1ac573d8f5a4bcb55386e99707221ee5
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/DirectBufferParameterStrategy$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/DirectBufferParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/DirectBufferParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ec2dd7e467be9bfd0573409cf0372055d03064b
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/DirectBufferParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/DirectMemoryIO.class b/src/main/resources/jnr/ffi/provider/jffi/DirectMemoryIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3fe38b0128450c7143bb350512ebd94119bc6c3
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/DirectMemoryIO.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/DirectMemoryParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/DirectMemoryParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..87b4aef779b66869357d3eedde3b148dffca357e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/DirectMemoryParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/DirectPointerParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/DirectPointerParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..250bdfb380dc0132414a0b6b6403f8d0646fea3f
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/DirectPointerParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/DirectStructParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/DirectStructParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9a7e338259549bb6775f10a1cabf58f8e6cc85a
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/DirectStructParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/FastIntMethodGenerator$1.class b/src/main/resources/jnr/ffi/provider/jffi/FastIntMethodGenerator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd5d1fb658f77f4470c6f9c73cff6bdc7ed06ef7
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/FastIntMethodGenerator$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/FastIntMethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/FastIntMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..39ac0c468c5c3ec2297cf9ba19d081399eeecdd6
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/FastIntMethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/FastLongMethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/FastLongMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..278be9949077a25e03b37824840a6ebdfca8d86d
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/FastLongMethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/FastNumericMethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/FastNumericMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..f116d2bd44e8ae2390e725e8b8637f599c9e8401
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/FastNumericMethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/FromNativeType.class b/src/main/resources/jnr/ffi/provider/jffi/FromNativeType.class
new file mode 100644
index 0000000000000000000000000000000000000000..973ead82cb8247c3d4d9b7ec81b5e696eca4a684
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/FromNativeType.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/HeapBufferMemoryParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/HeapBufferMemoryParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ab3cd23e982f73a2415b2f69db6f49214807d70
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/HeapBufferMemoryParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/HeapBufferParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/HeapBufferParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..45e57fabf2a91589dff0a309560efc2cffba9d52
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/HeapBufferParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/HeapStructParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/HeapStructParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2155f373342ea1437eaf1dccfa1cd341cc786a9
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/HeapStructParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/InvokerUtil$1.class b/src/main/resources/jnr/ffi/provider/jffi/InvokerUtil$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..989f1d605dbece2d89d47f5555379d0fcb328f50
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/InvokerUtil$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/InvokerUtil.class b/src/main/resources/jnr/ffi/provider/jffi/InvokerUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d95b1d8d37f6ab17f8683bcdfaba0955fb56bc7
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/InvokerUtil.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/JNIInvokeInterface.class b/src/main/resources/jnr/ffi/provider/jffi/JNIInvokeInterface.class
new file mode 100644
index 0000000000000000000000000000000000000000..4345935c58390cbdb47f2a58cad8701eaeb0887e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/JNIInvokeInterface.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/JNINativeInterface.class b/src/main/resources/jnr/ffi/provider/jffi/JNINativeInterface.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9fd0c0c5073b8b43031d86188eaf68a3d77344c
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/JNINativeInterface.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/LibraryLoader.class b/src/main/resources/jnr/ffi/provider/jffi/LibraryLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3fca578b8df999cc94739260813eca9c5b80dfe
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/LibraryLoader.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/LocalVariable.class b/src/main/resources/jnr/ffi/provider/jffi/LocalVariable.class
new file mode 100644
index 0000000000000000000000000000000000000000..816d8fd2b80d814c030fbd486074043bec21b305
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/LocalVariable.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/LocalVariableAllocator.class b/src/main/resources/jnr/ffi/provider/jffi/LocalVariableAllocator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6be35de6998b48ebc740a785fc376e806890036a
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/LocalVariableAllocator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/MemoryUtil.class b/src/main/resources/jnr/ffi/provider/jffi/MemoryUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe2491e79617077df6e66554b3c2f72d36696375
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/MemoryUtil.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/MethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/MethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ed862d922153b5e8841d8b4e0cd394419a9f376
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/MethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory$1.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..947014c95082bdf51faa5b5b42c9f25cd52689eb
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory$ClosureReference.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory$ClosureReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..c5830ccf45add016b6adda211f42a9ee3ddf123e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory$ClosureReference.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2116fa15785d4bf099e281029c862fa9928a586
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureFactory.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager$1.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a496275f83cd6e118044c75c65359c22ffe56d6d
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager$ClosureSite.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager$ClosureSite.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba3f10375cccd138999669c7b594d00bcb06fced
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager$ClosureSite.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..03bcb8a59695ff1856709690d210b8b2a031d1a1
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureManager.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosurePointer.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosurePointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..74609eca2b06fb2be53d2f2db414acf114e86ce6
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosurePointer.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy$1.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bc962bbe33b1c12634ad9da7b576bb3368a7b25
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy$Factory.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy$Factory.class
new file mode 100644
index 0000000000000000000000000000000000000000..656431cec5958b8e226a77254418d55ed6eeabf5
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy$Factory.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy.class b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f86f628bef4cc2598ab77783f1f8be9cd00954e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeClosureProxy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeFinalizer$SingletonHolder.class b/src/main/resources/jnr/ffi/provider/jffi/NativeFinalizer$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..10142b1142f58287aaf3306b2b449bd71bb4800a
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeFinalizer$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeFinalizer.class b/src/main/resources/jnr/ffi/provider/jffi/NativeFinalizer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4835129478b2c2e1e4afef8c10ce494a9854146
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeFinalizer.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeLibrary$StaticDataHolder.class b/src/main/resources/jnr/ffi/provider/jffi/NativeLibrary$StaticDataHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..034f91df9e462ec089508fa9d8f1ca7445aa4a04
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeLibrary$StaticDataHolder.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeLibrary.class b/src/main/resources/jnr/ffi/provider/jffi/NativeLibrary.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6463ed5210b22e77693e4d9e610dc375e701679
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeLibrary.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeMemoryManager.class b/src/main/resources/jnr/ffi/provider/jffi/NativeMemoryManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cef93ea358a5f88e0488788f65ef7c97ee91190
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeMemoryManager.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$1.class b/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..646824939f6b743c849c2f3bc7794504df7a6953
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$SingletonHolder.class b/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..eaf96c7e0cc5fab3231ddd304df7b5c6d58e9f19
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$TypeDelegate.class b/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$TypeDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d9cba05f11257b5a4817426313eba05c8c5b3e2
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime$TypeDelegate.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime.class b/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime.class
new file mode 100644
index 0000000000000000000000000000000000000000..77b5f78033ea9527fcd579eea5ee92b944918f8c
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NativeRuntime.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NoTrace.class b/src/main/resources/jnr/ffi/provider/jffi/NoTrace.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a7385a91bbf8d6f660624270e453e2f5dff237b
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NoTrace.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NoX86.class b/src/main/resources/jnr/ffi/provider/jffi/NoX86.class
new file mode 100644
index 0000000000000000000000000000000000000000..1231009b0eb71b3eda8deea2b482c635fb93f5f2
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NoX86.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NotImplMethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/NotImplMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..1edfa522199f2d519a36c137cd289fa3d19e9444
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NotImplMethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NullPointerParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/NullPointerParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..da9fc8e68e827398555a6a19f6556df522f09b17
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NullPointerParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NumberUtil$1.class b/src/main/resources/jnr/ffi/provider/jffi/NumberUtil$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b78c8af46d0bbd9fd9933f63bed0380ad4a1bec
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NumberUtil$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/NumberUtil.class b/src/main/resources/jnr/ffi/provider/jffi/NumberUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6dfc8ea1538d7d6e5526cb50b186df23ffad89f
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/NumberUtil.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ParameterConverter.class b/src/main/resources/jnr/ffi/provider/jffi/ParameterConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..5acdd7a8fe2459e6ced35211d3115c507363f9ff
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ParameterConverter.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ParameterType.class b/src/main/resources/jnr/ffi/provider/jffi/ParameterType.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ff9fc92b2a1e9093c38c7c20fd06d4e2d5de861
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ParameterType.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PointerParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/PointerParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a6dbaf16f197724f6d94bdf7cf258d913bb5c23
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PointerParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$1.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2edc71cbc9e688c6d0bc63bc0540b878ba5b1ad8
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$2.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8e87f6ced60c10a641cda03e833dd1ba6744691
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$2.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$3.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d73a495365443fdcfd741b7e4c371b610351f14
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$3.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$4.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..40c0847d33e927e81aaada821306725b7631d91a
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$4.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$5.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..6468d26b84ce4c8693ead86a8d826aa65d0df520
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$5.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$6.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..25b9edcaece179279c7752c8963fef0c9e4c2193
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$6.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$7.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6f35d8490746c116ecf631fa5bc38c2c1bc3efe
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$7.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$8.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..801218a540c0c0274de8baedcd6df790eb29ca56
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy$8.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..84f00746f9cefccdc17219c7dd3aeebef6db87af
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/PrimitiveArrayParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/Provider.class b/src/main/resources/jnr/ffi/provider/jffi/Provider.class
new file mode 100644
index 0000000000000000000000000000000000000000..f161cad310c3d3e5634a670dafba76a6148d4920
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/Provider.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ResultConverter.class b/src/main/resources/jnr/ffi/provider/jffi/ResultConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae7652d93f74ff02d12b156f1b0ae38ae7ad806d
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ResultConverter.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ResultType.class b/src/main/resources/jnr/ffi/provider/jffi/ResultType.class
new file mode 100644
index 0000000000000000000000000000000000000000..98ceae2acb7caf0b149f5f49360f459f646be451
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ResultType.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/SigType.class b/src/main/resources/jnr/ffi/provider/jffi/SigType.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7bc4a6492c37b619980bf7b79649691506b8652
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/SigType.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/Signature.class b/src/main/resources/jnr/ffi/provider/jffi/Signature.class
new file mode 100644
index 0000000000000000000000000000000000000000..0523368f304fdce251c6bdfeaaa31266adaf6481
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/Signature.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/SkinnyMethodAdapter.class b/src/main/resources/jnr/ffi/provider/jffi/SkinnyMethodAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a30084a445561eb8a6ca9152433f5453ac6331b
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/SkinnyMethodAdapter.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/StringParameterStrategy.class b/src/main/resources/jnr/ffi/provider/jffi/StringParameterStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b1ce0617e5ae039a5e7e0cf61c3472ccab459db
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/StringParameterStrategy.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/StubCompiler$1.class b/src/main/resources/jnr/ffi/provider/jffi/StubCompiler$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..472ee12ba9675ad981edbebaa27a84b6d2492f37
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/StubCompiler$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/StubCompiler$DummyStubCompiler.class b/src/main/resources/jnr/ffi/provider/jffi/StubCompiler$DummyStubCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..54150513eae83646e585f1595c731f576320181a
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/StubCompiler$DummyStubCompiler.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/StubCompiler.class b/src/main/resources/jnr/ffi/provider/jffi/StubCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..32c49cd083ece591a71ae5c7f8d3790d72d42dda
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/StubCompiler.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/SymbolNotFoundError.class b/src/main/resources/jnr/ffi/provider/jffi/SymbolNotFoundError.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcf7c9106ce73f4835d3eb3c84aefde5888343a3
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/SymbolNotFoundError.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/ToNativeType.class b/src/main/resources/jnr/ffi/provider/jffi/ToNativeType.class
new file mode 100644
index 0000000000000000000000000000000000000000..40fd670fd7d2d062851990288c73b2d2edd12ca1
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/ToNativeType.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$1.class b/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..57c4e043ef1768fc0a3cb798b3985fd607dcea03
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$Magazine.class b/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$Magazine.class
new file mode 100644
index 0000000000000000000000000000000000000000..84532662273a8bc0ad2fbe0d12cbda684e8966a7
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$Magazine.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$Sentinel.class b/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$Sentinel.class
new file mode 100644
index 0000000000000000000000000000000000000000..691832eda78b36a56b0aeca8e2c8f0aaefb605ab
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory$Sentinel.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory.class b/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..66e15ec8c2c2a59d0bdf4c406e9a24bbfd498ce1
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/TransientNativeMemory.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$Mode.class b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$Mode.class
new file mode 100644
index 0000000000000000000000000000000000000000..dacedb2f76c5c92194a5c0c3075557373fa22149
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$Mode.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$SingletonHolder.class b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f718d576a5caaedddbed60e57d006b739bb6e53
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$Syntax.class b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$Syntax.class
new file mode 100644
index 0000000000000000000000000000000000000000..77bf30daf6e8493e9da9e7b4d6aaf23ab49a5784
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$Syntax.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$UDis86.class b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$UDis86.class
new file mode 100644
index 0000000000000000000000000000000000000000..610ea523e6630243bf04029bf42c44246835ac9d
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$UDis86.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$X86DisassemblerConverter.class b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$X86DisassemblerConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2c6c14a81a68a66be1021bce6f703978b82750c
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler$X86DisassemblerConverter.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler.class b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler.class
new file mode 100644
index 0000000000000000000000000000000000000000..77c2953938199761783d9b0b0ce4caf2fb9b6cb6
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86Disassembler.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86MethodGenerator$1.class b/src/main/resources/jnr/ffi/provider/jffi/X86MethodGenerator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..40a77a35fa0ce82d498b6cdba598d13a8430cd80
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86MethodGenerator$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86MethodGenerator.class b/src/main/resources/jnr/ffi/provider/jffi/X86MethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d76afc0425c552b1967d4c34d96163a2bb1b8a0
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86MethodGenerator.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86_32StubCompiler$1.class b/src/main/resources/jnr/ffi/provider/jffi/X86_32StubCompiler$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f7ef290747921480f0a4421d039ac16c5d49f32
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86_32StubCompiler$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86_32StubCompiler.class b/src/main/resources/jnr/ffi/provider/jffi/X86_32StubCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..64b7fae7a0f5884409cb538380a591f028bb8b0c
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86_32StubCompiler.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86_64StubCompiler$1.class b/src/main/resources/jnr/ffi/provider/jffi/X86_64StubCompiler$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..af4a9bf7c67ccdb82a9ec5ba9264810c4722d864
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86_64StubCompiler$1.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/X86_64StubCompiler.class b/src/main/resources/jnr/ffi/provider/jffi/X86_64StubCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ae139852e7ff77a008574b68bbfa41762a3feb0
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/X86_64StubCompiler.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/arm/linux/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/arm/linux/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb65938cf5a5c5963607af56bf0141767055c04d
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/arm/linux/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/i386/darwin/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/darwin/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7c76c30f419c87dc957a13aa6ae92c41f77cf01
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/darwin/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/i386/freebsd/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/freebsd/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..37f41e6472a1ae503ddff6aad4262f7c13d1eee2
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/freebsd/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/i386/linux/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/linux/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3050994a695b5bc5534d6158d50ca4d5abe9c03
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/linux/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/i386/openbsd/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/openbsd/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..0645fcffe47a1f00151227998c270228129813e3
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/openbsd/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/i386/solaris/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/solaris/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccf24cf539cf4b4cb55da674e7375241b67b3d71
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/solaris/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/i386/windows/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/windows/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..d82883977d441d2ef39edc9a0fa61ab66e50e198
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/i386/windows/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/mips/linux/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/mips/linux/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..47e16fa7cf8ebd7c316ee4260e41f6ca1feff487
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/mips/linux/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/mipsel/linux/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/mipsel/linux/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d0db9125fbb12588509d365fff90d0199c95596
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/mipsel/linux/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/aix/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/aix/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f30eb40c3e3f1c4c7bf297b749d73c69b8490dc
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/aix/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/darwin/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/darwin/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..b45f6848b1722199967dbb97f024f30ef30a7714
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/darwin/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/linux/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/linux/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..c46e289873ebffa6afdb02ef22ea05e1e8d170e4
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/powerpc/linux/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/s390/linux/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/s390/linux/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..153d61ca2a97bc58d3557574b21baf941483780e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/s390/linux/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/s390x/linux/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/s390x/linux/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..55ef59f4f380562ed36a38022bd1f72513dd40ba
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/s390x/linux/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/sparc/solaris/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/sparc/solaris/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad7e6e4a59ddc8f951576705622451b090352d83
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/sparc/solaris/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/sparcv9/solaris/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/sparcv9/solaris/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..0aaac874e48973f0d41c21573fbccf442706ce3c
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/sparcv9/solaris/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/darwin/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/darwin/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..67dbccf7cd667a6dd7d71d52be9e33a2fd4302f3
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/darwin/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/freebsd/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/freebsd/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c98e227fc8853c48d339d06e17028a02bf872c4
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/freebsd/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/linux/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/linux/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c8dde64e161fd56039bdb9a5d23ef8bdab2ca7f
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/linux/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/openbsd/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/openbsd/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3452a03cbbe27a9aee4c685c7031b3763f9902e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/openbsd/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/solaris/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/solaris/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..79ae28798b2619911e4751432b276d1f40608159
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/solaris/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/windows/TypeAliases.class b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/windows/TypeAliases.class
new file mode 100644
index 0000000000000000000000000000000000000000..f151a129af382dd32f925b509ee3837b37001c7e
Binary files /dev/null and b/src/main/resources/jnr/ffi/provider/jffi/platform/x86_64/windows/TypeAliases.class differ
diff --git a/src/main/resources/jnr/ffi/types/blkcnt_t.class b/src/main/resources/jnr/ffi/types/blkcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..79c0b2877f6a2a61513d106428a252e5bca37bb3
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/blkcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/blksize_t.class b/src/main/resources/jnr/ffi/types/blksize_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c584269744e1c8e1f52f23f52edd035580e874d
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/blksize_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/caddr_t.class b/src/main/resources/jnr/ffi/types/caddr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fa09db0a56b1c88c026974d7e774a5cef205c8b
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/caddr_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/clock_t.class b/src/main/resources/jnr/ffi/types/clock_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a8e4b44371b41a12e955fb0b077685f6d92311f
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/clock_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/dev_t.class b/src/main/resources/jnr/ffi/types/dev_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..112e03cbd6f919cb5970ae2f44c0ec6768e7b6a5
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/dev_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/fsblkcnt_t.class b/src/main/resources/jnr/ffi/types/fsblkcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..75c8ebe5cf83c9494871b2bf7a2cbdb944f7f260
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/fsblkcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/fsfilcnt_t.class b/src/main/resources/jnr/ffi/types/fsfilcnt_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..d45bb2de1d31a23d61b3d2ac0332cae70336b916
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/fsfilcnt_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/gid_t.class b/src/main/resources/jnr/ffi/types/gid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..50e422117d37f2a526929a26b72674127c7ec14d
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/gid_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/id_t.class b/src/main/resources/jnr/ffi/types/id_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..46ba5190ef8103e67d9b28acc5d9a56ca4541633
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/id_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/in_addr_t.class b/src/main/resources/jnr/ffi/types/in_addr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..7781823ec5bde076bf0858baca16db2945cc75c1
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/in_addr_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/in_port_t.class b/src/main/resources/jnr/ffi/types/in_port_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..45c8b62e97081ad70d05c31058c9681fa3977e56
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/in_port_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/ino64_t.class b/src/main/resources/jnr/ffi/types/ino64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..f902faf7e90e019e3bb88071ba77e8b4767ff414
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/ino64_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/ino_t.class b/src/main/resources/jnr/ffi/types/ino_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5f6ea4f9eb43abeb1a6895647dea444df8dbd86
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/ino_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/int16_t.class b/src/main/resources/jnr/ffi/types/int16_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2e982e252d561e5bc3ed3cc7cfb37886c98794e
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/int16_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/int32_t.class b/src/main/resources/jnr/ffi/types/int32_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..58ec4596f269f04d97f752944232565436549a3b
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/int32_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/int64_t.class b/src/main/resources/jnr/ffi/types/int64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..2465120d767e20647dcb3788e9b18f46fe34bafd
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/int64_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/int8_t.class b/src/main/resources/jnr/ffi/types/int8_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..909f86561cfb3d3004f6579ff22c0a9eee7e96d0
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/int8_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/intptr_t.class b/src/main/resources/jnr/ffi/types/intptr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c829f8c593068b92c6372b059bb747eca24168f
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/intptr_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/key_t.class b/src/main/resources/jnr/ffi/types/key_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..13aa9468ed42b7bcee802d457d6e9ee84e1b7a3e
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/key_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/mode_t.class b/src/main/resources/jnr/ffi/types/mode_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2cc249462d4c41800e1005077e195b54ed458a0
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/mode_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/nlink_t.class b/src/main/resources/jnr/ffi/types/nlink_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..06bcfc0b61609d4aa71972ca8c6d7def1339be14
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/nlink_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/off_t.class b/src/main/resources/jnr/ffi/types/off_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..16dbdda4ca15af5f895765897ac8244427285ff4
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/off_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/pid_t.class b/src/main/resources/jnr/ffi/types/pid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2e1d0d245ec1624b98d2e5938914347839c4517
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/pid_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/rlim_t.class b/src/main/resources/jnr/ffi/types/rlim_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..f61bafd0efa8fd3ed22b6ed093ab2de8d784b956
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/rlim_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/sa_family_t.class b/src/main/resources/jnr/ffi/types/sa_family_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..a10d23f6205c104b17b7ceb34df812f2de4196d2
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/sa_family_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/size_t.class b/src/main/resources/jnr/ffi/types/size_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..c11cf7251a8806b6efd46749f1069cab262163d5
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/size_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/socklen_t.class b/src/main/resources/jnr/ffi/types/socklen_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..3eb82583075a60cac63e6baba3256ff9fb1e0153
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/socklen_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/ssize_t.class b/src/main/resources/jnr/ffi/types/ssize_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..36ef36eda747ca014040e4b64a254e994e57e8da
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/ssize_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/swblk_t.class b/src/main/resources/jnr/ffi/types/swblk_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..46d49fa31464d00a007991430b471cb7eef05b25
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/swblk_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/time_t.class b/src/main/resources/jnr/ffi/types/time_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..d679c439a6faec374e64aee81adf4fe7649150b5
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/time_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/u_int16_t.class b/src/main/resources/jnr/ffi/types/u_int16_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..5131580a24cb15a226ffe70adf991e0a40798fed
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/u_int16_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/u_int32_t.class b/src/main/resources/jnr/ffi/types/u_int32_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..093f800950538387e9b105b2a40003891a4d2cdd
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/u_int32_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/u_int64_t.class b/src/main/resources/jnr/ffi/types/u_int64_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..2fafce30b58022c76ef4461d006a5b4c452baebb
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/u_int64_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/u_int8_t.class b/src/main/resources/jnr/ffi/types/u_int8_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7c5e302d8cb8bf053114991875c755aa040a3d0
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/u_int8_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/uid_t.class b/src/main/resources/jnr/ffi/types/uid_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..d429537af493e0d12d4eb543207c03450dd7a481
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/uid_t.class differ
diff --git a/src/main/resources/jnr/ffi/types/uintptr_t.class b/src/main/resources/jnr/ffi/types/uintptr_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..b67733b21f290bbe9dd5432d98101a2347b17dad
Binary files /dev/null and b/src/main/resources/jnr/ffi/types/uintptr_t.class differ
diff --git a/src/main/resources/jnr/ffi/util/BufferUtil.class b/src/main/resources/jnr/ffi/util/BufferUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..6cf4961f34c4b453f76bcc0a95efbe9c94800ba4
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/BufferUtil.class differ
diff --git a/src/main/resources/jnr/ffi/util/EnumMapper$IntegerEnum.class b/src/main/resources/jnr/ffi/util/EnumMapper$IntegerEnum.class
new file mode 100644
index 0000000000000000000000000000000000000000..147909ced52ec325f68bedf6ea7bc91e8974299c
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/EnumMapper$IntegerEnum.class differ
diff --git a/src/main/resources/jnr/ffi/util/EnumMapper$StaticDataHolder.class b/src/main/resources/jnr/ffi/util/EnumMapper$StaticDataHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..d84653a7dce4f06b3142b22c39df5bda6a43f49a
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/EnumMapper$StaticDataHolder.class differ
diff --git a/src/main/resources/jnr/ffi/util/EnumMapper.class b/src/main/resources/jnr/ffi/util/EnumMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1c42d66674fe49231d8f393ade8c6631d0e7267
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/EnumMapper.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizablePhantomReference.class b/src/main/resources/jnr/ffi/util/ref/FinalizablePhantomReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..3357091381ff84eef7b7e624f9e89de6e57b4a3e
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizablePhantomReference.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizableReference.class b/src/main/resources/jnr/ffi/util/ref/FinalizableReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..7452ee04ab50e6bfb48bba00d5a7d603e1f23376
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizableReference.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$DecoupledLoader.class b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$DecoupledLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..a49468481222d68161d5dd70f74a80d0121feea2
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$DecoupledLoader.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$DirectLoader.class b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$DirectLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d025a1df5bc840890f32303b098f7c1472c0564
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$DirectLoader.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$FinalizerLoader.class b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$FinalizerLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..cca956b418cd0cf7e8bb33f3c2367e3a27c56ab5
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$FinalizerLoader.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$SystemLoader.class b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$SystemLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..b09b69471deaef39e2627d9587a073e82c17a355
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue$SystemLoader.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue.class b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..b332b9554036dc0b305757e54abca7c9b72efaa5
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizableReferenceQueue.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizableSoftReference.class b/src/main/resources/jnr/ffi/util/ref/FinalizableSoftReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecbabbc9e3ccc34daac931034126f15ba3212768
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizableSoftReference.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/FinalizableWeakReference.class b/src/main/resources/jnr/ffi/util/ref/FinalizableWeakReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bdc2e0a186f728d1630ed597927d4f623794035
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/FinalizableWeakReference.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/internal/Finalizer$1.class b/src/main/resources/jnr/ffi/util/ref/internal/Finalizer$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..326d1c70cb12eaea753a4b4112cd39bb431660ae
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/internal/Finalizer$1.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/internal/Finalizer$ShutDown.class b/src/main/resources/jnr/ffi/util/ref/internal/Finalizer$ShutDown.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7dabe6bebeb48bc2080fb519bef8d7ecb10b9d5
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/internal/Finalizer$ShutDown.class differ
diff --git a/src/main/resources/jnr/ffi/util/ref/internal/Finalizer.class b/src/main/resources/jnr/ffi/util/ref/internal/Finalizer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdb108489299bdde8a7e9a7a12a6a70194af0513
Binary files /dev/null and b/src/main/resources/jnr/ffi/util/ref/internal/Finalizer.class differ
diff --git a/src/main/resources/jnr/netdb/FileProtocolsDB$1.class b/src/main/resources/jnr/netdb/FileProtocolsDB$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a928e76628d9380fe09c5983a4dedb99f4ed61d7
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileProtocolsDB$1.class differ
diff --git a/src/main/resources/jnr/netdb/FileProtocolsDB$2.class b/src/main/resources/jnr/netdb/FileProtocolsDB$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..33109a8bc4bcafad0000869b87a93b7f851efcd4
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileProtocolsDB$2.class differ
diff --git a/src/main/resources/jnr/netdb/FileProtocolsDB$3.class b/src/main/resources/jnr/netdb/FileProtocolsDB$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..74cadb2000796ff7e01b7b7900e2a159284edc05
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileProtocolsDB$3.class differ
diff --git a/src/main/resources/jnr/netdb/FileProtocolsDB$Filter.class b/src/main/resources/jnr/netdb/FileProtocolsDB$Filter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c60c0949dcfda651091dfdcd0b3aeacfcb4745e3
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileProtocolsDB$Filter.class differ
diff --git a/src/main/resources/jnr/netdb/FileProtocolsDB$SingletonHolder.class b/src/main/resources/jnr/netdb/FileProtocolsDB$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..e810fec23f46e4101232d3dcd8a2e3e946f7fa57
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileProtocolsDB$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/netdb/FileProtocolsDB.class b/src/main/resources/jnr/netdb/FileProtocolsDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..a803280538a7e47074f33a083e671d134162afbd
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileProtocolsDB.class differ
diff --git a/src/main/resources/jnr/netdb/FileServicesDB$1.class b/src/main/resources/jnr/netdb/FileServicesDB$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..845ede1c4c241ec3b088dcb2feefe964c111ce3d
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileServicesDB$1.class differ
diff --git a/src/main/resources/jnr/netdb/FileServicesDB$2.class b/src/main/resources/jnr/netdb/FileServicesDB$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..f675f3e5d783f1446280eed8edf5bb72dc69db49
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileServicesDB$2.class differ
diff --git a/src/main/resources/jnr/netdb/FileServicesDB$3.class b/src/main/resources/jnr/netdb/FileServicesDB$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ad09b5b733b29185bbae98b8351f534a4364ab3
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileServicesDB$3.class differ
diff --git a/src/main/resources/jnr/netdb/FileServicesDB$Filter.class b/src/main/resources/jnr/netdb/FileServicesDB$Filter.class
new file mode 100644
index 0000000000000000000000000000000000000000..03ed9d0d49d6d510435310ffc19155ad6601288e
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileServicesDB$Filter.class differ
diff --git a/src/main/resources/jnr/netdb/FileServicesDB$SingletonHolder.class b/src/main/resources/jnr/netdb/FileServicesDB$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..01966d04676469e55e18be47d551489b4e83495b
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileServicesDB$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/netdb/FileServicesDB.class b/src/main/resources/jnr/netdb/FileServicesDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..1cd43c4e41a26576bb6407ad9e9bfba8d4ca33e5
Binary files /dev/null and b/src/main/resources/jnr/netdb/FileServicesDB.class differ
diff --git a/src/main/resources/jnr/netdb/IANAProtocolsDB$1.class b/src/main/resources/jnr/netdb/IANAProtocolsDB$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e17b220a607a9c36e5cc36e46fbf26a6b20c222f
Binary files /dev/null and b/src/main/resources/jnr/netdb/IANAProtocolsDB$1.class differ
diff --git a/src/main/resources/jnr/netdb/IANAProtocolsDB$ProtocolDBBuilder.class b/src/main/resources/jnr/netdb/IANAProtocolsDB$ProtocolDBBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..6cde568724aa88d808e18098e9295059af1acafb
Binary files /dev/null and b/src/main/resources/jnr/netdb/IANAProtocolsDB$ProtocolDBBuilder.class differ
diff --git a/src/main/resources/jnr/netdb/IANAProtocolsDB$SingletonHolder.class b/src/main/resources/jnr/netdb/IANAProtocolsDB$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..c42a943e28375676255b33be0ca4edb6757928c2
Binary files /dev/null and b/src/main/resources/jnr/netdb/IANAProtocolsDB$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/netdb/IANAProtocolsDB.class b/src/main/resources/jnr/netdb/IANAProtocolsDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..23e64b6a3d921a0755f202e53dddfbcbda3dfead
Binary files /dev/null and b/src/main/resources/jnr/netdb/IANAProtocolsDB.class differ
diff --git a/src/main/resources/jnr/netdb/IANAServicesDB$1.class b/src/main/resources/jnr/netdb/IANAServicesDB$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e2a821acc7af1f9d562e7180024de05871fe741
Binary files /dev/null and b/src/main/resources/jnr/netdb/IANAServicesDB$1.class differ
diff --git a/src/main/resources/jnr/netdb/IANAServicesDB$ServicesBuilder.class b/src/main/resources/jnr/netdb/IANAServicesDB$ServicesBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d09e2e3d653097d5dde01dba168c5e724e7f7de
Binary files /dev/null and b/src/main/resources/jnr/netdb/IANAServicesDB$ServicesBuilder.class differ
diff --git a/src/main/resources/jnr/netdb/IANAServicesDB$SingletonHolder.class b/src/main/resources/jnr/netdb/IANAServicesDB$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa2b5e838e38f85bec2c5156f9463e1c05712e74
Binary files /dev/null and b/src/main/resources/jnr/netdb/IANAServicesDB$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/netdb/IANAServicesDB.class b/src/main/resources/jnr/netdb/IANAServicesDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5084e1acf4ddca149379451cc0d1df19d70dd26
Binary files /dev/null and b/src/main/resources/jnr/netdb/IANAServicesDB.class differ
diff --git a/src/main/resources/jnr/netdb/NativeProtocolsDB$DefaultNativeProtocolsDB.class b/src/main/resources/jnr/netdb/NativeProtocolsDB$DefaultNativeProtocolsDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb4a45520c67cbdf5ad6282725f74f1c2d48ceb7
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeProtocolsDB$DefaultNativeProtocolsDB.class differ
diff --git a/src/main/resources/jnr/netdb/NativeProtocolsDB$LibProto.class b/src/main/resources/jnr/netdb/NativeProtocolsDB$LibProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b78fb253bccb7f80890d53bb2eea6a150dcf6ae
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeProtocolsDB$LibProto.class differ
diff --git a/src/main/resources/jnr/netdb/NativeProtocolsDB$LinuxLibProto.class b/src/main/resources/jnr/netdb/NativeProtocolsDB$LinuxLibProto.class
new file mode 100644
index 0000000000000000000000000000000000000000..d02bda47c7bd851634c8215cb6cbcdc990edc5c4
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeProtocolsDB$LinuxLibProto.class differ
diff --git a/src/main/resources/jnr/netdb/NativeProtocolsDB$LinuxNativeProtocolsDB.class b/src/main/resources/jnr/netdb/NativeProtocolsDB$LinuxNativeProtocolsDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..47708976e05645577757a0b8f72dd53e23026a0a
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeProtocolsDB$LinuxNativeProtocolsDB.class differ
diff --git a/src/main/resources/jnr/netdb/NativeProtocolsDB$SingletonHolder.class b/src/main/resources/jnr/netdb/NativeProtocolsDB$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..16e32cb4e7d1d4bc260c450acc6583f23f0dabbc
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeProtocolsDB$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/netdb/NativeProtocolsDB$UnixProtoent.class b/src/main/resources/jnr/netdb/NativeProtocolsDB$UnixProtoent.class
new file mode 100644
index 0000000000000000000000000000000000000000..0474b60dc21b5df1f06f3f30a0b08cf879694f7c
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeProtocolsDB$UnixProtoent.class differ
diff --git a/src/main/resources/jnr/netdb/NativeProtocolsDB.class b/src/main/resources/jnr/netdb/NativeProtocolsDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..25a714861c24d1d399c837d29efc78c606838353
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeProtocolsDB.class differ
diff --git a/src/main/resources/jnr/netdb/NativeServicesDB$DefaultNativeServicesDB.class b/src/main/resources/jnr/netdb/NativeServicesDB$DefaultNativeServicesDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bd9742f2e9fa3f89f8619827db6d269b3966273
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeServicesDB$DefaultNativeServicesDB.class differ
diff --git a/src/main/resources/jnr/netdb/NativeServicesDB$LibServices.class b/src/main/resources/jnr/netdb/NativeServicesDB$LibServices.class
new file mode 100644
index 0000000000000000000000000000000000000000..98b98168c0b67e20e4139c7b7d199a36a632a25e
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeServicesDB$LibServices.class differ
diff --git a/src/main/resources/jnr/netdb/NativeServicesDB$LinuxLibServices.class b/src/main/resources/jnr/netdb/NativeServicesDB$LinuxLibServices.class
new file mode 100644
index 0000000000000000000000000000000000000000..939abb669c3c8aa1c19b9c47c50e4ac819231f49
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeServicesDB$LinuxLibServices.class differ
diff --git a/src/main/resources/jnr/netdb/NativeServicesDB$LinuxServent.class b/src/main/resources/jnr/netdb/NativeServicesDB$LinuxServent.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f611e46a6314b42c13d29e71fc4d2a6b044d455
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeServicesDB$LinuxServent.class differ
diff --git a/src/main/resources/jnr/netdb/NativeServicesDB$LinuxServicesDB.class b/src/main/resources/jnr/netdb/NativeServicesDB$LinuxServicesDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..b723cd5c09d1e756b0697683789f627fae52b058
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeServicesDB$LinuxServicesDB.class differ
diff --git a/src/main/resources/jnr/netdb/NativeServicesDB$SingletonHolder.class b/src/main/resources/jnr/netdb/NativeServicesDB$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd489500d8769268cff40f9feab0d2c2684a8512
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeServicesDB$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/netdb/NativeServicesDB$UnixServent.class b/src/main/resources/jnr/netdb/NativeServicesDB$UnixServent.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a1632b0f242d605505f2cd74bad4004a3649cd7
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeServicesDB$UnixServent.class differ
diff --git a/src/main/resources/jnr/netdb/NativeServicesDB.class b/src/main/resources/jnr/netdb/NativeServicesDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..cbb80372a778fa2d185d00ea1d7d5d71ebd85766
Binary files /dev/null and b/src/main/resources/jnr/netdb/NativeServicesDB.class differ
diff --git a/src/main/resources/jnr/netdb/NetDBEntry.class b/src/main/resources/jnr/netdb/NetDBEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..46ee2cd14ed485dd06c5c62fc8eaa95112902f81
Binary files /dev/null and b/src/main/resources/jnr/netdb/NetDBEntry.class differ
diff --git a/src/main/resources/jnr/netdb/NetDBFilter.class b/src/main/resources/jnr/netdb/NetDBFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..15f009eaf88a7d145f82a50a2b4bd6faf31f31b9
Binary files /dev/null and b/src/main/resources/jnr/netdb/NetDBFilter.class differ
diff --git a/src/main/resources/jnr/netdb/NetDBIterator.class b/src/main/resources/jnr/netdb/NetDBIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..297d9bb9eb363470ce0bec497d46f9486524ed38
Binary files /dev/null and b/src/main/resources/jnr/netdb/NetDBIterator.class differ
diff --git a/src/main/resources/jnr/netdb/NetDBParser.class b/src/main/resources/jnr/netdb/NetDBParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..98266cdc78732f6ea21daf7c5951f24ccc7b42e5
Binary files /dev/null and b/src/main/resources/jnr/netdb/NetDBParser.class differ
diff --git a/src/main/resources/jnr/netdb/Protocol$ProtocolDBSingletonHolder.class b/src/main/resources/jnr/netdb/Protocol$ProtocolDBSingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa7818b2d0834e64a8ee6f408c17117c33d8e81b
Binary files /dev/null and b/src/main/resources/jnr/netdb/Protocol$ProtocolDBSingletonHolder.class differ
diff --git a/src/main/resources/jnr/netdb/Protocol.class b/src/main/resources/jnr/netdb/Protocol.class
new file mode 100644
index 0000000000000000000000000000000000000000..6320d6a2b8eac1e108c4f7f1b97492b8d7b2f83c
Binary files /dev/null and b/src/main/resources/jnr/netdb/Protocol.class differ
diff --git a/src/main/resources/jnr/netdb/ProtocolsDB.class b/src/main/resources/jnr/netdb/ProtocolsDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfdff45c4579a6885f835a94cd778c5a47d40cbf
Binary files /dev/null and b/src/main/resources/jnr/netdb/ProtocolsDB.class differ
diff --git a/src/main/resources/jnr/netdb/Service$ServicesDBSingletonHolder.class b/src/main/resources/jnr/netdb/Service$ServicesDBSingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..19cdc2a43d05473c475b124a3562bc943925ea7a
Binary files /dev/null and b/src/main/resources/jnr/netdb/Service$ServicesDBSingletonHolder.class differ
diff --git a/src/main/resources/jnr/netdb/Service.class b/src/main/resources/jnr/netdb/Service.class
new file mode 100644
index 0000000000000000000000000000000000000000..b382a9a3075b1de301c983a63ed3739361f13f16
Binary files /dev/null and b/src/main/resources/jnr/netdb/Service.class differ
diff --git a/src/main/resources/jnr/netdb/ServicesDB.class b/src/main/resources/jnr/netdb/ServicesDB.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0a008b8b24fc5d2fffabb718efdc44f9391c724
Binary files /dev/null and b/src/main/resources/jnr/netdb/ServicesDB.class differ
diff --git a/src/main/resources/jnr/netdb/StringUtil.class b/src/main/resources/jnr/netdb/StringUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..73c1a2a20ba63b7c4dcf3a0718554a82a96abe4e
Binary files /dev/null and b/src/main/resources/jnr/netdb/StringUtil.class differ
diff --git a/src/main/resources/jnr/posix/BaseFileStat.class b/src/main/resources/jnr/posix/BaseFileStat.class
new file mode 100644
index 0000000000000000000000000000000000000000..e931b4c617b041c877db0de2de0152a3f7d97b4b
Binary files /dev/null and b/src/main/resources/jnr/posix/BaseFileStat.class differ
diff --git a/src/main/resources/jnr/posix/BaseNativePOSIX$1.class b/src/main/resources/jnr/posix/BaseNativePOSIX$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff9ae7f486825a3befe9191c1661d57f5954510d
Binary files /dev/null and b/src/main/resources/jnr/posix/BaseNativePOSIX$1.class differ
diff --git a/src/main/resources/jnr/posix/BaseNativePOSIX$2.class b/src/main/resources/jnr/posix/BaseNativePOSIX$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..11f7e61b6618ce06e61cd293ec925729c2b535f0
Binary files /dev/null and b/src/main/resources/jnr/posix/BaseNativePOSIX$2.class differ
diff --git a/src/main/resources/jnr/posix/BaseNativePOSIX$3.class b/src/main/resources/jnr/posix/BaseNativePOSIX$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a9550d862a48b2f16582f9b0188505c0213a3bf
Binary files /dev/null and b/src/main/resources/jnr/posix/BaseNativePOSIX$3.class differ
diff --git a/src/main/resources/jnr/posix/BaseNativePOSIX$4.class b/src/main/resources/jnr/posix/BaseNativePOSIX$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..49d44f3bd33b73ab5264f36f0192ee3bbff3fe59
Binary files /dev/null and b/src/main/resources/jnr/posix/BaseNativePOSIX$4.class differ
diff --git a/src/main/resources/jnr/posix/BaseNativePOSIX$5.class b/src/main/resources/jnr/posix/BaseNativePOSIX$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..3aabb2af7455fdc78f3d75acb59d419b20369cdc
Binary files /dev/null and b/src/main/resources/jnr/posix/BaseNativePOSIX$5.class differ
diff --git a/src/main/resources/jnr/posix/BaseNativePOSIX$PointerConverter.class b/src/main/resources/jnr/posix/BaseNativePOSIX$PointerConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6d6fa968ea2b9305fc939b5b4406a7abd6e9cf7
Binary files /dev/null and b/src/main/resources/jnr/posix/BaseNativePOSIX$PointerConverter.class differ
diff --git a/src/main/resources/jnr/posix/BaseNativePOSIX.class b/src/main/resources/jnr/posix/BaseNativePOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..976d6677d2f7f00ea9cc91b5801f148d21c88018
Binary files /dev/null and b/src/main/resources/jnr/posix/BaseNativePOSIX.class differ
diff --git a/src/main/resources/jnr/posix/DefaultNativeGroup$Layout.class b/src/main/resources/jnr/posix/DefaultNativeGroup$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..fefd296604bd72ba907d186a5321bfac92dbcae9
Binary files /dev/null and b/src/main/resources/jnr/posix/DefaultNativeGroup$Layout.class differ
diff --git a/src/main/resources/jnr/posix/DefaultNativeGroup.class b/src/main/resources/jnr/posix/DefaultNativeGroup.class
new file mode 100644
index 0000000000000000000000000000000000000000..02841507e79f40d98f4bb2506c1d91d46c41e656
Binary files /dev/null and b/src/main/resources/jnr/posix/DefaultNativeGroup.class differ
diff --git a/src/main/resources/jnr/posix/DefaultNativeTimeval.class b/src/main/resources/jnr/posix/DefaultNativeTimeval.class
new file mode 100644
index 0000000000000000000000000000000000000000..291f0fddca10913d07784cbc1219595e0e255b1b
Binary files /dev/null and b/src/main/resources/jnr/posix/DefaultNativeTimeval.class differ
diff --git a/src/main/resources/jnr/posix/FileStat.class b/src/main/resources/jnr/posix/FileStat.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8504a92a2e26f4d77b08a5563bbbe8f18a71f22
Binary files /dev/null and b/src/main/resources/jnr/posix/FileStat.class differ
diff --git a/src/main/resources/jnr/posix/FileTime.class b/src/main/resources/jnr/posix/FileTime.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd5e3537690c5bac1d69d5d74d17732e6333b4fe
Binary files /dev/null and b/src/main/resources/jnr/posix/FileTime.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDFileStat$1.class b/src/main/resources/jnr/posix/FreeBSDFileStat$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb3d75237f84a1c64f6e8fc10667eb2c5bdaa9e1
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDFileStat$1.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDFileStat$Layout$dev_t.class b/src/main/resources/jnr/posix/FreeBSDFileStat$Layout$dev_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..9cbf13a3a449e152aa0499bd0d777653b2cc3efc
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDFileStat$Layout$dev_t.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDFileStat$Layout$time_t.class b/src/main/resources/jnr/posix/FreeBSDFileStat$Layout$time_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8be01ec05dc0d9cfe8525b165edaceda59be723
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDFileStat$Layout$time_t.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDFileStat$Layout.class b/src/main/resources/jnr/posix/FreeBSDFileStat$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..82590ba4a58574c3d7a40cd097f91124056fa296
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDFileStat$Layout.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDFileStat.class b/src/main/resources/jnr/posix/FreeBSDFileStat.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7f072c9db405a72d8c69e72e6d9e6b961c34f5b
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDFileStat.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDPOSIX$1.class b/src/main/resources/jnr/posix/FreeBSDPOSIX$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6905ad74994785e50eb81e1545ceb50161d65943
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDPOSIX$1.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDPOSIX.class b/src/main/resources/jnr/posix/FreeBSDPOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..c81d70c1d769029aadc0fafa92f1d02597386db1
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDPOSIX.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDPasswd$1.class b/src/main/resources/jnr/posix/FreeBSDPasswd$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbf73ce20dbe44016698b7a6a3716e16dae43ed4
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDPasswd$1.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDPasswd$Layout.class b/src/main/resources/jnr/posix/FreeBSDPasswd$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..d127a7686badc35a6c85efc49c19ffc81e47b3d3
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDPasswd$Layout.class differ
diff --git a/src/main/resources/jnr/posix/FreeBSDPasswd.class b/src/main/resources/jnr/posix/FreeBSDPasswd.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b53b121ff01915660ed3e29055d72c66d4a7c0e
Binary files /dev/null and b/src/main/resources/jnr/posix/FreeBSDPasswd.class differ
diff --git a/src/main/resources/jnr/posix/Group.class b/src/main/resources/jnr/posix/Group.class
new file mode 100644
index 0000000000000000000000000000000000000000..94c462b5dbae9b44fd43cecdc1787b1c4e17cef0
Binary files /dev/null and b/src/main/resources/jnr/posix/Group.class differ
diff --git a/src/main/resources/jnr/posix/HANDLE$1.class b/src/main/resources/jnr/posix/HANDLE$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..70ee30d541f0644ea20e03b53d2fa3443a8cd9d5
Binary files /dev/null and b/src/main/resources/jnr/posix/HANDLE$1.class differ
diff --git a/src/main/resources/jnr/posix/HANDLE.class b/src/main/resources/jnr/posix/HANDLE.class
new file mode 100644
index 0000000000000000000000000000000000000000..c56cc2d2f09ccdcef7f3dbb3ef9cedf3d0b51284
Binary files /dev/null and b/src/main/resources/jnr/posix/HANDLE.class differ
diff --git a/src/main/resources/jnr/posix/JavaFileStat.class b/src/main/resources/jnr/posix/JavaFileStat.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2dd49f3a361b268a3a82e354cc5d7a3111381f5
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaFileStat.class differ
diff --git a/src/main/resources/jnr/posix/JavaLibCHelper$1.class b/src/main/resources/jnr/posix/JavaLibCHelper$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..45dd8248dce92ea63d8637adcd4ddc542c0f5410
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaLibCHelper$1.class differ
diff --git a/src/main/resources/jnr/posix/JavaLibCHelper$ErrnoParsingOutputStream.class b/src/main/resources/jnr/posix/JavaLibCHelper$ErrnoParsingOutputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..64e6fdfc2324769f80d415f045de977f1c1026b6
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaLibCHelper$ErrnoParsingOutputStream.class differ
diff --git a/src/main/resources/jnr/posix/JavaLibCHelper$PosixExec.class b/src/main/resources/jnr/posix/JavaLibCHelper$PosixExec.class
new file mode 100644
index 0000000000000000000000000000000000000000..c999456e21a3987d87f6e815f9e87ce61d2a4fb7
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaLibCHelper$PosixExec.class differ
diff --git a/src/main/resources/jnr/posix/JavaLibCHelper.class b/src/main/resources/jnr/posix/JavaLibCHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..70a982ee6cc18b6f7e53cc28417576c5ba720f6a
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaLibCHelper.class differ
diff --git a/src/main/resources/jnr/posix/JavaPOSIX$1.class b/src/main/resources/jnr/posix/JavaPOSIX$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6a765b4478b41cff2a7ab81143fb3c4f4ae1d4d
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaPOSIX$1.class differ
diff --git a/src/main/resources/jnr/posix/JavaPOSIX$FakePasswd.class b/src/main/resources/jnr/posix/JavaPOSIX$FakePasswd.class
new file mode 100644
index 0000000000000000000000000000000000000000..16aff6d227d0b6d1fc0ca54e12230902ce3503a1
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaPOSIX$FakePasswd.class differ
diff --git a/src/main/resources/jnr/posix/JavaPOSIX$IDHelper.class b/src/main/resources/jnr/posix/JavaPOSIX$IDHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..86dd17bb8c7a4845176cc361f9e84b16ee85c5ca
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaPOSIX$IDHelper.class differ
diff --git a/src/main/resources/jnr/posix/JavaPOSIX$LoginInfo.class b/src/main/resources/jnr/posix/JavaPOSIX$LoginInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..342ef3838da3f6658920aaa346a2fd246aa359bb
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaPOSIX$LoginInfo.class differ
diff --git a/src/main/resources/jnr/posix/JavaPOSIX.class b/src/main/resources/jnr/posix/JavaPOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc7630dbf0148145dff1c10b9898980211e478c7
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaPOSIX.class differ
diff --git a/src/main/resources/jnr/posix/JavaPasswd.class b/src/main/resources/jnr/posix/JavaPasswd.class
new file mode 100644
index 0000000000000000000000000000000000000000..fee95a9ae41abe9834ed6a37df792fa1a2610e15
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaPasswd.class differ
diff --git a/src/main/resources/jnr/posix/JavaSecuredFile.class b/src/main/resources/jnr/posix/JavaSecuredFile.class
new file mode 100644
index 0000000000000000000000000000000000000000..e221895a05d29b4469cdcefc668e6d91afe3f17a
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaSecuredFile.class differ
diff --git a/src/main/resources/jnr/posix/JavaTimes.class b/src/main/resources/jnr/posix/JavaTimes.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b0e4d25d21209958b4642dd8de3876bd7aa336e
Binary files /dev/null and b/src/main/resources/jnr/posix/JavaTimes.class differ
diff --git a/src/main/resources/jnr/posix/LazyPOSIX.class b/src/main/resources/jnr/posix/LazyPOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..667d69022641ba1557956a49886cb4ff363a0481
Binary files /dev/null and b/src/main/resources/jnr/posix/LazyPOSIX.class differ
diff --git a/src/main/resources/jnr/posix/LibC.class b/src/main/resources/jnr/posix/LibC.class
new file mode 100644
index 0000000000000000000000000000000000000000..fac439c2b7a6e289ba850fe071883f64a2d706e8
Binary files /dev/null and b/src/main/resources/jnr/posix/LibC.class differ
diff --git a/src/main/resources/jnr/posix/LibCProvider.class b/src/main/resources/jnr/posix/LibCProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b5956e8e4cf603e8850c6ca3598da392cb1de1c
Binary files /dev/null and b/src/main/resources/jnr/posix/LibCProvider.class differ
diff --git a/src/main/resources/jnr/posix/LinuxFileStat32$1.class b/src/main/resources/jnr/posix/LinuxFileStat32$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f37f56289a0931882134de04b25cba5af8856016
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxFileStat32$1.class differ
diff --git a/src/main/resources/jnr/posix/LinuxFileStat32$Layout.class b/src/main/resources/jnr/posix/LinuxFileStat32$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..220c1062b131be55e299effc351a45e20f67b835
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxFileStat32$Layout.class differ
diff --git a/src/main/resources/jnr/posix/LinuxFileStat32.class b/src/main/resources/jnr/posix/LinuxFileStat32.class
new file mode 100644
index 0000000000000000000000000000000000000000..561ecda593c1c076a0ba6d677a38b92f9d9e773a
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxFileStat32.class differ
diff --git a/src/main/resources/jnr/posix/LinuxFileStat64$Layout.class b/src/main/resources/jnr/posix/LinuxFileStat64$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..cbf4457c7b8574773b57df0561074d68a40180ac
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxFileStat64$Layout.class differ
diff --git a/src/main/resources/jnr/posix/LinuxFileStat64.class b/src/main/resources/jnr/posix/LinuxFileStat64.class
new file mode 100644
index 0000000000000000000000000000000000000000..819d3e0cf0d1e9d9e44f16e5f65f4206d2894bc1
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxFileStat64.class differ
diff --git a/src/main/resources/jnr/posix/LinuxLibC.class b/src/main/resources/jnr/posix/LinuxLibC.class
new file mode 100644
index 0000000000000000000000000000000000000000..66a1dc8c1aae81f3436a3215240feff722373906
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxLibC.class differ
diff --git a/src/main/resources/jnr/posix/LinuxPOSIX$1.class b/src/main/resources/jnr/posix/LinuxPOSIX$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..be0d321a838cb1bd1abfca544c3de07012b368f9
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxPOSIX$1.class differ
diff --git a/src/main/resources/jnr/posix/LinuxPOSIX.class b/src/main/resources/jnr/posix/LinuxPOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..291905346000ceefbc92bc17a53c6a9f987f4004
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxPOSIX.class differ
diff --git a/src/main/resources/jnr/posix/LinuxPasswd$1.class b/src/main/resources/jnr/posix/LinuxPasswd$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f78e128ff069d370d55add144f3adbedc37423d8
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxPasswd$1.class differ
diff --git a/src/main/resources/jnr/posix/LinuxPasswd$Layout.class b/src/main/resources/jnr/posix/LinuxPasswd$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..36427ef33dd3cd0a486b17ae1f55c000a9f311fb
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxPasswd$Layout.class differ
diff --git a/src/main/resources/jnr/posix/LinuxPasswd.class b/src/main/resources/jnr/posix/LinuxPasswd.class
new file mode 100644
index 0000000000000000000000000000000000000000..ada83e7f30aed0e98177339e712a25a325f56d13
Binary files /dev/null and b/src/main/resources/jnr/posix/LinuxPasswd.class differ
diff --git a/src/main/resources/jnr/posix/MacOSFileStat$Layout$time_t.class b/src/main/resources/jnr/posix/MacOSFileStat$Layout$time_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2d920657e197defedc187a5fe39a6d9b30257a5
Binary files /dev/null and b/src/main/resources/jnr/posix/MacOSFileStat$Layout$time_t.class differ
diff --git a/src/main/resources/jnr/posix/MacOSFileStat$Layout.class b/src/main/resources/jnr/posix/MacOSFileStat$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4526c643d297a28db2a877da32308fb57f6e4c9
Binary files /dev/null and b/src/main/resources/jnr/posix/MacOSFileStat$Layout.class differ
diff --git a/src/main/resources/jnr/posix/MacOSFileStat.class b/src/main/resources/jnr/posix/MacOSFileStat.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8246b2af61cc34d0f0d3a7e896884613ec00c3c
Binary files /dev/null and b/src/main/resources/jnr/posix/MacOSFileStat.class differ
diff --git a/src/main/resources/jnr/posix/MacOSPOSIX$1.class b/src/main/resources/jnr/posix/MacOSPOSIX$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e96a0b8bd0e7384b8b56aa2462f199e5cad2b428
Binary files /dev/null and b/src/main/resources/jnr/posix/MacOSPOSIX$1.class differ
diff --git a/src/main/resources/jnr/posix/MacOSPOSIX.class b/src/main/resources/jnr/posix/MacOSPOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..0537175694816eff0c62f76ab27fe96eda5ed915
Binary files /dev/null and b/src/main/resources/jnr/posix/MacOSPOSIX.class differ
diff --git a/src/main/resources/jnr/posix/MacOSPasswd$1.class b/src/main/resources/jnr/posix/MacOSPasswd$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..74f577e33a204d1805af266bf2c0d0774422509d
Binary files /dev/null and b/src/main/resources/jnr/posix/MacOSPasswd$1.class differ
diff --git a/src/main/resources/jnr/posix/MacOSPasswd$Layout.class b/src/main/resources/jnr/posix/MacOSPasswd$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca143bf3d326e9e8432dd7fb7f8e0da3c2803933
Binary files /dev/null and b/src/main/resources/jnr/posix/MacOSPasswd$Layout.class differ
diff --git a/src/main/resources/jnr/posix/MacOSPasswd.class b/src/main/resources/jnr/posix/MacOSPasswd.class
new file mode 100644
index 0000000000000000000000000000000000000000..d99d0d635c9f13ab7fdde04bd01288bbe2e41295
Binary files /dev/null and b/src/main/resources/jnr/posix/MacOSPasswd.class differ
diff --git a/src/main/resources/jnr/posix/NativeGroup.class b/src/main/resources/jnr/posix/NativeGroup.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f015b008998fdb22d8bda9597d9107f7fbc2954
Binary files /dev/null and b/src/main/resources/jnr/posix/NativeGroup.class differ
diff --git a/src/main/resources/jnr/posix/NativePOSIX.class b/src/main/resources/jnr/posix/NativePOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..391d1df78d7b811d578996b7470f0b78768206e4
Binary files /dev/null and b/src/main/resources/jnr/posix/NativePOSIX.class differ
diff --git a/src/main/resources/jnr/posix/NativePasswd.class b/src/main/resources/jnr/posix/NativePasswd.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5aaf9d92f8518acf41e130eea0ece849039fdea
Binary files /dev/null and b/src/main/resources/jnr/posix/NativePasswd.class differ
diff --git a/src/main/resources/jnr/posix/NativeTimes$Layout.class b/src/main/resources/jnr/posix/NativeTimes$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ebfb74f56e559f88e709c53cc2b18841889dbe1
Binary files /dev/null and b/src/main/resources/jnr/posix/NativeTimes$Layout.class differ
diff --git a/src/main/resources/jnr/posix/NativeTimes.class b/src/main/resources/jnr/posix/NativeTimes.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3e38fcd9f7abe96a54142a3636bb8233b6cb4d6
Binary files /dev/null and b/src/main/resources/jnr/posix/NativeTimes.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDFileStat$1.class b/src/main/resources/jnr/posix/OpenBSDFileStat$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f27acae9bcfef391002393b9c50c6af4890199b1
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDFileStat$1.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDFileStat$Layout$dev_t.class b/src/main/resources/jnr/posix/OpenBSDFileStat$Layout$dev_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ad20988902c03d17bd06162a69cc9f9bcaec6c5
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDFileStat$Layout$dev_t.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDFileStat$Layout$time_t.class b/src/main/resources/jnr/posix/OpenBSDFileStat$Layout$time_t.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0488b92d0a6a6b7fbd341633a7b69cf16b4d20b
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDFileStat$Layout$time_t.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDFileStat$Layout.class b/src/main/resources/jnr/posix/OpenBSDFileStat$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a824d68992ff19ea86cd732333c8e198f1e83c7
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDFileStat$Layout.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDFileStat.class b/src/main/resources/jnr/posix/OpenBSDFileStat.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f0472c17050a3878b4e347d2eef0915ab2a7904
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDFileStat.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDPOSIX$1.class b/src/main/resources/jnr/posix/OpenBSDPOSIX$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ae9ca64cbb017cbe6f43a379ce77ef8d4165737
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDPOSIX$1.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDPOSIX.class b/src/main/resources/jnr/posix/OpenBSDPOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..d31a4cebdd12a8018362cb75f78507efb316779a
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDPOSIX.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDPasswd$1.class b/src/main/resources/jnr/posix/OpenBSDPasswd$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..384565e1a404ffc9df06d1a495dcc0f3c0fd98b8
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDPasswd$1.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDPasswd$Layout.class b/src/main/resources/jnr/posix/OpenBSDPasswd$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..d16bf2aadc590dd47b7d1d9e2044713ab53537fd
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDPasswd$Layout.class differ
diff --git a/src/main/resources/jnr/posix/OpenBSDPasswd.class b/src/main/resources/jnr/posix/OpenBSDPasswd.class
new file mode 100644
index 0000000000000000000000000000000000000000..a137b84272b86c3403b5dc14ca259002bbb3bb77
Binary files /dev/null and b/src/main/resources/jnr/posix/OpenBSDPasswd.class differ
diff --git a/src/main/resources/jnr/posix/POSIX.class b/src/main/resources/jnr/posix/POSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca6ca5fa35abe98529c5432b5a15a924f916cc81
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIX.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$1.class b/src/main/resources/jnr/posix/POSIXFactory$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b8034a7629b85ceb5a08d187ada1dd38d3889e4
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$1.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$DefaultLibCProvider$SingletonHolder.class b/src/main/resources/jnr/posix/POSIXFactory$DefaultLibCProvider$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d4d3348af81fe8b11ef599b8e7a2dca52b40df8
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$DefaultLibCProvider$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$DefaultLibCProvider.class b/src/main/resources/jnr/posix/POSIXFactory$DefaultLibCProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..468be323a75526f585c01c2c399e7b804aab300f
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$DefaultLibCProvider.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$LinuxLibCProvider$SingletonHolder.class b/src/main/resources/jnr/posix/POSIXFactory$LinuxLibCProvider$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..8da329155d3a79ff5819cad008746bc8199635be
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$LinuxLibCProvider$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$LinuxLibCProvider.class b/src/main/resources/jnr/posix/POSIXFactory$LinuxLibCProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..afbc5eac04ad14116260eb650e6d0c302e51458c
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$LinuxLibCProvider.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$SolarisLibCProvider$SingletonHolder.class b/src/main/resources/jnr/posix/POSIXFactory$SolarisLibCProvider$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c7c3d54b9936db46c505083ccbd00aa9e29dde1
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$SolarisLibCProvider$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$SolarisLibCProvider.class b/src/main/resources/jnr/posix/POSIXFactory$SolarisLibCProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ba87f827b0b747e529c3f24eeb0e2b529ae972f
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$SolarisLibCProvider.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$WindowsLibCProvider$SingletonHolder.class b/src/main/resources/jnr/posix/POSIXFactory$WindowsLibCProvider$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..f60503c4e8de0923cd8fff86311e05814e00560c
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$WindowsLibCProvider$SingletonHolder.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory$WindowsLibCProvider.class b/src/main/resources/jnr/posix/POSIXFactory$WindowsLibCProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ae9c4a43a18cc337fec8b2a8d7f61a0772a350c
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory$WindowsLibCProvider.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFactory.class b/src/main/resources/jnr/posix/POSIXFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e1262bffc721a3b37c5905b13e415630ecd1380
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFactory.class differ
diff --git a/src/main/resources/jnr/posix/POSIXFunctionMapper.class b/src/main/resources/jnr/posix/POSIXFunctionMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec0022d1776e84e3e5bc672f3ec7460038b068dc
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXFunctionMapper.class differ
diff --git a/src/main/resources/jnr/posix/POSIXHandler$WARNING_ID.class b/src/main/resources/jnr/posix/POSIXHandler$WARNING_ID.class
new file mode 100644
index 0000000000000000000000000000000000000000..5fbbbe399d9c6e33305cbe937b0f50875138c8a6
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXHandler$WARNING_ID.class differ
diff --git a/src/main/resources/jnr/posix/POSIXHandler.class b/src/main/resources/jnr/posix/POSIXHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..24e048070ac5cb4a8e8a500714a4c124b5b0e30a
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXHandler.class differ
diff --git a/src/main/resources/jnr/posix/POSIXTypeMapper.class b/src/main/resources/jnr/posix/POSIXTypeMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..65b356b188e9aefc8684136dcc30fd4d305f576f
Binary files /dev/null and b/src/main/resources/jnr/posix/POSIXTypeMapper.class differ
diff --git a/src/main/resources/jnr/posix/Passwd.class b/src/main/resources/jnr/posix/Passwd.class
new file mode 100644
index 0000000000000000000000000000000000000000..83c8593755e991bb33b7ec5d85e910bc6726a6fb
Binary files /dev/null and b/src/main/resources/jnr/posix/Passwd.class differ
diff --git a/src/main/resources/jnr/posix/SolarisFileStat32$Layout.class b/src/main/resources/jnr/posix/SolarisFileStat32$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..d1befe6ad274f47d465d7b565d17542ddad04fb9
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisFileStat32$Layout.class differ
diff --git a/src/main/resources/jnr/posix/SolarisFileStat32.class b/src/main/resources/jnr/posix/SolarisFileStat32.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b0256e1ee8560c82eeec069ff38b0f9806b6bcc
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisFileStat32.class differ
diff --git a/src/main/resources/jnr/posix/SolarisFileStat64$Layout.class b/src/main/resources/jnr/posix/SolarisFileStat64$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0040ceb71233d61ad7bba229c7ed72e9c32252c
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisFileStat64$Layout.class differ
diff --git a/src/main/resources/jnr/posix/SolarisFileStat64.class b/src/main/resources/jnr/posix/SolarisFileStat64.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bbf87676af068771decfc8b3383ef608d929e28
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisFileStat64.class differ
diff --git a/src/main/resources/jnr/posix/SolarisLibC.class b/src/main/resources/jnr/posix/SolarisLibC.class
new file mode 100644
index 0000000000000000000000000000000000000000..86ff1592e749e2e98a955cf4ee7ae3b464019be3
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisLibC.class differ
diff --git a/src/main/resources/jnr/posix/SolarisPOSIX$1.class b/src/main/resources/jnr/posix/SolarisPOSIX$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d74930b1a9ff54f1aaeb090b171738caf55af9d
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisPOSIX$1.class differ
diff --git a/src/main/resources/jnr/posix/SolarisPOSIX.class b/src/main/resources/jnr/posix/SolarisPOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..451e1dadbda9a39acb1a7518f6e0ce21e42a4014
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisPOSIX.class differ
diff --git a/src/main/resources/jnr/posix/SolarisPasswd$1.class b/src/main/resources/jnr/posix/SolarisPasswd$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce5765fb16b7875176449811d9ec1b8e26e64fde
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisPasswd$1.class differ
diff --git a/src/main/resources/jnr/posix/SolarisPasswd$Layout.class b/src/main/resources/jnr/posix/SolarisPasswd$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..0172878720a23bcfe110b44bd918ebbadbf42f80
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisPasswd$Layout.class differ
diff --git a/src/main/resources/jnr/posix/SolarisPasswd.class b/src/main/resources/jnr/posix/SolarisPasswd.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a9ac468eefd046d8f0c4c69bb1dbaa2d718727e
Binary files /dev/null and b/src/main/resources/jnr/posix/SolarisPasswd.class differ
diff --git a/src/main/resources/jnr/posix/SpawnFileAction$Close.class b/src/main/resources/jnr/posix/SpawnFileAction$Close.class
new file mode 100644
index 0000000000000000000000000000000000000000..4db96f648fc75db97810bda6ac459c691e88cb80
Binary files /dev/null and b/src/main/resources/jnr/posix/SpawnFileAction$Close.class differ
diff --git a/src/main/resources/jnr/posix/SpawnFileAction$Dup.class b/src/main/resources/jnr/posix/SpawnFileAction$Dup.class
new file mode 100644
index 0000000000000000000000000000000000000000..f563bebe79051ad5c56640b2958f524827c2d4c9
Binary files /dev/null and b/src/main/resources/jnr/posix/SpawnFileAction$Dup.class differ
diff --git a/src/main/resources/jnr/posix/SpawnFileAction$Open.class b/src/main/resources/jnr/posix/SpawnFileAction$Open.class
new file mode 100644
index 0000000000000000000000000000000000000000..87b5af2cd12e3146c5d191ca258acc81a795dccb
Binary files /dev/null and b/src/main/resources/jnr/posix/SpawnFileAction$Open.class differ
diff --git a/src/main/resources/jnr/posix/SpawnFileAction.class b/src/main/resources/jnr/posix/SpawnFileAction.class
new file mode 100644
index 0000000000000000000000000000000000000000..2485096624c4dbdaf503196ef6f421d065e5c795
Binary files /dev/null and b/src/main/resources/jnr/posix/SpawnFileAction.class differ
diff --git a/src/main/resources/jnr/posix/Times.class b/src/main/resources/jnr/posix/Times.class
new file mode 100644
index 0000000000000000000000000000000000000000..df302e20bc1c94baf07c2e1ca5050502a57702e1
Binary files /dev/null and b/src/main/resources/jnr/posix/Times.class differ
diff --git a/src/main/resources/jnr/posix/Timeval.class b/src/main/resources/jnr/posix/Timeval.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8408a90af443bf7140953a0524a605640c3d4d9
Binary files /dev/null and b/src/main/resources/jnr/posix/Timeval.class differ
diff --git a/src/main/resources/jnr/posix/UTimBuf64.class b/src/main/resources/jnr/posix/UTimBuf64.class
new file mode 100644
index 0000000000000000000000000000000000000000..8eef0e76e7788d9e6428289c5ab93615fa111a35
Binary files /dev/null and b/src/main/resources/jnr/posix/UTimBuf64.class differ
diff --git a/src/main/resources/jnr/posix/UnixLibC.class b/src/main/resources/jnr/posix/UnixLibC.class
new file mode 100644
index 0000000000000000000000000000000000000000..64929615d34b969e973f738da77fda239b6653c0
Binary files /dev/null and b/src/main/resources/jnr/posix/UnixLibC.class differ
diff --git a/src/main/resources/jnr/posix/WString$1.class b/src/main/resources/jnr/posix/WString$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ba887d7f946edfd861a7018b1c5e43af7d0d46c
Binary files /dev/null and b/src/main/resources/jnr/posix/WString$1.class differ
diff --git a/src/main/resources/jnr/posix/WString.class b/src/main/resources/jnr/posix/WString.class
new file mode 100644
index 0000000000000000000000000000000000000000..896cec3cd8df5d9ca7539cf5def21a35e2a31582
Binary files /dev/null and b/src/main/resources/jnr/posix/WString.class differ
diff --git a/src/main/resources/jnr/posix/WindowsChildRecord.class b/src/main/resources/jnr/posix/WindowsChildRecord.class
new file mode 100644
index 0000000000000000000000000000000000000000..174649a4a48c3fd4e82de8e1b3f188db1d46f177
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsChildRecord.class differ
diff --git a/src/main/resources/jnr/posix/WindowsFileStat$1.class b/src/main/resources/jnr/posix/WindowsFileStat$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c0455fe043f269dd7d9df0aa91a94e52a4d2cd0
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsFileStat$1.class differ
diff --git a/src/main/resources/jnr/posix/WindowsFileStat$Layout.class b/src/main/resources/jnr/posix/WindowsFileStat$Layout.class
new file mode 100644
index 0000000000000000000000000000000000000000..151e11009d6d47607d09f71f36992c0c19f1f578
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsFileStat$Layout.class differ
diff --git a/src/main/resources/jnr/posix/WindowsFileStat.class b/src/main/resources/jnr/posix/WindowsFileStat.class
new file mode 100644
index 0000000000000000000000000000000000000000..b295fd60297df13c6c1bb35a3c291e91fec01fef
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsFileStat.class differ
diff --git a/src/main/resources/jnr/posix/WindowsLibC.class b/src/main/resources/jnr/posix/WindowsLibC.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8ff0dd04ecfa9f4bccca3d25a67a9c11f71d4c5
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsLibC.class differ
diff --git a/src/main/resources/jnr/posix/WindowsLibCFunctionMapper.class b/src/main/resources/jnr/posix/WindowsLibCFunctionMapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..56abc443308ebb33e01996cab2510ecf28e34eb7
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsLibCFunctionMapper.class differ
diff --git a/src/main/resources/jnr/posix/WindowsPOSIX$1.class b/src/main/resources/jnr/posix/WindowsPOSIX$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..100ae705803e65ca96c3a31d0f8fe98f24debbc1
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsPOSIX$1.class differ
diff --git a/src/main/resources/jnr/posix/WindowsPOSIX.class b/src/main/resources/jnr/posix/WindowsPOSIX.class
new file mode 100644
index 0000000000000000000000000000000000000000..d785319cac8f6a1d220e38172db484c2cd768fd4
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsPOSIX.class differ
diff --git a/src/main/resources/jnr/posix/WindowsProcessInformation.class b/src/main/resources/jnr/posix/WindowsProcessInformation.class
new file mode 100644
index 0000000000000000000000000000000000000000..30816a6a074744c54493a29d7dde71e41c37285b
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsProcessInformation.class differ
diff --git a/src/main/resources/jnr/posix/WindowsSecurityAttributes.class b/src/main/resources/jnr/posix/WindowsSecurityAttributes.class
new file mode 100644
index 0000000000000000000000000000000000000000..642fcafc5333efe30a5650505e9f062e50d3a607
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsSecurityAttributes.class differ
diff --git a/src/main/resources/jnr/posix/WindowsStartupInfo.class b/src/main/resources/jnr/posix/WindowsStartupInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..7833931542124632b524849542b2fcb4fb51eab6
Binary files /dev/null and b/src/main/resources/jnr/posix/WindowsStartupInfo.class differ
diff --git a/src/main/resources/jnr/posix/util/Chmod.class b/src/main/resources/jnr/posix/util/Chmod.class
new file mode 100644
index 0000000000000000000000000000000000000000..fdac52a7568bbf0a1368c231653e91289594d73f
Binary files /dev/null and b/src/main/resources/jnr/posix/util/Chmod.class differ
diff --git a/src/main/resources/jnr/posix/util/DefaultPOSIXHandler.class b/src/main/resources/jnr/posix/util/DefaultPOSIXHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..478bd13793d4c5bdc94a1877413b5c2ba0fefe13
Binary files /dev/null and b/src/main/resources/jnr/posix/util/DefaultPOSIXHandler.class differ
diff --git a/src/main/resources/jnr/posix/util/ExecIt$StreamPumper.class b/src/main/resources/jnr/posix/util/ExecIt$StreamPumper.class
new file mode 100644
index 0000000000000000000000000000000000000000..3dc23e6716b2a5527811c9af9e81154e462021bf
Binary files /dev/null and b/src/main/resources/jnr/posix/util/ExecIt$StreamPumper.class differ
diff --git a/src/main/resources/jnr/posix/util/ExecIt.class b/src/main/resources/jnr/posix/util/ExecIt.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a24edb0dd08429da76dede4c1bee2f6c1ebeeee
Binary files /dev/null and b/src/main/resources/jnr/posix/util/ExecIt.class differ
diff --git a/src/main/resources/jnr/posix/util/FieldAccess.class b/src/main/resources/jnr/posix/util/FieldAccess.class
new file mode 100644
index 0000000000000000000000000000000000000000..39b3fef5039b529150d4d9a2144c419bcef5dbb0
Binary files /dev/null and b/src/main/resources/jnr/posix/util/FieldAccess.class differ
diff --git a/src/main/resources/jnr/posix/util/Finder.class b/src/main/resources/jnr/posix/util/Finder.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fddfd1ab3d523a9d266399883b7977a664cc2d2
Binary files /dev/null and b/src/main/resources/jnr/posix/util/Finder.class differ
diff --git a/src/main/resources/jnr/posix/util/Java5ProcessMaker.class b/src/main/resources/jnr/posix/util/Java5ProcessMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4193dab71ce1e00e8ea77c1cb1856d0565bd891
Binary files /dev/null and b/src/main/resources/jnr/posix/util/Java5ProcessMaker.class differ
diff --git a/src/main/resources/jnr/posix/util/Platform.class b/src/main/resources/jnr/posix/util/Platform.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e42c9557dea3de303176270aa54e56158a85e9a
Binary files /dev/null and b/src/main/resources/jnr/posix/util/Platform.class differ
diff --git a/src/main/resources/jnr/posix/util/ProcessMaker$Redirect$Type.class b/src/main/resources/jnr/posix/util/ProcessMaker$Redirect$Type.class
new file mode 100644
index 0000000000000000000000000000000000000000..928bc578b07e35dd84c89e2c12f42a61efbb93e4
Binary files /dev/null and b/src/main/resources/jnr/posix/util/ProcessMaker$Redirect$Type.class differ
diff --git a/src/main/resources/jnr/posix/util/ProcessMaker$Redirect.class b/src/main/resources/jnr/posix/util/ProcessMaker$Redirect.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc6525e583626f599806b87ff325535ee791627c
Binary files /dev/null and b/src/main/resources/jnr/posix/util/ProcessMaker$Redirect.class differ
diff --git a/src/main/resources/jnr/posix/util/ProcessMaker.class b/src/main/resources/jnr/posix/util/ProcessMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..7456b56283563a38040e7e83ecd7a0ae7290ece6
Binary files /dev/null and b/src/main/resources/jnr/posix/util/ProcessMaker.class differ
diff --git a/src/main/resources/jnr/posix/util/WindowsHelpers$1.class b/src/main/resources/jnr/posix/util/WindowsHelpers$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d46522ba6e2dcf4c87d1c36be5a18bee5216da72
Binary files /dev/null and b/src/main/resources/jnr/posix/util/WindowsHelpers$1.class differ
diff --git a/src/main/resources/jnr/posix/util/WindowsHelpers$InternalType.class b/src/main/resources/jnr/posix/util/WindowsHelpers$InternalType.class
new file mode 100644
index 0000000000000000000000000000000000000000..9743b041280b783742174854053e636beb9916f8
Binary files /dev/null and b/src/main/resources/jnr/posix/util/WindowsHelpers$InternalType.class differ
diff --git a/src/main/resources/jnr/posix/util/WindowsHelpers.class b/src/main/resources/jnr/posix/util/WindowsHelpers.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6d510934c8b2227a27d43430daf6a441c6d90dc
Binary files /dev/null and b/src/main/resources/jnr/posix/util/WindowsHelpers.class differ
diff --git a/src/main/resources/org/apache/xmlcommons/Version.class b/src/main/resources/org/apache/xmlcommons/Version.class
new file mode 100644
index 0000000000000000000000000000000000000000..898d3ea24cb5f16424c0be6e3eaaad01e8467257
Binary files /dev/null and b/src/main/resources/org/apache/xmlcommons/Version.class differ
diff --git a/src/main/resources/org/python/Version.class b/src/main/resources/org/python/Version.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee077be66e488331477d84050f28f174f8a06930
Binary files /dev/null and b/src/main/resources/org/python/Version.class differ
diff --git a/src/main/resources/org/python/antlr/AST$PyExposer.class b/src/main/resources/org/python/antlr/AST$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e415bdcf46f244a778a4e5a0a766b321cab789eb
Binary files /dev/null and b/src/main/resources/org/python/antlr/AST$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/AST.class b/src/main/resources/org/python/antlr/AST.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea5356cf14960c05e9eb7871d1ee2b6e28d323f6
Binary files /dev/null and b/src/main/resources/org/python/antlr/AST.class differ
diff --git a/src/main/resources/org/python/antlr/AnalyzingParser$AnalyzerTreeAdaptor.class b/src/main/resources/org/python/antlr/AnalyzingParser$AnalyzerTreeAdaptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e475954f471891c60b566bd9a6bad5877d569991
Binary files /dev/null and b/src/main/resources/org/python/antlr/AnalyzingParser$AnalyzerTreeAdaptor.class differ
diff --git a/src/main/resources/org/python/antlr/AnalyzingParser.class b/src/main/resources/org/python/antlr/AnalyzingParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a0815f2d599bf48c3fd3f51388eaf1cb9f79d91
Binary files /dev/null and b/src/main/resources/org/python/antlr/AnalyzingParser.class differ
diff --git a/src/main/resources/org/python/antlr/BaseParser.class b/src/main/resources/org/python/antlr/BaseParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..ebb7b5f9f3aebbfaa8291216600478dd7472f2a7
Binary files /dev/null and b/src/main/resources/org/python/antlr/BaseParser.class differ
diff --git a/src/main/resources/org/python/antlr/ErrorHandler.class b/src/main/resources/org/python/antlr/ErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..38de33a7292b326deaf8c85fef8d65cb2c2725ab
Binary files /dev/null and b/src/main/resources/org/python/antlr/ErrorHandler.class differ
diff --git a/src/main/resources/org/python/antlr/FailFastHandler.class b/src/main/resources/org/python/antlr/FailFastHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..726a1e4034a960d37f34e8012303e3d29195c754
Binary files /dev/null and b/src/main/resources/org/python/antlr/FailFastHandler.class differ
diff --git a/src/main/resources/org/python/antlr/GrammarActions$StringPair.class b/src/main/resources/org/python/antlr/GrammarActions$StringPair.class
new file mode 100644
index 0000000000000000000000000000000000000000..e768602657e6a221cce5fd573f1fe27aefb0c646
Binary files /dev/null and b/src/main/resources/org/python/antlr/GrammarActions$StringPair.class differ
diff --git a/src/main/resources/org/python/antlr/GrammarActions.class b/src/main/resources/org/python/antlr/GrammarActions.class
new file mode 100644
index 0000000000000000000000000000000000000000..af4052f857aaacebd11e0d5c1d307a69c6c3db8f
Binary files /dev/null and b/src/main/resources/org/python/antlr/GrammarActions.class differ
diff --git a/src/main/resources/org/python/antlr/GrammarTester.class b/src/main/resources/org/python/antlr/GrammarTester.class
new file mode 100644
index 0000000000000000000000000000000000000000..995d87790c8c963ee7445a7776584208a15a1303
Binary files /dev/null and b/src/main/resources/org/python/antlr/GrammarTester.class differ
diff --git a/src/main/resources/org/python/antlr/ListErrorHandler.class b/src/main/resources/org/python/antlr/ListErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..4cbbf5a910d3c19f732ea1cb35136601bd76009a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ListErrorHandler.class differ
diff --git a/src/main/resources/org/python/antlr/NoCloseReaderStream.class b/src/main/resources/org/python/antlr/NoCloseReaderStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..2fe6f4fdbdeb9307d408b40be30355e2e1a6dc92
Binary files /dev/null and b/src/main/resources/org/python/antlr/NoCloseReaderStream.class differ
diff --git a/src/main/resources/org/python/antlr/ParseException.class b/src/main/resources/org/python/antlr/ParseException.class
new file mode 100644
index 0000000000000000000000000000000000000000..ffc92f91e695b897e4f35900ad9aa08e1265c5e9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ParseException.class differ
diff --git a/src/main/resources/org/python/antlr/PythonErrorNode.class b/src/main/resources/org/python/antlr/PythonErrorNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbc89ec0927cd3432232fdf730d00424fc64c930
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonErrorNode.class differ
diff --git a/src/main/resources/org/python/antlr/PythonLexer$DFA14.class b/src/main/resources/org/python/antlr/PythonLexer$DFA14.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ed13ce5fc424023c9c3dbb40f74d678777fa356
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonLexer$DFA14.class differ
diff --git a/src/main/resources/org/python/antlr/PythonLexer$DFA17.class b/src/main/resources/org/python/antlr/PythonLexer$DFA17.class
new file mode 100644
index 0000000000000000000000000000000000000000..69731ca41e1a8031be81914e5f3cd1844218a5dd
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonLexer$DFA17.class differ
diff --git a/src/main/resources/org/python/antlr/PythonLexer$DFA45.class b/src/main/resources/org/python/antlr/PythonLexer$DFA45.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a4e8ce7becefbda8bb44262de8b6da8f0e24010
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonLexer$DFA45.class differ
diff --git a/src/main/resources/org/python/antlr/PythonLexer$DFA46.class b/src/main/resources/org/python/antlr/PythonLexer$DFA46.class
new file mode 100644
index 0000000000000000000000000000000000000000..68ef087e3e2867db3a598d7bbc7e0eff2775c33b
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonLexer$DFA46.class differ
diff --git a/src/main/resources/org/python/antlr/PythonLexer$DFA5.class b/src/main/resources/org/python/antlr/PythonLexer$DFA5.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a0323c537f3373e6803ec3e5d2bf4059eeee610
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonLexer$DFA5.class differ
diff --git a/src/main/resources/org/python/antlr/PythonLexer.class b/src/main/resources/org/python/antlr/PythonLexer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c2589863a5a3767eaa25cabfcce983e599d1524
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonLexer.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA112.class b/src/main/resources/org/python/antlr/PythonParser$DFA112.class
new file mode 100644
index 0000000000000000000000000000000000000000..af432cd09080336ac5a21269c64f6a2e078b31d4
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA112.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA116.class b/src/main/resources/org/python/antlr/PythonParser$DFA116.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e3071745c49c56bdb3eaae75fb85e940f57d41c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA116.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA129.class b/src/main/resources/org/python/antlr/PythonParser$DFA129.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ec04b31e89020db8c62642e272da5e7ad405257
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA129.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA131.class b/src/main/resources/org/python/antlr/PythonParser$DFA131.class
new file mode 100644
index 0000000000000000000000000000000000000000..dad99f4895b61ad43b791999eb106df86c4eb02e
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA131.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA133.class b/src/main/resources/org/python/antlr/PythonParser$DFA133.class
new file mode 100644
index 0000000000000000000000000000000000000000..e55ff975c1316f87372df32f6fb3350e68ca56bf
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA133.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA134.class b/src/main/resources/org/python/antlr/PythonParser$DFA134.class
new file mode 100644
index 0000000000000000000000000000000000000000..948b131793ca40c79fd658aade9872c6e891fdaa
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA134.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA136.class b/src/main/resources/org/python/antlr/PythonParser$DFA136.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e45666eccbcaee32876823cb1abf81b8bcf8196
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA136.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA138.class b/src/main/resources/org/python/antlr/PythonParser$DFA138.class
new file mode 100644
index 0000000000000000000000000000000000000000..3506e6eb232e58cc358b6392d9e4a7f9807ef1f4
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA138.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA139.class b/src/main/resources/org/python/antlr/PythonParser$DFA139.class
new file mode 100644
index 0000000000000000000000000000000000000000..2354c6d73d1e7c339dc3c032644fddcdcf0614d8
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA139.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA30.class b/src/main/resources/org/python/antlr/PythonParser$DFA30.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9f84664bd2d81d7633839f93edf3dee8189970c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA30.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA31.class b/src/main/resources/org/python/antlr/PythonParser$DFA31.class
new file mode 100644
index 0000000000000000000000000000000000000000..591ace25314932030df523b61542d90bc86247ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA31.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA35.class b/src/main/resources/org/python/antlr/PythonParser$DFA35.class
new file mode 100644
index 0000000000000000000000000000000000000000..d024d0f864336a92e81fcf8bd65197765db2e39b
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA35.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA38.class b/src/main/resources/org/python/antlr/PythonParser$DFA38.class
new file mode 100644
index 0000000000000000000000000000000000000000..b545a62fa192a6e36ee1eac8c15acb377068c56e
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA38.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA40.class b/src/main/resources/org/python/antlr/PythonParser$DFA40.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7f009cf114e6cb89b24b8b1205329ecb03545ed
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA40.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA41.class b/src/main/resources/org/python/antlr/PythonParser$DFA41.class
new file mode 100644
index 0000000000000000000000000000000000000000..062adf7e73bd81e3c2b1c7c108e7d8e67b56d27d
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA41.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA43.class b/src/main/resources/org/python/antlr/PythonParser$DFA43.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d23aac1e5574001584803d0e8a9d2fb836a718f
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA43.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA52.class b/src/main/resources/org/python/antlr/PythonParser$DFA52.class
new file mode 100644
index 0000000000000000000000000000000000000000..14410a931c194464df4fb15b69391168c1ec0246
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA52.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA80.class b/src/main/resources/org/python/antlr/PythonParser$DFA80.class
new file mode 100644
index 0000000000000000000000000000000000000000..494d554c3dc2f93ab54300d3e56cb461b942daf7
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA80.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$DFA89.class b/src/main/resources/org/python/antlr/PythonParser$DFA89.class
new file mode 100644
index 0000000000000000000000000000000000000000..d12f9467a44a745624b05f43ba119908823c6f27
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$DFA89.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$and_expr_return.class b/src/main/resources/org/python/antlr/PythonParser$and_expr_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb166f295fcc74c84e16df5d92ccd34c18f0dc86
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$and_expr_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$and_test_return.class b/src/main/resources/org/python/antlr/PythonParser$and_test_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..64973f6e2e0cdc9b2912ad9a29152c8e1017c64e
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$and_test_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$arglist_return.class b/src/main/resources/org/python/antlr/PythonParser$arglist_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..091f08fba0827bc85f9446a618c487e4975c99a1
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$arglist_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$argument_return.class b/src/main/resources/org/python/antlr/PythonParser$argument_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..efbab0d41952ace19a41db0c81d6147e19a8dda4
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$argument_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$arith_expr_return.class b/src/main/resources/org/python/antlr/PythonParser$arith_expr_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..80c7f1bc7e323939c801318a260e92be12e77b4d
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$arith_expr_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$arith_op_return.class b/src/main/resources/org/python/antlr/PythonParser$arith_op_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a560125813010f33959d52ce0d6bb92bbe148b4
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$arith_op_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$assert_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$assert_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce0bb4e228a2f4c6ba49447e3b1cafd750fc115d
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$assert_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$atom_return.class b/src/main/resources/org/python/antlr/PythonParser$atom_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..14e3f6e9bece9f8db85811e085719e2f1690bb17
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$atom_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$attr_return.class b/src/main/resources/org/python/antlr/PythonParser$attr_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ade506ba1a3b609bd7b44fe170a15c9778aafe5
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$attr_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$augassign_return.class b/src/main/resources/org/python/antlr/PythonParser$augassign_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..5409d3dd2a828f175b4f3f285322c983d4abe82a
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$augassign_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$break_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$break_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5a06c4c247d438b4f4c9dfc021349ce350f5138
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$break_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$classdef_return.class b/src/main/resources/org/python/antlr/PythonParser$classdef_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7b6527d077a03527413fc4576518c00c0a38451
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$classdef_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$comp_for_return.class b/src/main/resources/org/python/antlr/PythonParser$comp_for_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..b82b10163b06201fd0c7c6a0fc947eb7507ea79c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$comp_for_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$comp_if_return.class b/src/main/resources/org/python/antlr/PythonParser$comp_if_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..3331a30219b3a58c24831ad04235bdc766d29ec5
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$comp_if_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$comp_iter_return.class b/src/main/resources/org/python/antlr/PythonParser$comp_iter_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ff84649cfad9fee355fa24f7d67818a6971baef
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$comp_iter_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$comp_op_return.class b/src/main/resources/org/python/antlr/PythonParser$comp_op_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba81941c1f02698c089aa0325b87867484ef5098
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$comp_op_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$comparison_return.class b/src/main/resources/org/python/antlr/PythonParser$comparison_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..b25a170ca57854c80db5e82c317811dcfb2be48c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$comparison_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$compound_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$compound_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c50934d012bc2ec054fa82e9d6c315f06bfa6ed
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$compound_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$continue_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$continue_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bd2b60175749d09416a48c475abb2ec43acf354
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$continue_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$decorator_return.class b/src/main/resources/org/python/antlr/PythonParser$decorator_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..834414ab0bbf732e262123f0459d6c3df5b1b856
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$decorator_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$decorators_return.class b/src/main/resources/org/python/antlr/PythonParser$decorators_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..8520ac46fb7a15cf9e8257455808ea6bed34e27a
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$decorators_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$defparameter_return.class b/src/main/resources/org/python/antlr/PythonParser$defparameter_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..19569e58299770f6813223623a06c39478fe4172
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$defparameter_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$del_list_return.class b/src/main/resources/org/python/antlr/PythonParser$del_list_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef16d9633a389cea6fbe29f054371638f98d697a
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$del_list_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$del_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$del_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..e84203ec0980b7e7d12d7916570e7326d79da17c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$del_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$dictorsetmaker_return.class b/src/main/resources/org/python/antlr/PythonParser$dictorsetmaker_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0d3c1e42068da3126a5c3cb6293d07616868374
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$dictorsetmaker_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$dotted_as_name_return.class b/src/main/resources/org/python/antlr/PythonParser$dotted_as_name_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..d178d2b1aa3d7dae7b94a1e11075f322122b6997
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$dotted_as_name_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$dotted_as_names_return.class b/src/main/resources/org/python/antlr/PythonParser$dotted_as_names_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..65493aa089d2a91b178ed8198f4ae6e177427a03
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$dotted_as_names_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$dotted_attr_return.class b/src/main/resources/org/python/antlr/PythonParser$dotted_attr_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..76d681cbf2231924fba98e7a878ff82c59b372b8
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$dotted_attr_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$dotted_name_return.class b/src/main/resources/org/python/antlr/PythonParser$dotted_name_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..41bd9e898177009aa0ae14e474fb7ff79b4d02d3
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$dotted_name_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$elif_clause_return.class b/src/main/resources/org/python/antlr/PythonParser$elif_clause_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..df05ab2d567f5b858b9a38ff72b43087ac8d0184
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$elif_clause_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$else_clause_return.class b/src/main/resources/org/python/antlr/PythonParser$else_clause_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..c47df3ba605f7131cb93375768fed49205b757fd
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$else_clause_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$eval_input_return.class b/src/main/resources/org/python/antlr/PythonParser$eval_input_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f9f637f8f67316b7d06568dfd9d081a75bc9d5d
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$eval_input_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$except_clause_return.class b/src/main/resources/org/python/antlr/PythonParser$except_clause_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..a44220567f0d14b9b5c035dbec4b30f689325cf1
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$except_clause_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$exec_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$exec_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3b3f63d60f703c6499e7250574f43b49bf409ea
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$exec_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$expr_return.class b/src/main/resources/org/python/antlr/PythonParser$expr_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c78b26e20ee33cfdc9d25e851e05f78b6022623
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$expr_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$expr_scope.class b/src/main/resources/org/python/antlr/PythonParser$expr_scope.class
new file mode 100644
index 0000000000000000000000000000000000000000..1562c3791e46d8bc11c01000e9759b62f9d638f1
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$expr_scope.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$expr_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$expr_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3f633e115b2002c8f82959335347d39cb6496b3
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$expr_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$exprlist_return.class b/src/main/resources/org/python/antlr/PythonParser$exprlist_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..00ac671e7bb45e11847b68848fbd4c1a6bde5c6b
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$exprlist_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$factor_return.class b/src/main/resources/org/python/antlr/PythonParser$factor_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..5673dc2af88721b4def6cda08202570935c8146e
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$factor_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$file_input_return.class b/src/main/resources/org/python/antlr/PythonParser$file_input_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..be699dde49ef668a995533ea7b8f0a7b2c81a11d
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$file_input_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$flow_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$flow_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..34a52c06bc4989ba603d76e11d5ca2b73a7c61aa
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$flow_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$for_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$for_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee0f414ae613cd3e1d35ef907d76d4e39ca5bef2
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$for_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$fpdef_return.class b/src/main/resources/org/python/antlr/PythonParser$fpdef_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..010e8f1f1f889120cb6c1f0eb8d8161f331dff2b
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$fpdef_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$fplist_return.class b/src/main/resources/org/python/antlr/PythonParser$fplist_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fee9bdddcfc9b18107fcea299281ff8ecd41738
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$fplist_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$funcdef_return.class b/src/main/resources/org/python/antlr/PythonParser$funcdef_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..a24983ce38aef2a07af156af1d9179f393c3d211
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$funcdef_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$global_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$global_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e03985e6325a8f3699242da9e3be4a6395f138d
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$global_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$if_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$if_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..679cce60a86fd17d0f0e335b5c7fc91ba3e00ed5
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$if_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$import_as_name_return.class b/src/main/resources/org/python/antlr/PythonParser$import_as_name_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ac77399a7a5faed6551d527e2fb80ecb61d858c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$import_as_name_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$import_as_names_return.class b/src/main/resources/org/python/antlr/PythonParser$import_as_names_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..418a968b83b5e69e41ce144ac0cf72dde984199c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$import_as_names_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$import_from_return.class b/src/main/resources/org/python/antlr/PythonParser$import_from_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe6281712475ee883a0258a9fe54e8c6c373fa99
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$import_from_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$import_name_return.class b/src/main/resources/org/python/antlr/PythonParser$import_name_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8a5e4ca8efc1c3f11db5a198f3f95b614c838dd
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$import_name_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$import_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$import_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..b069ead664d8511621b9fbc8fbe34865e4420962
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$import_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$lambdef_return.class b/src/main/resources/org/python/antlr/PythonParser$lambdef_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..2aeeb83d4d0d5b670a6e4f9c1a86e7a383e9366c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$lambdef_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$list_for_return.class b/src/main/resources/org/python/antlr/PythonParser$list_for_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1a9caa50cf0d05b8722a57191ea508e23630ee2
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$list_for_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$list_if_return.class b/src/main/resources/org/python/antlr/PythonParser$list_if_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d70b261d7e38d17b860d6da2f957765c01004fd
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$list_if_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$list_iter_return.class b/src/main/resources/org/python/antlr/PythonParser$list_iter_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2c4c54acb04c04ccf545cf85dd82d61358f2ac3
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$list_iter_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$listmaker_return.class b/src/main/resources/org/python/antlr/PythonParser$listmaker_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..d25a8a64d687f3de1f9dc092b74ab9630a8747a7
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$listmaker_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$name_or_print_return.class b/src/main/resources/org/python/antlr/PythonParser$name_or_print_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..78e987af19ec466c55c6118c0833caa995cad108
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$name_or_print_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$not_test_return.class b/src/main/resources/org/python/antlr/PythonParser$not_test_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..a828491aee4fa0293375cb5957a2d069a327b3d3
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$not_test_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$or_test_return.class b/src/main/resources/org/python/antlr/PythonParser$or_test_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..308ab9172b123ded987af45599613466f858de3c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$or_test_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$parameters_return.class b/src/main/resources/org/python/antlr/PythonParser$parameters_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..112727e382537578a22f0830bc6c301c5cd161fc
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$parameters_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$pass_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$pass_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..a60412e6499a9e2783dd65c719573037efccde87
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$pass_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$power_return.class b/src/main/resources/org/python/antlr/PythonParser$power_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a09f659eae917fd6638f11d97972cf90f081837
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$power_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$print_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$print_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..14b18f5c6e717f5364dc987426e21ad5077e241b
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$print_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$printlist2_return.class b/src/main/resources/org/python/antlr/PythonParser$printlist2_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ca8732728257ad8f0f5ab8a75488af35d4647a6
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$printlist2_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$printlist_return.class b/src/main/resources/org/python/antlr/PythonParser$printlist_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a4acebf44aa56cc631b73795308c8aed58eee19
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$printlist_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$raise_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$raise_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..467706d6aa7effb191c955ac4c8f163a79aefa42
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$raise_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$return_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$return_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9ad4f1c184bcc1be5f65cebca132c2f4e2bfddd
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$return_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$shift_expr_return.class b/src/main/resources/org/python/antlr/PythonParser$shift_expr_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ac548bcf17597dd52de5641722ffa1de39acbd5
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$shift_expr_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$shift_op_return.class b/src/main/resources/org/python/antlr/PythonParser$shift_op_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..224d0560e2be13a6981f90a6f231e32f5e3ea072
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$shift_op_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$simple_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$simple_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc742ba0e23267d05c8833599d1c1441a1cc4926
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$simple_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$single_input_return.class b/src/main/resources/org/python/antlr/PythonParser$single_input_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..26c52674dc524c43e07f7bdc6930c530574de779
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$single_input_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$sliceop_return.class b/src/main/resources/org/python/antlr/PythonParser$sliceop_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..babefb791a8aca8b2450e6141195c18c2f875bd3
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$sliceop_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$small_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$small_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..43b27e6a2529bbf1119b9176cb6942e2a02646ca
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$small_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..90de4d0e7571052b3bad3a5ab37724331b764fe6
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$subscript_return.class b/src/main/resources/org/python/antlr/PythonParser$subscript_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd611f8fc04fc3e05f6a4f677ca92324c69b0a3c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$subscript_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$subscriptlist_return.class b/src/main/resources/org/python/antlr/PythonParser$subscriptlist_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..54d1bb1d3f714ddce31516ddb509d068b7d65e4e
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$subscriptlist_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$suite_return.class b/src/main/resources/org/python/antlr/PythonParser$suite_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2988ea967949a6085b70407938b0e353c335d1a
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$suite_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$suite_scope.class b/src/main/resources/org/python/antlr/PythonParser$suite_scope.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe66a90594620c43e9600181face525e6e46c1e5
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$suite_scope.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$term_op_return.class b/src/main/resources/org/python/antlr/PythonParser$term_op_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..13d1986f0d58904d13e41c0c92f3ed8d3477c386
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$term_op_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$term_return.class b/src/main/resources/org/python/antlr/PythonParser$term_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b82b39b8ff5a3d3d501bc1f529f70d21057d82b
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$term_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$test_return.class b/src/main/resources/org/python/antlr/PythonParser$test_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4d1c4182d29dfc789b1154b209352f5cb4fb2b7
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$test_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$testlist_gexp_return.class b/src/main/resources/org/python/antlr/PythonParser$testlist_gexp_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..895ad8d5e1adab6b4f3ef269c52f999040276a54
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$testlist_gexp_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$testlist_return.class b/src/main/resources/org/python/antlr/PythonParser$testlist_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..804df121f0953cf469c9efd0c27a326e03540692
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$testlist_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$trailer_return.class b/src/main/resources/org/python/antlr/PythonParser$trailer_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..90f3461f9e7e63b0d5a480b0fe445586d5278a03
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$trailer_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$try_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$try_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e6664ad2e6d2575bcb697f76a1597222e0f6980
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$try_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$varargslist_return.class b/src/main/resources/org/python/antlr/PythonParser$varargslist_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fd12a2111ae2b7f514a2863b05e11a5d3169d75
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$varargslist_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$while_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$while_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a25c94e51d3c03aa0a8cdcf74d55f80be7d60fe
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$while_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$with_item_return.class b/src/main/resources/org/python/antlr/PythonParser$with_item_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad6dc2e5e6d08ad48a5ffe1df448e1fe4c242173
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$with_item_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$with_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$with_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..33fd7175dc0364eee3b287645c5ae793341a6860
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$with_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$xor_expr_return.class b/src/main/resources/org/python/antlr/PythonParser$xor_expr_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f7c90599e068b06aad3a309e050ffe5a84c5a51
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$xor_expr_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$yield_expr_return.class b/src/main/resources/org/python/antlr/PythonParser$yield_expr_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..22f1f98f4310efbaa17e6fcd7c21753490773acc
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$yield_expr_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser$yield_stmt_return.class b/src/main/resources/org/python/antlr/PythonParser$yield_stmt_return.class
new file mode 100644
index 0000000000000000000000000000000000000000..7720679a52aff6197a1236a3d6d1006038a1c256
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser$yield_stmt_return.class differ
diff --git a/src/main/resources/org/python/antlr/PythonParser.class b/src/main/resources/org/python/antlr/PythonParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..a712e4df59ac7c886804ee422d4f72af8e9f50ba
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonParser.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA12.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA12.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d1b3a89264f66333b5ec7ce4cd17df6a608a432
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA12.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA15.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA15.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d61237817e6d7c8ee1eb3e82585bb175d06799f
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA15.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA21.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA21.class
new file mode 100644
index 0000000000000000000000000000000000000000..01678201ba2ffb838681c5cd7e0d460ddf86546a
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA21.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA25.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA25.class
new file mode 100644
index 0000000000000000000000000000000000000000..8edf37619cb8a91b509205bbc5c98a2762d94551
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA25.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA26.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA26.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4814c464c4c9b99508e0976bf9c8c05a1218823
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA26.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA27.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA27.class
new file mode 100644
index 0000000000000000000000000000000000000000..6791e45f108153f22713ec2d0d91df0fc75f4b00
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA27.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA5.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA5.class
new file mode 100644
index 0000000000000000000000000000000000000000..51e40a1c50c53ded07ef91ac1cb79e123296e65c
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA5.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA51.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA51.class
new file mode 100644
index 0000000000000000000000000000000000000000..24d95a0d5e7f49076221a51c2a66ac1431f14c98
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA51.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer$DFA52.class b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA52.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa45e379ad375ee121b400fc4d492499fca16dee
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer$DFA52.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialLexer.class b/src/main/resources/org/python/antlr/PythonPartialLexer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c9615ca93821069b0c615f08894a3c90ca95af9
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialLexer.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA107.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA107.class
new file mode 100644
index 0000000000000000000000000000000000000000..04d51a7e6a5762881cc9bc36847a51f43eee971f
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA107.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA120.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA120.class
new file mode 100644
index 0000000000000000000000000000000000000000..efe8b02d427d23efc1030a2cc3662c21e54fa2e2
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA120.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA122.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA122.class
new file mode 100644
index 0000000000000000000000000000000000000000..51223cb0b56c8a6f6129fda3a64e5843d9998764
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA122.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA124.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA124.class
new file mode 100644
index 0000000000000000000000000000000000000000..41cbf639b8488579201d9712151233e71a3b414e
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA124.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA125.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA125.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc17d615c8a29ee88acf502f0eac0552fad073e1
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA125.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA127.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA127.class
new file mode 100644
index 0000000000000000000000000000000000000000..a50ce13c7051aa587a10fb6d7651f66e8e2eb9e8
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA127.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA129.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA129.class
new file mode 100644
index 0000000000000000000000000000000000000000..b633b1ad3963d7e07d1bb116aaaba61dbd816568
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA129.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA130.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA130.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab0827f597f78845462b673c51bc07d390a9908d
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA130.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA27.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA27.class
new file mode 100644
index 0000000000000000000000000000000000000000..375eece03b40ad7fb04eb224f4f02fbc73345c8e
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA27.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA32.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA32.class
new file mode 100644
index 0000000000000000000000000000000000000000..13031a15f1f5baea3b5c765690fae887bc55dcc3
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA32.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA34.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA34.class
new file mode 100644
index 0000000000000000000000000000000000000000..68efd68e8b7c3982362d1c772886f572a0c4b94a
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA34.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA36.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA36.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6de06fa89b6d8c1ae61caabbaab68a58f540e98
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA36.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA45.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA45.class
new file mode 100644
index 0000000000000000000000000000000000000000..914cca6d247e69a86f73850afad21d8b41f70712
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA45.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA57.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA57.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a0a0ea8980b3474b4221ba1849830fcf89e821a
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA57.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA74.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA74.class
new file mode 100644
index 0000000000000000000000000000000000000000..7831d8642d7a142ea8790ac8ff4739b9133aff23
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA74.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser$DFA83.class b/src/main/resources/org/python/antlr/PythonPartialParser$DFA83.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ffb71e2385c9acba0546915dcba4e280bdef3a1
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser$DFA83.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialParser.class b/src/main/resources/org/python/antlr/PythonPartialParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0a180b8135e4c769956098171e6bdff17aced80
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialParser.class differ
diff --git a/src/main/resources/org/python/antlr/PythonPartialTester.class b/src/main/resources/org/python/antlr/PythonPartialTester.class
new file mode 100644
index 0000000000000000000000000000000000000000..a64427b15e937927e3a421e67abdfa2492d47ff0
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonPartialTester.class differ
diff --git a/src/main/resources/org/python/antlr/PythonTokenSource.class b/src/main/resources/org/python/antlr/PythonTokenSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..3141209289f5c0f8e2691c180c96d0defdb00d5a
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonTokenSource.class differ
diff --git a/src/main/resources/org/python/antlr/PythonTree.class b/src/main/resources/org/python/antlr/PythonTree.class
new file mode 100644
index 0000000000000000000000000000000000000000..988c03676b4161fb29f0c665f17ae2de081cbba4
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonTree.class differ
diff --git a/src/main/resources/org/python/antlr/PythonTreeAdaptor.class b/src/main/resources/org/python/antlr/PythonTreeAdaptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..eab19be8448a3790850ec7f637bbdae91d8594d3
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonTreeAdaptor.class differ
diff --git a/src/main/resources/org/python/antlr/PythonTreeTester$1.class b/src/main/resources/org/python/antlr/PythonTreeTester$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3193aa1fb1bef859a07bdac05c10fdf419e1abd2
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonTreeTester$1.class differ
diff --git a/src/main/resources/org/python/antlr/PythonTreeTester$Block.class b/src/main/resources/org/python/antlr/PythonTreeTester$Block.class
new file mode 100644
index 0000000000000000000000000000000000000000..ebe6a743115f0d9a2983ded218cfe12f4c8705ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonTreeTester$Block.class differ
diff --git a/src/main/resources/org/python/antlr/PythonTreeTester.class b/src/main/resources/org/python/antlr/PythonTreeTester.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e273543978c4a01e24ff564f2d9bf94a8b1953f
Binary files /dev/null and b/src/main/resources/org/python/antlr/PythonTreeTester.class differ
diff --git a/src/main/resources/org/python/antlr/RecordingErrorHandler.class b/src/main/resources/org/python/antlr/RecordingErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8185c5a43a789f144c921c7b2ceb516c54a7e08
Binary files /dev/null and b/src/main/resources/org/python/antlr/RecordingErrorHandler.class differ
diff --git a/src/main/resources/org/python/antlr/Visitor.class b/src/main/resources/org/python/antlr/Visitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b724dd0737d6e8250fecdc6de9d7cb4656511ea
Binary files /dev/null and b/src/main/resources/org/python/antlr/Visitor.class differ
diff --git a/src/main/resources/org/python/antlr/WalkerTester.class b/src/main/resources/org/python/antlr/WalkerTester.class
new file mode 100644
index 0000000000000000000000000000000000000000..5887b4498731be405c4f86200fbfc3bad419b695
Binary files /dev/null and b/src/main/resources/org/python/antlr/WalkerTester.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/AliasAdapter.class b/src/main/resources/org/python/antlr/adapter/AliasAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..65b152f5e441805f21ff86cf673edff96fd207cd
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/AliasAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/AstAdapter.class b/src/main/resources/org/python/antlr/adapter/AstAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..66c2487e0f2010a7e274d42fccc8aeaad744091c
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/AstAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/AstAdapters$1.class b/src/main/resources/org/python/antlr/adapter/AstAdapters$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb6a8eb28e5a17e1e788a3e16d056dd330587ae0
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/AstAdapters$1.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/AstAdapters.class b/src/main/resources/org/python/antlr/adapter/AstAdapters.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e71a6958514f0f09450823f56c4be6ddbe53aa1
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/AstAdapters.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/CmpopAdapter$1.class b/src/main/resources/org/python/antlr/adapter/CmpopAdapter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d64c12906f406e0e755b3f4114aa25caf49941d1
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/CmpopAdapter$1.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/CmpopAdapter.class b/src/main/resources/org/python/antlr/adapter/CmpopAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f01c13367f889722169b99500f9a70afe15c159
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/CmpopAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/ComprehensionAdapter.class b/src/main/resources/org/python/antlr/adapter/ComprehensionAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3ff7c419866381763769ec82e18a71f608ae044
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/ComprehensionAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/ExcepthandlerAdapter.class b/src/main/resources/org/python/antlr/adapter/ExcepthandlerAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..4061596e8d97ceb2bde6c3ad4a382d56e3d70a45
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/ExcepthandlerAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/ExprAdapter.class b/src/main/resources/org/python/antlr/adapter/ExprAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5065cf97e38244bd2a38ed109d13a206cda8382
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/ExprAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/IdentifierAdapter.class b/src/main/resources/org/python/antlr/adapter/IdentifierAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc8011a37667e86d186b130f34cb0d16635b9f50
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/IdentifierAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/KeywordAdapter.class b/src/main/resources/org/python/antlr/adapter/KeywordAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..8dc8c2f32d2c458110e8b93b7b3334a608d42c6b
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/KeywordAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/SliceAdapter.class b/src/main/resources/org/python/antlr/adapter/SliceAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..57a2472af98767cec5fabc94c58d399af0c31410
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/SliceAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/adapter/StmtAdapter.class b/src/main/resources/org/python/antlr/adapter/StmtAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c3341707516c413b3fe784ea37d47aeef6f9b02
Binary files /dev/null and b/src/main/resources/org/python/antlr/adapter/StmtAdapter.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$Assert___init___exposer.class b/src/main/resources/org/python/antlr/ast/Assert$Assert___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..78181b068fb38f4242e73dc77f4d6f5602178c36
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$Assert___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$PyExposer.class b/src/main/resources/org/python/antlr/ast/Assert$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..19efcc09bae0163e63d30905bc0e1bd127480522
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Assert$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..042b5eee8c3fe2db8e895e337d1f286028d06d66
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Assert$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a927246a1387f6d9797e4ee830838cdf0cc8fe38
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Assert$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4467a0c4971c8f27707afbf109e887c770a2484
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Assert$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..d63949ee906f7811ac9cc38e00219954c943929d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Assert$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b41003337f5b7a1299cb1f15a52692f686dbcf22
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$msg_descriptor.class b/src/main/resources/org/python/antlr/ast/Assert$msg_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5025066228abea91728867bb1b7b71a64b2a7726
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$msg_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Assert$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9dca735cf46e8ccab10631be8d244592e67a52a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert$test_descriptor.class b/src/main/resources/org/python/antlr/ast/Assert$test_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cde32a314c8970b4fb00ad6d65e55b0d39ca0eee
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert$test_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assert.class b/src/main/resources/org/python/antlr/ast/Assert.class
new file mode 100644
index 0000000000000000000000000000000000000000..630852248bdbe654a539c6ca851695fa9fd1a761
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assert.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AssertDerived.class b/src/main/resources/org/python/antlr/ast/AssertDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..f892bd8e0e71a49ace5d96c310240983b2608af7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AssertDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$Assign___init___exposer.class b/src/main/resources/org/python/antlr/ast/Assign$Assign___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b8937eb7c7b25e35a85158711f001aff7aafdf0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$Assign___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$PyExposer.class b/src/main/resources/org/python/antlr/ast/Assign$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2d81c7bc7f077eb63c013ce6f15963e09c049ca
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Assign$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6174c19f9fc3c563db13d281d7a5d81b897d5d7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Assign$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..50c5bde4f52d91b357f92813a2760a5ad2979769
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Assign$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..30040db14287a6fc76febab9b31d646f977fc0b9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Assign$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4d14ba173ee4b32e6f6b96b5a6685e9cf5ca8f2
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Assign$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..18c553208e8f0aa9422427ca43aa9bd550d3db03
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Assign$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..229dab050dc2c3de94d1d69d1b828b32cf0851dc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$targets_descriptor.class b/src/main/resources/org/python/antlr/ast/Assign$targets_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1553ee9f2846ea9b63d33285611bba79a89347d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$targets_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign$value_descriptor.class b/src/main/resources/org/python/antlr/ast/Assign$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f29a3945dccf38f8d4557655338cbd33b2ec171
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Assign.class b/src/main/resources/org/python/antlr/ast/Assign.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad61e2a22ab39fdcd19c306e4221ba921b651272
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Assign.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AssignDerived.class b/src/main/resources/org/python/antlr/ast/AssignDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ade2a9615e95dd1eeb32ffe657712680fe6fd64
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AssignDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AstModule.class b/src/main/resources/org/python/antlr/ast/AstModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ab09baa652749df7d62dc2381b5ed296605831d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AstModule.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$Attribute___init___exposer.class b/src/main/resources/org/python/antlr/ast/Attribute$Attribute___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f028a07d9cbf40e1ef1bf79f69c3b5466f7d59b7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$Attribute___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$PyExposer.class b/src/main/resources/org/python/antlr/ast/Attribute$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5886353d81b921959589793c645da05f0b0f480
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Attribute$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e5cc7ce8c696057a837137cd03714bd54838515
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Attribute$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..621f2133ed0f0a6c45348e8601f0c5d426330905
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$attr_descriptor.class b/src/main/resources/org/python/antlr/ast/Attribute$attr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..731e6e52be55d058ce62d7156ab89476bb16eccf
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$attr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Attribute$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..39c165a0545c4eb8036e18452a37a45eb6617906
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$ctx_descriptor.class b/src/main/resources/org/python/antlr/ast/Attribute$ctx_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8e949d3f5d67847edc81c4c4ac056f8ea27b292
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$ctx_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Attribute$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b15b3cdb5d9a0073b2408d94f0675b380100bb53
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Attribute$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9054e5e9be70ea7177eddd75212300896f78df9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Attribute$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3770b4238f7af3e7116b6921acf814346fa83328
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute$value_descriptor.class b/src/main/resources/org/python/antlr/ast/Attribute$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3078d4b5568cf1582b0b8a0388cadba875c4110a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Attribute.class b/src/main/resources/org/python/antlr/ast/Attribute.class
new file mode 100644
index 0000000000000000000000000000000000000000..34917de8a826b0c9fd81e786724a4333ec0f39f1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Attribute.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AttributeDerived.class b/src/main/resources/org/python/antlr/ast/AttributeDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..818f4047b4a130ab5a7ea35670e321dd30dc3aa1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AttributeDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$AugAssign___init___exposer.class b/src/main/resources/org/python/antlr/ast/AugAssign$AugAssign___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b0fc3c40d32a43d71553fcbeb8a93b996b562bbc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$AugAssign___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$PyExposer.class b/src/main/resources/org/python/antlr/ast/AugAssign$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..73b4eaab37c961f01fe78bbfe282ea8a083e8936
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/AugAssign$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..030fa90c33734b4743c67c3ff533f206c4ddc0a6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/AugAssign$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..79136600b43ad495a11ed88710329956410c12d0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/AugAssign$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..56540fda2fda5e3b9961dd5feaca5c45bf73204c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$exposed___new__.class b/src/main/resources/org/python/antlr/ast/AugAssign$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cfef675bd21ade1e95fc8b93d6644ac22b0dfbe
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/AugAssign$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2034d2636e157b36be726843b30940873a09ec84
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$op_descriptor.class b/src/main/resources/org/python/antlr/ast/AugAssign$op_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5ff14c2c669f9fb604d980427b62d2ababd13de
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$op_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/AugAssign$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..213ca66dbb2f2e62eb7df5e36c211a4b265a10a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$target_descriptor.class b/src/main/resources/org/python/antlr/ast/AugAssign$target_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b875e21dba1ed19e2a4a62501593b11644eb5de2
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$target_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign$value_descriptor.class b/src/main/resources/org/python/antlr/ast/AugAssign$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..de20a8160990ac855f49b53daaab0b3da6c22e64
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssign.class b/src/main/resources/org/python/antlr/ast/AugAssign.class
new file mode 100644
index 0000000000000000000000000000000000000000..941d78fc95ec145ca3ba42c3fd4ce65b72763820
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssign.class differ
diff --git a/src/main/resources/org/python/antlr/ast/AugAssignDerived.class b/src/main/resources/org/python/antlr/ast/AugAssignDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..1168adf58bffe266045fa77cb722b984ad4096c5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/AugAssignDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$BinOp___init___exposer.class b/src/main/resources/org/python/antlr/ast/BinOp$BinOp___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..31ea5e68f93c3442cd842e7403794177b9f3994d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$BinOp___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$PyExposer.class b/src/main/resources/org/python/antlr/ast/BinOp$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0c946ed6c8cd233a83da3e891ecd9634bc3147d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/BinOp$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..233252541c1857c05fccf53fa7d4395dc717aa21
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/BinOp$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d8f625a28c28d011fe738d9166dd3607de45f77
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/BinOp$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1edfc55913c9941cbf4e53e4e9182a2137e87829
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$exposed___new__.class b/src/main/resources/org/python/antlr/ast/BinOp$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b915f70ab5cfee5bf1ddd2392c57ed029f3415f6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$left_descriptor.class b/src/main/resources/org/python/antlr/ast/BinOp$left_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8263876692765bfedccc7b19238c03544cc9de4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$left_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/BinOp$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6a51512810f4b0d07488db29c417d106ae455ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$op_descriptor.class b/src/main/resources/org/python/antlr/ast/BinOp$op_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a65968733517d821314a8ee0eccb63caa07b68f9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$op_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/BinOp$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..67dd7091afa8d73f22e5489ca23c00d11559f972
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp$right_descriptor.class b/src/main/resources/org/python/antlr/ast/BinOp$right_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f687574d3402ed19153494943d9c2692c490eb08
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp$right_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOp.class b/src/main/resources/org/python/antlr/ast/BinOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..69d3628d27e596a3fce6b7716af0e52c970a96a7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOp.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BinOpDerived.class b/src/main/resources/org/python/antlr/ast/BinOpDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..90e9ac6e50b8cd657bf92b698c00e8ff734382e0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BinOpDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$BoolOp___init___exposer.class b/src/main/resources/org/python/antlr/ast/BoolOp$BoolOp___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0415094941c9756a3bc536cdf69eab3bb56d1a7b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$BoolOp___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$PyExposer.class b/src/main/resources/org/python/antlr/ast/BoolOp$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7bfad5c51768ad9cdf1f8e5d3142ea2fff776a6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/BoolOp$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..75d88b802805f0acbef6d2c98a1e38e1062ec230
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/BoolOp$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b110fbb747614dd2770745d231494d189c6e9e34
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/BoolOp$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e28e08440b749587cc5649ac566fb06248f6a8a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$exposed___new__.class b/src/main/resources/org/python/antlr/ast/BoolOp$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..049a6fb4ce4a3a8e44d333820e9083da2e528bcb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/BoolOp$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8994d343b432f1daf8d6df863ea610d866face41
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$op_descriptor.class b/src/main/resources/org/python/antlr/ast/BoolOp$op_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..195510324069b97f1407c8f28f5cc1e91446268e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$op_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/BoolOp$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d17494440d13e55c08efc7aeccb6a6a6397a3648
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp$values_descriptor.class b/src/main/resources/org/python/antlr/ast/BoolOp$values_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a281c3f0b0992171bef37930cd7f7b6b1fee7e5d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp$values_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOp.class b/src/main/resources/org/python/antlr/ast/BoolOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..40e3da8501f1ee4000201425da6841776666ed0f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOp.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BoolOpDerived.class b/src/main/resources/org/python/antlr/ast/BoolOpDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fdbf23229de3d0360826a2074aac9f0684588f0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BoolOpDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break$Break___init___exposer.class b/src/main/resources/org/python/antlr/ast/Break$Break___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..531ddb8cbd67d11239aa91fbe5661a43717fe7de
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break$Break___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break$PyExposer.class b/src/main/resources/org/python/antlr/ast/Break$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..61435787bfcb5ab601324f55c263395c76becc06
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Break$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..33f097db95151d77e872bac67c57bc9d8eaf3bd9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Break$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccb9441f80471e6608c6b65c0b10a034ff985c5a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Break$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..500d0ef408ead7dcbebc4ce9aa2c0d783f0dc871
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Break$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cff7dfe74c27841925a14feced5ce10b21722ce
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Break$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..20c0d5511094f7e32d1f50453bd3794a75fe6fe7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Break$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aab8f4f14447523ac36f13c80a9cfe814c04eb6d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Break.class b/src/main/resources/org/python/antlr/ast/Break.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6206459028d54bef11cc755af1ed7ae6a247a3d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Break.class differ
diff --git a/src/main/resources/org/python/antlr/ast/BreakDerived.class b/src/main/resources/org/python/antlr/ast/BreakDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..e038fb244b6d52d1283a78d948c1aad654659820
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/BreakDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$Call___init___exposer.class b/src/main/resources/org/python/antlr/ast/Call$Call___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d371429bc73fdfabe4b47941314ac654a82fabd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$Call___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$PyExposer.class b/src/main/resources/org/python/antlr/ast/Call$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6728ec837bd68957fcf842cb464f74bb6f7b168f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..60537bd320514bfd644dcea299b995a444bfa01e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..68a58103b3f7d0284062fa3766e0de8275b5c504
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$args_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$args_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..947e92f876bd2a70ead8a81088a71e4fc7f39cf3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$args_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5225b3ec1f01d53a96edfa4209ab864afc239ce4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Call$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fa35bc7397146be6c7a92d18128294265d30749
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$func_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$func_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1a99bdc7f844e9f90721c04f514e83a7be71a2a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$func_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$keywords_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$keywords_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e874a1f4be514d8a49e15ad53a32a2cc807f6162
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$keywords_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$kwargs_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$kwargs_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad481805f7dd8615d2bad89de53df83ac94684e4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$kwargs_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..adee2e02ba30bad8293f9a0c867e004e85d00010
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..29c02a3dc16eb0a03c723e3aa1e84db8f603abbf
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call$starargs_descriptor.class b/src/main/resources/org/python/antlr/ast/Call$starargs_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cda726e75ecc8d80c29b4c43269f47aeb9563322
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call$starargs_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Call.class b/src/main/resources/org/python/antlr/ast/Call.class
new file mode 100644
index 0000000000000000000000000000000000000000..f51b596fd6e9c9c8e64e2e5afddabe9207c1853d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Call.class differ
diff --git a/src/main/resources/org/python/antlr/ast/CallDerived.class b/src/main/resources/org/python/antlr/ast/CallDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..22c432611ef03824776260c209b4f86df8a23b87
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/CallDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$ClassDef___init___exposer.class b/src/main/resources/org/python/antlr/ast/ClassDef$ClassDef___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..64df5bc0060ef318dc02f8d722cc56b2e5fbf09f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$ClassDef___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$PyExposer.class b/src/main/resources/org/python/antlr/ast/ClassDef$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..304d3f7aa3e1b13308d265ed87e49a4e5afe591e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d74f75b935249ebad76c160859d0633c70a5b21
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..167e8a22b3042a55a78c130fafd791e6de5640dc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$bases_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$bases_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3fc846db04e316060aeb5fe32be5814f03bce16
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$bases_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$body_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..41af8cc583f16348865b582ab93bb4a4b60b7a93
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ced670777026a0e6c3fd16225cd8a5f0e98ee6f3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$decorator_list_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$decorator_list_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..76edc2393b67032f2d643c43e7b6ea0fdd99e0f4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$decorator_list_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$exposed___new__.class b/src/main/resources/org/python/antlr/ast/ClassDef$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd2d8657652299a7e2a6366324bc9250fa049079
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..df6f21e9999d0e89718a10fd5cf82e90011b4c27
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$name_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8666cbf5bb2e721c1f42869c48a1ad02a56cd0c8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$name_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/ClassDef$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f31d856a0b895eaa65a731c9b6eb96aa6614060
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDef.class b/src/main/resources/org/python/antlr/ast/ClassDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..39ee5bdebc3f5f52b126b34a63f168d0d06c0019
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDef.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ClassDefDerived.class b/src/main/resources/org/python/antlr/ast/ClassDefDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..1975151ed9b2528c5f2910d0089ec04c055feaaa
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ClassDefDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$Compare___init___exposer.class b/src/main/resources/org/python/antlr/ast/Compare$Compare___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..00b12d88816b64ac99119cfbc6e7982e78518f68
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$Compare___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$PyExposer.class b/src/main/resources/org/python/antlr/ast/Compare$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccfaa880361e3494e61c69a69bd2a6d9ccb5de23
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Compare$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a278c49a03f73e876409e6b414b1596d1cff698
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Compare$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..853642075956344819ff8069ffde0d6167fece43
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Compare$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..10c69a77c69e79f72278c56cbf2ca01b72a68c73
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$comparators_descriptor.class b/src/main/resources/org/python/antlr/ast/Compare$comparators_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7298115a12cad09093bcae6ebabea8c607e1a9d5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$comparators_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Compare$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..252947e6d98715c4b25306287571036bb05add7f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$left_descriptor.class b/src/main/resources/org/python/antlr/ast/Compare$left_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec46820ac57f781e32dd4931cd3e0ec4a5a44d86
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$left_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Compare$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..78b43e9114e212e5dba06676852a781b67c671c7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$ops_descriptor.class b/src/main/resources/org/python/antlr/ast/Compare$ops_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb276af8ada6a439e40af8c7880ec82f5fa24faf
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$ops_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Compare$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e81d6c49b83eff85413edfd28945c5a0a22c040c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Compare.class b/src/main/resources/org/python/antlr/ast/Compare.class
new file mode 100644
index 0000000000000000000000000000000000000000..de4b3135beb2b31db967af9b118c5a252864944c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Compare.class differ
diff --git a/src/main/resources/org/python/antlr/ast/CompareDerived.class b/src/main/resources/org/python/antlr/ast/CompareDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..76aab509e5576b2023c9139ff846f409695e25b7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/CompareDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Context.class b/src/main/resources/org/python/antlr/ast/Context.class
new file mode 100644
index 0000000000000000000000000000000000000000..c405defff9988915ac8e2bb92ae7f8eb5952de3c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Context.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue$Continue___init___exposer.class b/src/main/resources/org/python/antlr/ast/Continue$Continue___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a38bc183434522034d76c8ce7b0c0994838a0287
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue$Continue___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue$PyExposer.class b/src/main/resources/org/python/antlr/ast/Continue$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..76bbe8569e5156a18eb05877841bd776f6d618fc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Continue$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1806e05adf0c3269d38d73572e543a66ee3de430
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Continue$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd8c3cfaee07e21788d9cabeea3729c1c797721b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Continue$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f316a568130169ac03025638ac234d47347a27bc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Continue$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..e005b4f100161d8f37875c12d20434f642528031
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Continue$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..81d7477d561ae8b9012cd4cdf3fdcb57e79d16b9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Continue$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..857ec53bd4808880bb411874a10973edd98018f1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Continue.class b/src/main/resources/org/python/antlr/ast/Continue.class
new file mode 100644
index 0000000000000000000000000000000000000000..f445379853b4e0bb599380c34948e1265b6bf3a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Continue.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ContinueDerived.class b/src/main/resources/org/python/antlr/ast/ContinueDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..8221576ff00ba6cf69fbfa76c28787690e1731c0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ContinueDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$Delete___init___exposer.class b/src/main/resources/org/python/antlr/ast/Delete$Delete___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc1886c2dd8045ce4cb0255105df217d88245f5e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$Delete___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$PyExposer.class b/src/main/resources/org/python/antlr/ast/Delete$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b919abf9e57d4e850a248e968e3c38c353ea8e40
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Delete$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc66c5742a6626aaf4076fafa3c4f57bcc3d2a46
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Delete$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d606cc0e142284d9c482b25bc32a12cbefbdbfd3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Delete$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..893453846b4fe721ec8b6b7570599f66fc76f6b0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Delete$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4b47b3482be8ceb14c1875d410c4b1f6c969f24
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Delete$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..45fd2fc22af6f851473c9a3e48cfef469c76588b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Delete$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac1d7e2c6b2e793a9afb6467557cd68328362384
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete$targets_descriptor.class b/src/main/resources/org/python/antlr/ast/Delete$targets_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5af035a02936d8c971fee4434c25a6d3f4e7c5dd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete$targets_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Delete.class b/src/main/resources/org/python/antlr/ast/Delete.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8b69d296adbed043206fdbb1190cf475e8883ee
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Delete.class differ
diff --git a/src/main/resources/org/python/antlr/ast/DeleteDerived.class b/src/main/resources/org/python/antlr/ast/DeleteDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..b97b11be2ba93385748e68d30274dfcb73c33ebd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/DeleteDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$Dict___init___exposer.class b/src/main/resources/org/python/antlr/ast/Dict$Dict___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc14d15ff41763e7c044f3223397c2d02f1c38dd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$Dict___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$PyExposer.class b/src/main/resources/org/python/antlr/ast/Dict$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d491e18c3efa75a41f4a4e5b0e032aa8fdd0d8d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Dict$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7df02910e31d07ad302631cba731d88ac4bc86a0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Dict$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2895ce30d1b64124677ed465a556324b7dcdcac4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Dict$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..83547449ec066f507fc931eea95df29c3ab03462
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Dict$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..0069542b030f518e4962dfbc6f5ea82e85e45200
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$keys_descriptor.class b/src/main/resources/org/python/antlr/ast/Dict$keys_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..635ffe04f12719f50a2a36e985e9f4dd8e89cf1a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$keys_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Dict$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5c65d957b4f179ee18f4090b39178ccf950b0a3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Dict$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcb83e3738fe28e290d75fe22e47f64fcd7eed08
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict$values_descriptor.class b/src/main/resources/org/python/antlr/ast/Dict$values_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..94af236ea5174533d8e2eff66cf052bb2dde0764
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict$values_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Dict.class b/src/main/resources/org/python/antlr/ast/Dict.class
new file mode 100644
index 0000000000000000000000000000000000000000..5098894a43b5da61e88da7e7ab49fd47ca5809a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Dict.class differ
diff --git a/src/main/resources/org/python/antlr/ast/DictComp.class b/src/main/resources/org/python/antlr/ast/DictComp.class
new file mode 100644
index 0000000000000000000000000000000000000000..c11890f9da37bc5987f2260c2d441de5f47be033
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/DictComp.class differ
diff --git a/src/main/resources/org/python/antlr/ast/DictDerived.class b/src/main/resources/org/python/antlr/ast/DictDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c23270d5034d2cb1c06dabe0ab5a2818bcf10b3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/DictDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Ellipsis$Ellipsis___init___exposer.class b/src/main/resources/org/python/antlr/ast/Ellipsis$Ellipsis___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..016feb4c6eb67bfa4160ed21d33229fca2b3bcd3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Ellipsis$Ellipsis___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Ellipsis$PyExposer.class b/src/main/resources/org/python/antlr/ast/Ellipsis$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec34e68e8d2993f034f255c20aaedbd0769e23a1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Ellipsis$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Ellipsis$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Ellipsis$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a860a6560eff3c44137968d89cc21ec7be5739f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Ellipsis$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Ellipsis$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Ellipsis$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..951f31a3955b1105cb1b6cf925e345bab1f792e7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Ellipsis$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Ellipsis$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Ellipsis$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..661a0fb802da1bee542f2b28fffb0e36aa1e8c71
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Ellipsis$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Ellipsis$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Ellipsis$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5333ef5e6e20985db19f36f1887153ac5d249852
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Ellipsis$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Ellipsis.class b/src/main/resources/org/python/antlr/ast/Ellipsis.class
new file mode 100644
index 0000000000000000000000000000000000000000..d51a2231709d1a17aee308d5f1edd5ba48078eb8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Ellipsis.class differ
diff --git a/src/main/resources/org/python/antlr/ast/EllipsisDerived.class b/src/main/resources/org/python/antlr/ast/EllipsisDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5de9b82bfb10b4916b058cad9b32fe432e9e125
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/EllipsisDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ErrorExpr.class b/src/main/resources/org/python/antlr/ast/ErrorExpr.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6a700dfe42e36218c6f86b56705b5b3574db824
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ErrorExpr.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ErrorMod.class b/src/main/resources/org/python/antlr/ast/ErrorMod.class
new file mode 100644
index 0000000000000000000000000000000000000000..25dd5268a801150083c3e4001bbdbe1424b297cd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ErrorMod.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ErrorSlice.class b/src/main/resources/org/python/antlr/ast/ErrorSlice.class
new file mode 100644
index 0000000000000000000000000000000000000000..c46aac1c22229f0792462b7d65827f7fa79292fa
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ErrorSlice.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ErrorStmt.class b/src/main/resources/org/python/antlr/ast/ErrorStmt.class
new file mode 100644
index 0000000000000000000000000000000000000000..70992b4ac7277d1aa4b8e6e5a9562714c081f7a8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ErrorStmt.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$ExceptHandler___init___exposer.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$ExceptHandler___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f29b37ac24c2e7a66a155f7d6a74e6ab4bab1d01
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$ExceptHandler___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$PyExposer.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..772f56e7638d1de5d07a53141df38527c1213da3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7e054acb39457dae1bc846ebe58aa888636eb4a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cdb9fec74fe445790e6a2ac702594909c465ff76
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$body_descriptor.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..96be26d5c15e5217cce43f5ede765a0d4bd853a5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5e45e99427a4245b591f28055b9ac5f2501d7da
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$exposed___new__.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..182351227747b5eaee6d9d4a050e25535bd9b770
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6727c9cee010c7cf1c3f18f46303a29733c8ceb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$name_descriptor.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..db26c9ed5c07f652c5efe9b8cfce2dee376ab4e6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$name_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c837cbf6f05b5e84649fc1b1068cdc5b62f0908
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler$type_descriptor.class b/src/main/resources/org/python/antlr/ast/ExceptHandler$type_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e8a605dbde4f387a7ad3b91638c1e1466ddea38
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler$type_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandler.class b/src/main/resources/org/python/antlr/ast/ExceptHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..68d58559b0a50c4608e2739c3ac8fa85a2b398d4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandler.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExceptHandlerDerived.class b/src/main/resources/org/python/antlr/ast/ExceptHandlerDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..02a9e8d516aa66848625fb3b7196251bb1decdc9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExceptHandlerDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$Exec___init___exposer.class b/src/main/resources/org/python/antlr/ast/Exec$Exec___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f776dae65c0b733bb567174904cf769cdeb1a3a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$Exec___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$PyExposer.class b/src/main/resources/org/python/antlr/ast/Exec$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..723809b60033d8458e23a3b6463448c5dd438d55
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Exec$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca456d820c5a23b9a3ca9a19a53f3fca4479b58c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Exec$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0df0c3572c081d34a2be2b2c3f19ec60782e2d2d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$body_descriptor.class b/src/main/resources/org/python/antlr/ast/Exec$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b48b1eeb30e020f397288c46b0fe12118b239f3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Exec$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1df88cc2dac771642512aa52c7254ec8e7cedd3e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Exec$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9cf1edaa3655de1dcaae6041e4fb5010dc19713
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$globals_descriptor.class b/src/main/resources/org/python/antlr/ast/Exec$globals_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..45bd233e8182f804521ea9516d3c64e1b5cf462b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$globals_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Exec$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a6fd63e9f961c8b858ff51c20e70937bb46304d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$locals_descriptor.class b/src/main/resources/org/python/antlr/ast/Exec$locals_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..95a3b22df7d115deaade0dde603894b45b8c0707
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$locals_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Exec$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6d610382e965b33da6b32d36014a95894cfd782
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Exec.class b/src/main/resources/org/python/antlr/ast/Exec.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3448e218fb9b777b50fd31651457d4a02b80998
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Exec.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExecDerived.class b/src/main/resources/org/python/antlr/ast/ExecDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ad68b282f877d676c7d65cdac44a8da07af28ca
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExecDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$Expr___init___exposer.class b/src/main/resources/org/python/antlr/ast/Expr$Expr___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6021e47766299368f311214aa78cbbbb6cc8cfb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$Expr___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$PyExposer.class b/src/main/resources/org/python/antlr/ast/Expr$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d81d6117bbddc28bb87d294ef9783d4e781466e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Expr$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d40ddaa2b09ed220f9d7f844cbe49fdf1f2207b3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Expr$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a6b964d9d1435d7a878419b974e069ae6263e45
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Expr$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d07ffc38aa59699723c935ef912e2b7aa14b5786
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Expr$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..08bd132480161e6d0ba12f12ab5a8b1b2e3f8d5f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Expr$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..079d0e22e427df9422fda17c368e3c7ee5baf121
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Expr$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bac01323c4e8d1f63aab5424172c6e139a50c43a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr$value_descriptor.class b/src/main/resources/org/python/antlr/ast/Expr$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cc9384075347ff97496ab62810909ca056089eb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expr.class b/src/main/resources/org/python/antlr/ast/Expr.class
new file mode 100644
index 0000000000000000000000000000000000000000..2fa15526f6fc0af5c8127e02c0ce5917149a73c7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expr.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExprDerived.class b/src/main/resources/org/python/antlr/ast/ExprDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..af4d6774d68343ed40d08db25ae80e433c3bc283
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExprDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expression$Expression___init___exposer.class b/src/main/resources/org/python/antlr/ast/Expression$Expression___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf5d09f3152d3f7054fceb7f8610f5e8944f3c4f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expression$Expression___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expression$PyExposer.class b/src/main/resources/org/python/antlr/ast/Expression$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d35222d40c4e5b40b6f06c6f035a84612db9648d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expression$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expression$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Expression$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..947fb8ca6171cf5618cbb6a0cef07dc21563aa8b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expression$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expression$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Expression$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2923385b311a6d9492bff665f09469f1b32caeea
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expression$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expression$body_descriptor.class b/src/main/resources/org/python/antlr/ast/Expression$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab520d2881f4c11a09037580adf00aa506bfdb13
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expression$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expression$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Expression$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ff1c759b5cb44ce8fbb4bdba47339d3ad470f05
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expression$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expression$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Expression$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a843b384e9ee1adecfbb68a92800fbb0063de117
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expression$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Expression.class b/src/main/resources/org/python/antlr/ast/Expression.class
new file mode 100644
index 0000000000000000000000000000000000000000..9feb7615f4b06c66ccfd13b285f4da64c4646975
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Expression.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExpressionDerived.class b/src/main/resources/org/python/antlr/ast/ExpressionDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..da56b978286fb9457119d843c176ec2a38ee5042
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExpressionDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSlice$ExtSlice___init___exposer.class b/src/main/resources/org/python/antlr/ast/ExtSlice$ExtSlice___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6a399edbc818020be8990b753853bc8ddc184e6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSlice$ExtSlice___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSlice$PyExposer.class b/src/main/resources/org/python/antlr/ast/ExtSlice$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d10ebe9d7a609176f36e04d22d4e02e7dc49a77
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSlice$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSlice$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/ExtSlice$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7711064b822d83180d58062a88c97cfdcb6a23e9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSlice$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSlice$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/ExtSlice$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..818fc7b93de496871dca939a02a0d3fb0e2a4545
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSlice$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSlice$dims_descriptor.class b/src/main/resources/org/python/antlr/ast/ExtSlice$dims_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..809f9700c05ab85bfff738b5847d300186f80860
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSlice$dims_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSlice$exposed___new__.class b/src/main/resources/org/python/antlr/ast/ExtSlice$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b98416ffae055fcde5aecf635565ce2f91a97b8a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSlice$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSlice$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/ExtSlice$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5644fad40e656676e579ac0f7bbb2b9ea6f2eada
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSlice$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSlice.class b/src/main/resources/org/python/antlr/ast/ExtSlice.class
new file mode 100644
index 0000000000000000000000000000000000000000..891234fe34c5b143033da6981149708db3385195
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSlice.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ExtSliceDerived.class b/src/main/resources/org/python/antlr/ast/ExtSliceDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ef40e30f75a34c054da2fcd816b896525882dcf
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ExtSliceDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$For___init___exposer.class b/src/main/resources/org/python/antlr/ast/For$For___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1bccee6cb2024a4b70b215578d78b809bdbe21d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$For___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$PyExposer.class b/src/main/resources/org/python/antlr/ast/For$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1bf41a522cd696ff2e5d7bb0e0b95681d82c0d1f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/For$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..83d03e666040e8642289752638d386f6e5c147e9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/For$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5d0172f4a589835c8f0aac82f3534836189e3ed
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$body_descriptor.class b/src/main/resources/org/python/antlr/ast/For$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e59a33f584eb21979658ca7bf80b8988dc4728e1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/For$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5a3c85b6c49be0fe934bd2a0164fb5468951af6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$exposed___new__.class b/src/main/resources/org/python/antlr/ast/For$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..8807b91b1fdce48ba33deb377adb441305d4b456
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$iter_descriptor.class b/src/main/resources/org/python/antlr/ast/For$iter_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..56b5f6593866bf0bfe23a583daa8ff24b49792c3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$iter_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/For$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b93fe312b3ee3596018d5b3450ad8f1ff503c94
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$orelse_descriptor.class b/src/main/resources/org/python/antlr/ast/For$orelse_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..378b38ed6cf361843679cb17ca623ba30cffe70f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$orelse_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/For$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0c0b29eefaa641b1412958ee37e44a5fa82003d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For$target_descriptor.class b/src/main/resources/org/python/antlr/ast/For$target_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8dbbe44a7d3eaf8304009a8d6634c819ef9d90a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For$target_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/For.class b/src/main/resources/org/python/antlr/ast/For.class
new file mode 100644
index 0000000000000000000000000000000000000000..86d91ed01d2ba3427c047ee3feeae82a2b6565a4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/For.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ForDerived.class b/src/main/resources/org/python/antlr/ast/ForDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d55fef8c4b86b74de29944d18eff0c58a9bcb43
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ForDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$FunctionDef___init___exposer.class b/src/main/resources/org/python/antlr/ast/FunctionDef$FunctionDef___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe3d5811da92c50a6617c145dc6953f50bd1c00f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$FunctionDef___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$PyExposer.class b/src/main/resources/org/python/antlr/ast/FunctionDef$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e4321c13fb02459938c7a5971213ebddda8d2d32
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..11a357bd9789f4114c9e964f7912cc8a312ffa01
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..57af326a574bd52dede692bc348df448ae9ad084
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$args_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$args_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..08f396bbb072b48b708ecd9ca9d259de4bc9257c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$args_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$body_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6807a691fffa5beb70d3459a96bfde2ce403f4a5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3db634bc74a357a559a43fa3be150a15aa9e3fc2
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$decorator_list_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$decorator_list_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e849670577d22cd2b891912db44a34adce44e4d2
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$decorator_list_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$exposed___new__.class b/src/main/resources/org/python/antlr/ast/FunctionDef$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1898a66a3d16098090b28b621443a2b489e308e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d02c9be3fc217507e10c032b7295bc64131f59af
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$name_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..576b4c41b1e75e50edc936021ca4c0422c3c5ff5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$name_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/FunctionDef$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6755d84689fa7efe29f0293c4947f5f77492e84
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDef.class b/src/main/resources/org/python/antlr/ast/FunctionDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d8cff5d4d774369ff9352811afd974d4c86f067
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDef.class differ
diff --git a/src/main/resources/org/python/antlr/ast/FunctionDefDerived.class b/src/main/resources/org/python/antlr/ast/FunctionDefDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..e27b2434fbbe9a65f390419529fd2d6109961e8b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/FunctionDefDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$GeneratorExp___init___exposer.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$GeneratorExp___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a65fa905e17b54503ef31868af5160b4b0cd7c8e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$GeneratorExp___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$PyExposer.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ca792b7a7bd6df755fc7f69ad74cf85e89f203d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..580ffa721508dbd9a526e33bf80e8cffd3a4115b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0e6e4e2562bd358481c187c06e6b3bf1685855f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6835ff94000105028acd0e16b56997005cdfb8c5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$elt_descriptor.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$elt_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..417f304740243516558ad41aee2d1ce861ab43ff
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$elt_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$exposed___new__.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..206a996058d85e4c4ffcfb44a5423ca420caacde
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$generators_descriptor.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$generators_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..91dc893a608e975f224e21cb472d5e265c27c885
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$generators_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca9f7d2138c55d1761c846bdadc9b29d2b534d85
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/GeneratorExp$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..47069f86d98c13fa97def0cc203d35ca18877122
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExp.class b/src/main/resources/org/python/antlr/ast/GeneratorExp.class
new file mode 100644
index 0000000000000000000000000000000000000000..415e76e7322a8b1146b62150ee902e1081003ce5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExp.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GeneratorExpDerived.class b/src/main/resources/org/python/antlr/ast/GeneratorExpDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7177f1f89205d01ac0a761c5b80eeb7f6a5b6b4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GeneratorExpDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$Global___init___exposer.class b/src/main/resources/org/python/antlr/ast/Global$Global___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ebafa15a28d60e48b243bf5fea9861bbc86e7a86
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$Global___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$PyExposer.class b/src/main/resources/org/python/antlr/ast/Global$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd54cf780e5e49f6f99ec1ba7a1a76992f109b19
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Global$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..25c5e772feaf819059438e4df9e8ccb11e1956bb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Global$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..997a68b3998a34ad7ef8af3a1820dbcd4552e750
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Global$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8df939917eea822de8ebfee948d617c9f624d91c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Global$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..89292e7bdc4c35bbb533d1a46f0ee4ab2a0a3b77
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Global$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9548bffafa2953b613c40af54fcf0d20173d2c9f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$names_descriptor.class b/src/main/resources/org/python/antlr/ast/Global$names_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d8633bf108a7b35b209fc8cc48d3bc36afd8c23
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$names_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Global$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b64ccfaa209aab2d1c70bca02831a0bc20cc6f5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Global.class b/src/main/resources/org/python/antlr/ast/Global.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ef1fa9270b844a04140326165fe9b97bba874e3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Global.class differ
diff --git a/src/main/resources/org/python/antlr/ast/GlobalDerived.class b/src/main/resources/org/python/antlr/ast/GlobalDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..da19d744c2689d1fad8288bf16d1436f1b8f20d6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/GlobalDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$If___init___exposer.class b/src/main/resources/org/python/antlr/ast/If$If___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a127d727e0b9cf6d1a591653773ed6dab24a4bd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$If___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$PyExposer.class b/src/main/resources/org/python/antlr/ast/If$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5722521e5d37949ce8a44dcfae6c40f8314864e0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/If$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0253d094060bffefd1435cd6d6065890e69bf3a1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/If$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6abd51030d21d717ce36bd5e282d2eab6254ba4f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$body_descriptor.class b/src/main/resources/org/python/antlr/ast/If$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ace314a98ed9431f4bfac55dadf951568a87d7b8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/If$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a85ba4cdca951b6f9c8c52424e18af946154355
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$exposed___new__.class b/src/main/resources/org/python/antlr/ast/If$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..a967dfc058cc619ce9fcb8aadbfc4c964b68d9f5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/If$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..76d5271a902c9cd1eda1b7919036f8d6738e2f3c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$orelse_descriptor.class b/src/main/resources/org/python/antlr/ast/If$orelse_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f18ae0fd0bcb6b0eb4dcdc3bbaaa09999027be0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$orelse_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/If$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa86ef672111174d8d37cc25692077f6713bf7fd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If$test_descriptor.class b/src/main/resources/org/python/antlr/ast/If$test_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aaab7b0bf2079f8b16350aabd43dc690299d22f6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If$test_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/If.class b/src/main/resources/org/python/antlr/ast/If.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a18f1c3d92eba28d2d2aba730c53e1ac8345533
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/If.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfDerived.class b/src/main/resources/org/python/antlr/ast/IfDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..00186af43bf66c8b40deda78b1851ee16936d090
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$IfExp___init___exposer.class b/src/main/resources/org/python/antlr/ast/IfExp$IfExp___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..775d681011c87a768f72b8ae6daed494fde8d98f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$IfExp___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$PyExposer.class b/src/main/resources/org/python/antlr/ast/IfExp$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..441f15c74d256f84c3ad6149cf115221319375c0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/IfExp$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..242de2b4004039d76ff1701ef24a34b183b8ee69
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/IfExp$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3582ad6a225a7b3e826a47237d236db597114a0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$body_descriptor.class b/src/main/resources/org/python/antlr/ast/IfExp$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7aea7d8a0d0d832e927237289c7d60a1087c494f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/IfExp$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..30dcc2adef221011db7870dcadb05b1e26d05393
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$exposed___new__.class b/src/main/resources/org/python/antlr/ast/IfExp$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8e79036653a031c0987ae8cca71b1cbacce6528
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/IfExp$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f835b10ce71d6b6a018e50366efaca93fd5fb10b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$orelse_descriptor.class b/src/main/resources/org/python/antlr/ast/IfExp$orelse_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..68f77c774f1491808c3641a5b9b596f9195b77ce
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$orelse_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/IfExp$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea37d4af2f6b73e7931f22f1f2f53283641e3a83
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp$test_descriptor.class b/src/main/resources/org/python/antlr/ast/IfExp$test_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aee4aab8a79c0f3270a68a1cfe4c4311801e9046
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp$test_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExp.class b/src/main/resources/org/python/antlr/ast/IfExp.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2162370948bd5ff335148c533f006aae3040742
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExp.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IfExpDerived.class b/src/main/resources/org/python/antlr/ast/IfExpDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..161f0164406df72f46653d86e02f2d1b906269f1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IfExpDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$Import___init___exposer.class b/src/main/resources/org/python/antlr/ast/Import$Import___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..915149ba7997e5719125770f8f7cc033fb049ecd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$Import___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$PyExposer.class b/src/main/resources/org/python/antlr/ast/Import$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a19ffe680f1f9e4242df84f6bf40230d2cb0e5b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Import$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..303d1e1046aea6f020aae33762c7dbbfa2696e47
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Import$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f16ac153ab2e83b0dd3b929c08b6474ff3af9c4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Import$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3793477cc42fcaa975c0b84d2c673bf8e68e4f8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Import$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e288224398b759d4cfa305c590ea22a3a9f35c1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Import$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8d7d151e7f6afc6a73ed01ad424fa4953f62c08
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$names_descriptor.class b/src/main/resources/org/python/antlr/ast/Import$names_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..02886e3c80729528ca6942369022d8967ac80fd0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$names_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Import$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f9c67ad9c3a919e5926b3f527f847bf4337a346
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Import.class b/src/main/resources/org/python/antlr/ast/Import.class
new file mode 100644
index 0000000000000000000000000000000000000000..0dfa0779eb1fdbab10534b22ffa3bbe133401804
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Import.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportDerived.class b/src/main/resources/org/python/antlr/ast/ImportDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..608c6ee26d05c003f58d5e622e9f2eb2a382e38c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$ImportFrom___init___exposer.class b/src/main/resources/org/python/antlr/ast/ImportFrom$ImportFrom___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f488d517bae9efde9d8809ea87612ecbb5649aeb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$ImportFrom___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$PyExposer.class b/src/main/resources/org/python/antlr/ast/ImportFrom$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..14ecf784779a1b1fe158f305e64e9d35fac3c917
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/ImportFrom$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0910751a546dad252233c59c6ae6c078292759a7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/ImportFrom$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e5440c12509b8c34b5519d2c9995f14034168a1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/ImportFrom$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..44812c97a0c9edbf3820bc540a73a7f59374b361
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$exposed___new__.class b/src/main/resources/org/python/antlr/ast/ImportFrom$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bb555687f783bef98a3e71a581a39e99223ceed
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$level_descriptor.class b/src/main/resources/org/python/antlr/ast/ImportFrom$level_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b36ff3fb7e8ea872e24e27a23e33fdc9f9e0d27
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$level_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/ImportFrom$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b6dfa8c8b7d14079fa67eab98648ba50a2a46c7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$module_descriptor.class b/src/main/resources/org/python/antlr/ast/ImportFrom$module_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa5f268483da8edf9cb279d3bff7630e2dacd571
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$module_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$names_descriptor.class b/src/main/resources/org/python/antlr/ast/ImportFrom$names_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..423c03b6b6a554c3e1822ad5bfe95dc4c382c3d9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$names_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/ImportFrom$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..571ba92d5876125ea6ef24575c175841b5245ab6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFrom.class b/src/main/resources/org/python/antlr/ast/ImportFrom.class
new file mode 100644
index 0000000000000000000000000000000000000000..59096de0eb0f2b234fbf9132b5651704a0e148fd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFrom.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ImportFromDerived.class b/src/main/resources/org/python/antlr/ast/ImportFromDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8d687c09f8616a6c65dd4862e76057776390c58
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ImportFromDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Index$Index___init___exposer.class b/src/main/resources/org/python/antlr/ast/Index$Index___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a29c0364b8b69b8589a2b2f031fb957f496871b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Index$Index___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Index$PyExposer.class b/src/main/resources/org/python/antlr/ast/Index$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a874160b9c993d46d124a73ad9b872b3f8883601
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Index$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Index$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Index$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..40939302a7a6cc81cf6c28a046967772731d2641
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Index$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Index$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Index$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c91ac43e68567fe19fe3cbb215dc451ff0fd6e0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Index$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Index$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Index$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..a262b602e36e6a5938e43cce529e74af09ef4d37
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Index$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Index$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Index$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..16f6d67bb36549104e67b60ba7cdc68a23dc8b6d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Index$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Index$value_descriptor.class b/src/main/resources/org/python/antlr/ast/Index$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ad84abc59164612522abff3076f0d0e0c220504
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Index$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Index.class b/src/main/resources/org/python/antlr/ast/Index.class
new file mode 100644
index 0000000000000000000000000000000000000000..7827c08dd4379356bd41280417ecd8169fd857d2
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Index.class differ
diff --git a/src/main/resources/org/python/antlr/ast/IndexDerived.class b/src/main/resources/org/python/antlr/ast/IndexDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7698fda93bb49cdf9e70a205afce03738a6f0b3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/IndexDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Interactive$Interactive___init___exposer.class b/src/main/resources/org/python/antlr/ast/Interactive$Interactive___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f058dc271913675812992cd4fc92cafd6e560da3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Interactive$Interactive___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Interactive$PyExposer.class b/src/main/resources/org/python/antlr/ast/Interactive$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2dbcf62bc1a2de28b024fae7d27283ff37dbcb6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Interactive$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Interactive$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Interactive$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7797cafbf4b8c67186efb7256c1d1bda5c95a27d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Interactive$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Interactive$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Interactive$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bece51455d3e739b56c729d6a7d838feefaf97f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Interactive$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Interactive$body_descriptor.class b/src/main/resources/org/python/antlr/ast/Interactive$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6c81f90434232a69524d9de46a5474921c68630
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Interactive$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Interactive$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Interactive$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d318add0521d667aaa4ea329cf14223698ff494
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Interactive$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Interactive$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Interactive$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..10da7625769dffa0917e8820e7108abdac045ccd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Interactive$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Interactive.class b/src/main/resources/org/python/antlr/ast/Interactive.class
new file mode 100644
index 0000000000000000000000000000000000000000..9010fa47c6b99272f40b30f4e1972711a0c8a33b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Interactive.class differ
diff --git a/src/main/resources/org/python/antlr/ast/InteractiveDerived.class b/src/main/resources/org/python/antlr/ast/InteractiveDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8978ea25af42a486cc0fdb072779b45970916c8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/InteractiveDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$Lambda___init___exposer.class b/src/main/resources/org/python/antlr/ast/Lambda$Lambda___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..81ba4689c6e406cd72b7bf64e32acd0f7caea31e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$Lambda___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$PyExposer.class b/src/main/resources/org/python/antlr/ast/Lambda$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..62146b03d2f1124eae214c9c57e197e6c2f1912b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Lambda$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..564aad78b704e2656e9a9edfd227008ee09f24e7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Lambda$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..059509fae360261391d057d562c2007655768430
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$args_descriptor.class b/src/main/resources/org/python/antlr/ast/Lambda$args_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca1ca579ee1ed134ea160695173b4f71bb38bfa6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$args_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$body_descriptor.class b/src/main/resources/org/python/antlr/ast/Lambda$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a8fdba5d31c112da73322785b338ed355ea42f7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Lambda$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1df223a40c02252a71a584f49ab0bb5dcb802361
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Lambda$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..27181016f0dcb6a1b855e2334a4919ff019408f9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Lambda$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f49ab64a77a3fe9c372014a548373a3e939ccad5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Lambda$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d1f565932479c3d9a4ee1d3205ff148dfb1b749
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Lambda.class b/src/main/resources/org/python/antlr/ast/Lambda.class
new file mode 100644
index 0000000000000000000000000000000000000000..25250ed12f7a109bab234aef0e467e3f7346c2c7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Lambda.class differ
diff --git a/src/main/resources/org/python/antlr/ast/LambdaDerived.class b/src/main/resources/org/python/antlr/ast/LambdaDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c238c4262b10db1a068980b75a3d316c4fab990
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/LambdaDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$List___init___exposer.class b/src/main/resources/org/python/antlr/ast/List$List___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..01650b6a48679c6d02a0a9560b237591f54c9014
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$List___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$PyExposer.class b/src/main/resources/org/python/antlr/ast/List$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d93b4c9030acf9c47a488a62f7a7226de4cf5d93
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/List$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b18bd404606e527d232b7119f92a716ac938a7bb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/List$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3149339160ab77e8e6509565751c025f4ddf7c7b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/List$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f27ff74113957497f294fe7937a48169003baa45
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$ctx_descriptor.class b/src/main/resources/org/python/antlr/ast/List$ctx_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c2ab37e5e90540e5cbd9327e72a699127581c67
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$ctx_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$elts_descriptor.class b/src/main/resources/org/python/antlr/ast/List$elts_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b02399fadc631c05a37c6503bf76f2766180b1c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$elts_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$exposed___new__.class b/src/main/resources/org/python/antlr/ast/List$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d65ae4e42cbf01e28d60146857c175338593985
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/List$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c9c83f524b050086ee4820a0eb942cfeeaa3d86
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/List$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fad700c0e625102efc0807c3cc9364c11663a4e0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/List.class b/src/main/resources/org/python/antlr/ast/List.class
new file mode 100644
index 0000000000000000000000000000000000000000..688718af2320ca7b81f9ab421f936860dbb755c0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/List.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$ListComp___init___exposer.class b/src/main/resources/org/python/antlr/ast/ListComp$ListComp___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e13e29deb37dbac426fa68fd6b3148974b82320b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$ListComp___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$PyExposer.class b/src/main/resources/org/python/antlr/ast/ListComp$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..40a5fa4f8a2911bf8e674610addbbc761d6794bf
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/ListComp$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a362feabf64e0a5058ca9c56667cae00c00f946
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/ListComp$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5bd268cd8d9d38bf03f7d81aef7466a6f9d63dce
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/ListComp$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c32473d653a1ef0b80aec8f2c601b6f60cac2868
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$elt_descriptor.class b/src/main/resources/org/python/antlr/ast/ListComp$elt_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a84a98ca556697bd7587dfe4d1d80de558c7da8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$elt_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$exposed___new__.class b/src/main/resources/org/python/antlr/ast/ListComp$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..32baa3aad3ce2c9b89a0c384f4401449bc1436aa
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$generators_descriptor.class b/src/main/resources/org/python/antlr/ast/ListComp$generators_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8f286698a241761ad0c3b8e0b3addaf76dcc0b9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$generators_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/ListComp$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9052233a56e6d28b8a1a03a67c0e7706cd90dd67
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/ListComp$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb7a84556b382fde567eaab1d5e7b81449655cb9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListComp.class b/src/main/resources/org/python/antlr/ast/ListComp.class
new file mode 100644
index 0000000000000000000000000000000000000000..d47cf13e21156561b675f0d64c4a118d8d540f3e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListComp.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListCompDerived.class b/src/main/resources/org/python/antlr/ast/ListCompDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..99b0c2379c50234aa82adfa9581001d77d9e5467
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListCompDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ListDerived.class b/src/main/resources/org/python/antlr/ast/ListDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9da896209a7bbd9181e132654c0350bdddac12f1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ListDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Module$Module___init___exposer.class b/src/main/resources/org/python/antlr/ast/Module$Module___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6eb3d4739885163092945940e4eef1c20cfa0ae4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Module$Module___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Module$PyExposer.class b/src/main/resources/org/python/antlr/ast/Module$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c03196852cbb2f8239a1adfd62bd3e76387a37c8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Module$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Module$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Module$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2ce27d534bcbcda708e4b0282ddf6051b5b5d6e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Module$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Module$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Module$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1312399da9b74f99e2ca3df2cc05dfa3c5a7e280
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Module$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Module$body_descriptor.class b/src/main/resources/org/python/antlr/ast/Module$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..58a456653eca4c6d6c7042a34d748fcbf2710f8b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Module$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Module$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Module$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..acf0e24a7ddd36588ae3f675f40f001c03ce39a7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Module$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Module$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Module$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4240ff754b0f0ee06d604720b16a1e15fbc53fc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Module$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Module.class b/src/main/resources/org/python/antlr/ast/Module.class
new file mode 100644
index 0000000000000000000000000000000000000000..137668a43985e7db16fdbad153cbff1172a0c878
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Module.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ModuleDerived.class b/src/main/resources/org/python/antlr/ast/ModuleDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2c73a56f6efec6bd11de72f6771a16dfd4de8ac
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ModuleDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$Name___init___exposer.class b/src/main/resources/org/python/antlr/ast/Name$Name___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..379a50e8fa8099e7b764975b39bd80a02c5e1e39
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$Name___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$PyExposer.class b/src/main/resources/org/python/antlr/ast/Name$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ccc18a0c214d5e1c34a72d2f25794848aeef5a3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Name$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d2f9950a491c7a73cafe02b47ebd97ae5a70c63
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Name$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc4e31d4a5f0b80bac453167338997af99fe1772
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Name$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d0e9d85d5e3c67c83195a07d579a208aae4bf8c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$ctx_descriptor.class b/src/main/resources/org/python/antlr/ast/Name$ctx_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..096426897559318c252238a5b3883e6d0c72d37d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$ctx_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Name$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..df9218d2daa61566e5b41c238f12289b36900dc7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$id_descriptor.class b/src/main/resources/org/python/antlr/ast/Name$id_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..91f28d834a498deea60d985b429a1acf04476962
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$id_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Name$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aee5e5123865bb6998d5d1eaf5058f61055f00f4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Name$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e3ed1b10772a4860c0a8fbdd58001304079711e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Name.class b/src/main/resources/org/python/antlr/ast/Name.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1e7e7d9f9fb914753617ca6cd5ca8b3eebe36b0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Name.class differ
diff --git a/src/main/resources/org/python/antlr/ast/NameDerived.class b/src/main/resources/org/python/antlr/ast/NameDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6945819800a639792cc644e71ce5b64dccdbfa5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/NameDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$Num___init___exposer.class b/src/main/resources/org/python/antlr/ast/Num$Num___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e95fce3053521c4df1aede3988e22d73e51a998
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$Num___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$PyExposer.class b/src/main/resources/org/python/antlr/ast/Num$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6dadbf8bf34fa206e85a27195e17ae319e264a1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Num$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ad9f600dccc5b0d7bf80d9afd816039fad45214
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Num$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f98c271cbfc0857d358930bb5562737a107e8ad3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Num$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bd8665d48d6471915e949259ecf0ff2f5a6f935
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Num$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8da5e58f33899f06c663a27a8c75bfdb78685a0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Num$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b31ca8a5b48e6af97d9fb8ccb14a86d714b102b8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$n_descriptor.class b/src/main/resources/org/python/antlr/ast/Num$n_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae433709dda61bc3d73ece975eb9573e39402356
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$n_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Num$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9203dfcd24d9060f82cb15cc453e6a3daa5c8c82
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Num.class b/src/main/resources/org/python/antlr/ast/Num.class
new file mode 100644
index 0000000000000000000000000000000000000000..5146385b78fb12b58d0ac2509866e20de3b965ab
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Num.class differ
diff --git a/src/main/resources/org/python/antlr/ast/NumDerived.class b/src/main/resources/org/python/antlr/ast/NumDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..22394dff8c192f8106f62d90855e14e0f79e2c5b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/NumDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass$Pass___init___exposer.class b/src/main/resources/org/python/antlr/ast/Pass$Pass___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..121c379dfccc01f7ab2e87b96131dbe866fbc168
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass$Pass___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass$PyExposer.class b/src/main/resources/org/python/antlr/ast/Pass$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..18331a5451d029315fba26a9f486134dfd254ec4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Pass$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..acfcc4c0f81c0c943dd35adb0a28cde7841aea55
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Pass$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..998d139aeabd91833edbb1b8797718774c314f34
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Pass$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..156b94325cb119a7ee7c63d4ff06d465b5a123f8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Pass$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..e869bc515c7768eff2a2b4be3acc88994d6c3298
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Pass$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..db03d0db3a60eec34517e7a9d2a3d40aaaa3e155
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Pass$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..356ddb65bd49bb42572f3e8c89bb3d0b88ec29f3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Pass.class b/src/main/resources/org/python/antlr/ast/Pass.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2daff1c20621db5d94b83277c7aa2e446cfa548
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Pass.class differ
diff --git a/src/main/resources/org/python/antlr/ast/PassDerived.class b/src/main/resources/org/python/antlr/ast/PassDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d5a734aa9614a65c63b8aaca61239a172de4e40
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/PassDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$Print___init___exposer.class b/src/main/resources/org/python/antlr/ast/Print$Print___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b05423f21f6058f864455e186be889deb4fab11f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$Print___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$PyExposer.class b/src/main/resources/org/python/antlr/ast/Print$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f0edc529a2a8750f0a10bb2b6f8308f387c259f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Print$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..97df58ef5296c76c10b5e5f7004fc0c71d94eb9a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Print$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..28ea957ba8fe3d9fd2af649340e919ad4b611484
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Print$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..922541c14c9b8bbc558f44c23c22e82a35d94669
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$dest_descriptor.class b/src/main/resources/org/python/antlr/ast/Print$dest_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1085432d1757df39b0684fd0a09c09fa5772ea5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$dest_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Print$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..66f4efbe22862a76601fd5eab22d73ea88882952
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Print$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c61eb4367c2bea7e858d247790c0841211034ad3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$nl_descriptor.class b/src/main/resources/org/python/antlr/ast/Print$nl_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f7bf3969d1b23e7086a2b5f7e17573da0a55eaa
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$nl_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Print$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..72d4bec848e902f472a136f84da05ca5705033fa
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print$values_descriptor.class b/src/main/resources/org/python/antlr/ast/Print$values_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea30eb15d38fc257f8f0dde37ee57fc45ef97c13
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print$values_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Print.class b/src/main/resources/org/python/antlr/ast/Print.class
new file mode 100644
index 0000000000000000000000000000000000000000..50dee016d2f5d9dc12ad03a511bc38b1d4bf8df7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Print.class differ
diff --git a/src/main/resources/org/python/antlr/ast/PrintDerived.class b/src/main/resources/org/python/antlr/ast/PrintDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..c560abd17e9543d22eaccdded7d30636b50d8c21
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/PrintDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$PyExposer.class b/src/main/resources/org/python/antlr/ast/Raise$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b813c957f166761a05c567b0bb847b543ac52255
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$Raise___init___exposer.class b/src/main/resources/org/python/antlr/ast/Raise$Raise___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..be937cab2dcba5b5043560a78e1220c19dbc9dd7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$Raise___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Raise$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dbc3ffb227810bcb4a8f31063feaf76840b9cdd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Raise$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a184a7b222def8980b6fce80f9772e32da40158
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Raise$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7e17195aacd4a2cfbd3da387f26e0818be5b128
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Raise$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea36a94b81694093883d14eeac3d75c4cb2fdf86
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$inst_descriptor.class b/src/main/resources/org/python/antlr/ast/Raise$inst_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e7c1e4f6a080fefd0a3512312f4c703ef45a42b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$inst_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Raise$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8927e2a157a623002072ef18202ca72dcbc0db5f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Raise$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d4c55336d9ebe113a32e291a279ba2704ad17ff
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$tback_descriptor.class b/src/main/resources/org/python/antlr/ast/Raise$tback_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..32f678a0d72f0c1db8a776714b6692569a5b94bc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$tback_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise$type_descriptor.class b/src/main/resources/org/python/antlr/ast/Raise$type_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b336ade1128014b9ca2dd66befd64bd1725b4d07
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise$type_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Raise.class b/src/main/resources/org/python/antlr/ast/Raise.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a01131c14ad76ffda47f1e78d000250511d7fb2
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Raise.class differ
diff --git a/src/main/resources/org/python/antlr/ast/RaiseDerived.class b/src/main/resources/org/python/antlr/ast/RaiseDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..208344fe1a8894b3fcd00aa996e2e00ee3884c3b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/RaiseDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$PyExposer.class b/src/main/resources/org/python/antlr/ast/Repr$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f29d43956ce07dc43dab17825cac43e7e7d2ca8e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$Repr___init___exposer.class b/src/main/resources/org/python/antlr/ast/Repr$Repr___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0f938be8127451e0a49779c3b601af0286f4318
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$Repr___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Repr$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3b440d074b66932b181174d68dfcc1994fe98c7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Repr$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9562194ea31a5510e82b4a65cf19677fb2a928a6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Repr$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb68bbe360c3b10aea724e0164e2ba81a782cc1d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Repr$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..85204413c24b1a30bdc281228b35c7722907949d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Repr$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d1135ad25c1db7adcad2cd0a7cc6bcd95099dac8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Repr$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f07db44e33ea5832f277db0aa1cf1ae4ac40421
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr$value_descriptor.class b/src/main/resources/org/python/antlr/ast/Repr$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8fbee9189349720f080131abcaee118b92c7d3a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Repr.class b/src/main/resources/org/python/antlr/ast/Repr.class
new file mode 100644
index 0000000000000000000000000000000000000000..585f0980f9d2bd37e072a03a0121ae84e5b03447
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Repr.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ReprDerived.class b/src/main/resources/org/python/antlr/ast/ReprDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..60329c4b7f125975434c6242afd4bcadf6d89175
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ReprDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$PyExposer.class b/src/main/resources/org/python/antlr/ast/Return$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..50e7acc282d57724bf2b6e1efb5fd38055bdcd0a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$Return___init___exposer.class b/src/main/resources/org/python/antlr/ast/Return$Return___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8892fcfef77402bf57e84d5ccefcd84ee869759
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$Return___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Return$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f0adf628b5c507d7859f31cf8c3a29831f1749c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Return$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9061bcbb686ec6a42dcf9cbc68d284df8ab81729
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Return$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..74e6b1e3339713b57cc799612ebbeda64b2a86e0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Return$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc7dcaa7ae92831598a3ad1e049cf1346989930a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Return$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f8b661ac4b9bcaba69889e39210ae129e51cf5b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Return$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..13911da9a3032a75fd17260e33ed33d591b32597
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return$value_descriptor.class b/src/main/resources/org/python/antlr/ast/Return$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..964b84278f94365ba47e3b021b72381af8a820b9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Return.class b/src/main/resources/org/python/antlr/ast/Return.class
new file mode 100644
index 0000000000000000000000000000000000000000..24546105a101e31be1f98435381eaa419142a425
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Return.class differ
diff --git a/src/main/resources/org/python/antlr/ast/ReturnDerived.class b/src/main/resources/org/python/antlr/ast/ReturnDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9908e279813c798e363c4bf080ca67217bf6a730
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/ReturnDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Set.class b/src/main/resources/org/python/antlr/ast/Set.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fb2a44cda0138de3cdefdaa058ee65347bcf447
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Set.class differ
diff --git a/src/main/resources/org/python/antlr/ast/SetComp.class b/src/main/resources/org/python/antlr/ast/SetComp.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e4115a8d7cfe9e06aab3e41cd9aaecd1344f4f8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/SetComp.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$PyExposer.class b/src/main/resources/org/python/antlr/ast/Slice$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab600e37befdcb21281385cc0c15a0a2cb6678c5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$Slice___init___exposer.class b/src/main/resources/org/python/antlr/ast/Slice$Slice___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e4fefae65049d4cdc8ec206de19ef2a9283d1a4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$Slice___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Slice$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..03b8ae7782ee194744bd5cb2d14da7fc42049424
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Slice$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a349fd501b692b7a1c944305d2991e73f66c1d4e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Slice$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2daa914ade29c616ec2cc333c5c147bfd7161ad
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$lower_descriptor.class b/src/main/resources/org/python/antlr/ast/Slice$lower_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c16557ebb2472b73da9ad4f0ad4c811dbb8023c8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$lower_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Slice$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3723bbef913040aab80be94c70f312ada228d7c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$step_descriptor.class b/src/main/resources/org/python/antlr/ast/Slice$step_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2396b19dac477805096190100432b072076a75e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$step_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice$upper_descriptor.class b/src/main/resources/org/python/antlr/ast/Slice$upper_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..355105fff319755c69da7ee2983cd7753480f509
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice$upper_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Slice.class b/src/main/resources/org/python/antlr/ast/Slice.class
new file mode 100644
index 0000000000000000000000000000000000000000..94520a04ce067d38b6a711d7f61f520fcc6ca48f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Slice.class differ
diff --git a/src/main/resources/org/python/antlr/ast/SliceDerived.class b/src/main/resources/org/python/antlr/ast/SliceDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..132a232e1f2022e19cb6414a97245296097f4aa4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/SliceDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$PyExposer.class b/src/main/resources/org/python/antlr/ast/Str$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad8c1eac90236d2523b829653f8cae4bdc5a5153
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$Str___init___exposer.class b/src/main/resources/org/python/antlr/ast/Str$Str___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b3d7cb3339be737a30c363ae4e5e9f81a0ebefe
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$Str___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Str$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..569ca5e1dad9c7ee5fa7b40b50c7a5ec72956544
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Str$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..79c19f5009e3651b252e96579602bed54522fa0d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Str$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dfa965baec7d56e4f8e2e2caf039d3b95d8c995
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Str$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4368a53030a57a64071bc6a7ece6a57c1ae3f00d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Str$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4654fe699c8c1ba1ebb8fa2fe3eb38cc0623189
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Str$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2e8b900d91f9cce24bca8605f81bcc1129eac68
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str$s_descriptor.class b/src/main/resources/org/python/antlr/ast/Str$s_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..296dc803bea3c2f5c54a6cfa27be770b56a09ccc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str$s_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Str.class b/src/main/resources/org/python/antlr/ast/Str.class
new file mode 100644
index 0000000000000000000000000000000000000000..c59df2695f1aee1190514a6d7eb890d57027e1a7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Str.class differ
diff --git a/src/main/resources/org/python/antlr/ast/StrDerived.class b/src/main/resources/org/python/antlr/ast/StrDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..f20ae428cf213cff298a1cc8fb50daa869553b70
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/StrDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$PyExposer.class b/src/main/resources/org/python/antlr/ast/Subscript$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7e525f8a1f49870c46aeeb2bde088ac96881219
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$Subscript___init___exposer.class b/src/main/resources/org/python/antlr/ast/Subscript$Subscript___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..95eb968bb61ea943fd1a2e0ea529f85752ee9246
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$Subscript___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Subscript$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b8a2136bc804d94bbd09491161549f153026958
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Subscript$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c4f145e68d011654677c9618918361f21adcbef
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Subscript$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..649ccc08378ce7d4e09348a0965e13aff07b9037
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$ctx_descriptor.class b/src/main/resources/org/python/antlr/ast/Subscript$ctx_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..28c75b5110773a8195dde117356d9f61e32914d9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$ctx_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Subscript$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..27b2e31c3d7d951579c59a77658b21da99f43a26
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Subscript$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..eaa3470b9a24701aface82d169bfc2359fc6ea69
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Subscript$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5612db21683846cc71bc44f1a788326eae4c6a4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$slice_descriptor.class b/src/main/resources/org/python/antlr/ast/Subscript$slice_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2525e012ef0da39aaed46a893897e0b61721f2f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$slice_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript$value_descriptor.class b/src/main/resources/org/python/antlr/ast/Subscript$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed6079f5918bb27c80aae72642abe2ee73d16f52
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Subscript.class b/src/main/resources/org/python/antlr/ast/Subscript.class
new file mode 100644
index 0000000000000000000000000000000000000000..63e169c4904d959a9660cab6cc202a3dd6acc68d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Subscript.class differ
diff --git a/src/main/resources/org/python/antlr/ast/SubscriptDerived.class b/src/main/resources/org/python/antlr/ast/SubscriptDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..7276046940176de0ef0ee7893ad4a6a83ec847ac
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/SubscriptDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Suite$PyExposer.class b/src/main/resources/org/python/antlr/ast/Suite$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6677108fe9fcb5d69402302c078305a7940967c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Suite$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Suite$Suite___init___exposer.class b/src/main/resources/org/python/antlr/ast/Suite$Suite___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1aaa7d367201053cffa7864ad6143b5d956c7193
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Suite$Suite___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Suite$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Suite$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcf307ecbd42d2069c67b8e6ff458f31a305e816
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Suite$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Suite$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Suite$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1a85fd6d4fd115992e1cb70e2a95cbd4cbea40d
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Suite$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Suite$body_descriptor.class b/src/main/resources/org/python/antlr/ast/Suite$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3b8beb9a658283e58e2dfe3e309296a4a49f62e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Suite$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Suite$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Suite$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb0825ec5d22592933499aaef1afb61887787869
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Suite$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Suite$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Suite$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..611bcaa8a37bbccf9ce310aa6c9b5e95a60af34f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Suite$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Suite.class b/src/main/resources/org/python/antlr/ast/Suite.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff7d88e5249d73fa1f781f4a25fa175e5c14e8bc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Suite.class differ
diff --git a/src/main/resources/org/python/antlr/ast/SuiteDerived.class b/src/main/resources/org/python/antlr/ast/SuiteDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c3c344d901df61f4bdb91551d358ae22378c63f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/SuiteDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$PyExposer.class b/src/main/resources/org/python/antlr/ast/TryExcept$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ddd407aa80ea224f7118fee59e1b840605cda7f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$TryExcept___init___exposer.class b/src/main/resources/org/python/antlr/ast/TryExcept$TryExcept___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..befbc082241b066c1b5e8cfe911c29d22706bad2
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$TryExcept___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/TryExcept$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..be66124dab000af06035227ab5632255cc728e06
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/TryExcept$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e782093bca13c0bf679aaea67b6950c88a6ae65
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$body_descriptor.class b/src/main/resources/org/python/antlr/ast/TryExcept$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..39636add861775361bec00e34de72cb2c5d61741
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/TryExcept$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2136996771dbab939d3bf9b03b8d0c60691a9b3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$exposed___new__.class b/src/main/resources/org/python/antlr/ast/TryExcept$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa6b560470985c20461e657afe438113c2e091aa
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$handlers_descriptor.class b/src/main/resources/org/python/antlr/ast/TryExcept$handlers_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..45210c1df290e608bd91c7ec299a59a55b19baab
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$handlers_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/TryExcept$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fdffe0e7f4bca4c78b53c6c1a70f20d9212f3f8c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$orelse_descriptor.class b/src/main/resources/org/python/antlr/ast/TryExcept$orelse_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..389b575a109b8cda1a8aeca7264d2baf6aae24c9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$orelse_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/TryExcept$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a28fc81836cac04ad1a4677312c16de94e3d131e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExcept.class b/src/main/resources/org/python/antlr/ast/TryExcept.class
new file mode 100644
index 0000000000000000000000000000000000000000..f76fd811763dbe982576c0ca4e20ce14d3b92adf
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExcept.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryExceptDerived.class b/src/main/resources/org/python/antlr/ast/TryExceptDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..5fef64f49f95d5d7acb6ea3ba5c07a6d45df2df4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryExceptDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$PyExposer.class b/src/main/resources/org/python/antlr/ast/TryFinally$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..41b548e47c6befb7eef53d249309f1e2d217af36
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$TryFinally___init___exposer.class b/src/main/resources/org/python/antlr/ast/TryFinally$TryFinally___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3241721a7d9694655c928edb165cd4bdc3bbe000
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$TryFinally___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/TryFinally$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5786e4c426bf0e5a29f2e78198899f267f8d1fff
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/TryFinally$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4a0bde613b7163887f640e42c4193e4b2ae39eb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$body_descriptor.class b/src/main/resources/org/python/antlr/ast/TryFinally$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1186c912e9fff373fc8f3a01f851b97c942bec33
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/TryFinally$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7395a59cfb83b08449d91adcadaec4ae8549b5e5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$exposed___new__.class b/src/main/resources/org/python/antlr/ast/TryFinally$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..35e39cce948c4d19cb2561a2c9718b4921ead7ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$finalbody_descriptor.class b/src/main/resources/org/python/antlr/ast/TryFinally$finalbody_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ad23c475f6dda01dcc45b15a970e0ae51051fc3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$finalbody_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/TryFinally$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9066a67e5ac1d349e91415835b073219f3c44111
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/TryFinally$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..28a16d4670eac2ffd0ec5ce81f2d3798fb9c77f3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinally.class b/src/main/resources/org/python/antlr/ast/TryFinally.class
new file mode 100644
index 0000000000000000000000000000000000000000..9deca9ccaed3026112de6209667af568874de0e0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinally.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TryFinallyDerived.class b/src/main/resources/org/python/antlr/ast/TryFinallyDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..b196118f693ad17023122c1beaecba0abf870a15
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TryFinallyDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$PyExposer.class b/src/main/resources/org/python/antlr/ast/Tuple$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..32ee493856bb00afbe3eaac2354f60f602b70c54
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$Tuple___init___exposer.class b/src/main/resources/org/python/antlr/ast/Tuple$Tuple___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a006dfc38f49c0ebf84e48233c164fa8e494d71c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$Tuple___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Tuple$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..036aeea54ca677f3c5f6e7feefc3aba3cb1e01de
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Tuple$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..47021c1a36f996bf18b545fff8d7388d410e3af6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Tuple$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..daea0ff02007f663421c8b0c90aa4b7e4642cb15
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$ctx_descriptor.class b/src/main/resources/org/python/antlr/ast/Tuple$ctx_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ef600b4dbe6d4a4831349c378368c4abb5e3ebb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$ctx_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$elts_descriptor.class b/src/main/resources/org/python/antlr/ast/Tuple$elts_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..669ca51981927f28de30789c085af7bb66ff95ad
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$elts_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Tuple$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..893df8bfe59f4463cab84569be75c1edaf4be097
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Tuple$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1384214c7f4ee3a18c4045fbfdb41a9dc4cb176
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Tuple$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..65200562ac604dce92f5e6153dd0413f0cdc1dd5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Tuple.class b/src/main/resources/org/python/antlr/ast/Tuple.class
new file mode 100644
index 0000000000000000000000000000000000000000..42b36e60f5527847609d7d941790229e5012b347
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Tuple.class differ
diff --git a/src/main/resources/org/python/antlr/ast/TupleDerived.class b/src/main/resources/org/python/antlr/ast/TupleDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3a2692ed4ca805e0eb82e59fbfff8ccc4cd24a7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/TupleDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$PyExposer.class b/src/main/resources/org/python/antlr/ast/UnaryOp$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..182e352d395fb626509ba3c7a5e9514643357e7e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$UnaryOp___init___exposer.class b/src/main/resources/org/python/antlr/ast/UnaryOp$UnaryOp___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f6fed8bf03a7dfd00a4c04c99471034fc00b7e3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$UnaryOp___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/UnaryOp$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa52631195d82cf0f7c49c60b9fc65ee2098d7d9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/UnaryOp$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..916826f8503964e8be46e2a85fcd63cc8c4152a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/UnaryOp$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a854fa16507262c1257cc4c4a3ac87d7e6d251c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$exposed___new__.class b/src/main/resources/org/python/antlr/ast/UnaryOp$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..83df0333e641a2c5f7852acd378ab467629f4032
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/UnaryOp$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d782888fbe99e04e3fa576533148d10a8bf5acc3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$op_descriptor.class b/src/main/resources/org/python/antlr/ast/UnaryOp$op_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..659ffac96f56dcebc8bed3e852f07c73ffd0e4fc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$op_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$operand_descriptor.class b/src/main/resources/org/python/antlr/ast/UnaryOp$operand_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4de67934c35ee3580feb5dd1240f246b63fce293
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$operand_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/UnaryOp$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..572232f687d1eef45e11cfe61cdf49e4eb1892ea
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOp.class b/src/main/resources/org/python/antlr/ast/UnaryOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..20667f982ea7e48e9d5b3e6734ebbd9abd188e74
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOp.class differ
diff --git a/src/main/resources/org/python/antlr/ast/UnaryOpDerived.class b/src/main/resources/org/python/antlr/ast/UnaryOpDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..534229c782ccb85a4708e5363905f99ae70bcf27
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/UnaryOpDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/VisitorBase.class b/src/main/resources/org/python/antlr/ast/VisitorBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6f61a823eeea458ff1c96d2eef6dd993838ea3e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/VisitorBase.class differ
diff --git a/src/main/resources/org/python/antlr/ast/VisitorIF.class b/src/main/resources/org/python/antlr/ast/VisitorIF.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0fc09ca0c979fe5fb5263e6af262ab325675034
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/VisitorIF.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$PyExposer.class b/src/main/resources/org/python/antlr/ast/While$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bf59744546a6e1285c61530324c7c51beb8528a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$While___init___exposer.class b/src/main/resources/org/python/antlr/ast/While$While___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6371cce451810bc59eb6af51da1d5294a36700b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$While___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/While$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfe4dfab82ad2788923a65b1968c53c40d2eac82
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/While$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..42b79bc1d5ef680ae680630c9c4b8b84f0a559ce
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$body_descriptor.class b/src/main/resources/org/python/antlr/ast/While$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2eeb5f2806f931d521ceab2a7d11f4e8868ab811
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/While$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0784dc0ec58fc93aec6ea90ec11367fac0d7c743
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$exposed___new__.class b/src/main/resources/org/python/antlr/ast/While$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d1399b0a8a77759105050642d5507d1451c8a58
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/While$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8929ef92bcbeb788b374933543be5b4fc86bae03
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$orelse_descriptor.class b/src/main/resources/org/python/antlr/ast/While$orelse_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a61b4cc8abdb7525026fb74e239f1d2bd54d82ca
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$orelse_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/While$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2b273bebe742cc2d54ac284154643611aaaf7e3
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While$test_descriptor.class b/src/main/resources/org/python/antlr/ast/While$test_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..53e606a8779e963068f68d6f36234077a08e5989
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While$test_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/While.class b/src/main/resources/org/python/antlr/ast/While.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d30fb301deacc018cffa0ec47f4a19b7fa5f038
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/While.class differ
diff --git a/src/main/resources/org/python/antlr/ast/WhileDerived.class b/src/main/resources/org/python/antlr/ast/WhileDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..812817ddf834b6f2848fca537b4bea10756630a4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/WhileDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$PyExposer.class b/src/main/resources/org/python/antlr/ast/With$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe3537775dbdeaebdc13ae3a4ad4bac7364154ee
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$With___init___exposer.class b/src/main/resources/org/python/antlr/ast/With$With___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..48c3a81c5d22a7d493fadcbd925f07fd8bc2c33c
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$With___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/With$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b75ac7224233990021c36c225ff5a40755321aed
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/With$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..05e02d62daba04b500ea0edec7201f325a971d7a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$body_descriptor.class b/src/main/resources/org/python/antlr/ast/With$body_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d61de0b44c08968cf367481d11c83c61a19e46ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$body_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/With$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..889fe5467bb7502560a0197fd6c16a84d6aa2bb8
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$context_expr_descriptor.class b/src/main/resources/org/python/antlr/ast/With$context_expr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a12f4d35aaa22d763a930495f9b5e2945f1b513
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$context_expr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$exposed___new__.class b/src/main/resources/org/python/antlr/ast/With$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dc9110436db53e58ce05faebf1b9f4a289216d7
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/With$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb6ae18cb08eaa0b61412798208068d90c4a2e32
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$optional_vars_descriptor.class b/src/main/resources/org/python/antlr/ast/With$optional_vars_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..38e40cd39baa9219522663ff18bd0ca0d633d67f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$optional_vars_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/With$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf7529b854a91f9c6d405ca6ee7d49be4814baf9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/With.class b/src/main/resources/org/python/antlr/ast/With.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4dd7757de0f154e6b823bbd9726c694c1997053
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/With.class differ
diff --git a/src/main/resources/org/python/antlr/ast/WithDerived.class b/src/main/resources/org/python/antlr/ast/WithDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c41f927c32f836720ec804236db5ec2cf8b6ee5
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/WithDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$PyExposer.class b/src/main/resources/org/python/antlr/ast/Yield$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f71aed10de2668d0c10cad1eac3ed0de8c59ce83
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$Yield___init___exposer.class b/src/main/resources/org/python/antlr/ast/Yield$Yield___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8f89dea936059696509fbdc10233bb14762bdc0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$Yield___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/Yield$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6026c2eb9162fa2c1acc7f33569478c3d7406d0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/Yield$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4a26a75009df0c9adfa712c88cd3a9151099d67
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$col_offset_descriptor.class b/src/main/resources/org/python/antlr/ast/Yield$col_offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ddee61f89157bc6afa19cb69ff1e18f750f72cc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$col_offset_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$exposed___new__.class b/src/main/resources/org/python/antlr/ast/Yield$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6d510eec6c3b23a640019decf6cd92402ccf553
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$lineno_descriptor.class b/src/main/resources/org/python/antlr/ast/Yield$lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc5892f0533df67c10e14529934ebeb70bc200c9
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/Yield$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b733cd49ec2698d6fbc8cec0341b24ff7484aff
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield$value_descriptor.class b/src/main/resources/org/python/antlr/ast/Yield$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fae3a96a887c517f64f60710449820aad1c7a11e
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/Yield.class b/src/main/resources/org/python/antlr/ast/Yield.class
new file mode 100644
index 0000000000000000000000000000000000000000..fce5900ca9c00c6b1ddb2361950e60a4a2c85aeb
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/Yield.class differ
diff --git a/src/main/resources/org/python/antlr/ast/YieldDerived.class b/src/main/resources/org/python/antlr/ast/YieldDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..d390751434afe7c73c61916ca8439b4e8bfaea73
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/YieldDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias$PyExposer.class b/src/main/resources/org/python/antlr/ast/alias$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6076a0b980a888278c2f995385702031b9b4190f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/alias$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc42003f5f74d627e25127124f6fc28713bfe874
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/alias$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..616fb7a91e651ae863dcb1d1457cf2cefb9c90c1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias$alias___init___exposer.class b/src/main/resources/org/python/antlr/ast/alias$alias___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc2c3bb1de06c0d17b532ad51bb8b58a0cbfbdbf
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias$alias___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias$asname_descriptor.class b/src/main/resources/org/python/antlr/ast/alias$asname_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ab2039a8dc0a2d0c55ba064a55ac796aedc3cbf
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias$asname_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias$exposed___new__.class b/src/main/resources/org/python/antlr/ast/alias$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..86ce359a5578364cec4b9a0f27939592db9a2f17
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias$name_descriptor.class b/src/main/resources/org/python/antlr/ast/alias$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1dd67bbb10da0af646d8639d849999e22796b48
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias$name_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/alias$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..731938f7b3fc4dc08c83c9f0592235910b87a35a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/alias.class b/src/main/resources/org/python/antlr/ast/alias.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3be599364061daff8778e971c3403c7f8fdc732
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/alias.class differ
diff --git a/src/main/resources/org/python/antlr/ast/aliasDerived.class b/src/main/resources/org/python/antlr/ast/aliasDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c0888d5cfd9766a37a9349973d5dffece57b659
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/aliasDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$PyExposer.class b/src/main/resources/org/python/antlr/ast/arguments$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b391968f7588f8ea75422091f7efe52499b4a27b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/arguments$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2d59ebb7f49f5613067ede0800c8c77a8a73191
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/arguments$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6cccbbcc6199bb735a463f4a11023d0913c9ba0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$args_descriptor.class b/src/main/resources/org/python/antlr/ast/arguments$args_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e45d93e5f64e1dd4a8bd297c8fcdf5ddadf13f0
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$args_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$arguments___init___exposer.class b/src/main/resources/org/python/antlr/ast/arguments$arguments___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa12dc8f9abb16782df564e4481d696bd3b7b48a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$arguments___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$defaults_descriptor.class b/src/main/resources/org/python/antlr/ast/arguments$defaults_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fd5af7b44f9155f082592666ef92e4f0bda592f
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$defaults_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$exposed___new__.class b/src/main/resources/org/python/antlr/ast/arguments$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..af59fdec289fecd18e1db29e75ce292718edef83
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$kwarg_descriptor.class b/src/main/resources/org/python/antlr/ast/arguments$kwarg_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6df9d7656d97e30249dd0c18d161ee79289b4ba
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$kwarg_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/arguments$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..35bf192eabe80c3a6b4d337172213e747aa12c24
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments$vararg_descriptor.class b/src/main/resources/org/python/antlr/ast/arguments$vararg_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..15d80e21cde46abd390bd30baccbe793d95f3317
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments$vararg_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/arguments.class b/src/main/resources/org/python/antlr/ast/arguments.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d49a93169fc4fe4bb9a2d9e3c642d9d9edef50b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/arguments.class differ
diff --git a/src/main/resources/org/python/antlr/ast/argumentsDerived.class b/src/main/resources/org/python/antlr/ast/argumentsDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d6ff89401d1829172497833c5faeb403b3e2cd6
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/argumentsDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/boolopType.class b/src/main/resources/org/python/antlr/ast/boolopType.class
new file mode 100644
index 0000000000000000000000000000000000000000..252c8c0062e62663cd3d202787f0422f1c11292a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/boolopType.class differ
diff --git a/src/main/resources/org/python/antlr/ast/cmpopType.class b/src/main/resources/org/python/antlr/ast/cmpopType.class
new file mode 100644
index 0000000000000000000000000000000000000000..87522d2be78e6c6b2999a5a06d76fbdc58c5e922
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/cmpopType.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$PyExposer.class b/src/main/resources/org/python/antlr/ast/comprehension$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..671021358f2626e52c026c75b556525de1b3db44
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/comprehension$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd2e0713ff0dd61f07a97c2cd360a777de35e6a4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/comprehension$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2f82b6597b7de12aab4c0e6248fecdcfdf18b92
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$comprehension___init___exposer.class b/src/main/resources/org/python/antlr/ast/comprehension$comprehension___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f290309d00bf363de336f61920a9ef33a300b562
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$comprehension___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$exposed___new__.class b/src/main/resources/org/python/antlr/ast/comprehension$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f292bd96515ad36dd9781376dc4ef65f10a64fc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$ifs_descriptor.class b/src/main/resources/org/python/antlr/ast/comprehension$ifs_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7e988aa79aa3862137f60cb80935487c9530541
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$ifs_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$iter_descriptor.class b/src/main/resources/org/python/antlr/ast/comprehension$iter_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..13731d7ab7926203ca470a1b4eba046b85be42e4
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$iter_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/comprehension$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5484cfa3682232b25bea80bbd99eda0107bd28ac
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension$target_descriptor.class b/src/main/resources/org/python/antlr/ast/comprehension$target_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5cca7713a568f296beac52e64f9553da3fd560dc
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension$target_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehension.class b/src/main/resources/org/python/antlr/ast/comprehension.class
new file mode 100644
index 0000000000000000000000000000000000000000..0159347de6a8e7be57159f982febee1c0aece727
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehension.class differ
diff --git a/src/main/resources/org/python/antlr/ast/comprehensionDerived.class b/src/main/resources/org/python/antlr/ast/comprehensionDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9413f1e0fd547797eeb190192851044466460223
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/comprehensionDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/expr_contextType.class b/src/main/resources/org/python/antlr/ast/expr_contextType.class
new file mode 100644
index 0000000000000000000000000000000000000000..be4734f6ceb9658b3f3f93e49c9cdf02798b5e49
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/expr_contextType.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword$PyExposer.class b/src/main/resources/org/python/antlr/ast/keyword$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..09871bf14fa2dbf44d271a14eb841b9aa52237ce
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword$_attributes_descriptor.class b/src/main/resources/org/python/antlr/ast/keyword$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9cf1f1c82891fc04005d3297dffb3b66845c41ec
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword$_fields_descriptor.class b/src/main/resources/org/python/antlr/ast/keyword$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b33a4f346ff92251d43ae52ca2ec311df9afba35
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword$arg_descriptor.class b/src/main/resources/org/python/antlr/ast/keyword$arg_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a76bac10f8d6f9d289c6c9b88f55b5829543e3f1
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword$arg_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword$exposed___new__.class b/src/main/resources/org/python/antlr/ast/keyword$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f9092bbe6bbf18f02a88d606845ee4970a6c356
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword$keyword___init___exposer.class b/src/main/resources/org/python/antlr/ast/keyword$keyword___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bf27d22ec4c8cdbc5ca681161a0cd74c636f1ba
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword$keyword___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword$repr_descriptor.class b/src/main/resources/org/python/antlr/ast/keyword$repr_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e24543d5d15c6d6a00ce7c25c2dc2e0b9b5e3c5a
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword$repr_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword$value_descriptor.class b/src/main/resources/org/python/antlr/ast/keyword$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d874f9a456fc7cb0e44eed0dacffe335332b8775
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword$value_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keyword.class b/src/main/resources/org/python/antlr/ast/keyword.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a7aaaa4f5817a32c8a949fc65fbde2abe0ebb5b
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keyword.class differ
diff --git a/src/main/resources/org/python/antlr/ast/keywordDerived.class b/src/main/resources/org/python/antlr/ast/keywordDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3977fa3d1ac53acc850f0aa2ef918fa889b8efdd
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/keywordDerived.class differ
diff --git a/src/main/resources/org/python/antlr/ast/operatorType.class b/src/main/resources/org/python/antlr/ast/operatorType.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef3100051b6b032f07bea4069272f697a55fd230
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/operatorType.class differ
diff --git a/src/main/resources/org/python/antlr/ast/unaryopType.class b/src/main/resources/org/python/antlr/ast/unaryopType.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a4287d4e44e35f4d7f375b10fd4b92492b0dd62
Binary files /dev/null and b/src/main/resources/org/python/antlr/ast/unaryopType.class differ
diff --git a/src/main/resources/org/python/antlr/base/excepthandler$PyExposer.class b/src/main/resources/org/python/antlr/base/excepthandler$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..853993b1285630e85c65e2a00b2a8a52b6af0ca3
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/excepthandler$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/base/excepthandler$_attributes_descriptor.class b/src/main/resources/org/python/antlr/base/excepthandler$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d2ed5b1e496aa66ecb98518af2a808563e6c285
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/excepthandler$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/excepthandler$_fields_descriptor.class b/src/main/resources/org/python/antlr/base/excepthandler$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c962c04296ecb57825d8cd74971af5b8d66de880
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/excepthandler$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/excepthandler.class b/src/main/resources/org/python/antlr/base/excepthandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..58177d836641c77af4fa5a167a1dd2b0c95f021e
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/excepthandler.class differ
diff --git a/src/main/resources/org/python/antlr/base/expr$PyExposer.class b/src/main/resources/org/python/antlr/base/expr$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..104628942c9cddcbd0ea52694b01ef65073f75e2
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/expr$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/base/expr$_attributes_descriptor.class b/src/main/resources/org/python/antlr/base/expr$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..942afc21dcb903a80804003b91a9fddee229fbf6
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/expr$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/expr$_fields_descriptor.class b/src/main/resources/org/python/antlr/base/expr$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..11217243f40ca8a29b7e5503210223227471177d
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/expr$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/expr.class b/src/main/resources/org/python/antlr/base/expr.class
new file mode 100644
index 0000000000000000000000000000000000000000..451644d6ac8f8a8da12249eb825c091c0f91798e
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/expr.class differ
diff --git a/src/main/resources/org/python/antlr/base/mod$PyExposer.class b/src/main/resources/org/python/antlr/base/mod$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..efd540f123e558a30383d3428d7a8564e98720e0
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/mod$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/base/mod$_attributes_descriptor.class b/src/main/resources/org/python/antlr/base/mod$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5cc80308de723b0fad3bffd2e139146a7738d2dd
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/mod$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/mod$_fields_descriptor.class b/src/main/resources/org/python/antlr/base/mod$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdb09fa739dfca593a706fcd96370f930e3e035e
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/mod$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/mod.class b/src/main/resources/org/python/antlr/base/mod.class
new file mode 100644
index 0000000000000000000000000000000000000000..fef3dc62c770eac4a991c4c0a17dc00155f3722d
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/mod.class differ
diff --git a/src/main/resources/org/python/antlr/base/slice$PyExposer.class b/src/main/resources/org/python/antlr/base/slice$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..83c1c4796b3a542e32fc74126d1cc0a45d590ef5
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/slice$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/base/slice$_attributes_descriptor.class b/src/main/resources/org/python/antlr/base/slice$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b748da3952720a935e3ac8f2b8533d4ad9c53a3
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/slice$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/slice$_fields_descriptor.class b/src/main/resources/org/python/antlr/base/slice$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dc6018279f099e59512577c0f83e7a4df1bdf5e
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/slice$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/slice.class b/src/main/resources/org/python/antlr/base/slice.class
new file mode 100644
index 0000000000000000000000000000000000000000..eac323ae15401a60882df3a64565ad223eee69c0
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/slice.class differ
diff --git a/src/main/resources/org/python/antlr/base/stmt$PyExposer.class b/src/main/resources/org/python/antlr/base/stmt$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..05ebc49f69e85f6651f2a8f4781cc712f4e13562
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/stmt$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/base/stmt$_attributes_descriptor.class b/src/main/resources/org/python/antlr/base/stmt$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..456caeb3f96b2103b38bd03b72fb5c24f89ca73c
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/stmt$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/stmt$_fields_descriptor.class b/src/main/resources/org/python/antlr/base/stmt$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f9a8930d792e9f47f87134e61bbe23192c403d6
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/stmt$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/base/stmt.class b/src/main/resources/org/python/antlr/base/stmt.class
new file mode 100644
index 0000000000000000000000000000000000000000..a65dfd3a5382a39dd6736c80322af7dd7d012f03
Binary files /dev/null and b/src/main/resources/org/python/antlr/base/stmt.class differ
diff --git a/src/main/resources/org/python/antlr/op/Add$Add___init___exposer.class b/src/main/resources/org/python/antlr/op/Add$Add___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1827b6a1af3d0c328de261d9736db976a3607166
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Add$Add___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Add$PyExposer.class b/src/main/resources/org/python/antlr/op/Add$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6d9047c08c31d0298a30a5ea4ca59ad64b9425c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Add$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Add$__int___exposer.class b/src/main/resources/org/python/antlr/op/Add$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7aeb21e7a33107621bb63de0b254e4dd045dfb7
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Add$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Add$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Add$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d077a1eca995d61a8df56c8b4f95bf37d3efef6
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Add$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Add$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Add$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5ec558ffea2a6ca3896890d25bba5ed1835cc14
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Add$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Add$exposed___new__.class b/src/main/resources/org/python/antlr/op/Add$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a4937c20ead03f7c69bc1b1e58267a08086687c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Add$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Add.class b/src/main/resources/org/python/antlr/op/Add.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9f71048d35129f6559e8ed4a76949b39a1326b0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Add.class differ
diff --git a/src/main/resources/org/python/antlr/op/AddDerived.class b/src/main/resources/org/python/antlr/op/AddDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ef2d559d3ad7e0d66341900ce1b5c2f9da4fb6c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AddDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/And$And___init___exposer.class b/src/main/resources/org/python/antlr/op/And$And___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..398d8a857291c448b254cb9a5fe3a07e23486f59
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/And$And___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/And$PyExposer.class b/src/main/resources/org/python/antlr/op/And$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e8a8bd05f404edb1ca793c32a39d1d977227c37
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/And$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/And$__int___exposer.class b/src/main/resources/org/python/antlr/op/And$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fc1afc71d771d350a307079a227afcef113ffb5
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/And$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/And$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/And$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..89508da209091cc94ab2617f2e17f007d2505b08
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/And$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/And$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/And$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e6249925cb3c52241af1d4a783491912dc2a342
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/And$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/And$exposed___new__.class b/src/main/resources/org/python/antlr/op/And$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..87c58a81e0eac411d71c98277a623cf772d15530
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/And$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/And.class b/src/main/resources/org/python/antlr/op/And.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bd9c22ddb8ffec77e04813bae0efa150a74e755
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/And.class differ
diff --git a/src/main/resources/org/python/antlr/op/AndDerived.class b/src/main/resources/org/python/antlr/op/AndDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3744450ab4db82932dd8f10b380c311942c63b6f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AndDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugLoad$AugLoad___init___exposer.class b/src/main/resources/org/python/antlr/op/AugLoad$AugLoad___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b394b1c5cb2f668f977d4fd4e09787507f8fa
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugLoad$AugLoad___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugLoad$PyExposer.class b/src/main/resources/org/python/antlr/op/AugLoad$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..572eadcc301c495765ab00741de41a06e782fab2
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugLoad$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugLoad$__int___exposer.class b/src/main/resources/org/python/antlr/op/AugLoad$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..438cf3c1d56f1a4c114bcadb1241240cdebdb3ce
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugLoad$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugLoad$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/AugLoad$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2affb47a07ff6c7a900c3ca5a39202f545dffb9
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugLoad$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugLoad$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/AugLoad$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b98b26201e1096d7f910aaa0f041b3c52bdb804c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugLoad$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugLoad$exposed___new__.class b/src/main/resources/org/python/antlr/op/AugLoad$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..469bdee057af0e41450bf673ec5d240902fff5aa
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugLoad$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugLoad.class b/src/main/resources/org/python/antlr/op/AugLoad.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b188bd247e3e28b0454dfd2b1a0618df063bf13
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugLoad.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugLoadDerived.class b/src/main/resources/org/python/antlr/op/AugLoadDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..d28be80a676c0c2b14559543fded6c5c27144168
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugLoadDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugStore$AugStore___init___exposer.class b/src/main/resources/org/python/antlr/op/AugStore$AugStore___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae28437f17646ff3e933cf46688087b319a77232
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugStore$AugStore___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugStore$PyExposer.class b/src/main/resources/org/python/antlr/op/AugStore$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f41db85e2b6a239d43153418ec701986dfca0aa
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugStore$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugStore$__int___exposer.class b/src/main/resources/org/python/antlr/op/AugStore$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..93db9ca23fb71b7b80c82007bb27d93525ad95d0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugStore$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugStore$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/AugStore$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c5ee96ac06c49961419102744d9b84629bac1205
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugStore$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugStore$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/AugStore$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a9e2ed063772def76ef9789811f01226f109992
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugStore$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugStore$exposed___new__.class b/src/main/resources/org/python/antlr/op/AugStore$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c82c526bf7539048551decf63c47f4fde60be8b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugStore$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugStore.class b/src/main/resources/org/python/antlr/op/AugStore.class
new file mode 100644
index 0000000000000000000000000000000000000000..02dbcd404a4d017d5a6958998cabb89767d22652
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugStore.class differ
diff --git a/src/main/resources/org/python/antlr/op/AugStoreDerived.class b/src/main/resources/org/python/antlr/op/AugStoreDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b7b9831df56badc98eb3bb62c7bfd9833c1c4a3
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/AugStoreDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitAnd$BitAnd___init___exposer.class b/src/main/resources/org/python/antlr/op/BitAnd$BitAnd___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f12f19624ff61ea1bff97cbbb4a227622f12a53d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitAnd$BitAnd___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitAnd$PyExposer.class b/src/main/resources/org/python/antlr/op/BitAnd$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..60c0100428f7d98d3380b95c5512059a6e234345
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitAnd$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitAnd$__int___exposer.class b/src/main/resources/org/python/antlr/op/BitAnd$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..49f6f6a846c95e69d12ea43535913148a8747dac
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitAnd$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitAnd$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/BitAnd$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb9aafad092491e49282d5dd6d0d9484c0e37c63
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitAnd$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitAnd$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/BitAnd$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..136502ff980f56e9d9d6eda4ea84b77d9d383266
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitAnd$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitAnd$exposed___new__.class b/src/main/resources/org/python/antlr/op/BitAnd$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..99add42e429c2709588ded1abe5f7d28348dc8d6
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitAnd$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitAnd.class b/src/main/resources/org/python/antlr/op/BitAnd.class
new file mode 100644
index 0000000000000000000000000000000000000000..e080202df06ec3258338efb96ad5423039aa3b17
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitAnd.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitAndDerived.class b/src/main/resources/org/python/antlr/op/BitAndDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8a6f96703124f9b33d97d61d5db1f8cf3a68015
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitAndDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitOr$BitOr___init___exposer.class b/src/main/resources/org/python/antlr/op/BitOr$BitOr___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d369ce6065602ba0554f18d7e3144f41b6fddb62
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitOr$BitOr___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitOr$PyExposer.class b/src/main/resources/org/python/antlr/op/BitOr$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4a9961da98448f9f2175cc5eacfcaaeab327cc6
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitOr$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitOr$__int___exposer.class b/src/main/resources/org/python/antlr/op/BitOr$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7549f7c9259b29c9f60ea3d926cfb9abb32b6d0b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitOr$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitOr$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/BitOr$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..370642b8eb3da6b2732339dc41e7a7e0b400a498
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitOr$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitOr$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/BitOr$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bb7d5c935d862ce3c0636e30a15133405767c62
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitOr$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitOr$exposed___new__.class b/src/main/resources/org/python/antlr/op/BitOr$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..58340841c7d246efbc44456ae2b7b343d6eee014
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitOr$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitOr.class b/src/main/resources/org/python/antlr/op/BitOr.class
new file mode 100644
index 0000000000000000000000000000000000000000..885986cbf30e24d0269a4aa9e7c2e0577463497c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitOr.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitOrDerived.class b/src/main/resources/org/python/antlr/op/BitOrDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..a511fcdd43175b71786dc7c82504b7e448d4c035
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitOrDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitXor$BitXor___init___exposer.class b/src/main/resources/org/python/antlr/op/BitXor$BitXor___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4cf4029567eea910c29cd67ab101d691f0838d81
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitXor$BitXor___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitXor$PyExposer.class b/src/main/resources/org/python/antlr/op/BitXor$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f4e6e74916e3dedec9b4b72e603c9c43150b292
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitXor$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitXor$__int___exposer.class b/src/main/resources/org/python/antlr/op/BitXor$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dfdf5f662751440a4645441c85245eec9966df1e
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitXor$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitXor$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/BitXor$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0124d80d5e26f8882690a9f3c32c35d345f3af5
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitXor$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitXor$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/BitXor$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..168240504b1df65c3f0e2284d2c2bac1b6301e51
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitXor$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitXor$exposed___new__.class b/src/main/resources/org/python/antlr/op/BitXor$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..46a758823e61ffdc5a3962a541fe0b79f0fe7601
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitXor$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitXor.class b/src/main/resources/org/python/antlr/op/BitXor.class
new file mode 100644
index 0000000000000000000000000000000000000000..97f5787adfe42cdddfa807b37c00922279baaf1d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitXor.class differ
diff --git a/src/main/resources/org/python/antlr/op/BitXorDerived.class b/src/main/resources/org/python/antlr/op/BitXorDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..af25ccc87f8aa7d578ab86e3ef6d36c3682484ee
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/BitXorDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Del$Del___init___exposer.class b/src/main/resources/org/python/antlr/op/Del$Del___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..469370ded8128ead139f05bb1f0bbe0d39828a4b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Del$Del___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Del$PyExposer.class b/src/main/resources/org/python/antlr/op/Del$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c95ecbb883aebf82b67247dd3aa354ec2bb126f2
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Del$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Del$__int___exposer.class b/src/main/resources/org/python/antlr/op/Del$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e2b54cb88e63404df53826ff0524cda062ab30f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Del$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Del$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Del$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6663a3d4a17e2b580cb43982d34527f61bc8930d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Del$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Del$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Del$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..dfd315a0bf802576103ce3bd125caec56465343f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Del$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Del$exposed___new__.class b/src/main/resources/org/python/antlr/op/Del$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..1504c14fbc700ba18ed4dd14203ab17da0a53be0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Del$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Del.class b/src/main/resources/org/python/antlr/op/Del.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d5554f004b5dc783c6f9d9b6ee1bd012ec8cfa3
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Del.class differ
diff --git a/src/main/resources/org/python/antlr/op/DelDerived.class b/src/main/resources/org/python/antlr/op/DelDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e06666f4f65ac83d39a522b2d64aafa762b8708
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/DelDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Div$Div___init___exposer.class b/src/main/resources/org/python/antlr/op/Div$Div___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab0ac3d6a4e74bc206411a60c69b7ca34fd8dc67
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Div$Div___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Div$PyExposer.class b/src/main/resources/org/python/antlr/op/Div$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bec73c60318304b10ca12b8c75d0144a2a36750
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Div$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Div$__int___exposer.class b/src/main/resources/org/python/antlr/op/Div$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a19efe861f543e88adddb32862d4be1bd3aa8f52
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Div$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Div$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Div$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..33d7dc1dfa45bfb4f229868b946524ea60dab74a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Div$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Div$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Div$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..08cdf73da7f826eda09000609c61191725b76b4c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Div$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Div$exposed___new__.class b/src/main/resources/org/python/antlr/op/Div$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc635122d743aefd71e04661092923ae8f12c8d1
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Div$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Div.class b/src/main/resources/org/python/antlr/op/Div.class
new file mode 100644
index 0000000000000000000000000000000000000000..05d28755a7df99fa423e58409241d9f973f41471
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Div.class differ
diff --git a/src/main/resources/org/python/antlr/op/DivDerived.class b/src/main/resources/org/python/antlr/op/DivDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..28d9d2760be448dfe46f7bff276ecb102666759d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/DivDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Eq$Eq___init___exposer.class b/src/main/resources/org/python/antlr/op/Eq$Eq___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..48a2809871987aa51310c73753f95f7e07fdeadd
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Eq$Eq___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Eq$PyExposer.class b/src/main/resources/org/python/antlr/op/Eq$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..438b6a8ee1794d9ce83eceaf72162dd3b9be6084
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Eq$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Eq$__int___exposer.class b/src/main/resources/org/python/antlr/op/Eq$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9561f388137f0111dca71175dec53f4e15117235
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Eq$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Eq$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Eq$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3eceded759363efcaf13dc5ecdbe0c3828af00e1
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Eq$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Eq$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Eq$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..41161efb33b3d4bd34f49abc39854a8d7a322bab
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Eq$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Eq$exposed___new__.class b/src/main/resources/org/python/antlr/op/Eq$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b475ad823e2c7478d009d453f45af8e2e63b79b0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Eq$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Eq.class b/src/main/resources/org/python/antlr/op/Eq.class
new file mode 100644
index 0000000000000000000000000000000000000000..081231847c031230ff658df93161584212ac4c54
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Eq.class differ
diff --git a/src/main/resources/org/python/antlr/op/EqDerived.class b/src/main/resources/org/python/antlr/op/EqDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..993b2279ef2c9726157e89612f46046326d1a39b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/EqDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/FloorDiv$FloorDiv___init___exposer.class b/src/main/resources/org/python/antlr/op/FloorDiv$FloorDiv___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1522ec215e245deb82eff3743966ddaefb8625a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/FloorDiv$FloorDiv___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/FloorDiv$PyExposer.class b/src/main/resources/org/python/antlr/op/FloorDiv$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..edcd61d0d80aa51b05fa210a9abc2f34fbfcf309
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/FloorDiv$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/FloorDiv$__int___exposer.class b/src/main/resources/org/python/antlr/op/FloorDiv$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8699462abcf0663da96060ec21186a15c79b422b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/FloorDiv$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/FloorDiv$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/FloorDiv$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1927dac4e5dad8172cf9117a30553a46014438a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/FloorDiv$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/FloorDiv$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/FloorDiv$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..22722bc602028086c9b5671d9b46b1b1ea03933f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/FloorDiv$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/FloorDiv$exposed___new__.class b/src/main/resources/org/python/antlr/op/FloorDiv$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..775a2a6570aa760c9f5691ed51a33756927985e7
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/FloorDiv$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/FloorDiv.class b/src/main/resources/org/python/antlr/op/FloorDiv.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccc58161d436aa774aebc69221ceaabe0dbdc459
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/FloorDiv.class differ
diff --git a/src/main/resources/org/python/antlr/op/FloorDivDerived.class b/src/main/resources/org/python/antlr/op/FloorDivDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..41f5ca62c9c1c7c0fd8dee3599e019a33d81eb4a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/FloorDivDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Gt$Gt___init___exposer.class b/src/main/resources/org/python/antlr/op/Gt$Gt___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0ce5908f69be65d54131b3f27655ab1e8e61a77
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Gt$Gt___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Gt$PyExposer.class b/src/main/resources/org/python/antlr/op/Gt$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0c2c148d59009f8350e7f0369c12e95b6c70ff4
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Gt$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Gt$__int___exposer.class b/src/main/resources/org/python/antlr/op/Gt$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e16f47cf213c7ae2044974bbe01a172289277375
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Gt$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Gt$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Gt$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1614bd972b5e5a22b55a4e85a4c46128e41c2c3
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Gt$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Gt$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Gt$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b2119d5929dfe79ae8d0e05424ccb476ae4ab78
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Gt$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Gt$exposed___new__.class b/src/main/resources/org/python/antlr/op/Gt$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..277f8fbbf75b6717ace3a89b2429d8d64697716c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Gt$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Gt.class b/src/main/resources/org/python/antlr/op/Gt.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d1920038e6446043f95abe9530819454b11a099
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Gt.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtDerived.class b/src/main/resources/org/python/antlr/op/GtDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..d420552094d394b77fd76ce58e3ca65d5c4ffb33
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtE$GtE___init___exposer.class b/src/main/resources/org/python/antlr/op/GtE$GtE___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..40a4b30fedf128fcc509e7780d7e482bf393acfe
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtE$GtE___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtE$PyExposer.class b/src/main/resources/org/python/antlr/op/GtE$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f7b9b9b8cb3b8df0c37004287d2b9c7e73a5d95
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtE$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtE$__int___exposer.class b/src/main/resources/org/python/antlr/op/GtE$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..674bf8298538a2489460a06932c038c60fd1eb65
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtE$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtE$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/GtE$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..976317a82606877edb8a280e3bb6fdafcac98bf2
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtE$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtE$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/GtE$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a51d7e1fc6d91f0e4c8edd5e19190f728c6031b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtE$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtE$exposed___new__.class b/src/main/resources/org/python/antlr/op/GtE$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..868d50c8a3385b38f901ed4c2b8b4e95298fe445
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtE$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtE.class b/src/main/resources/org/python/antlr/op/GtE.class
new file mode 100644
index 0000000000000000000000000000000000000000..010af8ed95bce78441411582df8221ae3d281806
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtE.class differ
diff --git a/src/main/resources/org/python/antlr/op/GtEDerived.class b/src/main/resources/org/python/antlr/op/GtEDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ea200493b1f873cac22504465093a9e6537c7bd
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/GtEDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/In$In___init___exposer.class b/src/main/resources/org/python/antlr/op/In$In___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f95149ad433eb7a5888b187f9f54046d4d12a96
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/In$In___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/In$PyExposer.class b/src/main/resources/org/python/antlr/op/In$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6c7574bd84801ab9a506b858b68ff08d7d49e07
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/In$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/In$__int___exposer.class b/src/main/resources/org/python/antlr/op/In$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f66e366ea9827fb633530b09fcf133ea34b91c9c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/In$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/In$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/In$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1b44bb876d9181cfb210b278e70fef162d1054a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/In$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/In$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/In$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..42454a1b72c21dd4d22c50d022b12575745568d0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/In$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/In$exposed___new__.class b/src/main/resources/org/python/antlr/op/In$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..ffb7e5c816f4509685e4dc7b9d9bd01530cac427
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/In$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/In.class b/src/main/resources/org/python/antlr/op/In.class
new file mode 100644
index 0000000000000000000000000000000000000000..fcd580478be722031623c87ae1c374b18fc724a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/In.class differ
diff --git a/src/main/resources/org/python/antlr/op/InDerived.class b/src/main/resources/org/python/antlr/op/InDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..84e718fc4f115b6f29d38d1afd92213a480b4395
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/InDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Invert$Invert___init___exposer.class b/src/main/resources/org/python/antlr/op/Invert$Invert___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5a6f096aa4b83308ae49f30bcdf4bf85ca08b1d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Invert$Invert___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Invert$PyExposer.class b/src/main/resources/org/python/antlr/op/Invert$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6053beacf412565437834cffe53deac9adda9907
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Invert$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Invert$__int___exposer.class b/src/main/resources/org/python/antlr/op/Invert$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9b8b8cd47add66ed5e4327ddc1649e22a3bd7fe
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Invert$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Invert$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Invert$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e791dd033965fb72b6f4f3e88ce27d7a260bba08
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Invert$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Invert$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Invert$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8b03482f9e123d18d051904c65816ba7bcd8372
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Invert$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Invert$exposed___new__.class b/src/main/resources/org/python/antlr/op/Invert$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..51c2bb88aa098d078222db443eeade0d3b884ffc
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Invert$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Invert.class b/src/main/resources/org/python/antlr/op/Invert.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae8e225c693431719d5566235d7a48d1a88c4a04
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Invert.class differ
diff --git a/src/main/resources/org/python/antlr/op/InvertDerived.class b/src/main/resources/org/python/antlr/op/InvertDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..060ae0fc8934f0c25aa76aaefb4ca1b46567f766
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/InvertDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Is$Is___init___exposer.class b/src/main/resources/org/python/antlr/op/Is$Is___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ba2f7612a230771dce53ac04b8627fe10063b71
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Is$Is___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Is$PyExposer.class b/src/main/resources/org/python/antlr/op/Is$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f43c0a7e68a385f9c06bdd397e66f27276d77662
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Is$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Is$__int___exposer.class b/src/main/resources/org/python/antlr/op/Is$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..43702e177f164770b28dfb0cddc8390a25c53bf6
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Is$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Is$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Is$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..524b91629954356106e522e95e841894ecc71e29
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Is$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Is$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Is$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8892749aec8299cffb49997dd4161afd2536757c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Is$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Is$exposed___new__.class b/src/main/resources/org/python/antlr/op/Is$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba56a55bffc9b2e9ce9a43699301dc468d8676df
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Is$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Is.class b/src/main/resources/org/python/antlr/op/Is.class
new file mode 100644
index 0000000000000000000000000000000000000000..525b9682e5d2eb1c93a7c1947d5e1ca6a6de825e
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Is.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsDerived.class b/src/main/resources/org/python/antlr/op/IsDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b81805923e4de862bc96a4ef52b3c4f144309e9
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsNot$IsNot___init___exposer.class b/src/main/resources/org/python/antlr/op/IsNot$IsNot___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce9148f565c08a97e55d8042ec2f19a474caeb62
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsNot$IsNot___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsNot$PyExposer.class b/src/main/resources/org/python/antlr/op/IsNot$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f76030d22edca69de2d0e7473400527680b54bd6
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsNot$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsNot$__int___exposer.class b/src/main/resources/org/python/antlr/op/IsNot$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9b8a24ece53ca6f06d46bcff97281e0354f96d0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsNot$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsNot$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/IsNot$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad25233773e4eed1935622661c6d9caa7c0c5f5d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsNot$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsNot$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/IsNot$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..db46188e52624627a9f49f48d53a006e4f737bea
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsNot$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsNot$exposed___new__.class b/src/main/resources/org/python/antlr/op/IsNot$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..6bc8d5dcf69eb4bbfd50e2e74320ada6c6a9b61f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsNot$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsNot.class b/src/main/resources/org/python/antlr/op/IsNot.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9629e665169bcd3e0b4e92e81b58b4ba15d190c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsNot.class differ
diff --git a/src/main/resources/org/python/antlr/op/IsNotDerived.class b/src/main/resources/org/python/antlr/op/IsNotDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..0255eaa5a98cb14508eea1484aa446cc04978a67
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/IsNotDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/LShift$LShift___init___exposer.class b/src/main/resources/org/python/antlr/op/LShift$LShift___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1da5393f80c97a228950d89ff7bbd130cf13fd2e
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LShift$LShift___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/LShift$PyExposer.class b/src/main/resources/org/python/antlr/op/LShift$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fdcafa2e3312638e777766ff0bc6a4cda2f8eaf
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LShift$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/LShift$__int___exposer.class b/src/main/resources/org/python/antlr/op/LShift$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb9b787d4080d9ff83d116938f60be3cadca6998
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LShift$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/LShift$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/LShift$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..82d776985fe81d5f688137971695546fa258fd46
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LShift$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/LShift$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/LShift$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8e77aaee151b7be4bf1c9c8a1a7f7fa11210c9b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LShift$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/LShift$exposed___new__.class b/src/main/resources/org/python/antlr/op/LShift$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..80e5baa89b6492707e3f0dcf9ac0f6e174e2fdc7
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LShift$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/LShift.class b/src/main/resources/org/python/antlr/op/LShift.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7ac971d5bee822a0ae21cf68a4acbdbbebc40a4
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LShift.class differ
diff --git a/src/main/resources/org/python/antlr/op/LShiftDerived.class b/src/main/resources/org/python/antlr/op/LShiftDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..c97873cee0ead9bd9706322f1dc643d4e5017832
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LShiftDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Load$Load___init___exposer.class b/src/main/resources/org/python/antlr/op/Load$Load___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a96dfa9b932ef3ff452c2a09e4b59e39476ceea4
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Load$Load___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Load$PyExposer.class b/src/main/resources/org/python/antlr/op/Load$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa62cca561f1d727d78738f8ecabc8bbd25bdb62
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Load$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Load$__int___exposer.class b/src/main/resources/org/python/antlr/op/Load$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..85b9a6acd72ae5905a663f599053e3698ee98ebb
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Load$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Load$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Load$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cccbc152eacf4cbfb4e48d819bd5ab8a33f1ab25
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Load$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Load$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Load$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9332d2b87f81658fb601f2ed3000e5d30fb7e15a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Load$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Load$exposed___new__.class b/src/main/resources/org/python/antlr/op/Load$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..7578aefe3d74fe7f317e4da4ef3a23e4a406f0ce
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Load$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Load.class b/src/main/resources/org/python/antlr/op/Load.class
new file mode 100644
index 0000000000000000000000000000000000000000..896d1730ed9cb63dffd0dcfef29010e2726dcfc3
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Load.class differ
diff --git a/src/main/resources/org/python/antlr/op/LoadDerived.class b/src/main/resources/org/python/antlr/op/LoadDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3eab0cff9b5def4796bb7ca61f5b4109127f66b8
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LoadDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Lt$Lt___init___exposer.class b/src/main/resources/org/python/antlr/op/Lt$Lt___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..662df46d40e3bd59be2c10bed85450122ddaa82a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Lt$Lt___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Lt$PyExposer.class b/src/main/resources/org/python/antlr/op/Lt$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6ce55a7c7cdc8b419413aeb033a79faf30b1af6
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Lt$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Lt$__int___exposer.class b/src/main/resources/org/python/antlr/op/Lt$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4254edc48a3b14ace8e337056e4a31dbeab5709b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Lt$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Lt$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Lt$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..979da477a58c1abfd5c22a0f267088267716d0cc
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Lt$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Lt$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Lt$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..278be54460710f5d6e690f3d42c011274e1c45fd
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Lt$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Lt$exposed___new__.class b/src/main/resources/org/python/antlr/op/Lt$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..193a81d7c62c94538d2f283976279e1300368022
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Lt$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Lt.class b/src/main/resources/org/python/antlr/op/Lt.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9ee2f5b022c26da7295d8dd4927eae461c30da6
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Lt.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtDerived.class b/src/main/resources/org/python/antlr/op/LtDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf449ab2f79ba4bd6819c3de323dc81b5e5f1fb4
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtE$LtE___init___exposer.class b/src/main/resources/org/python/antlr/op/LtE$LtE___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e058272dc60705c1125534b24f334d1af7232eb
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtE$LtE___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtE$PyExposer.class b/src/main/resources/org/python/antlr/op/LtE$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8c26d0ea9f71da3d44e697a2632690362c8f8ba
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtE$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtE$__int___exposer.class b/src/main/resources/org/python/antlr/op/LtE$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a11ef18c383f726756a84af7fb9ff35ae83cb64
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtE$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtE$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/LtE$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd396b97953804454d2563e674f9e2c85d855269
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtE$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtE$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/LtE$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..98d42d70053a9f3fafb7f5ddcfe7c5f660a981e4
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtE$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtE$exposed___new__.class b/src/main/resources/org/python/antlr/op/LtE$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..2db3f6575af3aa1c9d782638e62d664bbabbc44d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtE$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtE.class b/src/main/resources/org/python/antlr/op/LtE.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bd457b1d9c9bf14c2db7631310fa333b023416f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtE.class differ
diff --git a/src/main/resources/org/python/antlr/op/LtEDerived.class b/src/main/resources/org/python/antlr/op/LtEDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..593d2eec19f016de7e693ed3964f29798c7e0b41
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/LtEDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mod$Mod___init___exposer.class b/src/main/resources/org/python/antlr/op/Mod$Mod___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..637d93286ca31e0a4b1e4c6ebc36ba37603362a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mod$Mod___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mod$PyExposer.class b/src/main/resources/org/python/antlr/op/Mod$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5409db702719593b8e3bc7efd1c9e9cd01644bce
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mod$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mod$__int___exposer.class b/src/main/resources/org/python/antlr/op/Mod$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..70bbbb4eb6bdcd31bb5700247a0e3633ca09fa67
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mod$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mod$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Mod$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..041e6acabf498b23ee2d3dce3e21e716aefc63ff
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mod$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mod$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Mod$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2cb9b996c09ad35a7a340fef5ed50dd582f05eaf
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mod$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mod$exposed___new__.class b/src/main/resources/org/python/antlr/op/Mod$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..716892f0de56b0563d4597a24c8fe19012fae9ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mod$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mod.class b/src/main/resources/org/python/antlr/op/Mod.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2a0fef961686e1a67ab1b790b8d544a1ed2448e
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mod.class differ
diff --git a/src/main/resources/org/python/antlr/op/ModDerived.class b/src/main/resources/org/python/antlr/op/ModDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..75a8b2834928e7be03e199109da16ba249c19d4c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/ModDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mult$Mult___init___exposer.class b/src/main/resources/org/python/antlr/op/Mult$Mult___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f54f8f59f619001ff8eb9f0004a7590c011831b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mult$Mult___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mult$PyExposer.class b/src/main/resources/org/python/antlr/op/Mult$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1bdfb8348f95e6201c56f71364f900ad27eafd8
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mult$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mult$__int___exposer.class b/src/main/resources/org/python/antlr/op/Mult$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3c2909bc140e535a65ed78b8de2a454f159bff1
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mult$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mult$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Mult$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b107a142e8ea954ad69c8f6706d7100c77514a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mult$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mult$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Mult$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bfc8c45f2593c74ebc9845d6e244476c4c4e209d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mult$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mult$exposed___new__.class b/src/main/resources/org/python/antlr/op/Mult$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dd98ed0365e323dfceaeab25d9fc7c982ff0fd3
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mult$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Mult.class b/src/main/resources/org/python/antlr/op/Mult.class
new file mode 100644
index 0000000000000000000000000000000000000000..aaca848b74af575389a4e3b9f31b8c54586b884d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Mult.class differ
diff --git a/src/main/resources/org/python/antlr/op/MultDerived.class b/src/main/resources/org/python/antlr/op/MultDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3889699c80205e26f1f6ecd32071f1df439adde
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/MultDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Not$Not___init___exposer.class b/src/main/resources/org/python/antlr/op/Not$Not___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8116893c450f598c4d8fc9be4404e89f17beaa94
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Not$Not___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Not$PyExposer.class b/src/main/resources/org/python/antlr/op/Not$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..08552ab85ca14e7da2c46b8bb43b18e11ee60b7a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Not$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Not$__int___exposer.class b/src/main/resources/org/python/antlr/op/Not$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2b16edf7ec9a61489c2eac6256b09188233a585
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Not$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Not$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Not$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cecd3798a39f5a9ab49eef797b19480692b29d53
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Not$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Not$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Not$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aae2bc4c5235d523f1e18169e72521dc8e599328
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Not$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Not$exposed___new__.class b/src/main/resources/org/python/antlr/op/Not$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..2806e26ff0ac4ad98b4ad306ec4eb134050e443b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Not$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Not.class b/src/main/resources/org/python/antlr/op/Not.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad5c643391601e3d593e981d501aef134a9d2da1
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Not.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotDerived.class b/src/main/resources/org/python/antlr/op/NotDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..54574cf983da48006f73525037fc6be94b402e8b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotEq$NotEq___init___exposer.class b/src/main/resources/org/python/antlr/op/NotEq$NotEq___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c14bd2255ec2e02cc4e92bcebe53d6dbb03edb06
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotEq$NotEq___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotEq$PyExposer.class b/src/main/resources/org/python/antlr/op/NotEq$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..97ea5a17c1051d2760ca87de0b9db0249e3267c8
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotEq$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotEq$__int___exposer.class b/src/main/resources/org/python/antlr/op/NotEq$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc6698480ee17a6448ae89bd7d39001696b7ceb3
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotEq$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotEq$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/NotEq$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8761bcda8dd2eb09e33710c19acf1f91fd99d00f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotEq$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotEq$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/NotEq$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c8fe59fa5b1e240b4f25c959ba50623d755ea0d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotEq$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotEq$exposed___new__.class b/src/main/resources/org/python/antlr/op/NotEq$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c45dc255d2947b4457e062e8a2c9e425e94c827
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotEq$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotEq.class b/src/main/resources/org/python/antlr/op/NotEq.class
new file mode 100644
index 0000000000000000000000000000000000000000..00adff07ef5c5ea3047340c69c7a256619ae8b27
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotEq.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotEqDerived.class b/src/main/resources/org/python/antlr/op/NotEqDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..919c09f8bf14034cb3a1355869cb81c6955e9fba
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotEqDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotIn$NotIn___init___exposer.class b/src/main/resources/org/python/antlr/op/NotIn$NotIn___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7df918c27c7f743b09540fbea871473ef26330ab
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotIn$NotIn___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotIn$PyExposer.class b/src/main/resources/org/python/antlr/op/NotIn$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcca2b3a06fb3a89ba741149b86d3913787691a3
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotIn$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotIn$__int___exposer.class b/src/main/resources/org/python/antlr/op/NotIn$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a579044689909cb94a223675db50dc1631f5965d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotIn$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotIn$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/NotIn$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b9016d47611ab6f412dd6eea08cc469839006e5
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotIn$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotIn$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/NotIn$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e07ace956100bdd3d72d015b296e76e653f1f0f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotIn$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotIn$exposed___new__.class b/src/main/resources/org/python/antlr/op/NotIn$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f6ca8f5224b8dc2d5817e34313652a47f221687
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotIn$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotIn.class b/src/main/resources/org/python/antlr/op/NotIn.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea2e33e075cc3b49cb3746e1dcdcd599476b0d10
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotIn.class differ
diff --git a/src/main/resources/org/python/antlr/op/NotInDerived.class b/src/main/resources/org/python/antlr/op/NotInDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..805430f8bb43e1af0e48082dca4376b60ecab06e
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/NotInDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Or$Or___init___exposer.class b/src/main/resources/org/python/antlr/op/Or$Or___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fea912a5c0ebb06f99e51e90c93c66c35f8afff
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Or$Or___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Or$PyExposer.class b/src/main/resources/org/python/antlr/op/Or$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8891512efe0b9f65b35b8aa04cf81b7c104d0e67
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Or$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Or$__int___exposer.class b/src/main/resources/org/python/antlr/op/Or$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..08578fb18e3a0842dc308f180a0fae749011f1fa
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Or$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Or$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Or$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9e323675c7cf22c3b119eb0b8a7a2e29487bfc7
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Or$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Or$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Or$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8dbc855909647f7ec3aeb3ad66c55b32402341f0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Or$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Or$exposed___new__.class b/src/main/resources/org/python/antlr/op/Or$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..51731077bd64800e4be57e22294567f287c64b27
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Or$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Or.class b/src/main/resources/org/python/antlr/op/Or.class
new file mode 100644
index 0000000000000000000000000000000000000000..aeb810afc8d13550df3e9697fca74a30c5c3d063
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Or.class differ
diff --git a/src/main/resources/org/python/antlr/op/OrDerived.class b/src/main/resources/org/python/antlr/op/OrDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c5fe45ba529f6452477c9586d2e1050ab7d00d0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/OrDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Param$Param___init___exposer.class b/src/main/resources/org/python/antlr/op/Param$Param___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3161b58f74e018e00ff17e1498817efd629c1e8d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Param$Param___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Param$PyExposer.class b/src/main/resources/org/python/antlr/op/Param$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..550111b8901b3a8b7bd40b20e3e360d16eeff156
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Param$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Param$__int___exposer.class b/src/main/resources/org/python/antlr/op/Param$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..571ef55d8a1cee6d32a88f1680b1588f5d5d9f6f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Param$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Param$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Param$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f91885b8f7cde262601da1088aa824b4f4bf972
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Param$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Param$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Param$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..73461b0ed0a540faa131df69b3f217193a3ccccc
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Param$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Param$exposed___new__.class b/src/main/resources/org/python/antlr/op/Param$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9066238ad1a39755163d45b9885c7cfda7aff78
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Param$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Param.class b/src/main/resources/org/python/antlr/op/Param.class
new file mode 100644
index 0000000000000000000000000000000000000000..4494849f134fdc193c0d4d5d3141a8d5f4c6b45c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Param.class differ
diff --git a/src/main/resources/org/python/antlr/op/ParamDerived.class b/src/main/resources/org/python/antlr/op/ParamDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab5b6d83ff2fb8abae02b6030ac1fda6526dfd4d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/ParamDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Pow$Pow___init___exposer.class b/src/main/resources/org/python/antlr/op/Pow$Pow___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3549dfcb8c40d1bb26a9e78dc1ab71789ba3988a
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Pow$Pow___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Pow$PyExposer.class b/src/main/resources/org/python/antlr/op/Pow$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8260008388dc9201314699d4f71073a72e70e5d8
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Pow$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Pow$__int___exposer.class b/src/main/resources/org/python/antlr/op/Pow$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f4eacafe647c093e560a2205c1ef717542a82da
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Pow$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Pow$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Pow$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7164c3dbdb476a1b12da7a320ba2432e7d29f58f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Pow$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Pow$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Pow$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..df45bc9ec269eb81eb25347300f528cc428c8bd8
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Pow$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Pow$exposed___new__.class b/src/main/resources/org/python/antlr/op/Pow$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..456d419c137275ad7d0b827501ed0bf1238b760f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Pow$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Pow.class b/src/main/resources/org/python/antlr/op/Pow.class
new file mode 100644
index 0000000000000000000000000000000000000000..efc29dd2fa0fc827898f91bf0528773e01e8c063
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Pow.class differ
diff --git a/src/main/resources/org/python/antlr/op/PowDerived.class b/src/main/resources/org/python/antlr/op/PowDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb2acebfb464a679f503a4a2a83cb1a54b585335
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/PowDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/RShift$PyExposer.class b/src/main/resources/org/python/antlr/op/RShift$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c7cc543cea240f668a91e52b67845dc1f9b6e52
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/RShift$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/RShift$RShift___init___exposer.class b/src/main/resources/org/python/antlr/op/RShift$RShift___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c5e2880558ac5400d8914feab672343b57c29b46
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/RShift$RShift___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/RShift$__int___exposer.class b/src/main/resources/org/python/antlr/op/RShift$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8fd5c87e13931f99f308b75419340fbcbacaf24
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/RShift$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/RShift$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/RShift$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d86b58930ec96d62855150d03321e24df986558f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/RShift$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/RShift$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/RShift$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8cb306ccda5e94374f7e216d076119d458efde1
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/RShift$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/RShift$exposed___new__.class b/src/main/resources/org/python/antlr/op/RShift$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f212a8c6941c6a9e1e59abe8ec24af16af146e0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/RShift$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/RShift.class b/src/main/resources/org/python/antlr/op/RShift.class
new file mode 100644
index 0000000000000000000000000000000000000000..fba6d844c6aacbac429df49cda7d6506009461ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/RShift.class differ
diff --git a/src/main/resources/org/python/antlr/op/RShiftDerived.class b/src/main/resources/org/python/antlr/op/RShiftDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..91b835f82e52e37374a9fc484c1c751c5adc1c2c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/RShiftDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Store$PyExposer.class b/src/main/resources/org/python/antlr/op/Store$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..597088aedc9dcc9561409c46eb2a2a37ab176976
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Store$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Store$Store___init___exposer.class b/src/main/resources/org/python/antlr/op/Store$Store___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7d36f01ef3e4a6677fcf55c60164e8fab55e695
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Store$Store___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Store$__int___exposer.class b/src/main/resources/org/python/antlr/op/Store$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..57dbe9e9af959caf4da8bd338e55fb42b0259350
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Store$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Store$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Store$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..35ccd6dfe6d79180df2d9ec45916b17810e225ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Store$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Store$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Store$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..adba447c3c7ef7f4b3cbfc465924432b6d1562d0
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Store$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Store$exposed___new__.class b/src/main/resources/org/python/antlr/op/Store$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa722b0fbb60f06c774704d5ddf86cca17aa5bec
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Store$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Store.class b/src/main/resources/org/python/antlr/op/Store.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ef0247667e657057c3196a42bfff7bfd2019c55
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Store.class differ
diff --git a/src/main/resources/org/python/antlr/op/StoreDerived.class b/src/main/resources/org/python/antlr/op/StoreDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba10e526d99046caf2328fc4b666649944382246
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/StoreDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/Sub$PyExposer.class b/src/main/resources/org/python/antlr/op/Sub$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..28d6095a1cb2918903873bfc7ec94e99f549d70b
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Sub$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Sub$Sub___init___exposer.class b/src/main/resources/org/python/antlr/op/Sub$Sub___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9f5d9d8f675b34920ebddd077bca29391636a04
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Sub$Sub___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Sub$__int___exposer.class b/src/main/resources/org/python/antlr/op/Sub$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cce996e486c32c036368c7ea3ea9216be34c7166
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Sub$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/Sub$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/Sub$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3037df443398fb2b49743152a24a0c536ae2350
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Sub$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Sub$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/Sub$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2770b5f5e401b83c7654a7668969a30173e234de
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Sub$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/Sub$exposed___new__.class b/src/main/resources/org/python/antlr/op/Sub$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8b0c03bea7db2576518c0511a60d19e444809da
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Sub$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/Sub.class b/src/main/resources/org/python/antlr/op/Sub.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e826d10f22e1015ec0ad28017cc8ea171c0adf1
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/Sub.class differ
diff --git a/src/main/resources/org/python/antlr/op/SubDerived.class b/src/main/resources/org/python/antlr/op/SubDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3736947de160728fe0d2e66b6b925484b11eeda6
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/SubDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/UAdd$PyExposer.class b/src/main/resources/org/python/antlr/op/UAdd$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ba8c2d3b71560a78c949abc1a5b58d526d4c6dd
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/UAdd$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/UAdd$UAdd___init___exposer.class b/src/main/resources/org/python/antlr/op/UAdd$UAdd___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fcb1932784faf72288fea7df6937744257b1518
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/UAdd$UAdd___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/UAdd$__int___exposer.class b/src/main/resources/org/python/antlr/op/UAdd$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..837ffc0ecf409491e608026ebef6db0ba8e1d8bb
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/UAdd$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/UAdd$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/UAdd$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa02b5777724b1754b5d3edd716af8c8ffa6b47f
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/UAdd$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/UAdd$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/UAdd$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..118bef989cc19a93898125ec4190117fdd7c19ae
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/UAdd$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/UAdd$exposed___new__.class b/src/main/resources/org/python/antlr/op/UAdd$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4846a926de156ce8ca60d56f4a361cc065820ce
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/UAdd$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/UAdd.class b/src/main/resources/org/python/antlr/op/UAdd.class
new file mode 100644
index 0000000000000000000000000000000000000000..cecf3edb49ec21c69a0e394ddb405a67b7b5e61d
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/UAdd.class differ
diff --git a/src/main/resources/org/python/antlr/op/UAddDerived.class b/src/main/resources/org/python/antlr/op/UAddDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..75ecf47a7d04a2f1f12eebc362d765af6159f800
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/UAddDerived.class differ
diff --git a/src/main/resources/org/python/antlr/op/USub$PyExposer.class b/src/main/resources/org/python/antlr/op/USub$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e5c9098bb45b93256d957c4081f6f52259b817c
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/USub$PyExposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/USub$USub___init___exposer.class b/src/main/resources/org/python/antlr/op/USub$USub___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..888dc13cae0a08dd75eebf4b6212dda767d962c5
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/USub$USub___init___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/USub$__int___exposer.class b/src/main/resources/org/python/antlr/op/USub$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9afa7e528598fac83795c8cd9130886a820a9e40
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/USub$__int___exposer.class differ
diff --git a/src/main/resources/org/python/antlr/op/USub$_attributes_descriptor.class b/src/main/resources/org/python/antlr/op/USub$_attributes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f171bcc2b3c1dd337f89d06021e28fcbe2eeb3cd
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/USub$_attributes_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/USub$_fields_descriptor.class b/src/main/resources/org/python/antlr/op/USub$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6605ea8cb329b0b527f11412951e2a6edc087103
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/USub$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/antlr/op/USub$exposed___new__.class b/src/main/resources/org/python/antlr/op/USub$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..710f4f932cc60ff111d00c02501925dfaaf6e2d9
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/USub$exposed___new__.class differ
diff --git a/src/main/resources/org/python/antlr/op/USub.class b/src/main/resources/org/python/antlr/op/USub.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a08f3ad942eb88a90d3ed125f1b1bd63359aac1
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/USub.class differ
diff --git a/src/main/resources/org/python/antlr/op/USubDerived.class b/src/main/resources/org/python/antlr/op/USubDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9931c142623c27b5e485ca93770f88a21069fd20
Binary files /dev/null and b/src/main/resources/org/python/antlr/op/USubDerived.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/ANTLRFileStream.class b/src/main/resources/org/python/antlr/runtime/ANTLRFileStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..c869445b09d559a4c4f7ca2d6bca476687a4ed6d
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/ANTLRFileStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/ANTLRInputStream.class b/src/main/resources/org/python/antlr/runtime/ANTLRInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..039035ec3255f2b3bc8b3bf2bda9f739ef71b1c1
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/ANTLRInputStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/ANTLRReaderStream.class b/src/main/resources/org/python/antlr/runtime/ANTLRReaderStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..592e464aa342921bec2331d1ae8e4a28bea37d89
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/ANTLRReaderStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/ANTLRStringStream.class b/src/main/resources/org/python/antlr/runtime/ANTLRStringStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..18332ab985ffced6e9aa2d2dc5164fa4e5bec2be
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/ANTLRStringStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/BaseRecognizer.class b/src/main/resources/org/python/antlr/runtime/BaseRecognizer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d245126f543a23405c824e9cd416f8c6b8d4381
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/BaseRecognizer.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/BitSet.class b/src/main/resources/org/python/antlr/runtime/BitSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..c5f9f1ee883098bb05538bb3826e6a272250d9a9
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/BitSet.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/CharStream.class b/src/main/resources/org/python/antlr/runtime/CharStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..450e77089e0ea84110ae6c11cf03bbc074e221d1
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/CharStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/CharStreamState.class b/src/main/resources/org/python/antlr/runtime/CharStreamState.class
new file mode 100644
index 0000000000000000000000000000000000000000..1122748e5a4effc97c7dc9467b5bff5f55f68315
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/CharStreamState.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/ClassicToken.class b/src/main/resources/org/python/antlr/runtime/ClassicToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..02f16eabc64d349fb96297dc9a52d97d96e5282e
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/ClassicToken.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/CommonToken.class b/src/main/resources/org/python/antlr/runtime/CommonToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..8eeb33e65e43ebecbddd13c311e49ce28dee500f
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/CommonToken.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/CommonTokenStream.class b/src/main/resources/org/python/antlr/runtime/CommonTokenStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8cecb659e2c48d2f3aeebe88763eab3f5775d08
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/CommonTokenStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/DFA.class b/src/main/resources/org/python/antlr/runtime/DFA.class
new file mode 100644
index 0000000000000000000000000000000000000000..badd87d6cdb744a464858a2ff1bea56b79cd8fb4
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/DFA.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/EarlyExitException.class b/src/main/resources/org/python/antlr/runtime/EarlyExitException.class
new file mode 100644
index 0000000000000000000000000000000000000000..294b28554b24392eb80a7a5ac5786fad0f26a4b0
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/EarlyExitException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/FailedPredicateException.class b/src/main/resources/org/python/antlr/runtime/FailedPredicateException.class
new file mode 100644
index 0000000000000000000000000000000000000000..34da00677960f26feab7d316b4f3fbbdc0950181
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/FailedPredicateException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/IntStream.class b/src/main/resources/org/python/antlr/runtime/IntStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..6eb69808f28088044d12771aaf1338849eed7fac
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/IntStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/Lexer.class b/src/main/resources/org/python/antlr/runtime/Lexer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ddd0883f8992e4d7c126af3192d1385a0ebf3bef
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/Lexer.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/MismatchedNotSetException.class b/src/main/resources/org/python/antlr/runtime/MismatchedNotSetException.class
new file mode 100644
index 0000000000000000000000000000000000000000..131c6355f59c4846ea653a16620daf2d54b5ef02
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/MismatchedNotSetException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/MismatchedRangeException.class b/src/main/resources/org/python/antlr/runtime/MismatchedRangeException.class
new file mode 100644
index 0000000000000000000000000000000000000000..65a7af8dcb7725321a368a0dd8b3f71846a8393a
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/MismatchedRangeException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/MismatchedSetException.class b/src/main/resources/org/python/antlr/runtime/MismatchedSetException.class
new file mode 100644
index 0000000000000000000000000000000000000000..faa5e0ebce836c32e06d77aca96d527ae99933b4
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/MismatchedSetException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/MismatchedTokenException.class b/src/main/resources/org/python/antlr/runtime/MismatchedTokenException.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b8dd9a50c77f992def0120bd43f44c926387f3d
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/MismatchedTokenException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/MismatchedTreeNodeException.class b/src/main/resources/org/python/antlr/runtime/MismatchedTreeNodeException.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2e2f184722b5caaf61e65d849cb9820f18d2dc9
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/MismatchedTreeNodeException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/MissingTokenException.class b/src/main/resources/org/python/antlr/runtime/MissingTokenException.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8d4e98de6edef3b6eaad1fdfd47e3f383fcf85c
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/MissingTokenException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/NoViableAltException.class b/src/main/resources/org/python/antlr/runtime/NoViableAltException.class
new file mode 100644
index 0000000000000000000000000000000000000000..146fd95b48257b6159b7fed5be2173340988facb
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/NoViableAltException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/Parser.class b/src/main/resources/org/python/antlr/runtime/Parser.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2987c822487e02e65001a4559a684506581ece9
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/Parser.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/ParserRuleReturnScope.class b/src/main/resources/org/python/antlr/runtime/ParserRuleReturnScope.class
new file mode 100644
index 0000000000000000000000000000000000000000..29be4d9d6fa004cf1cfab662a1f95f36a046214a
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/ParserRuleReturnScope.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/RecognitionException.class b/src/main/resources/org/python/antlr/runtime/RecognitionException.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ee0d9bbdaf49657173c0c077243471bb69821bf
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/RecognitionException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/RecognizerSharedState.class b/src/main/resources/org/python/antlr/runtime/RecognizerSharedState.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e16e77208f3a01c853b5f3e1d14705395fffd02
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/RecognizerSharedState.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/RuleReturnScope.class b/src/main/resources/org/python/antlr/runtime/RuleReturnScope.class
new file mode 100644
index 0000000000000000000000000000000000000000..e026422676e2fc7d9bbecf332c3b44e64d44aa98
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/RuleReturnScope.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/SerializedGrammar$Block.class b/src/main/resources/org/python/antlr/runtime/SerializedGrammar$Block.class
new file mode 100644
index 0000000000000000000000000000000000000000..a926a9f20f17e885eae6170c10c653a1814f1415
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/SerializedGrammar$Block.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/SerializedGrammar$Rule.class b/src/main/resources/org/python/antlr/runtime/SerializedGrammar$Rule.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d767e556c64bc8d35a01c080acaac9c356e8fff
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/SerializedGrammar$Rule.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/SerializedGrammar$RuleRef.class b/src/main/resources/org/python/antlr/runtime/SerializedGrammar$RuleRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..220efc1a77b29965272da6a9224b3467b260ba60
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/SerializedGrammar$RuleRef.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/SerializedGrammar$TokenRef.class b/src/main/resources/org/python/antlr/runtime/SerializedGrammar$TokenRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..3af06172211e673820d6e6f9ebf88e0ebe08f78b
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/SerializedGrammar$TokenRef.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/SerializedGrammar.class b/src/main/resources/org/python/antlr/runtime/SerializedGrammar.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba0a2ea26bd6f768e22a03aedaeae7c0a1adb52f
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/SerializedGrammar.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/Token.class b/src/main/resources/org/python/antlr/runtime/Token.class
new file mode 100644
index 0000000000000000000000000000000000000000..5339ba2603e17fb2cbd8a45ce706df6ed6bd70e1
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/Token.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$DeleteOp.class b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$DeleteOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..95e3136f26fbe6af5d50b802d7f8d57fe84fdd19
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$DeleteOp.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$InsertBeforeOp.class b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$InsertBeforeOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf8f24a7a3717f1e4fa1c374519a08c829dfa938
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$InsertBeforeOp.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$ReplaceOp.class b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$ReplaceOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a2e543518484718332d1e6df0bffb6c46fdc17a
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$ReplaceOp.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$RewriteOperation.class b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$RewriteOperation.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cfc9c874bdf6723d50186f56c07cbe09b357fed
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream$RewriteOperation.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/TokenRewriteStream.class b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cb2c3b6b217bae2e9428c560018e0388c43f69f
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/TokenRewriteStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/TokenSource.class b/src/main/resources/org/python/antlr/runtime/TokenSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ae21f5bd3a588e3e265823eb07a0cacb9ed9f66
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/TokenSource.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/TokenStream.class b/src/main/resources/org/python/antlr/runtime/TokenStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..3816c3b46b8442f7ebf64d5133742a170f4b85e9
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/TokenStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/UnwantedTokenException.class b/src/main/resources/org/python/antlr/runtime/UnwantedTokenException.class
new file mode 100644
index 0000000000000000000000000000000000000000..4588562bc5cf32bf914496c258c8e29bc274b661
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/UnwantedTokenException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/BlankDebugEventListener.class b/src/main/resources/org/python/antlr/runtime/debug/BlankDebugEventListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..4364c5c96af1b872ca8bfc32a80ba5cc8af525f4
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/BlankDebugEventListener.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugEventHub.class b/src/main/resources/org/python/antlr/runtime/debug/DebugEventHub.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d27499edc7e430f3cc8e7616829e2f667b38e06
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugEventHub.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugEventListener.class b/src/main/resources/org/python/antlr/runtime/debug/DebugEventListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..c93610153c526560028608729cb671161b6aa2c8
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugEventListener.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugEventRepeater.class b/src/main/resources/org/python/antlr/runtime/debug/DebugEventRepeater.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e311723c66f814b1de6d6733106da9bc5c403ab
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugEventRepeater.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugEventSocketProxy.class b/src/main/resources/org/python/antlr/runtime/debug/DebugEventSocketProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..b77596217a1deea158bff9cc8614e3b38a542b8f
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugEventSocketProxy.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugParser.class b/src/main/resources/org/python/antlr/runtime/debug/DebugParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..28393b654131f1bfc20682c04faf88f39f13f736
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugParser.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugTokenStream.class b/src/main/resources/org/python/antlr/runtime/debug/DebugTokenStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c853b2bb5f6211c23ad72de9228b80100b20444
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugTokenStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugTreeAdaptor.class b/src/main/resources/org/python/antlr/runtime/debug/DebugTreeAdaptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b4b19090fb97ccc4cff0a744aab119636eb937e
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugTreeAdaptor.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugTreeNodeStream.class b/src/main/resources/org/python/antlr/runtime/debug/DebugTreeNodeStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..4aacaa5933f02970d725d738998d5efcdd9d9031
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugTreeNodeStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/DebugTreeParser.class b/src/main/resources/org/python/antlr/runtime/debug/DebugTreeParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..a419ec3e1c042243993df01bc934dc700061993a
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/DebugTreeParser.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/ParseTreeBuilder.class b/src/main/resources/org/python/antlr/runtime/debug/ParseTreeBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..920c3c037e74c32a61e6daba94f92d10f2d66b58
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/ParseTreeBuilder.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/Profiler.class b/src/main/resources/org/python/antlr/runtime/debug/Profiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9156eccaeb27a72371fc8b270e71a3024057bd9
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/Profiler.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener$ProxyToken.class b/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener$ProxyToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbcbbb58ae85de5e50529138e7bda5850f7bc051
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener$ProxyToken.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener$ProxyTree.class b/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener$ProxyTree.class
new file mode 100644
index 0000000000000000000000000000000000000000..049ffc140d7c05be90f94289326e8d777c79100c
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener$ProxyTree.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener.class b/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..093e98ed7a3aba27ef71188014d7390c8c572a13
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/RemoteDebugEventSocketListener.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/TraceDebugEventListener.class b/src/main/resources/org/python/antlr/runtime/debug/TraceDebugEventListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..69848594fa3264c42a029296b050e8dccd37e9a1
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/TraceDebugEventListener.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/debug/Tracer.class b/src/main/resources/org/python/antlr/runtime/debug/Tracer.class
new file mode 100644
index 0000000000000000000000000000000000000000..937149705dda8fc24540d34df324a5b6b454b2fc
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/debug/Tracer.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/misc/FastQueue.class b/src/main/resources/org/python/antlr/runtime/misc/FastQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..8450231406ff44f7382cf60e6aa20408d6326d8f
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/misc/FastQueue.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/misc/IntArray.class b/src/main/resources/org/python/antlr/runtime/misc/IntArray.class
new file mode 100644
index 0000000000000000000000000000000000000000..f462f70f7fa109e056a2af7b668f421d3d0a8497
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/misc/IntArray.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/misc/LookaheadStream.class b/src/main/resources/org/python/antlr/runtime/misc/LookaheadStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..39647d3ab698306d0ded2eade5bffaa0fdc3b8bc
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/misc/LookaheadStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/misc/Stats.class b/src/main/resources/org/python/antlr/runtime/misc/Stats.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ee0eefddca259ef04f79a0bc8f6ebd8541c0b80
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/misc/Stats.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/BaseTree.class b/src/main/resources/org/python/antlr/runtime/tree/BaseTree.class
new file mode 100644
index 0000000000000000000000000000000000000000..352a6ce8e1b1f8d9a2d7c12a34d76e307b3bfc81
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/BaseTree.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/BaseTreeAdaptor.class b/src/main/resources/org/python/antlr/runtime/tree/BaseTreeAdaptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..535ca0df0991452d375232beecb64414af8f6447
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/BaseTreeAdaptor.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/BufferedTreeNodeStream$StreamIterator.class b/src/main/resources/org/python/antlr/runtime/tree/BufferedTreeNodeStream$StreamIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..2db93e38611132fa8c6a3e20bcddd7d0ab1dc9e1
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/BufferedTreeNodeStream$StreamIterator.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/BufferedTreeNodeStream.class b/src/main/resources/org/python/antlr/runtime/tree/BufferedTreeNodeStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..15e2c469ff6e6946491ae27655eb09f617771c81
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/BufferedTreeNodeStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/CommonErrorNode.class b/src/main/resources/org/python/antlr/runtime/tree/CommonErrorNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..eaa777268dc4650b9fbede9920234c6fdceba00f
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/CommonErrorNode.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/CommonTree.class b/src/main/resources/org/python/antlr/runtime/tree/CommonTree.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ffd491af385804459ccbb8287e6cab7ed524fab
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/CommonTree.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/CommonTreeAdaptor.class b/src/main/resources/org/python/antlr/runtime/tree/CommonTreeAdaptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a581bb442c0c2d33be1b4457054f9835e687335a
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/CommonTreeAdaptor.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/CommonTreeNodeStream.class b/src/main/resources/org/python/antlr/runtime/tree/CommonTreeNodeStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..90fdb2f5281f4eadb8bc73a3f1fa6056c7466b79
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/CommonTreeNodeStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/DOTTreeGenerator.class b/src/main/resources/org/python/antlr/runtime/tree/DOTTreeGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4ab28ca7fe37cfd60689ac17b238ad2a9729999
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/DOTTreeGenerator.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/ParseTree.class b/src/main/resources/org/python/antlr/runtime/tree/ParseTree.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7e9ababca970cf939dd298a3621d0747311f1d6
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/ParseTree.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/RewriteCardinalityException.class b/src/main/resources/org/python/antlr/runtime/tree/RewriteCardinalityException.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9f2d92c805d003ed1838210462c0df9ded435e8
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/RewriteCardinalityException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/RewriteEarlyExitException.class b/src/main/resources/org/python/antlr/runtime/tree/RewriteEarlyExitException.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a5c0b361477f9f1a9dd005a35b341b37034c3f4
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/RewriteEarlyExitException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/RewriteEmptyStreamException.class b/src/main/resources/org/python/antlr/runtime/tree/RewriteEmptyStreamException.class
new file mode 100644
index 0000000000000000000000000000000000000000..42406f1a2a393e7841b018057e3daf697b099571
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/RewriteEmptyStreamException.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleElementStream.class b/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleElementStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..bda7fa4c8aa5c7b788411177c00c045fcfbdf700
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleElementStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleNodeStream.class b/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleNodeStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..7581e688ca1b501c59033dcfa33bc287f2c40a0d
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleNodeStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleSubtreeStream.class b/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleSubtreeStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f7d63a810b19fc98cf237e899901068253d6d0f
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleSubtreeStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleTokenStream.class b/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleTokenStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..72601963e4f6acab113c9258e8c304f301f574a6
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/RewriteRuleTokenStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/Tree.class b/src/main/resources/org/python/antlr/runtime/tree/Tree.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fdb885e40ae8db10a9b12a27680192f36226d83
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/Tree.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeAdaptor.class b/src/main/resources/org/python/antlr/runtime/tree/TreeAdaptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2deba643928bc143bac8802e14cbd8b1b6ed257
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeAdaptor.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$1.class b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c10a0a268c5dc6cc33ede7124fa0fefc4158806b
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$1.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$2.class b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..47c928789a27de91ab6330df651db425e796e2fe
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$2.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$3.class b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5871d4ca7fc84fb4b0f8563cace3d48de58efbe
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$3.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$fptr.class b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$fptr.class
new file mode 100644
index 0000000000000000000000000000000000000000..6dbcb5511ce0a5875d16e5b68825aaec2c8ed60d
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter$fptr.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeFilter.class b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e4b39e32210d1f9af2952752bdd5bd54f52291c
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeFilter.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeIterator.class b/src/main/resources/org/python/antlr/runtime/tree/TreeIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..7214fc821097cef6ba959397999e75765ed1c1da
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeIterator.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeNodeStream.class b/src/main/resources/org/python/antlr/runtime/tree/TreeNodeStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..662cd3e5f9207a4e0a5d3f216dd051e90fc799db
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeNodeStream.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeParser.class b/src/main/resources/org/python/antlr/runtime/tree/TreeParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..6886fe4507a8767dcc1a851696d9a0676588b800
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeParser.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreePatternLexer.class b/src/main/resources/org/python/antlr/runtime/tree/TreePatternLexer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2000daa4fe44fbff20524998bb7b28ad627a900a
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreePatternLexer.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreePatternParser.class b/src/main/resources/org/python/antlr/runtime/tree/TreePatternParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..2318f87eb8c11097d504daec39524737274bf9ee
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreePatternParser.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$1.class b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5fc8bbd7b725458feea33217623044fc48416e92
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$1.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$2.class b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..b06b194d5e25dbf8f950dc03642618ecd86f76be
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$2.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$3.class b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd1844d7203e54612877c2043a8a902ba5b59b93
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$3.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$fptr.class b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$fptr.class
new file mode 100644
index 0000000000000000000000000000000000000000..837d5393274c3640b73ba316b535599e6aba0203
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter$fptr.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter.class b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..1acab89e1aac121c198ccf458d419665f506566f
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeRewriter.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeRuleReturnScope.class b/src/main/resources/org/python/antlr/runtime/tree/TreeRuleReturnScope.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fe077b3f6cd229f1abd44d287f0d4bd6e040437
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeRuleReturnScope.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeVisitor.class b/src/main/resources/org/python/antlr/runtime/tree/TreeVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..515f056d722aadee2e92fb804f4692ea2970dab7
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeVisitor.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeVisitorAction.class b/src/main/resources/org/python/antlr/runtime/tree/TreeVisitorAction.class
new file mode 100644
index 0000000000000000000000000000000000000000..85909ce156bfc64963db8fb026b532b5fedecf41
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeVisitorAction.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$1.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..31b8fec53cfe6fb8776c5f4096dafbccfd7f425d
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$1.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$2.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3996cacbd659d922b824c39523d3b61cf616fd5
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$2.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$3.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..55e334d10df2b259522a50f5474c65c8955392e1
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$3.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$ContextVisitor.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$ContextVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..009547e2d3a7299bb3badca0e8b83e5b8c41a1a4
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$ContextVisitor.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$TreePattern.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$TreePattern.class
new file mode 100644
index 0000000000000000000000000000000000000000..60ab28555aebfd34f273e9d785781ab80a5b92f6
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$TreePattern.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$TreePatternTreeAdaptor.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$TreePatternTreeAdaptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..566695364e71c53f241c76c4cb712dd75eca565e
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$TreePatternTreeAdaptor.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$Visitor.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$Visitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1fc8d8bc9242141eaee3a49e5d15259cae08771
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$Visitor.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$WildcardTreePattern.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$WildcardTreePattern.class
new file mode 100644
index 0000000000000000000000000000000000000000..4acd2683df466a88be7ca0213aa24ef7e079c0d2
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard$WildcardTreePattern.class differ
diff --git a/src/main/resources/org/python/antlr/runtime/tree/TreeWizard.class b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard.class
new file mode 100644
index 0000000000000000000000000000000000000000..859d360ea6f657f65ad8968db65bfd988b023c54
Binary files /dev/null and b/src/main/resources/org/python/antlr/runtime/tree/TreeWizard.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/CollectionIndex.class b/src/main/resources/org/python/apache/html/dom/CollectionIndex.class
new file mode 100644
index 0000000000000000000000000000000000000000..986ab7ca9b2690b073ae8b6a47e4f4a359d15dcd
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/CollectionIndex.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLAnchorElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLAnchorElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..72747b2d651da4d16463e52db352518fd7d2adf8
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLAnchorElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLAppletElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLAppletElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5bf02fb0ce9b9922b0092619298a73763b7128b6
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLAppletElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLAreaElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLAreaElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..32a4d97e8d5786c1f92914dac1c2cb6458720166
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLAreaElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLBRElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLBRElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..44da9f8d1e2f87472d0bb76ab5e37d535eac2550
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLBRElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLBaseElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLBaseElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..4faabced7d6bf5e303679452a5332add5bc2d63e
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLBaseElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLBaseFontElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLBaseFontElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..18ac5599b994571d1e89a58c1b95ae52826456be
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLBaseFontElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLBodyElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLBodyElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..495f78d66435ae379bada29731bb4bc4a7810628
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLBodyElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLBuilder.class b/src/main/resources/org/python/apache/html/dom/HTMLBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..70e8c0c384fa265a463508d1942f3b9dcf14e3a8
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLBuilder.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLButtonElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLButtonElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd0beeca7dd86324aeb099d30eb74c0f941d5c1e
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLButtonElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLCollectionImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLCollectionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..71ae7f250b818c8be0905d2dca8afbda10a0ea21
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLCollectionImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLDListElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLDListElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..f456367f834e74ca0203dccbf8134b8ddd0fc0cd
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLDListElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLDOMImplementationImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLDOMImplementationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..06ae81e619e7a8043717185a192f7d38d9573c40
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLDOMImplementationImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLDirectoryElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLDirectoryElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..13710343b39fb2c73ac2de7278c94a9a1a8062ad
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLDirectoryElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLDivElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLDivElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..995b8384d6cbc70e31d32aaf889cb03d21df8c34
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLDivElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLDocumentImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLDocumentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..346cbeedf1fba37aee2680b358b3b44924d41fb7
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLDocumentImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..f637991aa16033f24781d3e083018993467b916f
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLFieldSetElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLFieldSetElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2087049c2ae95720c5813b49c1c26b17d90b67f5
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLFieldSetElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLFontElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLFontElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..94183e48033a2312ff292ce78c3610b5ee70762b
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLFontElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLFormControl.class b/src/main/resources/org/python/apache/html/dom/HTMLFormControl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a71b7fb69c5b91c6c67ccabcb44c942f04d690a
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLFormControl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLFormElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLFormElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c66c7a41b088aff397db698f6d3b9bd36a57725
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLFormElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLFrameElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLFrameElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba9d8bb1ace7e9fb282d21d2ac178d502dd02576
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLFrameElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLFrameSetElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLFrameSetElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfafb1c141a897e60e756edfdc122d4f1bc234c1
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLFrameSetElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLHRElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLHRElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7bf14ad24deddb66899c05968e54219f76b751c
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLHRElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLHeadElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLHeadElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a44051e6ecd3527d2b733cc4c92636b30a83527e
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLHeadElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLHeadingElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLHeadingElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fb77d68e3e72238ac1f8dfbd91f064a2f141283
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLHeadingElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLHtmlElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLHtmlElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc9a5a7a6865f89cc0601f3330fdcd94bd633015
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLHtmlElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLIFrameElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLIFrameElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..03278e12c2fbbea6250704a0678296d04eb52f04
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLIFrameElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLImageElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLImageElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b60e94640ee4dfc8a7f021282da2100c0ce8d172
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLImageElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLInputElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLInputElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..285bd89ec85d0219e20a09e4e9cd905d8a610e7a
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLInputElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLIsIndexElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLIsIndexElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..baaffdbd671504a87d718d0c5b7846e6ad48efde
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLIsIndexElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLLIElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLLIElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a938942ab744d98c3b3e1fd9ea0d6ce56ebdf12
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLLIElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLLabelElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLLabelElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..fae5544e8e20f4464e96bdc024cf072d525df074
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLLabelElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLLegendElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLLegendElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d45c59f1ad017e88edda5938c8e29e7b6df4acd3
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLLegendElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLLinkElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLLinkElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..7872419ddd58269328f0ac861093a7759ca35655
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLLinkElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLMapElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLMapElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8af6860376bb2210a1d00b51fd5a2fea4a4cba37
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLMapElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLMenuElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLMenuElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa31e26307ad581037548d456f3317e6c336ca45
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLMenuElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLMetaElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLMetaElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4c8b56f03a0d876bc12ccf14db2e38206186af6
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLMetaElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLModElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLModElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..07901e426436e5c7be522755c46051e7b6e604b5
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLModElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLOListElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLOListElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d3c8692f9ea73c73487c31f92e45b67cb882627
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLOListElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLObjectElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLObjectElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..4918765f969fbbef1e0ef864704c24088acb9f1f
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLObjectElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLOptGroupElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLOptGroupElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..50c7aa727e923a36a64bcdcd9c0945a23980cd4d
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLOptGroupElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLOptionElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLOptionElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e32c120658c0a550945d7c15cd1d7662868c911
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLOptionElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLParagraphElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLParagraphElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..15c5424257e8fd4efd8c17d3bb040a8a0ea81dd8
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLParagraphElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLParamElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLParamElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..faad5c6d996b041dd741efb43ee5ea27ac4290b4
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLParamElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLPreElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLPreElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..60ad68ebb84d88f2cff97bb129a0924eac4939c6
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLPreElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLQuoteElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLQuoteElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b046ffef3aa188e4aa68bc6532f78788660d65f
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLQuoteElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLScriptElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLScriptElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..149680dd04dc4146cb5c1e53388729d48858783b
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLScriptElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLSelectElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLSelectElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..91ebede56bf3a81aac85ab42b4bb3377cfe8bec2
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLSelectElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLStyleElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLStyleElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..76e4ac1644a522785248875af87abccbaaf18266
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLStyleElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLTableCaptionElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLTableCaptionElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f5ced9fe2db781267b200fa5d018153d472fbf9
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLTableCaptionElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLTableCellElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLTableCellElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..9016ce3fa7f06cbd835fc9fc7c741054d6dc524a
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLTableCellElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLTableColElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLTableColElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..868311909c66757a1104293ec949aa418a759b2f
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLTableColElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLTableElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLTableElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..39d7af9a6793d767336196f75e4e6f82792b5746
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLTableElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLTableRowElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLTableRowElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1a067582e81752d24b73d2cf24ccb37c0d161bb
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLTableRowElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLTableSectionElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLTableSectionElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2650250e6cafea04e8b9ec91166af1440a455c9
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLTableSectionElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLTextAreaElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLTextAreaElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..26f8a26b1b0d3cf6616f4911f67daff007ef4071
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLTextAreaElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLTitleElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLTitleElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..030b57f4fb906a64af93541083573fc0288882f1
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLTitleElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/HTMLUListElementImpl.class b/src/main/resources/org/python/apache/html/dom/HTMLUListElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a4f2d4a8d8032ffb1fea4094143451bee6d46d7
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/HTMLUListElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/NameNodeListImpl.class b/src/main/resources/org/python/apache/html/dom/NameNodeListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b82c002c9337ab3435b9a19405eea5644f7abb0e
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/NameNodeListImpl.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/ObjectFactory$ConfigurationError.class b/src/main/resources/org/python/apache/html/dom/ObjectFactory$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad21b581082f4b5aa31ba3b22cd59126f4a416a2
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/ObjectFactory$ConfigurationError.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/ObjectFactory.class b/src/main/resources/org/python/apache/html/dom/ObjectFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..458e2ee54114c7b836ed953e1e2eee37ad9705aa
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/ObjectFactory.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport$1.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..067822274679056d4a4dc70b95df163b0591ddd1
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport$1.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport$2.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7de98b1be72a9ae6c97af179234043cf1ed8bee
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport$2.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport$3.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa44a4ee1b58a18230ebefc7a1a8a87c98747010
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport$3.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport$4.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ef8a59adf1f73755b73ac6d6832326cbac34fef
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport$4.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport$5.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..2036c9ca8fa310962f64183f43f1b5b8b109efdf
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport$5.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport$6.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2a740838129cc6108d284cf8b6d3f562e9b211a
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport$6.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport$7.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e181b37e4a4004c1748e5b9147b07aba232be82
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport$7.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport$8.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..cca2fcc2779e873fe3ef6b8ccc76ed4e6ca857a4
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport$8.class differ
diff --git a/src/main/resources/org/python/apache/html/dom/SecuritySupport.class b/src/main/resources/org/python/apache/html/dom/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..7569976ab70ddc26ec33c568289f35fe0ad4f49b
Binary files /dev/null and b/src/main/resources/org/python/apache/html/dom/SecuritySupport.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLAElement.class b/src/main/resources/org/python/apache/wml/WMLAElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4cf759f9dbee87231450d53fa058ad10214a885
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLAElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLAccessElement.class b/src/main/resources/org/python/apache/wml/WMLAccessElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fd3f881ab3027af8884ec39f9e6a3f5ff869dc7
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLAccessElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLAnchorElement.class b/src/main/resources/org/python/apache/wml/WMLAnchorElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..39a9f1e4fcd0556b7af4f64f6c9b6a6d7c5e14f1
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLAnchorElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLBElement.class b/src/main/resources/org/python/apache/wml/WMLBElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f98ceb12c4ee9a9d6eb682cc7d2251c7270956a
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLBElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLBigElement.class b/src/main/resources/org/python/apache/wml/WMLBigElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..417ba1be0eb2e7a27360d236a6579494ead7bd94
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLBigElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLBrElement.class b/src/main/resources/org/python/apache/wml/WMLBrElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..61031dfd1d99543d6ec05063498d998d122ff687
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLBrElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLCardElement.class b/src/main/resources/org/python/apache/wml/WMLCardElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbb16e15061b4330dc69d086062dd8fcd48fb42a
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLCardElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLDOMImplementation.class b/src/main/resources/org/python/apache/wml/WMLDOMImplementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..0844bc4a87a15caab0ecfddcc2e6b72859afd6ea
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLDOMImplementation.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLDoElement.class b/src/main/resources/org/python/apache/wml/WMLDoElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bc46e3b9fc8d8bf87c9876a0e1be0e3da86fd6c
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLDoElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLDocument.class b/src/main/resources/org/python/apache/wml/WMLDocument.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf6260b0efaf24b1767069701a8bdd9a30afa3ce
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLDocument.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLElement.class b/src/main/resources/org/python/apache/wml/WMLElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..5afec0c7f5914d763facc9a2f734bf7ef6be9d7f
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLEmElement.class b/src/main/resources/org/python/apache/wml/WMLEmElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..25729d0c7ac95dd3c895508b28330bf8ed287dd3
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLEmElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLFieldsetElement.class b/src/main/resources/org/python/apache/wml/WMLFieldsetElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb40ef8458064deaddd366414da20821e77b5d0f
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLFieldsetElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLGoElement.class b/src/main/resources/org/python/apache/wml/WMLGoElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6d774266854f293929ea86e3072a1b1e03d66d1
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLGoElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLHeadElement.class b/src/main/resources/org/python/apache/wml/WMLHeadElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6de32fcd67943eab893b1509ebea29a8c5ccea5
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLHeadElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLIElement.class b/src/main/resources/org/python/apache/wml/WMLIElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d29bdaa1223a78acc6b945f7a9aaeedb80ca7cd
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLIElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLImgElement.class b/src/main/resources/org/python/apache/wml/WMLImgElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..e126ed41552ca9e81e80b5191dc3ade55b9c18b7
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLImgElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLInputElement.class b/src/main/resources/org/python/apache/wml/WMLInputElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..52f6b0bb0bc0e8e3b4fc1613210cfa58c9f84bf7
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLInputElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLMetaElement.class b/src/main/resources/org/python/apache/wml/WMLMetaElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..c593103c43b9e045da10591bd50a6aa5c0cba725
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLMetaElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLNoopElement.class b/src/main/resources/org/python/apache/wml/WMLNoopElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f461fa06f426a6dc43fb55451b6a02f02700da6
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLNoopElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLOneventElement.class b/src/main/resources/org/python/apache/wml/WMLOneventElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a0be6ffbf3dac0184d71886a4c4ba1bdba9611b
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLOneventElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLOptgroupElement.class b/src/main/resources/org/python/apache/wml/WMLOptgroupElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..567a2ff47c2dda8da62479b50013713dae77af90
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLOptgroupElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLOptionElement.class b/src/main/resources/org/python/apache/wml/WMLOptionElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9f89ff1a3b565a0da1072cd19e09d7a78b1f331
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLOptionElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLPElement.class b/src/main/resources/org/python/apache/wml/WMLPElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..db887f54822fdab1708bec54bfe9eb6d11f0c4b0
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLPElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLPostfieldElement.class b/src/main/resources/org/python/apache/wml/WMLPostfieldElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..fcfe40d0ed1cab4e22f3a53e967bf6ea4b5eed9f
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLPostfieldElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLPrevElement.class b/src/main/resources/org/python/apache/wml/WMLPrevElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..262e0820b07763e8320f63029fa78d5eb7670497
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLPrevElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLRefreshElement.class b/src/main/resources/org/python/apache/wml/WMLRefreshElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..caaf05751ed68f366b6e17825cc607bb6b1ab17d
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLRefreshElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLSelectElement.class b/src/main/resources/org/python/apache/wml/WMLSelectElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a1ecaa0b0cb5ae83ad2fdfcc49ad844e2f14150
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLSelectElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLSetvarElement.class b/src/main/resources/org/python/apache/wml/WMLSetvarElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..f15dba24d65b1a88ea1f3755ada8444d6993ced3
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLSetvarElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLSmallElement.class b/src/main/resources/org/python/apache/wml/WMLSmallElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a466c1564dc1c616390731a283a1f576b2cc3e2
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLSmallElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLStrongElement.class b/src/main/resources/org/python/apache/wml/WMLStrongElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d63ace108c24cb40c7e8f7a465d05f498a09d25
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLStrongElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLTableElement.class b/src/main/resources/org/python/apache/wml/WMLTableElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..57c2af9c17c387a5afe5f121676ff109df8a3cec
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLTableElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLTdElement.class b/src/main/resources/org/python/apache/wml/WMLTdElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..90d91b242618060abd51ebe9f89060431a291502
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLTdElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLTemplateElement.class b/src/main/resources/org/python/apache/wml/WMLTemplateElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff17d390ec6d1ae7d2d139343434c367d8669143
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLTemplateElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLTimerElement.class b/src/main/resources/org/python/apache/wml/WMLTimerElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3544249e1acaf530e353148870577d4096c4bad
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLTimerElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLTrElement.class b/src/main/resources/org/python/apache/wml/WMLTrElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8ef3237164511c968964b5948ed493170eb85fc
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLTrElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLUElement.class b/src/main/resources/org/python/apache/wml/WMLUElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..58a20e05847721744092d3ca43719246f22f0a6d
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLUElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/WMLWmlElement.class b/src/main/resources/org/python/apache/wml/WMLWmlElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae9cda1a676a7393100d72411b1be5e24880bb59
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/WMLWmlElement.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLAElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLAElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..023bea774740b91a28010bd9285f736c483217cb
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLAElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLAccessElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLAccessElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d598567f0ce1e6f3f53bbea4915e6044d07e5aad
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLAccessElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLAnchorElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLAnchorElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..4cfd3d2354924ef3f7b2c9408c55b8afbd693d82
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLAnchorElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLBElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLBElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8adc5f069124a9942aef0932866213e063a37ce
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLBElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLBigElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLBigElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..95ab12f5cbfa4609fe8cc049658cdea5e3d58dad
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLBigElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLBrElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLBrElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..fec737f7c5ce8904d23bca71333fa0344549614a
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLBrElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLCardElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLCardElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a9a512044490ff0184d1f9c1b30a99c87e8cf50
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLCardElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLDOMImplementationImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLDOMImplementationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d493bd6a8c6793bfbfdb98772509ab9b757a61dc
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLDOMImplementationImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLDoElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLDoElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f444638a8822991befaaf1d610bf89daed31a9e
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLDoElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLDocumentImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLDocumentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..36a5f9652050823d00a4b9387ebbc00e773c3566
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLDocumentImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ebc53ebe299b08c2325ad6a311549e3bef625dc
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLEmElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLEmElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..482f61d28309c28822a8af846e1032f035355dba
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLEmElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLFieldsetElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLFieldsetElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..65ac60b53a7a07ac5f24122517f896f755e73cd1
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLFieldsetElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLGoElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLGoElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..16b3dfebc3aac31732552a440acebcfbb3a4c48e
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLGoElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLHeadElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLHeadElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..200217927dcdbd369f4e5d53925e788c221dfe95
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLHeadElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLIElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLIElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed79c7ca9a2e06973e29c5e092d1ef3df6e8103a
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLIElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLImgElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLImgElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6490189491828d40758c74b39d52859de8bca607
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLImgElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLInputElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLInputElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..7225f842c4cefb4cb36c905597f79591dab3819f
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLInputElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLMetaElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLMetaElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb591cf6bb7a876ebf4d9063817662613cce6dfc
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLMetaElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLNoopElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLNoopElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3223a55bac690ad17fa56807a424a853162f020
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLNoopElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLOneventElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLOneventElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..c10694c384eaa5cda6a91548097d81f3a66d3979
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLOneventElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLOptgroupElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLOptgroupElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..7da1206fd70506417644e36554cd673f7f3825d9
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLOptgroupElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLOptionElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLOptionElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6a9555a241160aec96e8065cc012729a3d1a12e
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLOptionElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLPElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLPElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..0de286e445e90115c6f0b5c35f871e2dd3bc3308
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLPElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLPostfieldElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLPostfieldElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..7629580b02290a470bc4ba2a9511ee19590c15de
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLPostfieldElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLPrevElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLPrevElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..85ac3f88686a13f783003b211151182cac40ed3f
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLPrevElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLRefreshElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLRefreshElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..af81ce28bda0394f21b4583b2602385c9b90ef96
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLRefreshElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLSelectElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLSelectElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c18ed425f401cd71e36dc808c595b610d504835
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLSelectElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLSetvarElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLSetvarElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cbca7bddfe4f97a996b2a0b37be7f1f2aee6e34
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLSetvarElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLSmallElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLSmallElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a16a44e0ee326ee87d284bd1ed9bb138330d4648
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLSmallElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLStrongElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLStrongElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..218d972eba975719b9da4a1fe5620b2d86ff4418
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLStrongElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLTableElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLTableElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c87f7454384f3d367445a3cb6151fc1a08d9df2
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLTableElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLTdElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLTdElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..95bce453aba74543c7592b53e174512a1fd7638f
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLTdElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLTemplateElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLTemplateElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd35a6c883ff0e92121c81de68c1046481af06f1
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLTemplateElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLTimerElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLTimerElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..61776f70439b1198b9e5c63bca1e4938bfb47d51
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLTimerElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLTrElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLTrElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..092346bfc3cf941a1e0d758acf5e48591719e214
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLTrElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLUElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLUElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bd430232adc150eed7bad0c7733f73db57ad00e
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLUElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/wml/dom/WMLWmlElementImpl.class b/src/main/resources/org/python/apache/wml/dom/WMLWmlElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d587339d279c12facb7b08a7f16a5bc4411eccb
Binary files /dev/null and b/src/main/resources/org/python/apache/wml/dom/WMLWmlElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ASDOMImplementationImpl.class b/src/main/resources/org/python/apache/xerces/dom/ASDOMImplementationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..46df6c9438069c1829e6510d954af7b465f48152
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ASDOMImplementationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ASModelImpl.class b/src/main/resources/org/python/apache/xerces/dom/ASModelImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..91aa45bdd32490904acf3e397649263ec4873683
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ASModelImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/AttrImpl.class b/src/main/resources/org/python/apache/xerces/dom/AttrImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..30bef1ddbe5c7f7441a2ce435556e3dd2c36cda0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/AttrImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/AttrNSImpl.class b/src/main/resources/org/python/apache/xerces/dom/AttrNSImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..32e9086d3fd43606f3711f0a8442e3d1199476dc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/AttrNSImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/AttributeMap.class b/src/main/resources/org/python/apache/xerces/dom/AttributeMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..f30fb647ead60d48876e991c90d34b544bb7eff1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/AttributeMap.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/CDATASectionImpl.class b/src/main/resources/org/python/apache/xerces/dom/CDATASectionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb555042ec3ba46dcdff5e4e73fb64c456796eec
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/CDATASectionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/CharacterDataImpl$1.class b/src/main/resources/org/python/apache/xerces/dom/CharacterDataImpl$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b31958eac15348abbb39109c71ed1db2fbb2b06
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/CharacterDataImpl$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/CharacterDataImpl.class b/src/main/resources/org/python/apache/xerces/dom/CharacterDataImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..68bc7626c8b7b1fb9f0c01f2094b849f862bce04
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/CharacterDataImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ChildNode.class b/src/main/resources/org/python/apache/xerces/dom/ChildNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..7446e50e948194385ed8abff23801a974c4f6183
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ChildNode.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/CommentImpl.class b/src/main/resources/org/python/apache/xerces/dom/CommentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e645b5d7c31777c7f5ed33027f9ba73d9156fe8e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/CommentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl$RevalidationHandlerHolder.class b/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl$RevalidationHandlerHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..97ec65eaeba04c160f835bfaa602fc6810b3f81f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl$RevalidationHandlerHolder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl$XMLDTDLoaderHolder.class b/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl$XMLDTDLoaderHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5a6966aaa32bb6fa926c9d7651ee0cf4a2f1276
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl$XMLDTDLoaderHolder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl.class b/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8fbe412876232ce811f98785b24df18c7753f56
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/CoreDOMImplementationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/CoreDocumentImpl.class b/src/main/resources/org/python/apache/xerces/dom/CoreDocumentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dbaa8bf07bb26fc2306a60cfb0f8609fac1cb5d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/CoreDocumentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMConfigurationImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMConfigurationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..acc4063d8961091c7a76812f49d516d329c6eed8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMConfigurationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMErrorImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMErrorImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..25ab2a33e7607576b16d8e8fede7ee8e3c5a44c9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMErrorImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMImplementationImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMImplementationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..42b840d28de542b1b1abef71d5cf712dbceb79d9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMImplementationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMImplementationListImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMImplementationListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..34dd0b6f3c5d0d529133b213eacc8f0f0c5afcf3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMImplementationListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMImplementationSourceImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMImplementationSourceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d2875323e9189ca0c9d212f0ce1760f0ab0d8fd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMImplementationSourceImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMInputImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMInputImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..37f8a599293ebb5800216fd9a1b269df29ba0d79
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMInputImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMLocatorImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMLocatorImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d202a9b3750707695b5cddcc784a05a005277faf
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMLocatorImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMMessageFormatter.class b/src/main/resources/org/python/apache/xerces/dom/DOMMessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..38be8fc15f455bc8fcb5911347e569ccec061ebd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMMessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMNormalizer$XMLAttributesProxy.class b/src/main/resources/org/python/apache/xerces/dom/DOMNormalizer$XMLAttributesProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bc27aaf03752da63dd59eda00ac708bd3a19d6c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMNormalizer$XMLAttributesProxy.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMNormalizer.class b/src/main/resources/org/python/apache/xerces/dom/DOMNormalizer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa35188b5e8c11fa7b40403772dafa4c546203f1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMNormalizer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMOutputImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMOutputImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ac51275cacd1da174afc7a7b77811ed3c48858f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMOutputImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMStringListImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMStringListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..69a8768a91753ad433ab17f0fac6102f57fafa9d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMStringListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DOMXSImplementationSourceImpl.class b/src/main/resources/org/python/apache/xerces/dom/DOMXSImplementationSourceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..abc6403081dcc64ed6cb3441bb3cc176c61e63de
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DOMXSImplementationSourceImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeepNodeListImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeepNodeListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3562df292a836013a88dc89642630cf73164866e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeepNodeListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredAttrImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredAttrImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1acb80e9bc9cbbf537c1902e6d43fc5ce7575ff6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredAttrImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredAttrNSImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredAttrNSImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f34d111013734c909a04e29ba446c881478615b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredAttrNSImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredCDATASectionImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredCDATASectionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..70e54f337f720798cac1fa990e7bda3d57decac7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredCDATASectionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredCommentImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredCommentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d67a54deba5f21729d084d82dd6d717f4ade6723
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredCommentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredDOMImplementationImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredDOMImplementationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..0053dfa854e0d0ad172bc0674fcff0f830aeeab3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredDOMImplementationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl$IntVector.class b/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl$IntVector.class
new file mode 100644
index 0000000000000000000000000000000000000000..36d8d41f6ff7c676a7ec713de7390793ba8acc97
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl$IntVector.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl$RefCount.class b/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl$RefCount.class
new file mode 100644
index 0000000000000000000000000000000000000000..3704bc5b3b456ab0a491c34d86867fd1e6f30942
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl$RefCount.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e4d7163071783a8b39e61b7405d51a982084c0e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentTypeImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentTypeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c96911d9df4cb83f49d15398f832ad43c99ab9e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredDocumentTypeImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredElementDefinitionImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredElementDefinitionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d9f004a9da40e9036d55a710fc5fac92ad5ab1c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredElementDefinitionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredElementImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..94c986e89e0fd313b4f1bb761b98c87aeea10e1b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredElementNSImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredElementNSImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4a0d7a0a923518b188eb2bdf85b700565b21d76
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredElementNSImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredEntityImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredEntityImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..734f295a27d64dc91fbcefbcb3227790c1de2afe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredEntityImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredEntityReferenceImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredEntityReferenceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e81fe94ac3e9c91fc8a9b09b6e1339e4ce4e9a2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredEntityReferenceImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredNode.class b/src/main/resources/org/python/apache/xerces/dom/DeferredNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..949fc0dedfbb18064df962f8c359f7245e2fb3ad
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredNode.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredNotationImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredNotationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b95f0ae9e0fda5f9fbed5a90cf5621ab2f8c0fd4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredNotationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredProcessingInstructionImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredProcessingInstructionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8efe45719bcaadd15e598065e46980f646179bc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredProcessingInstructionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DeferredTextImpl.class b/src/main/resources/org/python/apache/xerces/dom/DeferredTextImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f0bc455595e76e1767673d8c5d79122c6764aab
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DeferredTextImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DocumentFragmentImpl.class b/src/main/resources/org/python/apache/xerces/dom/DocumentFragmentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac69c3b7aa67350edbea20fbbf6539aac60869c4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DocumentFragmentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DocumentImpl$EnclosingAttr.class b/src/main/resources/org/python/apache/xerces/dom/DocumentImpl$EnclosingAttr.class
new file mode 100644
index 0000000000000000000000000000000000000000..06b03ef7741d6c158be4b7ac359bba59052597f7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DocumentImpl$EnclosingAttr.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DocumentImpl$LEntry.class b/src/main/resources/org/python/apache/xerces/dom/DocumentImpl$LEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef302084c06536dd37e35a71f6bf6b2c3043e761
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DocumentImpl$LEntry.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DocumentImpl.class b/src/main/resources/org/python/apache/xerces/dom/DocumentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..be921a81b56d61807df4ec47e37d837fe95c8755
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DocumentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/DocumentTypeImpl.class b/src/main/resources/org/python/apache/xerces/dom/DocumentTypeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ddf4f87ff52654c7110fb076f13ddfb9939a392
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/DocumentTypeImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ElementDefinitionImpl.class b/src/main/resources/org/python/apache/xerces/dom/ElementDefinitionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..03642f2f7efd0e9e6c8c0fab32878efef3748fee
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ElementDefinitionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ElementImpl.class b/src/main/resources/org/python/apache/xerces/dom/ElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1868125967327249967daa18ffa5251aa1a622f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ElementNSImpl.class b/src/main/resources/org/python/apache/xerces/dom/ElementNSImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ff29f0ea5db78f85f0c7371cba84a88fe32cff2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ElementNSImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/EntityImpl.class b/src/main/resources/org/python/apache/xerces/dom/EntityImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf8eed28c5d23be2fc21d303234ad15862e85f30
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/EntityImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/EntityReferenceImpl.class b/src/main/resources/org/python/apache/xerces/dom/EntityReferenceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5084b271b7f16293f85b79e2790b3f5904b46138
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/EntityReferenceImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/LCount.class b/src/main/resources/org/python/apache/xerces/dom/LCount.class
new file mode 100644
index 0000000000000000000000000000000000000000..bea4e38ee27a4cf0ce1a5fe9a99a4c0f1c1ce967
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/LCount.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/NamedNodeMapImpl.class b/src/main/resources/org/python/apache/xerces/dom/NamedNodeMapImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..376eceea9a5a0c057c93ef590eeabba099decb72
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/NamedNodeMapImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/NodeImpl.class b/src/main/resources/org/python/apache/xerces/dom/NodeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8be4e94cb5ee016a6ccea3501008614af2176c43
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/NodeImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/NodeIteratorImpl.class b/src/main/resources/org/python/apache/xerces/dom/NodeIteratorImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..4509809d7cd50fb70fe3789822da38106f598dbe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/NodeIteratorImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/NodeListCache.class b/src/main/resources/org/python/apache/xerces/dom/NodeListCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..bfaa8c3ef6e9d87639410e517ca612f6486e69eb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/NodeListCache.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/NotationImpl.class b/src/main/resources/org/python/apache/xerces/dom/NotationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad292f551f0fcf03000d1b6f79fe97e7c1ed364f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/NotationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ObjectFactory$ConfigurationError.class b/src/main/resources/org/python/apache/xerces/dom/ObjectFactory$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..6bdd68972baaeff66ba09e66af42bcaec59c44cf
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ObjectFactory$ConfigurationError.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ObjectFactory.class b/src/main/resources/org/python/apache/xerces/dom/ObjectFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..fcac89f72f57c2b8761bfceb12305c3e4a5a6b44
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ObjectFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/PSVIAttrNSImpl.class b/src/main/resources/org/python/apache/xerces/dom/PSVIAttrNSImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ea813d2ae2870d6d18046bc2e71ee2eed335a1d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/PSVIAttrNSImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/PSVIDOMImplementationImpl.class b/src/main/resources/org/python/apache/xerces/dom/PSVIDOMImplementationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3ea1838f0ac84131e450e06bd59426d19e7a40b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/PSVIDOMImplementationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/PSVIDocumentImpl.class b/src/main/resources/org/python/apache/xerces/dom/PSVIDocumentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..c32c4564a05f6b66bef54a6bfaea9e4a600f53d8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/PSVIDocumentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/PSVIElementNSImpl.class b/src/main/resources/org/python/apache/xerces/dom/PSVIElementNSImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..20245ebfccc047ea61f767ff8d47bd0ebb470624
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/PSVIElementNSImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ParentNode$1.class b/src/main/resources/org/python/apache/xerces/dom/ParentNode$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b1ab35e83d27a059530078b0f1968801973f5ef
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ParentNode$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ParentNode$UserDataRecord.class b/src/main/resources/org/python/apache/xerces/dom/ParentNode$UserDataRecord.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7a44c9186ae337d25ef34c88bffdd6e8186938e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ParentNode$UserDataRecord.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ParentNode.class b/src/main/resources/org/python/apache/xerces/dom/ParentNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c0876d86090618f334dbf37cab1a1aa9f28bb1a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ParentNode.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/ProcessingInstructionImpl.class b/src/main/resources/org/python/apache/xerces/dom/ProcessingInstructionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dfae4d0c5b572dbe36ab8827bf0dd5987a262c9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/ProcessingInstructionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/RangeExceptionImpl.class b/src/main/resources/org/python/apache/xerces/dom/RangeExceptionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d13e8735530d0a8e9a5158a065bf1649b66320b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/RangeExceptionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/RangeImpl.class b/src/main/resources/org/python/apache/xerces/dom/RangeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..91ce35bd6061bb2a2fb46db6ffaa5838c282d0ab
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/RangeImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$1.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..024e50cca38d173ac7acaee192032ff28be5cbd7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$2.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..0dd364bdc4828e009fa7626fd42f7567953d70de
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$2.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$3.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f7777b1252c22f2a3ca9a1df8572485645cd0dd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$3.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$4.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..b337e3286205a042b434a4902b088983b9813df6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$4.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$5.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..51e5edc37a5d38a22e0e834fa3c4c88e81feaefe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$5.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$6.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d49f0ee55bab8e3a09c91048f08d8ae69b1bdfd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$6.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$7.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d6f2060bfdc902bc5a63203dee37c5e9aebe55b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$7.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$8.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9edbed350e1c16ad452d92d8884dfe7e999b770
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport$8.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/SecuritySupport.class b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..a85af0b91b8139faffbe2e09560801a39435142c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/SecuritySupport.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/TextImpl.class b/src/main/resources/org/python/apache/xerces/dom/TextImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c8db49db381631ba431953157a25d69706807b7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/TextImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/TreeWalkerImpl.class b/src/main/resources/org/python/apache/xerces/dom/TreeWalkerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e3e92810c08eafe6adddfe9a0a76e1d912b1a62
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/TreeWalkerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/events/EventImpl.class b/src/main/resources/org/python/apache/xerces/dom/events/EventImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2706c5064ff6a73c7d79a58a25349337b98124ab
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/events/EventImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/events/MouseEventImpl.class b/src/main/resources/org/python/apache/xerces/dom/events/MouseEventImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4aff044a65fa6c57ad11ec218d82ea5e6ca3b60
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/events/MouseEventImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/events/MutationEventImpl.class b/src/main/resources/org/python/apache/xerces/dom/events/MutationEventImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e73ac76137a8af5799cb118a5487368d3273dc66
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/events/MutationEventImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom/events/UIEventImpl.class b/src/main/resources/org/python/apache/xerces/dom/events/UIEventImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e866d26c84b9da883de679170fa5ccd837283a3c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom/events/UIEventImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASAttributeDeclaration.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASAttributeDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac6af795dccd77de64b627ddb8b95cec5524ceac
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASAttributeDeclaration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASContentModel.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASContentModel.class
new file mode 100644
index 0000000000000000000000000000000000000000..196321684a2054547a6a124ecab66eb33dfaa19c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASContentModel.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASDataType.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASDataType.class
new file mode 100644
index 0000000000000000000000000000000000000000..420fc7adc9d2907de6278bc899eed693d9397d2e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASDataType.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASElementDeclaration.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASElementDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7a11561d303c5b11eea71d5d5fdeea10174f16c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASElementDeclaration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASEntityDeclaration.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASEntityDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..17af00ee4935ca10fb7d13ece56aaf35c216e708
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASEntityDeclaration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASModel.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASModel.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb81dc77038ea88ff3bc66fa3031030d2e9e965c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASModel.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASNamedObjectMap.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASNamedObjectMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6e1cf6a1a56d050e57654ac7e282adfe3d58c38
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASNamedObjectMap.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASNotationDeclaration.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASNotationDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..f893aaa01908a6effde27d163023e99a3cb18d43
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASNotationDeclaration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASObject.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..16ab69ee927986caccdfa862d436514c5ee31375
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASObject.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ASObjectList.class b/src/main/resources/org/python/apache/xerces/dom3/as/ASObjectList.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b30ba76073c5f2602365f5c08f1209f10247bf8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ASObjectList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/CharacterDataEditAS.class b/src/main/resources/org/python/apache/xerces/dom3/as/CharacterDataEditAS.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ee12755160c2b687e5049c27a4ad81076e754b2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/CharacterDataEditAS.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/DOMASBuilder.class b/src/main/resources/org/python/apache/xerces/dom3/as/DOMASBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1cc5e7a6afb2f2f99c167349469d62f21db690f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/DOMASBuilder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/DOMASException.class b/src/main/resources/org/python/apache/xerces/dom3/as/DOMASException.class
new file mode 100644
index 0000000000000000000000000000000000000000..08c3845f98f499992a4a56575b9a5eb47c0514db
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/DOMASException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/DOMASWriter.class b/src/main/resources/org/python/apache/xerces/dom3/as/DOMASWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..10acc5b0e9c5495726470a55ebee8de5fabb1fe7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/DOMASWriter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/DOMImplementationAS.class b/src/main/resources/org/python/apache/xerces/dom3/as/DOMImplementationAS.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e7ac46e47dd7afe70f61d4c5fe912b9891fbe41
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/DOMImplementationAS.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/DocumentAS.class b/src/main/resources/org/python/apache/xerces/dom3/as/DocumentAS.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b00c0b93377a74492e8053efdb48b35d728c76f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/DocumentAS.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/DocumentEditAS.class b/src/main/resources/org/python/apache/xerces/dom3/as/DocumentEditAS.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b2cff05380520dfa01be82eb4ffdebf027fa83c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/DocumentEditAS.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/ElementEditAS.class b/src/main/resources/org/python/apache/xerces/dom3/as/ElementEditAS.class
new file mode 100644
index 0000000000000000000000000000000000000000..063632ee1acf1358e0b32b780dc41c736eb9603c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/ElementEditAS.class differ
diff --git a/src/main/resources/org/python/apache/xerces/dom3/as/NodeEditAS.class b/src/main/resources/org/python/apache/xerces/dom3/as/NodeEditAS.class
new file mode 100644
index 0000000000000000000000000000000000000000..f99ef084048d869db821c6368b0c8c50f6a8c84d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/dom3/as/NodeEditAS.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/Constants$ArrayEnumeration.class b/src/main/resources/org/python/apache/xerces/impl/Constants$ArrayEnumeration.class
new file mode 100644
index 0000000000000000000000000000000000000000..95709c2410b4a4be7f22f5d577fdb7ccb696e432
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/Constants$ArrayEnumeration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/Constants.class b/src/main/resources/org/python/apache/xerces/impl/Constants.class
new file mode 100644
index 0000000000000000000000000000000000000000..aadbac3badf7ca4d0f08718c3cf069633ac3f7ed
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/Constants.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/ExternalSubsetResolver.class b/src/main/resources/org/python/apache/xerces/impl/ExternalSubsetResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..8385e939dabbcb289aa41e3c2bcdf7cf088fe4c5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/ExternalSubsetResolver.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/RevalidationHandler.class b/src/main/resources/org/python/apache/xerces/impl/RevalidationHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f6e7f45d22530f452f99d9cef24151ef33e2636
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/RevalidationHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/Version.class b/src/main/resources/org/python/apache/xerces/impl/Version.class
new file mode 100644
index 0000000000000000000000000000000000000000..313ad10f603ffebdca61680146004276625acd1a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/Version.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XML11DTDScannerImpl.class b/src/main/resources/org/python/apache/xerces/impl/XML11DTDScannerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..19e9b07a2c0789e941c1a909c6923a9278a08b9a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XML11DTDScannerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XML11DocumentScannerImpl.class b/src/main/resources/org/python/apache/xerces/impl/XML11DocumentScannerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..303f45d8d9719baf3ba42376d75c4ff6f95050c7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XML11DocumentScannerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XML11EntityScanner.class b/src/main/resources/org/python/apache/xerces/impl/XML11EntityScanner.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf86a19d76772fb34ae8a74677d4587bea75f16b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XML11EntityScanner.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XML11NSDocumentScannerImpl$NS11ContentDispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XML11NSDocumentScannerImpl$NS11ContentDispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..fff90bd786ca176a7ef0c5800aaa5c48fe1d03c0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XML11NSDocumentScannerImpl$NS11ContentDispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XML11NSDocumentScannerImpl.class b/src/main/resources/org/python/apache/xerces/impl/XML11NSDocumentScannerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d87193d4c499ef00beeb0bf9365ad4614e4f679
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XML11NSDocumentScannerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XML11NamespaceBinder.class b/src/main/resources/org/python/apache/xerces/impl/XML11NamespaceBinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..aedf29c86319c81c7493ab6af1f52101104f3f28
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XML11NamespaceBinder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDTDScannerImpl.class b/src/main/resources/org/python/apache/xerces/impl/XMLDTDScannerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a41cff519d298eea620f42c6f9c6be84d222804
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDTDScannerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$Dispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$Dispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ce605475731e7843e2dc5043e246852fef3367f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$Dispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$ElementStack.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$ElementStack.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d6b3e590c1eb03e420d57ef680c5f2210141c1e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$ElementStack.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..554c593d4e78399bf53e55b0dc228b565e2350b3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f3a8fc6067248f5e36489ffa31d0679551ce629
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentFragmentScannerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$ContentDispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$ContentDispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..cca539b4c0f6962144c4d2be487646f0f7793155
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$ContentDispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$DTDDispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$DTDDispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..78c3a29d5ae41b6a4f0647eecf0a2af0a0c7e531
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$DTDDispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$PrologDispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$PrologDispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..306c8d878c3c8d3ec565ede905a771514ef22cfa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$PrologDispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$TrailingMiscDispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$TrailingMiscDispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..250b979b3dbed008afa22ddfa59eb645a898ef23
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$TrailingMiscDispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$XMLDeclDispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$XMLDeclDispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..3525f16121862e7126b9d0bacdb235affa5a6ef1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl$XMLDeclDispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl.class b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..0feeb53feb6e546795e0ecd37ea5570844add4f1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLDocumentScannerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityDescription.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityDescription.class
new file mode 100644
index 0000000000000000000000000000000000000000..02fc1cc9e095269ecb43e0052edc33e3c5fcfec6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityDescription.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityHandler.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..96d0883f321475de11b8374b8a6cfc0d7fef9b3f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$1.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..785286f82873ddb934efc89b607143918e845501
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ByteBufferPool.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ByteBufferPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..fff15392903e304ad1cca606ce0f8a4ffb62f33f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ByteBufferPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$CharacterBuffer.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$CharacterBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..93499518089ba9bea6f396871d515ea40cc11178
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$CharacterBuffer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$CharacterBufferPool.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$CharacterBufferPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b6a06a9d7825bdd91aeb8acacfcd8fe00c96bed
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$CharacterBufferPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$EncodingInfo.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$EncodingInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7c5464d4e23e7915d3f17443e32ee97964beca8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$EncodingInfo.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$Entity.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$Entity.class
new file mode 100644
index 0000000000000000000000000000000000000000..651c11b10c334c16e021a01b0dcd40a69a20bce0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$Entity.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ExternalEntity.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ExternalEntity.class
new file mode 100644
index 0000000000000000000000000000000000000000..d77550a62442a26856c511932bdc20f0645ed6a0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ExternalEntity.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$InternalEntity.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$InternalEntity.class
new file mode 100644
index 0000000000000000000000000000000000000000..1694e6e24322aeb6aaca3be8d2481b1c6c845189
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$InternalEntity.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$RewindableInputStream.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$RewindableInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..cac3822b928075a241f67f3e814227035bb733b5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$RewindableInputStream.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ScannedEntity.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ScannedEntity.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c9d10cf3aaa9fa723cda7e0a0528f554ad1d9c4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager$ScannedEntity.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc11c3f9697dfe206f4119563ef5932a3528c525
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityManager.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityScanner$1.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityScanner$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf4e4bbd23bf124eaf0d818da47a81237fbaec68
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityScanner$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLEntityScanner.class b/src/main/resources/org/python/apache/xerces/impl/XMLEntityScanner.class
new file mode 100644
index 0000000000000000000000000000000000000000..90893be08fac6e1d66031e17d71501ff930d92eb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLEntityScanner.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLErrorReporter$1.class b/src/main/resources/org/python/apache/xerces/impl/XMLErrorReporter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac38d910f8e47ec0a3dac553eb5449e853d0565f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLErrorReporter$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLErrorReporter.class b/src/main/resources/org/python/apache/xerces/impl/XMLErrorReporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c653c0cb84a58f146c85d67b8db6cc97fb9c2f60
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLErrorReporter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLNSDocumentScannerImpl$NSContentDispatcher.class b/src/main/resources/org/python/apache/xerces/impl/XMLNSDocumentScannerImpl$NSContentDispatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..988015aa1b79c70ed5263379332c048efda70064
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLNSDocumentScannerImpl$NSContentDispatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLNSDocumentScannerImpl.class b/src/main/resources/org/python/apache/xerces/impl/XMLNSDocumentScannerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..721da0668cbf22004fdfb4a564b8b1b0ecb191ce
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLNSDocumentScannerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLNamespaceBinder.class b/src/main/resources/org/python/apache/xerces/impl/XMLNamespaceBinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..944167e4713a1667ab1000c9b502ef4bad57e043
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLNamespaceBinder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLScanner.class b/src/main/resources/org/python/apache/xerces/impl/XMLScanner.class
new file mode 100644
index 0000000000000000000000000000000000000000..57517f3fe2a7d88fea79def3b86513fc68fecd5c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLScanner.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/XMLVersionDetector.class b/src/main/resources/org/python/apache/xerces/impl/XMLVersionDetector.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdcdd6da92b039c03213af1862d1c19f8dbd4575
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/XMLVersionDetector.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/BalancedDTDGrammar.class b/src/main/resources/org/python/apache/xerces/impl/dtd/BalancedDTDGrammar.class
new file mode 100644
index 0000000000000000000000000000000000000000..df38f70b8d52f99f3e1a568dd262018824efbc2a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/BalancedDTDGrammar.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar$ChildrenList.class b/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar$ChildrenList.class
new file mode 100644
index 0000000000000000000000000000000000000000..ddd1636903a0280126f04a660584758cbe609d63
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar$ChildrenList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar$QNameHashtable.class b/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar$QNameHashtable.class
new file mode 100644
index 0000000000000000000000000000000000000000..90ee959b009f7f3e5534165d6ea10084ecf97df5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar$QNameHashtable.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar.class b/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar.class
new file mode 100644
index 0000000000000000000000000000000000000000..e56c961e196f4d3eadb0b1d20d7beabeb1c3f953
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammar.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammarBucket.class b/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammarBucket.class
new file mode 100644
index 0000000000000000000000000000000000000000..23658ccb0fc1de3902948815c744aedc66b965ae
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/DTDGrammarBucket.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XML11DTDProcessor.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XML11DTDProcessor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a95a02184984065665dd51745597d32fe583492c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XML11DTDProcessor.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XML11DTDValidator.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XML11DTDValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..c51451f5164d0977eed26be30aa6ddacc4b8c606
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XML11DTDValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XML11NSDTDValidator.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XML11NSDTDValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..b874dfd5c638e84bc38830bbc0fbb213061c88e9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XML11NSDTDValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLAttributeDecl.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLAttributeDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..34ddaa7585bb8ab1bfdd002c22e43f18d3a9b134
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLAttributeDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLContentSpec$Provider.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLContentSpec$Provider.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbaa9f87fa48a9faafcb79185abc88ffa4d3c76c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLContentSpec$Provider.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLContentSpec.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLContentSpec.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed2615bc1d7c88e6eadc5622be41aa7444294728
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLContentSpec.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDDescription.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDDescription.class
new file mode 100644
index 0000000000000000000000000000000000000000..b32edb0073a0ed86e4f7c7d93bd89d5d67df3b76
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDDescription.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDLoader.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..39b381ca7fa448880386c06a124bb8ecdc32eef0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDLoader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDProcessor.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDProcessor.class
new file mode 100644
index 0000000000000000000000000000000000000000..84db0d79bde8164d2215195ed6e8c26c85737843
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDProcessor.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDValidator.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..98f6606acdf73b2311fc3a2c421daa0ae82bc9dc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDValidatorFilter.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDValidatorFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3eb7b54aa27385820c3b137bc8df11ff3b99642
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLDTDValidatorFilter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLElementDecl.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLElementDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..dad3d08c277a14317b6b079698afbad2c8e78ad5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLElementDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLEntityDecl.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLEntityDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..15c94e7c9b5c94a5245c85ca4fda34dcd32162bf
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLEntityDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLNSDTDValidator.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLNSDTDValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f735c00e066ebab7e16534f505d5709f05bbbd8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLNSDTDValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLNotationDecl.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLNotationDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f1b3766abf49991ad05bcbfb190ed866dab9e37
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLNotationDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/XMLSimpleType.class b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLSimpleType.class
new file mode 100644
index 0000000000000000000000000000000000000000..022b8a75003d455c14178c6f957be745c7e2de07
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/XMLSimpleType.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMAny.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMAny.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b765c65b4c5f3d679a91bb77d4dc0ef1441bf40
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMAny.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMBinOp.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMBinOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..4658e1524018060e640955298e83e690a22fc0a8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMBinOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMLeaf.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMLeaf.class
new file mode 100644
index 0000000000000000000000000000000000000000..66b1bbc8076e608d6dae5e014128b17ac7ce609c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMLeaf.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMNode.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4b8ea92c66f4ad3321227a7a5c043b17ff3447f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMNode.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMStateSet.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMStateSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..e802aa581e407ed4a85ad3e379573b9251c6f3fe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMStateSet.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMUniOp.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMUniOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3c6cc8153c6c028ea6e056f4084d362b28fac52
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/CMUniOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/ContentModelValidator.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/ContentModelValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..426d3975645d3204bead0cef1a1411f350e95040
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/ContentModelValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/DFAContentModel.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/DFAContentModel.class
new file mode 100644
index 0000000000000000000000000000000000000000..c404a2337187e445eb3f5025ca0b6b9f46a441c9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/DFAContentModel.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/MixedContentModel.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/MixedContentModel.class
new file mode 100644
index 0000000000000000000000000000000000000000..36722b71c9eccc86c2bdc2f8d6576bd6884aff61
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/MixedContentModel.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dtd/models/SimpleContentModel.class b/src/main/resources/org/python/apache/xerces/impl/dtd/models/SimpleContentModel.class
new file mode 100644
index 0000000000000000000000000000000000000000..c5ee9d86b7426b5ee075796c48cf47e3d4a49b14
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dtd/models/SimpleContentModel.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/DTDDVFactory.class b/src/main/resources/org/python/apache/xerces/impl/dv/DTDDVFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd70d01ea37602fdc4d640990eb938709351c4c6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/DTDDVFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/DVFactoryException.class b/src/main/resources/org/python/apache/xerces/impl/dv/DVFactoryException.class
new file mode 100644
index 0000000000000000000000000000000000000000..8778a560c33bfd44231b760dfa31ab575bcb1895
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/DVFactoryException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/DatatypeException.class b/src/main/resources/org/python/apache/xerces/impl/dv/DatatypeException.class
new file mode 100644
index 0000000000000000000000000000000000000000..118a25588977d1d77c9ecce4b82f188d835f84c0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/DatatypeException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/DatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/DatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ffa746ed7065bcfd75b4bcdb3001642cf4d67445
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/DatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/InvalidDatatypeFacetException.class b/src/main/resources/org/python/apache/xerces/impl/dv/InvalidDatatypeFacetException.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3f1a5e18a70a8689e2b6392fd9bebabe7979203
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/InvalidDatatypeFacetException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/InvalidDatatypeValueException.class b/src/main/resources/org/python/apache/xerces/impl/dv/InvalidDatatypeValueException.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c01a338b5da0522a44e9ada283625eacb9a2f84
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/InvalidDatatypeValueException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/ObjectFactory$ConfigurationError.class b/src/main/resources/org/python/apache/xerces/impl/dv/ObjectFactory$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..af2f623952a5ae20a6381dda70b62d2fa6c9de48
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/ObjectFactory$ConfigurationError.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/ObjectFactory.class b/src/main/resources/org/python/apache/xerces/impl/dv/ObjectFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..953b94c363c81a8003a180901c6fa5843cf266b0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/ObjectFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SchemaDVFactory.class b/src/main/resources/org/python/apache/xerces/impl/dv/SchemaDVFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9690fba7d930abb86fed427adb357a149264ae5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SchemaDVFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$1.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..850c45ba1be2dda00220f0fa972bf42b42564fc2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$2.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..f80b6837cf0a3c35626ced3f9594c15515e239f0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$2.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$3.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e21955291357693a14b3ed14aa8cb8e88f82f6c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$3.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$4.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..655e2d6f73f9370648cf81c448b0a43d8415b6e8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$4.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$5.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1a519c3a4b2a3425f11983610146ce34e09999a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$5.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$6.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..967c992ec026e9a69a1bb5a3960ec172681b6a43
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$6.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$7.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..74bf8643e50788e6e6c8b57890e7cbe037744cb4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$7.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$8.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3f0b8703bd576a7ff1aa14be39968c7faf9bee1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport$8.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport.class b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..a96101a5f4eebfe094abd38360f7c3a00a6da610
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/SecuritySupport.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/ValidatedInfo.class b/src/main/resources/org/python/apache/xerces/impl/dv/ValidatedInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4ed19285d34459fd36a81f6d0225aae06105907
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/ValidatedInfo.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/ValidationContext.class b/src/main/resources/org/python/apache/xerces/impl/dv/ValidationContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bd1d444d9b854843775f8b59bf779add306fdc9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/ValidationContext.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/XSFacets.class b/src/main/resources/org/python/apache/xerces/impl/dv/XSFacets.class
new file mode 100644
index 0000000000000000000000000000000000000000..d13d6b22c2c78a4598137b7675b8b15dbbd53cbe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/XSFacets.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/XSSimpleType.class b/src/main/resources/org/python/apache/xerces/impl/dv/XSSimpleType.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d9cf88e93f5e65a53fa361d74226494c8d1b39b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/XSSimpleType.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/DTDDVFactoryImpl.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/DTDDVFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ebecf095a4154dc8d12f403bbaf376ab226378c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/DTDDVFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/ENTITYDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/ENTITYDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b074efe77b2cc5b2aaa9fb24493672dad5d6f00
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/ENTITYDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/IDDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/IDDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd24f5bd101bb4e0f729b30f159fb43ff8f3319e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/IDDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/IDREFDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/IDREFDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc435027a146092c577582cb9e81982dd741b190
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/IDREFDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/ListDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/ListDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6709c0908e49ea5029de51e80e53261adf673981
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/ListDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/NMTOKENDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/NMTOKENDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..0897103ff4cd41a0a2c1ae04e339ea0925d6365f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/NMTOKENDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/NOTATIONDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/NOTATIONDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..15d3587f478a254c41a72858e6ecf056d3f8ee3d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/NOTATIONDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/StringDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/StringDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..8eb5be5074b6714a385baceec9da0c89d67d8868
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/StringDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11DTDDVFactoryImpl.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11DTDDVFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..14447db205b051c058fa2dee842c11b7bff9d096
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11DTDDVFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11IDDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11IDDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..115bfc4c4f40009bdc8a23fa3200ede55ea994fb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11IDDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11IDREFDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11IDREFDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..d76dc75a274debd18ede699ea155b7add848de1a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11IDREFDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11NMTOKENDatatypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11NMTOKENDatatypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcf8b030a2260d58d49abf1af74ad257021e2f33
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/dtd/XML11NMTOKENDatatypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/util/Base64.class b/src/main/resources/org/python/apache/xerces/impl/dv/util/Base64.class
new file mode 100644
index 0000000000000000000000000000000000000000..c001123295a69687fbbeecf88fca322f87e4bedc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/util/Base64.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/util/ByteListImpl.class b/src/main/resources/org/python/apache/xerces/impl/dv/util/ByteListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7f10df56ed9ed08a75939f1c175587c4ab70d6c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/util/ByteListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/util/HexBin.class b/src/main/resources/org/python/apache/xerces/impl/dv/util/HexBin.class
new file mode 100644
index 0000000000000000000000000000000000000000..85c13996db1b32c39c9cbe17d8896c3cfc3e5b54
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/util/HexBin.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/AbstractDateTimeDV$DateTimeData.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AbstractDateTimeDV$DateTimeData.class
new file mode 100644
index 0000000000000000000000000000000000000000..a27c346e61a8c0402e9b96b5041df6bd7d977be0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AbstractDateTimeDV$DateTimeData.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/AbstractDateTimeDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AbstractDateTimeDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cfc39e501c1745e5d20147c0c9f90f617b21e9e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AbstractDateTimeDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnyAtomicDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnyAtomicDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..b85efa9bcf6373fd2519bd0628fa2591bf1357ef
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnyAtomicDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnySimpleDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnySimpleDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1bbe2a010b19d28147e0e950f0820c8e142ef88
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnySimpleDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnyURIDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnyURIDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcdcd3f43336ac1b74bb5086ae563e4fc18729a3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/AnyURIDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/Base64BinaryDV$XBase64.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/Base64BinaryDV$XBase64.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b7156e1287a4ff6d9db6d7a292582fa4bacfa72
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/Base64BinaryDV$XBase64.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/Base64BinaryDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/Base64BinaryDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1fd7d68fbfe6df8051809c296c7eab737c4a3a2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/Base64BinaryDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/BaseDVFactory.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/BaseDVFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b8827ba92c42372ea239343bc481cb663a62028
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/BaseDVFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/BaseSchemaDVFactory.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/BaseSchemaDVFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..c78b148b074d096f74955efce10bbff8d47f1c93
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/BaseSchemaDVFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/BooleanDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/BooleanDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdce74b72248093d5acdb0cf5c6d9811f24198cd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/BooleanDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DateDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DateDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..d1135e46ffc55d5d34e2c699ec4848ac336d00fd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DateDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DateTimeDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DateTimeDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..55d5202445977eda24b898c7bcb9cdb3aecabc1a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DateTimeDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DayDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DayDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6b43eb1660dfbd3f6054de1d1b014a363d337c6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DayDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DayTimeDurationDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DayTimeDurationDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..b63c36cc1ecf476124b6a5a62e3026eb2ed22a2c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DayTimeDurationDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DecimalDV$XDecimal.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DecimalDV$XDecimal.class
new file mode 100644
index 0000000000000000000000000000000000000000..90231b3b2b8b90b87e10b82de1ca448b11a2d2d0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DecimalDV$XDecimal.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DecimalDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DecimalDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..357e48259a3f04f3a90baa840280a73c4f2a12b5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DecimalDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DoubleDV$XDouble.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DoubleDV$XDouble.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa42f9549cd3ac0d15de704f310b58f5dc6a1953
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DoubleDV$XDouble.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DoubleDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DoubleDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c60b4b5416909f67bc55780e2fe9bf5e671c186
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DoubleDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/DurationDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DurationDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..09e28a1ce3bab52e09fdb3253bd3e087259febf7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/DurationDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/EntityDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/EntityDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1707c3548297d7e7786b97d62a0a40758367ca0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/EntityDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/ExtendedSchemaDVFactoryImpl.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/ExtendedSchemaDVFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ed8240a4b52da8c607a12e1e4b0d37006087772
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/ExtendedSchemaDVFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/FloatDV$XFloat.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/FloatDV$XFloat.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f1e5a425a7f285233068e601613eec3a144f3ca
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/FloatDV$XFloat.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/FloatDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/FloatDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5d53db8cdaec0675ce79188b874ed65012b8bd5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/FloatDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/FullDVFactory.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/FullDVFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa7a01681ec93a124ca51572e454a5063b74cd88
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/FullDVFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/HexBinaryDV$XHex.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/HexBinaryDV$XHex.class
new file mode 100644
index 0000000000000000000000000000000000000000..936186b9863680ddb69ac251657575ffed8d060b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/HexBinaryDV$XHex.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/HexBinaryDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/HexBinaryDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..33f89a9d613ecca3c8ec41c8926ec3fe12ca27c7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/HexBinaryDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/IDDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/IDDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..14a5b404bffec4dc0811fb22dff2430877baa7b3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/IDDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/IDREFDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/IDREFDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..395dc06628f343450e774af8d68677461a356504
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/IDREFDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/IntegerDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/IntegerDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..004ce252f04c933401f1968477c5b128b959afb9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/IntegerDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/ListDV$ListData.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/ListDV$ListData.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3577629f3934a19082070a438abb8487391c776
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/ListDV$ListData.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/ListDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/ListDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..4419ad85b072cff4a2944d4b92dd779267be677f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/ListDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/MonthDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/MonthDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..38f37de39e3d2830455d66244f14b3a883ad2157
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/MonthDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/MonthDayDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/MonthDayDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..73890e51508960b253f1f90cd2e4558ae5c91ddc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/MonthDayDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/PrecisionDecimalDV$XPrecisionDecimal.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/PrecisionDecimalDV$XPrecisionDecimal.class
new file mode 100644
index 0000000000000000000000000000000000000000..8279080a4bde8d7cedc87e04f04ecf89065aeede
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/PrecisionDecimalDV$XPrecisionDecimal.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/PrecisionDecimalDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/PrecisionDecimalDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..8567ee222ce5b50431285718e20e6594ce07f23e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/PrecisionDecimalDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/QNameDV$XQName.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/QNameDV$XQName.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c5b7b0057a7dee1d3a0568bde12308222eb7112
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/QNameDV$XQName.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/QNameDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/QNameDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..3aaa3f46d5f8d8b7f28aaec7f47a6cab4f50f446
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/QNameDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/SchemaDVFactoryImpl.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/SchemaDVFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..da74a38a50b0ccd8781c187c9c3bb630118e062d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/SchemaDVFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/SchemaDateTimeException.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/SchemaDateTimeException.class
new file mode 100644
index 0000000000000000000000000000000000000000..e164710fab62d48ed2ea716d80e4c7a6a1e146ab
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/SchemaDateTimeException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/StringDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/StringDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..7585d367a7839d5c16da37cc443da774b089b024
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/StringDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/TimeDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/TimeDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c40d0c141434f3fbbbf96d49306a5ac50909dbf
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/TimeDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/TypeValidator.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/TypeValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..050f941ae8a12f3cd423593bf771fe2044d6596a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/TypeValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/UnionDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/UnionDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ac62f55311bf300107cdbdb8682fb1a0432044a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/UnionDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$1.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1c9f3ce57fe62de814189759fe14dd102709ea1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$2.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..08ab3d6717b31d0d797b73d10f1c3bca62dce16b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$2.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$3.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..370ad5dd9587d9ed8a03cafbaa23033fe0b0ab80
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$3.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$4.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..739f92bea3593a80caf872fb1ac735a91f5dff80
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$4.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$AbstractObjectList.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$AbstractObjectList.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba5555c3b21724011a4284ae989451b16f6c9daa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$AbstractObjectList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$ValidationContextImpl.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$ValidationContextImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad34121f04277e81121f876d4e39bc9051a37279
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$ValidationContextImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$XSFacetImpl.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$XSFacetImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b839d532da8fb2680110ff5bd6a9dff66c6fd1fe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$XSFacetImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$XSMVFacetImpl.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$XSMVFacetImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d770fae06b83d5d20bc0f255fab9d5133d667f4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl$XSMVFacetImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3313fd37be9653d6806e85f899c11037dcf8abe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDelegate.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..346863ef084bdcaefc7c9f9b0ca1fb18e940e938
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/XSSimpleTypeDelegate.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7094456780b67a2a1b7334d6514c5028d7a7be9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearMonthDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearMonthDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..5efbf36cf9380ade4371b9abd590285b8695c223
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearMonthDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearMonthDurationDV.class b/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearMonthDurationDV.class
new file mode 100644
index 0000000000000000000000000000000000000000..4155600ffa104f9a87f1cbcdd22ee3bf42b228bc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/dv/xs/YearMonthDurationDV.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/io/ASCIIReader.class b/src/main/resources/org/python/apache/xerces/impl/io/ASCIIReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f72614246eedad9c78d3c838c8fad3691356bbb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/io/ASCIIReader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/io/Latin1Reader.class b/src/main/resources/org/python/apache/xerces/impl/io/Latin1Reader.class
new file mode 100644
index 0000000000000000000000000000000000000000..8777142845ff82b25a8f2feb986eaa4c0faba14d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/io/Latin1Reader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/io/MalformedByteSequenceException.class b/src/main/resources/org/python/apache/xerces/impl/io/MalformedByteSequenceException.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c1793dc1260b85a9c5e679e7a8ed13618dc169e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/io/MalformedByteSequenceException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/io/UCSReader.class b/src/main/resources/org/python/apache/xerces/impl/io/UCSReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..38830c1fdffbe319e764482e77348ca54005125c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/io/UCSReader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/io/UTF16Reader.class b/src/main/resources/org/python/apache/xerces/impl/io/UTF16Reader.class
new file mode 100644
index 0000000000000000000000000000000000000000..f587d7afaa83aa1a2af9b3d3c423c25171684657
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/io/UTF16Reader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/io/UTF8Reader.class b/src/main/resources/org/python/apache/xerces/impl/io/UTF8Reader.class
new file mode 100644
index 0000000000000000000000000000000000000000..776615693c122775d0da13655035707cd2072d81
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/io/UTF8Reader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/DOMMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/DOMMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..dd2745543f382571f0f2b13721067ff89ec35fcb
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/DOMMessages.properties
@@ -0,0 +1,84 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces
+# DOM implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: DOMMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+        BadMessageKey = The error message corresponding to the message key can not be found.
+        FormatFailed = An internal error occurred while formatting the following message:\n  
+
+# DOM Core
+
+# exception codes
+DOMSTRING_SIZE_ERR = The specified range of text does not fit into a DOMString. 
+HIERARCHY_REQUEST_ERR  = An attempt was made to insert a node where it is not permitted. 
+INDEX_SIZE_ERR = The index or size is negative, or greater than the allowed value.
+INUSE_ATTRIBUTE_ERR = An attempt is made to add an attribute that is already in use elsewhere.
+INVALID_ACCESS_ERR  = A parameter or an operation is not supported by the underlying object. 
+INVALID_CHARACTER_ERR = An invalid or illegal XML character is specified. 
+INVALID_MODIFICATION_ERR =  An attempt is made to modify the type of the underlying object. 
+INVALID_STATE_ERR = An attempt is made to use an object that is not, or is no longer, usable. 
+NAMESPACE_ERR = An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
+NOT_FOUND_ERR = An attempt is made to reference a node in a context where it does not exist.
+NOT_SUPPORTED_ERR = The implementation does not support the requested type of object or operation. 
+NO_DATA_ALLOWED_ERR = Data is specified for a node which does not support data.
+NO_MODIFICATION_ALLOWED_ERR = An attempt is made to modify an object where modifications are not allowed.
+SYNTAX_ERR = An invalid or illegal string is specified. 
+VALIDATION_ERR = A call to a method such as insertBefore or removeChild would make the Node invalid with respect to document grammar.
+WRONG_DOCUMENT_ERR = A node is used in a different document than the one that created it.
+TYPE_MISMATCH_ERR = The value type for this parameter name is incompatible with the expected value type. 
+ 
+#error messages or exceptions
+FEATURE_NOT_SUPPORTED = The parameter {0} is recognized but the requested value cannot be set.
+FEATURE_NOT_FOUND = The parameter {0} is not recognized.
+STRING_TOO_LONG   = The resulting string is too long to fit in a DOMString: ''{0}''.
+
+#DOM Level 3 DOMError codes
+wf-invalid-character =  The text {0} of the {1} node contains invalid XML characters.
+wf-invalid-character-in-node-name = The {0} node named {1} contains invalid XML characters.
+cdata-sections-splitted =  CDATA sections containing the CDATA section termination marker \"]]>\"
+doctype-not-allowed = DOCTYPE declaration is not allowed.
+unsupported-encoding = The encoding {0} is not supported.
+
+#Error codes used in DOM Normalizer
+InvalidXMLCharInDOM = An invalid XML character (Unicode: 0x{0}) was found in the DOM during normalization.
+UndeclaredEntRefInAttrValue = The attribute \"{0}\" value \"{1}\" referenced an entity that was not declared.
+NullLocalElementName = A null local name was encountered during namespace normalization of element {0}.
+NullLocalAttrName = A null local name was encountered during namespace normalization of attribute {0}.
+
+#Error codes used in DOMParser
+InvalidDocumentClassName = The class name of the document factory \"{0}\" used to construct the DOM tree is not of type org.w3c.dom.Document.
+MissingDocumentClassName = The class name of the document factory \"{0}\" used to construct the DOM tree could not be found.
+CannotCreateDocumentClass = The class named \"{0}\" could not be constructed as a org.w3c.dom.Document.
+CannotQueryDeferredNode = Current element node cannot be queried when node expansion is deferred.
+
+# Error codes used by JAXP DocumentBuilder
+jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''.
+jaxp-null-input-source = The source specified cannot be null.
+
+#Ranges
+BAD_BOUNDARYPOINTS_ERR = The boundary-points of a Range do not meet specific requirements.
+INVALID_NODE_TYPE_ERR = The container of a boundary-point of a Range is being set to either a node of an invalid type or a node with an ancestor of an invalid type.
+
+
+#Events
+UNSPECIFIED_EVENT_TYPE_ERR = The Event's type was not specified by initializing the event before the method was called. 
+
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/DOMMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/DOMMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..dd2745543f382571f0f2b13721067ff89ec35fcb
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/DOMMessages_en.properties
@@ -0,0 +1,84 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces
+# DOM implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: DOMMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+        BadMessageKey = The error message corresponding to the message key can not be found.
+        FormatFailed = An internal error occurred while formatting the following message:\n  
+
+# DOM Core
+
+# exception codes
+DOMSTRING_SIZE_ERR = The specified range of text does not fit into a DOMString. 
+HIERARCHY_REQUEST_ERR  = An attempt was made to insert a node where it is not permitted. 
+INDEX_SIZE_ERR = The index or size is negative, or greater than the allowed value.
+INUSE_ATTRIBUTE_ERR = An attempt is made to add an attribute that is already in use elsewhere.
+INVALID_ACCESS_ERR  = A parameter or an operation is not supported by the underlying object. 
+INVALID_CHARACTER_ERR = An invalid or illegal XML character is specified. 
+INVALID_MODIFICATION_ERR =  An attempt is made to modify the type of the underlying object. 
+INVALID_STATE_ERR = An attempt is made to use an object that is not, or is no longer, usable. 
+NAMESPACE_ERR = An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
+NOT_FOUND_ERR = An attempt is made to reference a node in a context where it does not exist.
+NOT_SUPPORTED_ERR = The implementation does not support the requested type of object or operation. 
+NO_DATA_ALLOWED_ERR = Data is specified for a node which does not support data.
+NO_MODIFICATION_ALLOWED_ERR = An attempt is made to modify an object where modifications are not allowed.
+SYNTAX_ERR = An invalid or illegal string is specified. 
+VALIDATION_ERR = A call to a method such as insertBefore or removeChild would make the Node invalid with respect to document grammar.
+WRONG_DOCUMENT_ERR = A node is used in a different document than the one that created it.
+TYPE_MISMATCH_ERR = The value type for this parameter name is incompatible with the expected value type. 
+ 
+#error messages or exceptions
+FEATURE_NOT_SUPPORTED = The parameter {0} is recognized but the requested value cannot be set.
+FEATURE_NOT_FOUND = The parameter {0} is not recognized.
+STRING_TOO_LONG   = The resulting string is too long to fit in a DOMString: ''{0}''.
+
+#DOM Level 3 DOMError codes
+wf-invalid-character =  The text {0} of the {1} node contains invalid XML characters.
+wf-invalid-character-in-node-name = The {0} node named {1} contains invalid XML characters.
+cdata-sections-splitted =  CDATA sections containing the CDATA section termination marker \"]]>\"
+doctype-not-allowed = DOCTYPE declaration is not allowed.
+unsupported-encoding = The encoding {0} is not supported.
+
+#Error codes used in DOM Normalizer
+InvalidXMLCharInDOM = An invalid XML character (Unicode: 0x{0}) was found in the DOM during normalization.
+UndeclaredEntRefInAttrValue = The attribute \"{0}\" value \"{1}\" referenced an entity that was not declared.
+NullLocalElementName = A null local name was encountered during namespace normalization of element {0}.
+NullLocalAttrName = A null local name was encountered during namespace normalization of attribute {0}.
+
+#Error codes used in DOMParser
+InvalidDocumentClassName = The class name of the document factory \"{0}\" used to construct the DOM tree is not of type org.w3c.dom.Document.
+MissingDocumentClassName = The class name of the document factory \"{0}\" used to construct the DOM tree could not be found.
+CannotCreateDocumentClass = The class named \"{0}\" could not be constructed as a org.w3c.dom.Document.
+CannotQueryDeferredNode = Current element node cannot be queried when node expansion is deferred.
+
+# Error codes used by JAXP DocumentBuilder
+jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''.
+jaxp-null-input-source = The source specified cannot be null.
+
+#Ranges
+BAD_BOUNDARYPOINTS_ERR = The boundary-points of a Range do not meet specific requirements.
+INVALID_NODE_TYPE_ERR = The container of a boundary-point of a Range is being set to either a node of an invalid type or a node with an ancestor of an invalid type.
+
+
+#Events
+UNSPECIFIED_EVENT_TYPE_ERR = The Event's type was not specified by initializing the event before the method was called. 
+
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/DatatypeMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/DatatypeMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..f1739e7abdb03fe4289c026287ea6365cf69381e
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/DatatypeMessages.properties
@@ -0,0 +1,47 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces JAXP Datatype API implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: DatatypeMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+FieldCannotBeNull={0} cannot be called with 'null' parameter.
+UnknownField={0} called with an unknown field\:{1}
+#There are two similar keys 'InvalidXMLGreogorianCalendarValue' . Suffix (year, month) has been added and are used as per the context.
+InvalidXGCValue-milli=Year \= {0}, Month \= {1}, Day \= {2}, Hour \= {3}, Minute \= {4}, Second \= {5}, fractionalSecond \= {6}, Timezone \= {7} , is not a valid representation of an XML Gregorian Calendar value.
+#There are two similar keys 'InvalidXMLGreogorianCalendarValue' . Suffix (year, month) has been added and are used as per the context.
+InvalidXGCValue-fractional=Year \= {0}, Month \= {1}, Day \= {2}, Hour \= {3}, Minute \= {4}, Second \= {5}, fractionalSecond \= {6}, Timezone \= {7} , is not a valid representation of an XML Gregorian Calendar value.
+
+InvalidXGCFields=Invalid set of fields set for XMLGregorianCalendar
+
+InvalidFractional=Invalid value {0} for fractional second.
+
+#XGC stands for XML Gregorian Calendar
+InvalidXGCRepresentation="{0}" is not a valid representation of an XML Gregorian Calendar value.
+
+InvalidFieldValue=Invalid value {0} for {1} field.
+
+NegativeField= {0} field is negative
+
+AllFieldsNull=All the fields (javax.xml.datatype.DatatypeConstants.Field) are null.
+
+TooLarge={0} value "{1}" too large to be supported by this implementation
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/DatatypeMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/DatatypeMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..f1739e7abdb03fe4289c026287ea6365cf69381e
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/DatatypeMessages_en.properties
@@ -0,0 +1,47 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces JAXP Datatype API implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: DatatypeMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+FieldCannotBeNull={0} cannot be called with 'null' parameter.
+UnknownField={0} called with an unknown field\:{1}
+#There are two similar keys 'InvalidXMLGreogorianCalendarValue' . Suffix (year, month) has been added and are used as per the context.
+InvalidXGCValue-milli=Year \= {0}, Month \= {1}, Day \= {2}, Hour \= {3}, Minute \= {4}, Second \= {5}, fractionalSecond \= {6}, Timezone \= {7} , is not a valid representation of an XML Gregorian Calendar value.
+#There are two similar keys 'InvalidXMLGreogorianCalendarValue' . Suffix (year, month) has been added and are used as per the context.
+InvalidXGCValue-fractional=Year \= {0}, Month \= {1}, Day \= {2}, Hour \= {3}, Minute \= {4}, Second \= {5}, fractionalSecond \= {6}, Timezone \= {7} , is not a valid representation of an XML Gregorian Calendar value.
+
+InvalidXGCFields=Invalid set of fields set for XMLGregorianCalendar
+
+InvalidFractional=Invalid value {0} for fractional second.
+
+#XGC stands for XML Gregorian Calendar
+InvalidXGCRepresentation="{0}" is not a valid representation of an XML Gregorian Calendar value.
+
+InvalidFieldValue=Invalid value {0} for {1} field.
+
+NegativeField= {0} field is negative
+
+AllFieldsNull=All the fields (javax.xml.datatype.DatatypeConstants.Field) are null.
+
+TooLarge={0} value "{1}" too large to be supported by this implementation
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/JAXPValidationMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/JAXPValidationMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6a31cad569cbd0052a3b0cd15205b45668b420e2
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/JAXPValidationMessages.properties
@@ -0,0 +1,50 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces JAXP Validation API implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: JAXPValidationMessages.properties 683837 2008-08-08 04:12:37Z mrglavas $
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+# SchemaFactory error messages
+SchemaLanguageNull = The schema language specified cannot be null.
+SchemaLanguageLengthZero = The schema language specified cannot have a length of zero characters.
+SchemaSourceArrayNull = The Source array parameter cannot be null.
+SchemaSourceArrayMemberNull = The Source array parameter cannot contain any items that are null.
+SchemaFactorySourceUnrecognized = Source parameter of type ''{0}'' is not recognized by this SchemaFactory.
+SAXSourceNullInputSource = The SAXSource specified contains no InputSource.
+
+# Validator error messages
+SourceParameterNull = Source parameter cannot be null.
+SourceNotAccepted = Source parameter of type ''{0}'' is not accepted by this validator.
+SourceResultMismatch = Source parameter of type ''{0}'' is not compatible with result parameter of type ''{1}''.
+StAXIllegalInitialState = Expecting the initial state to be start document or start element.
+StreamResultNotInitialized = The StreamResult contains no OutputStream, Writer, or system ID.
+
+# TypeInfoProvider error messages
+TypeInfoProviderIllegalStateElement = Element type information cannot be queried from a TypeInfoProvider outside of a startElement or endElement callback.
+TypeInfoProviderIllegalStateAttribute = Attribute type information cannot be queried from a TypeInfoProvider outside of a startElement callback.
+
+# General error messages
+FeatureNameNull = The feature name cannot be null.
+ProperyNameNull = The property name cannot be null.
+
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/JAXPValidationMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/JAXPValidationMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6a31cad569cbd0052a3b0cd15205b45668b420e2
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/JAXPValidationMessages_en.properties
@@ -0,0 +1,50 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces JAXP Validation API implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: JAXPValidationMessages.properties 683837 2008-08-08 04:12:37Z mrglavas $
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+# SchemaFactory error messages
+SchemaLanguageNull = The schema language specified cannot be null.
+SchemaLanguageLengthZero = The schema language specified cannot have a length of zero characters.
+SchemaSourceArrayNull = The Source array parameter cannot be null.
+SchemaSourceArrayMemberNull = The Source array parameter cannot contain any items that are null.
+SchemaFactorySourceUnrecognized = Source parameter of type ''{0}'' is not recognized by this SchemaFactory.
+SAXSourceNullInputSource = The SAXSource specified contains no InputSource.
+
+# Validator error messages
+SourceParameterNull = Source parameter cannot be null.
+SourceNotAccepted = Source parameter of type ''{0}'' is not accepted by this validator.
+SourceResultMismatch = Source parameter of type ''{0}'' is not compatible with result parameter of type ''{1}''.
+StAXIllegalInitialState = Expecting the initial state to be start document or start element.
+StreamResultNotInitialized = The StreamResult contains no OutputStream, Writer, or system ID.
+
+# TypeInfoProvider error messages
+TypeInfoProviderIllegalStateElement = Element type information cannot be queried from a TypeInfoProvider outside of a startElement or endElement callback.
+TypeInfoProviderIllegalStateAttribute = Attribute type information cannot be queried from a TypeInfoProvider outside of a startElement callback.
+
+# General error messages
+FeatureNameNull = The feature name cannot be null.
+ProperyNameNull = The property name cannot be null.
+
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/SAXMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/SAXMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..ae65a962b081d61b8257557537d8df7bf412c546
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/SAXMessages.properties
@@ -0,0 +1,46 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces
+# SAX implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: SAXMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+# JAXP messages
+schema-not-supported = The specified schema language is not supported.
+jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''. 
+schema-already-specified = Property ''{0}'' cannot be set when a non-null Schema object has already been specified.
+
+# feature messages
+feature-not-supported = Feature ''{0}'' is not supported.
+feature-not-recognized = Feature ''{0}'' is not recognized.
+true-not-supported = True state for feature ''{0}'' is not supported.
+false-not-supported = False state for feature ''{0}'' is not supported.
+feature-read-only = Feature ''{0}'' is read only.
+
+# property messages
+property-not-supported = Property ''{0}'' is not supported.
+property-not-recognized = Property ''{0}'' is not recognized.
+property-read-only = Property ''{0}'' is read only.
+property-not-parsing-supported = Property ''{0}'' is not supported while parsing.
+dom-node-read-not-supported = Cannot read DOM node property. No DOM tree exists.
+incompatible-class = The value specified for property ''{0}'' cannot be casted to {1}.
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/SAXMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/SAXMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..ae65a962b081d61b8257557537d8df7bf412c546
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/SAXMessages_en.properties
@@ -0,0 +1,46 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces
+# SAX implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: SAXMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+# JAXP messages
+schema-not-supported = The specified schema language is not supported.
+jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''. 
+schema-already-specified = Property ''{0}'' cannot be set when a non-null Schema object has already been specified.
+
+# feature messages
+feature-not-supported = Feature ''{0}'' is not supported.
+feature-not-recognized = Feature ''{0}'' is not recognized.
+true-not-supported = True state for feature ''{0}'' is not supported.
+false-not-supported = False state for feature ''{0}'' is not supported.
+feature-read-only = Feature ''{0}'' is read only.
+
+# property messages
+property-not-supported = Property ''{0}'' is not supported.
+property-not-recognized = Property ''{0}'' is not recognized.
+property-read-only = Property ''{0}'' is read only.
+property-not-parsing-supported = Property ''{0}'' is not supported while parsing.
+dom-node-read-not-supported = Cannot read DOM node property. No DOM tree exists.
+incompatible-class = The value specified for property ''{0}'' cannot be casted to {1}.
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XIncludeMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XIncludeMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..01e82ea2fe745b2529b324c0b9edf680165c4e0f
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XIncludeMessages.properties
@@ -0,0 +1,56 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces XInclude implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: XIncludeMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n  
+
+# Messages for erroneous input
+NoFallback = An 'include' failed, and no 'fallback' element was found.
+MultipleFallbacks = The [children] of an 'include' element cannot contain more than one 'fallback' element.
+FallbackParent = A 'fallback' element was found that did not have 'include' as the parent.
+IncludeChild = Elements from namespace ''http://www.w3.org/2001/XInclude'', other than ''fallback'', are not allowed to be children of ''include'' elements.  However, ''{0}'' was found.
+FallbackChild = Elements from namespace ''http://www.w3.org/2001/XInclude'', other than ''include'', are not allowed to be children of ''fallback'' elements.  However, ''{0}'' was found.
+HrefMissing = The 'href' attribute of an 'include' element is missing.
+RecursiveInclude = Recursive include detected.  Document ''{0}'' was already processed.
+InvalidParseValue = Invalid value for ''parse'' attribute on ''include'' element: ''{0}''.
+XMLParseError = Error attempting to parse XML file (href=''{0}'').
+XMLResourceError = Include operation failed, reverting to fallback. Resource error reading file as XML (href=''{0}''). Reason: {1}
+TextResourceError = Include operation failed, reverting to fallback. Resource error reading file as text (href=''{0}''). Reason: {1}
+NonDuplicateNotation = Multiple notations were used which had the name ''{0}'', but which were not determined to be duplicates.
+NonDuplicateUnparsedEntity = Multiple unparsed entities were used which had the name ''{0}'', but which were not determined to be duplicates.
+XpointerMissing = xpointer attribute must be present when href attribute is absent.
+AcceptMalformed = Characters outside the range #x20 through #x7E are not allowed in the value of the 'accept' attribute of an 'include' element.
+AcceptLanguageMalformed = Characters outside the range #x20 through #x7E are not allowed in the value of the 'accept-language' attribute of an 'include' element.
+RootElementRequired = A well-formed document requires a root element.
+MultipleRootElements = A well-formed document must not contain multiple root elements.
+ContentIllegalAtTopLevel = The replacement of an 'include' element appearing as the document element in the top-level source infoset cannot contain characters.
+UnexpandedEntityReferenceIllegal = The replacement of an 'include' element appearing as the document element in the top-level source infoset cannot contain unexpanded entity references.
+HrefFragmentIdentifierIllegal = Fragment identifiers must not be used. The ''href'' attribute value ''{0}'' is not permitted.
+HrefSyntacticallyInvalid = ''href'' attribute value ''{0}'' is syntactically invalid. After applying escaping rules the value is neither a syntactically correct URI or IRI.
+XPointerStreamability = An xpointer was specified that points to a location in the source infoset. This location cannot be accessed due to the streaming nature of the processor.
+XPointerResolutionUnsuccessful = XPointer resolution unsuccessful.
+
+# Messages from erroneous set-up
+IncompatibleNamespaceContext = The type of the NamespaceContext is incompatible with using XInclude; it must be an instance of XIncludeNamespaceSupport
+ExpandedSystemId = Could not expand system id of included resource
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XIncludeMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XIncludeMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..01e82ea2fe745b2529b324c0b9edf680165c4e0f
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XIncludeMessages_en.properties
@@ -0,0 +1,56 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces XInclude implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: XIncludeMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n  
+
+# Messages for erroneous input
+NoFallback = An 'include' failed, and no 'fallback' element was found.
+MultipleFallbacks = The [children] of an 'include' element cannot contain more than one 'fallback' element.
+FallbackParent = A 'fallback' element was found that did not have 'include' as the parent.
+IncludeChild = Elements from namespace ''http://www.w3.org/2001/XInclude'', other than ''fallback'', are not allowed to be children of ''include'' elements.  However, ''{0}'' was found.
+FallbackChild = Elements from namespace ''http://www.w3.org/2001/XInclude'', other than ''include'', are not allowed to be children of ''fallback'' elements.  However, ''{0}'' was found.
+HrefMissing = The 'href' attribute of an 'include' element is missing.
+RecursiveInclude = Recursive include detected.  Document ''{0}'' was already processed.
+InvalidParseValue = Invalid value for ''parse'' attribute on ''include'' element: ''{0}''.
+XMLParseError = Error attempting to parse XML file (href=''{0}'').
+XMLResourceError = Include operation failed, reverting to fallback. Resource error reading file as XML (href=''{0}''). Reason: {1}
+TextResourceError = Include operation failed, reverting to fallback. Resource error reading file as text (href=''{0}''). Reason: {1}
+NonDuplicateNotation = Multiple notations were used which had the name ''{0}'', but which were not determined to be duplicates.
+NonDuplicateUnparsedEntity = Multiple unparsed entities were used which had the name ''{0}'', but which were not determined to be duplicates.
+XpointerMissing = xpointer attribute must be present when href attribute is absent.
+AcceptMalformed = Characters outside the range #x20 through #x7E are not allowed in the value of the 'accept' attribute of an 'include' element.
+AcceptLanguageMalformed = Characters outside the range #x20 through #x7E are not allowed in the value of the 'accept-language' attribute of an 'include' element.
+RootElementRequired = A well-formed document requires a root element.
+MultipleRootElements = A well-formed document must not contain multiple root elements.
+ContentIllegalAtTopLevel = The replacement of an 'include' element appearing as the document element in the top-level source infoset cannot contain characters.
+UnexpandedEntityReferenceIllegal = The replacement of an 'include' element appearing as the document element in the top-level source infoset cannot contain unexpanded entity references.
+HrefFragmentIdentifierIllegal = Fragment identifiers must not be used. The ''href'' attribute value ''{0}'' is not permitted.
+HrefSyntacticallyInvalid = ''href'' attribute value ''{0}'' is syntactically invalid. After applying escaping rules the value is neither a syntactically correct URI or IRI.
+XPointerStreamability = An xpointer was specified that points to a location in the source infoset. This location cannot be accessed due to the streaming nature of the processor.
+XPointerResolutionUnsuccessful = XPointer resolution unsuccessful.
+
+# Messages from erroneous set-up
+IncompatibleNamespaceContext = The type of the NamespaceContext is incompatible with using XInclude; it must be an instance of XIncludeNamespaceSupport
+ExpandedSystemId = Could not expand system id of included resource
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessageFormatter.class b/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..a266effa07b4c9146cf9f60d71f970daa81b0a27
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..47e42141a2c5cc7038dde7fd28697454eb71ebfa
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessages.properties
@@ -0,0 +1,309 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file contains error and warning messages related to XML
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: XMLMessages.properties 595214 2007-11-15 05:32:38Z mrglavas $
+
+        BadMessageKey = The error message corresponding to the message key can not be found.
+        FormatFailed = An internal error occurred while formatting the following message:\n  
+        
+# Document messages
+        PrematureEOF=Premature end of file.
+# 2.1 Well-Formed XML Documents
+        RootElementRequired = The root element is required in a well-formed document.
+# 2.2 Characters
+        InvalidCharInCDSect = An invalid XML character (Unicode: 0x{0}) was found in the CDATA section.
+        InvalidCharInContent = An invalid XML character (Unicode: 0x{0}) was found in the element content of the document.
+        TwoColonsInQName = An invalid second ':' was found in the element type or attribute name.
+        ColonNotLegalWithNS = A colon is not allowed in the name ''{0}'' when namespaces are enabled.
+        InvalidCharInMisc = An invalid XML character (Unicode: 0x{0}) was found in markup after the end of the element content.
+        InvalidCharInProlog = An invalid XML character (Unicode: 0x{0}) was found in the prolog of the document.
+        InvalidCharInXMLDecl = An invalid XML character (Unicode: 0x{0}) was found in the XML declaration.
+# 2.4 Character Data and Markup
+        CDEndInContent = The character sequence \"]]>\" must not appear in content unless used to mark the end of a CDATA section.
+# 2.7 CDATA Sections
+        CDSectUnterminated = The CDATA section must end with \"]]>\".
+# 2.8 Prolog and Document Type Declaration
+        XMLDeclMustBeFirst = The XML declaration may only appear at the very beginning of the document.
+        EqRequiredInXMLDecl = The '' = '' character must follow \"{0}\" in the XML declaration.
+        QuoteRequiredInXMLDecl = The value following \"{0}\" in the XML declaration must be a quoted string.
+        XMLDeclUnterminated = The XML declaration must end with \"?>\".
+        VersionInfoRequired = The version is required in the XML declaration.
+        SpaceRequiredBeforeVersionInXMLDecl = White space is required before the version pseudo attribute in the XML declaration.
+        SpaceRequiredBeforeEncodingInXMLDecl = White space is required before the encoding pseudo attribute in the XML declaration.
+        SpaceRequiredBeforeStandalone = White space is required before the encoding pseudo attribute in the XML declaration.
+        MarkupNotRecognizedInProlog = The markup in the document preceding the root element must be well-formed.
+        MarkupNotRecognizedInMisc = The markup in the document following the root element must be well-formed.
+        AlreadySeenDoctype = Already seen doctype.
+        DoctypeNotAllowed = DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.
+        ContentIllegalInProlog = Content is not allowed in prolog.
+        ReferenceIllegalInProlog = Reference is not allowed in prolog.
+# Trailing Misc
+        ContentIllegalInTrailingMisc=Content is not allowed in trailing section.
+        ReferenceIllegalInTrailingMisc=Reference is not allowed in trailing section.
+        
+# 2.9 Standalone Document Declaration
+        SDDeclInvalid = The standalone document declaration value must be \"yes\" or \"no\", not \"{0}\".
+# 2.12 Language Identification
+        XMLLangInvalid = The xml:lang attribute value \"{0}\" is an invalid language identifier.
+# 3. Logical Structures
+        ETagRequired = The element type \"{0}\" must be terminated by the matching end-tag \"</{0}>\".
+# 3.1 Start-Tags, End-Tags, and Empty-Element Tags
+        ElementUnterminated = Element type \"{0}\" must be followed by either attribute specifications, \">\" or \"/>\".
+        EqRequiredInAttribute = Attribute name \"{1}\" associated with an element type \"{0}\" must be followed by the '' = '' character.
+        OpenQuoteExpected = Open quote is expected for attribute \"{1}\" associated with an  element type  \"{0}\".
+        CloseQuoteExpected = Close quote is expected for attribute \"{1}\" associated with an element type \"{0}\".
+        AttributeNotUnique = Attribute \"{1}\" was already specified for element \"{0}\".
+        AttributeNSNotUnique = Attribute \"{1}\" bound to namespace \"{2}\" was already specified for element \"{0}\".
+        ETagUnterminated = The end-tag for element type \"{0}\" must end with a ''>'' delimiter.
+        MarkupNotRecognizedInContent = The content of elements must consist of well-formed character data or markup.
+        DoctypeIllegalInContent = A DOCTYPE is not allowed in content.
+# 4.1 Character and Entity References
+        ReferenceUnterminated = The reference must be terminated by a ';' delimiter.
+# 4.3.2 Well-Formed Parsed Entities
+        ReferenceNotInOneEntity = The reference must be entirely contained within the same parsed entity.
+        ElementEntityMismatch = The element \"{0}\" must start and end within the same entity.
+        MarkupEntityMismatch=XML document structures must start and end within the same entity.
+        
+# Messages common to Document and DTD
+# 2.2 Characters
+        InvalidCharInAttValue = An invalid XML character (Unicode: 0x{2}) was found in the value of attribute \"{1}\" and element is \"{0}\".
+        InvalidCharInComment = An invalid XML character (Unicode: 0x{0}) was found in the comment.
+        InvalidCharInPI = An invalid XML character (Unicode: 0x{0}) was found in the processing instruction.
+        InvalidCharInInternalSubset = An invalid XML character (Unicode: 0x{0}) was found in the internal subset of the DTD.
+        InvalidCharInTextDecl = An invalid XML character (Unicode: 0x{0}) was found in the text declaration.
+# 2.3 Common Syntactic Constructs
+        QuoteRequiredInAttValue = The value of attribute \"{1}\" must begin with either a single or double quote character.
+        LessthanInAttValue = The value of attribute \"{1}\" associated with an element type \"{0}\" must not contain the ''<'' character.
+        AttributeValueUnterminated = The value for attribute \"{1}\" must end with the matching quote character.
+# 2.5 Comments
+        InvalidCommentStart = Comment must start with \"<!--\".
+        DashDashInComment = The string \"--\" is not permitted within comments.
+        CommentUnterminated = The comment must end with \"-->\".
+        COMMENT_NOT_IN_ONE_ENTITY = The comment is not enclosed in the same entity.
+# 2.6 Processing Instructions
+        PITargetRequired = The processing instruction must begin with the name of the target.
+        SpaceRequiredInPI = White space is required between the processing instruction target and data.
+        PIUnterminated = The processing instruction must end with \"?>\".
+        ReservedPITarget = The processing instruction target matching \"[xX][mM][lL]\" is not allowed.
+        PI_NOT_IN_ONE_ENTITY = The processing instruction is not enclosed in the same entity.
+# 2.8 Prolog and Document Type Declaration
+        VersionInfoInvalid = Invalid version \"{0}\".
+        VersionNotSupported = XML version \"{0}\" is not supported, only XML 1.0 is supported.
+        VersionNotSupported11 = XML version \"{0}\" is not supported, only XML 1.0 and XML 1.1 are supported.
+# 4.1 Character and Entity References
+        DigitRequiredInCharRef = A decimal representation must immediately follow the \"&#\" in a character reference.
+        HexdigitRequiredInCharRef = A hexadecimal representation must immediately follow the \"&#x\" in a character reference.
+        SemicolonRequiredInCharRef = The character reference must end with the ';' delimiter.
+        InvalidCharRef = Character reference \"&#{0}\" is an invalid XML character.
+        NameRequiredInReference = The entity name must immediately follow the '&' in the entity reference.
+        SemicolonRequiredInReference = The reference to entity \"{0}\" must end with the '';'' delimiter.
+# 4.3.1 The Text Declaration
+        TextDeclMustBeFirst = The text declaration may only appear at the very beginning of the external parsed entity.
+        EqRequiredInTextDecl = The '' = '' character must follow \"{0}\" in the text declaration.
+        QuoteRequiredInTextDecl = The value following \"{0}\" in the text declaration must be a quoted string.
+        CloseQuoteMissingInTextDecl = closing quote in the value following \"{0}\" in the text declaration is missing.
+        SpaceRequiredBeforeVersionInTextDecl = White space is required before the version pseudo attribute in the text declaration.
+        SpaceRequiredBeforeEncodingInTextDecl = White space is required before the encoding pseudo attribute in the text declaration.
+        TextDeclUnterminated = The text declaration must end with \"?>\".
+        EncodingDeclRequired = The encoding declaration is required in the text declaration.
+        NoMorePseudoAttributes = No more pseudo attributes are allowed.
+        MorePseudoAttributes = More pseudo attributes are expected.
+        PseudoAttrNameExpected = A pseudo attribute name is expected. 
+# 4.3.2 Well-Formed Parsed Entities
+        CommentNotInOneEntity = The comment must be entirely contained within the same parsed entity.
+        PINotInOneEntity = The processing instruction must be entirely contained within the same parsed entity.
+# 4.3.3 Character Encoding in Entities
+        EncodingDeclInvalid = Invalid encoding name \"{0}\".
+        EncodingByteOrderUnsupported = Given byte order for encoding \"{0}\" is not supported.
+        InvalidByte = Invalid byte {0} of {1}-byte UTF-8 sequence.
+        ExpectedByte = Expected byte {0} of {1}-byte UTF-8 sequence.  
+        InvalidHighSurrogate = High surrogate bits in UTF-8 sequence must not exceed 0x10 but found 0x{0}.
+        OperationNotSupported = Operation \"{0}\" not supported by {1} reader.
+        InvalidASCII = Byte \"{0}\" is not a member of the (7-bit) ASCII character set.
+        CharConversionFailure = An entity determined to be in a certain encoding must not contain sequences illegal in that encoding.
+        
+# DTD Messages
+# 2.2 Characters
+        InvalidCharInEntityValue = An invalid XML character (Unicode: 0x{0}) was found in the literal entity value.
+        InvalidCharInExternalSubset = An invalid XML character (Unicode: 0x{0}) was found in the external subset of the DTD.
+        InvalidCharInIgnoreSect = An invalid XML character (Unicode: 0x{0}) was found in the excluded conditional section.
+        InvalidCharInPublicID = An invalid XML character (Unicode: 0x{0}) was found in the public identifier.
+        InvalidCharInSystemID = An invalid XML character (Unicode: 0x{0}) was found in the system identifier.
+# 2.3 Common Syntactic Constructs
+        SpaceRequiredAfterSYSTEM = White space is required after keyword SYSTEM in DOCTYPE decl.
+        QuoteRequiredInSystemID = The system identifier must begin with either a single or double quote character.
+        SystemIDUnterminated = The system identifier must end with the matching quote character.
+        SpaceRequiredAfterPUBLIC = White spaces are required after keyword PUBLIC in DOCTYPE decl.
+        QuoteRequiredInPublicID = The public identifier must begin with either a single or double quote character.
+        PublicIDUnterminated = The public identifier must end with the matching quote character.
+        PubidCharIllegal = The character (Unicode: 0x{0}) is not permitted in the public identifier.
+        SpaceRequiredBetweenPublicAndSystem = White spaces are required between publicId and systemId.
+# 2.8 Prolog and Document Type Declaration
+        MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = White space is required after \"<!DOCTYPE\" in the document type declaration.
+        MSG_ROOT_ELEMENT_TYPE_REQUIRED = The root element type must appear after \"<!DOCTYPE\" in the document type declaration.
+        DoctypedeclUnterminated = The document type declaration for root element type \"{0}\" must end with ''>''.
+        PEReferenceWithinMarkup = The parameter entity reference \"%{0};\" cannot occur within markup in the internal subset of the DTD.
+        MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = The markup declarations contained or pointed to by the document type declaration must be well-formed.
+# 2.10 White Space Handling
+        MSG_XML_SPACE_DECLARATION_ILLEGAL = The attribute declaration for \"xml:space\" must be given as an enumerated type whose only possible values are \"default\" and \"preserve\".
+# 3.2 Element Type Declarations
+        MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ELEMENTDECL = White space is required after \"<!ELEMENT\" in the element type declaration.
+        MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL = The element type is required in the element type declaration.
+        MSG_SPACE_REQUIRED_BEFORE_CONTENTSPEC_IN_ELEMENTDECL = White space is required after the element type \"{0}\" in the element type declaration.
+        MSG_CONTENTSPEC_REQUIRED_IN_ELEMENTDECL = The constraint is required after the element type \"{0}\" in the element type declaration.
+        ElementDeclUnterminated = The declaration for element type \"{0}\" must end with ''>''.
+# 3.2.1 Element Content
+        MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN = A ''('' character or an element type is required in the declaration of element type \"{0}\".
+        MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN = A '')'' is required in the declaration of element type \"{0}\".
+# 3.2.2 Mixed Content
+        MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT = An element type is required in the declaration of element type \"{0}\".
+        MSG_CLOSE_PAREN_REQUIRED_IN_MIXED = A '')'' is required in the declaration of element type \"{0}\".
+        MixedContentUnterminated = The mixed content model \"{0}\" must end with \")*\" when the types of child elements are constrained.
+# 3.3 Attribute-List Declarations
+        MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ATTLISTDECL = White space is required after \"<!ATTLIST\" in the attribute-list declaration.
+        MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL = The element type is required in the attribute-list declaration.
+        MSG_SPACE_REQUIRED_BEFORE_ATTRIBUTE_NAME_IN_ATTDEF = White space is required before the attribute name in the attribute-list declaration for element \"{0}\".
+        AttNameRequiredInAttDef = The attribute name must be specified in the attribute-list declaration for element \"{0}\".
+        MSG_SPACE_REQUIRED_BEFORE_ATTTYPE_IN_ATTDEF = White space is required before the attribute type in the declaration of attribute \"{1}\" for element \"{0}\".
+        AttTypeRequiredInAttDef = The attribute type is required in the declaration of attribute \"{1}\" for element \"{0}\".
+        MSG_SPACE_REQUIRED_BEFORE_DEFAULTDECL_IN_ATTDEF = White space is required before the attribute default in the declaration of attribute \"{1}\" for element \"{0}\".
+        MSG_DUPLICATE_ATTRIBUTE_DEFINITION = More than one attribute definition is provided for the same attribute \"{1}\" of a given element \"{0}\".
+# 3.3.1 Attribute Types
+        MSG_SPACE_REQUIRED_AFTER_NOTATION_IN_NOTATIONTYPE = White space must appear after \"NOTATION\" in the \"{1}\" attribute declaration.
+        MSG_OPEN_PAREN_REQUIRED_IN_NOTATIONTYPE = The ''('' character must follow \"NOTATION\" in the \"{1}\" attribute declaration.
+        MSG_NAME_REQUIRED_IN_NOTATIONTYPE = The notation name is required in the notation type list for the \"{1}\" attribute declaration.
+        NotationTypeUnterminated = The notation type list must end with '')'' in the \"{1}\" attribute declaration.
+        MSG_NMTOKEN_REQUIRED_IN_ENUMERATION = The name token is required in the enumerated type list for the \"{1}\" attribute declaration.
+        EnumerationUnterminated = The enumerated type list must end with '')'' in the \"{1}\" attribute declaration.
+        MSG_DISTINCT_TOKENS_IN_ENUMERATION = The enumeration value \"{1}\" was specified more than once in the declaration of attribute \"{2}\" for element \"{0}\". The NMTOKENS in a single Enumeration attribute declaration must all be distinct.
+        MSG_DISTINCT_NOTATION_IN_ENUMERATION = The enumeration value \"{1}\" was specified more than once in the declaration of attribute \"{2}\" for element \"{0}\". The NOTATION names in a single NotationType attribute declaration must all be distinct.
+# 3.3.2 Attribute Defaults
+        MSG_SPACE_REQUIRED_AFTER_FIXED_IN_DEFAULTDECL = White space must appear after \"FIXED\" in the \"{1}\" attribute declaration.
+# 3.4 Conditional Sections
+        IncludeSectUnterminated = The included conditional section must end with \"]]>\".
+        IgnoreSectUnterminated = The excluded conditional section must end with \"]]>\".
+# 4.1 Character and Entity References
+        NameRequiredInPEReference = The entity name must immediately follow the '%' in the parameter entity reference.
+        SemicolonRequiredInPEReference = The parameter entity reference \"%{0};\" must end with the '';'' delimiter.
+# 4.2 Entity Declarations
+        MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL = White space is required after \"<!ENTITY\" in the entity declaration.
+        MSG_SPACE_REQUIRED_BEFORE_PERCENT_IN_PEDECL = White space is required between \"<!ENTITY\" and the '%' character in the parameter entity declaration.
+        MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_PEDECL = White space is required between the '%' and the entity name in the parameter entity declaration.
+        MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL = The name of the entity is required in the entity declaration.
+        MSG_SPACE_REQUIRED_AFTER_ENTITY_NAME_IN_ENTITYDECL = White space is required between the entity name \"{0}\" and the definition in the entity declaration.
+        MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL = White space is required between \"NDATA\" and the notation name in the declaration for the entity \"{0}\".
+        MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = White space is required before \"NDATA\" in the declaration for the entity \"{0}\".
+        MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = The notation name is required after \"NDATA\" in the declaration for the entity \"{0}\".
+        EntityDeclUnterminated = The declaration for the entity \"{0}\" must end with ''>''.
+        MSG_DUPLICATE_ENTITY_DEFINITION = Entity \"{0}\" is declared more than once.        
+# 4.2.2 External Entities
+        ExternalIDRequired = The external entity declaration must begin with either \"SYSTEM\" or \"PUBLIC\".
+        MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = White space is required between \"PUBLIC\" and the public identifier.
+        MSG_SPACE_REQUIRED_AFTER_PUBIDLITERAL_IN_EXTERNALID = White space is required between the public identifier and the system identifier.
+        MSG_SPACE_REQUIRED_BEFORE_SYSTEMLITERAL_IN_EXTERNALID = White space is required between \"SYSTEM\" and the system identifier.
+        MSG_URI_FRAGMENT_IN_SYSTEMID = The fragment identifier should not be specified as part of the system identifier \"{0}\".
+# 4.7 Notation Declarations
+        MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_NOTATIONDECL = White space is required after \"<!NOTATION\" in the notation declaration.
+        MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL = The name of the notation is required in the notation declaration.
+        MSG_SPACE_REQUIRED_AFTER_NOTATION_NAME_IN_NOTATIONDECL = White space is required after the notation name \"{0}\" in the notation declaration.
+        ExternalIDorPublicIDRequired = The declaration for the notation \"{0}\" must include a system or public identifier.
+        NotationDeclUnterminated = The declaration for the notation \"{0}\" must end with ''>''.
+        
+# Validation messages
+        DuplicateTypeInMixedContent = The element type \"{1}\" was already specified in the content model of the element decl \"{0}\".
+        ENTITIESInvalid = Attribute value \"{1}\" of type ENTITIES must be the names of one or more unparsed entities.
+        ENTITYInvalid = Attribute value \"{1}\" of type ENTITY must be the name of an unparsed entity.
+        IDDefaultTypeInvalid = The ID attribute \"{0}\" must have a declared default of \"#IMPLIED\" or \"#REQUIRED\".
+        IDInvalid = Attribute value \"{0}\" of type ID must be a name.
+        IDInvalidWithNamespaces = Attribute value \"{0}\" of type ID must be an NCName when namespaces are enabled.
+        IDNotUnique = Attribute value \"{0}\" of type ID must be unique within the document.
+        IDREFInvalid = Attribute value \"{0}\" of type IDREF must be a name.
+        IDREFInvalidWithNamespaces = Attribute value \"{0}\" of type IDREF must be an NCName when namespaces are enabled.
+        IDREFSInvalid = Attribute value \"{0}\" of type IDREFS must be one or more names.
+        ILL_FORMED_PARAMETER_ENTITY_WHEN_USED_IN_DECL = The replacement text of parameter entity \"{0}\" must include properly nested declarations when the entity reference is used as a complete declaration.
+        ImproperDeclarationNesting = The replacement text of parameter entity \"{0}\" must include properly nested declarations.
+        ImproperGroupNesting = The replacement text of parameter entity \"{0}\" must include properly nested pairs of parentheses.
+        INVALID_PE_IN_CONDITIONAL = The replacement text of parameter entity \"{0}\" must include the entire conditional section or just INCLUDE or IGNORE.
+        MSG_ATTRIBUTE_NOT_DECLARED = Attribute \"{1}\" must be declared for element type \"{0}\".
+        MSG_ATTRIBUTE_VALUE_NOT_IN_LIST = Attribute \"{0}\" with value \"{1}\" must have a value from the list \"{2}\".
+        MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE = The value \"{1}\" of attribute \"{0}\" must not be changed by normalization (to \"{2}\") in a standalone document.
+        MSG_CONTENT_INCOMPLETE = The content of element type \"{0}\" is incomplete, it must match \"{1}\".
+        MSG_CONTENT_INVALID = The content of element type \"{0}\" must match \"{1}\".
+        MSG_CONTENT_INVALID_SPECIFIED = The content of element type \"{0}\" must match \"{1}\".  Children of type \"{2}\" are not allowed.
+        MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED = Attribute \"{1}\" for element type \"{0}\" has a default value and must be specified in a standalone document.
+        MSG_DUPLICATE_ATTDEF = Attribute \"{1}\" is already declared for element type \"{0}\".
+        MSG_ELEMENT_ALREADY_DECLARED = Element type \"{0}\" must not be declared more than once.
+        MSG_ELEMENT_NOT_DECLARED = Element type \"{0}\" must be declared.
+        MSG_GRAMMAR_NOT_FOUND = Document is invalid: no grammar found.
+        MSG_ELEMENT_WITH_ID_REQUIRED = An element with the identifier \"{0}\" must appear in the document.
+        MSG_EXTERNAL_ENTITY_NOT_PERMITTED = The reference to external entity \"{0}\" is not permitted in a standalone document.
+        MSG_FIXED_ATTVALUE_INVALID = Attribute \"{1}\" with value \"{2}\" must have a value of \"{3}\".
+        MSG_MORE_THAN_ONE_ID_ATTRIBUTE = Element type \"{0}\" already has attribute \"{1}\" of type ID, a second attribute \"{2}\" of type ID is not permitted.
+        MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE = Element type \"{0}\" already has attribute \"{1}\" of type NOTATION, a second attribute \"{2}\" of type NOTATION is not permitted.
+        MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE = The notation \"{1}\" must be declared when referenced in the notation type list for attribute \"{0}\".
+        MSG_NOTATION_NOT_DECLARED_FOR_UNPARSED_ENTITYDECL = The notation \"{1}\" must be declared when referenced in the unparsed entity declaration for \"{0}\".
+        MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE = The reference to entity \"{0}\" declared in the external subset of the DTD or in a parameter entity is not permitted in a standalone document.
+        MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED = Attribute \"{1}\" is required and must be specified for element type \"{0}\".
+        MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE = In a standalone document white space must not occur between elements with element content which are declared in the external subset of the DTD or in a parameter entity.
+        NMTOKENInvalid = Attribute value \"{0}\" of type NMTOKEN must be a name token.
+        NMTOKENSInvalid = Attribute value \"{0}\" of type NMTOKENS must be one or more name tokens.
+        NoNotationOnEmptyElement = Element type \"{0}\" which was declared EMPTY cannot declare attribute \"{1}\" of type NOTATION.
+        RootElementTypeMustMatchDoctypedecl = Document root element \"{1}\", must match DOCTYPE root \"{0}\".
+        UndeclaredElementInContentSpec = The content model of element \"{0}\" refers to the undeclared element \"{1}\".
+        UniqueNotationName = The declaration for the notation \"{0}\" is not unique. A given Name must not be declared in more than one notation declaration.
+        ENTITYFailedInitializeGrammar =  ENTITYDatatype Validator: Failed Need to call initialize method with a valid Grammar reference. 	
+        ENTITYNotUnparsed = ENTITY \"{0}\" is not unparsed.
+        ENTITYNotValid = ENTITY \"{0}\" is not valid.
+        EmptyList = Value of type ENTITIES, IDREFS, and NMTOKENS cannot be empty list.
+
+# Entity related messages
+# 3.1 Start-Tags, End-Tags, and Empty-Element Tags
+        ReferenceToExternalEntity = The external entity reference \"&{0};\" is not permitted in an attribute value.
+# 4.1 Character and Entity References
+        EntityNotDeclared = The entity \"{0}\" was referenced, but not declared.
+        ReferenceToUnparsedEntity = The unparsed entity reference \"&{0};\" is not permitted.
+        RecursiveReference = Recursive entity reference \"{0}\". (Reference path: {1}),
+        RecursiveGeneralReference = Recursive general entity reference \"&{0};\". (Reference path: {1}),
+        RecursivePEReference = Recursive parameter entity reference \"%{0};\". (Reference path: {1}),
+# 4.3.3 Character Encoding in Entities
+        EncodingNotSupported = The encoding \"{0}\" is not supported.
+        EncodingRequired = A parsed entity not encoded in either UTF-8 or UTF-16 must contain an encoding declaration.
+        
+# Namespaces support
+# 4. Using Qualified Names
+        IllegalQName = Element or attribute do not match QName production: QName::=(NCName':')?NCName. 
+        ElementXMLNSPrefix = Element \"{0}\" cannot have \"xmlns\" as its prefix.
+        ElementPrefixUnbound = The prefix \"{0}\" for element \"{1}\" is not bound.
+        AttributePrefixUnbound = The prefix \"{2}\" for attribute \"{1}\" associated with an element type \"{0}\" is not bound.
+        EmptyPrefixedAttName = The value of the attribute \"{0}\" is invalid. Prefixed namespace bindings may not be empty.
+        PrefixDeclared = The namespace prefix \"{0}\" was not declared.
+        CantBindXMLNS = The prefix "xmlns" cannot be bound to any namespace explicitly; neither can the namespace for "xmlns" be bound to any prefix explicitly.
+        CantBindXML = The prefix "xml" cannot be bound to any namespace other than its usual namespace; neither can the namespace for "xml" be bound to any prefix other than "xml".
+        MSG_ATT_DEFAULT_INVALID = The defaultValue \"{1}\" of attribute \"{0}\" is not legal as for the lexical constraints of this attribute type.
+
+# REVISIT: These need messages
+        MSG_SPACE_REQUIRED_AFTER_SYSTEMLITERAL_IN_EXTERNALID=MSG_SPACE_REQUIRED_AFTER_SYSTEMLITERAL_IN_EXTERNALID
+        OpenQuoteMissingInDecl=OpenQuoteMissingInDecl
+        InvalidCharInLiteral=InvalidCharInLiteral
+
+
+#Application can set the limit of number of entities that should be expanded by the parser.
+EntityExpansionLimitExceeded=The parser has encountered more than \"{0}\" entity expansions in this document; this is the limit imposed by the application.
+
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..47e42141a2c5cc7038dde7fd28697454eb71ebfa
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XMLMessages_en.properties
@@ -0,0 +1,309 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file contains error and warning messages related to XML
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: XMLMessages.properties 595214 2007-11-15 05:32:38Z mrglavas $
+
+        BadMessageKey = The error message corresponding to the message key can not be found.
+        FormatFailed = An internal error occurred while formatting the following message:\n  
+        
+# Document messages
+        PrematureEOF=Premature end of file.
+# 2.1 Well-Formed XML Documents
+        RootElementRequired = The root element is required in a well-formed document.
+# 2.2 Characters
+        InvalidCharInCDSect = An invalid XML character (Unicode: 0x{0}) was found in the CDATA section.
+        InvalidCharInContent = An invalid XML character (Unicode: 0x{0}) was found in the element content of the document.
+        TwoColonsInQName = An invalid second ':' was found in the element type or attribute name.
+        ColonNotLegalWithNS = A colon is not allowed in the name ''{0}'' when namespaces are enabled.
+        InvalidCharInMisc = An invalid XML character (Unicode: 0x{0}) was found in markup after the end of the element content.
+        InvalidCharInProlog = An invalid XML character (Unicode: 0x{0}) was found in the prolog of the document.
+        InvalidCharInXMLDecl = An invalid XML character (Unicode: 0x{0}) was found in the XML declaration.
+# 2.4 Character Data and Markup
+        CDEndInContent = The character sequence \"]]>\" must not appear in content unless used to mark the end of a CDATA section.
+# 2.7 CDATA Sections
+        CDSectUnterminated = The CDATA section must end with \"]]>\".
+# 2.8 Prolog and Document Type Declaration
+        XMLDeclMustBeFirst = The XML declaration may only appear at the very beginning of the document.
+        EqRequiredInXMLDecl = The '' = '' character must follow \"{0}\" in the XML declaration.
+        QuoteRequiredInXMLDecl = The value following \"{0}\" in the XML declaration must be a quoted string.
+        XMLDeclUnterminated = The XML declaration must end with \"?>\".
+        VersionInfoRequired = The version is required in the XML declaration.
+        SpaceRequiredBeforeVersionInXMLDecl = White space is required before the version pseudo attribute in the XML declaration.
+        SpaceRequiredBeforeEncodingInXMLDecl = White space is required before the encoding pseudo attribute in the XML declaration.
+        SpaceRequiredBeforeStandalone = White space is required before the encoding pseudo attribute in the XML declaration.
+        MarkupNotRecognizedInProlog = The markup in the document preceding the root element must be well-formed.
+        MarkupNotRecognizedInMisc = The markup in the document following the root element must be well-formed.
+        AlreadySeenDoctype = Already seen doctype.
+        DoctypeNotAllowed = DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.
+        ContentIllegalInProlog = Content is not allowed in prolog.
+        ReferenceIllegalInProlog = Reference is not allowed in prolog.
+# Trailing Misc
+        ContentIllegalInTrailingMisc=Content is not allowed in trailing section.
+        ReferenceIllegalInTrailingMisc=Reference is not allowed in trailing section.
+        
+# 2.9 Standalone Document Declaration
+        SDDeclInvalid = The standalone document declaration value must be \"yes\" or \"no\", not \"{0}\".
+# 2.12 Language Identification
+        XMLLangInvalid = The xml:lang attribute value \"{0}\" is an invalid language identifier.
+# 3. Logical Structures
+        ETagRequired = The element type \"{0}\" must be terminated by the matching end-tag \"</{0}>\".
+# 3.1 Start-Tags, End-Tags, and Empty-Element Tags
+        ElementUnterminated = Element type \"{0}\" must be followed by either attribute specifications, \">\" or \"/>\".
+        EqRequiredInAttribute = Attribute name \"{1}\" associated with an element type \"{0}\" must be followed by the '' = '' character.
+        OpenQuoteExpected = Open quote is expected for attribute \"{1}\" associated with an  element type  \"{0}\".
+        CloseQuoteExpected = Close quote is expected for attribute \"{1}\" associated with an element type \"{0}\".
+        AttributeNotUnique = Attribute \"{1}\" was already specified for element \"{0}\".
+        AttributeNSNotUnique = Attribute \"{1}\" bound to namespace \"{2}\" was already specified for element \"{0}\".
+        ETagUnterminated = The end-tag for element type \"{0}\" must end with a ''>'' delimiter.
+        MarkupNotRecognizedInContent = The content of elements must consist of well-formed character data or markup.
+        DoctypeIllegalInContent = A DOCTYPE is not allowed in content.
+# 4.1 Character and Entity References
+        ReferenceUnterminated = The reference must be terminated by a ';' delimiter.
+# 4.3.2 Well-Formed Parsed Entities
+        ReferenceNotInOneEntity = The reference must be entirely contained within the same parsed entity.
+        ElementEntityMismatch = The element \"{0}\" must start and end within the same entity.
+        MarkupEntityMismatch=XML document structures must start and end within the same entity.
+        
+# Messages common to Document and DTD
+# 2.2 Characters
+        InvalidCharInAttValue = An invalid XML character (Unicode: 0x{2}) was found in the value of attribute \"{1}\" and element is \"{0}\".
+        InvalidCharInComment = An invalid XML character (Unicode: 0x{0}) was found in the comment.
+        InvalidCharInPI = An invalid XML character (Unicode: 0x{0}) was found in the processing instruction.
+        InvalidCharInInternalSubset = An invalid XML character (Unicode: 0x{0}) was found in the internal subset of the DTD.
+        InvalidCharInTextDecl = An invalid XML character (Unicode: 0x{0}) was found in the text declaration.
+# 2.3 Common Syntactic Constructs
+        QuoteRequiredInAttValue = The value of attribute \"{1}\" must begin with either a single or double quote character.
+        LessthanInAttValue = The value of attribute \"{1}\" associated with an element type \"{0}\" must not contain the ''<'' character.
+        AttributeValueUnterminated = The value for attribute \"{1}\" must end with the matching quote character.
+# 2.5 Comments
+        InvalidCommentStart = Comment must start with \"<!--\".
+        DashDashInComment = The string \"--\" is not permitted within comments.
+        CommentUnterminated = The comment must end with \"-->\".
+        COMMENT_NOT_IN_ONE_ENTITY = The comment is not enclosed in the same entity.
+# 2.6 Processing Instructions
+        PITargetRequired = The processing instruction must begin with the name of the target.
+        SpaceRequiredInPI = White space is required between the processing instruction target and data.
+        PIUnterminated = The processing instruction must end with \"?>\".
+        ReservedPITarget = The processing instruction target matching \"[xX][mM][lL]\" is not allowed.
+        PI_NOT_IN_ONE_ENTITY = The processing instruction is not enclosed in the same entity.
+# 2.8 Prolog and Document Type Declaration
+        VersionInfoInvalid = Invalid version \"{0}\".
+        VersionNotSupported = XML version \"{0}\" is not supported, only XML 1.0 is supported.
+        VersionNotSupported11 = XML version \"{0}\" is not supported, only XML 1.0 and XML 1.1 are supported.
+# 4.1 Character and Entity References
+        DigitRequiredInCharRef = A decimal representation must immediately follow the \"&#\" in a character reference.
+        HexdigitRequiredInCharRef = A hexadecimal representation must immediately follow the \"&#x\" in a character reference.
+        SemicolonRequiredInCharRef = The character reference must end with the ';' delimiter.
+        InvalidCharRef = Character reference \"&#{0}\" is an invalid XML character.
+        NameRequiredInReference = The entity name must immediately follow the '&' in the entity reference.
+        SemicolonRequiredInReference = The reference to entity \"{0}\" must end with the '';'' delimiter.
+# 4.3.1 The Text Declaration
+        TextDeclMustBeFirst = The text declaration may only appear at the very beginning of the external parsed entity.
+        EqRequiredInTextDecl = The '' = '' character must follow \"{0}\" in the text declaration.
+        QuoteRequiredInTextDecl = The value following \"{0}\" in the text declaration must be a quoted string.
+        CloseQuoteMissingInTextDecl = closing quote in the value following \"{0}\" in the text declaration is missing.
+        SpaceRequiredBeforeVersionInTextDecl = White space is required before the version pseudo attribute in the text declaration.
+        SpaceRequiredBeforeEncodingInTextDecl = White space is required before the encoding pseudo attribute in the text declaration.
+        TextDeclUnterminated = The text declaration must end with \"?>\".
+        EncodingDeclRequired = The encoding declaration is required in the text declaration.
+        NoMorePseudoAttributes = No more pseudo attributes are allowed.
+        MorePseudoAttributes = More pseudo attributes are expected.
+        PseudoAttrNameExpected = A pseudo attribute name is expected. 
+# 4.3.2 Well-Formed Parsed Entities
+        CommentNotInOneEntity = The comment must be entirely contained within the same parsed entity.
+        PINotInOneEntity = The processing instruction must be entirely contained within the same parsed entity.
+# 4.3.3 Character Encoding in Entities
+        EncodingDeclInvalid = Invalid encoding name \"{0}\".
+        EncodingByteOrderUnsupported = Given byte order for encoding \"{0}\" is not supported.
+        InvalidByte = Invalid byte {0} of {1}-byte UTF-8 sequence.
+        ExpectedByte = Expected byte {0} of {1}-byte UTF-8 sequence.  
+        InvalidHighSurrogate = High surrogate bits in UTF-8 sequence must not exceed 0x10 but found 0x{0}.
+        OperationNotSupported = Operation \"{0}\" not supported by {1} reader.
+        InvalidASCII = Byte \"{0}\" is not a member of the (7-bit) ASCII character set.
+        CharConversionFailure = An entity determined to be in a certain encoding must not contain sequences illegal in that encoding.
+        
+# DTD Messages
+# 2.2 Characters
+        InvalidCharInEntityValue = An invalid XML character (Unicode: 0x{0}) was found in the literal entity value.
+        InvalidCharInExternalSubset = An invalid XML character (Unicode: 0x{0}) was found in the external subset of the DTD.
+        InvalidCharInIgnoreSect = An invalid XML character (Unicode: 0x{0}) was found in the excluded conditional section.
+        InvalidCharInPublicID = An invalid XML character (Unicode: 0x{0}) was found in the public identifier.
+        InvalidCharInSystemID = An invalid XML character (Unicode: 0x{0}) was found in the system identifier.
+# 2.3 Common Syntactic Constructs
+        SpaceRequiredAfterSYSTEM = White space is required after keyword SYSTEM in DOCTYPE decl.
+        QuoteRequiredInSystemID = The system identifier must begin with either a single or double quote character.
+        SystemIDUnterminated = The system identifier must end with the matching quote character.
+        SpaceRequiredAfterPUBLIC = White spaces are required after keyword PUBLIC in DOCTYPE decl.
+        QuoteRequiredInPublicID = The public identifier must begin with either a single or double quote character.
+        PublicIDUnterminated = The public identifier must end with the matching quote character.
+        PubidCharIllegal = The character (Unicode: 0x{0}) is not permitted in the public identifier.
+        SpaceRequiredBetweenPublicAndSystem = White spaces are required between publicId and systemId.
+# 2.8 Prolog and Document Type Declaration
+        MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = White space is required after \"<!DOCTYPE\" in the document type declaration.
+        MSG_ROOT_ELEMENT_TYPE_REQUIRED = The root element type must appear after \"<!DOCTYPE\" in the document type declaration.
+        DoctypedeclUnterminated = The document type declaration for root element type \"{0}\" must end with ''>''.
+        PEReferenceWithinMarkup = The parameter entity reference \"%{0};\" cannot occur within markup in the internal subset of the DTD.
+        MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = The markup declarations contained or pointed to by the document type declaration must be well-formed.
+# 2.10 White Space Handling
+        MSG_XML_SPACE_DECLARATION_ILLEGAL = The attribute declaration for \"xml:space\" must be given as an enumerated type whose only possible values are \"default\" and \"preserve\".
+# 3.2 Element Type Declarations
+        MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ELEMENTDECL = White space is required after \"<!ELEMENT\" in the element type declaration.
+        MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL = The element type is required in the element type declaration.
+        MSG_SPACE_REQUIRED_BEFORE_CONTENTSPEC_IN_ELEMENTDECL = White space is required after the element type \"{0}\" in the element type declaration.
+        MSG_CONTENTSPEC_REQUIRED_IN_ELEMENTDECL = The constraint is required after the element type \"{0}\" in the element type declaration.
+        ElementDeclUnterminated = The declaration for element type \"{0}\" must end with ''>''.
+# 3.2.1 Element Content
+        MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN = A ''('' character or an element type is required in the declaration of element type \"{0}\".
+        MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN = A '')'' is required in the declaration of element type \"{0}\".
+# 3.2.2 Mixed Content
+        MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT = An element type is required in the declaration of element type \"{0}\".
+        MSG_CLOSE_PAREN_REQUIRED_IN_MIXED = A '')'' is required in the declaration of element type \"{0}\".
+        MixedContentUnterminated = The mixed content model \"{0}\" must end with \")*\" when the types of child elements are constrained.
+# 3.3 Attribute-List Declarations
+        MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ATTLISTDECL = White space is required after \"<!ATTLIST\" in the attribute-list declaration.
+        MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL = The element type is required in the attribute-list declaration.
+        MSG_SPACE_REQUIRED_BEFORE_ATTRIBUTE_NAME_IN_ATTDEF = White space is required before the attribute name in the attribute-list declaration for element \"{0}\".
+        AttNameRequiredInAttDef = The attribute name must be specified in the attribute-list declaration for element \"{0}\".
+        MSG_SPACE_REQUIRED_BEFORE_ATTTYPE_IN_ATTDEF = White space is required before the attribute type in the declaration of attribute \"{1}\" for element \"{0}\".
+        AttTypeRequiredInAttDef = The attribute type is required in the declaration of attribute \"{1}\" for element \"{0}\".
+        MSG_SPACE_REQUIRED_BEFORE_DEFAULTDECL_IN_ATTDEF = White space is required before the attribute default in the declaration of attribute \"{1}\" for element \"{0}\".
+        MSG_DUPLICATE_ATTRIBUTE_DEFINITION = More than one attribute definition is provided for the same attribute \"{1}\" of a given element \"{0}\".
+# 3.3.1 Attribute Types
+        MSG_SPACE_REQUIRED_AFTER_NOTATION_IN_NOTATIONTYPE = White space must appear after \"NOTATION\" in the \"{1}\" attribute declaration.
+        MSG_OPEN_PAREN_REQUIRED_IN_NOTATIONTYPE = The ''('' character must follow \"NOTATION\" in the \"{1}\" attribute declaration.
+        MSG_NAME_REQUIRED_IN_NOTATIONTYPE = The notation name is required in the notation type list for the \"{1}\" attribute declaration.
+        NotationTypeUnterminated = The notation type list must end with '')'' in the \"{1}\" attribute declaration.
+        MSG_NMTOKEN_REQUIRED_IN_ENUMERATION = The name token is required in the enumerated type list for the \"{1}\" attribute declaration.
+        EnumerationUnterminated = The enumerated type list must end with '')'' in the \"{1}\" attribute declaration.
+        MSG_DISTINCT_TOKENS_IN_ENUMERATION = The enumeration value \"{1}\" was specified more than once in the declaration of attribute \"{2}\" for element \"{0}\". The NMTOKENS in a single Enumeration attribute declaration must all be distinct.
+        MSG_DISTINCT_NOTATION_IN_ENUMERATION = The enumeration value \"{1}\" was specified more than once in the declaration of attribute \"{2}\" for element \"{0}\". The NOTATION names in a single NotationType attribute declaration must all be distinct.
+# 3.3.2 Attribute Defaults
+        MSG_SPACE_REQUIRED_AFTER_FIXED_IN_DEFAULTDECL = White space must appear after \"FIXED\" in the \"{1}\" attribute declaration.
+# 3.4 Conditional Sections
+        IncludeSectUnterminated = The included conditional section must end with \"]]>\".
+        IgnoreSectUnterminated = The excluded conditional section must end with \"]]>\".
+# 4.1 Character and Entity References
+        NameRequiredInPEReference = The entity name must immediately follow the '%' in the parameter entity reference.
+        SemicolonRequiredInPEReference = The parameter entity reference \"%{0};\" must end with the '';'' delimiter.
+# 4.2 Entity Declarations
+        MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL = White space is required after \"<!ENTITY\" in the entity declaration.
+        MSG_SPACE_REQUIRED_BEFORE_PERCENT_IN_PEDECL = White space is required between \"<!ENTITY\" and the '%' character in the parameter entity declaration.
+        MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_PEDECL = White space is required between the '%' and the entity name in the parameter entity declaration.
+        MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL = The name of the entity is required in the entity declaration.
+        MSG_SPACE_REQUIRED_AFTER_ENTITY_NAME_IN_ENTITYDECL = White space is required between the entity name \"{0}\" and the definition in the entity declaration.
+        MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL = White space is required between \"NDATA\" and the notation name in the declaration for the entity \"{0}\".
+        MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = White space is required before \"NDATA\" in the declaration for the entity \"{0}\".
+        MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = The notation name is required after \"NDATA\" in the declaration for the entity \"{0}\".
+        EntityDeclUnterminated = The declaration for the entity \"{0}\" must end with ''>''.
+        MSG_DUPLICATE_ENTITY_DEFINITION = Entity \"{0}\" is declared more than once.        
+# 4.2.2 External Entities
+        ExternalIDRequired = The external entity declaration must begin with either \"SYSTEM\" or \"PUBLIC\".
+        MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = White space is required between \"PUBLIC\" and the public identifier.
+        MSG_SPACE_REQUIRED_AFTER_PUBIDLITERAL_IN_EXTERNALID = White space is required between the public identifier and the system identifier.
+        MSG_SPACE_REQUIRED_BEFORE_SYSTEMLITERAL_IN_EXTERNALID = White space is required between \"SYSTEM\" and the system identifier.
+        MSG_URI_FRAGMENT_IN_SYSTEMID = The fragment identifier should not be specified as part of the system identifier \"{0}\".
+# 4.7 Notation Declarations
+        MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_NOTATIONDECL = White space is required after \"<!NOTATION\" in the notation declaration.
+        MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL = The name of the notation is required in the notation declaration.
+        MSG_SPACE_REQUIRED_AFTER_NOTATION_NAME_IN_NOTATIONDECL = White space is required after the notation name \"{0}\" in the notation declaration.
+        ExternalIDorPublicIDRequired = The declaration for the notation \"{0}\" must include a system or public identifier.
+        NotationDeclUnterminated = The declaration for the notation \"{0}\" must end with ''>''.
+        
+# Validation messages
+        DuplicateTypeInMixedContent = The element type \"{1}\" was already specified in the content model of the element decl \"{0}\".
+        ENTITIESInvalid = Attribute value \"{1}\" of type ENTITIES must be the names of one or more unparsed entities.
+        ENTITYInvalid = Attribute value \"{1}\" of type ENTITY must be the name of an unparsed entity.
+        IDDefaultTypeInvalid = The ID attribute \"{0}\" must have a declared default of \"#IMPLIED\" or \"#REQUIRED\".
+        IDInvalid = Attribute value \"{0}\" of type ID must be a name.
+        IDInvalidWithNamespaces = Attribute value \"{0}\" of type ID must be an NCName when namespaces are enabled.
+        IDNotUnique = Attribute value \"{0}\" of type ID must be unique within the document.
+        IDREFInvalid = Attribute value \"{0}\" of type IDREF must be a name.
+        IDREFInvalidWithNamespaces = Attribute value \"{0}\" of type IDREF must be an NCName when namespaces are enabled.
+        IDREFSInvalid = Attribute value \"{0}\" of type IDREFS must be one or more names.
+        ILL_FORMED_PARAMETER_ENTITY_WHEN_USED_IN_DECL = The replacement text of parameter entity \"{0}\" must include properly nested declarations when the entity reference is used as a complete declaration.
+        ImproperDeclarationNesting = The replacement text of parameter entity \"{0}\" must include properly nested declarations.
+        ImproperGroupNesting = The replacement text of parameter entity \"{0}\" must include properly nested pairs of parentheses.
+        INVALID_PE_IN_CONDITIONAL = The replacement text of parameter entity \"{0}\" must include the entire conditional section or just INCLUDE or IGNORE.
+        MSG_ATTRIBUTE_NOT_DECLARED = Attribute \"{1}\" must be declared for element type \"{0}\".
+        MSG_ATTRIBUTE_VALUE_NOT_IN_LIST = Attribute \"{0}\" with value \"{1}\" must have a value from the list \"{2}\".
+        MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE = The value \"{1}\" of attribute \"{0}\" must not be changed by normalization (to \"{2}\") in a standalone document.
+        MSG_CONTENT_INCOMPLETE = The content of element type \"{0}\" is incomplete, it must match \"{1}\".
+        MSG_CONTENT_INVALID = The content of element type \"{0}\" must match \"{1}\".
+        MSG_CONTENT_INVALID_SPECIFIED = The content of element type \"{0}\" must match \"{1}\".  Children of type \"{2}\" are not allowed.
+        MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED = Attribute \"{1}\" for element type \"{0}\" has a default value and must be specified in a standalone document.
+        MSG_DUPLICATE_ATTDEF = Attribute \"{1}\" is already declared for element type \"{0}\".
+        MSG_ELEMENT_ALREADY_DECLARED = Element type \"{0}\" must not be declared more than once.
+        MSG_ELEMENT_NOT_DECLARED = Element type \"{0}\" must be declared.
+        MSG_GRAMMAR_NOT_FOUND = Document is invalid: no grammar found.
+        MSG_ELEMENT_WITH_ID_REQUIRED = An element with the identifier \"{0}\" must appear in the document.
+        MSG_EXTERNAL_ENTITY_NOT_PERMITTED = The reference to external entity \"{0}\" is not permitted in a standalone document.
+        MSG_FIXED_ATTVALUE_INVALID = Attribute \"{1}\" with value \"{2}\" must have a value of \"{3}\".
+        MSG_MORE_THAN_ONE_ID_ATTRIBUTE = Element type \"{0}\" already has attribute \"{1}\" of type ID, a second attribute \"{2}\" of type ID is not permitted.
+        MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE = Element type \"{0}\" already has attribute \"{1}\" of type NOTATION, a second attribute \"{2}\" of type NOTATION is not permitted.
+        MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE = The notation \"{1}\" must be declared when referenced in the notation type list for attribute \"{0}\".
+        MSG_NOTATION_NOT_DECLARED_FOR_UNPARSED_ENTITYDECL = The notation \"{1}\" must be declared when referenced in the unparsed entity declaration for \"{0}\".
+        MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE = The reference to entity \"{0}\" declared in the external subset of the DTD or in a parameter entity is not permitted in a standalone document.
+        MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED = Attribute \"{1}\" is required and must be specified for element type \"{0}\".
+        MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE = In a standalone document white space must not occur between elements with element content which are declared in the external subset of the DTD or in a parameter entity.
+        NMTOKENInvalid = Attribute value \"{0}\" of type NMTOKEN must be a name token.
+        NMTOKENSInvalid = Attribute value \"{0}\" of type NMTOKENS must be one or more name tokens.
+        NoNotationOnEmptyElement = Element type \"{0}\" which was declared EMPTY cannot declare attribute \"{1}\" of type NOTATION.
+        RootElementTypeMustMatchDoctypedecl = Document root element \"{1}\", must match DOCTYPE root \"{0}\".
+        UndeclaredElementInContentSpec = The content model of element \"{0}\" refers to the undeclared element \"{1}\".
+        UniqueNotationName = The declaration for the notation \"{0}\" is not unique. A given Name must not be declared in more than one notation declaration.
+        ENTITYFailedInitializeGrammar =  ENTITYDatatype Validator: Failed Need to call initialize method with a valid Grammar reference. 	
+        ENTITYNotUnparsed = ENTITY \"{0}\" is not unparsed.
+        ENTITYNotValid = ENTITY \"{0}\" is not valid.
+        EmptyList = Value of type ENTITIES, IDREFS, and NMTOKENS cannot be empty list.
+
+# Entity related messages
+# 3.1 Start-Tags, End-Tags, and Empty-Element Tags
+        ReferenceToExternalEntity = The external entity reference \"&{0};\" is not permitted in an attribute value.
+# 4.1 Character and Entity References
+        EntityNotDeclared = The entity \"{0}\" was referenced, but not declared.
+        ReferenceToUnparsedEntity = The unparsed entity reference \"&{0};\" is not permitted.
+        RecursiveReference = Recursive entity reference \"{0}\". (Reference path: {1}),
+        RecursiveGeneralReference = Recursive general entity reference \"&{0};\". (Reference path: {1}),
+        RecursivePEReference = Recursive parameter entity reference \"%{0};\". (Reference path: {1}),
+# 4.3.3 Character Encoding in Entities
+        EncodingNotSupported = The encoding \"{0}\" is not supported.
+        EncodingRequired = A parsed entity not encoded in either UTF-8 or UTF-16 must contain an encoding declaration.
+        
+# Namespaces support
+# 4. Using Qualified Names
+        IllegalQName = Element or attribute do not match QName production: QName::=(NCName':')?NCName. 
+        ElementXMLNSPrefix = Element \"{0}\" cannot have \"xmlns\" as its prefix.
+        ElementPrefixUnbound = The prefix \"{0}\" for element \"{1}\" is not bound.
+        AttributePrefixUnbound = The prefix \"{2}\" for attribute \"{1}\" associated with an element type \"{0}\" is not bound.
+        EmptyPrefixedAttName = The value of the attribute \"{0}\" is invalid. Prefixed namespace bindings may not be empty.
+        PrefixDeclared = The namespace prefix \"{0}\" was not declared.
+        CantBindXMLNS = The prefix "xmlns" cannot be bound to any namespace explicitly; neither can the namespace for "xmlns" be bound to any prefix explicitly.
+        CantBindXML = The prefix "xml" cannot be bound to any namespace other than its usual namespace; neither can the namespace for "xml" be bound to any prefix other than "xml".
+        MSG_ATT_DEFAULT_INVALID = The defaultValue \"{1}\" of attribute \"{0}\" is not legal as for the lexical constraints of this attribute type.
+
+# REVISIT: These need messages
+        MSG_SPACE_REQUIRED_AFTER_SYSTEMLITERAL_IN_EXTERNALID=MSG_SPACE_REQUIRED_AFTER_SYSTEMLITERAL_IN_EXTERNALID
+        OpenQuoteMissingInDecl=OpenQuoteMissingInDecl
+        InvalidCharInLiteral=InvalidCharInLiteral
+
+
+#Application can set the limit of number of entities that should be expanded by the parser.
+EntityExpansionLimitExceeded=The parser has encountered more than \"{0}\" entity expansions in this document; this is the limit imposed by the application.
+
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XMLSchemaMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XMLSchemaMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cd8765da056a52ba84301800ba5c031d3797c239
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XMLSchemaMessages.properties
@@ -0,0 +1,320 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file contains error and warning messages related to XML Schema
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: XMLSchemaMessages.properties 806363 2009-08-20 21:18:48Z mrglavas $
+
+        BadMessageKey = The error message corresponding to the message key can not be found.
+        FormatFailed = An internal error occurred while formatting the following message:\n
+
+# For internal use
+
+        Internal-Error = Internal error: {0}.
+        dt-whitespace = Whitespace facet value is not available for the union simpleType ''{0}''
+        GrammarConflict = One of the grammar(s) returned from the user's grammar pool is in conflict with another grammar.
+
+# Identity constraints
+
+        AbsentKeyValue = cvc-identity-constraint.4.2.1.a: Element \"{0}\" has no value for the key \"{1}\".
+        DuplicateField = Duplicate match in scope for field \"{0}\".
+        DuplicateKey = cvc-identity-constraint.4.2.2: Duplicate key value [{0}] declared for identity constraint \"{2}\" of element \"{1}\".
+        DuplicateUnique = cvc-identity-constraint.4.1: Duplicate unique value [{0}] declared for identity constraint \"{2}\" of element \"{1}\".
+        FieldMultipleMatch = cvc-identity-constraint.3: Field \"{0}\" of identity constraint \"{1}\" matches more than one value within the scope of its selector; fields must match unique values.
+        FixedDiffersFromActual = The content of this element is not equivalent to the value of the \"fixed\" attribute in the element's declaration in the schema.
+        KeyMatchesNillable = cvc-identity-constraint.4.2.3: Element \"{0}\" has the key \"{1}\" which matches an element which has nillable set to true.
+        KeyNotEnoughValues = cvc-identity-constraint.4.2.1.b: Not enough values specified for <key name=\"{1}\"> identity constraint specified for element \"{0}\".
+        KeyNotFound = cvc-identity-constraint.4.3: Key ''{0}'' with value ''{1}'' not found for identity constraint of element ''{2}''.
+        KeyRefOutOfScope = Identity Constraint error:  identity constraint \"{0}\" has a keyref which refers to a key or unique that is out of scope.
+        KeyRefReferNotFound = Key reference declaration \"{0}\" refers to unknown key with name \"{1}\".
+        UnknownField = Internal identity constraint error; unknown field \"{0}\" for identity constraint \"{2}\" specified for element \"{1}\".
+
+# Ideally, we should only use the following error keys, not the ones under
+# "Identity constraints". And we should cover all of the following errors.
+
+#validation (3.X.4)
+
+        cvc-attribute.3 = cvc-attribute.3: The value ''{2}'' of attribute ''{1}'' on element ''{0}'' is not valid with respect to its type, ''{3}''.
+        cvc-attribute.4 = cvc-attribute.4: The value ''{2}'' of attribute ''{1}'' on element ''{0}'' is not valid with respect to its fixed '{'value constraint'}'. The attribute must have a value of ''{3}''.
+        cvc-complex-type.2.1 = cvc-complex-type.2.1: Element ''{0}'' must have no character or element information item [children], because the type''s content type is empty.
+        cvc-complex-type.2.2 = cvc-complex-type.2.2: Element ''{0}'' must have no element [children], and the value must be valid.
+        cvc-complex-type.2.3 = cvc-complex-type.2.3: Element ''{0}'' cannot have character [children], because the type''s content type is element-only.
+        cvc-complex-type.2.4.a = cvc-complex-type.2.4.a: Invalid content was found starting with element ''{0}''. One of ''{1}'' is expected.
+        cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: The content of element ''{0}'' is not complete. One of ''{1}'' is expected.
+        cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ''{0}''.
+        cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: Invalid content was found starting with element ''{0}''. No child element is expected at this point.
+        cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}'' can occur a maximum of ''{2}'' times in the current sequence. This limit was exceeded. At this point one of ''{1}'' is expected.
+        cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}'' can occur a maximum of ''{1}'' times in the current sequence. This limit was exceeded. No child element is expected at this point.
+        cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: Invalid content was found starting with element ''{0}''. ''{1}'' is expected to occur a minimum of ''{2}'' times in the current sequence. One more instance is required to satisfy this constraint.
+        cvc-complex-type.2.4.h = cvc-complex-type.2.4.h: Invalid content was found starting with element ''{0}''. ''{1}'' is expected to occur a minimum of ''{2}'' times in the current sequence. ''{3}'' more instances are required to satisfy this constraint.
+        cvc-complex-type.2.4.i = cvc-complex-type.2.4.i: The content of element ''{0}'' is not complete. ''{1}'' is expected to occur a minimum of ''{2}'' times. One more instance is required to satisfy this constraint.
+        cvc-complex-type.2.4.j = cvc-complex-type.2.4.j: The content of element ''{0}'' is not complete. ''{1}'' is expected to occur a minimum of ''{2}'' times. ''{3}'' more instances are required to satisfy this constraint.
+        cvc-complex-type.3.1 = cvc-complex-type.3.1: Value ''{2}'' of attribute ''{1}'' of element ''{0}'' is not valid with respect to the corresponding attribute use. Attribute ''{1}'' has a fixed value of ''{3}''.
+        cvc-complex-type.3.2.1 = cvc-complex-type.3.2.1: Element ''{0}'' does not have an attribute wildcard for attribute ''{1}''.
+        cvc-complex-type.3.2.2 = cvc-complex-type.3.2.2: Attribute ''{1}'' is not allowed to appear in element ''{0}''.
+        cvc-complex-type.4 = cvc-complex-type.4: Attribute ''{1}'' must appear on element ''{0}''.
+        cvc-complex-type.5.1 = cvc-complex-type.5.1: In element ''{0}'', attribute ''{1}'' is a Wild ID. But there is already a Wild ID ''{2}''. There can be only one.
+        cvc-complex-type.5.2 = cvc-complex-type.5.2: In element ''{0}'', attribute ''{1}'' is a Wild ID. But there is already an attribute ''{2}'' derived from ID among the '{'attribute uses'}'.
+        cvc-datatype-valid.1.2.1 = cvc-datatype-valid.1.2.1: ''{0}'' is not a valid value for ''{1}''.
+        cvc-datatype-valid.1.2.2 = cvc-datatype-valid.1.2.2: ''{0}'' is not a valid value of list type ''{1}''.
+        cvc-datatype-valid.1.2.3 = cvc-datatype-valid.1.2.3: ''{0}'' is not a valid value of union type ''{1}''.
+        cvc-elt.1.a = cvc-elt.1.a: Cannot find the declaration of element ''{0}''.
+        cvc-elt.1.b = cvc-elt.1.b: The name of the element does not match the name of the element declaration. Saw ''{0}''. Expected ''{1}''.
+        cvc-elt.2 = cvc-elt.2: The value of '{'abstract'}' in the element declaration for ''{0}'' must be false.
+        cvc-elt.3.1 = cvc-elt.3.1: Attribute ''{1}'' must not appear on element ''{0}'', because the '{'nillable'}' property of ''{0}'' is false.
+        cvc-elt.3.2.1 = cvc-elt.3.2.1: Element ''{0}'' cannot have character or element information [children], because ''{1}'' is specified.
+        cvc-elt.3.2.2 = cvc-elt.3.2.2: There must be no fixed '{'value constraint'}' for element ''{0}'', because ''{1}'' is specified.
+        cvc-elt.4.1 = cvc-elt.4.1: The value ''{2}'' of attribute ''{1}'' of element ''{0}'' is not a valid QName.
+        cvc-elt.4.2 = cvc-elt.4.2: Cannot resolve ''{1}'' to a type definition for element ''{0}''.
+        cvc-elt.4.3 = cvc-elt.4.3: Type ''{1}'' is not validly derived from the type definition, ''{2}'', of element ''{0}''.
+        cvc-elt.5.1.1 = cvc-elt.5.1.1: '{'value constraint'}' ''{2}'' of element ''{0}'' is not a valid default value for type ''{1}''.
+        cvc-elt.5.2.2.1 = cvc-elt.5.2.2.1: Element ''{0}'' must have no element information item [children].
+        cvc-elt.5.2.2.2.1 = cvc-elt.5.2.2.2.1: The value ''{1}'' of element ''{0}'' does not match the fixed '{'value constraint'}' value ''{2}''.
+        cvc-elt.5.2.2.2.2 = cvc-elt.5.2.2.2.2: The value ''{1}'' of element ''{0}'' does not match the '{'value constraint'}' value ''{2}''.
+        cvc-enumeration-valid = cvc-enumeration-valid: Value ''{0}'' is not facet-valid with respect to enumeration ''{1}''. It must be a value from the enumeration.
+        cvc-fractionDigits-valid = cvc-fractionDigits-valid: Value ''{0}'' has {1} fraction digits, but the number of fraction digits has been limited to {2}.
+        cvc-id.1 = cvc-id.1: There is no ID/IDREF binding for IDREF ''{0}''.
+        cvc-id.2 = cvc-id.2: There are multiple occurrences of ID value ''{0}''.
+        cvc-id.3 = cvc-id.3: A field of identity constraint ''{0}'' matched element ''{1}'', but this element does not have a simple type.
+        cvc-length-valid = cvc-length-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to length ''{2}'' for type ''{3}''.
+        cvc-maxExclusive-valid = cvc-maxExclusive-valid: Value ''{0}'' is not facet-valid with respect to maxExclusive ''{1}'' for type ''{2}''.
+        cvc-maxInclusive-valid = cvc-maxInclusive-valid: Value ''{0}'' is not facet-valid with respect to maxInclusive ''{1}'' for type ''{2}''.
+        cvc-maxLength-valid = cvc-maxLength-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to maxLength ''{2}'' for type ''{3}''.
+        cvc-minExclusive-valid = cvc-minExclusive-valid: Value ''{0}'' is not facet-valid with respect to minExclusive ''{1}'' for type ''{2}''.
+        cvc-minInclusive-valid = cvc-minInclusive-valid: Value ''{0}'' is not facet-valid with respect to minInclusive ''{1}'' for type ''{2}''.
+        cvc-minLength-valid = cvc-minLength-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to minLength ''{2}'' for type ''{3}''.
+        cvc-pattern-valid = cvc-pattern-valid: Value ''{0}'' is not facet-valid with respect to pattern ''{1}'' for type ''{2}''.
+        cvc-totalDigits-valid = cvc-totalDigits-valid: Value ''{0}'' has {1} total digits, but the number of total digits has been limited to {2}.
+        cvc-type.1 = cvc-type.1: The type definition ''{0}'' was not found.
+        cvc-type.2 = cvc-type.2: The type definition cannot be abstract for element {0}.
+        cvc-type.3.1.1 = cvc-type.3.1.1: Element ''{0}'' is a simple type, so it cannot have attributes, excepting those whose namespace name is identical to ''http://www.w3.org/2001/XMLSchema-instance'' and whose [local name] is one of ''type'', ''nil'', ''schemaLocation'' or ''noNamespaceSchemaLocation''. However, the attribute, ''{1}'' was found.
+        cvc-type.3.1.2 = cvc-type.3.1.2: Element ''{0}'' is a simple type, so it must have no element information item [children].
+        cvc-type.3.1.3 = cvc-type.3.1.3: The value ''{1}'' of element ''{0}'' is not valid.
+
+#schema valid (3.X.3)
+
+        schema_reference.4 = schema_reference.4: Failed to read schema document ''{0}'', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
+        src-annotation = src-annotation: <annotation> elements can only contain <appinfo> and <documentation> elements, but ''{0}'' was found.
+        src-attribute.1 = src-attribute.1: The properties ''default'' and ''fixed'' cannot both be present in attribute declaration ''{0}''. Use only one of them.
+        src-attribute.2 = src-attribute.2: : The property ''default'' is present in attribute ''{0}'', so the value of ''use'' must be ''optional''.
+        src-attribute.3.1 = src-attribute.3.1: One of 'ref' or 'name' must be present in a local attribute declaration.
+        src-attribute.3.2 = src-attribute.3.2: The content must match (annotation?) for the attribute reference ''{0}''.
+        src-attribute.4 = src-attribute.4: Attribute ''{0}'' has both a ''type'' attribute and an anonymous ''simpleType'' child. Only one of these is allowed for an attribute.
+        src-attribute_group.2 = src-attribute_group.2: The intersection of wildcards is not expressible for attribute group ''{0}''.
+        src-attribute_group.3 = src-attribute_group.3: Circular definitions detected for attribute group ''{0}''. Recursively following attribute group references eventually leads back to itself.
+        src-ct.1 = src-ct.1: Complex Type Definition Representation Error for type ''{0}''.  When <complexContent> is used, the base type must be a complexType. ''{1}'' is a simpleType.
+        src-ct.2.1 = src-ct.2.1: Complex Type Definition Representation Error for type ''{0}''.  When <simpleContent> is used, the base type must be a complexType whose content type is simple, or, only if restriction is specified, a complex type with mixed content and emptiable particle, or, only if extension is specified, a simple type. ''{1}'' satisfies none of these conditions.
+        src-ct.2.2 = src-ct.2.2: Complex Type Definition Representation Error for type ''{0}''.  When a complexType with simpleContent restricts a complexType with mixed content and emptiable particle, then there must be a <simpleType> among the children of <restriction>.
+        src-ct.4 = src-ct.4: Complex Type Definition Representation Error for type ''{0}''. The intersection of wildcards is not expressible.
+        src-ct.5 = src-ct.5: Complex Type Definition Representation Error for type ''{0}''. The union of wildcards is not expressible.
+        src-element.1 = src-element.1: The properties ''default'' and ''fixed'' cannot both be present in element declaration ''{0}''. Use only one of them.
+        src-element.2.1 = src-element.2.1: : One of 'ref' or 'name' must be present in a local element declaration.
+        src-element.2.2 = src-element.2.2: Since ''{0}'' contains the ''ref'' attribute, its content must match (annotation?). However, ''{1}'' was found.
+        src-element.3 = src-element.3: Element ''{0}'' has both a ''type'' attribute and a ''anonymous type'' child. Only one of these is allowed for an element.
+        src-import.1.1 = src-import.1.1: The namespace attribute ''{0}'' of an <import> element information item must not be the same as the targetNamespace of the schema it exists in.
+        src-import.1.2 = src-import.1.2: If the namespace attribute is not present on an <import> element information item then the enclosing schema must have a targetNamespace.
+        src-import.2 = src-import.2: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+        src-import.3.1 = src-import.3.1: The namespace attribute, ''{0}'', of an <import> element information item must be identical to the targetNamespace attribute, ''{1}'', of the imported document.
+        src-import.3.2 = src-import.3.2: An <import> element information item that had no namespace attribute was found, so the imported document cannot have a targetNamespace attribute. However, the targetNamespace ''{1}'' was found in the imported document.
+        src-include.1 = src-include.1: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+        src-include.2.1 = src-include.2.1: The targetNamespace of the referenced schema, currently ''{1}'', must be identical to that of the including schema, currently ''{0}''.
+        src-redefine.2 = src-redefine.2: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+        src-redefine.3.1 = src-redefine.3.1: The targetNamespace of the referenced schema, currently ''{1}'', must be identical to that of the redefining schema, currently ''{0}''.
+        src-redefine.5.a.a = src-redefine.5.a.a: No non-annotation children of <simpleType> were found. <simpleType> children of <redefine> elements must have <restriction> descendants, with 'base' attributes that refer to themselves.
+        src-redefine.5.a.b = src-redefine.5.a.b: ''{0}'' is not a valid child element. <simpleType> children of <redefine> elements must have <restriction> descendants, with ''base'' attributes that refer to themselves.
+        src-redefine.5.a.c = src-redefine.5.a.c: ''{0}'' does not have a ''base'' attribute that refers to the redefined element, ''{1}''. <simpleType> children of <redefine> elements must have <restriction> descendants, with ''base'' attributes that refer to themselves.
+        src-redefine.5.b.a = src-redefine.5.b.a: No non-annotation children of <complexType> were found. <complexType> children of <redefine> elements must have <extension> or <restriction> descendants, with 'base' attributes that refer to themselves.
+        src-redefine.5.b.b = src-redefine.5.b.b: No non-annotation grandchildren of <complexType> were found. <complexType> children of <redefine> elements must have <extension> or <restriction> descendants, with 'base' attributes that refer to themselves.
+        src-redefine.5.b.c = src-redefine.5.b.c: ''{0}'' is not a valid grandchild element. <complexType> children of <redefine> elements must have <extension> or <restriction> descendants, with ''base'' attributes that refer to themselves.
+        src-redefine.5.b.d = src-redefine.5.b.d: ''{0}'' does not have a ''base'' attribute that refers to the redefined element, ''{1}''. <complexType> children of <redefine> elements must have <extension> or <restriction> descendants, with ''base'' attributes that refer to themselves.
+        src-redefine.6.1.1 = src-redefine.6.1.1:  If a group child of a <redefine> element contains a group referring itself, it must have exactly 1; this one has ''{0}''.
+        src-redefine.6.1.2 = src-redefine.6.1.2:  The group ''{0}'', which contains a reference to a group being redefined, must have ''minOccurs'' = ''maxOccurs'' = 1.
+        src-redefine.6.2.1 = src-redefine.6.2.1: No group in the redefined schema has a name matching ''{0}''.
+        src-redefine.6.2.2 = src-redefine.6.2.2: Group ''{0}'' does not properly restrict the group it redefines; constraint violated:  ''{1}''.
+        src-redefine.7.1 = src-redefine.7.1:  If an attributeGroup child of a <redefine> element contains an attributeGroup referring itself, it must have exactly 1; this one has {0}.
+        src-redefine.7.2.1 = src-redefine.7.2.1: No attributeGroup in the redefined schema has a name matching ''{0}''.
+        src-redefine.7.2.2 = src-redefine.7.2.2: AttributeGroup ''{0}'' does not properly restrict the attributeGroup it redefines; constraint violated:  ''{1}''.
+        src-resolve = src-resolve: Cannot resolve the name ''{0}'' to a(n) ''{1}'' component.
+        src-resolve.4.1 = src-resolve.4.1: Error resolving component ''{2}''. It was detected that ''{2}'' has no namespace, but components with no target namespace are not referenceable from schema document ''{0}''. If ''{2}'' is intended to have a namespace, perhaps a prefix needs to be provided. If it is intended that ''{2}'' has no namespace, then an ''import'' without a "namespace" attribute should be added to ''{0}''.
+        src-resolve.4.2 = src-resolve.4.2: Error resolving component ''{2}''. It was detected that ''{2}'' is in namespace ''{1}'', but components from this namespace are not referenceable from schema document ''{0}''. If this is the incorrect namespace, perhaps the prefix of ''{2}'' needs to be changed. If this is the correct namespace, then an appropriate ''import'' tag should be added to ''{0}''.
+        src-simple-type.2.a = src-simple-type.2.a: A <restriction> element was found that has both a base [attribute] and a <simpleType> element among its [children]. Only one is allowed.
+        src-simple-type.2.b = src-simple-type.2.b: A <restriction> element was found that has neither a base [attribute] nor a <simpleType> element among its [children]. One is required.
+        src-simple-type.3.a = src-simple-type.3.a: A <list> element was found that has both an itemType [attribute] and a <simpleType> element among its [children]. Only one is allowed.
+        src-simple-type.3.b = src-simple-type.3.b: A <list> element was found that has neither an itemType [attribute] nor a <simpleType> element among its [children]. One is required.
+        src-single-facet-value = src-single-facet-value: The facet ''{0}'' is defined more than once.
+        src-union-memberTypes-or-simpleTypes = src-union-memberTypes-or-simpleTypes: A <union> element must have either a non-empty memberTypes [attribute] or at least one <simpleType> element among its [children].
+
+#constraint valid (3.X.6)
+
+        ag-props-correct.2 = ag-props-correct.2: Error for attribute group ''{0}''.  Duplicate attribute uses with the same name and target namespace are specified.  Name of duplicate attribute use is ''{1}''.
+        ag-props-correct.3 = ag-props-correct.3: Error for attribute group ''{0}''.  Two attribute declarations, ''{1}'' and ''{2}'' have types which are derived from ID.
+        a-props-correct.2 = a-props-correct.2: Invalid value constraint value ''{1}'' in attribute ''{0}''.
+        a-props-correct.3 = a-props-correct.3: Attribute ''{0}'' cannot use ''fixed'' or ''default'', because the attribute''s '{'type definition'}' is ID, or is derived from ID.
+        au-props-correct.2 = au-props-correct.2: In the attribute declaration of ''{0}'', a fixed value of ''{1}'' was specified. So if the attribute use referring to ''{0}'' also has a '{'value constraint'}', it must be fixed and its value must be ''{1}''.
+        cos-all-limited.1.2 = cos-all-limited.1.2: An 'all' model group must appear in a particle with '{'min occurs'}' = '{'max occurs'}' = 1, and that particle must be part of a pair which constitutes the '{'content type'}' of a complex type definition.
+        cos-all-limited.2 = cos-all-limited.2: The '{'max occurs'}' of an element in an ''all'' model group must be 0 or 1. The value ''{0}'' for element ''{1}'' is invalid.
+        cos-applicable-facets = cos-applicable-facets: Facet ''{0}'' is not allowed by type {1}.
+        cos-ct-extends.1.1 = cos-ct-extends.1.1: Type ''{0}'' was derived by extension from type ''{1}''.  However, the ''final'' attribute of ''{1}'' forbids derivation by extension.
+        cos-ct-extends.1.4.3.2.2.1.a = cos-ct-extends.1.4.3.2.2.1.a: The content type of a derived type and that of its base must both be mixed or both be element-only. Type ''{0}'' is element only, but its base type is not.
+        cos-ct-extends.1.4.3.2.2.1.b = cos-ct-extends.1.4.3.2.2.1.b: The content type of a derived type and that of its base must both be mixed or both be element-only. Type ''{0}'' is mixed, but its base type is not.
+        cos-element-consistent = cos-element-consistent: Error for type ''{0}''. Multiple elements with name ''{1}'', with different types, appear in the model group.
+        cos-list-of-atomic = cos-list-of-atomic: In the definition of list type ''{0}'', type ''{1}'' is an invalid list element type because it is not atomic (''{1}'' is either a list type, or a union type which contains a list).
+        cos-nonambig = cos-nonambig: {0} and {1} (or elements from their substitution group) violate \"Unique Particle Attribution\". During validation against this schema, ambiguity would be created for those two particles.
+        cos-particle-restrict.a = cos-particle-restrict.a: Derived particle is empty, and base is not emptiable.
+        cos-particle-restrict.b = cos-particle-restrict.b: Base particle is empty, but derived particle is not.
+        cos-particle-restrict.2 = cos-particle-restrict.2: Forbidden particle restriction: ''{0}''.
+        cos-st-restricts.1.1 = cos-st-restricts.1.1: The type ''{1}'' is atomic, so its '{'base type definition'}', ''{0}'', must be an atomic simple type definition or a built-in primitive datatype.
+        cos-st-restricts.2.1 = cos-st-restricts.2.1: In the definition of list type ''{0}'', type ''{1}'' is an invalid item type because it is either a list type, or a union type that contains a list.
+        cos-st-restricts.2.3.1.1 = cos-st-restricts.2.3.1.1: The '{'final'}' component of the '{'item type definition'}', ''{0}'', contains ''list''. This means that ''{0}'' cannot be used as an item type for list type ''{1}''.
+        cos-st-restricts.3.3.1.1 = cos-st-restricts.3.3.1.1: The '{'final'}' component of the '{'member type definitions'}', ''{0}'', contains ''union''. This means that ''{0}'' cannot be used as an member type for union type ''{1}''.
+        cos-valid-default.2.1 = cos-valid-default.2.1: Element ''{0}'' has a value constraint and must have a mixed or simple content model.
+        cos-valid-default.2.2.2 = cos-valid-default.2.2.2: Since element ''{0}'' has a '{'value constraint'}' and its type definition has mixed '{'content type'}', then the particle of the '{'content type'}' must be emptiable.
+        c-props-correct.2 = c-props-correct.2: Cardinality of Fields for keyref ''{0}'' and key ''{1}'' must match each other.
+        ct-props-correct.3 = ct-props-correct.3: Circular definitions detected for complex type ''{0}''. This means that ''{0}'' is contained in its own type hierarchy, which is an error.
+        ct-props-correct.4 = ct-props-correct.4: Error for type ''{0}''. Duplicate attribute uses with the same name and target namespace are specified.  Name of duplicate attribute use is ''{1}''.
+        ct-props-correct.5 = ct-props-correct.5: Error for type ''{0}''. Two attribute declarations, ''{1}'' and ''{2}'' have types which are derived from ID.
+        derivation-ok-restriction.1 = derivation-ok-restriction.1: Type ''{0}'' was derived by restriction from type ''{1}''.  However, ''{1}'' has a '{'final'}' property that forbids derivation by restriction.
+        derivation-ok-restriction.2.1.1 = derivation-ok-restriction.2.1.1: Error for type ''{0}''.  The attribute use ''{1}'' in this type has a ''use'' value of ''{2}'', which is inconsistent with the value of ''required'' in a matching attribute use in the base type.
+        derivation-ok-restriction.2.1.2 = derivation-ok-restriction.2.1.2: Error for type ''{0}''.  The attribute use ''{1}'' in this type has type ''{2}'', which is not validly derived from ''{3}'', the type of the matching attribute use in the base type.
+        derivation-ok-restriction.2.1.3.a = derivation-ok-restriction.2.1.3.a: Error for type ''{0}''.  The attribute use ''{1}'' in this type has an effective value constraint which is not fixed, and the effective value constraint of the matching attribute use in the base type is fixed.
+        derivation-ok-restriction.2.1.3.b = derivation-ok-restriction.2.1.3.b: Error for type ''{0}''.  The attribute use ''{1}'' in this type has an effective value constraint fixed with a value of ''{2}'', which is not consistent with the value of ''{3}'' for the fixed effective value constraint of the matching attribute use in the base type.
+        derivation-ok-restriction.2.2.a = derivation-ok-restriction.2.2.a: Error for type ''{0}''.  The attribute use ''{1}'' in this type does not have a matching attribute use in the base, and the base type does not have a wildcard attribute.
+        derivation-ok-restriction.2.2.b = derivation-ok-restriction.2.2.b: Error for type ''{0}''.  The attribute use ''{1}'' in this type does not have a matching attribute use in the base, and the wildcard in the base type does not allow the namespace ''{2}'' of this attribute use.
+        derivation-ok-restriction.3 = derivation-ok-restriction.3: Error for type ''{0}''.  The attribute use ''{1}'' in the base type has REQUIRED as true, but there is no matching attribute use in the derived type.
+        derivation-ok-restriction.4.1 = derivation-ok-restriction.4.1: Error for type ''{0}''.  The derivation has an attribute wildcard, but the base does not have one.
+        derivation-ok-restriction.4.2 = derivation-ok-restriction.4.2: Error for type ''{0}''.  The wildcard in the derivation is not a valid wildcard subset of the one in the base.
+        derivation-ok-restriction.4.3 = derivation-ok-restriction.4.3: Error for type ''{0}''.  The process contents of the wildcard in the derivation ({1}) is weaker than that in the base ({2}).
+        derivation-ok-restriction.5.2.2.1 = derivation-ok-restriction.5.2.2.1: Error for type ''{0}''.  The simple content type of this type, ''{1}'', is not a valid restriction of the simple content type of the base, ''{2}''.
+        derivation-ok-restriction.5.3.2 = derivation-ok-restriction.5.3.2: Error for type ''{0}''.  The content type of this type is empty, but the content type of the base, ''{1}'', is not empty or emptiable.
+        derivation-ok-restriction.5.4.1.2 = derivation-ok-restriction.5.4.1.2: Error for type ''{0}''.  The content type of this type is mixed, but the content type of the base, ''{1}'', is not.
+        derivation-ok-restriction.5.4.2 = derivation-ok-restriction.5.4.2: Error for type ''{0}''.  The particle of the type is not a valid restriction of the particle of the base.
+        enumeration-required-notation = enumeration-required-notation: The NOTATION type, ''{0}'' used by {2} ''{1}'', must have an enumeration facet value which specifies the notation elements used by this type.
+        enumeration-valid-restriction = enumeration-valid-restriction: Enumeration value ''{0}'' is not in the value space of the base type, {1}.
+        e-props-correct.2 = e-props-correct.2: Invalid value constraint value ''{1}'' in element ''{0}''.
+        e-props-correct.4 = e-props-correct.4: The '{'type definition'}' of element ''{0}'' is not validly derived from the '{'type definition'}' of the substitutionHead ''{1}'', or the '{'substitution group exclusions'}' property of ''{1}'' does not allow this derivation.
+        e-props-correct.5 = e-props-correct.5: A '{'value constraint'}' must not be present on element ''{0}'', because the element''s '{'type definition'}' or '{'type definition'}'''s '{'content type'}' is ID, or is derived from ID.
+        e-props-correct.6 = e-props-correct.6: Circular substitution group detected for element ''{0}''.
+        fractionDigits-valid-restriction = fractionDigits-valid-restriction: In the definition of {2}, the value ''{0}'' for the facet ''fractionDigits'' is invalid, because it must be <= the value for ''fractionDigits'' which was set to ''{1}'' in one of the ancestor types.
+        fractionDigits-totalDigits = fractionDigits-totalDigits: In the definition of {2}, the value ''{0}'' for the facet ''fractionDigits'' is invalid, because the value must be <= the value for ''totalDigits'' which is ''{1}''.
+        length-minLength-maxLength.1.1 = length-minLength-maxLength.1.1: For type {0}, it is an error for the value of length ''{1}'' to be less than the value of minLength ''{2}''.
+        length-minLength-maxLength.1.2.a = length-minLength-maxLength.1.2.a: For type {0}, it is an error for the base to not have a minLength facet if the current restriction has the minLength facet and the current restriction or base has the length facet. 
+        length-minLength-maxLength.1.2.b = length-minLength-maxLength.1.2.b: For type {0}, it is an error for the current minLength ''{1}'' to not equal the base minLength ''{2}''.
+        length-minLength-maxLength.2.1 = length-minLength-maxLength.2.1: For type {0}, it is an error for the value of length ''{1}'' to be greater than the value of maxLength ''{2}''. 
+        length-minLength-maxLength.2.2.a = length-minLength-maxLength.2.2.a: For type {0}, it is an error for the base to not have a maxLength facet if the current restriction has the maxLength facet and the current restriction or base has the length facet. 
+        length-minLength-maxLength.2.2.b = length-minLength-maxLength.2.2.b: For type {0}, it is an error for the current maxLength ''{1}'' to not equal the base maxLength ''{2}''.        
+        length-valid-restriction = length-valid-restriction: Error for type ''{2}''. The value of length = ''{0}'' must be = the value of that of the base type ''{1}''.
+        maxExclusive-valid-restriction.1 = maxExclusive-valid-restriction.1: Error for type ''{2}''. The maxExclusive value =''{0}'' must be <= maxExclusive of the base type ''{1}''.
+        maxExclusive-valid-restriction.2 = maxExclusive-valid-restriction.2: Error for type ''{2}''. The maxExclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+        maxExclusive-valid-restriction.3 = maxExclusive-valid-restriction.3: Error for type ''{2}''. The maxExclusive value =''{0}'' must be > minInclusive of the base type ''{1}''.
+        maxExclusive-valid-restriction.4 = maxExclusive-valid-restriction.4: Error for type ''{2}''. The maxExclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+        maxInclusive-maxExclusive = maxInclusive-maxExclusive: It is an error for both maxInclusive and maxExclusive to be specified for the same datatype. In {2}, maxInclusive = ''{0}'' and maxExclusive = ''{1}''.
+        maxInclusive-valid-restriction.1 = maxInclusive-valid-restriction.1: Error for type ''{2}''. The maxInclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+        maxInclusive-valid-restriction.2 = maxInclusive-valid-restriction.2: Error for type ''{2}''. The maxInclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+        maxInclusive-valid-restriction.3 = maxInclusive-valid-restriction.3: Error for type ''{2}''. The maxInclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+        maxInclusive-valid-restriction.4 = maxInclusive-valid-restriction.4: Error for type ''{2}''. The maxInclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+        maxLength-valid-restriction = maxLength-valid-restriction: In the definition of {2}, maxLength value = ''{0}'' must be <= that of the base type ''{1}''.
+        mg-props-correct.2 = mg-props-correct.2: Circular definitions detected for group ''{0}''. Recursively following the '{'term'}' values of the particles leads to a particle whose '{'term'}' is the group itself.
+        minExclusive-less-than-equal-to-maxExclusive = minExclusive-less-than-equal-to-maxExclusive: In the definition of {2}, minExclusive value = ''{0}'' must be <= maxExclusive value = ''{1}''.
+        minExclusive-less-than-maxInclusive = minExclusive-less-than-maxInclusive: In the definition of {2}, minExclusive value = ''{0}'' must be < maxInclusive value = ''{1}''.
+        minExclusive-valid-restriction.1 = minExclusive-valid-restriction.1: Error for type ''{2}''. The minExclusive value =''{0}'' must be >= minExclusive of the base type ''{1}''.
+        minExclusive-valid-restriction.2 = minExclusive-valid-restriction.2: Error for type ''{2}''. The minExclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+        minExclusive-valid-restriction.3 = minExclusive-valid-restriction.3: Error for type ''{2}''. The minExclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+        minExclusive-valid-restriction.4 = minExclusive-valid-restriction.4: Error for type ''{2}''. The minExclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+        minInclusive-less-than-equal-to-maxInclusive = minInclusive-less-than-equal-to-maxInclusive: In the definition of {2}, minInclusive value = ''{0}'' must be <= maxInclusive value = ''{1}''.
+        minInclusive-less-than-maxExclusive = minInclusive-less-than-maxExclusive: In the definition of {2}, minInclusive value = ''{0}'' must be < maxExclusive value = ''{1}''.
+        minInclusive-minExclusive = minInclusive-minExclusive: It is an error for both minInclusive and minExclusive to be specified for the same datatype. In {2}, minInclusive = ''{0}'' and minExclusive = ''{1}''.
+        minInclusive-valid-restriction.1 = minInclusive-valid-restriction.1: Error for type ''{2}''. The minInclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+        minInclusive-valid-restriction.2 = minInclusive-valid-restriction.2: Error for type ''{2}''. The minInclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+        minInclusive-valid-restriction.3 = minInclusive-valid-restriction.3: Error for type ''{2}''. The minInclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+        minInclusive-valid-restriction.4 = minInclusive-valid-restriction.4: Error for type ''{2}''. The minInclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+        minLength-less-than-equal-to-maxLength = minLength-less-than-equal-to-maxLength: In the definition of {2}, value of minLength = ''{0}'' must be < value of maxLength = ''{1}''.
+        minLength-valid-restriction = minLength-valid-restriction: In the definition of {2}, minLength = ''{0}'' must be >= than that of the base type, ''{1}''.
+        no-xmlns = no-xmlns: The {name} of an attribute declaration must not match 'xmlns'.
+        no-xsi = no-xsi: The '{'target namespace'}' of an attribute declaration must not match ''{0}''.
+        p-props-correct.2.1 = p-props-correct.2.1: In the declaration of ''{0}'', the value of ''minOccurs'' is ''{1}'', but it must not be greater than the value of ''maxOccurs'', which is ''{2}''.
+        rcase-MapAndSum.1 = rcase-MapAndSum.1: There is not a complete functional mapping between the particles.
+        rcase-MapAndSum.2 = rcase-MapAndSum.2: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+        rcase-NameAndTypeOK.1 = rcase-NameAndTypeOK.1: Elements have names and target namespaces which are not the same:  Element ''{0}'' in namespace ''{1}'' and element ''{2}'' in namespace ''{3}''.
+        rcase-NameAndTypeOK.2 = rcase-NameAndTypeOK.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. The element declaration''s '{'nillable'}' is true, but the corresponding particle in the base type has an element declaration whose '{'nillable'}' is false.
+        rcase-NameAndTypeOK.3 = rcase-NameAndTypeOK.3: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}), of the corresponding particle in the base type.
+        rcase-NameAndTypeOK.4.a = rcase-NameAndTypeOK.4.a: Element ''{0}'' is not fixed, but the corresponding element in the base type is fixed with value ''{1}''.
+        rcase-NameAndTypeOK.4.b = rcase-NameAndTypeOK.4.b: Element ''{0}'' is fixed with value ''{1}'', but the corresponding element in the base type is fixed with value ''{2}''.
+        rcase-NameAndTypeOK.5 = rcase-NameAndTypeOK.5: Identity constraints for element ''{0}'' are not a subset of those in base.
+        rcase-NameAndTypeOK.6 = rcase-NameAndTypeOK.6: The disallowed substitutions for element ''{0}'' are not a superset of those in the base.
+        rcase-NameAndTypeOK.7 = rcase-NameAndTypeOK.7: The type of element ''{0}'', ''{1}'', is not derived from the type of the base element, ''{2}''.
+        rcase-NSCompat.1 = rcase-NSCompat.1: Element ''{0}'' has a namespace ''{1}'' which is not allowed by the wildcard in the base.
+        rcase-NSCompat.2 = rcase-NSCompat.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}), of the corresponding particle in the base type.
+        rcase-NSRecurseCheckCardinality.1 = rcase-NSRecurseCheckCardinality.1: There is not a complete functional mapping between the particles.
+        rcase-NSRecurseCheckCardinality.2 = rcase-NSRecurseCheckCardinality.2: Group''s occurrence range, ({0},{1}), is not a valid restriction of base wildcard''s range, ({2},{3}).
+        rcase-NSSubset.1 = rcase-NSSubset.1: Wildcard is not a subset of corresponding wildcard in base.
+        rcase-NSSubset.2 = rcase-NSSubset.2: Wildcard''s occurrence range, ({0},{1}), is not a valid restriction of that in the base, ({2},{3}),.
+        rcase-NSSubset.3 = rcase-NSSubset.3: Wildcard''s process contents, ''{0}'', is weaker than that in the base, ''{1}''.
+        rcase-Recurse.1 = rcase-Recurse.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+        rcase-Recurse.2 = rcase-Recurse.2: There is not a complete functional mapping between the particles.
+        rcase-RecurseLax.1 = rcase-RecurseLax.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+        rcase-RecurseLax.2 = rcase-RecurseLax.2: There is not a complete functional mapping between the particles.
+        rcase-RecurseUnordered.1 = rcase-RecurseUnordered.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+        rcase-RecurseUnordered.2 = rcase-RecurseUnordered.2: There is not a complete functional mapping between the particles.
+#        We're using sch-props-correct.2 instead of the old src-redefine.1
+#        src-redefine.1 = src-redefine.1: The component ''{0}'' is begin redefined, but its corresponding component isn't in the schema document being redefined (with namespace ''{2}''), but in a different document, with namespace ''{1}''.
+        sch-props-correct.2 = sch-props-correct.2: A schema cannot contain two global components with the same name; this schema contains two occurrences of ''{0}''.
+        st-props-correct.2 = st-props-correct.2: Circular definitions have been detected for simple type ''{0}''. This means that ''{0}'' is contained in its own type hierarchy, which is an error.
+        st-props-correct.3 = st-props-correct.3: Error for type ''{0}''. The value of '{'final'}' of the '{'base type definition'}', ''{1}'', forbids derivation by restriction.
+        totalDigits-valid-restriction = totalDigits-valid-restriction: In the definition of {2}, the value ''{0}'' for the facet ''totalDigits'' is invalid, because it must be <= the value for ''totalDigits'' which was set to ''{1}'' in one of the ancestor types.
+        whiteSpace-valid-restriction.1 = whiteSpace-valid-restriction.1: In the definition of {0}, the value ''{1}'' for the facet ''whitespace'' is invalid, because the value for ''whitespace'' has been set to ''collapse'' in one of the ancestor types.
+        whiteSpace-valid-restriction.2 = whiteSpace-valid-restriction.2: In the definition of {0}, the value ''preserve'' for the facet ''whitespace'' is invalid, because the value for ''whitespace'' has been set to ''replace'' in one of the ancestor types.
+
+#schema for Schemas
+
+        s4s-att-invalid-value = s4s-att-invalid-value: Invalid attribute value for ''{1}'' in element ''{0}''. Recorded reason: {2}
+        s4s-att-must-appear = s4s-att-must-appear: Attribute ''{1}'' must appear in element ''{0}''.
+        s4s-att-not-allowed = s4s-att-not-allowed: Attribute ''{1}'' cannot appear in element ''{0}''.
+        s4s-elt-invalid = s4s-elt-invalid: Element ''{0}'' is not a valid element in a schema document.
+        s4s-elt-must-match.1 = s4s-elt-must-match.1: The content of ''{0}'' must match {1}. A problem was found starting at: {2}.
+        s4s-elt-must-match.2 = s4s-elt-must-match.2: The content of ''{0}'' must match {1}. Not enough elements were found.
+        # the "invalid-content" messages provide less information than the "must-match" counterparts above. They're used for complex types when providing a "match" would be an information dump
+        s4s-elt-invalid-content.1 = s4s-elt-invalid-content.1: The content of ''{0}'' is invalid.  Element ''{1}'' is invalid, misplaced, or occurs too often.
+        s4s-elt-invalid-content.2 = s4s-elt-invalid-content.2: The content of ''{0}'' is invalid.  Element ''{1}'' cannot be empty.
+        s4s-elt-invalid-content.3 = s4s-elt-invalid-content.3: Elements of type ''{0}'' cannot appear after declarations as children of a <schema> element.
+        s4s-elt-schema-ns = s4s-elt-schema-ns: The namespace of element ''{0}'' must be from the schema namespace, ''http://www.w3.org/2001/XMLSchema''.
+        s4s-elt-character = s4s-elt-character: Non-whitespace characters are not allowed in schema elements other than ''xs:appinfo'' and ''xs:documentation''. Saw ''{0}''.
+
+# codes not defined by the spec
+
+        c-fields-xpaths = c-fields-xpaths: The field value = ''{0}'' is not valid.
+        c-general-xpath = c-general-xpath: The expression ''{0}'' is not valid with respect to the XPath subset supported by XML Schema.
+        c-general-xpath-ns = c-general-xpath-ns: A namespace prefix in XPath expression ''{0}'' was not bound to a namespace.
+        c-selector-xpath = c-selector-xpath: The selector value = ''{0}'' is not valid; selector xpaths cannot contain attributes.
+        EmptyTargetNamespace = EmptyTargetNamespace: In schema document ''{0}'', the value of the ''targetNamespace'' attribute cannot be an empty string.
+        FacetValueFromBase = FacetValueFromBase: In the declaration of type ''{0}'', value ''{1}'' of facet ''{2}'' must be from the value space of the base type, ''{3}''.
+        FixedFacetValue = FixedFacetValue: In the definition of {3}, the value ''{1}'' for the facet ''{0}'' is invalid, because the value for ''{0}'' has been set to ''{2}'' in one of the ancestor types, and '{'fixed'}' = true.
+        InvalidRegex = InvalidRegex: Pattern value ''{0}'' is not a valid regular expression. The reported error was: ''{1}''.
+        maxOccurLimit = Current configuration of the parser doesn''t allow the expansion of a content model for a complex type to contain more than {0} nodes.
+        PublicSystemOnNotation = PublicSystemOnNotation: At least one of 'public' and 'system' must appear in element 'notation'.
+        SchemaLocation = SchemaLocation: schemaLocation value = ''{0}'' must have even number of URI''s.
+        TargetNamespace.1 = TargetNamespace.1: Expecting namespace ''{0}'', but the target namespace of the schema document is ''{1}''.
+        TargetNamespace.2 = TargetNamespace.2: Expecting no namespace, but the schema document has a target namespace of ''{1}''.
+        UndeclaredEntity = UndeclaredEntity: Entity ''{0}'' is not declared.
+        UndeclaredPrefix = UndeclaredPrefix: Cannot resolve ''{0}'' as a QName: the prefix ''{1}'' is not declared.
+
+# JAXP 1.2 schema source property errors
+
+        jaxp12-schema-source-type.1 = The ''http://java.sun.com/xml/jaxp/properties/schemaSource'' property cannot have a value of type ''{0}''. Possible types of the value supported are String, File, InputStream, InputSource or an array of these types.
+        jaxp12-schema-source-type.2 = The ''http://java.sun.com/xml/jaxp/properties/schemaSource'' property cannot have an array value of type ''{0}''. Possible types of the array supported are Object, String, File, InputStream and InputSource.
+        jaxp12-schema-source-ns = When using an array of Objects as the value of the 'http://java.sun.com/xml/jaxp/properties/schemaSource' property, it is illegal to have two schemas that share the same target namespace.
+        
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XMLSchemaMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XMLSchemaMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cd8765da056a52ba84301800ba5c031d3797c239
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XMLSchemaMessages_en.properties
@@ -0,0 +1,320 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file contains error and warning messages related to XML Schema
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: XMLSchemaMessages.properties 806363 2009-08-20 21:18:48Z mrglavas $
+
+        BadMessageKey = The error message corresponding to the message key can not be found.
+        FormatFailed = An internal error occurred while formatting the following message:\n
+
+# For internal use
+
+        Internal-Error = Internal error: {0}.
+        dt-whitespace = Whitespace facet value is not available for the union simpleType ''{0}''
+        GrammarConflict = One of the grammar(s) returned from the user's grammar pool is in conflict with another grammar.
+
+# Identity constraints
+
+        AbsentKeyValue = cvc-identity-constraint.4.2.1.a: Element \"{0}\" has no value for the key \"{1}\".
+        DuplicateField = Duplicate match in scope for field \"{0}\".
+        DuplicateKey = cvc-identity-constraint.4.2.2: Duplicate key value [{0}] declared for identity constraint \"{2}\" of element \"{1}\".
+        DuplicateUnique = cvc-identity-constraint.4.1: Duplicate unique value [{0}] declared for identity constraint \"{2}\" of element \"{1}\".
+        FieldMultipleMatch = cvc-identity-constraint.3: Field \"{0}\" of identity constraint \"{1}\" matches more than one value within the scope of its selector; fields must match unique values.
+        FixedDiffersFromActual = The content of this element is not equivalent to the value of the \"fixed\" attribute in the element's declaration in the schema.
+        KeyMatchesNillable = cvc-identity-constraint.4.2.3: Element \"{0}\" has the key \"{1}\" which matches an element which has nillable set to true.
+        KeyNotEnoughValues = cvc-identity-constraint.4.2.1.b: Not enough values specified for <key name=\"{1}\"> identity constraint specified for element \"{0}\".
+        KeyNotFound = cvc-identity-constraint.4.3: Key ''{0}'' with value ''{1}'' not found for identity constraint of element ''{2}''.
+        KeyRefOutOfScope = Identity Constraint error:  identity constraint \"{0}\" has a keyref which refers to a key or unique that is out of scope.
+        KeyRefReferNotFound = Key reference declaration \"{0}\" refers to unknown key with name \"{1}\".
+        UnknownField = Internal identity constraint error; unknown field \"{0}\" for identity constraint \"{2}\" specified for element \"{1}\".
+
+# Ideally, we should only use the following error keys, not the ones under
+# "Identity constraints". And we should cover all of the following errors.
+
+#validation (3.X.4)
+
+        cvc-attribute.3 = cvc-attribute.3: The value ''{2}'' of attribute ''{1}'' on element ''{0}'' is not valid with respect to its type, ''{3}''.
+        cvc-attribute.4 = cvc-attribute.4: The value ''{2}'' of attribute ''{1}'' on element ''{0}'' is not valid with respect to its fixed '{'value constraint'}'. The attribute must have a value of ''{3}''.
+        cvc-complex-type.2.1 = cvc-complex-type.2.1: Element ''{0}'' must have no character or element information item [children], because the type''s content type is empty.
+        cvc-complex-type.2.2 = cvc-complex-type.2.2: Element ''{0}'' must have no element [children], and the value must be valid.
+        cvc-complex-type.2.3 = cvc-complex-type.2.3: Element ''{0}'' cannot have character [children], because the type''s content type is element-only.
+        cvc-complex-type.2.4.a = cvc-complex-type.2.4.a: Invalid content was found starting with element ''{0}''. One of ''{1}'' is expected.
+        cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: The content of element ''{0}'' is not complete. One of ''{1}'' is expected.
+        cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ''{0}''.
+        cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: Invalid content was found starting with element ''{0}''. No child element is expected at this point.
+        cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}'' can occur a maximum of ''{2}'' times in the current sequence. This limit was exceeded. At this point one of ''{1}'' is expected.
+        cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}'' can occur a maximum of ''{1}'' times in the current sequence. This limit was exceeded. No child element is expected at this point.
+        cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: Invalid content was found starting with element ''{0}''. ''{1}'' is expected to occur a minimum of ''{2}'' times in the current sequence. One more instance is required to satisfy this constraint.
+        cvc-complex-type.2.4.h = cvc-complex-type.2.4.h: Invalid content was found starting with element ''{0}''. ''{1}'' is expected to occur a minimum of ''{2}'' times in the current sequence. ''{3}'' more instances are required to satisfy this constraint.
+        cvc-complex-type.2.4.i = cvc-complex-type.2.4.i: The content of element ''{0}'' is not complete. ''{1}'' is expected to occur a minimum of ''{2}'' times. One more instance is required to satisfy this constraint.
+        cvc-complex-type.2.4.j = cvc-complex-type.2.4.j: The content of element ''{0}'' is not complete. ''{1}'' is expected to occur a minimum of ''{2}'' times. ''{3}'' more instances are required to satisfy this constraint.
+        cvc-complex-type.3.1 = cvc-complex-type.3.1: Value ''{2}'' of attribute ''{1}'' of element ''{0}'' is not valid with respect to the corresponding attribute use. Attribute ''{1}'' has a fixed value of ''{3}''.
+        cvc-complex-type.3.2.1 = cvc-complex-type.3.2.1: Element ''{0}'' does not have an attribute wildcard for attribute ''{1}''.
+        cvc-complex-type.3.2.2 = cvc-complex-type.3.2.2: Attribute ''{1}'' is not allowed to appear in element ''{0}''.
+        cvc-complex-type.4 = cvc-complex-type.4: Attribute ''{1}'' must appear on element ''{0}''.
+        cvc-complex-type.5.1 = cvc-complex-type.5.1: In element ''{0}'', attribute ''{1}'' is a Wild ID. But there is already a Wild ID ''{2}''. There can be only one.
+        cvc-complex-type.5.2 = cvc-complex-type.5.2: In element ''{0}'', attribute ''{1}'' is a Wild ID. But there is already an attribute ''{2}'' derived from ID among the '{'attribute uses'}'.
+        cvc-datatype-valid.1.2.1 = cvc-datatype-valid.1.2.1: ''{0}'' is not a valid value for ''{1}''.
+        cvc-datatype-valid.1.2.2 = cvc-datatype-valid.1.2.2: ''{0}'' is not a valid value of list type ''{1}''.
+        cvc-datatype-valid.1.2.3 = cvc-datatype-valid.1.2.3: ''{0}'' is not a valid value of union type ''{1}''.
+        cvc-elt.1.a = cvc-elt.1.a: Cannot find the declaration of element ''{0}''.
+        cvc-elt.1.b = cvc-elt.1.b: The name of the element does not match the name of the element declaration. Saw ''{0}''. Expected ''{1}''.
+        cvc-elt.2 = cvc-elt.2: The value of '{'abstract'}' in the element declaration for ''{0}'' must be false.
+        cvc-elt.3.1 = cvc-elt.3.1: Attribute ''{1}'' must not appear on element ''{0}'', because the '{'nillable'}' property of ''{0}'' is false.
+        cvc-elt.3.2.1 = cvc-elt.3.2.1: Element ''{0}'' cannot have character or element information [children], because ''{1}'' is specified.
+        cvc-elt.3.2.2 = cvc-elt.3.2.2: There must be no fixed '{'value constraint'}' for element ''{0}'', because ''{1}'' is specified.
+        cvc-elt.4.1 = cvc-elt.4.1: The value ''{2}'' of attribute ''{1}'' of element ''{0}'' is not a valid QName.
+        cvc-elt.4.2 = cvc-elt.4.2: Cannot resolve ''{1}'' to a type definition for element ''{0}''.
+        cvc-elt.4.3 = cvc-elt.4.3: Type ''{1}'' is not validly derived from the type definition, ''{2}'', of element ''{0}''.
+        cvc-elt.5.1.1 = cvc-elt.5.1.1: '{'value constraint'}' ''{2}'' of element ''{0}'' is not a valid default value for type ''{1}''.
+        cvc-elt.5.2.2.1 = cvc-elt.5.2.2.1: Element ''{0}'' must have no element information item [children].
+        cvc-elt.5.2.2.2.1 = cvc-elt.5.2.2.2.1: The value ''{1}'' of element ''{0}'' does not match the fixed '{'value constraint'}' value ''{2}''.
+        cvc-elt.5.2.2.2.2 = cvc-elt.5.2.2.2.2: The value ''{1}'' of element ''{0}'' does not match the '{'value constraint'}' value ''{2}''.
+        cvc-enumeration-valid = cvc-enumeration-valid: Value ''{0}'' is not facet-valid with respect to enumeration ''{1}''. It must be a value from the enumeration.
+        cvc-fractionDigits-valid = cvc-fractionDigits-valid: Value ''{0}'' has {1} fraction digits, but the number of fraction digits has been limited to {2}.
+        cvc-id.1 = cvc-id.1: There is no ID/IDREF binding for IDREF ''{0}''.
+        cvc-id.2 = cvc-id.2: There are multiple occurrences of ID value ''{0}''.
+        cvc-id.3 = cvc-id.3: A field of identity constraint ''{0}'' matched element ''{1}'', but this element does not have a simple type.
+        cvc-length-valid = cvc-length-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to length ''{2}'' for type ''{3}''.
+        cvc-maxExclusive-valid = cvc-maxExclusive-valid: Value ''{0}'' is not facet-valid with respect to maxExclusive ''{1}'' for type ''{2}''.
+        cvc-maxInclusive-valid = cvc-maxInclusive-valid: Value ''{0}'' is not facet-valid with respect to maxInclusive ''{1}'' for type ''{2}''.
+        cvc-maxLength-valid = cvc-maxLength-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to maxLength ''{2}'' for type ''{3}''.
+        cvc-minExclusive-valid = cvc-minExclusive-valid: Value ''{0}'' is not facet-valid with respect to minExclusive ''{1}'' for type ''{2}''.
+        cvc-minInclusive-valid = cvc-minInclusive-valid: Value ''{0}'' is not facet-valid with respect to minInclusive ''{1}'' for type ''{2}''.
+        cvc-minLength-valid = cvc-minLength-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to minLength ''{2}'' for type ''{3}''.
+        cvc-pattern-valid = cvc-pattern-valid: Value ''{0}'' is not facet-valid with respect to pattern ''{1}'' for type ''{2}''.
+        cvc-totalDigits-valid = cvc-totalDigits-valid: Value ''{0}'' has {1} total digits, but the number of total digits has been limited to {2}.
+        cvc-type.1 = cvc-type.1: The type definition ''{0}'' was not found.
+        cvc-type.2 = cvc-type.2: The type definition cannot be abstract for element {0}.
+        cvc-type.3.1.1 = cvc-type.3.1.1: Element ''{0}'' is a simple type, so it cannot have attributes, excepting those whose namespace name is identical to ''http://www.w3.org/2001/XMLSchema-instance'' and whose [local name] is one of ''type'', ''nil'', ''schemaLocation'' or ''noNamespaceSchemaLocation''. However, the attribute, ''{1}'' was found.
+        cvc-type.3.1.2 = cvc-type.3.1.2: Element ''{0}'' is a simple type, so it must have no element information item [children].
+        cvc-type.3.1.3 = cvc-type.3.1.3: The value ''{1}'' of element ''{0}'' is not valid.
+
+#schema valid (3.X.3)
+
+        schema_reference.4 = schema_reference.4: Failed to read schema document ''{0}'', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
+        src-annotation = src-annotation: <annotation> elements can only contain <appinfo> and <documentation> elements, but ''{0}'' was found.
+        src-attribute.1 = src-attribute.1: The properties ''default'' and ''fixed'' cannot both be present in attribute declaration ''{0}''. Use only one of them.
+        src-attribute.2 = src-attribute.2: : The property ''default'' is present in attribute ''{0}'', so the value of ''use'' must be ''optional''.
+        src-attribute.3.1 = src-attribute.3.1: One of 'ref' or 'name' must be present in a local attribute declaration.
+        src-attribute.3.2 = src-attribute.3.2: The content must match (annotation?) for the attribute reference ''{0}''.
+        src-attribute.4 = src-attribute.4: Attribute ''{0}'' has both a ''type'' attribute and an anonymous ''simpleType'' child. Only one of these is allowed for an attribute.
+        src-attribute_group.2 = src-attribute_group.2: The intersection of wildcards is not expressible for attribute group ''{0}''.
+        src-attribute_group.3 = src-attribute_group.3: Circular definitions detected for attribute group ''{0}''. Recursively following attribute group references eventually leads back to itself.
+        src-ct.1 = src-ct.1: Complex Type Definition Representation Error for type ''{0}''.  When <complexContent> is used, the base type must be a complexType. ''{1}'' is a simpleType.
+        src-ct.2.1 = src-ct.2.1: Complex Type Definition Representation Error for type ''{0}''.  When <simpleContent> is used, the base type must be a complexType whose content type is simple, or, only if restriction is specified, a complex type with mixed content and emptiable particle, or, only if extension is specified, a simple type. ''{1}'' satisfies none of these conditions.
+        src-ct.2.2 = src-ct.2.2: Complex Type Definition Representation Error for type ''{0}''.  When a complexType with simpleContent restricts a complexType with mixed content and emptiable particle, then there must be a <simpleType> among the children of <restriction>.
+        src-ct.4 = src-ct.4: Complex Type Definition Representation Error for type ''{0}''. The intersection of wildcards is not expressible.
+        src-ct.5 = src-ct.5: Complex Type Definition Representation Error for type ''{0}''. The union of wildcards is not expressible.
+        src-element.1 = src-element.1: The properties ''default'' and ''fixed'' cannot both be present in element declaration ''{0}''. Use only one of them.
+        src-element.2.1 = src-element.2.1: : One of 'ref' or 'name' must be present in a local element declaration.
+        src-element.2.2 = src-element.2.2: Since ''{0}'' contains the ''ref'' attribute, its content must match (annotation?). However, ''{1}'' was found.
+        src-element.3 = src-element.3: Element ''{0}'' has both a ''type'' attribute and a ''anonymous type'' child. Only one of these is allowed for an element.
+        src-import.1.1 = src-import.1.1: The namespace attribute ''{0}'' of an <import> element information item must not be the same as the targetNamespace of the schema it exists in.
+        src-import.1.2 = src-import.1.2: If the namespace attribute is not present on an <import> element information item then the enclosing schema must have a targetNamespace.
+        src-import.2 = src-import.2: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+        src-import.3.1 = src-import.3.1: The namespace attribute, ''{0}'', of an <import> element information item must be identical to the targetNamespace attribute, ''{1}'', of the imported document.
+        src-import.3.2 = src-import.3.2: An <import> element information item that had no namespace attribute was found, so the imported document cannot have a targetNamespace attribute. However, the targetNamespace ''{1}'' was found in the imported document.
+        src-include.1 = src-include.1: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+        src-include.2.1 = src-include.2.1: The targetNamespace of the referenced schema, currently ''{1}'', must be identical to that of the including schema, currently ''{0}''.
+        src-redefine.2 = src-redefine.2: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+        src-redefine.3.1 = src-redefine.3.1: The targetNamespace of the referenced schema, currently ''{1}'', must be identical to that of the redefining schema, currently ''{0}''.
+        src-redefine.5.a.a = src-redefine.5.a.a: No non-annotation children of <simpleType> were found. <simpleType> children of <redefine> elements must have <restriction> descendants, with 'base' attributes that refer to themselves.
+        src-redefine.5.a.b = src-redefine.5.a.b: ''{0}'' is not a valid child element. <simpleType> children of <redefine> elements must have <restriction> descendants, with ''base'' attributes that refer to themselves.
+        src-redefine.5.a.c = src-redefine.5.a.c: ''{0}'' does not have a ''base'' attribute that refers to the redefined element, ''{1}''. <simpleType> children of <redefine> elements must have <restriction> descendants, with ''base'' attributes that refer to themselves.
+        src-redefine.5.b.a = src-redefine.5.b.a: No non-annotation children of <complexType> were found. <complexType> children of <redefine> elements must have <extension> or <restriction> descendants, with 'base' attributes that refer to themselves.
+        src-redefine.5.b.b = src-redefine.5.b.b: No non-annotation grandchildren of <complexType> were found. <complexType> children of <redefine> elements must have <extension> or <restriction> descendants, with 'base' attributes that refer to themselves.
+        src-redefine.5.b.c = src-redefine.5.b.c: ''{0}'' is not a valid grandchild element. <complexType> children of <redefine> elements must have <extension> or <restriction> descendants, with ''base'' attributes that refer to themselves.
+        src-redefine.5.b.d = src-redefine.5.b.d: ''{0}'' does not have a ''base'' attribute that refers to the redefined element, ''{1}''. <complexType> children of <redefine> elements must have <extension> or <restriction> descendants, with ''base'' attributes that refer to themselves.
+        src-redefine.6.1.1 = src-redefine.6.1.1:  If a group child of a <redefine> element contains a group referring itself, it must have exactly 1; this one has ''{0}''.
+        src-redefine.6.1.2 = src-redefine.6.1.2:  The group ''{0}'', which contains a reference to a group being redefined, must have ''minOccurs'' = ''maxOccurs'' = 1.
+        src-redefine.6.2.1 = src-redefine.6.2.1: No group in the redefined schema has a name matching ''{0}''.
+        src-redefine.6.2.2 = src-redefine.6.2.2: Group ''{0}'' does not properly restrict the group it redefines; constraint violated:  ''{1}''.
+        src-redefine.7.1 = src-redefine.7.1:  If an attributeGroup child of a <redefine> element contains an attributeGroup referring itself, it must have exactly 1; this one has {0}.
+        src-redefine.7.2.1 = src-redefine.7.2.1: No attributeGroup in the redefined schema has a name matching ''{0}''.
+        src-redefine.7.2.2 = src-redefine.7.2.2: AttributeGroup ''{0}'' does not properly restrict the attributeGroup it redefines; constraint violated:  ''{1}''.
+        src-resolve = src-resolve: Cannot resolve the name ''{0}'' to a(n) ''{1}'' component.
+        src-resolve.4.1 = src-resolve.4.1: Error resolving component ''{2}''. It was detected that ''{2}'' has no namespace, but components with no target namespace are not referenceable from schema document ''{0}''. If ''{2}'' is intended to have a namespace, perhaps a prefix needs to be provided. If it is intended that ''{2}'' has no namespace, then an ''import'' without a "namespace" attribute should be added to ''{0}''.
+        src-resolve.4.2 = src-resolve.4.2: Error resolving component ''{2}''. It was detected that ''{2}'' is in namespace ''{1}'', but components from this namespace are not referenceable from schema document ''{0}''. If this is the incorrect namespace, perhaps the prefix of ''{2}'' needs to be changed. If this is the correct namespace, then an appropriate ''import'' tag should be added to ''{0}''.
+        src-simple-type.2.a = src-simple-type.2.a: A <restriction> element was found that has both a base [attribute] and a <simpleType> element among its [children]. Only one is allowed.
+        src-simple-type.2.b = src-simple-type.2.b: A <restriction> element was found that has neither a base [attribute] nor a <simpleType> element among its [children]. One is required.
+        src-simple-type.3.a = src-simple-type.3.a: A <list> element was found that has both an itemType [attribute] and a <simpleType> element among its [children]. Only one is allowed.
+        src-simple-type.3.b = src-simple-type.3.b: A <list> element was found that has neither an itemType [attribute] nor a <simpleType> element among its [children]. One is required.
+        src-single-facet-value = src-single-facet-value: The facet ''{0}'' is defined more than once.
+        src-union-memberTypes-or-simpleTypes = src-union-memberTypes-or-simpleTypes: A <union> element must have either a non-empty memberTypes [attribute] or at least one <simpleType> element among its [children].
+
+#constraint valid (3.X.6)
+
+        ag-props-correct.2 = ag-props-correct.2: Error for attribute group ''{0}''.  Duplicate attribute uses with the same name and target namespace are specified.  Name of duplicate attribute use is ''{1}''.
+        ag-props-correct.3 = ag-props-correct.3: Error for attribute group ''{0}''.  Two attribute declarations, ''{1}'' and ''{2}'' have types which are derived from ID.
+        a-props-correct.2 = a-props-correct.2: Invalid value constraint value ''{1}'' in attribute ''{0}''.
+        a-props-correct.3 = a-props-correct.3: Attribute ''{0}'' cannot use ''fixed'' or ''default'', because the attribute''s '{'type definition'}' is ID, or is derived from ID.
+        au-props-correct.2 = au-props-correct.2: In the attribute declaration of ''{0}'', a fixed value of ''{1}'' was specified. So if the attribute use referring to ''{0}'' also has a '{'value constraint'}', it must be fixed and its value must be ''{1}''.
+        cos-all-limited.1.2 = cos-all-limited.1.2: An 'all' model group must appear in a particle with '{'min occurs'}' = '{'max occurs'}' = 1, and that particle must be part of a pair which constitutes the '{'content type'}' of a complex type definition.
+        cos-all-limited.2 = cos-all-limited.2: The '{'max occurs'}' of an element in an ''all'' model group must be 0 or 1. The value ''{0}'' for element ''{1}'' is invalid.
+        cos-applicable-facets = cos-applicable-facets: Facet ''{0}'' is not allowed by type {1}.
+        cos-ct-extends.1.1 = cos-ct-extends.1.1: Type ''{0}'' was derived by extension from type ''{1}''.  However, the ''final'' attribute of ''{1}'' forbids derivation by extension.
+        cos-ct-extends.1.4.3.2.2.1.a = cos-ct-extends.1.4.3.2.2.1.a: The content type of a derived type and that of its base must both be mixed or both be element-only. Type ''{0}'' is element only, but its base type is not.
+        cos-ct-extends.1.4.3.2.2.1.b = cos-ct-extends.1.4.3.2.2.1.b: The content type of a derived type and that of its base must both be mixed or both be element-only. Type ''{0}'' is mixed, but its base type is not.
+        cos-element-consistent = cos-element-consistent: Error for type ''{0}''. Multiple elements with name ''{1}'', with different types, appear in the model group.
+        cos-list-of-atomic = cos-list-of-atomic: In the definition of list type ''{0}'', type ''{1}'' is an invalid list element type because it is not atomic (''{1}'' is either a list type, or a union type which contains a list).
+        cos-nonambig = cos-nonambig: {0} and {1} (or elements from their substitution group) violate \"Unique Particle Attribution\". During validation against this schema, ambiguity would be created for those two particles.
+        cos-particle-restrict.a = cos-particle-restrict.a: Derived particle is empty, and base is not emptiable.
+        cos-particle-restrict.b = cos-particle-restrict.b: Base particle is empty, but derived particle is not.
+        cos-particle-restrict.2 = cos-particle-restrict.2: Forbidden particle restriction: ''{0}''.
+        cos-st-restricts.1.1 = cos-st-restricts.1.1: The type ''{1}'' is atomic, so its '{'base type definition'}', ''{0}'', must be an atomic simple type definition or a built-in primitive datatype.
+        cos-st-restricts.2.1 = cos-st-restricts.2.1: In the definition of list type ''{0}'', type ''{1}'' is an invalid item type because it is either a list type, or a union type that contains a list.
+        cos-st-restricts.2.3.1.1 = cos-st-restricts.2.3.1.1: The '{'final'}' component of the '{'item type definition'}', ''{0}'', contains ''list''. This means that ''{0}'' cannot be used as an item type for list type ''{1}''.
+        cos-st-restricts.3.3.1.1 = cos-st-restricts.3.3.1.1: The '{'final'}' component of the '{'member type definitions'}', ''{0}'', contains ''union''. This means that ''{0}'' cannot be used as an member type for union type ''{1}''.
+        cos-valid-default.2.1 = cos-valid-default.2.1: Element ''{0}'' has a value constraint and must have a mixed or simple content model.
+        cos-valid-default.2.2.2 = cos-valid-default.2.2.2: Since element ''{0}'' has a '{'value constraint'}' and its type definition has mixed '{'content type'}', then the particle of the '{'content type'}' must be emptiable.
+        c-props-correct.2 = c-props-correct.2: Cardinality of Fields for keyref ''{0}'' and key ''{1}'' must match each other.
+        ct-props-correct.3 = ct-props-correct.3: Circular definitions detected for complex type ''{0}''. This means that ''{0}'' is contained in its own type hierarchy, which is an error.
+        ct-props-correct.4 = ct-props-correct.4: Error for type ''{0}''. Duplicate attribute uses with the same name and target namespace are specified.  Name of duplicate attribute use is ''{1}''.
+        ct-props-correct.5 = ct-props-correct.5: Error for type ''{0}''. Two attribute declarations, ''{1}'' and ''{2}'' have types which are derived from ID.
+        derivation-ok-restriction.1 = derivation-ok-restriction.1: Type ''{0}'' was derived by restriction from type ''{1}''.  However, ''{1}'' has a '{'final'}' property that forbids derivation by restriction.
+        derivation-ok-restriction.2.1.1 = derivation-ok-restriction.2.1.1: Error for type ''{0}''.  The attribute use ''{1}'' in this type has a ''use'' value of ''{2}'', which is inconsistent with the value of ''required'' in a matching attribute use in the base type.
+        derivation-ok-restriction.2.1.2 = derivation-ok-restriction.2.1.2: Error for type ''{0}''.  The attribute use ''{1}'' in this type has type ''{2}'', which is not validly derived from ''{3}'', the type of the matching attribute use in the base type.
+        derivation-ok-restriction.2.1.3.a = derivation-ok-restriction.2.1.3.a: Error for type ''{0}''.  The attribute use ''{1}'' in this type has an effective value constraint which is not fixed, and the effective value constraint of the matching attribute use in the base type is fixed.
+        derivation-ok-restriction.2.1.3.b = derivation-ok-restriction.2.1.3.b: Error for type ''{0}''.  The attribute use ''{1}'' in this type has an effective value constraint fixed with a value of ''{2}'', which is not consistent with the value of ''{3}'' for the fixed effective value constraint of the matching attribute use in the base type.
+        derivation-ok-restriction.2.2.a = derivation-ok-restriction.2.2.a: Error for type ''{0}''.  The attribute use ''{1}'' in this type does not have a matching attribute use in the base, and the base type does not have a wildcard attribute.
+        derivation-ok-restriction.2.2.b = derivation-ok-restriction.2.2.b: Error for type ''{0}''.  The attribute use ''{1}'' in this type does not have a matching attribute use in the base, and the wildcard in the base type does not allow the namespace ''{2}'' of this attribute use.
+        derivation-ok-restriction.3 = derivation-ok-restriction.3: Error for type ''{0}''.  The attribute use ''{1}'' in the base type has REQUIRED as true, but there is no matching attribute use in the derived type.
+        derivation-ok-restriction.4.1 = derivation-ok-restriction.4.1: Error for type ''{0}''.  The derivation has an attribute wildcard, but the base does not have one.
+        derivation-ok-restriction.4.2 = derivation-ok-restriction.4.2: Error for type ''{0}''.  The wildcard in the derivation is not a valid wildcard subset of the one in the base.
+        derivation-ok-restriction.4.3 = derivation-ok-restriction.4.3: Error for type ''{0}''.  The process contents of the wildcard in the derivation ({1}) is weaker than that in the base ({2}).
+        derivation-ok-restriction.5.2.2.1 = derivation-ok-restriction.5.2.2.1: Error for type ''{0}''.  The simple content type of this type, ''{1}'', is not a valid restriction of the simple content type of the base, ''{2}''.
+        derivation-ok-restriction.5.3.2 = derivation-ok-restriction.5.3.2: Error for type ''{0}''.  The content type of this type is empty, but the content type of the base, ''{1}'', is not empty or emptiable.
+        derivation-ok-restriction.5.4.1.2 = derivation-ok-restriction.5.4.1.2: Error for type ''{0}''.  The content type of this type is mixed, but the content type of the base, ''{1}'', is not.
+        derivation-ok-restriction.5.4.2 = derivation-ok-restriction.5.4.2: Error for type ''{0}''.  The particle of the type is not a valid restriction of the particle of the base.
+        enumeration-required-notation = enumeration-required-notation: The NOTATION type, ''{0}'' used by {2} ''{1}'', must have an enumeration facet value which specifies the notation elements used by this type.
+        enumeration-valid-restriction = enumeration-valid-restriction: Enumeration value ''{0}'' is not in the value space of the base type, {1}.
+        e-props-correct.2 = e-props-correct.2: Invalid value constraint value ''{1}'' in element ''{0}''.
+        e-props-correct.4 = e-props-correct.4: The '{'type definition'}' of element ''{0}'' is not validly derived from the '{'type definition'}' of the substitutionHead ''{1}'', or the '{'substitution group exclusions'}' property of ''{1}'' does not allow this derivation.
+        e-props-correct.5 = e-props-correct.5: A '{'value constraint'}' must not be present on element ''{0}'', because the element''s '{'type definition'}' or '{'type definition'}'''s '{'content type'}' is ID, or is derived from ID.
+        e-props-correct.6 = e-props-correct.6: Circular substitution group detected for element ''{0}''.
+        fractionDigits-valid-restriction = fractionDigits-valid-restriction: In the definition of {2}, the value ''{0}'' for the facet ''fractionDigits'' is invalid, because it must be <= the value for ''fractionDigits'' which was set to ''{1}'' in one of the ancestor types.
+        fractionDigits-totalDigits = fractionDigits-totalDigits: In the definition of {2}, the value ''{0}'' for the facet ''fractionDigits'' is invalid, because the value must be <= the value for ''totalDigits'' which is ''{1}''.
+        length-minLength-maxLength.1.1 = length-minLength-maxLength.1.1: For type {0}, it is an error for the value of length ''{1}'' to be less than the value of minLength ''{2}''.
+        length-minLength-maxLength.1.2.a = length-minLength-maxLength.1.2.a: For type {0}, it is an error for the base to not have a minLength facet if the current restriction has the minLength facet and the current restriction or base has the length facet. 
+        length-minLength-maxLength.1.2.b = length-minLength-maxLength.1.2.b: For type {0}, it is an error for the current minLength ''{1}'' to not equal the base minLength ''{2}''.
+        length-minLength-maxLength.2.1 = length-minLength-maxLength.2.1: For type {0}, it is an error for the value of length ''{1}'' to be greater than the value of maxLength ''{2}''. 
+        length-minLength-maxLength.2.2.a = length-minLength-maxLength.2.2.a: For type {0}, it is an error for the base to not have a maxLength facet if the current restriction has the maxLength facet and the current restriction or base has the length facet. 
+        length-minLength-maxLength.2.2.b = length-minLength-maxLength.2.2.b: For type {0}, it is an error for the current maxLength ''{1}'' to not equal the base maxLength ''{2}''.        
+        length-valid-restriction = length-valid-restriction: Error for type ''{2}''. The value of length = ''{0}'' must be = the value of that of the base type ''{1}''.
+        maxExclusive-valid-restriction.1 = maxExclusive-valid-restriction.1: Error for type ''{2}''. The maxExclusive value =''{0}'' must be <= maxExclusive of the base type ''{1}''.
+        maxExclusive-valid-restriction.2 = maxExclusive-valid-restriction.2: Error for type ''{2}''. The maxExclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+        maxExclusive-valid-restriction.3 = maxExclusive-valid-restriction.3: Error for type ''{2}''. The maxExclusive value =''{0}'' must be > minInclusive of the base type ''{1}''.
+        maxExclusive-valid-restriction.4 = maxExclusive-valid-restriction.4: Error for type ''{2}''. The maxExclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+        maxInclusive-maxExclusive = maxInclusive-maxExclusive: It is an error for both maxInclusive and maxExclusive to be specified for the same datatype. In {2}, maxInclusive = ''{0}'' and maxExclusive = ''{1}''.
+        maxInclusive-valid-restriction.1 = maxInclusive-valid-restriction.1: Error for type ''{2}''. The maxInclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+        maxInclusive-valid-restriction.2 = maxInclusive-valid-restriction.2: Error for type ''{2}''. The maxInclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+        maxInclusive-valid-restriction.3 = maxInclusive-valid-restriction.3: Error for type ''{2}''. The maxInclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+        maxInclusive-valid-restriction.4 = maxInclusive-valid-restriction.4: Error for type ''{2}''. The maxInclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+        maxLength-valid-restriction = maxLength-valid-restriction: In the definition of {2}, maxLength value = ''{0}'' must be <= that of the base type ''{1}''.
+        mg-props-correct.2 = mg-props-correct.2: Circular definitions detected for group ''{0}''. Recursively following the '{'term'}' values of the particles leads to a particle whose '{'term'}' is the group itself.
+        minExclusive-less-than-equal-to-maxExclusive = minExclusive-less-than-equal-to-maxExclusive: In the definition of {2}, minExclusive value = ''{0}'' must be <= maxExclusive value = ''{1}''.
+        minExclusive-less-than-maxInclusive = minExclusive-less-than-maxInclusive: In the definition of {2}, minExclusive value = ''{0}'' must be < maxInclusive value = ''{1}''.
+        minExclusive-valid-restriction.1 = minExclusive-valid-restriction.1: Error for type ''{2}''. The minExclusive value =''{0}'' must be >= minExclusive of the base type ''{1}''.
+        minExclusive-valid-restriction.2 = minExclusive-valid-restriction.2: Error for type ''{2}''. The minExclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+        minExclusive-valid-restriction.3 = minExclusive-valid-restriction.3: Error for type ''{2}''. The minExclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+        minExclusive-valid-restriction.4 = minExclusive-valid-restriction.4: Error for type ''{2}''. The minExclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+        minInclusive-less-than-equal-to-maxInclusive = minInclusive-less-than-equal-to-maxInclusive: In the definition of {2}, minInclusive value = ''{0}'' must be <= maxInclusive value = ''{1}''.
+        minInclusive-less-than-maxExclusive = minInclusive-less-than-maxExclusive: In the definition of {2}, minInclusive value = ''{0}'' must be < maxExclusive value = ''{1}''.
+        minInclusive-minExclusive = minInclusive-minExclusive: It is an error for both minInclusive and minExclusive to be specified for the same datatype. In {2}, minInclusive = ''{0}'' and minExclusive = ''{1}''.
+        minInclusive-valid-restriction.1 = minInclusive-valid-restriction.1: Error for type ''{2}''. The minInclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+        minInclusive-valid-restriction.2 = minInclusive-valid-restriction.2: Error for type ''{2}''. The minInclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+        minInclusive-valid-restriction.3 = minInclusive-valid-restriction.3: Error for type ''{2}''. The minInclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+        minInclusive-valid-restriction.4 = minInclusive-valid-restriction.4: Error for type ''{2}''. The minInclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+        minLength-less-than-equal-to-maxLength = minLength-less-than-equal-to-maxLength: In the definition of {2}, value of minLength = ''{0}'' must be < value of maxLength = ''{1}''.
+        minLength-valid-restriction = minLength-valid-restriction: In the definition of {2}, minLength = ''{0}'' must be >= than that of the base type, ''{1}''.
+        no-xmlns = no-xmlns: The {name} of an attribute declaration must not match 'xmlns'.
+        no-xsi = no-xsi: The '{'target namespace'}' of an attribute declaration must not match ''{0}''.
+        p-props-correct.2.1 = p-props-correct.2.1: In the declaration of ''{0}'', the value of ''minOccurs'' is ''{1}'', but it must not be greater than the value of ''maxOccurs'', which is ''{2}''.
+        rcase-MapAndSum.1 = rcase-MapAndSum.1: There is not a complete functional mapping between the particles.
+        rcase-MapAndSum.2 = rcase-MapAndSum.2: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+        rcase-NameAndTypeOK.1 = rcase-NameAndTypeOK.1: Elements have names and target namespaces which are not the same:  Element ''{0}'' in namespace ''{1}'' and element ''{2}'' in namespace ''{3}''.
+        rcase-NameAndTypeOK.2 = rcase-NameAndTypeOK.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. The element declaration''s '{'nillable'}' is true, but the corresponding particle in the base type has an element declaration whose '{'nillable'}' is false.
+        rcase-NameAndTypeOK.3 = rcase-NameAndTypeOK.3: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}), of the corresponding particle in the base type.
+        rcase-NameAndTypeOK.4.a = rcase-NameAndTypeOK.4.a: Element ''{0}'' is not fixed, but the corresponding element in the base type is fixed with value ''{1}''.
+        rcase-NameAndTypeOK.4.b = rcase-NameAndTypeOK.4.b: Element ''{0}'' is fixed with value ''{1}'', but the corresponding element in the base type is fixed with value ''{2}''.
+        rcase-NameAndTypeOK.5 = rcase-NameAndTypeOK.5: Identity constraints for element ''{0}'' are not a subset of those in base.
+        rcase-NameAndTypeOK.6 = rcase-NameAndTypeOK.6: The disallowed substitutions for element ''{0}'' are not a superset of those in the base.
+        rcase-NameAndTypeOK.7 = rcase-NameAndTypeOK.7: The type of element ''{0}'', ''{1}'', is not derived from the type of the base element, ''{2}''.
+        rcase-NSCompat.1 = rcase-NSCompat.1: Element ''{0}'' has a namespace ''{1}'' which is not allowed by the wildcard in the base.
+        rcase-NSCompat.2 = rcase-NSCompat.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}), of the corresponding particle in the base type.
+        rcase-NSRecurseCheckCardinality.1 = rcase-NSRecurseCheckCardinality.1: There is not a complete functional mapping between the particles.
+        rcase-NSRecurseCheckCardinality.2 = rcase-NSRecurseCheckCardinality.2: Group''s occurrence range, ({0},{1}), is not a valid restriction of base wildcard''s range, ({2},{3}).
+        rcase-NSSubset.1 = rcase-NSSubset.1: Wildcard is not a subset of corresponding wildcard in base.
+        rcase-NSSubset.2 = rcase-NSSubset.2: Wildcard''s occurrence range, ({0},{1}), is not a valid restriction of that in the base, ({2},{3}),.
+        rcase-NSSubset.3 = rcase-NSSubset.3: Wildcard''s process contents, ''{0}'', is weaker than that in the base, ''{1}''.
+        rcase-Recurse.1 = rcase-Recurse.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+        rcase-Recurse.2 = rcase-Recurse.2: There is not a complete functional mapping between the particles.
+        rcase-RecurseLax.1 = rcase-RecurseLax.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+        rcase-RecurseLax.2 = rcase-RecurseLax.2: There is not a complete functional mapping between the particles.
+        rcase-RecurseUnordered.1 = rcase-RecurseUnordered.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+        rcase-RecurseUnordered.2 = rcase-RecurseUnordered.2: There is not a complete functional mapping between the particles.
+#        We're using sch-props-correct.2 instead of the old src-redefine.1
+#        src-redefine.1 = src-redefine.1: The component ''{0}'' is begin redefined, but its corresponding component isn't in the schema document being redefined (with namespace ''{2}''), but in a different document, with namespace ''{1}''.
+        sch-props-correct.2 = sch-props-correct.2: A schema cannot contain two global components with the same name; this schema contains two occurrences of ''{0}''.
+        st-props-correct.2 = st-props-correct.2: Circular definitions have been detected for simple type ''{0}''. This means that ''{0}'' is contained in its own type hierarchy, which is an error.
+        st-props-correct.3 = st-props-correct.3: Error for type ''{0}''. The value of '{'final'}' of the '{'base type definition'}', ''{1}'', forbids derivation by restriction.
+        totalDigits-valid-restriction = totalDigits-valid-restriction: In the definition of {2}, the value ''{0}'' for the facet ''totalDigits'' is invalid, because it must be <= the value for ''totalDigits'' which was set to ''{1}'' in one of the ancestor types.
+        whiteSpace-valid-restriction.1 = whiteSpace-valid-restriction.1: In the definition of {0}, the value ''{1}'' for the facet ''whitespace'' is invalid, because the value for ''whitespace'' has been set to ''collapse'' in one of the ancestor types.
+        whiteSpace-valid-restriction.2 = whiteSpace-valid-restriction.2: In the definition of {0}, the value ''preserve'' for the facet ''whitespace'' is invalid, because the value for ''whitespace'' has been set to ''replace'' in one of the ancestor types.
+
+#schema for Schemas
+
+        s4s-att-invalid-value = s4s-att-invalid-value: Invalid attribute value for ''{1}'' in element ''{0}''. Recorded reason: {2}
+        s4s-att-must-appear = s4s-att-must-appear: Attribute ''{1}'' must appear in element ''{0}''.
+        s4s-att-not-allowed = s4s-att-not-allowed: Attribute ''{1}'' cannot appear in element ''{0}''.
+        s4s-elt-invalid = s4s-elt-invalid: Element ''{0}'' is not a valid element in a schema document.
+        s4s-elt-must-match.1 = s4s-elt-must-match.1: The content of ''{0}'' must match {1}. A problem was found starting at: {2}.
+        s4s-elt-must-match.2 = s4s-elt-must-match.2: The content of ''{0}'' must match {1}. Not enough elements were found.
+        # the "invalid-content" messages provide less information than the "must-match" counterparts above. They're used for complex types when providing a "match" would be an information dump
+        s4s-elt-invalid-content.1 = s4s-elt-invalid-content.1: The content of ''{0}'' is invalid.  Element ''{1}'' is invalid, misplaced, or occurs too often.
+        s4s-elt-invalid-content.2 = s4s-elt-invalid-content.2: The content of ''{0}'' is invalid.  Element ''{1}'' cannot be empty.
+        s4s-elt-invalid-content.3 = s4s-elt-invalid-content.3: Elements of type ''{0}'' cannot appear after declarations as children of a <schema> element.
+        s4s-elt-schema-ns = s4s-elt-schema-ns: The namespace of element ''{0}'' must be from the schema namespace, ''http://www.w3.org/2001/XMLSchema''.
+        s4s-elt-character = s4s-elt-character: Non-whitespace characters are not allowed in schema elements other than ''xs:appinfo'' and ''xs:documentation''. Saw ''{0}''.
+
+# codes not defined by the spec
+
+        c-fields-xpaths = c-fields-xpaths: The field value = ''{0}'' is not valid.
+        c-general-xpath = c-general-xpath: The expression ''{0}'' is not valid with respect to the XPath subset supported by XML Schema.
+        c-general-xpath-ns = c-general-xpath-ns: A namespace prefix in XPath expression ''{0}'' was not bound to a namespace.
+        c-selector-xpath = c-selector-xpath: The selector value = ''{0}'' is not valid; selector xpaths cannot contain attributes.
+        EmptyTargetNamespace = EmptyTargetNamespace: In schema document ''{0}'', the value of the ''targetNamespace'' attribute cannot be an empty string.
+        FacetValueFromBase = FacetValueFromBase: In the declaration of type ''{0}'', value ''{1}'' of facet ''{2}'' must be from the value space of the base type, ''{3}''.
+        FixedFacetValue = FixedFacetValue: In the definition of {3}, the value ''{1}'' for the facet ''{0}'' is invalid, because the value for ''{0}'' has been set to ''{2}'' in one of the ancestor types, and '{'fixed'}' = true.
+        InvalidRegex = InvalidRegex: Pattern value ''{0}'' is not a valid regular expression. The reported error was: ''{1}''.
+        maxOccurLimit = Current configuration of the parser doesn''t allow the expansion of a content model for a complex type to contain more than {0} nodes.
+        PublicSystemOnNotation = PublicSystemOnNotation: At least one of 'public' and 'system' must appear in element 'notation'.
+        SchemaLocation = SchemaLocation: schemaLocation value = ''{0}'' must have even number of URI''s.
+        TargetNamespace.1 = TargetNamespace.1: Expecting namespace ''{0}'', but the target namespace of the schema document is ''{1}''.
+        TargetNamespace.2 = TargetNamespace.2: Expecting no namespace, but the schema document has a target namespace of ''{1}''.
+        UndeclaredEntity = UndeclaredEntity: Entity ''{0}'' is not declared.
+        UndeclaredPrefix = UndeclaredPrefix: Cannot resolve ''{0}'' as a QName: the prefix ''{1}'' is not declared.
+
+# JAXP 1.2 schema source property errors
+
+        jaxp12-schema-source-type.1 = The ''http://java.sun.com/xml/jaxp/properties/schemaSource'' property cannot have a value of type ''{0}''. Possible types of the value supported are String, File, InputStream, InputSource or an array of these types.
+        jaxp12-schema-source-type.2 = The ''http://java.sun.com/xml/jaxp/properties/schemaSource'' property cannot have an array value of type ''{0}''. Possible types of the array supported are Object, String, File, InputStream and InputSource.
+        jaxp12-schema-source-ns = When using an array of Objects as the value of the 'http://java.sun.com/xml/jaxp/properties/schemaSource' property, it is illegal to have two schemas that share the same target namespace.
+        
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XMLSerializerMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XMLSerializerMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..5a86e03b88815ada2343e864fe8079cf0ceb6e64
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XMLSerializerMessages.properties
@@ -0,0 +1,50 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores error messages for the Xerces XML
+# serializer.  Many DOM Load/Save error messages also 
+# live here, since the serializer largely implements that package.
+#
+# As usual with properties files, the messages are arranged in
+# key/value tuples.
+# 
+# @version $Id: XMLSerializerMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+    BadMessageKey = The error message corresponding to the message key can not be found.
+    FormatFailed = An internal error occurred while formatting the following message:\n
+
+    ArgumentIsNull = Argument ''{0}'' is null.
+    NoWriterSupplied = No writer supplied for serializer.
+    MethodNotSupported = The method ''{0}'' is not supported by this factory.
+    ResetInMiddle = The serializer may not be reset in the middle of serialization.
+    Internal = Internal error: element state is zero.
+    NoName = There is no rawName and localName is null.
+    ElementQName = The element name ''{0}'' is not a QName.
+    ElementPrefix = Element ''{0}'' does not belong to any namespace: prefix could be undeclared or bound to some namespace.
+    AttributeQName = The attribute name ''{0}'' is not a QName.
+    AttributePrefix = Attribute ''{0}'' does not belong to any namespace: prefix could be undeclared or bound to some namespace.
+    InvalidNSDecl = Namespace declaration syntax is incorrect: {0}.
+    EndingCDATA = The character sequence \"]]>\" must not appear in content unless used to mark the end of a CDATA section.
+    SplittingCDATA = Splitting a CDATA section containing the CDATA section termination marker \"]]>\".
+    ResourceNotFound = The resource ''{0}'' could not be found.
+    ResourceNotLoaded = The resource ''{0}'' could not be loaded. {1}
+    SerializationStopped =  Serialization stopped at user request.
+
+    # DOM Level 3 load and save messages
+    no-output-specified = no-output-specified: The output destination for data to be written to was null.
+    unsupported-encoding = unsupported-encoding: An unsupported encoding is encountered.
+    unable-to-serialize-node = unable-to-serialize-node: The node could not be serialized.
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XMLSerializerMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XMLSerializerMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..5a86e03b88815ada2343e864fe8079cf0ceb6e64
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XMLSerializerMessages_en.properties
@@ -0,0 +1,50 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores error messages for the Xerces XML
+# serializer.  Many DOM Load/Save error messages also 
+# live here, since the serializer largely implements that package.
+#
+# As usual with properties files, the messages are arranged in
+# key/value tuples.
+# 
+# @version $Id: XMLSerializerMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+    BadMessageKey = The error message corresponding to the message key can not be found.
+    FormatFailed = An internal error occurred while formatting the following message:\n
+
+    ArgumentIsNull = Argument ''{0}'' is null.
+    NoWriterSupplied = No writer supplied for serializer.
+    MethodNotSupported = The method ''{0}'' is not supported by this factory.
+    ResetInMiddle = The serializer may not be reset in the middle of serialization.
+    Internal = Internal error: element state is zero.
+    NoName = There is no rawName and localName is null.
+    ElementQName = The element name ''{0}'' is not a QName.
+    ElementPrefix = Element ''{0}'' does not belong to any namespace: prefix could be undeclared or bound to some namespace.
+    AttributeQName = The attribute name ''{0}'' is not a QName.
+    AttributePrefix = Attribute ''{0}'' does not belong to any namespace: prefix could be undeclared or bound to some namespace.
+    InvalidNSDecl = Namespace declaration syntax is incorrect: {0}.
+    EndingCDATA = The character sequence \"]]>\" must not appear in content unless used to mark the end of a CDATA section.
+    SplittingCDATA = Splitting a CDATA section containing the CDATA section termination marker \"]]>\".
+    ResourceNotFound = The resource ''{0}'' could not be found.
+    ResourceNotLoaded = The resource ''{0}'' could not be loaded. {1}
+    SerializationStopped =  Serialization stopped at user request.
+
+    # DOM Level 3 load and save messages
+    no-output-specified = no-output-specified: The output destination for data to be written to was null.
+    unsupported-encoding = unsupported-encoding: An unsupported encoding is encountered.
+    unable-to-serialize-node = unable-to-serialize-node: The node could not be serialized.
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XPointerMessages.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XPointerMessages.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cdd4c6e38a345dd322e2b54f3fa3b7630785c0ab
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XPointerMessages.properties
@@ -0,0 +1,44 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces XPointer implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: XPointerMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n  
+
+# XPointer Framework Error Messages
+XPointerProcessingError = XPointerProcessingError: An error occurred while processing the XPointer expression.
+InvalidXPointerToken = InvalidXPointerToken: The XPointer expression contains the invalid token ''{0}''
+InvalidXPointerExpression = InvalidXPointerExpression: The XPointer expression ''{0}'' is invalid.
+MultipleShortHandPointers = MultipleShortHandPointers:  The XPointer expression ''{0}'' is invalid.  It has more than one ShortHand Pointer. 
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: The XPointer expression ''{0}'' is invalid.  The SchemeData was not followed by a '')'' character. 
+SchemeUnsupported = SchemeUnsupported: The XPointer scheme ''{0}'' is not supported.
+InvalidShortHandPointer = InvalidShortHandPointer: The NCName of the ShortHand Pointer ''{0}'' is invalid.
+UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: The XPointer expression ''{0}'' is invalid.  The number of open parenthesis ''{1}'' is not equal to the number of close parenthesis ''{2}''.
+InvalidSchemeDataInXPointer = InvalidSchemeDataInXPointer: The XPointer expression ''{0}'' contains invalid SchemeData.
+
+# XPointer Element Scheme Error Messages
+InvalidElementSchemeToken = InvalidElementSchemeToken: The element() scheme XPointer expression contains the invalid token ''{0}''
+InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: The Element Scheme XPointer expression ''{0}'' is invalid.
+XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: An error occurred while processing the XPointer element() Scheme expression.
+InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: The element() Scheme contains a ShortHand Pointer ''{0}'' with an invalid NCName.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''. 
\ No newline at end of file
diff --git a/src/main/resources/org/python/apache/xerces/impl/msg/XPointerMessages_en.properties b/src/main/resources/org/python/apache/xerces/impl/msg/XPointerMessages_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cdd4c6e38a345dd322e2b54f3fa3b7630785c0ab
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/msg/XPointerMessages_en.properties
@@ -0,0 +1,44 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces XPointer implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id: XPointerMessages.properties 595211 2007-11-15 05:28:12Z mrglavas $
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n  
+
+# XPointer Framework Error Messages
+XPointerProcessingError = XPointerProcessingError: An error occurred while processing the XPointer expression.
+InvalidXPointerToken = InvalidXPointerToken: The XPointer expression contains the invalid token ''{0}''
+InvalidXPointerExpression = InvalidXPointerExpression: The XPointer expression ''{0}'' is invalid.
+MultipleShortHandPointers = MultipleShortHandPointers:  The XPointer expression ''{0}'' is invalid.  It has more than one ShortHand Pointer. 
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: The XPointer expression ''{0}'' is invalid.  The SchemeData was not followed by a '')'' character. 
+SchemeUnsupported = SchemeUnsupported: The XPointer scheme ''{0}'' is not supported.
+InvalidShortHandPointer = InvalidShortHandPointer: The NCName of the ShortHand Pointer ''{0}'' is invalid.
+UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: The XPointer expression ''{0}'' is invalid.  The number of open parenthesis ''{1}'' is not equal to the number of close parenthesis ''{2}''.
+InvalidSchemeDataInXPointer = InvalidSchemeDataInXPointer: The XPointer expression ''{0}'' contains invalid SchemeData.
+
+# XPointer Element Scheme Error Messages
+InvalidElementSchemeToken = InvalidElementSchemeToken: The element() scheme XPointer expression contains the invalid token ''{0}''
+InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: The Element Scheme XPointer expression ''{0}'' is invalid.
+XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: An error occurred while processing the XPointer element() Scheme expression.
+InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: The element() Scheme contains a ShortHand Pointer ''{0}'' with an invalid NCName.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''. 
\ No newline at end of file
diff --git a/src/main/resources/org/python/apache/xerces/impl/validation/ConfigurableValidationState.class b/src/main/resources/org/python/apache/xerces/impl/validation/ConfigurableValidationState.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ebc7b039070e1a245ced2f86a25fa0467ab579b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/validation/ConfigurableValidationState.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/validation/EntityState.class b/src/main/resources/org/python/apache/xerces/impl/validation/EntityState.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d5df97a4563a127a0579d7efc9eca456d3af957
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/validation/EntityState.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/validation/ValidationManager.class b/src/main/resources/org/python/apache/xerces/impl/validation/ValidationManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad02f684c3f8853fac83a96582066bcd37dd01ed
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/validation/ValidationManager.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/validation/ValidationState.class b/src/main/resources/org/python/apache/xerces/impl/validation/ValidationState.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6d9d516891855153255e330be79a28d96726408
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/validation/ValidationState.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$1.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5dfdca70abb4d759a3eab3730a9ea5949e6c0f4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Axis.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Axis.class
new file mode 100644
index 0000000000000000000000000000000000000000..a352d036c1fb9026710a82cef2d876ff1cbf40e9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Axis.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$LocationPath.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$LocationPath.class
new file mode 100644
index 0000000000000000000000000000000000000000..38bac66a5ec80953d86acfe37d5e9691ec6b9e4f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$LocationPath.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$NodeTest.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$NodeTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4508f993d605db6d4b24f6249a66a4726fef9cb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$NodeTest.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Scanner.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Scanner.class
new file mode 100644
index 0000000000000000000000000000000000000000..e706aab76db2a9165ae1a8f73d8f0fc9373ba4a2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Scanner.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Step.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Step.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8865bc1b00da2550e522007a5c58422ba8a0df2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Step.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Tokens.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Tokens.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5df6154a2f4b1a7035ddae53044b4b7430c97fb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath$Tokens.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPath.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath.class
new file mode 100644
index 0000000000000000000000000000000000000000..6db0abdccd6b3ce3afc4d01954c1df3ba81901e2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPath.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/XPathException.class b/src/main/resources/org/python/apache/xerces/impl/xpath/XPathException.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b76390b829f6ae3cb647b6878a7633d5122d983
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/XPathException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/BMPattern.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/BMPattern.class
new file mode 100644
index 0000000000000000000000000000000000000000..13f46acd238ad238835de92a61a7386b4cb7486d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/BMPattern.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/CaseInsensitiveMap.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/CaseInsensitiveMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..a22f0d813a42f6c9103428760e121566d4a97570
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/CaseInsensitiveMap.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Match.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Match.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa48ba3af727f7a4a342bbfbf644f807d62c029c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Match.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$CharOp.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$CharOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7adbcdf8050e66e8ef93c898ae8173bd39dfbb7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$CharOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ChildOp.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ChildOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..d593f1adf2c7cce940b78b6774ae5a9f51a3df9f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ChildOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ConditionOp.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ConditionOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9f0ca92bef9fa8ae3092afe22f1105c4c79b87d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ConditionOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ModifierOp.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ModifierOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..2aab7acf4e8ef6c55807ecad5b9ab2ac48e4d657
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$ModifierOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$RangeOp.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$RangeOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..703b2415fdf2134181bb3940714c9be9526fcccf
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$RangeOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$StringOp.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$StringOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ceb35431085b323e0847b50e0560d3c3a3a6c10
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$StringOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$UnionOp.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$UnionOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..b89e9e3df85e4ddc50fe86ce164c90079abc89d2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op$UnionOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0b970429a6e9632529431d50ac428799c32988e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Op.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/ParseException.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/ParseException.class
new file mode 100644
index 0000000000000000000000000000000000000000..3657228452dc9fca5a21007adca6a4bd154a7be5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/ParseException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/ParserForXMLSchema.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/ParserForXMLSchema.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7015543954cfe86dd47308cd0d3256784829f11
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/ParserForXMLSchema.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/REUtil.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/REUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcf74ed8b73f96b103c051d576ab735be5ad5cce
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/REUtil.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RangeToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RangeToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..397e6438cd43a5feef7f03f0ee97e2243a36366a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RangeToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegexParser$ReferencePosition.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegexParser$ReferencePosition.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbee5312d62d4a35e1b5e1ee2a4c89aa44fece5c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegexParser$ReferencePosition.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegexParser.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegexParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..bff5bf7bfca168b8ba9d8152d08e41ffa1857a90
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegexParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$CharArrayTarget.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$CharArrayTarget.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0549c1bbfb8d8bafe9ecec6b2380d7c46ccefb5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$CharArrayTarget.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$CharacterIteratorTarget.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$CharacterIteratorTarget.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e05f16f04f73db489b29f99cf6ac2eaeff66aa4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$CharacterIteratorTarget.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$ClosureContext.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$ClosureContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..74f8e07c094469e5bbc3f0e7624db4baee29f6c0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$ClosureContext.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$Context.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$Context.class
new file mode 100644
index 0000000000000000000000000000000000000000..afb2eef4a9d9f81f753027e4c87103f20ae81384
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$Context.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$ExpressionTarget.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$ExpressionTarget.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b86dd2e63ebdbc89212bd839d153adb3819a739
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$ExpressionTarget.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$StringTarget.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$StringTarget.class
new file mode 100644
index 0000000000000000000000000000000000000000..00bff61c519b28d745af6d8728d7aa4a2be1b627
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression$StringTarget.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression.class
new file mode 100644
index 0000000000000000000000000000000000000000..cffc362d156f63c161c9137f4234835f356a9f44
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/RegularExpression.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$CharToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$CharToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..21e7d10dbccc56b467a700806fd62d93058a40f1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$CharToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ClosureToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ClosureToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce0aab5c01f9b12c82ea124cad1c058ebb3c9a40
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ClosureToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ConcatToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ConcatToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..6bd00b4e5a9fccd992b9e1c9bf58ff28d2675970
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ConcatToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ConditionToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ConditionToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..7cc449987f2fe6bc3b44f802f10d27ac99af3d8f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ConditionToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$FixedStringContainer.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$FixedStringContainer.class
new file mode 100644
index 0000000000000000000000000000000000000000..88d87ab0abf0a48befa98f3f736e02dfce076df8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$FixedStringContainer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ModifierToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ModifierToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fdb6e83e64067a93ce13b8817501d71183b58dc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ModifierToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ParenToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ParenToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..7284a06bdb72d46a6bc643063114964a749333e2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$ParenToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$StringToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$StringToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..368cdb14e27ed5a8936d3d28bb776c378cfeda6b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$StringToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$UnionToken.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$UnionToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..8002ad5d1da935e2206ca82b5c0a3cf507df9bb9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token$UnionToken.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token.class b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac60c39ead176d83f299a4078e086013d027a211
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/Token.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message.properties b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message.properties
new file mode 100644
index 0000000000000000000000000000000000000000..ee5d50d491b9ed1e5f4f36ec3e79dd9a1897c928
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message.properties
@@ -0,0 +1,58 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# @version $Id: message.properties 595212 2007-11-15 05:28:57Z mrglavas $
+
+parser.parse.1=Wrong character.
+parser.parse.2=Invalid reference number.
+parser.next.1=A character is required after \\.
+parser.next.2='?' is not expected.  '(?:' or '(?=' or '(?!' or '(?<' or '(?#' or '(?>'?
+parser.next.3='(?<=' or '(?<!' is expected.
+parser.next.4=A comment is not terminated.
+parser.factor.1=')' is expected.
+parser.factor.2=Unexpected end of the pattern in a modifier group.
+parser.factor.3=':' is expected.
+parser.factor.4=Unexpected end of the pattern in a conditional group.
+parser.factor.5=A back reference or an anchor or a lookahead or a lookbehind is expected in a conditional pattern.
+parser.factor.6=There are more than three choices in a conditional group.
+parser.atom.1=A character in U+0040-U+005f must follow \\c.
+parser.atom.2=A '{' is required before a character category.
+parser.atom.3=A property name is not closed by '}'.
+parser.atom.4=Unexpected meta character.
+parser.atom.5=Unknown property.
+parser.cc.1=A POSIX character class must be closed by ':]'.
+parser.cc.2=Unexpected end of the pattern in a character class.
+parser.cc.3=Unknown name for a POSIX character class.
+parser.cc.4='-' is invalid here.
+parser.cc.5=']' is expected.
+parser.cc.6='[' is invalid in a character class.  Write '\\['.
+parser.cc.7=']' is invalid in a character class.  Write '\\]'.
+parser.cc.8='-' is an invalid character range. Write '\\-'.
+parser.ope.1='[' is expected.
+parser.ope.2=')' or '-[' or '+[' or '&[' is expected.
+parser.ope.3=The range end code point is less than the start code point.
+parser.descape.1=Invalid Unicode hex notation.
+parser.descape.2=Overflow in a hex notation.
+parser.descape.3='\\x{' must be closed by '}'.
+parser.descape.4=Invalid Unicode code point.
+parser.descape.5=An anchor must not be here.
+parser.process.1=This expression is not supported in the current option setting.
+parser.quantifier.1=Invalid quantifier. A digit is expected.
+parser.quantifier.2=Invalid quantifier. Invalid quantity or a '}' is missing.
+parser.quantifier.3=Invalid quantifier. A digit or '}' is expected.
+parser.quantifier.4=Invalid quantifier. A min quantity must be <= a max quantity.
+parser.quantifier.5=Invalid quantifier. A quantity value overflow.
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_en.properties b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..ee5d50d491b9ed1e5f4f36ec3e79dd9a1897c928
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_en.properties
@@ -0,0 +1,58 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# @version $Id: message.properties 595212 2007-11-15 05:28:57Z mrglavas $
+
+parser.parse.1=Wrong character.
+parser.parse.2=Invalid reference number.
+parser.next.1=A character is required after \\.
+parser.next.2='?' is not expected.  '(?:' or '(?=' or '(?!' or '(?<' or '(?#' or '(?>'?
+parser.next.3='(?<=' or '(?<!' is expected.
+parser.next.4=A comment is not terminated.
+parser.factor.1=')' is expected.
+parser.factor.2=Unexpected end of the pattern in a modifier group.
+parser.factor.3=':' is expected.
+parser.factor.4=Unexpected end of the pattern in a conditional group.
+parser.factor.5=A back reference or an anchor or a lookahead or a lookbehind is expected in a conditional pattern.
+parser.factor.6=There are more than three choices in a conditional group.
+parser.atom.1=A character in U+0040-U+005f must follow \\c.
+parser.atom.2=A '{' is required before a character category.
+parser.atom.3=A property name is not closed by '}'.
+parser.atom.4=Unexpected meta character.
+parser.atom.5=Unknown property.
+parser.cc.1=A POSIX character class must be closed by ':]'.
+parser.cc.2=Unexpected end of the pattern in a character class.
+parser.cc.3=Unknown name for a POSIX character class.
+parser.cc.4='-' is invalid here.
+parser.cc.5=']' is expected.
+parser.cc.6='[' is invalid in a character class.  Write '\\['.
+parser.cc.7=']' is invalid in a character class.  Write '\\]'.
+parser.cc.8='-' is an invalid character range. Write '\\-'.
+parser.ope.1='[' is expected.
+parser.ope.2=')' or '-[' or '+[' or '&[' is expected.
+parser.ope.3=The range end code point is less than the start code point.
+parser.descape.1=Invalid Unicode hex notation.
+parser.descape.2=Overflow in a hex notation.
+parser.descape.3='\\x{' must be closed by '}'.
+parser.descape.4=Invalid Unicode code point.
+parser.descape.5=An anchor must not be here.
+parser.process.1=This expression is not supported in the current option setting.
+parser.quantifier.1=Invalid quantifier. A digit is expected.
+parser.quantifier.2=Invalid quantifier. Invalid quantity or a '}' is missing.
+parser.quantifier.3=Invalid quantifier. A digit or '}' is expected.
+parser.quantifier.4=Invalid quantifier. A min quantity must be <= a max quantity.
+parser.quantifier.5=Invalid quantifier. A quantity value overflow.
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_fr.properties b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_fr.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6c1e84029e3b91d087a3030c55dd3db242c531f2
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_fr.properties
@@ -0,0 +1,58 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# @version $Id: message_fr.properties 595212 2007-11-15 05:28:57Z mrglavas $
+
+parser.parse.1=Caract\u00e8re erron\u00e9.
+parser.parse.2=Num\u00e9ro de r\u00e9f\u00e9rence non valide.
+parser.next.1=Un caract\u00e8re est requis apr\u00e8s \\.
+parser.next.2='?' n'est pas attendu.  '(?:', '(?=', '(?!', '(?<', '(?#', '(?>'?
+parser.next.3='(?<=' ou '(?<!' est attendu.
+parser.next.4=Commentaire sans caract\u00e8re de terminaison.
+parser.factor.1=')' attendu.
+parser.factor.2=Fin du mod\u00e8le attendue dans un groupe de modificateurs.
+parser.factor.3=':' attendu.
+parser.factor.4=Fin du mod\u00e8le inattendue dans un groupe conditionnel.
+parser.factor.5=Un mod\u00e8le conditionnel doit contenir un renvoi, une ancre, une lecture anticip\u00e9e ou une lecture diff\u00e9r\u00e9e.
+parser.factor.6=Un groupe conditionnel comporte plus de trois choix.
+parser.atom.1=Un caract\u00e8re de U+0040-U+005f doit suivre \\c.
+parser.atom.2=Une accolade ('{') est obligatoire devant une cat\u00e9gorie de caract\u00e8res.
+parser.atom.3=Un nom de propri\u00e9t\u00e9 n'est pas ferm\u00e9 par '}'.
+parser.atom.4=M\u00e9ta-caract\u00e8re inattendu.
+parser.atom.5=Propri\u00e9t\u00e9 inconnue.
+parser.cc.1=Une classe de caract\u00e8res POSIX doit \u00eatre ferm\u00e9e par ':]'.
+parser.cc.2=Fin du mod\u00e8le inattendue dans une classe de caract\u00e8res.
+parser.cc.3=Nom inconnu pour une classe de caract\u00e8res POSIX.
+parser.cc.4='-' n'est pas valide ici.
+parser.cc.5=']' est attendu.
+parser.cc.6='[' n'est pas valide dans une classe de caract\u00e8res.  Ecrire '\\['.
+parser.cc.7=']' n'est pas valide dans une classe de caract\u00e8res.  Ecrire '\\['.
+parser.cc.8='-' n'est pas valide dans un intervalle de caract\u00e8res. Ecrire '\\-'.
+parser.ope.1='[' est attendu.
+parser.ope.2=')', '-[', '+[' ou '&[' est attendu.
+parser.ope.3=Le point de code final doit \u00eatre inf\u00e9rieur au point de code initial dans l'intervalle.
+parser.descape.1=Notation hexad\u00e9cimale Unicode non valide.
+parser.descape.2=D\u00e9passement d'une notation hexad\u00e9cimale.
+parser.descape.3='\\x{' doit \u00eatre ferm\u00e9 par '}'.
+parser.descape.4=Point de code Unicode non valide.
+parser.descape.5=Une ancre ne doit pas figurer ici.
+parser.process.1=Cette expression n'est pas prise en charge dans le param\u00e8tre d'option courant.
+parser.quantifier.1=Quantifieur non valide. Valeur num\u00e9rique requise.
+parser.quantifier.2=Quantifieur non valide. Quantit\u00e9 non valide ou '}' manquant.
+parser.quantifier.3=Quantifieur non valide. Nombre ou '}' obligatoire.
+parser.quantifier.4=Quantifieur non valide. Une quantit\u00e9 minimale doit \u00eatre <= \u00e0 une quantit\u00e9 maximale.
+parser.quantifier.5=Quantifieur non valide. D\u00e9passement de quantit\u00e9.
diff --git a/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_ja.properties b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_ja.properties
new file mode 100644
index 0000000000000000000000000000000000000000..043e5fa66682b67d20a51f9a0508ae0adbdfa2ab
--- /dev/null
+++ b/src/main/resources/org/python/apache/xerces/impl/xpath/regex/message_ja.properties
@@ -0,0 +1,58 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# @version $Id: message_ja.properties 595212 2007-11-15 05:28:57Z mrglavas $
+
+parser.parse.1=\u4e0d\u5f53\u306a\u6587\u5b57\u3002
+parser.parse.2=\u7121\u52b9\u306a\u53c2\u7167\u756a\u53f7\u3002
+parser.next.1=\\ \u306e\u5f8c\u306b\u6587\u5b57\u304c\u5fc5\u8981\u3067\u3059\u3002
+parser.next.2='?' \u306f\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002'(?:' \u307e\u305f\u306f '(?=' \u307e\u305f\u306f '(?!' \u307e\u305f\u306f '(?<' \u307e\u305f\u306f '(?#' \u307e\u305f\u306f '(?>'?
+parser.next.3='(?<=' \u307e\u305f\u306f '(?<!' \u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.next.4=\u30b3\u30e1\u30f3\u30c8\u304c\u7d42\u7d50\u3057\u3066\u3044\u307e\u305b\u3093\u3002
+parser.factor.1=')' \u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.factor.2=\u4fee\u98fe\u5b50\u30b0\u30eb\u30fc\u30d7\u5185\u3067\u30d1\u30bf\u30fc\u30f3\u306e\u4e88\u671f\u3057\u306a\u3044\u7d42\u4e86\u3002
+parser.factor.3=':' \u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.factor.4=\u6761\u4ef6\u4ed8\u304d\u30b0\u30eb\u30fc\u30d7\u5185\u3067\u30d1\u30bf\u30fc\u30f3\u306e\u4e88\u671f\u3057\u306a\u3044\u7d42\u4e86\u3002
+parser.factor.5=\u6761\u4ef6\u4ed8\u304d\u30d1\u30bf\u30fc\u30f3\u3067\u306f\u9006\u53c2\u7167\u307e\u305f\u306f\u30a2\u30f3\u30ab\u30fc\u307e\u305f\u306f\u5148\u8aad\u307f\u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.factor.6=\u6761\u4ef6\u4ed8\u304d\u30b0\u30eb\u30fc\u30d7\u306b 3 \u3064\u3092\u8d85\u3048\u308b\u9078\u629e\u9805\u76ee\u304c\u3042\u308a\u307e\u3059\u3002
+parser.atom.1=\u5f8c\u306b \\c \u304c\u5fc5\u8981\u306a\u6587\u5b57\u304c U+0040-U+005f \u306b\u3042\u308a\u307e\u3059\u3002
+parser.atom.2=\u6587\u5b57\u30ab\u30c6\u30b4\u30ea\u30fc\u306e\u524d\u306b '{' \u304c\u5fc5\u8981\u3067\u3059\u3002
+parser.atom.3=\u30d7\u30ed\u30d1\u30c6\u30a3\u30fc\u540d\u304c '}' \u3067\u9589\u3058\u3089\u308c\u3066\u3044\u307e\u305b\u3093\u3002
+parser.atom.4=\u4e88\u671f\u3057\u306a\u3044\u30e1\u30bf\u6587\u5b57\u3002
+parser.atom.5=\u4e0d\u660e\u306a\u30d7\u30ed\u30d1\u30c6\u30a3\u30fc\u3002
+parser.cc.1=POSIX \u6587\u5b57\u30af\u30e9\u30b9\u306f ':]' \u3067\u9589\u3058\u3089\u308c\u3066\u3044\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+parser.cc.2=\u6587\u5b57\u30af\u30e9\u30b9\u5185\u3067\u30d1\u30bf\u30fc\u30f3\u306e\u4e88\u671f\u3057\u306a\u3044\u7d42\u4e86\u3002
+parser.cc.3=POSIX \u6587\u5b57\u30af\u30e9\u30b9\u306e\u540d\u524d\u304c\u4e0d\u660e\u3067\u3059\u3002
+parser.cc.4='-' \u306f\u3053\u3053\u3067\u306f\u7121\u52b9\u3067\u3059\u3002
+parser.cc.5=']' \u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.cc.6='[' \u306f\u6587\u5b57\u30af\u30e9\u30b9\u5185\u3067\u306f\u7121\u52b9\u3067\u3059\u3002'\\[' \u3068\u66f8\u3044\u3066\u304f\u3060\u3055\u3044\u3002
+parser.cc.7=']' \u306f\u6587\u5b57\u30af\u30e9\u30b9\u5185\u3067\u306f\u7121\u52b9\u3067\u3059\u3002'\\]' \u3068\u66f8\u3044\u3066\u304f\u3060\u3055\u3044\u3002
+parser.cc.8='-' \u306f\u7121\u52b9\u306a\u6587\u5b57\u7bc4\u56f2\u3067\u3059\u3002'\\-' \u3068\u66f8\u3044\u3066\u304f\u3060\u3055\u3044\u3002
+parser.ope.1='[' \u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.ope.2=')' \u307e\u305f\u306f '-[' \u307e\u305f\u306f '+[' \u307e\u305f\u306f '&[' \u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.ope.3=\u7bc4\u56f2\u7d42\u4e86\u30b3\u30fc\u30c9\u30fb\u30dd\u30a4\u30f3\u30c8\u304c\u958b\u59cb\u30b3\u30fc\u30c9\u30fb\u30dd\u30a4\u30f3\u30c8\u3088\u308a\u5c0f\u3055\u3044\u5024\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002
+parser.descape.1=\u7121\u52b9\u306a Unicode 16 \u9032\u8868\u8a18\u3002
+parser.descape.2=16 \u9032\u8868\u8a18\u3067\u30aa\u30fc\u30d0\u30fc\u30d5\u30ed\u30fc\u3002
+parser.descape.3='\\x{' \u306f '}' \u3067\u9589\u3058\u3089\u308c\u3066\u3044\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+parser.descape.4=\u7121\u52b9\u306a Unicode \u30b3\u30fc\u30c9\u30fb\u30dd\u30a4\u30f3\u30c8\u3002
+parser.descape.5=\u3053\u3053\u306b\u30a2\u30f3\u30ab\u30fc\u304c\u3042\u3063\u3066\u306f\u306a\u308a\u307e\u305b\u3093\u3002
+parser.process.1=\u3053\u306e\u5f0f\u306f\u73fe\u5728\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u8a2d\u5b9a\u3067\u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u307e\u305b\u3093\u3002
+parser.quantifier.1=\u6570\u91cf\u8a5e\u304c\u7121\u52b9\u3067\u3059\u3002\u6570\u5b57\u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.quantifier.2=\u6570\u91cf\u8a5e\u304c\u7121\u52b9\u3067\u3059\u3002\u6570\u91cf\u304c\u7121\u52b9\u304b\u3001\u307e\u305f\u306f '}' \u304c\u3042\u308a\u307e\u305b\u3093\u3002
+parser.quantifier.3=\u6570\u91cf\u8a5e\u304c\u7121\u52b9\u3067\u3059\u3002\u6570\u5b57\u307e\u305f\u306f '}' \u304c\u671f\u5f85\u3055\u308c\u3066\u3044\u307e\u3059\u3002
+parser.quantifier.4=\u6570\u91cf\u8a5e\u304c\u7121\u52b9\u3067\u3059\u3002\u6700\u5c0f\u6570\u91cf\u306f\u6700\u5927\u6570\u91cf\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+parser.quantifier.5=\u6570\u91cf\u8a5e\u304c\u7121\u52b9\u3067\u3059\u3002\u6570\u91cf\u5024\u304c\u30aa\u30fc\u30d0\u30fc\u30d5\u30ed\u30fc\u3057\u3066\u3044\u307e\u3059\u3002
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/AttributePSVImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/AttributePSVImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..21e7816ba807102e42efceed1e3c5c53fb9deabc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/AttributePSVImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/ElementPSVImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/ElementPSVImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..355cd14ad172a0997491f8a49e37d6a6539f1c38
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/ElementPSVImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/FilePathToURI.class b/src/main/resources/org/python/apache/xerces/impl/xs/FilePathToURI.class
new file mode 100644
index 0000000000000000000000000000000000000000..98e1f62f38a52ea4e78e00439f68a6974309eba4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/FilePathToURI.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/PSVIErrorList.class b/src/main/resources/org/python/apache/xerces/impl/xs/PSVIErrorList.class
new file mode 100644
index 0000000000000000000000000000000000000000..951203d375d04dfd9b98323a5eb4241b13aff8e1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/PSVIErrorList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$BuiltinAttrDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$BuiltinAttrDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..911b5a5dc700fa63bf25f9fd10b8b7b42272a9a8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$BuiltinAttrDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$BuiltinSchemaGrammar.class b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$BuiltinSchemaGrammar.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bacf0e703942a596fea7fc31e56cd4980e3d163
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$BuiltinSchemaGrammar.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$Schema4Annotations.class b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$Schema4Annotations.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee2861222ecfa3a0de9c251164e3d7888bb21007
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$Schema4Annotations.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$XSAnyType.class b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$XSAnyType.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6de9989e881644a9e4a5cf27127349f138fb02e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar$XSAnyType.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar.class b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar.class
new file mode 100644
index 0000000000000000000000000000000000000000..e636bf5c6ae83572cde2b363af315fd44642303b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaGrammar.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SchemaNamespaceSupport$SchemaRootContext.class b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaNamespaceSupport$SchemaRootContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ae32d96c2b4935dee9ddd2ed538b1d66dc40b11
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaNamespaceSupport$SchemaRootContext.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SchemaNamespaceSupport.class b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaNamespaceSupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..44b19584cc5021c16d5be89f27c6599d196008b0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaNamespaceSupport.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SchemaSymbols.class b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaSymbols.class
new file mode 100644
index 0000000000000000000000000000000000000000..2899a31620fe89e443dbef5f2c93d1974e312239
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SchemaSymbols.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SubstitutionGroupHandler$OneSubGroup.class b/src/main/resources/org/python/apache/xerces/impl/xs/SubstitutionGroupHandler$OneSubGroup.class
new file mode 100644
index 0000000000000000000000000000000000000000..d13b4e4d68d826dcd5b0e317b4519d962c4a4412
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SubstitutionGroupHandler$OneSubGroup.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/SubstitutionGroupHandler.class b/src/main/resources/org/python/apache/xerces/impl/xs/SubstitutionGroupHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..e787defd4ae52ddb6e4438b15b6679e820fd23ee
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/SubstitutionGroupHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaException.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaException.class
new file mode 100644
index 0000000000000000000000000000000000000000..52bed19ce36b23f788b70a2dd0d8fbe2095f68d8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaLoader$LocationArray.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaLoader$LocationArray.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ba32356238c01ef4a0041e2e486e4028d935b56
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaLoader$LocationArray.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaLoader.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a9b39498aa8876c9bf581a7d9ff72a81b017ff1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaLoader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$KeyRefValueStore.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$KeyRefValueStore.class
new file mode 100644
index 0000000000000000000000000000000000000000..bee71650b32679d81f9e514fae020176cd30d25a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$KeyRefValueStore.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$KeyValueStore.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$KeyValueStore.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f42ba9dec1334ccc4c92d7b75270f451d384331
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$KeyValueStore.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$LocalIDKey.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$LocalIDKey.class
new file mode 100644
index 0000000000000000000000000000000000000000..e50872b4a3118f9c7c0ad97c9d2bbcf5dc470aa7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$LocalIDKey.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ShortVector.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ShortVector.class
new file mode 100644
index 0000000000000000000000000000000000000000..c96cc62c6cc0f5b26d6e704e62f47d573edacb70
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ShortVector.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$UniqueValueStore.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$UniqueValueStore.class
new file mode 100644
index 0000000000000000000000000000000000000000..30f1113aa724a531f96b9eecdd1fc1fa8ed375cc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$UniqueValueStore.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ValueStoreBase.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ValueStoreBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..28874d71a06af5235e43451bc57fffa16942be2a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ValueStoreBase.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ValueStoreCache.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ValueStoreCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..797fbeb4a448890bee0128382fbeb72b9edde8c4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$ValueStoreCache.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$XPathMatcherStack.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$XPathMatcherStack.class
new file mode 100644
index 0000000000000000000000000000000000000000..c02f55f38f24c33e29066d205a098de74e7fe488
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$XPathMatcherStack.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$XSIErrorReporter.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$XSIErrorReporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..44aecf686ea37f45c4ced79c7b00399f92372848
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator$XSIErrorReporter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator.class b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8061a7a4e111ee4784e082e9af168ce02864831
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XMLSchemaValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSAnnotationImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSAnnotationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..4838439737ac305241bdc79b1931b3347468ec12
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSAnnotationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..609a8233a43cecf31ccad372271cedf967de73e9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeGroupDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeGroupDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..af19368c35f9357a723fc81a18c62f1df62efff9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeGroupDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeUseImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeUseImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8989d8deb69f5a9638620f5a5ddc07e7e57770ff
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSAttributeUseImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSComplexTypeDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSComplexTypeDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a261a3d785a3c88618834eed2ab38addfc08d7d9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSComplexTypeDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSConstraints$1.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSConstraints$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..24118f55d7e786019cca3e6e7c5899814d785ef1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSConstraints$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSConstraints.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSConstraints.class
new file mode 100644
index 0000000000000000000000000000000000000000..0486814ea9309980991fc3671ecf8cce399088ba
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSConstraints.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSDDescription.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSDDescription.class
new file mode 100644
index 0000000000000000000000000000000000000000..31ba36faf6ef26bf0a5c935c73b2bcfca70fbc38
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSDDescription.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSDeclarationPool.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSDeclarationPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b41031fd9af803b3b5f08e7a24e5cfccf2a9996
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSDeclarationPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSElementDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSElementDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6725583640aff37071edfe65ad656f4fba8e3678
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSElementDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSElementDeclHelper.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSElementDeclHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..dddc0fd5caa4e6cab5fdfd27b6a70a3ce9482b1f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSElementDeclHelper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSGrammarBucket.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSGrammarBucket.class
new file mode 100644
index 0000000000000000000000000000000000000000..710675ddc35aec1bc5820b224c25d9fe02dfd8ff
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSGrammarBucket.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSGroupDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSGroupDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b93f1e4391803ff417cff6629ce84e3b122da9eb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSGroupDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSImplementationImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSImplementationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..f910c9ec09763ba0cd35f0f6118bcce2f5dc8abe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSImplementationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSLoaderImpl$XSGrammarMerger.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSLoaderImpl$XSGrammarMerger.class
new file mode 100644
index 0000000000000000000000000000000000000000..0745d362a0b95a7fdbc9ba69a3da4a331d691e9c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSLoaderImpl$XSGrammarMerger.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSLoaderImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSLoaderImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..81556725e6711474e01245294cf3b780ab376c52
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSLoaderImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSMessageFormatter.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSMessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2c5a194494f79160bfd5ae8740c0d08893b8685
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSMessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSModelGroupImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSModelGroupImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..11c5e288ed6756ea029314ea26e099b46d86d139
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSModelGroupImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSModelImpl$XSNamespaceItemListIterator.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSModelImpl$XSNamespaceItemListIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..2455b94ece9f5623a211860791eda8fc5992069b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSModelImpl$XSNamespaceItemListIterator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSModelImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSModelImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5beeb7da4390df1ca2c8647cca88d5111609b08
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSModelImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSNotationDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSNotationDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b23b5206902f82b23efaf10a0c18954cb676b90
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSNotationDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSParticleDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSParticleDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee2c2d5f6cb959a63463648f5b6b5341984d3e87
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSParticleDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/XSWildcardDecl.class b/src/main/resources/org/python/apache/xerces/impl/xs/XSWildcardDecl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3533692ce88a087d9a44386c9de3d6389e31af13
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/XSWildcardDecl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field$Matcher.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field$Matcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..47b333798feaa3a818b5c06c658f8c50d0c2927c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field$Matcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field$XPath.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field$XPath.class
new file mode 100644
index 0000000000000000000000000000000000000000..7301b16e49591a0eeadd0bcc88a037ce20c139e0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field$XPath.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field.class
new file mode 100644
index 0000000000000000000000000000000000000000..5310f8f27cd64dedc8ca4e866a59ddc2b9410175
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Field.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/FieldActivator.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/FieldActivator.class
new file mode 100644
index 0000000000000000000000000000000000000000..344b6fba8477d7f20ae0f40ec370c3ce75083208
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/FieldActivator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/IdentityConstraint.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/IdentityConstraint.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c48c9baffc002a0189ac60d2f5993b68bdfa3ac
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/IdentityConstraint.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/KeyRef.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/KeyRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..be20c4959bbbb9fa24d673bf87246f06073ea5eb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/KeyRef.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector$Matcher.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector$Matcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..10a652b0e63c55de7f8c5c8d4c6b48d0015f19e3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector$Matcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector$XPath.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector$XPath.class
new file mode 100644
index 0000000000000000000000000000000000000000..21620dda894c04bc5ff787886b57e1569076b095
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector$XPath.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector.class
new file mode 100644
index 0000000000000000000000000000000000000000..1cd5bbbcc4ea44dfcf970f29c33ba47d5e0d8a85
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/Selector.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/UniqueOrKey.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/UniqueOrKey.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c3c70209d0e0f7c4fdfe90dc3d836375e445239
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/UniqueOrKey.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/ValueStore.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/ValueStore.class
new file mode 100644
index 0000000000000000000000000000000000000000..995f292c81c0fb3c562b5ecc18c4263257cf427b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/ValueStore.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/identity/XPathMatcher.class b/src/main/resources/org/python/apache/xerces/impl/xs/identity/XPathMatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..6329c5e9f5ddf0f96866cdfd4bd3106f3e0ed1eb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/identity/XPathMatcher.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/CMBuilder.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/CMBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..8804eca7b13b5425ae3455b9adf2533e9707b8e8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/CMBuilder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/CMNodeFactory.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/CMNodeFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..43152f395de81bcfa28ef8d3cd539bb017d52ffa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/CMNodeFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSAllCM.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSAllCM.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7cbd230dbd167b3ece4f2b0d131f0dcd3e255d0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSAllCM.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMBinOp.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMBinOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..5534fde7fd5474049f6dd548a9fd2fcbdc54bc11
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMBinOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMLeaf.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMLeaf.class
new file mode 100644
index 0000000000000000000000000000000000000000..4490b66295f7151ec1295cf530d712c021b84e3b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMLeaf.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMRepeatingLeaf.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMRepeatingLeaf.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a08d6ebb67110434b1751e805f0efb39549593f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMRepeatingLeaf.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMUniOp.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMUniOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..b35b296ff2c1af952aca228784319e8f2e37aa74
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMUniOp.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMValidator.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMValidator.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a6bb350f4e706e21beeddb10a58d0bbc7142ced
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSCMValidator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSDFACM$Occurence.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSDFACM$Occurence.class
new file mode 100644
index 0000000000000000000000000000000000000000..d79190300e93ea114ef01e8bf2a39c9e5b4424d9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSDFACM$Occurence.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSDFACM.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSDFACM.class
new file mode 100644
index 0000000000000000000000000000000000000000..cbd9c91f750e98c062b7a8f205647bb1697d0955
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSDFACM.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/models/XSEmptyCM.class b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSEmptyCM.class
new file mode 100644
index 0000000000000000000000000000000000000000..286ce747cfa901d74bf6a73e5c94848688567db3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/models/XSEmptyCM.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/AttrImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/AttrImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e4c747b67a7c51ddf6973a81cc4ca96b9e52937
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/AttrImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultDocument.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultDocument.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc6cd458b863d703098ec80916cfd7539c7f4231
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultDocument.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultElement.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7baf6386a4ac1507eeac64abbcf9ab53a05cc75
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultElement.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultNode.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b73e0169e5a4c1f753234f74d55044a12201b28
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultNode.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultText.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultText.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a618d1c7ab56dc178a853a69b0a6d99a0b33e19
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultText.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultXMLDocumentHandler.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultXMLDocumentHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..61262b42301299e1dd0040d8753cb0c44b5bb393
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/DefaultXMLDocumentHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/ElementImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/ElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..849388af2e7f8ee4eebe2dc338828e42ea80cb8c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/ElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/NamedNodeMapImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/NamedNodeMapImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a08382b3e799df9ed07f4c4e0352646fd0f718c9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/NamedNodeMapImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/NodeImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/NodeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b52f4c60d3dd037d260c65a698a8ac5f77db58bb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/NodeImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOM.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOM.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb1ed6ba6c529e1d0a429ba0206a3f542513a006
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOM.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMImplementation.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMImplementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd5fe10b590c9cf5c5461b7aedb2ab9035de0b9c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMImplementation.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMParser$BooleanStack.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMParser$BooleanStack.class
new file mode 100644
index 0000000000000000000000000000000000000000..284f97a84036a5d2c4180e3e5a9d81043ae20504
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMParser$BooleanStack.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMParser.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc41da398f2a9b2dab5f548377385653af184a5c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaDOMParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaParsingConfig.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaParsingConfig.class
new file mode 100644
index 0000000000000000000000000000000000000000..954ca8e54a873d2839c8a2bea1fe68fe5a38c9cd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/SchemaParsingConfig.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/opti/TextImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/opti/TextImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e00e0c6f7b2877de291f62b3bbebfaf26bc60593
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/opti/TextImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/Container.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/Container.class
new file mode 100644
index 0000000000000000000000000000000000000000..58a50851addab6fcca7dddfe5adcbae980fd39ee
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/Container.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/LargeContainer.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/LargeContainer.class
new file mode 100644
index 0000000000000000000000000000000000000000..54d71ac1d3e311c5f1ad17e92ef8b58962628828
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/LargeContainer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/OneAttr.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/OneAttr.class
new file mode 100644
index 0000000000000000000000000000000000000000..3129e7c064975921d7e3e5c433e5aebbc951c509
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/OneAttr.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/SchemaContentHandler.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/SchemaContentHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..f42ae444ed7e24b091af69ed96e58d26c44496d4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/SchemaContentHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/SmallContainer.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/SmallContainer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c902cbe7555477cedfdb1e270bf8895404293d32
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/SmallContainer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/StAXSchemaParser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/StAXSchemaParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb552514f9e10fffa62e2155ca3b16cb2156726a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/StAXSchemaParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSAnnotationInfo.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSAnnotationInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ce511185ced007c5f2884e1b12b388731b3b7ca
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSAnnotationInfo.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSAttributeChecker.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSAttributeChecker.class
new file mode 100644
index 0000000000000000000000000000000000000000..86e9418d1cb028ab348e55f68d2e65029e953139
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSAttributeChecker.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractIDConstraintTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractIDConstraintTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..99fddf1791ec4763d06898e9fa034dccd3be6fcf
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractIDConstraintTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractParticleTraverser$ParticleArray.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractParticleTraverser$ParticleArray.class
new file mode 100644
index 0000000000000000000000000000000000000000..44cbde3e2bb28a608b0573539bc1db2c2c3bdc33
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractParticleTraverser$ParticleArray.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractParticleTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractParticleTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0aec9f6fe003ffaaea417ccce88dda2769165a9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractParticleTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractTraverser$FacetInfo.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractTraverser$FacetInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..5234e8f429932a926f223f3557433a9563b68faa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractTraverser$FacetInfo.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..4620c4d4883cbf54137362447686d4872cf09b21
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAbstractTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAttributeGroupTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAttributeGroupTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..085d1271d325d15599d9fe0eaae30298959b1b7d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAttributeGroupTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAttributeTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAttributeTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..2341fc48f0ce4c5d527c741c11df77f233d34e7d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDAttributeTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDComplexTypeTraverser$ComplexTypeRecoverableError.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDComplexTypeTraverser$ComplexTypeRecoverableError.class
new file mode 100644
index 0000000000000000000000000000000000000000..6354eeac8b69677a96e8bc0cf99b1e4645ce8fe4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDComplexTypeTraverser$ComplexTypeRecoverableError.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDComplexTypeTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDComplexTypeTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..3da6cbca28f243f0996e50b3fe035de157964ce0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDComplexTypeTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDElementTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDElementTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..f143b12452a5209572145b2bac47a6118a96626b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDElementTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDGroupTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDGroupTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd5442d60f310b7a9cc8a526decd1a76878ccc9b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDGroupTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$1.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..262f2c6df6f81d717bf3da3ea1e538ba1ff32162
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$SAX2XNIUtil.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$SAX2XNIUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf7136f245e56a8ad769cb8b1b96d58d306b42a6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$SAX2XNIUtil.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$XSAnnotationGrammarPool.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$XSAnnotationGrammarPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..75a608fe98faae05ed8190dadea289ba6917fd1b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$XSAnnotationGrammarPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$XSDKey.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$XSDKey.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e61c6450d6150c4c2992d91300c2bb4fc9f93b1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler$XSDKey.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5e15797d7873e920664b66fe726cdefd59318fa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDKeyrefTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDKeyrefTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..1701aeebeca401f7e715a8fb437235143b8b9551
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDKeyrefTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDNotationTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDNotationTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..524bc799ccde72f7107b7a06fcc08c600579e3a8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDNotationTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDSimpleTypeTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDSimpleTypeTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..db8dd36771831be12106b5d08aefcd484816930d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDSimpleTypeTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDUniqueOrKeyTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDUniqueOrKeyTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..f37f3e99f7505db9697ddb2e32503f8f184fb350
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDUniqueOrKeyTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDWildcardTraverser.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDWildcardTraverser.class
new file mode 100644
index 0000000000000000000000000000000000000000..5661ddc60f956f8fd259d3679c32fec7b026bb3f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDWildcardTraverser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDocumentInfo.class b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDocumentInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b0b05fcc6a4371d52e61b081b896505a2759fad
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/traversers/XSDocumentInfo.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/LSInputListImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/LSInputListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5817fc00b9f59b0a8aeb6e1612cdf131d50ad349
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/LSInputListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/ObjectListImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/ObjectListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..53b10ddc4479e2d500c3d41a2aef0c563a55f44d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/ObjectListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/ShortListImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/ShortListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a95b62156aef1ed4abb7bbd30490b2d72907440e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/ShortListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/SimpleLocator.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/SimpleLocator.class
new file mode 100644
index 0000000000000000000000000000000000000000..abd1b1fe8e50f4133f0e03b762b743414bb0abaf
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/SimpleLocator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/StringListImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/StringListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..77b9a1c7fa03a0231b4d8ad378469f63f9722494
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/StringListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XInt.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XInt.class
new file mode 100644
index 0000000000000000000000000000000000000000..0213b6c5f3f37157d36c8c408bd2863870366957
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XInt.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XIntPool.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XIntPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..52bedfa3804fa6c7236a16d2ca840864dfa75485
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XIntPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSGrammarPool.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSGrammarPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..feaa6c379a26efdd1557202bd1493d3f948622c2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSGrammarPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSInputSource.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSInputSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..74279c6a4b5d797d1b9b5c847a90d069921b2bf0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSInputSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMap4Types.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMap4Types.class
new file mode 100644
index 0000000000000000000000000000000000000000..15299f52c7b1c750cbe12f1a8a2d8076b00c0dbc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMap4Types.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$1.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..135bf4706fad1e0bafdc96e3ec28b4ceec3cff6b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$2.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f027ea41d37492927df7675b6f867828be5784a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$2.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$XSNamedMapEntry.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$XSNamedMapEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..477876c1e7c1cf91d7e2443191f3c6c45def33df
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl$XSNamedMapEntry.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1667f7c06153f7b5ab75601f91848f6f57c1ed7b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSNamedMapImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl$1.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c13f80129ce62193d9bafee66096f2d7a3ea40d8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl$XSObjectListIterator.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl$XSObjectListIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..54320eac8e581211d1e4dc9c080f6d66307ed3b1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl$XSObjectListIterator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl.class b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d1cf3e08e1dbfc2d003c6099de2813ef8120158
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/impl/xs/util/XSObjectListImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/DefaultValidationErrorHandler.class b/src/main/resources/org/python/apache/xerces/jaxp/DefaultValidationErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..067a1eefd14c07f413b7038747f5d49c202b3a60
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/DefaultValidationErrorHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/DocumentBuilderFactoryImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/DocumentBuilderFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ead69e65b3a441085a0a1bdacbd2d47bf1226cb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/DocumentBuilderFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/DocumentBuilderImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/DocumentBuilderImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..948c891313fcdcd5839c5e98909cafe1a56649f7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/DocumentBuilderImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/JAXPConstants.class b/src/main/resources/org/python/apache/xerces/jaxp/JAXPConstants.class
new file mode 100644
index 0000000000000000000000000000000000000000..a223f412c11e3f6d9f3ae690bfd3f8f7e7bd679f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/JAXPConstants.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$1.class b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e18ef40ade41223b51ddd9969c949c0b81f75325
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$2.class b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..13e738fb021b9baef6128e16b058da54d49bfc00
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$2.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$3.class b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..5bd71f07feda13890f2e352aa046fb118fae4c3c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$3.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$DraconianErrorHandler.class b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$DraconianErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..cdbb159667501bb5c98573ba5d71fed1d4603bee
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$DraconianErrorHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$SAX2XNI.class b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$SAX2XNI.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ef406be4897bdd07ba0b532b948c95bb07e54dc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$SAX2XNI.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$XNI2SAX.class b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$XNI2SAX.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f93c5c2a08c3c54e386c4072759775837b88415
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent$XNI2SAX.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent.class b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent.class
new file mode 100644
index 0000000000000000000000000000000000000000..0433e076d97eb6d55e5f6da95351166ec101919c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/JAXPValidatorComponent.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/SAXParserFactoryImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/SAXParserFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e95135f38c751c4309d7cb8987cb8ceb49617977
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/SAXParserFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/SAXParserImpl$JAXPSAXParser.class b/src/main/resources/org/python/apache/xerces/jaxp/SAXParserImpl$JAXPSAXParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..b38ce9750b00215799b2ca84ce126297a832e4ee
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/SAXParserImpl$JAXPSAXParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/SAXParserImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/SAXParserImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e37244b227efb9b76507b95c06e37d9aabff238c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/SAXParserImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/SchemaValidatorConfiguration.class b/src/main/resources/org/python/apache/xerces/jaxp/SchemaValidatorConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..4dbe7d3e27e53f40adaf297f21b51added62f920
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/SchemaValidatorConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/TeeXMLDocumentFilterImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/TeeXMLDocumentFilterImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d41185e4ecba3b0a0e9f476fbc970378a9bfcbc8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/TeeXMLDocumentFilterImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/UnparsedEntityHandler.class b/src/main/resources/org/python/apache/xerces/jaxp/UnparsedEntityHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..99ca659d726674690fbc702214868aebe1d98958
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/UnparsedEntityHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/datatype/DatatypeFactoryImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/datatype/DatatypeFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0addde8aa9064ba02d4ecc766d4489c15fcd360
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/datatype/DatatypeFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/datatype/DurationImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/datatype/DurationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf638b9a81c8da20a8d6a577b8069251201e9965
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/datatype/DurationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/datatype/SerializedDuration.class b/src/main/resources/org/python/apache/xerces/jaxp/datatype/SerializedDuration.class
new file mode 100644
index 0000000000000000000000000000000000000000..217ba6f9108f887c04519f0d904ef0838a5cc8d6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/datatype/SerializedDuration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/datatype/SerializedXMLGregorianCalendar.class b/src/main/resources/org/python/apache/xerces/jaxp/datatype/SerializedXMLGregorianCalendar.class
new file mode 100644
index 0000000000000000000000000000000000000000..99dc6c7f408f25dac61e9895abf2bce0c5ae7083
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/datatype/SerializedXMLGregorianCalendar.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$1.class b/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d62d8fda51e8d88dc437a866b38278d5c49a9b46
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$DaysInMonth.class b/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$DaysInMonth.class
new file mode 100644
index 0000000000000000000000000000000000000000..40d56e57c779a7a8424a11e7ddae2035acad08c6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$DaysInMonth.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$Parser.class b/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$Parser.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0342b24a1c5486a83f8fdbe5c2e37223f575df7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl$Parser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a907e3c942e92a2992508370818952ee0097425
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/datatype/XMLGregorianCalendarImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/AbstractXMLSchema.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/AbstractXMLSchema.class
new file mode 100644
index 0000000000000000000000000000000000000000..47f5839dc772ea9c40a198a0c2f3c925139b70cd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/AbstractXMLSchema.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMDocumentHandler.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMDocumentHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..caef3d037c0909f0af98102169ff499c8aed1d70
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMDocumentHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMResultAugmentor.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMResultAugmentor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9890e34c2667d38ef67eb687ad6b938619d4b2e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMResultAugmentor.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMResultBuilder.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMResultBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..1cbd494ec40d09a5055b58ce74431447348e7e75
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMResultBuilder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMValidatorHelper$DOMNamespaceContext.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMValidatorHelper$DOMNamespaceContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe3fc6f8ebb0da0bd8dfc35075049314d8be5d76
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMValidatorHelper$DOMNamespaceContext.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMValidatorHelper.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMValidatorHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd9f5392d962701f30203c670ea588de4d19d946
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/DOMValidatorHelper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/DraconianErrorHandler.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/DraconianErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5e64993e012ffbab0198199951532430feee068
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/DraconianErrorHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/EmptyXMLSchema.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/EmptyXMLSchema.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b25c2ac6ffcdea628c0beb17818ef08ebdeafca
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/EmptyXMLSchema.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/JAXPValidationMessageFormatter.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/JAXPValidationMessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..e505f7fd9c693582c31cdfb4e08501496ec39725
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/JAXPValidationMessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/ReadOnlyGrammarPool.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/ReadOnlyGrammarPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b720006c652c84e40fb6b7f371b1d6b8529aae4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/ReadOnlyGrammarPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/SimpleXMLSchema.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/SimpleXMLSchema.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9fbec04bbb9529ee8ff9b643c7f42697082929f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/SimpleXMLSchema.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool$Entry.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool$Entry.class
new file mode 100644
index 0000000000000000000000000000000000000000..249aca91eac906031ae83c3e9e74b1691809ea35
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool$Entry.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool$SoftGrammarReference.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool$SoftGrammarReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9c046a9db7c329bfd4ead13d47f73a8d76af022
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool$SoftGrammarReference.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0d07003ef3b525e8b9d5cdea5ebcb8fdf1502d3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/SoftReferenceGrammarPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXDocumentHandler.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXDocumentHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..bedb6f2e804d2374c6ed772d5342549dab984fcb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXDocumentHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$1.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f30b062683e9bc196316b49f3ea0616812a9f60
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$AttributeIterator.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$AttributeIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae4816b07acc86eb5646c179ed1355ea2c0600a7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$AttributeIterator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$NamespaceIterator.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$NamespaceIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..25023108ce621bddce843cd945f457516b43234d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder$NamespaceIterator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..17c64c2445f407d6461c60b0983c1e4ce4ed85a9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXEventResultBuilder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXStreamResultBuilder.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXStreamResultBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9ab776a845b80fc1cc31e339942a9fc70138f5a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXStreamResultBuilder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$EventHelper.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$EventHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..391388bad2e376a06bc1878443e40a06fcd6573f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$EventHelper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$StreamHelper.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$StreamHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8c3aab1cfc8f568a56a5a346cc5bc1e09386784
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$StreamHelper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$XMLStreamReaderLocation.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$XMLStreamReaderLocation.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f83758536d3a412f1aa00bb1ab3bd99e0c7e824
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper$XMLStreamReaderLocation.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f85a9c03a10baac4cd09a01a5ded5832b54def3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StAXValidatorHelper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/StreamValidatorHelper.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/StreamValidatorHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8e844a26cfef63f621e0518ccff4b50a7cfe357
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/StreamValidatorHelper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/Util.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/Util.class
new file mode 100644
index 0000000000000000000000000000000000000000..658482c13c176f829725e05a685cf974285f4484
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/Util.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$1.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c79431eea5e124ba8dc28a955cda244f1c059e2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$ResolutionForwarder.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$ResolutionForwarder.class
new file mode 100644
index 0000000000000000000000000000000000000000..853b7d438c3ea63ad997b4a4980bcca2a05b93c7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$ResolutionForwarder.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$XMLSchemaTypeInfoProvider.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$XMLSchemaTypeInfoProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..84db4670cb9152a9b249f7009ad5e3002277f30b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl$XMLSchemaTypeInfoProvider.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..96e5701bb5c7b276c910e3df1533a5f7ccaac314
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHandlerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHelper.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..0da208cb69af31f3b86522b22b7f8d1d053bcc77
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorHelper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorImpl.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8127a23e56edac624f6631c4c8e39dd94ac3624a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/ValidatorImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/WeakReferenceXMLSchema.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/WeakReferenceXMLSchema.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf9f4dfd66e3970a9a32380cbcd1122833f23595
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/WeakReferenceXMLSchema.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchema.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchema.class
new file mode 100644
index 0000000000000000000000000000000000000000..898a4333431b626147e91157b7055ce0697256fc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchema.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory$XMLGrammarPoolImplExtension.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory$XMLGrammarPoolImplExtension.class
new file mode 100644
index 0000000000000000000000000000000000000000..c171d9a7d3866dde475755997ea66326d615f253
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory$XMLGrammarPoolImplExtension.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory$XMLGrammarPoolWrapper.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory$XMLGrammarPoolWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4654dcb328df229396e0e6626e0140c8b392c81
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory$XMLGrammarPoolWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..7cd148cac4229ed252ab60f3659019da853e956e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaValidatorComponentManager.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaValidatorComponentManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb9a009c5a47588a74b7d517403eb4d5b6a89396
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/XMLSchemaValidatorComponentManager.class differ
diff --git a/src/main/resources/org/python/apache/xerces/jaxp/validation/XSGrammarPoolContainer.class b/src/main/resources/org/python/apache/xerces/jaxp/validation/XSGrammarPoolContainer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ebd503ebe2eb0df038fd18b62758c3670e58d6d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/jaxp/validation/XSGrammarPoolContainer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/AbstractDOMParser$Abort.class b/src/main/resources/org/python/apache/xerces/parsers/AbstractDOMParser$Abort.class
new file mode 100644
index 0000000000000000000000000000000000000000..f232232503909f76ef63f6d5e466ebea8b5327c5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/AbstractDOMParser$Abort.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/AbstractDOMParser.class b/src/main/resources/org/python/apache/xerces/parsers/AbstractDOMParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4e4b9b0c21a5319995fa8bd6b81710bb2938674
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/AbstractDOMParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser$AttributesProxy.class b/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser$AttributesProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6c6e71914ca1870adb7f16d2aeb76dc1ed56c6f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser$AttributesProxy.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser$LocatorProxy.class b/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser$LocatorProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf9aa960aab2726b73947898d9b5e176e2a87a63
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser$LocatorProxy.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser.class b/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..48c2ddd2414db7c8766c912bc3dfd340c772577d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/AbstractSAXParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/AbstractXMLDocumentParser.class b/src/main/resources/org/python/apache/xerces/parsers/AbstractXMLDocumentParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..84cb017281bb64643f0839bdbb88621c7e6ee58b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/AbstractXMLDocumentParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/BasicParserConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/BasicParserConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..af23064ba8ba12f9737bddd2deb4efd61d11f6b6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/BasicParserConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool$ShadowedGrammarPool.class b/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool$ShadowedGrammarPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7b13c4cb77d52fec3c4558efef8c19452394be6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool$ShadowedGrammarPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool$SynchronizedGrammarPool.class b/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool$SynchronizedGrammarPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..927dcb59b0564bbc2dc7834392c29efbd5b89f0f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool$SynchronizedGrammarPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool.class b/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..8214ff51a27a47f6e7ada72b0920ee9e00d72bc6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/CachingParserPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/DOMASBuilderImpl.class b/src/main/resources/org/python/apache/xerces/parsers/DOMASBuilderImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a244e301f470fc76a275045be3a8e7b6579ac217
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/DOMASBuilderImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/DOMParser.class b/src/main/resources/org/python/apache/xerces/parsers/DOMParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..71fd85616929119707dda65acac9b5f2e0bf7d37
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/DOMParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$1.class b/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cd8619d4e41c697f5ec8ad5c982b5beb90d2c71
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$AbortHandler.class b/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$AbortHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..b98b8d11eb6f4411ed34e0729e315ba827ca281a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$AbortHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$NullLSParserFilter.class b/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$NullLSParserFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..60c69d283ea0a9c3da3c9d6237c79aefab7186db
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl$NullLSParserFilter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl.class b/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..da0cd4856c2e6c15bc608b9c355887195bad0565
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/DOMParserImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/DTDConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/DTDConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..372f5a2adff6d6f03cf5852c3c5fa3ef61617b47
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/DTDConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/DTDParser.class b/src/main/resources/org/python/apache/xerces/parsers/DTDParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..2fda983fb583414d5b54e8d0691477a83a6f24b3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/DTDParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/IntegratedParserConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/IntegratedParserConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..c986c5190913bae833c87e7d595dbf46d641f183
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/IntegratedParserConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/NonValidatingConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/NonValidatingConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fe714be2e278e4c5fa0931a75efc95e99ef83ea
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/NonValidatingConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/ObjectFactory$ConfigurationError.class b/src/main/resources/org/python/apache/xerces/parsers/ObjectFactory$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ce81e7accb25546e22618d9566de05c13cf008e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/ObjectFactory$ConfigurationError.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/ObjectFactory.class b/src/main/resources/org/python/apache/xerces/parsers/ObjectFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..747012353823df6d388cc96794c9f9396cbcf4e1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/ObjectFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SAXParser.class b/src/main/resources/org/python/apache/xerces/parsers/SAXParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..8702e26293df80b3095b85385d17e93e3bed91f6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SAXParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecurityConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/SecurityConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..b79bfc7e030e713e21c2630baed95147fb55503d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecurityConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$1.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ad1a554f11056c5bfa4ca79e719c7df1194e065
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$2.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ef3ee33aaf1f82fa18eeae3fa22e390d82e2857
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$2.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$3.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c531f004c72ac052cb7c6777051aabbbf8db9a1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$3.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$4.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..a66a42e6fbaebc299767fc5887c86b4c7586253e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$4.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$5.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..57f7ad7c0e9146f5ca794beb8d1a88b19e591174
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$5.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$6.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..6be68244e27ab9559b80d84ce3d7909e35a57d70
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$6.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$7.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..119403dfb3d388a3ce4b30c43756525b0e48b5ad
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$7.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$8.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..57ea4a9a48d9e95c4f0b66fd1dbbd6cbe586f3dc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport$8.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport.class b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..d67bfc1c955fd3edfb7fdf7443f8ffbe8ca5211d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SecuritySupport.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/SoftReferenceSymbolTableConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/SoftReferenceSymbolTableConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a42988060a1adb39e2b79f90c0bf27c531aeb75
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/SoftReferenceSymbolTableConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/StandardParserConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/StandardParserConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2a6cc81d41d1f60c1b7356b57559f3d7773f69b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/StandardParserConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XIncludeAwareParserConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/XIncludeAwareParserConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bd6982d625267a6ab23c23a909ea7bef3482808
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XIncludeAwareParserConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XIncludeParserConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/XIncludeParserConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..9996b7629058825926fcb6aae5801031713095a0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XIncludeParserConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XML11Configurable.class b/src/main/resources/org/python/apache/xerces/parsers/XML11Configurable.class
new file mode 100644
index 0000000000000000000000000000000000000000..98310c3f31c5f6128e522f7fd904b21a2fda6dab
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XML11Configurable.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XML11Configuration.class b/src/main/resources/org/python/apache/xerces/parsers/XML11Configuration.class
new file mode 100644
index 0000000000000000000000000000000000000000..07c10cfecb575c757dab3b91816ee662e2288b3c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XML11Configuration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XML11DTDConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/XML11DTDConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ee7c6aff119a306bc411e82d5bf665984aa41bf
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XML11DTDConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XML11NonValidatingConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/XML11NonValidatingConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a6c1fb702d87a682dc1d4cd752bb44476742307
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XML11NonValidatingConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XMLDocumentParser.class b/src/main/resources/org/python/apache/xerces/parsers/XMLDocumentParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..f167cb68256b01b78ab01de18077bf1e0e932437
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XMLDocumentParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarCachingConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarCachingConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a84a39f6de413e755404e7f362588b458e3f274
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarCachingConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarParser.class b/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..55e5767c7392ab16bb777426c183598de1530ad7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarPreparser$XMLGrammarLoaderContainer.class b/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarPreparser$XMLGrammarLoaderContainer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4f1ce43dce9b932e7064e7c97b786c3ec691ec5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarPreparser$XMLGrammarLoaderContainer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarPreparser.class b/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarPreparser.class
new file mode 100644
index 0000000000000000000000000000000000000000..36ddd772e10736a286f5501448d86400122eeaef
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XMLGrammarPreparser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XMLParser.class b/src/main/resources/org/python/apache/xerces/parsers/XMLParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..756c4c57ad6d6f165ce88b59f441dffe4d138d5d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XMLParser.class differ
diff --git a/src/main/resources/org/python/apache/xerces/parsers/XPointerParserConfiguration.class b/src/main/resources/org/python/apache/xerces/parsers/XPointerParserConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b8f4850e18286b76f14960ffbb7e4be8cea6f9e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/parsers/XPointerParserConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext$1.class b/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d38214a497b12be8e2b56a523848692831e3baa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext$2.class b/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c85acae8d4f0e49a9cdeae31a96a2de3448efd2f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext$2.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext.class b/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..34dd42c85d3959af55fffb01d46c12e568bf96a9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/DefaultNamespaceContext.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/EmptyLocation.class b/src/main/resources/org/python/apache/xerces/stax/EmptyLocation.class
new file mode 100644
index 0000000000000000000000000000000000000000..baa3f194bdb36789ea3e621ec9f0499b49dd1763
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/EmptyLocation.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/ImmutableLocation.class b/src/main/resources/org/python/apache/xerces/stax/ImmutableLocation.class
new file mode 100644
index 0000000000000000000000000000000000000000..f707b8de3a23f26bb7f3b652f84042cbca4ea816
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/ImmutableLocation.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/XMLEventFactoryImpl.class b/src/main/resources/org/python/apache/xerces/stax/XMLEventFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3203bdb717c7ee1585f8d7fa98fc14090aa61e2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/XMLEventFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/AttributeImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/AttributeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d0f029248353e11cb09a3ef7e7847a505979c45
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/AttributeImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/CharactersImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/CharactersImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..39db7835fb7d399f4d3041a9c9fb759a04c76e26
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/CharactersImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/CommentImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/CommentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..9faee56f0affd29288d041407e18c5a9f12c1c9b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/CommentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/DTDImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/DTDImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..052ec8db75425b508c20f3a4b13131c8403ddee4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/DTDImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/ElementImpl$NoRemoveIterator.class b/src/main/resources/org/python/apache/xerces/stax/events/ElementImpl$NoRemoveIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff371e9cb4fea83bdf40140fa42aa27a1a69dd40
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/ElementImpl$NoRemoveIterator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/ElementImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/ElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d73304d1ce38d463090758da2b8304a68ad713c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/ElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/EndDocumentImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/EndDocumentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c8ac0ff34bd30ba68eeb533ff284d389dbf75a0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/EndDocumentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/EndElementImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/EndElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..96b3eec2b92383ac0683b8bad0eaf34391ac290f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/EndElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/EntityDeclarationImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/EntityDeclarationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..004cc82852a6e889cf9bbea180bf21acbbc239fd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/EntityDeclarationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/EntityReferenceImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/EntityReferenceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d8669a3574fd5e1ea91718edc510283ac7d21b3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/EntityReferenceImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/NamespaceImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/NamespaceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac1464009d8379d11258218141d6505794c3fbe4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/NamespaceImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/NotationDeclarationImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/NotationDeclarationImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8acb81081422739e3869581420bbf961a9862b05
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/NotationDeclarationImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/ProcessingInstructionImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/ProcessingInstructionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a92fa6c45ae20b41270d2665cfa9b87df074352
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/ProcessingInstructionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/StartDocumentImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/StartDocumentImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dd4b61fb158f0d2a7edf87c8a746d5d5d825537
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/StartDocumentImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/StartElementImpl$1.class b/src/main/resources/org/python/apache/xerces/stax/events/StartElementImpl$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f3e008b07d782de16d4fd7664fc4b556994d001
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/StartElementImpl$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/StartElementImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/StartElementImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..c745c9dee47e3dc4a9feb736324639353e10b75d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/StartElementImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/stax/events/XMLEventImpl.class b/src/main/resources/org/python/apache/xerces/stax/events/XMLEventImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..d917a84079dcf64011fc2eba8f21a030d48b824f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/stax/events/XMLEventImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/AttributesProxy.class b/src/main/resources/org/python/apache/xerces/util/AttributesProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..1623bb8768f92d309681d30633782c26c744193b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/AttributesProxy.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$AugmentationsItemsContainer.class b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$AugmentationsItemsContainer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9b652f4dd7cc0f872ed6d5514e2466edf6bdb8f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$AugmentationsItemsContainer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$LargeContainer.class b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$LargeContainer.class
new file mode 100644
index 0000000000000000000000000000000000000000..22ad06d67de9698a77353910fc26dbbbefc772ae
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$LargeContainer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$SmallContainer$SmallContainerKeyEnumeration.class b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$SmallContainer$SmallContainerKeyEnumeration.class
new file mode 100644
index 0000000000000000000000000000000000000000..e535edfbd412cfce280a142970c1aab76871b964
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$SmallContainer$SmallContainerKeyEnumeration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$SmallContainer.class b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$SmallContainer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7404e4700bc26fe3a02a2ea7c503d435413abfd2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl$SmallContainer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl.class b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b4b819b0b6e4eb212cf81b2bf2c493f4844ff36
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/AugmentationsImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/DOMEntityResolverWrapper.class b/src/main/resources/org/python/apache/xerces/util/DOMEntityResolverWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..30ed27bd6ea99bfdc6fb7c98971d8e41586e642e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/DOMEntityResolverWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/DOMErrorHandlerWrapper$DOMErrorTypeMap.class b/src/main/resources/org/python/apache/xerces/util/DOMErrorHandlerWrapper$DOMErrorTypeMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..2293e84b8cecfd31def29944e2136ae07f51b5df
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/DOMErrorHandlerWrapper$DOMErrorTypeMap.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/DOMErrorHandlerWrapper.class b/src/main/resources/org/python/apache/xerces/util/DOMErrorHandlerWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9f7b94d7be948028c753444c8dc9c1c7612b15d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/DOMErrorHandlerWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/DOMInputSource.class b/src/main/resources/org/python/apache/xerces/util/DOMInputSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c8490b4199d2988ba0e4ff2dfc9065ae136578b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/DOMInputSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/DOMUtil$ThrowableMethods.class b/src/main/resources/org/python/apache/xerces/util/DOMUtil$ThrowableMethods.class
new file mode 100644
index 0000000000000000000000000000000000000000..f102213465afd31f640c91e90c2ad2aefd7109a7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/DOMUtil$ThrowableMethods.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/DOMUtil.class b/src/main/resources/org/python/apache/xerces/util/DOMUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2f340d5640916af2dffe686840fe63d5c842f4e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/DOMUtil.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/DatatypeMessageFormatter.class b/src/main/resources/org/python/apache/xerces/util/DatatypeMessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..e4af604278a50cdb5eae7c8db1c3549dbe97296b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/DatatypeMessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/DefaultErrorHandler.class b/src/main/resources/org/python/apache/xerces/util/DefaultErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..c694d3e98db1defcc1cc948170804a3497587f02
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/DefaultErrorHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/EncodingMap.class b/src/main/resources/org/python/apache/xerces/util/EncodingMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ea53776caacf2c3701b4ac52e052de3991d7670
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/EncodingMap.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/EntityResolver2Wrapper.class b/src/main/resources/org/python/apache/xerces/util/EntityResolver2Wrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..91693b0b4efe08e9c075f24cfbc68fca6bd49539
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/EntityResolver2Wrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/EntityResolverWrapper.class b/src/main/resources/org/python/apache/xerces/util/EntityResolverWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..87b4e2ba13f93b6d2e3652f3738ae2d09c84ef04
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/EntityResolverWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/ErrorHandlerProxy.class b/src/main/resources/org/python/apache/xerces/util/ErrorHandlerProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..7821f89f543f711f899189038c0d17726ddb38f6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/ErrorHandlerProxy.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/ErrorHandlerWrapper$1.class b/src/main/resources/org/python/apache/xerces/util/ErrorHandlerWrapper$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..280a4edc31aba0b158e31340b046794e53c119b7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/ErrorHandlerWrapper$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/ErrorHandlerWrapper.class b/src/main/resources/org/python/apache/xerces/util/ErrorHandlerWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3b9ee8303efe204c27f33a4b2bf0be6b4112c56
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/ErrorHandlerWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/HTTPInputSource.class b/src/main/resources/org/python/apache/xerces/util/HTTPInputSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..254d9fcbd8abe6f62051e44f9e6e63aca19fa009
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/HTTPInputSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/IntStack.class b/src/main/resources/org/python/apache/xerces/util/IntStack.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3027b7e64aca7cf8aaec6b5cafce509cace5220
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/IntStack.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/JAXPNamespaceContextWrapper.class b/src/main/resources/org/python/apache/xerces/util/JAXPNamespaceContextWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7f61d88c539ae95b791f9fa06bcdb01135cd631
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/JAXPNamespaceContextWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/LocatorProxy.class b/src/main/resources/org/python/apache/xerces/util/LocatorProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d39323d14763aa54302abe98532f1085df69078
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/LocatorProxy.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/MessageFormatter.class b/src/main/resources/org/python/apache/xerces/util/MessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b831290756f2227a656e23e96a1558c0773abeb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/MessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/NamespaceSupport$Prefixes.class b/src/main/resources/org/python/apache/xerces/util/NamespaceSupport$Prefixes.class
new file mode 100644
index 0000000000000000000000000000000000000000..05575018be3dea80c55b523f2fc881ae69400901
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/NamespaceSupport$Prefixes.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/NamespaceSupport.class b/src/main/resources/org/python/apache/xerces/util/NamespaceSupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cc2a25ebd7235492d50a07fe6921f3257607be8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/NamespaceSupport.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/ParserConfigurationSettings.class b/src/main/resources/org/python/apache/xerces/util/ParserConfigurationSettings.class
new file mode 100644
index 0000000000000000000000000000000000000000..0377a8702a4e388e575d1f8b330d717991eb2e26
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/ParserConfigurationSettings.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SAXInputSource.class b/src/main/resources/org/python/apache/xerces/util/SAXInputSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..c5390cda6c466d87f8b66b6090905f011c8365bc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SAXInputSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SAXLocatorWrapper.class b/src/main/resources/org/python/apache/xerces/util/SAXLocatorWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d4f4cf009f4380b2e8e6e15523a4753ec08fe20
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SAXLocatorWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SAXMessageFormatter.class b/src/main/resources/org/python/apache/xerces/util/SAXMessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..29bfd0936a4d15a4a50861b509efb8aec4b90d8a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SAXMessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SecurityManager.class b/src/main/resources/org/python/apache/xerces/util/SecurityManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..94ec9272f936a98a091db3e4b7d143d928912967
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SecurityManager.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/ShadowedSymbolTable.class b/src/main/resources/org/python/apache/xerces/util/ShadowedSymbolTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..9db6c4754977d1290fe65bec324633a89b719cbc
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/ShadowedSymbolTable.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable$SREntry.class b/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable$SREntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..24a7fa1b1d70b4df7f5332c814ce80bd1bee6dde
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable$SREntry.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable$SREntryData.class b/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable$SREntryData.class
new file mode 100644
index 0000000000000000000000000000000000000000..c98482b94e1ecba92d09453835eca57ae71b7e1f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable$SREntryData.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable.class b/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab03ba3b9bf1fb99ffe5b4a44205db45540f689d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SoftReferenceSymbolTable.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/StAXInputSource.class b/src/main/resources/org/python/apache/xerces/util/StAXInputSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..89a6474d4eb0f2e5921b1704ad1755d023bb5398
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/StAXInputSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/StAXLocationWrapper.class b/src/main/resources/org/python/apache/xerces/util/StAXLocationWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed77c2ddfe6e5a3db004aed21510e4d97e76cccb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/StAXLocationWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SymbolHash$Entry.class b/src/main/resources/org/python/apache/xerces/util/SymbolHash$Entry.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fc51eeadf0948ebcc65488e02b34604992297d4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SymbolHash$Entry.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SymbolHash.class b/src/main/resources/org/python/apache/xerces/util/SymbolHash.class
new file mode 100644
index 0000000000000000000000000000000000000000..6cfb27ad4094c5c4d19a3a2f927d32128597d855
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SymbolHash.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SymbolTable$Entry.class b/src/main/resources/org/python/apache/xerces/util/SymbolTable$Entry.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9d7de011400abd03b349db402cedf4fd82ab801
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SymbolTable$Entry.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SymbolTable.class b/src/main/resources/org/python/apache/xerces/util/SymbolTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9daa379c0b94a391e5cd34ea786b64907150d0a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SymbolTable.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/SynchronizedSymbolTable.class b/src/main/resources/org/python/apache/xerces/util/SynchronizedSymbolTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..df10aaf85adaa7526df229ac737d87c5e7dce5f6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/SynchronizedSymbolTable.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/URI$MalformedURIException.class b/src/main/resources/org/python/apache/xerces/util/URI$MalformedURIException.class
new file mode 100644
index 0000000000000000000000000000000000000000..700914caecd80e33cc4b1911b02bffb81cba9378
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/URI$MalformedURIException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/URI.class b/src/main/resources/org/python/apache/xerces/util/URI.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f61b91cbcd835deb823d45c264dd9dd08213774
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/URI.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XML11Char.class b/src/main/resources/org/python/apache/xerces/util/XML11Char.class
new file mode 100644
index 0000000000000000000000000000000000000000..083dd4e46454c237d6ccef710602c9d43c280910
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XML11Char.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLAttributesImpl$Attribute.class b/src/main/resources/org/python/apache/xerces/util/XMLAttributesImpl$Attribute.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8e01de44a7177d2fad70b4d2847feeb813059c2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLAttributesImpl$Attribute.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLAttributesImpl.class b/src/main/resources/org/python/apache/xerces/util/XMLAttributesImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..2904106947e78217b8c94ed416db5cd379220aae
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLAttributesImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLCatalogResolver.class b/src/main/resources/org/python/apache/xerces/util/XMLCatalogResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..94c9ed3a338b92ad5a517da90bb777530a161c3f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLCatalogResolver.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLChar.class b/src/main/resources/org/python/apache/xerces/util/XMLChar.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff4f659f6e53fea33b234f5f30d4a9ed082141f9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLChar.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLEntityDescriptionImpl.class b/src/main/resources/org/python/apache/xerces/util/XMLEntityDescriptionImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..a48033fbf3f41e817a17939bbb4e46bbb1cf52d5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLEntityDescriptionImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLErrorCode.class b/src/main/resources/org/python/apache/xerces/util/XMLErrorCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab88b05fe20b557ad0acf731990569cfcc0ea155
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLErrorCode.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLGrammarPoolImpl$Entry.class b/src/main/resources/org/python/apache/xerces/util/XMLGrammarPoolImpl$Entry.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ed96742edc1cea5f995b5804066edaad6176183
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLGrammarPoolImpl$Entry.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLGrammarPoolImpl.class b/src/main/resources/org/python/apache/xerces/util/XMLGrammarPoolImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f1bb5559100f925f6d4285699bd8b83e930edd5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLGrammarPoolImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLLocatorWrapper.class b/src/main/resources/org/python/apache/xerces/util/XMLLocatorWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..f933559571cc028f6443a3e80127fde6b7d7cde0
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLLocatorWrapper.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLResourceIdentifierImpl.class b/src/main/resources/org/python/apache/xerces/util/XMLResourceIdentifierImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1cd1402cb6811b526d512c5a70df6ef455c3a399
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLResourceIdentifierImpl.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLStringBuffer.class b/src/main/resources/org/python/apache/xerces/util/XMLStringBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..02cfd1d851f849bd8535c0e0695869b3e17f54f5
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLStringBuffer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/util/XMLSymbols.class b/src/main/resources/org/python/apache/xerces/util/XMLSymbols.class
new file mode 100644
index 0000000000000000000000000000000000000000..8dbfda5f58377379cd7aeb3e7c13ac5d751feb82
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/util/XMLSymbols.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/MultipleScopeNamespaceSupport.class b/src/main/resources/org/python/apache/xerces/xinclude/MultipleScopeNamespaceSupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..51c2efee3c648086732af68565496a0d4810f5bb
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/MultipleScopeNamespaceSupport.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/ObjectFactory$ConfigurationError.class b/src/main/resources/org/python/apache/xerces/xinclude/ObjectFactory$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..be1a6fa15e0ff755f6823f6517440c3af871dcd9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/ObjectFactory$ConfigurationError.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/ObjectFactory.class b/src/main/resources/org/python/apache/xerces/xinclude/ObjectFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8fa799ee66944168d5902134cec65529a55f57b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/ObjectFactory.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$1.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..342cd3c27489c58cd6cdd6e3d53d6336914b3062
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$2.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6714d6bd03c507a9a4fce40b6e15afa0683ce4c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$2.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$3.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba3f3fbccf3fabe747257a1987c34000ec921301
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$3.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$4.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..5633f341e2cd1184c7f760331da06e78a32fcc97
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$4.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$5.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c25f5029e0b07f9736bdfc9b8ce0ad98c455990
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$5.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$6.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..b589b207753ab3ce45e0122672da441ad5b77d47
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$6.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$7.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..803f735d321aac5f9457374e192fd8bdd2ec83c8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$7.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$8.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..e148c5c8e92a9242d0b735bdcec9f9abd2d8e96d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport$8.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport.class b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e66d47fdc8b7bc480424c46c317bc8133cd999f
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/SecuritySupport.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/XInclude11TextReader.class b/src/main/resources/org/python/apache/xerces/xinclude/XInclude11TextReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..89ab7f1f99791af2755ad1856d0b1658222cc573
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/XInclude11TextReader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler$Notation.class b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler$Notation.class
new file mode 100644
index 0000000000000000000000000000000000000000..631091c4b71d32dcb74c19f1e0444bcbb0bee292
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler$Notation.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler$UnparsedEntity.class b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler$UnparsedEntity.class
new file mode 100644
index 0000000000000000000000000000000000000000..ced9a861b70450cc1aa0e045d8d64599a0cf4661
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler$UnparsedEntity.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler.class b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..97c040f47afb0a4275bcafe487861c7b10a778aa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/XIncludeMessageFormatter.class b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeMessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd76fe7a0fd5d0680c3665368e5fcbafc22db13a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeMessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/XIncludeNamespaceSupport.class b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeNamespaceSupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..2325150627f338910702b69d64767275b1c4f9f6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeNamespaceSupport.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xinclude/XIncludeTextReader.class b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeTextReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..70ab7bbd8163c551c9c69d3bb04df05897ba2d8d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xinclude/XIncludeTextReader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/Augmentations.class b/src/main/resources/org/python/apache/xerces/xni/Augmentations.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2d811061d4932b56ad6990220323f068e3460d3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/Augmentations.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/NamespaceContext.class b/src/main/resources/org/python/apache/xerces/xni/NamespaceContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..a27d86b305e15091611ba099f3df9d3580c76799
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/NamespaceContext.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/QName.class b/src/main/resources/org/python/apache/xerces/xni/QName.class
new file mode 100644
index 0000000000000000000000000000000000000000..93d3bf30d262c6a01179201dd13437f640c256ba
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/QName.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XMLAttributes.class b/src/main/resources/org/python/apache/xerces/xni/XMLAttributes.class
new file mode 100644
index 0000000000000000000000000000000000000000..36b3b4710c6a888bfcc29d67c1c9d259ab6d9251
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XMLAttributes.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XMLDTDContentModelHandler.class b/src/main/resources/org/python/apache/xerces/xni/XMLDTDContentModelHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd5dd822b07c9d1102a877540bd3723c93d36664
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XMLDTDContentModelHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XMLDTDHandler.class b/src/main/resources/org/python/apache/xerces/xni/XMLDTDHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..47be0ff7b5e73de1db5c8b85090f9ce1cc11cb59
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XMLDTDHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XMLDocumentFragmentHandler.class b/src/main/resources/org/python/apache/xerces/xni/XMLDocumentFragmentHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..7be47c9fa822c6270aded6a068b690ffcf5b18c2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XMLDocumentFragmentHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XMLDocumentHandler.class b/src/main/resources/org/python/apache/xerces/xni/XMLDocumentHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..37d7b95f2cc1191a10d6d548cf2331d6fef21ba3
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XMLDocumentHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XMLLocator.class b/src/main/resources/org/python/apache/xerces/xni/XMLLocator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fa0bbcc8340ac081d0131cef460f0bde30d7a59
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XMLLocator.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XMLResourceIdentifier.class b/src/main/resources/org/python/apache/xerces/xni/XMLResourceIdentifier.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c978381c2c8f32f71357952d4aa3bc20b8f4084
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XMLResourceIdentifier.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XMLString.class b/src/main/resources/org/python/apache/xerces/xni/XMLString.class
new file mode 100644
index 0000000000000000000000000000000000000000..c96bfd5722db1f2a2b8c4def382e857f373a2291
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XMLString.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/XNIException.class b/src/main/resources/org/python/apache/xerces/xni/XNIException.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f754f44e8e275d5583a0b1ecaf050dd2fdd29bd
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/XNIException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/grammars/Grammar.class b/src/main/resources/org/python/apache/xerces/xni/grammars/Grammar.class
new file mode 100644
index 0000000000000000000000000000000000000000..adc79596b3a75574eacb54e21a6b80cebaf88b11
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/grammars/Grammar.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/grammars/XMLDTDDescription.class b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLDTDDescription.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f67a5a5d7dbd96d511426013b0f0ce0bb5eb131
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLDTDDescription.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarDescription.class b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarDescription.class
new file mode 100644
index 0000000000000000000000000000000000000000..551cbe1414bacc013b6357951b7047b3e4c1fca1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarDescription.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarLoader.class b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5de04c6ddd3496c6b67f8aaca77a82205be8fe6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarLoader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarPool.class b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarPool.class
new file mode 100644
index 0000000000000000000000000000000000000000..556e1c8996fcd535ed6268aeae05a6a4b10a7867
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLGrammarPool.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/grammars/XMLSchemaDescription.class b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLSchemaDescription.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c78e162e7e2ddfd964cd96f39eab07933de98f9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/grammars/XMLSchemaDescription.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/grammars/XSGrammar.class b/src/main/resources/org/python/apache/xerces/xni/grammars/XSGrammar.class
new file mode 100644
index 0000000000000000000000000000000000000000..6837aedac54bcdfcb5840483286544dfe3a6c07e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/grammars/XSGrammar.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLComponent.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLComponent.class
new file mode 100644
index 0000000000000000000000000000000000000000..b44a512401ef5af0a7ab16dcfc5b017608ddf6aa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLComponent.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLComponentManager.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLComponentManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..12cfae04480e35ad6ca09be21182a803c8d59859
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLComponentManager.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLConfigurationException.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLConfigurationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..f769549c85a6f8ab374d9851d1d33ed86f9001ca
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLConfigurationException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDContentModelFilter.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDContentModelFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..29606e52e4b0c7f272e1ae7f066d642f8877ed19
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDContentModelFilter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDContentModelSource.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDContentModelSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c80f96d65546a91d6ec90ed2d74ad4e9324c14b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDContentModelSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDFilter.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..743a704d52769508d7683dbba3637b71264bdbc4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDFilter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDScanner.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDScanner.class
new file mode 100644
index 0000000000000000000000000000000000000000..a38c71a6cdc836002e9aee439519fd143dd560a6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDScanner.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDSource.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d313004a627ee99285adddba73e78f25deb6bc6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDTDSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentFilter.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea7fdd0d765b624daf984544492c001b610db6e6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentFilter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentScanner.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentScanner.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ad7a273653f6b3d1814e046c6bc87a54cf351b6
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentScanner.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentSource.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..32fc4e2482b970149df8c248ab128ec8fd1ee359
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLDocumentSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLEntityResolver.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLEntityResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4c0c4a4a3d9cdb38610418dd599750445f3fc01
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLEntityResolver.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLErrorHandler.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..b449aa65bee7a77f50075a7c229772d3086d80b4
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLErrorHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLInputSource.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLInputSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..43ba6adc1b58df345df5c4d5d3b5a1309709dd7b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLInputSource.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLParseException.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLParseException.class
new file mode 100644
index 0000000000000000000000000000000000000000..a91084340b02e698e1524830e03e08ef5aa9751c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLParseException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLParserConfiguration.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLParserConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..76dd1293bf5182bb0506d682cfb3bd9152582bc2
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLParserConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xni/parser/XMLPullParserConfiguration.class b/src/main/resources/org/python/apache/xerces/xni/parser/XMLPullParserConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3cc057064ea3e54306c1439a3c55d78b3a7b37e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xni/parser/XMLPullParserConfiguration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$1.class b/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d67bc0ce0bb0a98b4f7149c62fcb2027d6abdc1
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$Scanner.class b/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$Scanner.class
new file mode 100644
index 0000000000000000000000000000000000000000..366163d92a7eeedc3105ef5bd0d82f4609bc11ab
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$Scanner.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$Tokens.class b/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$Tokens.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c9d1634072f3f65e3461c1b7ad3b5d614789430
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer$Tokens.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer.class b/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad457fa3fd665a7ec3c1df32ea67eddb765857fa
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/ElementSchemePointer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/ShortHandPointer.class b/src/main/resources/org/python/apache/xerces/xpointer/ShortHandPointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d5a92520482b4e9a2e68ab488c584cfc831c5c7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/ShortHandPointer.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/XPointerErrorHandler.class b/src/main/resources/org/python/apache/xerces/xpointer/XPointerErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcae43b96cd4c1387163cf9c8d810242efdf1ffe
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/XPointerErrorHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$1.class b/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..41ff9ac2332cada4eed66ae972467a63f3657a98
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$1.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$Scanner.class b/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$Scanner.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae732c8c3b184af4c5a4dee1053f04e04281000d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$Scanner.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$Tokens.class b/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$Tokens.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e5512f2d6eb48c9c454af25d2ea79a5691a4e13
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler$Tokens.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler.class b/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8274c892cc42c99631be4089bfe4a23a05d6603
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/XPointerHandler.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/XPointerMessageFormatter.class b/src/main/resources/org/python/apache/xerces/xpointer/XPointerMessageFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e2577d6ea088457b7f55b296ae05e3d04186c02
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/XPointerMessageFormatter.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/XPointerPart.class b/src/main/resources/org/python/apache/xerces/xpointer/XPointerPart.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9eb920bd9d8adabd582a572880a7922fff1da88
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/XPointerPart.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xpointer/XPointerProcessor.class b/src/main/resources/org/python/apache/xerces/xpointer/XPointerProcessor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0d467870a83b629b73095520ca42ddef5fcc865
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xpointer/XPointerProcessor.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/AttributePSVI.class b/src/main/resources/org/python/apache/xerces/xs/AttributePSVI.class
new file mode 100644
index 0000000000000000000000000000000000000000..f42c82ed81f6edae23c63795f62d932e0756e65b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/AttributePSVI.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/ElementPSVI.class b/src/main/resources/org/python/apache/xerces/xs/ElementPSVI.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6834261db636bb69720e99400d8771873166184
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/ElementPSVI.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/ItemPSVI.class b/src/main/resources/org/python/apache/xerces/xs/ItemPSVI.class
new file mode 100644
index 0000000000000000000000000000000000000000..7314829d79b285a7d4a1799c3b266cb57aa877f7
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/ItemPSVI.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/LSInputList.class b/src/main/resources/org/python/apache/xerces/xs/LSInputList.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf980433e0bebbdee656f56a5455effa106c2d2e
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/LSInputList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/PSVIProvider.class b/src/main/resources/org/python/apache/xerces/xs/PSVIProvider.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f5d491de94db7387a9b13bf7e0b30ef116d70d8
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/PSVIProvider.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/ShortList.class b/src/main/resources/org/python/apache/xerces/xs/ShortList.class
new file mode 100644
index 0000000000000000000000000000000000000000..9dea5bf3aeda208368a7a93c9eda11bbf202160d
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/ShortList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/StringList.class b/src/main/resources/org/python/apache/xerces/xs/StringList.class
new file mode 100644
index 0000000000000000000000000000000000000000..102d39518a36e9a31e0c5f4a010a29af66026861
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/StringList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSAnnotation.class b/src/main/resources/org/python/apache/xerces/xs/XSAnnotation.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae77e07fad1de6a1b34b0c37400ab84dccaf7374
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSAnnotation.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSAttributeDeclaration.class b/src/main/resources/org/python/apache/xerces/xs/XSAttributeDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..36971423009bee46d5832fb9e566711c2658256c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSAttributeDeclaration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSAttributeGroupDefinition.class b/src/main/resources/org/python/apache/xerces/xs/XSAttributeGroupDefinition.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ab5ab48566ea9cd55e4a4391683a03959c77770
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSAttributeGroupDefinition.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSAttributeUse.class b/src/main/resources/org/python/apache/xerces/xs/XSAttributeUse.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe1c5d704a4379955a962f1cc85d8bd2333f2899
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSAttributeUse.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSComplexTypeDefinition.class b/src/main/resources/org/python/apache/xerces/xs/XSComplexTypeDefinition.class
new file mode 100644
index 0000000000000000000000000000000000000000..18a5c06a5cbacc385ed9ae5f9e63aff73f458c60
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSComplexTypeDefinition.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSConstants.class b/src/main/resources/org/python/apache/xerces/xs/XSConstants.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1817c8554501b93dcc91440193722159ecd8f5a
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSConstants.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSElementDeclaration.class b/src/main/resources/org/python/apache/xerces/xs/XSElementDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..4266e37634f19bb95a48bbfb7f88098566bc8e58
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSElementDeclaration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSException.class b/src/main/resources/org/python/apache/xerces/xs/XSException.class
new file mode 100644
index 0000000000000000000000000000000000000000..08f828635773d795208650c98828aff6608638ba
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSException.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSFacet.class b/src/main/resources/org/python/apache/xerces/xs/XSFacet.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b9cc2692ad84403f2f3e74c71e5e773684ac9a9
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSFacet.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSIDCDefinition.class b/src/main/resources/org/python/apache/xerces/xs/XSIDCDefinition.class
new file mode 100644
index 0000000000000000000000000000000000000000..e929aa643e986cdcb416059558c384c2a455e408
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSIDCDefinition.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSImplementation.class b/src/main/resources/org/python/apache/xerces/xs/XSImplementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c9c952c92ff302e5fb1517297c8e52a00cd27ae
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSImplementation.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSLoader.class b/src/main/resources/org/python/apache/xerces/xs/XSLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..b19885e76ea4a44d75f1d04fa7def69c2bc72408
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSLoader.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSModel.class b/src/main/resources/org/python/apache/xerces/xs/XSModel.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a30146cd1514e6f90998781d1eb07921bf44789
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSModel.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSModelGroup.class b/src/main/resources/org/python/apache/xerces/xs/XSModelGroup.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c885362a7fa4f06034c2f9fb871f6e6a0a86403
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSModelGroup.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSModelGroupDefinition.class b/src/main/resources/org/python/apache/xerces/xs/XSModelGroupDefinition.class
new file mode 100644
index 0000000000000000000000000000000000000000..d89df94984ea807ec7a0f325f1b520635df7a259
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSModelGroupDefinition.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSMultiValueFacet.class b/src/main/resources/org/python/apache/xerces/xs/XSMultiValueFacet.class
new file mode 100644
index 0000000000000000000000000000000000000000..d06e805ae5cafda5d6bb3bc12a5d7762935a3cee
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSMultiValueFacet.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSNamedMap.class b/src/main/resources/org/python/apache/xerces/xs/XSNamedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..58e78f24b44737bad459c9b9b382d9b1b9a51360
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSNamedMap.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSNamespaceItem.class b/src/main/resources/org/python/apache/xerces/xs/XSNamespaceItem.class
new file mode 100644
index 0000000000000000000000000000000000000000..666bbfd76afdcde7ffb9e521599a167938692b12
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSNamespaceItem.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSNamespaceItemList.class b/src/main/resources/org/python/apache/xerces/xs/XSNamespaceItemList.class
new file mode 100644
index 0000000000000000000000000000000000000000..0000d57400c153124edad4d35da13477fc229005
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSNamespaceItemList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSNotationDeclaration.class b/src/main/resources/org/python/apache/xerces/xs/XSNotationDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bab43589f90e66d7584188185140bd9e59a1e96
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSNotationDeclaration.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSObject.class b/src/main/resources/org/python/apache/xerces/xs/XSObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..24e654c0e685de82f316b335b179599f907e9b19
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSObject.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSObjectList.class b/src/main/resources/org/python/apache/xerces/xs/XSObjectList.class
new file mode 100644
index 0000000000000000000000000000000000000000..128d86ba9589c6c0ae046aacba3fb64c9128751c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSObjectList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSParticle.class b/src/main/resources/org/python/apache/xerces/xs/XSParticle.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd30b403d162fff66d50be93afba1540b54a78be
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSParticle.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSSimpleTypeDefinition.class b/src/main/resources/org/python/apache/xerces/xs/XSSimpleTypeDefinition.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd6781082924d30bd1c2124b928ce4590a049885
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSSimpleTypeDefinition.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSTerm.class b/src/main/resources/org/python/apache/xerces/xs/XSTerm.class
new file mode 100644
index 0000000000000000000000000000000000000000..fcb3f91d15dc76aa79dc9d6e4f610f18c8d4ab34
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSTerm.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSTypeDefinition.class b/src/main/resources/org/python/apache/xerces/xs/XSTypeDefinition.class
new file mode 100644
index 0000000000000000000000000000000000000000..3aa743ac8512e2a1f7b9f121ff00475783b4861b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSTypeDefinition.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSValue.class b/src/main/resources/org/python/apache/xerces/xs/XSValue.class
new file mode 100644
index 0000000000000000000000000000000000000000..7faf08915cc72f93294c016ef1a07efc09b613ba
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSValue.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/XSWildcard.class b/src/main/resources/org/python/apache/xerces/xs/XSWildcard.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d5561648146957c72fe3174fc62ca654b49c635
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/XSWildcard.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/datatypes/ByteList.class b/src/main/resources/org/python/apache/xerces/xs/datatypes/ByteList.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd43d9f973af7b1b1a9fce7184c5b25dd5519408
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/datatypes/ByteList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/datatypes/ObjectList.class b/src/main/resources/org/python/apache/xerces/xs/datatypes/ObjectList.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab05b93d0647be59aa33c56e14a796d41be2723c
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/datatypes/ObjectList.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDateTime.class b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDateTime.class
new file mode 100644
index 0000000000000000000000000000000000000000..2fb6137457319d217f5d40f44fbf858b9e4212ad
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDateTime.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDecimal.class b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDecimal.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d6641fb88a0a78220523fb39dc690a21875b73b
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDecimal.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDouble.class b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDouble.class
new file mode 100644
index 0000000000000000000000000000000000000000..754862bfc08f212f5792c23163d3e9d36718a152
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSDouble.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/datatypes/XSFloat.class b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSFloat.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ab9a1f3f1e094445c9639f48d7fdc2c30f14127
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSFloat.class differ
diff --git a/src/main/resources/org/python/apache/xerces/xs/datatypes/XSQName.class b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSQName.class
new file mode 100644
index 0000000000000000000000000000000000000000..357ea6e99dbdcf924d74b777d8fd48cb646a2846
Binary files /dev/null and b/src/main/resources/org/python/apache/xerces/xs/datatypes/XSQName.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/BaseMarkupSerializer.class b/src/main/resources/org/python/apache/xml/serialize/BaseMarkupSerializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fc5880455d06482b01a81429d6b641cf528e2a8
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/BaseMarkupSerializer.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/DOMSerializer.class b/src/main/resources/org/python/apache/xml/serialize/DOMSerializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6c7a4e37c358873a855cc9a2d62a19a8457db57
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/DOMSerializer.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/DOMSerializerImpl$DocumentMethods.class b/src/main/resources/org/python/apache/xml/serialize/DOMSerializerImpl$DocumentMethods.class
new file mode 100644
index 0000000000000000000000000000000000000000..be86264e2803e964f8af43d3050685639cee1c8e
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/DOMSerializerImpl$DocumentMethods.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/DOMSerializerImpl.class b/src/main/resources/org/python/apache/xml/serialize/DOMSerializerImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..54728cabb2fa146fd86daa9c8601e0596d6d00e8
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/DOMSerializerImpl.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/ElementState.class b/src/main/resources/org/python/apache/xml/serialize/ElementState.class
new file mode 100644
index 0000000000000000000000000000000000000000..a58cfd94aaf59d3b5696e205622aa6694e655be8
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/ElementState.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/EncodingInfo$CharToByteConverterMethods.class b/src/main/resources/org/python/apache/xml/serialize/EncodingInfo$CharToByteConverterMethods.class
new file mode 100644
index 0000000000000000000000000000000000000000..74344298300be3ef3c30dc7630b65ee72a5f6c74
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/EncodingInfo$CharToByteConverterMethods.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/EncodingInfo$CharsetMethods.class b/src/main/resources/org/python/apache/xml/serialize/EncodingInfo$CharsetMethods.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a9aac060c9d6132f7ff82a7153f4eda02c21fe5
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/EncodingInfo$CharsetMethods.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/EncodingInfo.class b/src/main/resources/org/python/apache/xml/serialize/EncodingInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..6dfc78b1a4b15487f0d07518536403e6e1f18481
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/EncodingInfo.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/Encodings.class b/src/main/resources/org/python/apache/xml/serialize/Encodings.class
new file mode 100644
index 0000000000000000000000000000000000000000..c36a20fc9d29c60f4eb626ad1843cb52124e0831
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/Encodings.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/HTMLEntities.res b/src/main/resources/org/python/apache/xml/serialize/HTMLEntities.res
new file mode 100644
index 0000000000000000000000000000000000000000..fb70ec5cc3e6960d8013e61e7d6de19bf7236db8
--- /dev/null
+++ b/src/main/resources/org/python/apache/xml/serialize/HTMLEntities.res
@@ -0,0 +1,291 @@
+# $Id: HTMLEntities.res 316040 2000-08-30 18:59:22Z arkin $
+#
+# @version $Revision: 316040 $ $Date: 2000-08-30 14:59:22 -0400 (Wed, 30 Aug 2000) $
+# @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
+#
+# Character entity references for markup-significant
+#
+quot 34
+amp 38
+lt 60
+gt 62
+nbsp 160
+#
+# Character entity references for ISO 8859-1 characters
+#
+iexcl 161
+cent 162
+pound 163
+curren 164
+yen 165
+brvbar 166
+sect 167
+uml 168
+copy 169
+ordf 170
+laquo 171
+not 172
+shy 173
+reg 174
+macr 175
+deg 176
+plusmn 177
+sup2 178
+sup3 179
+acute 180
+micro 181
+para 182
+middot 183
+cedil 184
+sup1 185
+ordm 186
+raquo 187
+frac14 188
+frac12 189
+frac34 190
+iquest 191
+Agrave 192
+Aacute 193
+Acirc 194
+Atilde 195
+Auml 196
+Aring 197
+AElig 198
+Ccedil 199
+Egrave 200
+Eacute 201
+Ecirc 202
+Euml 203
+Igrave 204
+Iacute 205
+Icirc 206
+Iuml 207
+ETH 208
+Ntilde 209
+Ograve 210
+Oacute 211
+Ocirc 212
+Otilde 213
+Ouml 214
+times 215
+Oslash 216
+Ugrave 217
+Uacute 218
+Ucirc 219
+Uuml 220
+Yacute 221
+THORN 222
+szlig 223
+agrave 224
+aacute 225
+acirc 226
+atilde 227
+auml 228
+aring 229
+aelig 230
+ccedil 231
+egrave 232
+eacute 233
+ecirc 234
+euml 235
+igrave 236
+iacute 237
+icirc 238
+iuml 239
+eth 240
+ntilde 241
+ograve 242
+oacute 243
+ocirc 244
+otilde 245
+ouml 246
+divide 247
+oslash 248
+ugrave 249
+uacute 250
+ucirc 251
+uuml 252
+yacute 253
+thorn 254
+yuml 255
+#
+# Character entity references for symbols, mathematical symbols, and Greek letters
+#
+# Latin Extended
+fnof 402
+#
+# Greek
+Alpha 913
+Beta 914
+Gamma 915
+Delta 916
+Epsilon 917
+Zeta 918
+Eta 919
+Theta 920
+Iota 921
+Kappa 922
+Lambda 923
+Mu 924
+Nu 925
+Xi 926
+Omicron 927
+Pi 928
+Rho 929
+Sigma 931
+Tau 932
+Upsilon 933
+Phi 934
+Chi 935
+Psi 936
+Omega 937
+alpha 945
+beta 946
+gamma 947
+delta 948
+epsilon 949
+zeta 950
+eta 951
+theta 952
+iota 953
+kappa 954
+lambda 955
+mu 956
+nu 957
+xi 958
+omicron 959
+pi 960
+rho 961
+sigmaf 962
+sigma 963
+tau 964
+upsilon 965
+phi 966
+chi 967
+psi 968
+omega 969
+thetasym 977
+upsih 978
+piv 982
+#
+# General Punctuation
+bull 8226
+hellip 8230
+prime 8242
+Prime 8243
+oline 8254
+frasl 8260
+#
+# Letterlike Symbols
+weierp 8472
+image 8465
+real 8476
+trade 8482
+alefsym 8501
+#
+# Arrows
+larr 8592
+uarr 8593
+rarr 8594
+darr 8595
+harr 8596
+crarr 8629
+lArr 8656
+uArr 8657
+rArr 8658
+dArr 8659
+hArr 8660
+#
+# Mathematical Operators
+forall 8704
+part 8706
+exist 8707
+empty 8709
+nabla 8711
+isin 8712
+notin 8713
+ni 8715
+prod 8719
+sum 8721
+minus 8722
+lowast 8727
+radic 8730
+prop 8733
+infin 8734
+ang 8736
+and 8743
+or 8744
+cap 8745
+cup 8746
+int 8747
+there4 8756
+sim 8764
+cong 8773
+asymp 8776
+ne 8800
+equiv 8801
+le 8804
+ge 8805
+sub 8834
+sup 8835
+nsub 8836
+sube 8838
+supe 8839
+oplus 8853
+otimes 8855
+perp 8869
+sdot 8901
+#
+# Miscellaneous Technical
+lceil 8968
+rceil 8969
+lfloor 8970
+rfloor 8971
+lang 9001
+rang 9002
+#
+# Geometric Shapes
+loz 9674
+#
+# Miscellaneous Symbols
+spades 9824
+clubs 9827
+hearts 9829
+diams 9830
+#
+# Character entity references for internationalization characters
+#
+# Latin Extended-A
+OElig 338
+oelig 339
+#-- Commented out. NN 4.7 does not seem to support these --
+#Scaron 352
+#scaron 353
+Yuml 376
+#
+# Spacing Modifier Letters
+circ 710
+tilde 732
+#
+# General Punctuation
+ensp 8194
+emsp 8195
+thinsp 8201
+zwnj 8204
+zwj 8205
+lrm 8206
+rlm 8207
+ndash 8211
+mdash 8212
+lsquo 8216
+rsquo 8217
+sbquo 8218
+ldquo 8220
+rdquo 8221
+bdquo 8222
+dagger 8224
+Dagger 8225
+permil 8240
+lsaquo 8249
+rsaquo 8250
+euro 8364
diff --git a/src/main/resources/org/python/apache/xml/serialize/HTMLSerializer.class b/src/main/resources/org/python/apache/xml/serialize/HTMLSerializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..00e861320a10accc4d064cc4da3ec11ed3de2f3d
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/HTMLSerializer.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/HTMLdtd.class b/src/main/resources/org/python/apache/xml/serialize/HTMLdtd.class
new file mode 100644
index 0000000000000000000000000000000000000000..06d4347c004769dfbf8c38166cc53d1b9c531931
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/HTMLdtd.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/IndentPrinter.class b/src/main/resources/org/python/apache/xml/serialize/IndentPrinter.class
new file mode 100644
index 0000000000000000000000000000000000000000..efdbdb5b9f8dd3eaf612ef5708d9b4343f7b55e9
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/IndentPrinter.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/LineSeparator.class b/src/main/resources/org/python/apache/xml/serialize/LineSeparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7b4dc8a70680a8940b39e29838b87430af571a0
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/LineSeparator.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/Method.class b/src/main/resources/org/python/apache/xml/serialize/Method.class
new file mode 100644
index 0000000000000000000000000000000000000000..be7ea01e3e214da91de99fa856cbc4cbf0c82ace
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/Method.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/ObjectFactory$ConfigurationError.class b/src/main/resources/org/python/apache/xml/serialize/ObjectFactory$ConfigurationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..34d6f63e0822a34c3234b603b09be1ff92a65d20
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/ObjectFactory$ConfigurationError.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/ObjectFactory.class b/src/main/resources/org/python/apache/xml/serialize/ObjectFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f2de0ceecaa13a0639e40a9ad47d4adbc2063c2
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/ObjectFactory.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/OutputFormat$DTD.class b/src/main/resources/org/python/apache/xml/serialize/OutputFormat$DTD.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce09d75e4065bd4db4b7eae2679c711adbb4dd71
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/OutputFormat$DTD.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/OutputFormat$Defaults.class b/src/main/resources/org/python/apache/xml/serialize/OutputFormat$Defaults.class
new file mode 100644
index 0000000000000000000000000000000000000000..14660afecde05bec9889e69b0980a121988b7a16
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/OutputFormat$Defaults.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/OutputFormat.class b/src/main/resources/org/python/apache/xml/serialize/OutputFormat.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2055faa7e2342a3366142d3b1f5aadbc7f2bf5d
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/OutputFormat.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/Printer.class b/src/main/resources/org/python/apache/xml/serialize/Printer.class
new file mode 100644
index 0000000000000000000000000000000000000000..869dddd18f77fe0377e410ed75bfc83c1953de5e
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/Printer.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$1.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c6fe4ab7c9e76bf062ce9f4b2a8a127675142f2
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$1.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$2.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..7afe87a7ebfc42369b2492d8c2ab872798bda584
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$2.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$3.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..3983a37bea6bfaf6b5a7081fedba83c81804b3c4
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$3.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$4.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecffef100ff6a583866630761312c670a7aca710
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$4.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$5.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca95760d2417bfaf954491d74f1d84ebe7ba4a13
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$5.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$6.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3fdb419c5f455b16f315482d8966aecf8118363
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$6.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$7.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa64bf144921ed1b51b642b93a46f5ce25e4cbbf
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$7.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$8.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dd9ca7cb2d007f701a67690c88afbb9e95b8580
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport$8.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SecuritySupport.class b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..1017cdd32e3e85fc52a4cdf56c9537b5d04bd2ab
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SecuritySupport.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/Serializer.class b/src/main/resources/org/python/apache/xml/serialize/Serializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0165ce5d909a077bbe167c397699dc994e9117b7
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/Serializer.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SerializerFactory.class b/src/main/resources/org/python/apache/xml/serialize/SerializerFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbc3c97e723a76c2eae97dbea31e2fb6064471e0
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SerializerFactory.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/SerializerFactoryImpl.class b/src/main/resources/org/python/apache/xml/serialize/SerializerFactoryImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..84243281675f1337c4560c19b928ec45265f7db1
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/SerializerFactoryImpl.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/TextSerializer.class b/src/main/resources/org/python/apache/xml/serialize/TextSerializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eff98f1eaabc184493a4377508d187c6f1e5c95e
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/TextSerializer.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/XHTMLSerializer.class b/src/main/resources/org/python/apache/xml/serialize/XHTMLSerializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf33197f9490a133a6160b8926b64f75ed279c05
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/XHTMLSerializer.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/XML11Serializer.class b/src/main/resources/org/python/apache/xml/serialize/XML11Serializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b61c5e68e82903a5e8d0d911d3226331317603cb
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/XML11Serializer.class differ
diff --git a/src/main/resources/org/python/apache/xml/serialize/XMLSerializer.class b/src/main/resources/org/python/apache/xml/serialize/XMLSerializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c436a80ed6d81cbd14a29b8a76f586dacaa75df6
Binary files /dev/null and b/src/main/resources/org/python/apache/xml/serialize/XMLSerializer.class differ
diff --git a/src/main/resources/org/python/compiler/APIVersion.class b/src/main/resources/org/python/compiler/APIVersion.class
new file mode 100644
index 0000000000000000000000000000000000000000..4546728bc0ef2f00de77c754a7da238f7aa30362
Binary files /dev/null and b/src/main/resources/org/python/compiler/APIVersion.class differ
diff --git a/src/main/resources/org/python/compiler/AdapterMaker.class b/src/main/resources/org/python/compiler/AdapterMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1fd41a6010426f0c9b04e4f5a61f8f926df846e
Binary files /dev/null and b/src/main/resources/org/python/compiler/AdapterMaker.class differ
diff --git a/src/main/resources/org/python/compiler/ArgListCompiler.class b/src/main/resources/org/python/compiler/ArgListCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..deccdbba5b0883c929acf562ae880e369a48dce6
Binary files /dev/null and b/src/main/resources/org/python/compiler/ArgListCompiler.class differ
diff --git a/src/main/resources/org/python/compiler/ClassConstants.class b/src/main/resources/org/python/compiler/ClassConstants.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7d26a77757bdfa3c8b43b4f85cdd7334d2dd93b
Binary files /dev/null and b/src/main/resources/org/python/compiler/ClassConstants.class differ
diff --git a/src/main/resources/org/python/compiler/ClassFile.class b/src/main/resources/org/python/compiler/ClassFile.class
new file mode 100644
index 0000000000000000000000000000000000000000..9185ee17dfcb4d9742ab022e6448d5c345aa938d
Binary files /dev/null and b/src/main/resources/org/python/compiler/ClassFile.class differ
diff --git a/src/main/resources/org/python/compiler/Code.class b/src/main/resources/org/python/compiler/Code.class
new file mode 100644
index 0000000000000000000000000000000000000000..17e2d6077d6b9d11af9e9b6afee5ee8a45d01bde
Binary files /dev/null and b/src/main/resources/org/python/compiler/Code.class differ
diff --git a/src/main/resources/org/python/compiler/CodeCompiler$1.class b/src/main/resources/org/python/compiler/CodeCompiler$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a2c2d9f0ce3fbf926a370c110d380842a859fd6
Binary files /dev/null and b/src/main/resources/org/python/compiler/CodeCompiler$1.class differ
diff --git a/src/main/resources/org/python/compiler/CodeCompiler$2.class b/src/main/resources/org/python/compiler/CodeCompiler$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..38f4ffc9d7f3f3ad25fd9eef34bc1a2c59a58bc3
Binary files /dev/null and b/src/main/resources/org/python/compiler/CodeCompiler$2.class differ
diff --git a/src/main/resources/org/python/compiler/CodeCompiler$ExceptionHandler.class b/src/main/resources/org/python/compiler/CodeCompiler$ExceptionHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..68bac2c784ffd5b92252c28397189f4261fca861
Binary files /dev/null and b/src/main/resources/org/python/compiler/CodeCompiler$ExceptionHandler.class differ
diff --git a/src/main/resources/org/python/compiler/CodeCompiler$LambdaSyntheticReturn.class b/src/main/resources/org/python/compiler/CodeCompiler$LambdaSyntheticReturn.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a9a4079b6344cd88dadd8f5c2f26464d9f4a97c
Binary files /dev/null and b/src/main/resources/org/python/compiler/CodeCompiler$LambdaSyntheticReturn.class differ
diff --git a/src/main/resources/org/python/compiler/CodeCompiler.class b/src/main/resources/org/python/compiler/CodeCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..d291d46c2f3fdfbe0d517ce7c0626291cddd7480
Binary files /dev/null and b/src/main/resources/org/python/compiler/CodeCompiler.class differ
diff --git a/src/main/resources/org/python/compiler/CompilationContext.class b/src/main/resources/org/python/compiler/CompilationContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..8580d28152196c2f43fa3dc96dffe99130a0c4b9
Binary files /dev/null and b/src/main/resources/org/python/compiler/CompilationContext.class differ
diff --git a/src/main/resources/org/python/compiler/Constant.class b/src/main/resources/org/python/compiler/Constant.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad7de99c42918f414c57427fce4e643450dc6d49
Binary files /dev/null and b/src/main/resources/org/python/compiler/Constant.class differ
diff --git a/src/main/resources/org/python/compiler/CustomMaker.class b/src/main/resources/org/python/compiler/CustomMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..d12b811cf73d7b3aa2c7b9183eb9c641b703d3b3
Binary files /dev/null and b/src/main/resources/org/python/compiler/CustomMaker.class differ
diff --git a/src/main/resources/org/python/compiler/Future$1.class b/src/main/resources/org/python/compiler/Future$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..973cea8a4b205894eda100e4365db2c9618d4677
Binary files /dev/null and b/src/main/resources/org/python/compiler/Future$1.class differ
diff --git a/src/main/resources/org/python/compiler/Future.class b/src/main/resources/org/python/compiler/Future.class
new file mode 100644
index 0000000000000000000000000000000000000000..e260f392ea9f2ddd3cabadce329e9c10c8acb632
Binary files /dev/null and b/src/main/resources/org/python/compiler/Future.class differ
diff --git a/src/main/resources/org/python/compiler/JavaMaker.class b/src/main/resources/org/python/compiler/JavaMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bfb0235f7a28d86c9bf3aa6c04c6fb0e6e09700
Binary files /dev/null and b/src/main/resources/org/python/compiler/JavaMaker.class differ
diff --git a/src/main/resources/org/python/compiler/JavaMakerSmokeTest.class b/src/main/resources/org/python/compiler/JavaMakerSmokeTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..f36e9201467e4de48a8f5c41106a2f38b9675840
Binary files /dev/null and b/src/main/resources/org/python/compiler/JavaMakerSmokeTest.class differ
diff --git a/src/main/resources/org/python/compiler/LegacyCompiler$LazyLegacyBundle.class b/src/main/resources/org/python/compiler/LegacyCompiler$LazyLegacyBundle.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3544ef21408384b923afea7da541f85b7e501df
Binary files /dev/null and b/src/main/resources/org/python/compiler/LegacyCompiler$LazyLegacyBundle.class differ
diff --git a/src/main/resources/org/python/compiler/LegacyCompiler.class b/src/main/resources/org/python/compiler/LegacyCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..b85511c616de18b32beb8ed502f7ce7bc07e4a13
Binary files /dev/null and b/src/main/resources/org/python/compiler/LegacyCompiler.class differ
diff --git a/src/main/resources/org/python/compiler/LineNumberTable.class b/src/main/resources/org/python/compiler/LineNumberTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..8174313153002dd939e942b31a25ec8623574695
Binary files /dev/null and b/src/main/resources/org/python/compiler/LineNumberTable.class differ
diff --git a/src/main/resources/org/python/compiler/MTime.class b/src/main/resources/org/python/compiler/MTime.class
new file mode 100644
index 0000000000000000000000000000000000000000..8061f23a63f82a1ffa35d14cbf022732d81c0034
Binary files /dev/null and b/src/main/resources/org/python/compiler/MTime.class differ
diff --git a/src/main/resources/org/python/compiler/Module.class b/src/main/resources/org/python/compiler/Module.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fb2bb628723edd559c8265d7fce8f41e9a1ad7f
Binary files /dev/null and b/src/main/resources/org/python/compiler/Module.class differ
diff --git a/src/main/resources/org/python/compiler/ModuleTest.class b/src/main/resources/org/python/compiler/ModuleTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..16636da0b436b4a8a0fa339086a7c9005354019a
Binary files /dev/null and b/src/main/resources/org/python/compiler/ModuleTest.class differ
diff --git a/src/main/resources/org/python/compiler/ProxyCodeHelpers$AnnotationDescr.class b/src/main/resources/org/python/compiler/ProxyCodeHelpers$AnnotationDescr.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f0b7bc5b8c6845970bef7445a8a17ca31d0bfa5
Binary files /dev/null and b/src/main/resources/org/python/compiler/ProxyCodeHelpers$AnnotationDescr.class differ
diff --git a/src/main/resources/org/python/compiler/ProxyCodeHelpers$ConstructorDescr.class b/src/main/resources/org/python/compiler/ProxyCodeHelpers$ConstructorDescr.class
new file mode 100644
index 0000000000000000000000000000000000000000..acf765dcffd154a172369aa4592fa48f92145b98
Binary files /dev/null and b/src/main/resources/org/python/compiler/ProxyCodeHelpers$ConstructorDescr.class differ
diff --git a/src/main/resources/org/python/compiler/ProxyCodeHelpers$MethodDescr.class b/src/main/resources/org/python/compiler/ProxyCodeHelpers$MethodDescr.class
new file mode 100644
index 0000000000000000000000000000000000000000..e851ea30e2ae4139ecdf7998321375563be7b9e7
Binary files /dev/null and b/src/main/resources/org/python/compiler/ProxyCodeHelpers$MethodDescr.class differ
diff --git a/src/main/resources/org/python/compiler/ProxyCodeHelpers.class b/src/main/resources/org/python/compiler/ProxyCodeHelpers.class
new file mode 100644
index 0000000000000000000000000000000000000000..73b29c56379c563f990ecb2cc2e6af756cc99391
Binary files /dev/null and b/src/main/resources/org/python/compiler/ProxyCodeHelpers.class differ
diff --git a/src/main/resources/org/python/compiler/ProxyMaker.class b/src/main/resources/org/python/compiler/ProxyMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..44384d346267900511a56fdcb15a240581267306
Binary files /dev/null and b/src/main/resources/org/python/compiler/ProxyMaker.class differ
diff --git a/src/main/resources/org/python/compiler/PyCodeConstant.class b/src/main/resources/org/python/compiler/PyCodeConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..feda5a0412f8c9d202bd51af688c8ce0e2e62775
Binary files /dev/null and b/src/main/resources/org/python/compiler/PyCodeConstant.class differ
diff --git a/src/main/resources/org/python/compiler/PyComplexConstant.class b/src/main/resources/org/python/compiler/PyComplexConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..747a55fb2c1bf606d5175dff874d4578e1c15b86
Binary files /dev/null and b/src/main/resources/org/python/compiler/PyComplexConstant.class differ
diff --git a/src/main/resources/org/python/compiler/PyFloatConstant.class b/src/main/resources/org/python/compiler/PyFloatConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..55b78e8636dfaf6fe53440c6fbdb7a2329160ca6
Binary files /dev/null and b/src/main/resources/org/python/compiler/PyFloatConstant.class differ
diff --git a/src/main/resources/org/python/compiler/PyIntegerConstant.class b/src/main/resources/org/python/compiler/PyIntegerConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e8377d588599b6f41d16cc63aea06e2f75d1029
Binary files /dev/null and b/src/main/resources/org/python/compiler/PyIntegerConstant.class differ
diff --git a/src/main/resources/org/python/compiler/PyLongConstant.class b/src/main/resources/org/python/compiler/PyLongConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4284d377d5d7862e6730f338fc22237b51f87b6
Binary files /dev/null and b/src/main/resources/org/python/compiler/PyLongConstant.class differ
diff --git a/src/main/resources/org/python/compiler/PyStringConstant.class b/src/main/resources/org/python/compiler/PyStringConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..16951bbc4d36b2fb32b2e5535b8071490fb55e9f
Binary files /dev/null and b/src/main/resources/org/python/compiler/PyStringConstant.class differ
diff --git a/src/main/resources/org/python/compiler/PyUnicodeConstant.class b/src/main/resources/org/python/compiler/PyUnicodeConstant.class
new file mode 100644
index 0000000000000000000000000000000000000000..67eac6d28783bf8c3e8070d9f1d5bdb2172cbde3
Binary files /dev/null and b/src/main/resources/org/python/compiler/PyUnicodeConstant.class differ
diff --git a/src/main/resources/org/python/compiler/ScopeConstants.class b/src/main/resources/org/python/compiler/ScopeConstants.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d7068680d74c7a2c6347aaeb52d17d98832125e
Binary files /dev/null and b/src/main/resources/org/python/compiler/ScopeConstants.class differ
diff --git a/src/main/resources/org/python/compiler/ScopeInfo.class b/src/main/resources/org/python/compiler/ScopeInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..826aa543af843c684a8ee69615df38ad465ccf75
Binary files /dev/null and b/src/main/resources/org/python/compiler/ScopeInfo.class differ
diff --git a/src/main/resources/org/python/compiler/ScopesCompiler.class b/src/main/resources/org/python/compiler/ScopesCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d077d9fc2609c8d0ef0d3ab0b19e20141ad972a
Binary files /dev/null and b/src/main/resources/org/python/compiler/ScopesCompiler.class differ
diff --git a/src/main/resources/org/python/compiler/SymInfo.class b/src/main/resources/org/python/compiler/SymInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd374c35339aa2ab165f5c0abf0ea97153a3ec5b
Binary files /dev/null and b/src/main/resources/org/python/compiler/SymInfo.class differ
diff --git a/src/main/resources/org/python/compiler/custom_proxymaker/ClassAnnotationTest.class b/src/main/resources/org/python/compiler/custom_proxymaker/ClassAnnotationTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..328fe41666166289ca343d32827a23962587ab5d
Binary files /dev/null and b/src/main/resources/org/python/compiler/custom_proxymaker/ClassAnnotationTest.class differ
diff --git a/src/main/resources/org/python/compiler/custom_proxymaker/ConstructorSignatureTest.class b/src/main/resources/org/python/compiler/custom_proxymaker/ConstructorSignatureTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5f89e3950552626ab14d52883b067a20b263d5f
Binary files /dev/null and b/src/main/resources/org/python/compiler/custom_proxymaker/ConstructorSignatureTest.class differ
diff --git a/src/main/resources/org/python/compiler/custom_proxymaker/CustomAnnotation$Priority.class b/src/main/resources/org/python/compiler/custom_proxymaker/CustomAnnotation$Priority.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba11a0baf86e67672b119f8905b2cb48f5e78847
Binary files /dev/null and b/src/main/resources/org/python/compiler/custom_proxymaker/CustomAnnotation$Priority.class differ
diff --git a/src/main/resources/org/python/compiler/custom_proxymaker/CustomAnnotation.class b/src/main/resources/org/python/compiler/custom_proxymaker/CustomAnnotation.class
new file mode 100644
index 0000000000000000000000000000000000000000..58c95001240a1b0f4824e63ea5bd20b85920e87a
Binary files /dev/null and b/src/main/resources/org/python/compiler/custom_proxymaker/CustomAnnotation.class differ
diff --git a/src/main/resources/org/python/compiler/custom_proxymaker/JUnitTest.class b/src/main/resources/org/python/compiler/custom_proxymaker/JUnitTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..188c75e9c99f89966162cf0a34e03518d499abc1
Binary files /dev/null and b/src/main/resources/org/python/compiler/custom_proxymaker/JUnitTest.class differ
diff --git a/src/main/resources/org/python/compiler/custom_proxymaker/MethodSignatureTest.class b/src/main/resources/org/python/compiler/custom_proxymaker/MethodSignatureTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc7226f102d760b58a5eec6f044535e13d87ae12
Binary files /dev/null and b/src/main/resources/org/python/compiler/custom_proxymaker/MethodSignatureTest.class differ
diff --git a/src/main/resources/org/python/compiler/custom_proxymaker/MiniClampMaker.class b/src/main/resources/org/python/compiler/custom_proxymaker/MiniClampMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..493e3a1ce22206006f89368464a23400058d3748
Binary files /dev/null and b/src/main/resources/org/python/compiler/custom_proxymaker/MiniClampMaker.class differ
diff --git a/src/main/resources/org/python/core/AbstractArray.class b/src/main/resources/org/python/core/AbstractArray.class
new file mode 100644
index 0000000000000000000000000000000000000000..9569da27ae3fde006b7445dae0d4460bb9196e43
Binary files /dev/null and b/src/main/resources/org/python/core/AbstractArray.class differ
diff --git a/src/main/resources/org/python/core/AllFunction.class b/src/main/resources/org/python/core/AllFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff096520b21b50c48d0850c78c6813c53f984fe9
Binary files /dev/null and b/src/main/resources/org/python/core/AllFunction.class differ
diff --git a/src/main/resources/org/python/core/AnnotationReader$1.class b/src/main/resources/org/python/core/AnnotationReader$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9eef45e5a4cff948693fd7469120bc0eff0e6ddd
Binary files /dev/null and b/src/main/resources/org/python/core/AnnotationReader$1.class differ
diff --git a/src/main/resources/org/python/core/AnnotationReader.class b/src/main/resources/org/python/core/AnnotationReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..f94ba8990d09f9f7ca3ebda430a623e105eb6482
Binary files /dev/null and b/src/main/resources/org/python/core/AnnotationReader.class differ
diff --git a/src/main/resources/org/python/core/AnyFunction.class b/src/main/resources/org/python/core/AnyFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb882fc0e36a127c24e8a3aa2063b4255b216cb2
Binary files /dev/null and b/src/main/resources/org/python/core/AnyFunction.class differ
diff --git a/src/main/resources/org/python/core/ArgParser.class b/src/main/resources/org/python/core/ArgParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..77fb24e6051c382dfa9beabca2296b11513d673d
Binary files /dev/null and b/src/main/resources/org/python/core/ArgParser.class differ
diff --git a/src/main/resources/org/python/core/AstList$PyExposer.class b/src/main/resources/org/python/core/AstList$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..01c250d6830582358dd971cbe84217d39d6d4881
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$_fields_descriptor.class b/src/main/resources/org/python/core/AstList$_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..718ac14dfc67eb513632a20bd0f51ed91a5d3ad2
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___add___exposer.class b/src/main/resources/org/python/core/AstList$astlist___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3550086119ea1efd1252deff4bc78aece193018d
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___contains___exposer.class b/src/main/resources/org/python/core/AstList$astlist___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f19883845b1f04f2988e44309047a48fe82acec
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___delitem___exposer.class b/src/main/resources/org/python/core/AstList$astlist___delitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b1cc82872f10bb49964b8980e5d4058b1c533b8
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___delitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___delslice___exposer.class b/src/main/resources/org/python/core/AstList$astlist___delslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..94b70633b3a84671e6aa53c1c128411821ce492d
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___delslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___eq___exposer.class b/src/main/resources/org/python/core/AstList$astlist___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a828f8264d26eb83475ea3d7306a9dedf3138555
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___ge___exposer.class b/src/main/resources/org/python/core/AstList$astlist___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..41a3cf0ed3dfe1d86316e9458b98b9cb5a855666
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___getitem___exposer.class b/src/main/resources/org/python/core/AstList$astlist___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..27f73d7aa7c405991039c1f0f4d02c8894b071d9
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___getslice___exposer.class b/src/main/resources/org/python/core/AstList$astlist___getslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..11d87c87faf15aa1441df6d01d13f913d25d1274
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___getslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___gt___exposer.class b/src/main/resources/org/python/core/AstList$astlist___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eaea90d364dc4b8991db7d9194e77024dc67d5aa
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___iadd___exposer.class b/src/main/resources/org/python/core/AstList$astlist___iadd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d31df170378948054cc9bce074f747e01ee7013
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___iadd___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___imul___exposer.class b/src/main/resources/org/python/core/AstList$astlist___imul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d695e4bf9416faa1d292be321313ffcb7d51906
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___imul___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___iter___exposer.class b/src/main/resources/org/python/core/AstList$astlist___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee46b4fe1a970bd6f5f48bdb0ab78ac28c026dd4
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___le___exposer.class b/src/main/resources/org/python/core/AstList$astlist___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f951de0bf80b6a319a212703646b07a342a2884c
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___lt___exposer.class b/src/main/resources/org/python/core/AstList$astlist___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9cc6b5b4125a32f27974e3f72fd2f4b6b5b23a18
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___mul___exposer.class b/src/main/resources/org/python/core/AstList$astlist___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b71e8659202a10ee8f529cd92cbb9f75592153a4
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___ne___exposer.class b/src/main/resources/org/python/core/AstList$astlist___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7cf5e61cabad5b0e4aa99d3bdd0738e69ca0f74
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___nonzero___exposer.class b/src/main/resources/org/python/core/AstList$astlist___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc9ff77e2868724585c9f4bbca33e7b2d4a7a06d
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___radd___exposer.class b/src/main/resources/org/python/core/AstList$astlist___radd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c04bc205b2c24c397027ef645c3f2bead588f7dd
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___radd___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___rmul___exposer.class b/src/main/resources/org/python/core/AstList$astlist___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee3753c365d7e6e9bb94c4f5e138856cb36037d3
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___setitem___exposer.class b/src/main/resources/org/python/core/AstList$astlist___setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ef067bb2cad8b92d3ce0f2e0a93df090994b4c3
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___setitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist___setslice___exposer.class b/src/main/resources/org/python/core/AstList$astlist___setslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcabe8a2e9c4114b0115af3c4394e24cc2b2af37
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist___setslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_append_exposer.class b/src/main/resources/org/python/core/AstList$astlist_append_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2f7c2dbffaeeba5722329b964f439e3ef2a7a46
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_append_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_count_exposer.class b/src/main/resources/org/python/core/AstList$astlist_count_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ce1b88bbb9cc046d57bba6a92478209b4ed8739
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_count_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_extend_exposer.class b/src/main/resources/org/python/core/AstList$astlist_extend_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..17db8716299115bad853b5171d39cda3e6d52430
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_extend_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_index_exposer.class b/src/main/resources/org/python/core/AstList$astlist_index_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0fc98d382cb83baf4ec3efc04b8f1fa83ce6d84
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_index_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_insert_exposer.class b/src/main/resources/org/python/core/AstList$astlist_insert_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e03404cfd8dc4fb5d65cfb22d04cf1b1d933c757
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_insert_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_pop_exposer.class b/src/main/resources/org/python/core/AstList$astlist_pop_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f118632c7d6459fdacf15a0ad88ba4aa034a96b5
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_pop_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_remove_exposer.class b/src/main/resources/org/python/core/AstList$astlist_remove_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad373755e1904215b899f98d4eec6d5daabf1f59
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_remove_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_reverse_exposer.class b/src/main/resources/org/python/core/AstList$astlist_reverse_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..75c735121a2e017f3577e95b401e4811f6472db3
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_reverse_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList$astlist_toString_exposer.class b/src/main/resources/org/python/core/AstList$astlist_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..841f1371a70848b050cc80b8b09d00b649a06f46
Binary files /dev/null and b/src/main/resources/org/python/core/AstList$astlist_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/AstList.class b/src/main/resources/org/python/core/AstList.class
new file mode 100644
index 0000000000000000000000000000000000000000..2330f576148df131f3b61db1deb14c535bfca31c
Binary files /dev/null and b/src/main/resources/org/python/core/AstList.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes$1.class b/src/main/resources/org/python/core/BaseBytes$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b657135837a213420de6595aa441b44838aa6f2
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes$1.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes$Builder.class b/src/main/resources/org/python/core/BaseBytes$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e2d6250ab44cea0dc58b405886d9429aa42000d
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes$Builder.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes$ByteSet.class b/src/main/resources/org/python/core/BaseBytes$ByteSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..377dd19b1233f9d9cfaac8efb5a40e41eaf58cf3
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes$ByteSet.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes$Finder.class b/src/main/resources/org/python/core/BaseBytes$Finder.class
new file mode 100644
index 0000000000000000000000000000000000000000..016027f26446f05dfc2e5b97e241af3c91ad9fd3
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes$Finder.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes$Fragment.class b/src/main/resources/org/python/core/BaseBytes$Fragment.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2f7d576435e786c501cbedd9578204929a8fe2a
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes$Fragment.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes$FragmentList.class b/src/main/resources/org/python/core/BaseBytes$FragmentList.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ed09f82eb733729bc9683edaa48662197034b5a
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes$FragmentList.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes$IndexDelegate.class b/src/main/resources/org/python/core/BaseBytes$IndexDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2f86d287835bed50160c9309209dbecaa4971df
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes$IndexDelegate.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes$ReverseFinder.class b/src/main/resources/org/python/core/BaseBytes$ReverseFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..468633b232c96dcdf1f09057861ca65b7617f9b3
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes$ReverseFinder.class differ
diff --git a/src/main/resources/org/python/core/BaseBytes.class b/src/main/resources/org/python/core/BaseBytes.class
new file mode 100644
index 0000000000000000000000000000000000000000..982be54ccb5e3afc978ad51a89501bc108b1ea2c
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytes.class differ
diff --git a/src/main/resources/org/python/core/BaseBytesTest$BufferedObject.class b/src/main/resources/org/python/core/BaseBytesTest$BufferedObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..b78d13a8a4a7812cda241cebc126cb5d284191b2
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytesTest$BufferedObject.class differ
diff --git a/src/main/resources/org/python/core/BaseBytesTest$Image.class b/src/main/resources/org/python/core/BaseBytesTest$Image.class
new file mode 100644
index 0000000000000000000000000000000000000000..45e272943370997ade3d090c1731987a0a2d36e6
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytesTest$Image.class differ
diff --git a/src/main/resources/org/python/core/BaseBytesTest$MyBytes$1.class b/src/main/resources/org/python/core/BaseBytesTest$MyBytes$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5649cf626f9b4f8ce1ad77f56f6fbd4fb97db7c9
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytesTest$MyBytes$1.class differ
diff --git a/src/main/resources/org/python/core/BaseBytesTest$MyBytes.class b/src/main/resources/org/python/core/BaseBytesTest$MyBytes.class
new file mode 100644
index 0000000000000000000000000000000000000000..68abda13f2cca0dd04f9c24c2d57d403e96fbf93
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytesTest$MyBytes.class differ
diff --git a/src/main/resources/org/python/core/BaseBytesTest.class b/src/main/resources/org/python/core/BaseBytesTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f6d054e5afeea6b731ec74f335483c61b71f1c4
Binary files /dev/null and b/src/main/resources/org/python/core/BaseBytesTest.class differ
diff --git a/src/main/resources/org/python/core/BaseDictionaryView.class b/src/main/resources/org/python/core/BaseDictionaryView.class
new file mode 100644
index 0000000000000000000000000000000000000000..17656454d9f761823d5094b84d54453408923337
Binary files /dev/null and b/src/main/resources/org/python/core/BaseDictionaryView.class differ
diff --git a/src/main/resources/org/python/core/BaseSet$1.class b/src/main/resources/org/python/core/BaseSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4121bb4eea4b2a57add24f921381c781af70df3
Binary files /dev/null and b/src/main/resources/org/python/core/BaseSet$1.class differ
diff --git a/src/main/resources/org/python/core/BaseSet$2.class b/src/main/resources/org/python/core/BaseSet$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a7f50766c38c21a09d163febad14c3fc0b03fab
Binary files /dev/null and b/src/main/resources/org/python/core/BaseSet$2.class differ
diff --git a/src/main/resources/org/python/core/BaseSet.class b/src/main/resources/org/python/core/BaseSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..0659efbe52b9d841a14fa4e577f80c9d0bb99b73
Binary files /dev/null and b/src/main/resources/org/python/core/BaseSet.class differ
diff --git a/src/main/resources/org/python/core/BinFunction.class b/src/main/resources/org/python/core/BinFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..0585b42f7f822873d0d91d4be1e8703e858af1e9
Binary files /dev/null and b/src/main/resources/org/python/core/BinFunction.class differ
diff --git a/src/main/resources/org/python/core/BufferProtocol.class b/src/main/resources/org/python/core/BufferProtocol.class
new file mode 100644
index 0000000000000000000000000000000000000000..a18c47f4fbb353e4fbbdcac68e5db888f3e1b04e
Binary files /dev/null and b/src/main/resources/org/python/core/BufferProtocol.class differ
diff --git a/src/main/resources/org/python/core/BuiltinDocs.class b/src/main/resources/org/python/core/BuiltinDocs.class
new file mode 100644
index 0000000000000000000000000000000000000000..1347606c09e4c3e647d6f91fe6ebb4b0048c1aa3
Binary files /dev/null and b/src/main/resources/org/python/core/BuiltinDocs.class differ
diff --git a/src/main/resources/org/python/core/BuiltinFunctions.class b/src/main/resources/org/python/core/BuiltinFunctions.class
new file mode 100644
index 0000000000000000000000000000000000000000..f70d9c3c1808211ee0250759c9c808c6c27d0557
Binary files /dev/null and b/src/main/resources/org/python/core/BuiltinFunctions.class differ
diff --git a/src/main/resources/org/python/core/BytecodeLoader$Loader.class b/src/main/resources/org/python/core/BytecodeLoader$Loader.class
new file mode 100644
index 0000000000000000000000000000000000000000..be110d1f3c00b703edd64e40f6f1b1dd8afba831
Binary files /dev/null and b/src/main/resources/org/python/core/BytecodeLoader$Loader.class differ
diff --git a/src/main/resources/org/python/core/BytecodeLoader.class b/src/main/resources/org/python/core/BytecodeLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..09bc81a0852e87972e69b8ac9695da07f5d3f38f
Binary files /dev/null and b/src/main/resources/org/python/core/BytecodeLoader.class differ
diff --git a/src/main/resources/org/python/core/ClassDictInit.class b/src/main/resources/org/python/core/ClassDictInit.class
new file mode 100644
index 0000000000000000000000000000000000000000..6edfaec483fa0c4c7ea4038404d495406efe33ee
Binary files /dev/null and b/src/main/resources/org/python/core/ClassDictInit.class differ
diff --git a/src/main/resources/org/python/core/ClasspathPyImporter$1.class b/src/main/resources/org/python/core/ClasspathPyImporter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..32c26cbe37042b938e606eee0d24f1a9f9b59c35
Binary files /dev/null and b/src/main/resources/org/python/core/ClasspathPyImporter$1.class differ
diff --git a/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter___init___exposer.class b/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..da21e97f3351be59f5f7abe87d417c25676cb5b6
Binary files /dev/null and b/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter_find_module_exposer.class b/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter_find_module_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f5b26046bf16a5ec8911427eb8d7f6a4c5968e5
Binary files /dev/null and b/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter_find_module_exposer.class differ
diff --git a/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter_load_module_exposer.class b/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter_load_module_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee3f371c28c3cef0b05c54525b9f528baa22d6d2
Binary files /dev/null and b/src/main/resources/org/python/core/ClasspathPyImporter$ClasspathPyImporter_load_module_exposer.class differ
diff --git a/src/main/resources/org/python/core/ClasspathPyImporter$PyExposer.class b/src/main/resources/org/python/core/ClasspathPyImporter$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..35d6a625758df6fcaaaf626c7d0ac85392379740
Binary files /dev/null and b/src/main/resources/org/python/core/ClasspathPyImporter$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/ClasspathPyImporter$exposed___new__.class b/src/main/resources/org/python/core/ClasspathPyImporter$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..32769756aa3180756b54e0ea6f2f66cb0c25f0ca
Binary files /dev/null and b/src/main/resources/org/python/core/ClasspathPyImporter$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/ClasspathPyImporter.class b/src/main/resources/org/python/core/ClasspathPyImporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..38f18e784787c054762a52c2e0c443456ac9e494
Binary files /dev/null and b/src/main/resources/org/python/core/ClasspathPyImporter.class differ
diff --git a/src/main/resources/org/python/core/ClasspathPyImporterDerived.class b/src/main/resources/org/python/core/ClasspathPyImporterDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bdf5fec9388bc3bb73b24d64c917261403e6605
Binary files /dev/null and b/src/main/resources/org/python/core/ClasspathPyImporterDerived.class differ
diff --git a/src/main/resources/org/python/core/CodeBootstrap.class b/src/main/resources/org/python/core/CodeBootstrap.class
new file mode 100644
index 0000000000000000000000000000000000000000..537a3e8f9bafef5c8543b91a562e00347548dd4b
Binary files /dev/null and b/src/main/resources/org/python/core/CodeBootstrap.class differ
diff --git a/src/main/resources/org/python/core/CodeFlag$1$1.class b/src/main/resources/org/python/core/CodeFlag$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8d77ee5afc24442c0f8316b0f4bf0a1be115a4e
Binary files /dev/null and b/src/main/resources/org/python/core/CodeFlag$1$1.class differ
diff --git a/src/main/resources/org/python/core/CodeFlag$1.class b/src/main/resources/org/python/core/CodeFlag$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ee0028473d99833873d486d4839ea2f2d6336df
Binary files /dev/null and b/src/main/resources/org/python/core/CodeFlag$1.class differ
diff --git a/src/main/resources/org/python/core/CodeFlag.class b/src/main/resources/org/python/core/CodeFlag.class
new file mode 100644
index 0000000000000000000000000000000000000000..065b7742fe8497f922fad4264c6b43aeaf2327e3
Binary files /dev/null and b/src/main/resources/org/python/core/CodeFlag.class differ
diff --git a/src/main/resources/org/python/core/CodeLoader$1.class b/src/main/resources/org/python/core/CodeLoader$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab27b07c5b9a50b7e8a4c9606d7a0c9bd2be0ef2
Binary files /dev/null and b/src/main/resources/org/python/core/CodeLoader$1.class differ
diff --git a/src/main/resources/org/python/core/CodeLoader.class b/src/main/resources/org/python/core/CodeLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..672a373e45e5ca9f64b407393c161bd38997f6e6
Binary files /dev/null and b/src/main/resources/org/python/core/CodeLoader.class differ
diff --git a/src/main/resources/org/python/core/CompileFunction.class b/src/main/resources/org/python/core/CompileFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..911521cf462404428f3c0be0ebb0cc1d46219006
Binary files /dev/null and b/src/main/resources/org/python/core/CompileFunction.class differ
diff --git a/src/main/resources/org/python/core/CompileMode$1.class b/src/main/resources/org/python/core/CompileMode$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..74d6d1b0d8721ab468d1a99e3b445ec91586185c
Binary files /dev/null and b/src/main/resources/org/python/core/CompileMode$1.class differ
diff --git a/src/main/resources/org/python/core/CompileMode$2.class b/src/main/resources/org/python/core/CompileMode$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..6de246700434d793f059f88d5a22c8faaa9aad73
Binary files /dev/null and b/src/main/resources/org/python/core/CompileMode$2.class differ
diff --git a/src/main/resources/org/python/core/CompileMode$3.class b/src/main/resources/org/python/core/CompileMode$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..52e13e6ec1af4679e0dff57553e16321133cd1f4
Binary files /dev/null and b/src/main/resources/org/python/core/CompileMode$3.class differ
diff --git a/src/main/resources/org/python/core/CompileMode.class b/src/main/resources/org/python/core/CompileMode.class
new file mode 100644
index 0000000000000000000000000000000000000000..21f65eec5d5ab6ffb26caf7cd9044d56b6365d9d
Binary files /dev/null and b/src/main/resources/org/python/core/CompileMode.class differ
diff --git a/src/main/resources/org/python/core/CompilerFacade.class b/src/main/resources/org/python/core/CompilerFacade.class
new file mode 100644
index 0000000000000000000000000000000000000000..32d86bc9561eadd65a52ed43239c2d16a12aaca3
Binary files /dev/null and b/src/main/resources/org/python/core/CompilerFacade.class differ
diff --git a/src/main/resources/org/python/core/CompilerFlags.class b/src/main/resources/org/python/core/CompilerFlags.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfb8fa473e6ffdd282935ec5e6e38bf1758a1fb0
Binary files /dev/null and b/src/main/resources/org/python/core/CompilerFlags.class differ
diff --git a/src/main/resources/org/python/core/Console.class b/src/main/resources/org/python/core/Console.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cce954feb316f0d59ce6aaba2224db88735ab9e
Binary files /dev/null and b/src/main/resources/org/python/core/Console.class differ
diff --git a/src/main/resources/org/python/core/ContextGuard$ContextCode$1.class b/src/main/resources/org/python/core/ContextGuard$ContextCode$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..65756f193348722028e08880651773390ef67734
Binary files /dev/null and b/src/main/resources/org/python/core/ContextGuard$ContextCode$1.class differ
diff --git a/src/main/resources/org/python/core/ContextGuard$ContextCode$2.class b/src/main/resources/org/python/core/ContextGuard$ContextCode$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7df47197145a765428a6c71417bb2308f02ae78
Binary files /dev/null and b/src/main/resources/org/python/core/ContextGuard$ContextCode$2.class differ
diff --git a/src/main/resources/org/python/core/ContextGuard$ContextCode.class b/src/main/resources/org/python/core/ContextGuard$ContextCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..eda8d309c2691811dad9237e14747edede146276
Binary files /dev/null and b/src/main/resources/org/python/core/ContextGuard$ContextCode.class differ
diff --git a/src/main/resources/org/python/core/ContextGuard$GeneratorContextManager.class b/src/main/resources/org/python/core/ContextGuard$GeneratorContextManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bd6e12077272ac8866676158d4f22ef8ab5db24
Binary files /dev/null and b/src/main/resources/org/python/core/ContextGuard$GeneratorContextManager.class differ
diff --git a/src/main/resources/org/python/core/ContextGuard.class b/src/main/resources/org/python/core/ContextGuard.class
new file mode 100644
index 0000000000000000000000000000000000000000..19f8467c4118401bfc287b9afed3ac76d348bbfd
Binary files /dev/null and b/src/main/resources/org/python/core/ContextGuard.class differ
diff --git a/src/main/resources/org/python/core/ContextManager.class b/src/main/resources/org/python/core/ContextManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c4a82d694f73b8b8ecd85d8419ae59aa9791b24
Binary files /dev/null and b/src/main/resources/org/python/core/ContextManager.class differ
diff --git a/src/main/resources/org/python/core/Deriveds.class b/src/main/resources/org/python/core/Deriveds.class
new file mode 100644
index 0000000000000000000000000000000000000000..79accf96b77fbb05211a8ab0d42fbe4959453d5e
Binary files /dev/null and b/src/main/resources/org/python/core/Deriveds.class differ
diff --git a/src/main/resources/org/python/core/FilelikeInputStream.class b/src/main/resources/org/python/core/FilelikeInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..b77db5133531c3acc95dc0809c1154fb2f86a08c
Binary files /dev/null and b/src/main/resources/org/python/core/FilelikeInputStream.class differ
diff --git a/src/main/resources/org/python/core/FixedFileWrapper.class b/src/main/resources/org/python/core/FixedFileWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7b99391a45add2b6658a89a80a672c02a887da8
Binary files /dev/null and b/src/main/resources/org/python/core/FixedFileWrapper.class differ
diff --git a/src/main/resources/org/python/core/FloatInfo.class b/src/main/resources/org/python/core/FloatInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2379d007e5f41006196b1f48e80d1737b813704
Binary files /dev/null and b/src/main/resources/org/python/core/FloatInfo.class differ
diff --git a/src/main/resources/org/python/core/FormatFunction.class b/src/main/resources/org/python/core/FormatFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..62fe0c649c6c258e2e14ba23e5fde14511e372b0
Binary files /dev/null and b/src/main/resources/org/python/core/FormatFunction.class differ
diff --git a/src/main/resources/org/python/core/FunctionThread.class b/src/main/resources/org/python/core/FunctionThread.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bf5234565b4427914dadd94dae9b238304ad72d
Binary files /dev/null and b/src/main/resources/org/python/core/FunctionThread.class differ
diff --git a/src/main/resources/org/python/core/FutureFeature$1.class b/src/main/resources/org/python/core/FutureFeature$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff663366ca5e32bd35e1f2a2ec441537f41088d4
Binary files /dev/null and b/src/main/resources/org/python/core/FutureFeature$1.class differ
diff --git a/src/main/resources/org/python/core/FutureFeature$2.class b/src/main/resources/org/python/core/FutureFeature$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..590d167f5132e7928cca7eeff033e0879983a491
Binary files /dev/null and b/src/main/resources/org/python/core/FutureFeature$2.class differ
diff --git a/src/main/resources/org/python/core/FutureFeature$3.class b/src/main/resources/org/python/core/FutureFeature$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf9badbc29105e8a62fe262771509016e9369acf
Binary files /dev/null and b/src/main/resources/org/python/core/FutureFeature$3.class differ
diff --git a/src/main/resources/org/python/core/FutureFeature$4.class b/src/main/resources/org/python/core/FutureFeature$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc99eb7c1031fb4dc0e2418bc61062a1be00c2fd
Binary files /dev/null and b/src/main/resources/org/python/core/FutureFeature$4.class differ
diff --git a/src/main/resources/org/python/core/FutureFeature.class b/src/main/resources/org/python/core/FutureFeature.class
new file mode 100644
index 0000000000000000000000000000000000000000..517dcdc3b3e572ff7713d9b94d300f8018782575
Binary files /dev/null and b/src/main/resources/org/python/core/FutureFeature.class differ
diff --git a/src/main/resources/org/python/core/IdImpl$WeakIdentityMap$WeakIdKey.class b/src/main/resources/org/python/core/IdImpl$WeakIdentityMap$WeakIdKey.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ec780b075bfdccb47d7bc3340da2d6edb0610d8
Binary files /dev/null and b/src/main/resources/org/python/core/IdImpl$WeakIdentityMap$WeakIdKey.class differ
diff --git a/src/main/resources/org/python/core/IdImpl$WeakIdentityMap.class b/src/main/resources/org/python/core/IdImpl$WeakIdentityMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..857a09a952d33f5622363c08c9152409a433c74a
Binary files /dev/null and b/src/main/resources/org/python/core/IdImpl$WeakIdentityMap.class differ
diff --git a/src/main/resources/org/python/core/IdImpl.class b/src/main/resources/org/python/core/IdImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..8829b9ae4038270170141bb20c2e3be7df790b5c
Binary files /dev/null and b/src/main/resources/org/python/core/IdImpl.class differ
diff --git a/src/main/resources/org/python/core/ImportFunction.class b/src/main/resources/org/python/core/ImportFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5e22642b26b017c958aabc401b462549e4a46a3
Binary files /dev/null and b/src/main/resources/org/python/core/ImportFunction.class differ
diff --git a/src/main/resources/org/python/core/InitModule.class b/src/main/resources/org/python/core/InitModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5bbb6582ea69585c17dbbc0e9ce26f000dae6e3
Binary files /dev/null and b/src/main/resources/org/python/core/InitModule.class differ
diff --git a/src/main/resources/org/python/core/JavaCode.class b/src/main/resources/org/python/core/JavaCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..027e40509f66659c543cefaa7fbdc80fe3d8c7d6
Binary files /dev/null and b/src/main/resources/org/python/core/JavaCode.class differ
diff --git a/src/main/resources/org/python/core/JavaFunc.class b/src/main/resources/org/python/core/JavaFunc.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2b434b21e369a9b42aa9ef3ec5cfa58b480470e
Binary files /dev/null and b/src/main/resources/org/python/core/JavaFunc.class differ
diff --git a/src/main/resources/org/python/core/JavaImportHelper.class b/src/main/resources/org/python/core/JavaImportHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bb6a5c1e8febe5b10d019c2780bc01daf2568e7
Binary files /dev/null and b/src/main/resources/org/python/core/JavaImportHelper.class differ
diff --git a/src/main/resources/org/python/core/JavaImporter.class b/src/main/resources/org/python/core/JavaImporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a912420f10b67d7b14d34181cb9592a96f8775d
Binary files /dev/null and b/src/main/resources/org/python/core/JavaImporter.class differ
diff --git a/src/main/resources/org/python/core/JavaToPyMapEntry.class b/src/main/resources/org/python/core/JavaToPyMapEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..51322d3feb148e3480ed5638fe02234502a4b9b7
Binary files /dev/null and b/src/main/resources/org/python/core/JavaToPyMapEntry.class differ
diff --git a/src/main/resources/org/python/core/JythonInitializer.class b/src/main/resources/org/python/core/JythonInitializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee86789a6d05c4dbe2a21372116f4e20901dadb6
Binary files /dev/null and b/src/main/resources/org/python/core/JythonInitializer.class differ
diff --git a/src/main/resources/org/python/core/LongInfo.class b/src/main/resources/org/python/core/LongInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..b37c7865f7797642f33032173e31470edbe3ef03
Binary files /dev/null and b/src/main/resources/org/python/core/LongInfo.class differ
diff --git a/src/main/resources/org/python/core/MakeProxies.class b/src/main/resources/org/python/core/MakeProxies.class
new file mode 100644
index 0000000000000000000000000000000000000000..3234d4564f54d4261f6732674a765d54a14a12d8
Binary files /dev/null and b/src/main/resources/org/python/core/MakeProxies.class differ
diff --git a/src/main/resources/org/python/core/MaxFunction.class b/src/main/resources/org/python/core/MaxFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..cae6d6200f65663d2ba573fe6433f397325031f8
Binary files /dev/null and b/src/main/resources/org/python/core/MaxFunction.class differ
diff --git a/src/main/resources/org/python/core/MinFunction.class b/src/main/resources/org/python/core/MinFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..30bcd0757c43e6455a427c0c0acfc3ee9c6f6b97
Binary files /dev/null and b/src/main/resources/org/python/core/MinFunction.class differ
diff --git a/src/main/resources/org/python/core/NewCompilerResources.class b/src/main/resources/org/python/core/NewCompilerResources.class
new file mode 100644
index 0000000000000000000000000000000000000000..c38788638645fc6b78f1be6bfb74e7b6e0b4f52e
Binary files /dev/null and b/src/main/resources/org/python/core/NewCompilerResources.class differ
diff --git a/src/main/resources/org/python/core/NextFunction.class b/src/main/resources/org/python/core/NextFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..156cbf8b9fc9e6cbd816c786ecaa1da7e3ca147e
Binary files /dev/null and b/src/main/resources/org/python/core/NextFunction.class differ
diff --git a/src/main/resources/org/python/core/Opcode.class b/src/main/resources/org/python/core/Opcode.class
new file mode 100644
index 0000000000000000000000000000000000000000..f200b1809a3ab83cf64e4161d22a9f6ca88e7bac
Binary files /dev/null and b/src/main/resources/org/python/core/Opcode.class differ
diff --git a/src/main/resources/org/python/core/OpenFunction.class b/src/main/resources/org/python/core/OpenFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0e842c87247cd6dd3c01d08055c10ddaddf9692
Binary files /dev/null and b/src/main/resources/org/python/core/OpenFunction.class differ
diff --git a/src/main/resources/org/python/core/Options.class b/src/main/resources/org/python/core/Options.class
new file mode 100644
index 0000000000000000000000000000000000000000..b060501c51f810d5cb1b55e9d4922720e4815861
Binary files /dev/null and b/src/main/resources/org/python/core/Options.class differ
diff --git a/src/main/resources/org/python/core/ParserFacade$1.class b/src/main/resources/org/python/core/ParserFacade$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..7576a75e53055d860b9a75b543b67d30e3f5493f
Binary files /dev/null and b/src/main/resources/org/python/core/ParserFacade$1.class differ
diff --git a/src/main/resources/org/python/core/ParserFacade$ExpectedEncodingBufferedReader.class b/src/main/resources/org/python/core/ParserFacade$ExpectedEncodingBufferedReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..2634aa9ae6d4353911163129ac4ecc5b932c75b4
Binary files /dev/null and b/src/main/resources/org/python/core/ParserFacade$ExpectedEncodingBufferedReader.class differ
diff --git a/src/main/resources/org/python/core/ParserFacade.class b/src/main/resources/org/python/core/ParserFacade.class
new file mode 100644
index 0000000000000000000000000000000000000000..41fc71b10b8a04ffa408c8a50eb9678900adb9de
Binary files /dev/null and b/src/main/resources/org/python/core/ParserFacade.class differ
diff --git a/src/main/resources/org/python/core/PlainConsole.class b/src/main/resources/org/python/core/PlainConsole.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b4714a56f1d8c47277b150c88c7c1a58e0ed4ab
Binary files /dev/null and b/src/main/resources/org/python/core/PlainConsole.class differ
diff --git a/src/main/resources/org/python/core/Pragma$ForbiddenPragmaModule.class b/src/main/resources/org/python/core/Pragma$ForbiddenPragmaModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4b557d3b1ea82e85e183cad7439ed5987b28128
Binary files /dev/null and b/src/main/resources/org/python/core/Pragma$ForbiddenPragmaModule.class differ
diff --git a/src/main/resources/org/python/core/Pragma$PragmaModule.class b/src/main/resources/org/python/core/Pragma$PragmaModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef77586932a3eef66f549cb5f4950ec17c890304
Binary files /dev/null and b/src/main/resources/org/python/core/Pragma$PragmaModule.class differ
diff --git a/src/main/resources/org/python/core/Pragma.class b/src/main/resources/org/python/core/Pragma.class
new file mode 100644
index 0000000000000000000000000000000000000000..44e929fa260143a62f002cc6c1f3c33733e976ad
Binary files /dev/null and b/src/main/resources/org/python/core/Pragma.class differ
diff --git a/src/main/resources/org/python/core/PragmaReceiver.class b/src/main/resources/org/python/core/PragmaReceiver.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5a74da0d9c363e6ef9384e4dbeaca2251313945
Binary files /dev/null and b/src/main/resources/org/python/core/PragmaReceiver.class differ
diff --git a/src/main/resources/org/python/core/PrintFunction.class b/src/main/resources/org/python/core/PrintFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdafe61f75ca3c9b52e52ca7d46e49cae18ce049
Binary files /dev/null and b/src/main/resources/org/python/core/PrintFunction.class differ
diff --git a/src/main/resources/org/python/core/Py$SingletonResolver.class b/src/main/resources/org/python/core/Py$SingletonResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..fcad515a955a50a9ab1f77cf478000a492e695bf
Binary files /dev/null and b/src/main/resources/org/python/core/Py$SingletonResolver.class differ
diff --git a/src/main/resources/org/python/core/Py.class b/src/main/resources/org/python/core/Py.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2ca808776bc41d2dcb2c88374c76313c8b95a12
Binary files /dev/null and b/src/main/resources/org/python/core/Py.class differ
diff --git a/src/main/resources/org/python/core/Py.class-bak.class b/src/main/resources/org/python/core/Py.class-bak.class
new file mode 100644
index 0000000000000000000000000000000000000000..e95dd3e6091b796d841ea82df12903492174fca4
Binary files /dev/null and b/src/main/resources/org/python/core/Py.class-bak.class differ
diff --git a/src/main/resources/org/python/core/Py2kBuffer$PyExposer.class b/src/main/resources/org/python/core/Py2kBuffer$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a5d576946759a9dc4b1d7ce11e03b33fec17386
Binary files /dev/null and b/src/main/resources/org/python/core/Py2kBuffer$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/Py2kBuffer$buffer___add___exposer.class b/src/main/resources/org/python/core/Py2kBuffer$buffer___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba1e91b174a59b7fbc1a0f918c441034137dda2e
Binary files /dev/null and b/src/main/resources/org/python/core/Py2kBuffer$buffer___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/Py2kBuffer$buffer___mul___exposer.class b/src/main/resources/org/python/core/Py2kBuffer$buffer___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..14ea9f4c1c2074ff7054643d2e08ccb5e6f968e4
Binary files /dev/null and b/src/main/resources/org/python/core/Py2kBuffer$buffer___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/Py2kBuffer$buffer___rmul___exposer.class b/src/main/resources/org/python/core/Py2kBuffer$buffer___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a264c943ed6cc006fcadf89e74543ab0257686b5
Binary files /dev/null and b/src/main/resources/org/python/core/Py2kBuffer$buffer___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/Py2kBuffer$exposed___new__.class b/src/main/resources/org/python/core/Py2kBuffer$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..897552226f172eb75cd291cc2a2b527c9dc5419c
Binary files /dev/null and b/src/main/resources/org/python/core/Py2kBuffer$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/Py2kBuffer.class b/src/main/resources/org/python/core/Py2kBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..482cb8a225b53f356f69e42353db9d9881708174
Binary files /dev/null and b/src/main/resources/org/python/core/Py2kBuffer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$1.class b/src/main/resources/org/python/core/PyArray$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3f4cd4f5b70afcd9e70b00570f0f5f64cd5a39d
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$1.class differ
diff --git a/src/main/resources/org/python/core/PyArray$ArrayDelegate.class b/src/main/resources/org/python/core/PyArray$ArrayDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..56cc33f2b67769d99555ca6fc1d4fcaa1d8316b6
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$ArrayDelegate.class differ
diff --git a/src/main/resources/org/python/core/PyArray$PyExposer.class b/src/main/resources/org/python/core/PyArray$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..af33c2d46f516c0b08c03cab0ea837ff1854627f
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___add___exposer.class b/src/main/resources/org/python/core/PyArray$array___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5aca3bd0d767dda34a3dee220f17d752208d2b2e
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___contains___exposer.class b/src/main/resources/org/python/core/PyArray$array___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..19e68d60f664fa6737f1dd000611410bfbab2295
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___delitem___exposer.class b/src/main/resources/org/python/core/PyArray$array___delitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8daf065b148e0a15dbbfcef3dfa4beaad91c7994
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___delitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___delslice___exposer.class b/src/main/resources/org/python/core/PyArray$array___delslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f67305e56dfbfb3b3613a58162590f62aac58684
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___delslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___eq___exposer.class b/src/main/resources/org/python/core/PyArray$array___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..931bba6f22a4574cd89f4e7fc844f8d63615cabd
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___ge___exposer.class b/src/main/resources/org/python/core/PyArray$array___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..841b8c2d2b90396b5fba86f2454def8fe63450a2
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___getitem___exposer.class b/src/main/resources/org/python/core/PyArray$array___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb56ece506d299ffa882b84be55486e2672772d5
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___getslice___exposer.class b/src/main/resources/org/python/core/PyArray$array___getslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cf6660f93676dbf1a5ba8e08b5faa3d579bc5e3
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___getslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___gt___exposer.class b/src/main/resources/org/python/core/PyArray$array___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..81b8ee3c817b1ad9b62e175d1f6ddab475a6eed1
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___iadd___exposer.class b/src/main/resources/org/python/core/PyArray$array___iadd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c13919fb819913c1683c0d5a40be81442286103
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___iadd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___imul___exposer.class b/src/main/resources/org/python/core/PyArray$array___imul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a6eb31e43a937f23bf56a9596cccee311402fb8
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___imul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___iter___exposer.class b/src/main/resources/org/python/core/PyArray$array___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8348e78dc13bd3e9a5afcbeb1db3f5d88151f9a8
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___le___exposer.class b/src/main/resources/org/python/core/PyArray$array___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..efd36f2c88494486b56b37668c705d281010f099
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___len___exposer.class b/src/main/resources/org/python/core/PyArray$array___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3866d77b389353903be336efcc532b6214465530
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___lt___exposer.class b/src/main/resources/org/python/core/PyArray$array___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a6613efc6db28d2df09e5a31b993998ded1ca8f
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___mul___exposer.class b/src/main/resources/org/python/core/PyArray$array___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9fab98bef2e5368685f31b2f85431c5fbab0d1b
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___ne___exposer.class b/src/main/resources/org/python/core/PyArray$array___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a34232a62a9f340bce329311bb1aa27ca2172f2
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___nonzero___exposer.class b/src/main/resources/org/python/core/PyArray$array___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..787e1f20cb2a6d92b5fb836a3bc93686551c4ee5
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___reduce___exposer.class b/src/main/resources/org/python/core/PyArray$array___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dd28050070be60ec11e1f385a2fd66f19e2890b
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___rmul___exposer.class b/src/main/resources/org/python/core/PyArray$array___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..50dc271beaba5bd35935d2aa914f3e9b8d7a7102
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___setitem___exposer.class b/src/main/resources/org/python/core/PyArray$array___setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..16a3b38e1e7d9a00d68bfa3b39a89464d4f9ae88
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___setitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array___setslice___exposer.class b/src/main/resources/org/python/core/PyArray$array___setslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3abe590e8b1ca497c76357faff629de271c8033
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array___setslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_append_exposer.class b/src/main/resources/org/python/core/PyArray$array_append_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..370df6b1e49f61da80b2e62e10dc29011a4da57f
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_append_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_byteswap_exposer.class b/src/main/resources/org/python/core/PyArray$array_byteswap_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e939e12beafeeac8ef6e1dd2b7d2ccf60aa7094d
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_byteswap_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_count_exposer.class b/src/main/resources/org/python/core/PyArray$array_count_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9be2d5524506c20aa659f94d520cd9139730ddc4
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_count_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_extend_exposer.class b/src/main/resources/org/python/core/PyArray$array_extend_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d535ec2aa5c848762686ec08627bfc3d3cf4832
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_extend_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_fromfile_exposer.class b/src/main/resources/org/python/core/PyArray$array_fromfile_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4db8eced48a328c3a871d2454933541f049d9344
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_fromfile_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_fromlist_exposer.class b/src/main/resources/org/python/core/PyArray$array_fromlist_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..82ba50cfee629d9b7453a7945fdd1824e2f5a779
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_fromlist_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_fromstring_exposer.class b/src/main/resources/org/python/core/PyArray$array_fromstring_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..96f0a460289781ad907ce1077b53d444d030252e
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_fromstring_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_fromunicode_exposer.class b/src/main/resources/org/python/core/PyArray$array_fromunicode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..65c78ec55dc75723db8f11ec0b8d79854dbce288
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_fromunicode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_index_exposer.class b/src/main/resources/org/python/core/PyArray$array_index_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..31c1844df243531d3e9860bddb0d462f171b1735
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_index_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_insert_exposer.class b/src/main/resources/org/python/core/PyArray$array_insert_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e56070fae778cca1f0d66c78d60736e0d554634
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_insert_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_pop_exposer.class b/src/main/resources/org/python/core/PyArray$array_pop_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c95f0cafd290e2113eb97a05e3cb5424d0dfa75b
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_pop_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_remove_exposer.class b/src/main/resources/org/python/core/PyArray$array_remove_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6096bd87e9f4430070f48a3966e8c3afb6b1f4ab
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_remove_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_reverse_exposer.class b/src/main/resources/org/python/core/PyArray$array_reverse_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3ea5fab13d8dc8ea5fd304f168dcd2571283143
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_reverse_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_tofile_exposer.class b/src/main/resources/org/python/core/PyArray$array_tofile_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..53386f15876130713e2e2335ff76eb936b276c8a
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_tofile_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_tolist_exposer.class b/src/main/resources/org/python/core/PyArray$array_tolist_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b18d113f0f501405ba6b60ce1447e050fc12745
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_tolist_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_tostring_exposer.class b/src/main/resources/org/python/core/PyArray$array_tostring_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c591e827e00b1e32eee85e75b96e272a189966dd
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_tostring_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_tounicode_exposer.class b/src/main/resources/org/python/core/PyArray$array_tounicode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c3824c479e954be39c6f37a1c3b7ac454a53153
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_tounicode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$array_write_exposer.class b/src/main/resources/org/python/core/PyArray$array_write_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..559e9e7fe1f59adecc3d2317801e199df75295ef
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$array_write_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyArray$exposed___new__.class b/src/main/resources/org/python/core/PyArray$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..0887d17af44ea8f851b0ac638a0d7c5b7c783108
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyArray$itemsize_descriptor.class b/src/main/resources/org/python/core/PyArray$itemsize_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..87ac23e91a600f212024486ab42288a97631f6c6
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$itemsize_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyArray$typecode_descriptor.class b/src/main/resources/org/python/core/PyArray$typecode_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3c41857ed3575044019b1777888e482a8c3c2e7
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray$typecode_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyArray.class b/src/main/resources/org/python/core/PyArray.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b46062b13abff20dc09b70570cbf2d4cdfbf3cf
Binary files /dev/null and b/src/main/resources/org/python/core/PyArray.class differ
diff --git a/src/main/resources/org/python/core/PyArrayDerived.class b/src/main/resources/org/python/core/PyArrayDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9703c344b49f3971dc0a8109c7af0b54cdd31383
Binary files /dev/null and b/src/main/resources/org/python/core/PyArrayDerived.class differ
diff --git a/src/main/resources/org/python/core/PyArrayTest.class b/src/main/resources/org/python/core/PyArrayTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..df930051c73e23200498ab319bbe0971825fa79d
Binary files /dev/null and b/src/main/resources/org/python/core/PyArrayTest.class differ
diff --git a/src/main/resources/org/python/core/PyAttributeDeleted.class b/src/main/resources/org/python/core/PyAttributeDeleted.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf25afab010eacdaf0c91f35c0b19539d705996a
Binary files /dev/null and b/src/main/resources/org/python/core/PyAttributeDeleted.class differ
diff --git a/src/main/resources/org/python/core/PyBUF.class b/src/main/resources/org/python/core/PyBUF.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b27cf33128a100624ec9f09f9f2adfa91b1f649
Binary files /dev/null and b/src/main/resources/org/python/core/PyBUF.class differ
diff --git a/src/main/resources/org/python/core/PyBaseCode.class b/src/main/resources/org/python/core/PyBaseCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..47976162d8dd46bbb94ad96a4692ece5db8f1a04
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseCode.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException___getitem___exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc6cb408515c98a68d75833f023870cb35476771
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException___getslice___exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException___getslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf58999a140fdc7da39b2783b4e9685c64fcd3ed
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException___getslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException___init___exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2e5a335124cebe9821e4f8cc72724b315ea813e
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException___reduce___exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fe223bca27c1b27002cf9deae8e9c11f7395a2e
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException___setattr___exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException___setattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce34e5ab72bd7996b1b280b8242b4dbd8a96dfab
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException___setattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException___setstate___exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException___setstate___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a07ed2fc7900d78fd4afc8ca6392e79ba0ab98b5
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException___setstate___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException___str___exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException___str___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b69dd013222d0ca23e510593f8e5a008f0f0fdcc
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException___str___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException___unicode___exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException___unicode___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d399afc0f9943361dba0aee8af6436ac8e9f66a
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException___unicode___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$BaseException_toString_exposer.class b/src/main/resources/org/python/core/PyBaseException$BaseException_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff65958458792831c10ed78c5bc9a6fe4e2814b5
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$BaseException_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$PyExposer.class b/src/main/resources/org/python/core/PyBaseException$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fa909cd80d4d4a02e76330ff00bb80dce7d671f
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$__dict___descriptor.class b/src/main/resources/org/python/core/PyBaseException$__dict___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..570c6e02f83fe5f5690bace0ebdf23afbcdbb6b8
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$__dict___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$args_descriptor.class b/src/main/resources/org/python/core/PyBaseException$args_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..086f72e408e46b8d9dddeff6dec03db6220da5a2
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$args_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$exposed___new__.class b/src/main/resources/org/python/core/PyBaseException$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..9485edc518e2ed51b4345e1fc256b3d86b21eee3
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException$message_descriptor.class b/src/main/resources/org/python/core/PyBaseException$message_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb18bafca5494db244b7abdef1774a7386554ac2
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException$message_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyBaseException.class b/src/main/resources/org/python/core/PyBaseException.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ee762e7b5d93de1e4d7ddcc748ae946fe02888c
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseException.class differ
diff --git a/src/main/resources/org/python/core/PyBaseExceptionDerived.class b/src/main/resources/org/python/core/PyBaseExceptionDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dea1c69fca3b7fdb698cdc9000701e52d750c7b
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseExceptionDerived.class differ
diff --git a/src/main/resources/org/python/core/PyBaseString$PyExposer.class b/src/main/resources/org/python/core/PyBaseString$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c980703a245bb7f62d695a304448bd59848177d
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseString$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyBaseString.class b/src/main/resources/org/python/core/PyBaseString.class
new file mode 100644
index 0000000000000000000000000000000000000000..941cb1ee9feabe13369e5fd20a137fb0cb09e5f9
Binary files /dev/null and b/src/main/resources/org/python/core/PyBaseString.class differ
diff --git a/src/main/resources/org/python/core/PyBeanEvent.class b/src/main/resources/org/python/core/PyBeanEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..aef6e82b6948a38bcf6c8c81af64953f4141e5c1
Binary files /dev/null and b/src/main/resources/org/python/core/PyBeanEvent.class differ
diff --git a/src/main/resources/org/python/core/PyBeanEventProperty.class b/src/main/resources/org/python/core/PyBeanEventProperty.class
new file mode 100644
index 0000000000000000000000000000000000000000..f20874f9ab7e477ef81bea9cdd8a94281a36e4a9
Binary files /dev/null and b/src/main/resources/org/python/core/PyBeanEventProperty.class differ
diff --git a/src/main/resources/org/python/core/PyBeanProperty.class b/src/main/resources/org/python/core/PyBeanProperty.class
new file mode 100644
index 0000000000000000000000000000000000000000..831f6c33d29b07230d69f302fdd0871bb39e19ac
Binary files /dev/null and b/src/main/resources/org/python/core/PyBeanProperty.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$PyExposer.class b/src/main/resources/org/python/core/PyBoolean$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b89fda75250ec308fa176b9bb66be15821ea3f4
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool___abs___exposer.class b/src/main/resources/org/python/core/PyBoolean$bool___abs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5c7ef9f24e1c1e19649f27bca4f6e72a609f543
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool___abs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool___and___exposer.class b/src/main/resources/org/python/core/PyBoolean$bool___and___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..20c88a30dde5ee4f537fc229fcf4e30400ff59a1
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool___and___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool___hash___exposer.class b/src/main/resources/org/python/core/PyBoolean$bool___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..16e7074e6d30661cc370e5f8e13255b3380716e6
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool___neg___exposer.class b/src/main/resources/org/python/core/PyBoolean$bool___neg___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcd049b5b91eb236d0efdbc6ed5d3c2773b21761
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool___neg___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool___nonzero___exposer.class b/src/main/resources/org/python/core/PyBoolean$bool___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4de1651c68e46a8f36cef6aa8d723d1477138f6
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool___or___exposer.class b/src/main/resources/org/python/core/PyBoolean$bool___or___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..73b010ef478c8b7d8bd388cf4c3d4483d40b9d37
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool___or___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool___pos___exposer.class b/src/main/resources/org/python/core/PyBoolean$bool___pos___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9093e9c79c659275518af6567d2c7b46f2c223b2
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool___pos___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool___xor___exposer.class b/src/main/resources/org/python/core/PyBoolean$bool___xor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec2ee8372d118d23e79429166f98ecbdf301f22e
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool___xor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$bool_toString_exposer.class b/src/main/resources/org/python/core/PyBoolean$bool_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..16e1c84196745249e3a32c4e27ecea5598dcffbd
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$bool_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean$exposed___new__.class b/src/main/resources/org/python/core/PyBoolean$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd25bd8eb5cbf8df6378ddcda837fb9cf3f9561f
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyBoolean.class b/src/main/resources/org/python/core/PyBoolean.class
new file mode 100644
index 0000000000000000000000000000000000000000..56ff670e6e5b983c2c18f145105cc848f84372c9
Binary files /dev/null and b/src/main/resources/org/python/core/PyBoolean.class differ
diff --git a/src/main/resources/org/python/core/PyBuffer$Pointer.class b/src/main/resources/org/python/core/PyBuffer$Pointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..06b815303b5bd3caf07bae30d7ba901ec4e75f9d
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuffer$Pointer.class differ
diff --git a/src/main/resources/org/python/core/PyBuffer.class b/src/main/resources/org/python/core/PyBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..59abffed6bcfd21ca6c2fb70bcdbc06985a613bc
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuffer.class differ
diff --git a/src/main/resources/org/python/core/PyBufferTest$BufferTestPair.class b/src/main/resources/org/python/core/PyBufferTest$BufferTestPair.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a134a9b01ea086bcbaa7e99b0ac37719a58c866
Binary files /dev/null and b/src/main/resources/org/python/core/PyBufferTest$BufferTestPair.class differ
diff --git a/src/main/resources/org/python/core/PyBufferTest$ByteMaterial.class b/src/main/resources/org/python/core/PyBufferTest$ByteMaterial.class
new file mode 100644
index 0000000000000000000000000000000000000000..742d77e9f54e3c621e9d74a89cfe1f8cafb6f7f1
Binary files /dev/null and b/src/main/resources/org/python/core/PyBufferTest$ByteMaterial.class differ
diff --git a/src/main/resources/org/python/core/PyBufferTest$SimpleExporter.class b/src/main/resources/org/python/core/PyBufferTest$SimpleExporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7875940f5c03d89cf46306809f59314b8b5b30c
Binary files /dev/null and b/src/main/resources/org/python/core/PyBufferTest$SimpleExporter.class differ
diff --git a/src/main/resources/org/python/core/PyBufferTest$SimpleWritableExporter$1.class b/src/main/resources/org/python/core/PyBufferTest$SimpleWritableExporter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bcd2b7da2d98492c9c052924a5ebc305adc5a0b
Binary files /dev/null and b/src/main/resources/org/python/core/PyBufferTest$SimpleWritableExporter$1.class differ
diff --git a/src/main/resources/org/python/core/PyBufferTest$SimpleWritableExporter.class b/src/main/resources/org/python/core/PyBufferTest$SimpleWritableExporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb10d551b836ebb24530ccd814bce4731f2a1afa
Binary files /dev/null and b/src/main/resources/org/python/core/PyBufferTest$SimpleWritableExporter.class differ
diff --git a/src/main/resources/org/python/core/PyBufferTest$StringExporter.class b/src/main/resources/org/python/core/PyBufferTest$StringExporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d62f018b262c34e5394069828ccd80f7b411308
Binary files /dev/null and b/src/main/resources/org/python/core/PyBufferTest$StringExporter.class differ
diff --git a/src/main/resources/org/python/core/PyBufferTest$TestableExporter.class b/src/main/resources/org/python/core/PyBufferTest$TestableExporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..8496915503cbb239b507a0248533bceabd90ba0c
Binary files /dev/null and b/src/main/resources/org/python/core/PyBufferTest$TestableExporter.class differ
diff --git a/src/main/resources/org/python/core/PyBufferTest.class b/src/main/resources/org/python/core/PyBufferTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf6cd8e5f62516dbc097fc35acfb779f16751f78
Binary files /dev/null and b/src/main/resources/org/python/core/PyBufferTest.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable$DefaultInfo.class b/src/main/resources/org/python/core/PyBuiltinCallable$DefaultInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd7ed3d3823f7da6425b2c16089c73c375e2d3b4
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable$DefaultInfo.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable$Info.class b/src/main/resources/org/python/core/PyBuiltinCallable$Info.class
new file mode 100644
index 0000000000000000000000000000000000000000..481e269f3dc21060f5c2784067bf8f8ee7708d13
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable$Info.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable$PyExposer.class b/src/main/resources/org/python/core/PyBuiltinCallable$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa58337aad65c6eee218186c7ec68ba42c3630db
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable$__call___descriptor.class b/src/main/resources/org/python/core/PyBuiltinCallable$__call___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..06e858c9ddba4839165360d35f99a3918eb97669
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable$__call___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable$__doc___descriptor.class b/src/main/resources/org/python/core/PyBuiltinCallable$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1906fb2d63373f6ae0be8aeffd160fa2cc51b636
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable$__module___descriptor.class b/src/main/resources/org/python/core/PyBuiltinCallable$__module___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e9a58777089e4c9e77c097f7112c5682dab2b4f
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable$__module___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable$__name___descriptor.class b/src/main/resources/org/python/core/PyBuiltinCallable$__name___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a31ac0a5211b3bc9ea5f015ae06feaa0cf3dadbe
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable$__name___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable$__self___descriptor.class b/src/main/resources/org/python/core/PyBuiltinCallable$__self___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a5a5b11c6ff7ee30b893a4db3364541caa94538
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable$__self___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinCallable.class b/src/main/resources/org/python/core/PyBuiltinCallable.class
new file mode 100644
index 0000000000000000000000000000000000000000..c52d6931d169297c6272125e7f3d8e0f35e7f829
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinCallable.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinClassMethodNarrow.class b/src/main/resources/org/python/core/PyBuiltinClassMethodNarrow.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca73b364f8c289eea587d513d2b9641c1411c809
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinClassMethodNarrow.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinFunction.class b/src/main/resources/org/python/core/PyBuiltinFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5980e3aef5d8ccdd6c5195c3314ce8b96512a05
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinFunction.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinFunctionNarrow.class b/src/main/resources/org/python/core/PyBuiltinFunctionNarrow.class
new file mode 100644
index 0000000000000000000000000000000000000000..91050419142ac4f8f6d76f399c00193ea909ab9e
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinFunctionNarrow.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinFunctionSet.class b/src/main/resources/org/python/core/PyBuiltinFunctionSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9721a7f09b90574df6c288ce1b85bb3f2029fd5
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinFunctionSet.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinMethod.class b/src/main/resources/org/python/core/PyBuiltinMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..bff7800f3115c01b8e227ae44361a42bd7339f81
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinMethod.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinMethodNarrow.class b/src/main/resources/org/python/core/PyBuiltinMethodNarrow.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbfb95b7150375fac63c23541fbee7fc1bc2df92
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinMethodNarrow.class differ
diff --git a/src/main/resources/org/python/core/PyBuiltinMethodSet.class b/src/main/resources/org/python/core/PyBuiltinMethodSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ad1def3fafb291eb7d8195cebc586d6f049bc2e
Binary files /dev/null and b/src/main/resources/org/python/core/PyBuiltinMethodSet.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$1.class b/src/main/resources/org/python/core/PyByteArray$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c947fb7a43adcc3f2a17a36fb8a05295b44a96a
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$1.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$PyExposer.class b/src/main/resources/org/python/core/PyByteArray$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..77f98d0496222a9d0d333e73c11868aeb6c73c15
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___add___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e468329a7dd219c6daa5e8d48e1d2e2f0354d566
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___alloc___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___alloc___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2cfb54a8cb4886ee7712b0860543cc1f678311b8
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___alloc___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___contains___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f415d0a8f3dc4d8a0e34739a8f0a8e386f3be76a
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___eq___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f09b7a0b9971abc10bd394d8793941739e02fde1
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___ge___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a065b1b050c4ee7473df7716714e7444757533f7
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___getitem___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c6e140e2ce7f55b3801e5eb7ec267b28be461bf
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___gt___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0d90d92b218e88e5f91bba65e7893612c4d4770
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___hash___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..134714d3d537f29f4ea904806bc4de1aa599e2ed
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___iadd___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___iadd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..32ed01914f3d042b8e8f0837f94e3f8acfab6eb3
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___iadd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___imul___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___imul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..23360104c564841bc70d6f05f12d90d09388e122
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___imul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___init___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf81cc00da96298e3751c8954eb17ff8fd31163c
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___le___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d4e5223dadca3e8faa5100c7984f7d87c5b5d95
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___len___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..62015fe2039b5c527bb27c7947dda620b55485b3
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___lt___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8521a3914e88235add8095fdc235ff205ee0635b
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___mul___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..45c014d7fb92e6bb8f4c61a7a17b05ce6ce9602a
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___ne___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4fdbb176ea9c1aa4747437e6ec36d24701671c4
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___reduce___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb3d087f34feb46bcf3705a755ce2351fe51355f
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___rmul___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..392a993dd6e15d48f4b4e53666b7a33a2c5c246d
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray___setitem___exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray___setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..48228c1577a7e6cf738e73fccd6f74731eb04168
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray___setitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_append_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_append_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f73657403ca13114c9e5f9afde61164554c1b4ae
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_append_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_capitalize_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_capitalize_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..70b7070d7677d302c54a8e39915ec4c0cd083814
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_capitalize_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_center_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_center_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d116fa6f21500f6a23cf1a6d17292405d65b6ba7
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_center_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_count_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_count_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b00d51157f6415d2ecafed27c938346c8c97548e
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_count_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_decode_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_decode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bac8fdde05a1957520151a7cc468c6668a44020a
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_decode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_endswith_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_endswith_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc0ac1fe5c1c088f392458aa9c7504697dc1dbce
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_endswith_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_expandtabs_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_expandtabs_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..95928ef703a9d4855f579de2ce8c2bdb10340394
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_expandtabs_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_extend_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_extend_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f64728cd1c135c2586943b342f54bf627af61921
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_extend_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_find_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_find_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bf265c47f965a004f619ad50c6c3bc6bfe4564d
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_find_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_fromhex_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_fromhex_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfb88184747cd0ea1e5c1f62a6e0b8c09bd68ed0
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_fromhex_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_index_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_index_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c190d9e025dfa8a0b6acdfcc134d55fbae5c6044
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_index_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_insert_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_insert_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2139ab356c774113a1d938e44de789f9892efaa
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_insert_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_isalnum_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_isalnum_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f9433ae02ad2e0fb7e78a1c1f64c0f7255217ea
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_isalnum_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_isalpha_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_isalpha_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b293b016c67d222f1ebca8249c5114ba3cc6a601
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_isalpha_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_isdigit_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_isdigit_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd80bfcfaf472ff97547aea985df6a55cedee588
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_isdigit_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_islower_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_islower_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0244a0cb99ef7e9201dce81dfed0609f87e160a1
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_islower_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_isspace_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_isspace_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b0ffd9992da778a9a958f3dd89d702e464eaa64
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_isspace_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_istitle_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_istitle_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9663c510a34807cb87e8b02e75de787f0ee79a0
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_istitle_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_isupper_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_isupper_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c99f3c94cb48775a745567247d9cd4635dd7ab5
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_isupper_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_join_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_join_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d58632a5a84cd4263e7adeead02fdb5544d6ea7
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_join_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_ljust_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_ljust_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9913b00522de7072864f593c836a966eaa0e2e77
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_ljust_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_lower_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_lower_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4fcc8666aba044c106ae2a6649ca6f022e53b21
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_lower_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_lstrip_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_lstrip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8f200b69f6aafc2a97357513b71bdc7c4c313c9
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_lstrip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_partition_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_partition_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..afee93600fa5f97b0a1e21697798bb990f3321ef
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_partition_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_pop_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_pop_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..493518b14a0e891c5136699f148bdb2a8d72ab44
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_pop_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_remove_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_remove_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..37e2b3d63fc15116244eda8e5c842e81adb02921
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_remove_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_replace_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_replace_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ab308f6882af109608547d85a1a747a2675711a
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_replace_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_repr_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_repr_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c641591645da498eafd6f307cf07c49705825e3
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_repr_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_reverse_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_reverse_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..de74b9292369bf25efc9a1810b07fb9b9571c84b
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_reverse_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_rfind_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_rfind_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b60e429fd87c3f842e725ed03f5a49a516d25023
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_rfind_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_rindex_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_rindex_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..168f86a1b6c642f192cb0bc19ba5eeb9ecf9c432
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_rindex_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_rjust_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_rjust_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b87701eae9f6e622b699b5fcd20cd8cfc9bd60d7
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_rjust_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_rpartition_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_rpartition_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c4d68b9c5cee5bc014e2077ddff89596d04cba6
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_rpartition_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_rsplit_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_rsplit_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea6ece94ae0e837ad627033690432f67ec24c8ab
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_rsplit_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_rstrip_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_rstrip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..36f5909ce80189461e000a0e93c4ad162cb9e5be
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_rstrip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_split_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_split_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..572a856c65a623c52dce01616f66f4b46f092039
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_split_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_splitlines_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_splitlines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4c7038d1832d02b5cd3e3b35b1f46806e3f279a
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_splitlines_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_startswith_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_startswith_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2edbf04177e22c441ded79a7e659c02b7b12c254
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_startswith_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_str_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_str_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e7439784fa6482c4267f3aefbbac3fcf335ac0a
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_str_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_strip_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_strip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..478815bb8927890da74f272373d4779efe5d0e27
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_strip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_swapcase_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_swapcase_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..41058ff8898ddfd4bddd07c0f2b8cf3322358518
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_swapcase_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_title_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_title_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..25b88bb27ca54bf569d0ae31565fb38a72be3ed4
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_title_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_translate_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_translate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..605c26a47ef282cf8d41681aa2feb20ddfce4cda
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_translate_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_upper_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_upper_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7868ac316448603f38629d8db7a7b9decbebc158
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_upper_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$bytearray_zfill_exposer.class b/src/main/resources/org/python/core/PyByteArray$bytearray_zfill_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b6fc924595f9a390291142a95217c795a4de3e6
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$bytearray_zfill_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray$exposed___new__.class b/src/main/resources/org/python/core/PyByteArray$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b870e0af60ede21521fe7e67581e53004799d3f
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyByteArray.class b/src/main/resources/org/python/core/PyByteArray.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b70995f33adbb5502580820fbbd0211a3d05069
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArray.class differ
diff --git a/src/main/resources/org/python/core/PyByteArrayDerived.class b/src/main/resources/org/python/core/PyByteArrayDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..5165f9bf1cc25994c6e18c86d6460820c132472d
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArrayDerived.class differ
diff --git a/src/main/resources/org/python/core/PyByteArrayTest.class b/src/main/resources/org/python/core/PyByteArrayTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..20d02eadfe1d4f5222d2984c42250a5fc5dd0390
Binary files /dev/null and b/src/main/resources/org/python/core/PyByteArrayTest.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode$1.class b/src/main/resources/org/python/core/PyBytecode$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..abf227c8ae4cbc6e2e5508d6dbb59132cd8fccac
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode$1.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode$LineCache$Pair.class b/src/main/resources/org/python/core/PyBytecode$LineCache$Pair.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0930810b9a19aaf0ba92cdf268fa985dfab391e
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode$LineCache$Pair.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode$LineCache.class b/src/main/resources/org/python/core/PyBytecode$LineCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a0c6dbae8d15b9c2ed77f3bcd02b0fcd00a49c9
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode$LineCache.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode$PyStack.class b/src/main/resources/org/python/core/PyBytecode$PyStack.class
new file mode 100644
index 0000000000000000000000000000000000000000..571b55fc2ddf3bc39d6bc20801b534bbcff9d56c
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode$PyStack.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode$PyStackException.class b/src/main/resources/org/python/core/PyBytecode$PyStackException.class
new file mode 100644
index 0000000000000000000000000000000000000000..a12fa3e56d10caeb11edf81f6ee02bb3d8b55deb
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode$PyStackException.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode$PyStackWhy.class b/src/main/resources/org/python/core/PyBytecode$PyStackWhy.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3382436ddbea86c62fad8e9bca0a5bd90135585
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode$PyStackWhy.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode$PyTryBlock.class b/src/main/resources/org/python/core/PyBytecode$PyTryBlock.class
new file mode 100644
index 0000000000000000000000000000000000000000..149cfb5eac13d1e6b76be4ee3822ec6b1150b0c5
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode$PyTryBlock.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode$Why.class b/src/main/resources/org/python/core/PyBytecode$Why.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c04448244d20d5168262e9fda1c6f36cb0bf5ee
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode$Why.class differ
diff --git a/src/main/resources/org/python/core/PyBytecode.class b/src/main/resources/org/python/core/PyBytecode.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f882eb201836aeaeefd8ff8c78e248ee2c7e342
Binary files /dev/null and b/src/main/resources/org/python/core/PyBytecode.class differ
diff --git a/src/main/resources/org/python/core/PyCallIter.class b/src/main/resources/org/python/core/PyCallIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d8f8ed80100ced43a3b54fafdae90f346fde1ec
Binary files /dev/null and b/src/main/resources/org/python/core/PyCallIter.class differ
diff --git a/src/main/resources/org/python/core/PyCell$PyExposer.class b/src/main/resources/org/python/core/PyCell$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b21f8910ec375f1aab37766ed712424960316ce
Binary files /dev/null and b/src/main/resources/org/python/core/PyCell$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyCell$cell_contents_descriptor.class b/src/main/resources/org/python/core/PyCell$cell_contents_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a11b5c09cc95ec9b157a4803adf94afe7138398f
Binary files /dev/null and b/src/main/resources/org/python/core/PyCell$cell_contents_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyCell.class b/src/main/resources/org/python/core/PyCell.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef2dc226523902fa44e3db72ba9bcb60b4e791ee
Binary files /dev/null and b/src/main/resources/org/python/core/PyCell.class differ
diff --git a/src/main/resources/org/python/core/PyClass$PyExposer.class b/src/main/resources/org/python/core/PyClass$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcc0e2339c155e829221359404d9c68b15809b0c
Binary files /dev/null and b/src/main/resources/org/python/core/PyClass$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyClass$exposed___new__.class b/src/main/resources/org/python/core/PyClass$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..010d5c68b3641125466cd0d53e8250e1a3211368
Binary files /dev/null and b/src/main/resources/org/python/core/PyClass$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyClass.class b/src/main/resources/org/python/core/PyClass.class
new file mode 100644
index 0000000000000000000000000000000000000000..b327ed2e4214c4aead6495f3a4c00fa57e0fe45e
Binary files /dev/null and b/src/main/resources/org/python/core/PyClass.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethod$PyExposer.class b/src/main/resources/org/python/core/PyClassMethod$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f5ac0b7abd12614734b1729dbed5172d906ca45
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethod$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethod$classmethod___get___exposer.class b/src/main/resources/org/python/core/PyClassMethod$classmethod___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b06850121addd4515cb7d4eb43c064de7dba7ccb
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethod$classmethod___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethod$exposed___new__.class b/src/main/resources/org/python/core/PyClassMethod$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..3732d5b2e1c7581854fd9cac2ddf9e90c10c4ffa
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethod$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethod.class b/src/main/resources/org/python/core/PyClassMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..5035dc69025c16b717d60d00b9911d1df13f70fb
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethod.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethodDerived.class b/src/main/resources/org/python/core/PyClassMethodDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..deabdabf021ad254580b82a107ee6d9ff2b0e4de
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethodDerived.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethodDescr$PyExposer.class b/src/main/resources/org/python/core/PyClassMethodDescr$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..04478bc4efdb46c961585bd3650dcc78e621f8e4
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethodDescr$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethodDescr$__doc___descriptor.class b/src/main/resources/org/python/core/PyClassMethodDescr$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6492e1d49af5a7ee5bb12430fceee85f802c667
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethodDescr$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethodDescr$classmethod_descriptor___get___exposer.class b/src/main/resources/org/python/core/PyClassMethodDescr$classmethod_descriptor___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f32d1daa4169ee6fb5df1814ec6ade99cb14ad9
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethodDescr$classmethod_descriptor___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyClassMethodDescr.class b/src/main/resources/org/python/core/PyClassMethodDescr.class
new file mode 100644
index 0000000000000000000000000000000000000000..65b8b776b696e840c2b3a9f4df878e14a64e811a
Binary files /dev/null and b/src/main/resources/org/python/core/PyClassMethodDescr.class differ
diff --git a/src/main/resources/org/python/core/PyCode.class b/src/main/resources/org/python/core/PyCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba5ed25f5be0c0ed2fef61d1925d7348f63a7fd7
Binary files /dev/null and b/src/main/resources/org/python/core/PyCode.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$PyExposer.class b/src/main/resources/org/python/core/PyComplex$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7339a3f76c1ab7cf4ffe7727e3d1922dc0cdfd5a
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___abs___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___abs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4af6cd2b9dd6cafb9006da3f9688eefb1718ff43
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___abs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___add___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1450a0486103ac827a6fc1df0c24f457edc82410
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___coerce___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___coerce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a6b8dc2ff58572ac7145b5a2cb777303ea3994c
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___coerce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___div___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___div___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4593fc46e736e0d29e36d96231f8a094b8b67951
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___div___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___divmod___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___divmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..13def8bee246708b0ebb961beb3d94431a7e5aec
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___divmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___eq___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a923c7d2122ba8f74b36e01682ac18a24321682
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___float___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___float___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..da69ad2b792ded25261905f67b8f957daf67171d
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___float___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___floordiv___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___floordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..298f34749c606add38cdc0d1cc89afa9c9fd3dec
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___floordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___format___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___format___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..92c6e3af65bd62db541cd9b1ecc75880c7c84cde
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___format___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___ge___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2648c3c3d75a7c51c5d494c6dcf4328448ac820c
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___getnewargs___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___getnewargs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0dcd6a71ab26d8030c2de2dd89265e66d7c860da
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___getnewargs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___gt___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..694357601755f171d30ca40b3454796b5d7c9dd6
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___hash___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cc84c3465d7cc75881cddb7a102756f22827f8a
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___int___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee687f5fec779abf6fdf03e6d2745fab74a43827
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___int___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___le___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c3500b82b9d66ec2c0151f0672b991ebc9f2d19
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___long___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___long___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1694471b3d2c1d8cc474a73934676db0e8281ffc
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___long___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___lt___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a3c323a67465bc8fb65c4991533a09dd58f474c
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___mod___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___mod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..732ede01eac934ae33ab81f22bb5401d89d9a2ef
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___mod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___mul___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e1015c713be2e3107369751ad427124515fb44f
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___ne___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6691910f21568f587782ec6ef2fe4c719fe17aab
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___neg___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___neg___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a011185f24f6290571cd09bbec66d08c9c24511
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___neg___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___nonzero___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..62719de8474d40f7eca1483515fb33a5420eb1b4
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___pos___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___pos___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2891aae7c9a270df9334e4e93100f09a5ce139e5
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___pos___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___pow___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___pow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b329785c6e4e4a89a14ef9e14af8b5210aa4bab2
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___pow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___radd___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___radd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2d182201abfec550475cb4d0f826024976c7796
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___radd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___rdiv___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___rdiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..36a189a64c3291d535e42b3cd4b33f1d6371d59f
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___rdiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___rdivmod___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___rdivmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..26d6bdba52233164543f49a7193544d6a5466616
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___rdivmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___rfloordiv___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___rfloordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2de4dd61b60f5c3516263062c707a56ad37b519d
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___rfloordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___rmod___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___rmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..353b6e393752edfd9b031649303d211bf631f5ab
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___rmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___rmul___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..77ce1f6d7e04a1d4d5d731ac42faeb453f8c3703
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___rpow___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___rpow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c4c47c66edb1367dc69d6d7d6298f51d14592be
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___rpow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___rsub___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___rsub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4325261daa313c5835817e37b2c701a894e08eb7
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___rsub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___rtruediv___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___rtruediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d1b1062148757fea3012ab35b1e23ad6c646d113
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___rtruediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___sub___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..31c071476fc470889ff9684d93f2a82c968a805d
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex___truediv___exposer.class b/src/main/resources/org/python/core/PyComplex$complex___truediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..262d1bb34c6f31cf8f9ebb5edeb99d4a37cc172a
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex___truediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex_conjugate_exposer.class b/src/main/resources/org/python/core/PyComplex$complex_conjugate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9dcd52f1a093ffe202390cba2368bf1af197864
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex_conjugate_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$complex_toString_exposer.class b/src/main/resources/org/python/core/PyComplex$complex_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..20c7f2af7350dfcd4fd0172a2584b9d47ddecbbb
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$complex_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$exposed___new__.class b/src/main/resources/org/python/core/PyComplex$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..901e98ee3d2c7f0bfb289e19a6b6a712a3127faa
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$imag_descriptor.class b/src/main/resources/org/python/core/PyComplex$imag_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb00fa5e3effbf05a2a662a56126667d98c45bb9
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$imag_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyComplex$real_descriptor.class b/src/main/resources/org/python/core/PyComplex$real_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8280f1ebc3cfa51661c14a202a6f0798381bb3eb
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex$real_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyComplex.class b/src/main/resources/org/python/core/PyComplex.class
new file mode 100644
index 0000000000000000000000000000000000000000..a770bb8a3b7cf351ef1173ea901f9df67ef9d40b
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplex.class differ
diff --git a/src/main/resources/org/python/core/PyComplexDerived.class b/src/main/resources/org/python/core/PyComplexDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d7a1eda8206454095849e9ba483a821d6cd9f4d
Binary files /dev/null and b/src/main/resources/org/python/core/PyComplexDerived.class differ
diff --git a/src/main/resources/org/python/core/PyCompoundCallable.class b/src/main/resources/org/python/core/PyCompoundCallable.class
new file mode 100644
index 0000000000000000000000000000000000000000..f14fa99bb46d4e15821e2545f9de5c0d4ae11e24
Binary files /dev/null and b/src/main/resources/org/python/core/PyCompoundCallable.class differ
diff --git a/src/main/resources/org/python/core/PyDataDescr$PyExposer.class b/src/main/resources/org/python/core/PyDataDescr$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..001aba531f5dca31a7f482962de1478e80cdf1ba
Binary files /dev/null and b/src/main/resources/org/python/core/PyDataDescr$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyDataDescr$__doc___descriptor.class b/src/main/resources/org/python/core/PyDataDescr$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9722f34b8c59e34b5fe79752cb6399b6a126b8fc
Binary files /dev/null and b/src/main/resources/org/python/core/PyDataDescr$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyDataDescr$__name___descriptor.class b/src/main/resources/org/python/core/PyDataDescr$__name___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1605804bd682df1e16f73de2b34e839547448ec8
Binary files /dev/null and b/src/main/resources/org/python/core/PyDataDescr$__name___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyDataDescr$__objclass___descriptor.class b/src/main/resources/org/python/core/PyDataDescr$__objclass___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ac56979a616a702463602a8e2e33feceec0c736
Binary files /dev/null and b/src/main/resources/org/python/core/PyDataDescr$__objclass___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___delete___exposer.class b/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___delete___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f0ca48076ca3025ac0671a4f0e4c9bd7ae3691a
Binary files /dev/null and b/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___delete___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___get___exposer.class b/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..069becc49055ca1d91775a028eb185d6ca8c6afc
Binary files /dev/null and b/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___set___exposer.class b/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___set___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbf19b3a585105b9d77b1900162213017c8e6dfc
Binary files /dev/null and b/src/main/resources/org/python/core/PyDataDescr$getset_descriptor___set___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDataDescr.class b/src/main/resources/org/python/core/PyDataDescr.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cee3a865a146e8a7f0dc57c4369e377ce0090a7
Binary files /dev/null and b/src/main/resources/org/python/core/PyDataDescr.class differ
diff --git a/src/main/resources/org/python/core/PyDescriptor.class b/src/main/resources/org/python/core/PyDescriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9559806655949df0c0ca1bdfc262df8bd515a95c
Binary files /dev/null and b/src/main/resources/org/python/core/PyDescriptor.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$PyExposer.class b/src/main/resources/org/python/core/PyDictProxy$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8e61a685d70900895d657574327f33627aba57e
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$__str___exposer.class b/src/main/resources/org/python/core/PyDictProxy$__str___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9879fcc7bed21467d35aba231a51133d804d000
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$__str___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___cmp___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1f67c697a2d317635bb7a19945cb9c3deb5a45d
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___contains___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1535aadac1257db1c1d2bdbc24fe90ec622a4e7
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___eq___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4ef3f76aa32bb00df1c29fb758e2401d3698821
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___ge___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a1ebcdc86b151a31e763ddcbd9e1eea5fb2ca72
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___getitem___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ca877c760bc26a7a6a5cd1fd2c9d455acc1e5d0
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___gt___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a639ddda8d61bab57941c5060037d3aae363d72
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___le___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2670a982f40039b8d9f25c79218352838a9456c7
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___lt___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..21a4957d6f51b51f34a2b70502ef288e6981e85f
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy___ne___exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f64e3364ac56d13cea357ba9c3397eb59e03ccd7
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_copy_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_copy_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac598abb247a684336ac86512824c95b44291f0b
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_copy_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_get_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_get_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f21ce1f1d1238c37690cc77d7e8c40e5b2536ce
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_get_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_has_key_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_has_key_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e671def0a2bed3d896c1d3bdb6a32dddfe816df4
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_has_key_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_items_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_items_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..21358ba378d55435137685b4fe34198307c2235a
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_items_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_iteritems_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_iteritems_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a709becb9babd9100089e897e05fafb61501d630
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_iteritems_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_iterkeys_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_iterkeys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..72299499b5b238dc046c6d081380eeed9b21e6e4
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_iterkeys_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_itervalues_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_itervalues_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..80106c62b9c071c67edc984875fc3071673cf137
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_itervalues_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_keys_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_keys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aec7043fa858f5d5f7c4d225408501c6e2b5a6cc
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_keys_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy$dictproxy_values_exposer.class b/src/main/resources/org/python/core/PyDictProxy$dictproxy_values_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1020022bdab889f49c33e467f0987f27bc5fb559
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy$dictproxy_values_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictProxy.class b/src/main/resources/org/python/core/PyDictProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..41c59b4ad52259fe12ba4be3d1eb9fe2f2be542a
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictProxy.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$ItemsIter.class b/src/main/resources/org/python/core/PyDictionary$ItemsIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..99b7f1765e0c4ba9df8167c9dd692fccaf9a4095
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$ItemsIter.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$PyExposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1ce7702e833c1a289cc45958864e237798ef026
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___and___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___and___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ea1f66c7c1431b7a92a0208c5dd670d7da14c9c
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___and___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___contains___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b85f2837dfec8547210cb0648739fb6a7d08421
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___eq___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a70773129d73a6bfad22f88157306664119bbc49
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___ge___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..846e5100c0545c49930ddae975dcfba856dae983
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___gt___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1795839797385a89f8980dd9753f354832f21ab
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___iter___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aae1d9a6deb5e8e19a3509a117f2c5f42fc2f53b
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___le___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4d4831e8d9ca94bef1d3b84a247452366cb92f9
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___lt___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f34d16c71c31f5b5f9cf0d31a3c8882849aee73
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___ne___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..89884fbd2a510949d9f3ef21f2bf1a724ba1fbf7
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___or___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___or___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbc9a4aed330598e543ff4cffc6d35930fa93a21
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___or___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___sub___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..241d1d9410fcf38d7d1ad275509d00992a5939c9
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___xor___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___xor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a95c398a883a0c7447753123c09c4854a3514f8
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_items___xor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_keys_toString_exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_keys_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..790f47b8c425497c6ea5a6701ee73102f5ea37f5
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems$dict_keys_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdca78438839ecd925b4bf8be43bf2ed36b76e42
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewItems.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$PyExposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..03f5f4d89b0ddc638a5b0c9eb5c4e3f2da02400a
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___and___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___and___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf7e304c48fcf1c95ed396c8e17cb0d35386f4d6
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___and___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___contains___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4451bad6289c0b911c6dfd0bd0ec2d19325027ba
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___eq___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..48338aba646c68290d7185b83d213251c53c0093
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___ge___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..58dbe8d0ef9095ff0e0ea96ceb5bd043852b9ea8
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___gt___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e5ae625162196c462103aaeb12e556a39feaaf4
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___iter___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..53a8a264fc3cb589eeb7c9a4eecf89440a8b55de
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___le___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5ed53ffa3ee6abd5baeaeac657fd1443293ba9a
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___lt___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2b4e17d3549115a7311cb6f1fe414b7ccc7b179
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___ne___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1772831602b1730be6df917cc908240c0d40927b
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___or___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___or___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b821435e36ba2a75bcfd2bcc87a712eccae0cafb
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___or___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___sub___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..61b0e29f8090590eaec94722f4b688162f38723e
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___xor___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___xor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c2a04ebc0ddf399c83105ebb56f9f0bc5850584
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys___xor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys_toString_exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..be16e59e6e4166bcda3db03518b966092e124961
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys$dict_keys_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys.class
new file mode 100644
index 0000000000000000000000000000000000000000..25f8e2faaf5e9e387cfe8b530a37b6cdf4ebec36
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewKeys.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$PyExposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbf1cdb317a24a7241a2e0ef7a79f8897b514f7b
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values___iter___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c5c4b9db5ea06a06a66388391aa7d4fcd3e4dfa
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values___len___exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9377b9af466bcfd33e619391dfb5e46070b9a4f
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values_toString_exposer.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4e875c0352bd0d11a3bb5d629fa8634d75538b5
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues$dict_values_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues.class b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues.class
new file mode 100644
index 0000000000000000000000000000000000000000..354612fcc62bd7bec3a9e20bfaae2daebc605c50
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyDictionaryViewValues.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$PyExposer.class b/src/main/resources/org/python/core/PyDictionary$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea9e3ce16d03b56f284298a8b6bd17c010cc5578
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$ValuesIter.class b/src/main/resources/org/python/core/PyDictionary$ValuesIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cf0d88bd3248934c7c96497de81a298ccfe587b
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$ValuesIter.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___cmp___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dacdbf547e07f724ec8602265a6bf2a20cbccbbc
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___contains___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb81e1465064ca6ac78bfe047cca58f89577a4ca
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___delitem___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___delitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e72931495921ee74fd5787c8779dfc386ce68d5d
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___delitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___eq___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5703a42a299a619480a687f8c1a5dc067b33c1f
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___ge___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fcca7daafc302905842568a5d3fd060a44a31794
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___getitem___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..87f336faa4d8c6cd96c0d6ceb5a151e10ef1562b
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___gt___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0fe293445cd36ff80a403f9b869e696209b74210
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___hash___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2ef00ace13b25bad210275754b32c2db7c2a3bd
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___init___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..93c9869049671c02dba81100d2001212de4e8779
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___iter___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb9a774646390d49dc322698169df599badc6319
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___le___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..86c6eed769d73d0ff58e3703beac532a774215f9
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___len___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dfba574ee6deb9cf74d603876579238faaac7a3
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___lt___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..acef1abd279f80ff2553aeaf982eb50a920ae753
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___ne___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..504821d270075e33455ec0d1a600e3b6446a31a7
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict___setitem___exposer.class b/src/main/resources/org/python/core/PyDictionary$dict___setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7984c889b32426f9a4ebe559afbbf18788f6ba08
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict___setitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_clear_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_clear_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..88d56dd4ec432a3e29d5a7a882a2b0e30e83b99b
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_clear_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_copy_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_copy_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa73719bc071e2f13929b1b40bff27921b46932e
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_copy_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_fromkeys_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_fromkeys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..14f946f88e7f4b5f3783b97326aff253d269d0b8
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_fromkeys_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_get_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_get_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e07b281e84a0d9d2758aca273d1cd517c725c676
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_get_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_has_key_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_has_key_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..80d8f3c63cdfa096718b98635eb30b5fb6cd1c15
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_has_key_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_items_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_items_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..57ac2c0400268f1819af68e0ce09df4e3dc86d4d
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_items_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_iteritems_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_iteritems_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..84bd8ff8ff34b4ff2238d448cd42c79ed16eb309
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_iteritems_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_iterkeys_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_iterkeys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..83803a8c4a40b00a18502415cc8cac1ee7be7cd1
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_iterkeys_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_itervalues_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_itervalues_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7766f6990e98ed4f81eadac4ccce46e6390e5c1
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_itervalues_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_keys_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_keys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..910d07e98f5bdb5467c22cd733c760ec726de168
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_keys_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_pop_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_pop_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6d26edae7a958d133319bae404a4670fcf526f4
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_pop_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_popitem_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_popitem_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..500ea2a75fdd7d291fb285e58f947094c5c6b058
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_popitem_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_setdefault_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_setdefault_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1bf8100c8a82447e3b4603e3a02cff5a9cdd0b8c
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_setdefault_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_setifabsent_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_setifabsent_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..10b7cfec766190dccca4d3ddd90f0643259b2728
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_setifabsent_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_toString_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a8da5ef4f453750b8410e7281c37d310978e14e
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_update_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_update_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ade78f0683471e20205766bc388c1fccad89b971
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_update_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$dict_values_exposer.class b/src/main/resources/org/python/core/PyDictionary$dict_values_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcbcf55230200c690de326806c3629205dccd7cf
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$dict_values_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$exposed___new__.class b/src/main/resources/org/python/core/PyDictionary$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..05e1415ff9b396cee1e0b86670ad380cca10d624
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$viewitems_exposer.class b/src/main/resources/org/python/core/PyDictionary$viewitems_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cda528c54ecec43d046b5cdb1b4ca6f35e262212
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$viewitems_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$viewkeys_exposer.class b/src/main/resources/org/python/core/PyDictionary$viewkeys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d40330cbd9a5d67f8a7c3ce20609056224af40b
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$viewkeys_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary$viewvalues_exposer.class b/src/main/resources/org/python/core/PyDictionary$viewvalues_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..04186303b2e5c3c5b4849a21d879e321c6f210fc
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary$viewvalues_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyDictionary.class b/src/main/resources/org/python/core/PyDictionary.class
new file mode 100644
index 0000000000000000000000000000000000000000..af0a179c9ed1a429c16160f3f53fd2e0f3d18b19
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionary.class differ
diff --git a/src/main/resources/org/python/core/PyDictionaryDerived.class b/src/main/resources/org/python/core/PyDictionaryDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a0eb76988a24b9e7b7338069fa538377553e85d
Binary files /dev/null and b/src/main/resources/org/python/core/PyDictionaryDerived.class differ
diff --git a/src/main/resources/org/python/core/PyEllipsis$PyExposer.class b/src/main/resources/org/python/core/PyEllipsis$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c072362fe0d99a80c4d5d20c4e359c02e090d318
Binary files /dev/null and b/src/main/resources/org/python/core/PyEllipsis$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyEllipsis.class b/src/main/resources/org/python/core/PyEllipsis.class
new file mode 100644
index 0000000000000000000000000000000000000000..abd6cba4158d6ff08b9e9e58f42fe25fc5cdab38
Binary files /dev/null and b/src/main/resources/org/python/core/PyEllipsis.class differ
diff --git a/src/main/resources/org/python/core/PyEnumerate$PyExposer.class b/src/main/resources/org/python/core/PyEnumerate$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..928ecda677b3f8db1c35225ffa6983263703761c
Binary files /dev/null and b/src/main/resources/org/python/core/PyEnumerate$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyEnumerate$enumerate___iter___exposer.class b/src/main/resources/org/python/core/PyEnumerate$enumerate___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1cc8f44114defaba1dcabf9321849a347e36b3e
Binary files /dev/null and b/src/main/resources/org/python/core/PyEnumerate$enumerate___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyEnumerate$enumerate_next_exposer.class b/src/main/resources/org/python/core/PyEnumerate$enumerate_next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9da71ade89e59a18df8d92121e8d8675975cf77
Binary files /dev/null and b/src/main/resources/org/python/core/PyEnumerate$enumerate_next_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyEnumerate$exposed___new__.class b/src/main/resources/org/python/core/PyEnumerate$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b18d2d1519dcb2fff30320d0766d92cd77fd4b4a
Binary files /dev/null and b/src/main/resources/org/python/core/PyEnumerate$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyEnumerate.class b/src/main/resources/org/python/core/PyEnumerate.class
new file mode 100644
index 0000000000000000000000000000000000000000..11f02e82de53be65994c8b9f21d0b089ecd02971
Binary files /dev/null and b/src/main/resources/org/python/core/PyEnumerate.class differ
diff --git a/src/main/resources/org/python/core/PyEnumerateDerived.class b/src/main/resources/org/python/core/PyEnumerateDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c3edf64ab8cd4c080fe0ea1fcebec121fb2c7e7
Binary files /dev/null and b/src/main/resources/org/python/core/PyEnumerateDerived.class differ
diff --git a/src/main/resources/org/python/core/PyException.class b/src/main/resources/org/python/core/PyException.class
new file mode 100644
index 0000000000000000000000000000000000000000..72a347288cc8beeeb05cf2bbefe07a24c29408ee
Binary files /dev/null and b/src/main/resources/org/python/core/PyException.class differ
diff --git a/src/main/resources/org/python/core/PyFastSequenceIter$PyExposer.class b/src/main/resources/org/python/core/PyFastSequenceIter$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e01c54bb729c54d85cd6efb5a4fc22f9dab4b1af
Binary files /dev/null and b/src/main/resources/org/python/core/PyFastSequenceIter$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyFastSequenceIter$fastsequenceiterator_next_exposer.class b/src/main/resources/org/python/core/PyFastSequenceIter$fastsequenceiterator_next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5efe65fb58f50c0a2573dd3fae5d8e93d320e817
Binary files /dev/null and b/src/main/resources/org/python/core/PyFastSequenceIter$fastsequenceiterator_next_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFastSequenceIter.class b/src/main/resources/org/python/core/PyFastSequenceIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b5e5336fd963c12520936f38dff8bad40f99775
Binary files /dev/null and b/src/main/resources/org/python/core/PyFastSequenceIter.class differ
diff --git a/src/main/resources/org/python/core/PyFile$Closer.class b/src/main/resources/org/python/core/PyFile$Closer.class
new file mode 100644
index 0000000000000000000000000000000000000000..650f95e3e5357a23e16438a505d15eed3b2d8bb6
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$Closer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$PyExposer.class b/src/main/resources/org/python/core/PyFile$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b0adb5e32df9a38f0f1b38cdd93a3686b9a8002a
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$closed_descriptor.class b/src/main/resources/org/python/core/PyFile$closed_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d14a3176097039c473126ba4fc57873ef8ebc38
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$closed_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFile$encoding_descriptor.class b/src/main/resources/org/python/core/PyFile$encoding_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..267177c61615c66378dc6b1f06f515ddd5e97638
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$encoding_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFile$exposed___new__.class b/src/main/resources/org/python/core/PyFile$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..de34007772685dc8b46d36628bcee21eec528aa5
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file___exit___exposer.class b/src/main/resources/org/python/core/PyFile$file___exit___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5b0b9ed7c57ca6e4fd7b5de4ca6aaca2ed6b345
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file___exit___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file___init___exposer.class b/src/main/resources/org/python/core/PyFile$file___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f461e3359da2ddef0cad57b3d82724b6746146a1
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_close_exposer.class b/src/main/resources/org/python/core/PyFile$file_close_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa64bac62ebbbda7f872879a52d71f04270edb28
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_close_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_fileno_exposer.class b/src/main/resources/org/python/core/PyFile$file_fileno_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..02ce260e34424e33e436b6a9aa39c1675b899c61
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_fileno_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_flush_exposer.class b/src/main/resources/org/python/core/PyFile$file_flush_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d7633ca4afef1bdf3001a4d8f5579647852127f
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_flush_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_isatty_exposer.class b/src/main/resources/org/python/core/PyFile$file_isatty_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0af14082d2b5a6a74d5d486b724358403e9dec07
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_isatty_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_next_exposer.class b/src/main/resources/org/python/core/PyFile$file_next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..190127aa3299e405d71da2d6531abedd41f85aa3
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_next_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_read_exposer.class b/src/main/resources/org/python/core/PyFile$file_read_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ac916e42132b3ab43e35b8cfdfd23cdb0f636fe
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_read_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_readinto_exposer.class b/src/main/resources/org/python/core/PyFile$file_readinto_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c609460aafd8155a80cd2287dce10b0061ba146
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_readinto_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_readline_exposer.class b/src/main/resources/org/python/core/PyFile$file_readline_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f95f4bcf294ebfdc9aebe1cdf13398090f862c9
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_readline_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_readlines_exposer.class b/src/main/resources/org/python/core/PyFile$file_readlines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..87af895314f0015347b92aefb12d04e0e62fd603
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_readlines_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_seek_exposer.class b/src/main/resources/org/python/core/PyFile$file_seek_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a404c34615540814130f27944bf3961c9710f6c
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_seek_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_self_exposer.class b/src/main/resources/org/python/core/PyFile$file_self_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c612cea332c849c7d8a6d9f635c48e9aec1e440
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_self_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_tell_exposer.class b/src/main/resources/org/python/core/PyFile$file_tell_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2c675ecd226a48f7bfd74b640f1ced9aa49ed67
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_tell_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_toString_exposer.class b/src/main/resources/org/python/core/PyFile$file_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd5007cf012d96c6bb94713a5964e6b89faea7e9
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_truncate_exposer.class b/src/main/resources/org/python/core/PyFile$file_truncate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac6388b6fbab5e47057394baab53f3726dc4d618
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_truncate_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_write_exposer.class b/src/main/resources/org/python/core/PyFile$file_write_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..adc04fdd85fab4d6f6c87bb2d0de633e45445482
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_write_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$file_writelines_exposer.class b/src/main/resources/org/python/core/PyFile$file_writelines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..efa681560b90f3927f7a422a8d1c36f172c5fdea
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$file_writelines_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFile$mode_descriptor.class b/src/main/resources/org/python/core/PyFile$mode_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3e2b577d5ef65610d0aa1f1e7cccc80a4170754
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$mode_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFile$name_descriptor.class b/src/main/resources/org/python/core/PyFile$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5f236f6c3df1f6770c399488b650e66ec45fde1
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$name_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFile$newlines_descriptor.class b/src/main/resources/org/python/core/PyFile$newlines_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6a991cea5a73227588359edbf1d85e8616ec110
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$newlines_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFile$softspace_descriptor.class b/src/main/resources/org/python/core/PyFile$softspace_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..62ebd9565d49784330b89f8055156e09af0026c0
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile$softspace_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFile.class b/src/main/resources/org/python/core/PyFile.class
new file mode 100644
index 0000000000000000000000000000000000000000..55f3ffc133c6aabc56eb1bc4e49326ba5707d515
Binary files /dev/null and b/src/main/resources/org/python/core/PyFile.class differ
diff --git a/src/main/resources/org/python/core/PyFileDerived.class b/src/main/resources/org/python/core/PyFileDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..338eb6bda908589c60e2c3b021debcf60937b157
Binary files /dev/null and b/src/main/resources/org/python/core/PyFileDerived.class differ
diff --git a/src/main/resources/org/python/core/PyFileReader.class b/src/main/resources/org/python/core/PyFileReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..7931cdbd80b085a67b514fa51b999c0743c2b3fa
Binary files /dev/null and b/src/main/resources/org/python/core/PyFileReader.class differ
diff --git a/src/main/resources/org/python/core/PyFileWriter.class b/src/main/resources/org/python/core/PyFileWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..55ced7dad6b7df955983022678f9fc6fac3873d1
Binary files /dev/null and b/src/main/resources/org/python/core/PyFileWriter.class differ
diff --git a/src/main/resources/org/python/core/PyFinalizableInstance.class b/src/main/resources/org/python/core/PyFinalizableInstance.class
new file mode 100644
index 0000000000000000000000000000000000000000..8474d559b09c479a30069c4f8d625a12f3196295
Binary files /dev/null and b/src/main/resources/org/python/core/PyFinalizableInstance.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$Format.class b/src/main/resources/org/python/core/PyFloat$Format.class
new file mode 100644
index 0000000000000000000000000000000000000000..be40a25c1b762c2a497d99b5586e863612297596
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$Format.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$PyExposer.class b/src/main/resources/org/python/core/PyFloat$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7023932ca8c34331b3ba9c96a106c2dcf47a76fb
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$as_integer_ratio_exposer.class b/src/main/resources/org/python/core/PyFloat$as_integer_ratio_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8b98719f0d70b82ded42fb4766d4dcd8df5ea87
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$as_integer_ratio_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$exposed___new__.class b/src/main/resources/org/python/core/PyFloat$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..807a8de5fd085fcd11a2e4358ebbdc001a06396b
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___abs___exposer.class b/src/main/resources/org/python/core/PyFloat$float___abs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..824f0b11867d25c1bf39cf25a33011a279e4e75e
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___abs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___add___exposer.class b/src/main/resources/org/python/core/PyFloat$float___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a46317d653b53eb9d765557ef923c3cfd34fc56
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___cmp___exposer.class b/src/main/resources/org/python/core/PyFloat$float___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e7ad8013208be58fa9f99b64823a7236066da22
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___coerce___exposer.class b/src/main/resources/org/python/core/PyFloat$float___coerce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f25c25eddfe032850f1df8b79cdf101b30fb60c
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___coerce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___div___exposer.class b/src/main/resources/org/python/core/PyFloat$float___div___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2d5751728fc382efa6e50eb65f9fcc56a6fada4
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___div___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___divmod___exposer.class b/src/main/resources/org/python/core/PyFloat$float___divmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b77e80d666f30e2833bfb26dbbfe8c5d4fda40d3
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___divmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___float___exposer.class b/src/main/resources/org/python/core/PyFloat$float___float___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fca75cfe1af39a3eef231b6e1a7f56d06da97f4f
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___float___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___floordiv___exposer.class b/src/main/resources/org/python/core/PyFloat$float___floordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5028e4b4f9daf89adebeca826dd6e3ef3b8b293
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___floordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___format___exposer.class b/src/main/resources/org/python/core/PyFloat$float___format___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae7c68fd453e453128766f8f85cd9695823003b6
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___format___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___getformat___exposer.class b/src/main/resources/org/python/core/PyFloat$float___getformat___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c21561b103ed2871af1055dd57bc6e54718171cb
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___getformat___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___getnewargs___exposer.class b/src/main/resources/org/python/core/PyFloat$float___getnewargs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..add850424c30b9777e09e7dbdc61da74a14fdaed
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___getnewargs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___hash___exposer.class b/src/main/resources/org/python/core/PyFloat$float___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f894c86fdaaf013be144d7227ff2931bf284e750
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___int___exposer.class b/src/main/resources/org/python/core/PyFloat$float___int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..69b2f213faaef5f798dd600c3e8b4a669a7f972f
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___int___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___long___exposer.class b/src/main/resources/org/python/core/PyFloat$float___long___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..db6843de6bd5e5112598ba6d706a528b9e33467e
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___long___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___mod___exposer.class b/src/main/resources/org/python/core/PyFloat$float___mod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e861525c1f6d8ebf34dfd8f0f6f0994c5a137b3a
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___mod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___mul___exposer.class b/src/main/resources/org/python/core/PyFloat$float___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e331ef3e422c08fc39f537bff646b0fc31cf3be
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___neg___exposer.class b/src/main/resources/org/python/core/PyFloat$float___neg___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..345d38b431ef007f48fa884226f7e85844e9ea9d
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___neg___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___nonzero___exposer.class b/src/main/resources/org/python/core/PyFloat$float___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dab1bc4d41329ecd8cfc56c6cad790163e9a3ab2
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___pos___exposer.class b/src/main/resources/org/python/core/PyFloat$float___pos___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9971eed502835253a4229a3ce951c77cc215d1c2
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___pos___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___pow___exposer.class b/src/main/resources/org/python/core/PyFloat$float___pow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..45252c48940e766a847205996f325b3884ea975b
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___pow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___radd___exposer.class b/src/main/resources/org/python/core/PyFloat$float___radd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..18df95a5f84a62e6d7d53a220b24718e0725a643
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___radd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___rdiv___exposer.class b/src/main/resources/org/python/core/PyFloat$float___rdiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..54c31cd83b28a41d4382e334a16bcc1eef8f22e7
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___rdiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___rdivmod___exposer.class b/src/main/resources/org/python/core/PyFloat$float___rdivmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7864f1a11897bd01074acd5171cf761c09309837
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___rdivmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___repr___exposer.class b/src/main/resources/org/python/core/PyFloat$float___repr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..61a3eb4977fb5db66ee9f3e2fdd98951d1f7922f
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___repr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___rfloordiv___exposer.class b/src/main/resources/org/python/core/PyFloat$float___rfloordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..43c667e80d28313b69c189527aa22b997caad0ee
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___rfloordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___rmod___exposer.class b/src/main/resources/org/python/core/PyFloat$float___rmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee175582fc105166ee82be224082ae6cf1b82200
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___rmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___rmul___exposer.class b/src/main/resources/org/python/core/PyFloat$float___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b39ffdf228e4d427513cad4370672c003f3e5e69
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___rpow___exposer.class b/src/main/resources/org/python/core/PyFloat$float___rpow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e7545398d88fae1b30b5e33e40c1a6757b6f821
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___rpow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___rsub___exposer.class b/src/main/resources/org/python/core/PyFloat$float___rsub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..af8f879b47890dc2246f7cb9e430ccd2723d33be
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___rsub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___rtruediv___exposer.class b/src/main/resources/org/python/core/PyFloat$float___rtruediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b0d4a599b489d37b86a18f78a8285e55ee1ab94d
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___rtruediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___setformat___exposer.class b/src/main/resources/org/python/core/PyFloat$float___setformat___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c911de32a4806fad680360c3cbc386915ba8d62
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___setformat___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___str___exposer.class b/src/main/resources/org/python/core/PyFloat$float___str___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..448311690b6ab08f4330d8a160e9a2fc4dc13cdb
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___str___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___sub___exposer.class b/src/main/resources/org/python/core/PyFloat$float___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fa1e44e1b88653ca1ff63910e91db524d8647b5
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___truediv___exposer.class b/src/main/resources/org/python/core/PyFloat$float___truediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..56ca12329a391276c8da9c02662690a642eac4b8
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___truediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float___trunc___exposer.class b/src/main/resources/org/python/core/PyFloat$float___trunc___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..74398eddcedd77d82e1262e2cd6f90d867165655
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float___trunc___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float_conjugate_exposer.class b/src/main/resources/org/python/core/PyFloat$float_conjugate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4406bb32c6fe4422de0a52349133848b45960fe4
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float_conjugate_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float_fromhex_exposer.class b/src/main/resources/org/python/core/PyFloat$float_fromhex_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b07a9adc8286569707ed6a18a54c0c0aab772f2
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float_fromhex_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float_hex_exposer.class b/src/main/resources/org/python/core/PyFloat$float_hex_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9899edf9e412b417e998891af3fe02fa4ccf714
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float_hex_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$float_is_integer_exposer.class b/src/main/resources/org/python/core/PyFloat$float_is_integer_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..718eee459ba07003c4f57a8c2dd4119de40cafa7
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$float_is_integer_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$imag_descriptor.class b/src/main/resources/org/python/core/PyFloat$imag_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6feb1594539c03ecc52cf768cb83b0671457b34
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$imag_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFloat$real_descriptor.class b/src/main/resources/org/python/core/PyFloat$real_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1f7c0a7f18091dd3ba00e7442b763407b30ece5
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat$real_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFloat.class b/src/main/resources/org/python/core/PyFloat.class
new file mode 100644
index 0000000000000000000000000000000000000000..af5a7fcbcff45fe2fc582029257d34eb13dc6fb9
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloat.class differ
diff --git a/src/main/resources/org/python/core/PyFloatDerived.class b/src/main/resources/org/python/core/PyFloatDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b623a7c4512c8b83f221516918879fe3f504105
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloatDerived.class differ
diff --git a/src/main/resources/org/python/core/PyFloatTest.class b/src/main/resources/org/python/core/PyFloatTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8a5562928bebb4e83a5668ea21e161a2a28df4f
Binary files /dev/null and b/src/main/resources/org/python/core/PyFloatTest.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$PyExposer.class b/src/main/resources/org/python/core/PyFrame$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..025c6ba051a2c974d3692f24eac713124d39607b
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$f_back_descriptor.class b/src/main/resources/org/python/core/PyFrame$f_back_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c01ce5b5bde29443ea2b3b67573c59e49a162be
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$f_back_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$f_builtins_descriptor.class b/src/main/resources/org/python/core/PyFrame$f_builtins_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8de3e9f6b44fa8d067b90d42939663ac2abaf2f0
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$f_builtins_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$f_code_descriptor.class b/src/main/resources/org/python/core/PyFrame$f_code_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa31e044fb2b1db04695605f22482b6682cc27fe
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$f_code_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$f_globals_descriptor.class b/src/main/resources/org/python/core/PyFrame$f_globals_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff497cd15b2c72ac16c02a292640b0f516c2a5f9
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$f_globals_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$f_lasti_descriptor.class b/src/main/resources/org/python/core/PyFrame$f_lasti_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bc9cc4d288bcbd4fc93ae173fe1049239eebf07
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$f_lasti_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$f_lineno_descriptor.class b/src/main/resources/org/python/core/PyFrame$f_lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fda5a71fce6ed05214b51da22f462073446b363d
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$f_lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$f_locals_descriptor.class b/src/main/resources/org/python/core/PyFrame$f_locals_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf4d8924bbd6e2553863fc42675720767eccb32e
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$f_locals_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFrame$f_trace_descriptor.class b/src/main/resources/org/python/core/PyFrame$f_trace_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5ff53b00df609a86023e66621d8dc5ebdce86b4
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame$f_trace_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFrame.class b/src/main/resources/org/python/core/PyFrame.class
new file mode 100644
index 0000000000000000000000000000000000000000..9dccc00aaa0ee9856da118e48e47d5a7b3ba4aa7
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrame.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$1.class b/src/main/resources/org/python/core/PyFrozenSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..32b29bdb4266f6ed841b9a66209f218ae53e5766
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$1.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$PyExposer.class b/src/main/resources/org/python/core/PyFrozenSet$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee7e4b9217339784201f306f59e4f3edc82d94fd
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$exposed___new__.class b/src/main/resources/org/python/core/PyFrozenSet$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbec4fa369759f67f0b6e30afa8fbd6f77b1a13a
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___and___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___and___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c7ff7d1acf0834434939377d1024405b05f99ff
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___and___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___cmp___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ac6f8d084324987d00eb6956149c27f929c03be
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___contains___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf63bbcddd1d15cb434a27e9adfa8a8bada15973
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___eq___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1b9a23ed9d54dcad37e4a02c640d01b6fb4e4b9
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___ge___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3426db8376f75ab2a0a7653ec716a3bec4ee3d25
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___gt___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..90709a064a2a9610d110548ecb93d5745c3c97c9
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___hash___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0b49c73f3d932a9a25b0ae04ad56b9b6ba687fe
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___iter___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d01939fc912099870327f0383cd67a4b82a610e3
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___le___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea715c4de8c49530eea034ba5a20a4aabeede6fd
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___len___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f971c4d1586da905e49906c94c1bd0481fbff115
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___lt___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed52300d7662df5d0bf31f328576120331dceb96
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___ne___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..46ce437d55063aff47af35b5df9c81270260a48f
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___or___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___or___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6cae6bbb15d90bbf55b10ee80f5956abeaab35f3
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___or___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___reduce___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..27a5a4653c2aa68d4477d2fb51db9ea6bac2bd6c
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___sub___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..db4fd5255a3c88199d46d337d76ed96b4f4ae309
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset___xor___exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset___xor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..368102894fff65dd1b693b6b2486c519add9564d
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset___xor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_copy_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_copy_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..359eb25ffc9ef7e6786fe856e754511dcf531da0
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_copy_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_difference_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_difference_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..71d4ea25e01681c5409b00177b35697812b36912
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_difference_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_intersection_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_intersection_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f785933bbccd1798e1c4a681723f7ea4f1256ec8
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_intersection_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_isdisjoint_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_isdisjoint_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8bef5a4aec6fef4ea6aa284c24d9bc19c37018e
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_isdisjoint_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_issubset_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_issubset_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9890ec496185bb5fbdedf40146032b024d9b5f14
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_issubset_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_issuperset_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_issuperset_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3fdd664c4aae68279f078d99fd859785e56ce77
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_issuperset_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_symmetric_difference_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_symmetric_difference_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4e73aaf8c5c6e26ef92c0142b097ba544a572b4
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_symmetric_difference_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_toString_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8de5d4568fec9601d88262e3a87b7776fcff0ea
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet$frozenset_union_exposer.class b/src/main/resources/org/python/core/PyFrozenSet$frozenset_union_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..49d3d7a62348ad76cf23803b9701b86b7ce07359
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet$frozenset_union_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSet.class b/src/main/resources/org/python/core/PyFrozenSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9020261fbbd0b54d9f87c6febcdcbaba2bca41b
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSet.class differ
diff --git a/src/main/resources/org/python/core/PyFrozenSetDerived.class b/src/main/resources/org/python/core/PyFrozenSetDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..09528e13dfabb4a9ea6c51d0bbb2f731c4796cf6
Binary files /dev/null and b/src/main/resources/org/python/core/PyFrozenSetDerived.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$PyExposer.class b/src/main/resources/org/python/core/PyFunction$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6bd341d0df62ca5b346275136714444f43bac30
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$__code___descriptor.class b/src/main/resources/org/python/core/PyFunction$__code___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ccec5604daf5e4999749a725d69a1dd5dad506b
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$__code___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$__dict___descriptor.class b/src/main/resources/org/python/core/PyFunction$__dict___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb33231f533aadc37be25f2f11d19f537001901b
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$__dict___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$__doc___descriptor.class b/src/main/resources/org/python/core/PyFunction$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c580908b9cd21b40aaf185f9b7a6b85114ba576f
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$__globals___descriptor.class b/src/main/resources/org/python/core/PyFunction$__globals___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9430946a65e15ac3ef380d709309cdf6f9c171e
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$__globals___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$__module___descriptor.class b/src/main/resources/org/python/core/PyFunction$__module___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..748d389d96eb825128bdccb0d8178eb77820d76b
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$__module___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$__name___descriptor.class b/src/main/resources/org/python/core/PyFunction$__name___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d88f849e4a10c729d6fba669d6a99d30ada40f8
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$__name___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$exposed___new__.class b/src/main/resources/org/python/core/PyFunction$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..828ae56fdc376b2bc94574a5f40edfb8c0910134
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$func_closure_descriptor.class b/src/main/resources/org/python/core/PyFunction$func_closure_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5934b0f831df3e077fa4243b93ad4e8b795d13e5
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$func_closure_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$func_code_descriptor.class b/src/main/resources/org/python/core/PyFunction$func_code_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..77405ee0f7bdd455853395b542f41f418cf717a4
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$func_code_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$func_defaults_descriptor.class b/src/main/resources/org/python/core/PyFunction$func_defaults_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3994c2a334149dcc80e8f66f14172b41b4f59855
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$func_defaults_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$func_dict_descriptor.class b/src/main/resources/org/python/core/PyFunction$func_dict_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c162d7aa0860c4963a1d1919001bde088f64af3
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$func_dict_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$func_doc_descriptor.class b/src/main/resources/org/python/core/PyFunction$func_doc_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5dd766006b31daf9ae97a4b0c733a264ca9d2b3
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$func_doc_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$func_globals_descriptor.class b/src/main/resources/org/python/core/PyFunction$func_globals_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e176a22e447616693aec053886034fdff2563756
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$func_globals_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$func_name_descriptor.class b/src/main/resources/org/python/core/PyFunction$func_name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7684762b37bdd1b8ff65abe3a93ce3fb294c7d9
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$func_name_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$function___call___exposer.class b/src/main/resources/org/python/core/PyFunction$function___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4581a86c8bc7bb8c9f1106eb6d21710b1a941d58
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$function___call___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$function___get___exposer.class b/src/main/resources/org/python/core/PyFunction$function___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..69e77316ab0d2b960f45cf3f5d8125251c0bf305
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$function___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFunction$function___setattr___exposer.class b/src/main/resources/org/python/core/PyFunction$function___setattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac4e57459d2b11864d937b506933a847bae12dee
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction$function___setattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyFunction.class b/src/main/resources/org/python/core/PyFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..708b8422657ae5b03928dbbd42944b1ab9dd4cc7
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunction.class differ
diff --git a/src/main/resources/org/python/core/PyFunctionTable.class b/src/main/resources/org/python/core/PyFunctionTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..dff537cb8940a7a15a38b7888c387d56f3e12777
Binary files /dev/null and b/src/main/resources/org/python/core/PyFunctionTable.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$PyExposer.class b/src/main/resources/org/python/core/PyGenerator$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fdfcc311fd9ad190f1ed1c42c337e26007c112a
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$generator___iter___exposer.class b/src/main/resources/org/python/core/PyGenerator$generator___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba291a6d3a5a7a7a3ed197cd5f8c1980a4c22fab
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$generator___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$generator_close_exposer.class b/src/main/resources/org/python/core/PyGenerator$generator_close_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2567de3f7f14c1d88ae15216471f55083022d4d3
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$generator_close_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$generator_next_exposer.class b/src/main/resources/org/python/core/PyGenerator$generator_next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b79073e577d304d4ee8d773c469423faec769a9
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$generator_next_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$generator_send_exposer.class b/src/main/resources/org/python/core/PyGenerator$generator_send_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..17e966c9cdfecd62af20ff8bc780e3559258e74d
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$generator_send_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$generator_throw$_exposer.class b/src/main/resources/org/python/core/PyGenerator$generator_throw$_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1703aa55606b63b872aa908387aa6fb29db6d4f
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$generator_throw$_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$gi_code_descriptor.class b/src/main/resources/org/python/core/PyGenerator$gi_code_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e6e716938c0a1a00c8fb1e4b81dedb296b7d8e0
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$gi_code_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$gi_frame_descriptor.class b/src/main/resources/org/python/core/PyGenerator$gi_frame_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..63de8034b55dc66d65011aa7dbfce9b940b7d893
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$gi_frame_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator$gi_running_descriptor.class b/src/main/resources/org/python/core/PyGenerator$gi_running_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b066b651f342fab98fd6ba0cc2fd3bf9e2df312f
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator$gi_running_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyGenerator.class b/src/main/resources/org/python/core/PyGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..a34022f9b23dacadebd384f22812db0aeb9b0012
Binary files /dev/null and b/src/main/resources/org/python/core/PyGenerator.class differ
diff --git a/src/main/resources/org/python/core/PyIdentityTuple.class b/src/main/resources/org/python/core/PyIdentityTuple.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6bb747e94fbf447e77b3793764a6b4181c0e5de
Binary files /dev/null and b/src/main/resources/org/python/core/PyIdentityTuple.class differ
diff --git a/src/main/resources/org/python/core/PyIgnoreMethodTag.class b/src/main/resources/org/python/core/PyIgnoreMethodTag.class
new file mode 100644
index 0000000000000000000000000000000000000000..efe0c132faba96a469f8bb70bd528e659e8b5a60
Binary files /dev/null and b/src/main/resources/org/python/core/PyIgnoreMethodTag.class differ
diff --git a/src/main/resources/org/python/core/PyIndentationError.class b/src/main/resources/org/python/core/PyIndentationError.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f5940e22c0edee326eddfaf3c898bad6128083f
Binary files /dev/null and b/src/main/resources/org/python/core/PyIndentationError.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$PyExposer.class b/src/main/resources/org/python/core/PyInstance$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8833958251194ae505caed542a365ccb50a4d788
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$exposed___new__.class b/src/main/resources/org/python/core/PyInstance$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab531e45148b51b499acf3a28ff2c6ed118deb7c
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___abs___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___abs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae2fd050a56346fbe169884878ebbf5971c79aff
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___abs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___add___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1498a55dd2235b59d9fa9624bf097193eaf91f36
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___and___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___and___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..184902a985953573e3608a3488feebb22dd26124
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___and___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___call___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c78073f39d118a53bbe4ddf9d9174b4a0201a30
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___call___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___cmp___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc071154c05ae259b486e9f16aceb0ce983ffdc5
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___complex___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___complex___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5afe090b505bf1c9135aa15b3e6ba9a04a591aea
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___complex___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___contains___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..63a6d7e6447e669a2474e0006f26747e2538dea6
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___delattr___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___delattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1b1584a085713c0fe25fb9daf101fc5b81b031a
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___delattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___delitem___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___delitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a675b113e1502b37d41bfdb81674e49248c79f9d
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___delitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___delslice___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___delslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e742ba0efc05b82233edee09639cf342e53f5c3
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___delslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___div___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___div___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d834bb7898ceb20fc1338bb4271112b8e1c559a
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___div___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___divmod___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___divmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a5ba9d4cbca92c2da1d6668a8234e349653dac2
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___divmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___eq___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae3ab20d1a6989cfd5edebac97e20db35c4781d0
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___float___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___float___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..18aebf3d57af06f722fd2e0429677d94eb16538b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___float___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___floordiv___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___floordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d18ac5d3e08dd6e80076eac58415ad4e6b5f52b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___floordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___format___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___format___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4eb0d4932bdee27927669a95a199a7665536cfea
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___format___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___ge___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbc44927ca475f00d9c09f4907e92bd8ee6debaf
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___getitem___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3a822c06050d73b0ad9d286e5d25c58c3b6b0dd
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___getslice___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___getslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..536a108f3a78562be58848d50162ad545d50277e
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___getslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___gt___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..28fb97ce3c39afe1f0b0d7d7396744f086f32d9d
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___hex___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___hex___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0d48e7bdae4edfb4f230cbf60434752b1c33756
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___hex___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___iadd___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___iadd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..517d1d186410f94027c81342cfdf4c8c37a40a15
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___iadd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___iand___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___iand___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2117529d081c674aaf5f8ff315a2200dc42d31f4
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___iand___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___idiv___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___idiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1d38bcb1ade7031bc86d6dcace7e4327f030a2d
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___idiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___ifloordiv___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___ifloordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa46d98e517160b0615387fcc3884fa0eed79769
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___ifloordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___ilshift___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___ilshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4dd213ffed8de7ec527e8b5e6d46a605afa59504
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___ilshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___imod___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___imod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4b16b20842b59bae5c8f9f7ece69a483c0c738b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___imod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___imul___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___imul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d79597b679fca52a8aee1bef3d44b1c846d477bc
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___imul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___index___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___index___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a5a57b367170f958fd83cc94e83014ca76e5cf5
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___index___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___int___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8dcecd1a25a7f35c8ace7d229508f7fbf8fe6db
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___int___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___invert___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___invert___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bbee45f370c40ef78d8a7d277211fd5791bd30a
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___invert___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___ior___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___ior___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..225894e54658d80f1f73f52409cc7efa89a5b2f5
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___ior___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___ipow___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___ipow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef6ca99bb6bf49f3fe7efc058bc0141e26fd8c60
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___ipow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___irshift___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___irshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5215bfd39daea7a7efc7e518815feaecf60a9a21
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___irshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___isub___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___isub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b7854471a5cfccb8780302b707018685222f8b7
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___isub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___iter___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b151aae6369ed5b8e470ebc570574955b1aecd66
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___itruediv___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___itruediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f61f901d2c10cd1ae14ea879b082842c879862cc
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___itruediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___ixor___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___ixor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e01a7792d9290fecfe9c47c0755135d446bd2547
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___ixor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___le___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff73b6ebf5b2fc8a6b3b5ae50e3404ff145464ab
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___len___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..38c794cff8829270efc80ea875b37852abb16ca9
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___long___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___long___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab58ead1109000664c82fc764eaf15be437b4961
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___long___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___lshift___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___lshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..69fd425b1eebd209a70fc812b83d0201da1251a8
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___lshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___lt___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5a2ec5f68a95285af6ddf32d8edb48ea3208b6d
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___mod___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___mod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..95e2e9721c7027aa12f58c9d81faa96bd9582da8
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___mod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___mul___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..915c92e0402548453b7e998a31d667754521b781
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___ne___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f25f4dbc9938d47ee3f3b4b51ba068b1876779a
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___neg___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___neg___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..52077ef8d3250fe63a92531f9f0ccfa6fb7204b5
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___neg___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___nonzero___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8462c800887ff8f8d08f8ddb893aac50de60b9d0
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___oct___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___oct___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..24942becfd594ad5caad98becd33c68ee91ab7a9
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___oct___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___or___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___or___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..500d827e0d41ebb3803e3c33a2cdd0241b815189
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___or___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___pos___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___pos___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6188f18af635e16f599fbe7afc4ac3c7946757f
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___pos___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___pow___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___pow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..787f8737e928440d88110ea9396aa587252a4761
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___pow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___radd___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___radd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1435be87d9f0f6536c150ba63a24c9827328983c
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___radd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rand___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rand___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..57406b5129cb7b2c284c1929863f96540061ba30
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rand___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rdiv___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rdiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac02770a67df3cc5f4d7ec974102298dd5e7a059
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rdiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rdivmod___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rdivmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbb11b0094d9a66e6fed9f704e475c8a7e31249b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rdivmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___repr___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___repr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb173f1d933aa6dfdfd73b41c122b3472f204db2
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___repr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rfloordiv___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rfloordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6768345fd48d37e2b6e8d5e1397942e7a468422f
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rfloordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rlshift___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rlshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c6a8dad4734453070956b17e9306afd399f4a4c
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rlshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rmod___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc1e0d3301e93f8d275c349e222df69b964a31c8
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rmul___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc378f95eb7336aa3c68959bba8caffff46f85fb
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___ror___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___ror___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1bba19b53ad853ff8d5ee6f548f020f0fcb9fa57
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___ror___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rpow___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rpow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb9634fcbaba149abc4f8220af90750c0f69887e
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rpow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rrshift___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rrshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e4cf7ff4ba3dbc3497e96d1b96043b614d80439
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rrshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rshift___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5aac9ea39bf15717f3fb9cc9dc999cbca3834123
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rsub___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rsub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..00308cead3de2541cfe71aa8b9f45abc53280626
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rsub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rtruediv___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rtruediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c78d14d3bf001e1151ed27f040c42b5ad7284878
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rtruediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___rxor___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___rxor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4d7cb68165b7c17345c2efe51e92ebc3dd3b02d
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___rxor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___setattr___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___setattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dc9cdea5859887742b0f997b8f6086235870281
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___setattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___setitem___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b4a601dcdbac720f2b19dd263bcec0aa23051ea
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___setitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___setslice___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___setslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..996b65e81ebb261795456662b3a71aae7b95cbdc
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___setslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___str___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___str___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b6fe811f090fffaa3127e3d5491ee8b6d81861b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___str___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___sub___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1f403618b2fc78e4412fabbace7cd386a68cb0b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___truediv___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___truediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..106e13c45c827d3be8b28b8d7512477961c40b51
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___truediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___unicode___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___unicode___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dc2dad7a5ee31b0ff17fe1f5a91a7b089dbd4e2
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___unicode___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance$instance___xor___exposer.class b/src/main/resources/org/python/core/PyInstance$instance___xor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c64b59480e64e10c945ee2e5f504823df13736b2
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance$instance___xor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInstance.class b/src/main/resources/org/python/core/PyInstance.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4492e23fb9ffa9361cb9832e8e0c89ec708c3ac
Binary files /dev/null and b/src/main/resources/org/python/core/PyInstance.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$PyExposer.class b/src/main/resources/org/python/core/PyInteger$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..56b4cb555338865051764cd7e1c4c3401aaeb0eb
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$denominator_descriptor.class b/src/main/resources/org/python/core/PyInteger$denominator_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..30435dccd0540510fa2e293da22d849ed3690238
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$denominator_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$exposed___new__.class b/src/main/resources/org/python/core/PyInteger$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b65326ebfb4486e7c268c281b2d9e28128973e11
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$imag_descriptor.class b/src/main/resources/org/python/core/PyInteger$imag_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4ccab4e48352066843f330dfed6d11b095b0599
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$imag_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___abs___exposer.class b/src/main/resources/org/python/core/PyInteger$int___abs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf01af2756aeef7f31695933c910e6732b5f4b30
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___abs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___add___exposer.class b/src/main/resources/org/python/core/PyInteger$int___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d406db3d14dfc74a43fb6459b94e974668036b2b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___and___exposer.class b/src/main/resources/org/python/core/PyInteger$int___and___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..001ce8dfb3a9187d7b4c0fa723231b636767c67d
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___and___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___cmp___exposer.class b/src/main/resources/org/python/core/PyInteger$int___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7193a1dbc330f46544b62de116b5101d3489e3a1
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___coerce___exposer.class b/src/main/resources/org/python/core/PyInteger$int___coerce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..882ff70d4ecaab0f1266c1c685482c4385c92a12
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___coerce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___div___exposer.class b/src/main/resources/org/python/core/PyInteger$int___div___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..38bcbb5511272cf7a66a13efba07ae821c8b792b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___div___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___divmod___exposer.class b/src/main/resources/org/python/core/PyInteger$int___divmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0957c36c45e6ad966cb6ccbcc70a4d3bb6b9c29
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___divmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___float___exposer.class b/src/main/resources/org/python/core/PyInteger$int___float___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..64983e77fdf96ecd653a1ee371f16c1adbaa707d
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___float___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___floordiv___exposer.class b/src/main/resources/org/python/core/PyInteger$int___floordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..55540ea0f6ccc7408c2ecb587a5888ef46b9139e
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___floordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___format___exposer.class b/src/main/resources/org/python/core/PyInteger$int___format___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..252680172184f3b8a2bac6a87cad5eba37d7698e
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___format___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___getnewargs___exposer.class b/src/main/resources/org/python/core/PyInteger$int___getnewargs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a307f5039f350194a4b42533e1daa84f2102c133
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___getnewargs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___hex___exposer.class b/src/main/resources/org/python/core/PyInteger$int___hex___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1590e2d3bc8ffdfacb887ef717a9ad4208a03e04
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___hex___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___index___exposer.class b/src/main/resources/org/python/core/PyInteger$int___index___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..681d41d04ca8c0c3d533241fc2640d786f02bd1e
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___index___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___int___exposer.class b/src/main/resources/org/python/core/PyInteger$int___int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5da10ffdafe7bd2608324f604f1893efb271eaa9
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___int___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___invert___exposer.class b/src/main/resources/org/python/core/PyInteger$int___invert___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..acee7bb4a46b5aae517b2fba4f8c3dff66ac1adc
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___invert___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___long___exposer.class b/src/main/resources/org/python/core/PyInteger$int___long___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..da2a15d86a893a0d5fd58b3c1745c184f1858952
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___long___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___lshift___exposer.class b/src/main/resources/org/python/core/PyInteger$int___lshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..795671eb7d2dfbf2a1564029ddea1b109e14c350
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___lshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___mod___exposer.class b/src/main/resources/org/python/core/PyInteger$int___mod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5500131b4ad2a0187aa9c12081e41ae5f5d943a4
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___mod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___mul___exposer.class b/src/main/resources/org/python/core/PyInteger$int___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdb60c7814cc3abc86cb7fc3b80f795b3dbcdcae
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___neg___exposer.class b/src/main/resources/org/python/core/PyInteger$int___neg___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3ec02048827059881c231421134473bde142293
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___neg___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___nonzero___exposer.class b/src/main/resources/org/python/core/PyInteger$int___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb3fdc792c9184a35920e0ead8e834ab3af3cb42
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___oct___exposer.class b/src/main/resources/org/python/core/PyInteger$int___oct___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..164854180b2fd5eb5e2fcd88c71f6ea8a4b9edbf
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___oct___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___or___exposer.class b/src/main/resources/org/python/core/PyInteger$int___or___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad56ede803fc51a3dd60be0eac58413abce213e6
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___or___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___pos___exposer.class b/src/main/resources/org/python/core/PyInteger$int___pos___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8607b76a9b3f74e5fd35b6706846d172c7ad590
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___pos___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___pow___exposer.class b/src/main/resources/org/python/core/PyInteger$int___pow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d17191d583ec7b85eadb6649bbd9da5291fd2dfc
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___pow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___radd___exposer.class b/src/main/resources/org/python/core/PyInteger$int___radd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b0c8469d12d3324024704979d46522d763bbf678
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___radd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rand___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rand___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ce680a300c0c8c1440a60165a3ebdd099a3c65b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rand___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rdiv___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rdiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..918c2e5b19ed3c403102fa8e501d3a114f6c71b3
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rdiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rdivmod___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rdivmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e180307ca7c892973ef4de2e40d38447fc24316b
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rdivmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rfloordiv___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rfloordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a67e19d7e470807117e3f078b339f40fe2363f1c
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rfloordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rlshift___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rlshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fb931fb2bd11b6d141b004052f4f03e42532e47
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rlshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rmod___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cb73e087c7d9d1dbfee1d3d89ec4656a3d5a1ad
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rmul___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..425abd192fb187e576b334992594f01d313a8fb2
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___ror___exposer.class b/src/main/resources/org/python/core/PyInteger$int___ror___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3aa5adee1d98e2462f07e7a1b89fe285946c30c3
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___ror___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rpow___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rpow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5a7bdc7bc68e4cd915acf860508a70726ddfb7d
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rpow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rrshift___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rrshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ac8eb9c1838b5a00393a9b4b743902c767659e1
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rrshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rshift___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea5a6a18e4ae3246454f12b5d7e109903144bec9
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rsub___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rsub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7266cce3f36fe5e4d5926c5719dae11f0ee689d8
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rsub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rtruediv___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rtruediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2cdd39c82c1b73957bc0956d2e0eea3635489ef
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rtruediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___rxor___exposer.class b/src/main/resources/org/python/core/PyInteger$int___rxor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..af786e4d988aaf8fd7d37417b5ce989a6b9a9b55
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___rxor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___sub___exposer.class b/src/main/resources/org/python/core/PyInteger$int___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3a5e0b34c0692a61010f624e34bcac56669b99f
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___truediv___exposer.class b/src/main/resources/org/python/core/PyInteger$int___truediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4b5e837a6cc2a2d0231259ac5994f3068248ecd
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___truediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___trunc___exposer.class b/src/main/resources/org/python/core/PyInteger$int___trunc___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..63b5024cfcf4291f8a9a71270297ef012ffaa0bd
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___trunc___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int___xor___exposer.class b/src/main/resources/org/python/core/PyInteger$int___xor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc6716eeb523b0e2a2a6411150a3d97e0974c1db
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int___xor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int_bit_length_exposer.class b/src/main/resources/org/python/core/PyInteger$int_bit_length_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..39d3cd1d4519ebcb2676d659b3d9fe4bd603df9c
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int_bit_length_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int_conjugate_exposer.class b/src/main/resources/org/python/core/PyInteger$int_conjugate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..392bfac10cae31e022229b71875de69f7849e638
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int_conjugate_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int_hashCode_exposer.class b/src/main/resources/org/python/core/PyInteger$int_hashCode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8aa1cafb5868c65d0983da0361b1b8faa8cbb1c9
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int_hashCode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$int_toString_exposer.class b/src/main/resources/org/python/core/PyInteger$int_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..468ca79306ee4eb142054d70e56e0d29f9d1b6de
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$int_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$numerator_descriptor.class b/src/main/resources/org/python/core/PyInteger$numerator_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..27fbdb06dc562c3cf1a1087cdaafdcaf870765ae
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$numerator_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyInteger$real_descriptor.class b/src/main/resources/org/python/core/PyInteger$real_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ece38734e2d22b2dd71eee19da71f58a995bd013
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger$real_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyInteger.class b/src/main/resources/org/python/core/PyInteger.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa1777589b7a180e2fdd65050a5e6daecbfa61e7
Binary files /dev/null and b/src/main/resources/org/python/core/PyInteger.class differ
diff --git a/src/main/resources/org/python/core/PyIntegerDerived.class b/src/main/resources/org/python/core/PyIntegerDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2e1d7ddbc51801326238bae0f4a7fa6d59d3082
Binary files /dev/null and b/src/main/resources/org/python/core/PyIntegerDerived.class differ
diff --git a/src/main/resources/org/python/core/PyIterator$1.class b/src/main/resources/org/python/core/PyIterator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..60766b3954e676a47f03a8f41227835a9d0e61ca
Binary files /dev/null and b/src/main/resources/org/python/core/PyIterator$1.class differ
diff --git a/src/main/resources/org/python/core/PyIterator.class b/src/main/resources/org/python/core/PyIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ff77f67b000baa2e8812b76be546a2676f2de1b
Binary files /dev/null and b/src/main/resources/org/python/core/PyIterator.class differ
diff --git a/src/main/resources/org/python/core/PyJavaPackage.class b/src/main/resources/org/python/core/PyJavaPackage.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e4847626f9612103821d23d398ea864fd11e295
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaPackage.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$1.class b/src/main/resources/org/python/core/PyJavaType$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..92b2d0aa883d4eb5a9a839c9b8bab89030427d03
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$1.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$10.class b/src/main/resources/org/python/core/PyJavaType$10.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c9ffe20033543b36fb9f8eb3f17031c2102e1dd
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$10.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$11.class b/src/main/resources/org/python/core/PyJavaType$11.class
new file mode 100644
index 0000000000000000000000000000000000000000..d756ccbd19893bee9892b6b927909f200382e85c
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$11.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$12.class b/src/main/resources/org/python/core/PyJavaType$12.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc74f877d43f2db947d550bc8a7fd9701f391c6f
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$12.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$13.class b/src/main/resources/org/python/core/PyJavaType$13.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5b3993e0a9c5c2346077b759eccc9755aadd447
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$13.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$14.class b/src/main/resources/org/python/core/PyJavaType$14.class
new file mode 100644
index 0000000000000000000000000000000000000000..84ee3fde21a02a2625ffe7425c0bde6d7eceac4c
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$14.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$15.class b/src/main/resources/org/python/core/PyJavaType$15.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a7b3349fbeb98c79865700930c5b35c284ff964
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$15.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$16.class b/src/main/resources/org/python/core/PyJavaType$16.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f57922775984e4206aaaa285a8ae51b904284e3
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$16.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$17.class b/src/main/resources/org/python/core/PyJavaType$17.class
new file mode 100644
index 0000000000000000000000000000000000000000..37b5e3c8c8b811024469aff3f6a5d33897fefa77
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$17.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$18.class b/src/main/resources/org/python/core/PyJavaType$18.class
new file mode 100644
index 0000000000000000000000000000000000000000..58527690efff6494cf45c7751420581cbe484472
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$18.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$19.class b/src/main/resources/org/python/core/PyJavaType$19.class
new file mode 100644
index 0000000000000000000000000000000000000000..983ba07c46df7878513755a15c55f3533c42b785
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$19.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$2.class b/src/main/resources/org/python/core/PyJavaType$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..129e377a6b8f32234a99a25e568c10d4c4a7a0fa
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$2.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$20.class b/src/main/resources/org/python/core/PyJavaType$20.class
new file mode 100644
index 0000000000000000000000000000000000000000..f858260965513a26cb479414a11decd6287445db
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$20.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$21.class b/src/main/resources/org/python/core/PyJavaType$21.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed88f45af1d9412c06aceb89d8f30ba6a1df1dcc
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$21.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$22.class b/src/main/resources/org/python/core/PyJavaType$22.class
new file mode 100644
index 0000000000000000000000000000000000000000..22eeae87647bdb429f3cc6791c45685be49ab7e1
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$22.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$23.class b/src/main/resources/org/python/core/PyJavaType$23.class
new file mode 100644
index 0000000000000000000000000000000000000000..911a4cbdfe4bccf6149b7c744c52261a2c1184f7
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$23.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$24.class b/src/main/resources/org/python/core/PyJavaType$24.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecb841d8c1792fac064abb24c653645ba40bb45c
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$24.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$25.class b/src/main/resources/org/python/core/PyJavaType$25.class
new file mode 100644
index 0000000000000000000000000000000000000000..77c1261170585c4aa31c0031adbbb9bea41484fb
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$25.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$26.class b/src/main/resources/org/python/core/PyJavaType$26.class
new file mode 100644
index 0000000000000000000000000000000000000000..a480f7f0d6466092df32b4c2702807fda6a742af
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$26.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$27.class b/src/main/resources/org/python/core/PyJavaType$27.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0f3fc784ccec1919ae004715b5371c70aebc607
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$27.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$28.class b/src/main/resources/org/python/core/PyJavaType$28.class
new file mode 100644
index 0000000000000000000000000000000000000000..432fb1e2d255307213498939f175c23ad816e170
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$28.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$29.class b/src/main/resources/org/python/core/PyJavaType$29.class
new file mode 100644
index 0000000000000000000000000000000000000000..504781cfafa43591087f79d6734ae5d9d35b8901
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$29.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$3.class b/src/main/resources/org/python/core/PyJavaType$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..14facf81038bd69d311f3e9eb3e31edb0a09e5a3
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$3.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$4.class b/src/main/resources/org/python/core/PyJavaType$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ffa8ecd9d0025073c8cfdde05a4c9f1d8fdcaba
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$4.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$5.class b/src/main/resources/org/python/core/PyJavaType$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2c0ac2a8116b8cada9ba68ede446dacf0c751ec
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$5.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$6.class b/src/main/resources/org/python/core/PyJavaType$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..e908eb3e009287c9ecf6ee2104b8c5def74b82ef
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$6.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$7.class b/src/main/resources/org/python/core/PyJavaType$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..943c72f7b4111808ca2f719ef7ce7f25093eb740
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$7.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$8.class b/src/main/resources/org/python/core/PyJavaType$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..404251bf2f38d50bccf108d1bcb9edafc70576de
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$8.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$9.class b/src/main/resources/org/python/core/PyJavaType$9.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ee29e799999310c54a64b5fb0cb8f2e873840be
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$9.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$CloneInput.class b/src/main/resources/org/python/core/PyJavaType$CloneInput.class
new file mode 100644
index 0000000000000000000000000000000000000000..54e48fd7237613e288833b3dc4d832b43308b9da
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$CloneInput.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$CloneOutput.class b/src/main/resources/org/python/core/PyJavaType$CloneOutput.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e01dbcedcd208ccd2581afd2fb75255005e73f4
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$CloneOutput.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$ComparableMethod.class b/src/main/resources/org/python/core/PyJavaType$ComparableMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..415b1c6b5ed37f9ba547200df54cf23eb9839f6f
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$ComparableMethod.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$EnumerationIter.class b/src/main/resources/org/python/core/PyJavaType$EnumerationIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..7581e9ecb995efa8db03dd9635cb6e496d2c5ae1
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$EnumerationIter.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$IteratorIter.class b/src/main/resources/org/python/core/PyJavaType$IteratorIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..35c18abf4f6dc9eccb2fe886fe727f2af349f1ec
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$IteratorIter.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$ListIndexDelegate.class b/src/main/resources/org/python/core/PyJavaType$ListIndexDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4c4406905c147110e0b4bba27f433bb682ee0c6
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$ListIndexDelegate.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$ListMethod.class b/src/main/resources/org/python/core/PyJavaType$ListMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1f1d2262af8e683f0603c1aa6247b15ebe77e08
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$ListMethod.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType$MapMethod.class b/src/main/resources/org/python/core/PyJavaType$MapMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d972a5f89155b9216a8568c94a43ccc066b7a05
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType$MapMethod.class differ
diff --git a/src/main/resources/org/python/core/PyJavaType.class b/src/main/resources/org/python/core/PyJavaType.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9b4bf9f92d79458f80f2df16f7ec2efcd0bb2b3
Binary files /dev/null and b/src/main/resources/org/python/core/PyJavaType.class differ
diff --git a/src/main/resources/org/python/core/PyList$1.class b/src/main/resources/org/python/core/PyList$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..14d1e0c748ed420d17c61136ac9d80fd84bce603
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$1.class differ
diff --git a/src/main/resources/org/python/core/PyList$2.class b/src/main/resources/org/python/core/PyList$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..127e2ba67282bf2542f2f6ea8d17b9ae4382d29e
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$2.class differ
diff --git a/src/main/resources/org/python/core/PyList$KV.class b/src/main/resources/org/python/core/PyList$KV.class
new file mode 100644
index 0000000000000000000000000000000000000000..8495f5a4bf65fa45958f32e05dcac6bc2dad7c68
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$KV.class differ
diff --git a/src/main/resources/org/python/core/PyList$KVComparator.class b/src/main/resources/org/python/core/PyList$KVComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..81646a07988292b27bdc6f8ba95b71d6546da926
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$KVComparator.class differ
diff --git a/src/main/resources/org/python/core/PyList$PyExposer.class b/src/main/resources/org/python/core/PyList$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f0c7b1573afc5c46e73c4ad5fa688fcb243be0d
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$PyObjectComparator.class b/src/main/resources/org/python/core/PyList$PyObjectComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..39663f2748d4682fc801ad947ceda8f28c49524f
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$PyObjectComparator.class differ
diff --git a/src/main/resources/org/python/core/PyList$PyObjectDefaultComparator.class b/src/main/resources/org/python/core/PyList$PyObjectDefaultComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..765907d5cd659a6e50c6f95f690993d3910c6cbc
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$PyObjectDefaultComparator.class differ
diff --git a/src/main/resources/org/python/core/PyList$exposed___new__.class b/src/main/resources/org/python/core/PyList$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc17321d5f4fb85eae799095ad221fc06ffd1a61
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___add___exposer.class b/src/main/resources/org/python/core/PyList$list___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6fc54765b10eb2d654e13cffa54fdac6bc1d775
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___contains___exposer.class b/src/main/resources/org/python/core/PyList$list___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e7869f03f9aca8cd4df02c3412284a82a1ccd91
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___delitem___exposer.class b/src/main/resources/org/python/core/PyList$list___delitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..622e31b90eb64a47b5fc056e098fa5953704623e
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___delitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___delslice___exposer.class b/src/main/resources/org/python/core/PyList$list___delslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1efd042ff65b143e2441d4e674817f2b85cb22e6
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___delslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___eq___exposer.class b/src/main/resources/org/python/core/PyList$list___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab14c8b7145d2f146fc3c9b4fbe7d1460f7f11e8
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___ge___exposer.class b/src/main/resources/org/python/core/PyList$list___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2a5dc1a2f59972218aa9e9586c2d769d0198279
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___getitem___exposer.class b/src/main/resources/org/python/core/PyList$list___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1a4d25f97a574aaa95eceb7e08461eb8dbabc3e
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___getslice___exposer.class b/src/main/resources/org/python/core/PyList$list___getslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc2115c17584e8e29fbc94fa9340f4e72ca013fc
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___getslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___gt___exposer.class b/src/main/resources/org/python/core/PyList$list___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9014100fa4cbae978f48a26a25f300cf8eca71d
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___hash___exposer.class b/src/main/resources/org/python/core/PyList$list___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e28329498cabc7ca7ffd2084d9f17cf0cb1e8e5
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___iadd___exposer.class b/src/main/resources/org/python/core/PyList$list___iadd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5206ac505096e332a220d4d21fd55025af14fee8
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___iadd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___imul___exposer.class b/src/main/resources/org/python/core/PyList$list___imul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..588166429696d3cacde48ac19d79502f29aa0602
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___imul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___init___exposer.class b/src/main/resources/org/python/core/PyList$list___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c932c096dd62512e141b8924556fbfc1ac29ad63
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___iter___exposer.class b/src/main/resources/org/python/core/PyList$list___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9608c5c6dcee88a6bf5bc055a237702892afadc3
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___le___exposer.class b/src/main/resources/org/python/core/PyList$list___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b087db8d6e83813e98c80583a66713535a7f1398
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___len___exposer.class b/src/main/resources/org/python/core/PyList$list___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..77251cef636b5dd2e23c55397f29b4986f0b12f7
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___lt___exposer.class b/src/main/resources/org/python/core/PyList$list___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..38738d74352004ee8f8a7ebcd251e3a445f3139f
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___mul___exposer.class b/src/main/resources/org/python/core/PyList$list___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dd7f2bf693f76cb875d5a451b2ffb4032439ff5
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___ne___exposer.class b/src/main/resources/org/python/core/PyList$list___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c6f9432ee4a5ba39d9163778f5dbc27318c4189
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___radd___exposer.class b/src/main/resources/org/python/core/PyList$list___radd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbe187e5cd353aa43d82e2a588c0dbfcff4543f0
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___radd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___reversed___exposer.class b/src/main/resources/org/python/core/PyList$list___reversed___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc67480e32be8563c51063ebb5ba6459a440d31a
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___reversed___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___rmul___exposer.class b/src/main/resources/org/python/core/PyList$list___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e31653b69c6398b217bbf637da467b4d0906f6a
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___setitem___exposer.class b/src/main/resources/org/python/core/PyList$list___setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..26a8891053ac5fed03711af85e691efd6db44e2e
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___setitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list___setslice___exposer.class b/src/main/resources/org/python/core/PyList$list___setslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f93fdaa76751e948764cfb5b6b6cdb684d5ea76a
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list___setslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_append_exposer.class b/src/main/resources/org/python/core/PyList$list_append_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..07b1ca5e1b76f2082d4b7db65a8ac610fd03ac77
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_append_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_count_exposer.class b/src/main/resources/org/python/core/PyList$list_count_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e044260dbdad27e11febe4601823e648243fa34f
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_count_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_extend_exposer.class b/src/main/resources/org/python/core/PyList$list_extend_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fb8e469c674a6c528c45355cd00c09a716dceff
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_extend_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_index_exposer.class b/src/main/resources/org/python/core/PyList$list_index_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce64c1cef8e80bdbb46ff1258bf21504f40f69a4
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_index_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_insert_exposer.class b/src/main/resources/org/python/core/PyList$list_insert_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ca6e70f66f0fea1fa2b47651aebac1ef844d845
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_insert_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_pop_exposer.class b/src/main/resources/org/python/core/PyList$list_pop_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fc65277898a7098326d86cf0ccef5e600405cea
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_pop_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_remove_exposer.class b/src/main/resources/org/python/core/PyList$list_remove_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..784117b690080a76ab5a362e82f859826e158928
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_remove_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_reverse_exposer.class b/src/main/resources/org/python/core/PyList$list_reverse_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..76e6346166de5dba06bf7847dafcc33886a6a13b
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_reverse_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_sort_exposer.class b/src/main/resources/org/python/core/PyList$list_sort_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f0e2afdd68ee366cf3ec2947326e05283ecbff3
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_sort_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList$list_toString_exposer.class b/src/main/resources/org/python/core/PyList$list_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cad7e0049087237be8bc02b629535aafb22a51ac
Binary files /dev/null and b/src/main/resources/org/python/core/PyList$list_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyList.class b/src/main/resources/org/python/core/PyList.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6a3f8fbe3c2003cc9d8146c9f821525d3613022
Binary files /dev/null and b/src/main/resources/org/python/core/PyList.class differ
diff --git a/src/main/resources/org/python/core/PyListDerived.class b/src/main/resources/org/python/core/PyListDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe684023554e30a97a25afd59b2f62dc4eccfd36
Binary files /dev/null and b/src/main/resources/org/python/core/PyListDerived.class differ
diff --git a/src/main/resources/org/python/core/PyListTest.class b/src/main/resources/org/python/core/PyListTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab9d6c7b7c51e01ed79d64d26c03aa923a5f60ab
Binary files /dev/null and b/src/main/resources/org/python/core/PyListTest.class differ
diff --git a/src/main/resources/org/python/core/PyLong$PyExposer.class b/src/main/resources/org/python/core/PyLong$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c13785573cc4a5c44fc0f62ae3f2b413c377985
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$denominator_descriptor.class b/src/main/resources/org/python/core/PyLong$denominator_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cda4491606707de0ed46db2ef316e4d1ac73d26c
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$denominator_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyLong$exposed___new__.class b/src/main/resources/org/python/core/PyLong$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..77d942d8e6910c829a1d74d840f72edb0dd5a45f
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyLong$imag_descriptor.class b/src/main/resources/org/python/core/PyLong$imag_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aae1d1b0fdbc29ec08d54d47435cac3d03b1279d
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$imag_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___abs___exposer.class b/src/main/resources/org/python/core/PyLong$long___abs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7cb8aeaa8a762fd02de79e4c8b8036f9e220eab
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___abs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___add___exposer.class b/src/main/resources/org/python/core/PyLong$long___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1665e79e86eda01e31057d44dcb9ec9e6b3100a1
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___and___exposer.class b/src/main/resources/org/python/core/PyLong$long___and___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..416f8ca8260f1dd610c321c13c4dad634cacc8b7
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___and___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___cmp___exposer.class b/src/main/resources/org/python/core/PyLong$long___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..26e0351e0088c172efa0e7a56b4c9e375041d221
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___coerce___exposer.class b/src/main/resources/org/python/core/PyLong$long___coerce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b3fe7cbd6b21695f6c2130ddadf83883f2b2d1b
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___coerce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___div___exposer.class b/src/main/resources/org/python/core/PyLong$long___div___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..80b2bc4989b66daa0032a6d87f6134c7f23ca04e
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___div___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___divmod___exposer.class b/src/main/resources/org/python/core/PyLong$long___divmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d56ea81b9f5bd6d94fdf6341006f90f445303af2
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___divmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___float___exposer.class b/src/main/resources/org/python/core/PyLong$long___float___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee561b70e040abbd54e8191bec002b61d397e2eb
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___float___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___floordiv___exposer.class b/src/main/resources/org/python/core/PyLong$long___floordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..89bb80f57c1013daab44d891395418303dcf361c
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___floordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___format___exposer.class b/src/main/resources/org/python/core/PyLong$long___format___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..05b0772d37ac67ebb73d8b32a2ee1085e3b49370
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___format___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___getnewargs___exposer.class b/src/main/resources/org/python/core/PyLong$long___getnewargs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..02410269722778ef76e6029ea91bdede95659825
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___getnewargs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___hash___exposer.class b/src/main/resources/org/python/core/PyLong$long___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1eece6707b475271d046aa13fde32eb16dfac75e
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___hex___exposer.class b/src/main/resources/org/python/core/PyLong$long___hex___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..942402d8b404839f8e1d1bbcdcf73d6dfb6a0a81
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___hex___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___index___exposer.class b/src/main/resources/org/python/core/PyLong$long___index___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..08b2954d273271080ba3a055ca658855e90a6a7c
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___index___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___int___exposer.class b/src/main/resources/org/python/core/PyLong$long___int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d62087ce870a6c527a619aecd0d95df7819a256
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___int___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___invert___exposer.class b/src/main/resources/org/python/core/PyLong$long___invert___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa29c7729bb214740358fb30371853bbc5f47692
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___invert___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___long___exposer.class b/src/main/resources/org/python/core/PyLong$long___long___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8331fa0f1f956c7cabec54c7736ae7c4cd89e827
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___long___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___lshift___exposer.class b/src/main/resources/org/python/core/PyLong$long___lshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..47f3ca423218c70240537656efadcbfbe28df88e
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___lshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___mod___exposer.class b/src/main/resources/org/python/core/PyLong$long___mod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..48e245c33db8bbb82d6f67c91e1690c61513f97c
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___mod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___mul___exposer.class b/src/main/resources/org/python/core/PyLong$long___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4cde8bc3dc8f3b02934919e3f44f6072c2254551
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___neg___exposer.class b/src/main/resources/org/python/core/PyLong$long___neg___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd9e4ca8f8ff047612b7c9d07727c762de3ce742
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___neg___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___nonzero___exposer.class b/src/main/resources/org/python/core/PyLong$long___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6043119e43b0ac7161c9c895f55bc640e99c475
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___oct___exposer.class b/src/main/resources/org/python/core/PyLong$long___oct___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4d4fb42a027b6565bc36b7a04e04587d35469a3
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___oct___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___or___exposer.class b/src/main/resources/org/python/core/PyLong$long___or___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e448b00cd63a3db0bb74477adcb5d34e44e35a04
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___or___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___pos___exposer.class b/src/main/resources/org/python/core/PyLong$long___pos___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..042a1da0cba5c240db9653bad84889099c787ed6
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___pos___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___pow___exposer.class b/src/main/resources/org/python/core/PyLong$long___pow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb0f6ed089e402a48b6d95089dfaf466f8190004
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___pow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___radd___exposer.class b/src/main/resources/org/python/core/PyLong$long___radd___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..acf366f7339c7f10a7775e40ec03d1684c39fcdd
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___radd___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rand___exposer.class b/src/main/resources/org/python/core/PyLong$long___rand___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5115f1cb7fd209200b722f045628374f123a95ef
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rand___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rdiv___exposer.class b/src/main/resources/org/python/core/PyLong$long___rdiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1e9a65c949e2e96436417aacb7f1709268e4a48
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rdiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rdivmod___exposer.class b/src/main/resources/org/python/core/PyLong$long___rdivmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..37de59e7b8c007a1752f030bb8e7be1c1689e01f
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rdivmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rfloordiv___exposer.class b/src/main/resources/org/python/core/PyLong$long___rfloordiv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c43af9ae95d5620593d209ca1b62534235420bca
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rfloordiv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rlshift___exposer.class b/src/main/resources/org/python/core/PyLong$long___rlshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8308b2d8184729106b07482e397a8b33abaf66d8
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rlshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rmod___exposer.class b/src/main/resources/org/python/core/PyLong$long___rmod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6bf97482402539f5f3cb29d8f05556919763ec53
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rmod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rmul___exposer.class b/src/main/resources/org/python/core/PyLong$long___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb0de8372c71fa4e8a0493d536bf73ecc3d752af
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___ror___exposer.class b/src/main/resources/org/python/core/PyLong$long___ror___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..55ba88e22c7a3dab598df2bae1666008205904ba
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___ror___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rpow___exposer.class b/src/main/resources/org/python/core/PyLong$long___rpow___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..423a7576d31a7f6b89a43d5d5746739467df361e
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rpow___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rrshift___exposer.class b/src/main/resources/org/python/core/PyLong$long___rrshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..08fdfb12a02e096df45a6e93cee7cebc4f8f4516
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rrshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rshift___exposer.class b/src/main/resources/org/python/core/PyLong$long___rshift___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d407218b56531f256c0043ce5b94cc86a6fd645e
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rshift___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rsub___exposer.class b/src/main/resources/org/python/core/PyLong$long___rsub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c5569853827b03eb42ba772abdfec2e2569e4724
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rsub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rtruediv___exposer.class b/src/main/resources/org/python/core/PyLong$long___rtruediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..64accbad4ea219458eeb4e6be0a073fa64c4c6c0
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rtruediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___rxor___exposer.class b/src/main/resources/org/python/core/PyLong$long___rxor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b75bf7138f4bd112dcb1027e42ec9336699b9a7
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___rxor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___str___exposer.class b/src/main/resources/org/python/core/PyLong$long___str___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf3b50b2ae2e5db4ca0a4a7446c2275255ca0446
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___str___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___sub___exposer.class b/src/main/resources/org/python/core/PyLong$long___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e6127b615e13a5a89fef74f652c9a583a6d0ceb
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___truediv___exposer.class b/src/main/resources/org/python/core/PyLong$long___truediv___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..538f6d53c447cc2eaaab3862cf68ca425dcfceb1
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___truediv___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___trunc___exposer.class b/src/main/resources/org/python/core/PyLong$long___trunc___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d345f0aee99eca09f6daf79ecb22f98d783f94a8
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___trunc___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long___xor___exposer.class b/src/main/resources/org/python/core/PyLong$long___xor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..58e91b04dee11df235a8e27b154b920945ecbf1f
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long___xor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long_bit_length_exposer.class b/src/main/resources/org/python/core/PyLong$long_bit_length_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..23d5482f64a1ec72e5a9cb697053804f3ea47d62
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long_bit_length_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long_conjugate_exposer.class b/src/main/resources/org/python/core/PyLong$long_conjugate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..773783706675d0bec98d954f938989157fd1574f
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long_conjugate_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$long_toString_exposer.class b/src/main/resources/org/python/core/PyLong$long_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b0720a6c16492c920acad62add15fb7f33bcd9d6
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$long_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyLong$numerator_descriptor.class b/src/main/resources/org/python/core/PyLong$numerator_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..439eec9f746a644e590db64ec0451476edaeeb03
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$numerator_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyLong$real_descriptor.class b/src/main/resources/org/python/core/PyLong$real_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ea9051e2948669b18c6197be61cf5770106c84b
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong$real_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyLong.class b/src/main/resources/org/python/core/PyLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..af0895c083fc399bebfc0174d2a13549d1d613ff
Binary files /dev/null and b/src/main/resources/org/python/core/PyLong.class differ
diff --git a/src/main/resources/org/python/core/PyLongDerived.class b/src/main/resources/org/python/core/PyLongDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d4e775e2cbfb56223977f8d36b45cd7e3050ecb
Binary files /dev/null and b/src/main/resources/org/python/core/PyLongDerived.class differ
diff --git a/src/main/resources/org/python/core/PyMapEntrySet.class b/src/main/resources/org/python/core/PyMapEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2d86a02435ba2221d11b80446143873611ab126
Binary files /dev/null and b/src/main/resources/org/python/core/PyMapEntrySet.class differ
diff --git a/src/main/resources/org/python/core/PyMapKeyValSet.class b/src/main/resources/org/python/core/PyMapKeyValSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fb46f5340584217e8c03944019f7830f8dacdee
Binary files /dev/null and b/src/main/resources/org/python/core/PyMapKeyValSet.class differ
diff --git a/src/main/resources/org/python/core/PyMapSet$PySetIter.class b/src/main/resources/org/python/core/PyMapSet$PySetIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a4f3ea1cb34bed3924edb8e3fa76141326f7cc3
Binary files /dev/null and b/src/main/resources/org/python/core/PyMapSet$PySetIter.class differ
diff --git a/src/main/resources/org/python/core/PyMapSet.class b/src/main/resources/org/python/core/PyMapSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..477a519859e98edc3feaa72d699cece4f46a1881
Binary files /dev/null and b/src/main/resources/org/python/core/PyMapSet.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$PyExposer.class b/src/main/resources/org/python/core/PyMemoryView$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..355b955a306fb37eae15427335a3b7f6e3afa19d
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$exposed___new__.class b/src/main/resources/org/python/core/PyMemoryView$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..8457ccfdaf8e7021515cd9360c50e5117e3de344
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$format_descriptor.class b/src/main/resources/org/python/core/PyMemoryView$format_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f077391048ae3eeb5b8eda6bfc4444dbe422689f
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$format_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$itemsize_descriptor.class b/src/main/resources/org/python/core/PyMemoryView$itemsize_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b313a1c41995d240eb86e8c818e59e6a161e6956
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$itemsize_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___enter___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___enter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..778bcc51f7d566ce862d0166d7adc3e666c5ba26
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___enter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___eq___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb287ba78e2c228bd98c6eae2cad079753c2599e
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___exit___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___exit___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5ff61badbc67f419fa238ba4d68860b984a98fe
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___exit___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___ge___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e8ad19f93e2de77a0cf722e1695ab3c3d208fb1
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___gt___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..17f23e45d72f62db5fa3306ff71f02a690c20096
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___hash___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..19933f5f9674b305305476a6ca395b7da0bc9001
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___le___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e058a3c9e009398a1472a0bee30080d8a4f237b
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___lt___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9eea31bcebccb0a91bb406d93d1fce53a2d93a5d
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview___ne___exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b546c8c3e523ee4e7bb0e5db1e88ebf0bdc4bb6c
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview_release_exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview_release_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1be1c1ed072ea12dfaf1f4be212d2520f8f82532
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview_release_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview_tobytes_exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview_tobytes_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a16de7045dc97e17fa6ef36e51cd10ebb43867f
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview_tobytes_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$memoryview_tolist_exposer.class b/src/main/resources/org/python/core/PyMemoryView$memoryview_tolist_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a167ca1078221ec4798efcb4aa0abd4817b52272
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$memoryview_tolist_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$ndim_descriptor.class b/src/main/resources/org/python/core/PyMemoryView$ndim_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..21d2de2c6b37c9b1ea08ab0ceb0e463a4862814f
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$ndim_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$readonly_descriptor.class b/src/main/resources/org/python/core/PyMemoryView$readonly_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7ee1e0b17918024187a2a85d49b3b2c2503b87b
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$readonly_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$shape_descriptor.class b/src/main/resources/org/python/core/PyMemoryView$shape_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b7d2b36a55d2033dfd0bbb2529808bf637f6aff
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$shape_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$strides_descriptor.class b/src/main/resources/org/python/core/PyMemoryView$strides_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b9ac23d37928bcbd619cc19675c82ad6012984c
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$strides_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView$suboffsets_descriptor.class b/src/main/resources/org/python/core/PyMemoryView$suboffsets_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d76cd73cd81dc592e2bb445653ad9a6116f4c3bc
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView$suboffsets_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMemoryView.class b/src/main/resources/org/python/core/PyMemoryView.class
new file mode 100644
index 0000000000000000000000000000000000000000..e4b4814a4bb0950aecf1b1e07cd7ad8333457659
Binary files /dev/null and b/src/main/resources/org/python/core/PyMemoryView.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$PyExposer.class b/src/main/resources/org/python/core/PyMethod$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a797367f348c5b5e1e4b0e91afbab09c84fb391
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$__doc___descriptor.class b/src/main/resources/org/python/core/PyMethod$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e080d10dc29fcedb3725705cb399f72c4942d93
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$__func___descriptor.class b/src/main/resources/org/python/core/PyMethod$__func___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..42756f8b3d2506513027d67a8f86b8daf2072483
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$__func___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$__self___descriptor.class b/src/main/resources/org/python/core/PyMethod$__self___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbd8f834ebc5a287de7dabed0719304b2c99e77a
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$__self___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$exposed___new__.class b/src/main/resources/org/python/core/PyMethod$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ef8795dd3345fbe9d232c9342ecf390d6804de9
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$im_class_descriptor.class b/src/main/resources/org/python/core/PyMethod$im_class_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a95540747ca0e8d4d0166746faa3c67a3c06b1d
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$im_class_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$im_func_descriptor.class b/src/main/resources/org/python/core/PyMethod$im_func_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b049b53fe317db6086110a7b15c2ae74b08cf2c5
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$im_func_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$im_self_descriptor.class b/src/main/resources/org/python/core/PyMethod$im_self_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..20e5b82ed4932448dd68b6cf6e81d36bcb42e2de
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$im_self_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$instancemethod___call___exposer.class b/src/main/resources/org/python/core/PyMethod$instancemethod___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c70c4c9436caba842c9a47cb34590323f9b1670
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$instancemethod___call___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$instancemethod___cmp___exposer.class b/src/main/resources/org/python/core/PyMethod$instancemethod___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..747ee6ef88d0e5f496d41465918e26d843d80aa3
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$instancemethod___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$instancemethod___get___exposer.class b/src/main/resources/org/python/core/PyMethod$instancemethod___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8207c7662aa71cb959e79e93d34d65ee0c73e3c8
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$instancemethod___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMethod$instancemethod___getattribute___exposer.class b/src/main/resources/org/python/core/PyMethod$instancemethod___getattribute___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c772ee5ee266137639a1853182b174390180441c
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod$instancemethod___getattribute___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMethod.class b/src/main/resources/org/python/core/PyMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..2cf5e531cba3730433e0d778b503cf479490c421
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethod.class differ
diff --git a/src/main/resources/org/python/core/PyMethodDescr$PyExposer.class b/src/main/resources/org/python/core/PyMethodDescr$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9faec2ba19ac83374328d0e3b780c0fee3c2975c
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethodDescr$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyMethodDescr$__doc___descriptor.class b/src/main/resources/org/python/core/PyMethodDescr$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a4b7dc5bd59797f16540b80ed90ce30e696e839
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethodDescr$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethodDescr$__name___descriptor.class b/src/main/resources/org/python/core/PyMethodDescr$__name___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c66dd7c74697861b80c6eab04435acded03852c
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethodDescr$__name___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethodDescr$__objclass___descriptor.class b/src/main/resources/org/python/core/PyMethodDescr$__objclass___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a0b8cbb48bd58abf909651b57dc53a7cb67b7ce
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethodDescr$__objclass___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyMethodDescr$method_descriptor___call___exposer.class b/src/main/resources/org/python/core/PyMethodDescr$method_descriptor___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f225a61a0322876ce122bc6f8afbc76631144706
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethodDescr$method_descriptor___call___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMethodDescr$method_descriptor___get___exposer.class b/src/main/resources/org/python/core/PyMethodDescr$method_descriptor___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d7a730ac1d5c6d353f3b5493e8b3993bbbd5f3c
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethodDescr$method_descriptor___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyMethodDescr.class b/src/main/resources/org/python/core/PyMethodDescr.class
new file mode 100644
index 0000000000000000000000000000000000000000..e85984178cc8c325230df81494d70337085458ec
Binary files /dev/null and b/src/main/resources/org/python/core/PyMethodDescr.class differ
diff --git a/src/main/resources/org/python/core/PyModule$PyExposer.class b/src/main/resources/org/python/core/PyModule$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..714ac0d07419e9f94a528082d68766e47fcb5afc
Binary files /dev/null and b/src/main/resources/org/python/core/PyModule$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyModule$__dict___descriptor.class b/src/main/resources/org/python/core/PyModule$__dict___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d625f1efc2a8118d6d93bb3af42127c0582ab921
Binary files /dev/null and b/src/main/resources/org/python/core/PyModule$__dict___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyModule$exposed___new__.class b/src/main/resources/org/python/core/PyModule$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..18d9a77128ebf2cf482d4d57546e6cfd1c77d177
Binary files /dev/null and b/src/main/resources/org/python/core/PyModule$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyModule$module___delattr___exposer.class b/src/main/resources/org/python/core/PyModule$module___delattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aaaa402a80abe3c6de16948b98f2c264b0a5dcbe
Binary files /dev/null and b/src/main/resources/org/python/core/PyModule$module___delattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyModule$module___init___exposer.class b/src/main/resources/org/python/core/PyModule$module___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4dd4efe55f09bdebeb7e8a5595c3206cfa995757
Binary files /dev/null and b/src/main/resources/org/python/core/PyModule$module___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyModule$module___setattr___exposer.class b/src/main/resources/org/python/core/PyModule$module___setattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..048f0650ea0fbb722aa5c9242206a8c41528e19a
Binary files /dev/null and b/src/main/resources/org/python/core/PyModule$module___setattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyModule$module_toString_exposer.class b/src/main/resources/org/python/core/PyModule$module_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..216ed3eb2cee4c73a898cd4ecf66762932e1c9f0
Binary files /dev/null and b/src/main/resources/org/python/core/PyModule$module_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyModule.class b/src/main/resources/org/python/core/PyModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c8fcbaaf8377090b7085bcc904f5704f9fee20c
Binary files /dev/null and b/src/main/resources/org/python/core/PyModule.class differ
diff --git a/src/main/resources/org/python/core/PyModuleDerived.class b/src/main/resources/org/python/core/PyModuleDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..90c1e3fe3b455a3b9e9845512eb1357e77d5b096
Binary files /dev/null and b/src/main/resources/org/python/core/PyModuleDerived.class differ
diff --git a/src/main/resources/org/python/core/PyNewWrapper.class b/src/main/resources/org/python/core/PyNewWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..9cdc7775e2d0d50a48933a5e633619be129b4122
Binary files /dev/null and b/src/main/resources/org/python/core/PyNewWrapper.class differ
diff --git a/src/main/resources/org/python/core/PyNone$NoneType_toString_exposer.class b/src/main/resources/org/python/core/PyNone$NoneType_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cbf5faa22b039b47feaec497b140423590ea72ff
Binary files /dev/null and b/src/main/resources/org/python/core/PyNone$NoneType_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyNone$PyExposer.class b/src/main/resources/org/python/core/PyNone$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2db05f0ae5c53450a418892e107ed2781ff10e96
Binary files /dev/null and b/src/main/resources/org/python/core/PyNone$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyNone.class b/src/main/resources/org/python/core/PyNone.class
new file mode 100644
index 0000000000000000000000000000000000000000..65f1f6cb7a992ec0f813484a8433d02cf29d0a0f
Binary files /dev/null and b/src/main/resources/org/python/core/PyNone.class differ
diff --git a/src/main/resources/org/python/core/PyNotImplemented.class b/src/main/resources/org/python/core/PyNotImplemented.class
new file mode 100644
index 0000000000000000000000000000000000000000..17985ee5d451790aa940c09817d1103995b163c8
Binary files /dev/null and b/src/main/resources/org/python/core/PyNotImplemented.class differ
diff --git a/src/main/resources/org/python/core/PyObject$1$1.class b/src/main/resources/org/python/core/PyObject$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..412a88242da7bb12899a2adebc7c3da228880ae1
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$1$1.class differ
diff --git a/src/main/resources/org/python/core/PyObject$1.class b/src/main/resources/org/python/core/PyObject$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..fac0a6c6846dfdca28e0e4ae8030e7ff034d7eea
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$1.class differ
diff --git a/src/main/resources/org/python/core/PyObject$ConversionException.class b/src/main/resources/org/python/core/PyObject$ConversionException.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe901d56ecaf68e037b5d5f1bb4583d2e118c0cc
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$ConversionException.class differ
diff --git a/src/main/resources/org/python/core/PyObject$PyExposer.class b/src/main/resources/org/python/core/PyObject$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0fed6f19f2d82cd01d1cc1d4673d50abcf80f7ee
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$__class___descriptor.class b/src/main/resources/org/python/core/PyObject$__class___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f46cb3544c1be30f4ab08fee204554609ac1c621
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$__class___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyObject$__repr___exposer.class b/src/main/resources/org/python/core/PyObject$__repr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..19dbf0f2257a627785dc30e395312a10424358a9
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$__repr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$exposed___new__.class b/src/main/resources/org/python/core/PyObject$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..127437246b2693c1ccea5a2e9508ced39199ae8c
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___delattr___exposer.class b/src/main/resources/org/python/core/PyObject$object___delattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b25f904650b9472f8308271a24244ce11c996cc
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___delattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___format___exposer.class b/src/main/resources/org/python/core/PyObject$object___format___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b994a2871493f03a1732b353519861a3987b580
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___format___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___getattribute___exposer.class b/src/main/resources/org/python/core/PyObject$object___getattribute___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..adb554b22a8b555c89680cdfd53a443d61596679
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___getattribute___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___hash___exposer.class b/src/main/resources/org/python/core/PyObject$object___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c306cbfa18a3ea7cf4c9d662ee8f38dda77fd6b
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___init___exposer.class b/src/main/resources/org/python/core/PyObject$object___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..43de1d4c0e2022c3711d80a8e72769c1ddab0f98
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___reduce___exposer.class b/src/main/resources/org/python/core/PyObject$object___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1bd799b3062e29eb46bf33b47fafb094f2de9668
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___reduce_ex___exposer.class b/src/main/resources/org/python/core/PyObject$object___reduce_ex___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7e154179230bc37a46ecc4167b03811d48b42c6
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___reduce_ex___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___setattr___exposer.class b/src/main/resources/org/python/core/PyObject$object___setattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..78874edcd1f729aa2753d0256d8ae36ce998f750
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___setattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object___subclasshook___exposer.class b/src/main/resources/org/python/core/PyObject$object___subclasshook___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb6f4e22d4a799385df326a7bcf3023e5a6ef2ff
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object___subclasshook___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject$object_toString_exposer.class b/src/main/resources/org/python/core/PyObject$object_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..01e0e67bc7f52b8374d412930c627aac30c4e70b
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject$object_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyObject.class b/src/main/resources/org/python/core/PyObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..59443df1990f61aa2c788c899b05f56b4a44be8a
Binary files /dev/null and b/src/main/resources/org/python/core/PyObject.class differ
diff --git a/src/main/resources/org/python/core/PyObjectDerived.class b/src/main/resources/org/python/core/PyObjectDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccce8ed794461c8c07e8140bd6af22532091a5dd
Binary files /dev/null and b/src/main/resources/org/python/core/PyObjectDerived.class differ
diff --git a/src/main/resources/org/python/core/PyOverridableNew.class b/src/main/resources/org/python/core/PyOverridableNew.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7d9a873566c979c21ea7b1914da5d4c673e08ca
Binary files /dev/null and b/src/main/resources/org/python/core/PyOverridableNew.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$PyExposer.class b/src/main/resources/org/python/core/PyProperty$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..487384e51a8917bac42c1fcf124432942247e197
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$__doc___descriptor.class b/src/main/resources/org/python/core/PyProperty$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..eea3c0420daffb44132bf6d16a602286ea26f71c
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$exposed___new__.class b/src/main/resources/org/python/core/PyProperty$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..810979e9906104f70e36dd1347950edfe640656a
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$fdel_descriptor.class b/src/main/resources/org/python/core/PyProperty$fdel_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..146c434021d09aba42aec4f3c88c796c2959a60f
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$fdel_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$fget_descriptor.class b/src/main/resources/org/python/core/PyProperty$fget_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..408e0642c0b837f75b0b26eab9e0e72b8a92619f
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$fget_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$fset_descriptor.class b/src/main/resources/org/python/core/PyProperty$fset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..44ee1d320a45c66ffc25ca9dfd815fd1c6bc7a20
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$fset_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$property___delete___exposer.class b/src/main/resources/org/python/core/PyProperty$property___delete___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8c527f6a5f626ed1c009788718914aedcdfc536
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$property___delete___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$property___get___exposer.class b/src/main/resources/org/python/core/PyProperty$property___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac9aa38494074b76e8f04f6e3676c665f0b1fb7a
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$property___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$property___init___exposer.class b/src/main/resources/org/python/core/PyProperty$property___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a429aa16b715597d586153f57807c4de28b6ae8e
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$property___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$property___set___exposer.class b/src/main/resources/org/python/core/PyProperty$property___set___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..03ef6ccd00c0669fd2814e4701d1e5d9040f5004
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$property___set___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$property_deleter_exposer.class b/src/main/resources/org/python/core/PyProperty$property_deleter_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c04da5ac35bf3b8eedab1652befbe6f28d684016
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$property_deleter_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$property_getter_exposer.class b/src/main/resources/org/python/core/PyProperty$property_getter_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b1a31bea33752557578448595748615fedf6f88
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$property_getter_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyProperty$property_setter_exposer.class b/src/main/resources/org/python/core/PyProperty$property_setter_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..74f40823a4a922f12bebb6e7a61e93ee5077137a
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty$property_setter_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyProperty.class b/src/main/resources/org/python/core/PyProperty.class
new file mode 100644
index 0000000000000000000000000000000000000000..e47ff456aaf83c52344fa14458b0933cf264f8d2
Binary files /dev/null and b/src/main/resources/org/python/core/PyProperty.class differ
diff --git a/src/main/resources/org/python/core/PyPropertyDerived.class b/src/main/resources/org/python/core/PyPropertyDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4377d3a4774a5fbf9b37ffd27f421e4e322ff5b
Binary files /dev/null and b/src/main/resources/org/python/core/PyPropertyDerived.class differ
diff --git a/src/main/resources/org/python/core/PyProxy.class b/src/main/resources/org/python/core/PyProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca78a6bd446bf124cfab87f88c7e340afa8cf472
Binary files /dev/null and b/src/main/resources/org/python/core/PyProxy.class differ
diff --git a/src/main/resources/org/python/core/PyReflectedConstructor.class b/src/main/resources/org/python/core/PyReflectedConstructor.class
new file mode 100644
index 0000000000000000000000000000000000000000..68e946040fd9e1dc80521661e23ea782d4f565a0
Binary files /dev/null and b/src/main/resources/org/python/core/PyReflectedConstructor.class differ
diff --git a/src/main/resources/org/python/core/PyReflectedField.class b/src/main/resources/org/python/core/PyReflectedField.class
new file mode 100644
index 0000000000000000000000000000000000000000..10c678df570d74b7ff63254e1b362b82a4d4fb62
Binary files /dev/null and b/src/main/resources/org/python/core/PyReflectedField.class differ
diff --git a/src/main/resources/org/python/core/PyReflectedFunction.class b/src/main/resources/org/python/core/PyReflectedFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fe572d282517ec10bfdf1b6643e2f42d6f66173
Binary files /dev/null and b/src/main/resources/org/python/core/PyReflectedFunction.class differ
diff --git a/src/main/resources/org/python/core/PyReversedIterator.class b/src/main/resources/org/python/core/PyReversedIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..a739017c33096f142beccea2cf696de432e425a3
Binary files /dev/null and b/src/main/resources/org/python/core/PyReversedIterator.class differ
diff --git a/src/main/resources/org/python/core/PyRunnable.class b/src/main/resources/org/python/core/PyRunnable.class
new file mode 100644
index 0000000000000000000000000000000000000000..108f0fc8e02191ee42dca083b79e82ed81dd8566
Binary files /dev/null and b/src/main/resources/org/python/core/PyRunnable.class differ
diff --git a/src/main/resources/org/python/core/PyRunnableBootstrap$1.class b/src/main/resources/org/python/core/PyRunnableBootstrap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a45180c8738f1053875a90741b604349dcf09d2
Binary files /dev/null and b/src/main/resources/org/python/core/PyRunnableBootstrap$1.class differ
diff --git a/src/main/resources/org/python/core/PyRunnableBootstrap.class b/src/main/resources/org/python/core/PyRunnableBootstrap.class
new file mode 100644
index 0000000000000000000000000000000000000000..521f8bb2f1b1b5a4833941513e947e71f2c662f2
Binary files /dev/null and b/src/main/resources/org/python/core/PyRunnableBootstrap.class differ
diff --git a/src/main/resources/org/python/core/PySequence$DefaultIndexDelegate.class b/src/main/resources/org/python/core/PySequence$DefaultIndexDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ba20866bd2f9ba81a9b65e4fd434e01111defe6
Binary files /dev/null and b/src/main/resources/org/python/core/PySequence$DefaultIndexDelegate.class differ
diff --git a/src/main/resources/org/python/core/PySequence.class b/src/main/resources/org/python/core/PySequence.class
new file mode 100644
index 0000000000000000000000000000000000000000..44ac96bca75c97d43fc4f60e36f6924d70b6a686
Binary files /dev/null and b/src/main/resources/org/python/core/PySequence.class differ
diff --git a/src/main/resources/org/python/core/PySequenceIter.class b/src/main/resources/org/python/core/PySequenceIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dd4a5a5ad20d9ac0bc4a1ed5ed0de53e1de621b
Binary files /dev/null and b/src/main/resources/org/python/core/PySequenceIter.class differ
diff --git a/src/main/resources/org/python/core/PySequenceList.class b/src/main/resources/org/python/core/PySequenceList.class
new file mode 100644
index 0000000000000000000000000000000000000000..7cd293a22497f19974efbce88e87c588cb5905df
Binary files /dev/null and b/src/main/resources/org/python/core/PySequenceList.class differ
diff --git a/src/main/resources/org/python/core/PySet$PyExposer.class b/src/main/resources/org/python/core/PySet$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a237bb2c76ea51cc98e08b4786d4fe5264114e1f
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$exposed___new__.class b/src/main/resources/org/python/core/PySet$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1e1f508b2837e831333e44dd5a12f4242a84915
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___and___exposer.class b/src/main/resources/org/python/core/PySet$set___and___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c790c41cb534500c8f9dcf5c8c251156ee2bc4c3
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___and___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___cmp___exposer.class b/src/main/resources/org/python/core/PySet$set___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f7a511f312bf1675a98f114bdf3c0cdfb1c9b87
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___contains___exposer.class b/src/main/resources/org/python/core/PySet$set___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..790ca9fb3623537de559c74f0152094f6141542b
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___eq___exposer.class b/src/main/resources/org/python/core/PySet$set___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..be612ea0a1310105ee07517e47bd6eb69c10ceb5
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___ge___exposer.class b/src/main/resources/org/python/core/PySet$set___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2caf164e752c7e435044d6fe6c2f7d24a0134c4
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___gt___exposer.class b/src/main/resources/org/python/core/PySet$set___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f43cf1a3a9680a885a909521f301877f5758d0e
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___hash___exposer.class b/src/main/resources/org/python/core/PySet$set___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5c10fd7d757db48991d9332ebe6a38229e585c0
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___iand___exposer.class b/src/main/resources/org/python/core/PySet$set___iand___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..55af91da9ab4840206a0e65c105267231f5cc489
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___iand___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___init___exposer.class b/src/main/resources/org/python/core/PySet$set___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f9a5280f2012dab31e5cef224df8a3fb16f5475
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___ior___exposer.class b/src/main/resources/org/python/core/PySet$set___ior___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb20139817c3d8b17a81344655f95ccfe000d3aa
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___ior___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___isub___exposer.class b/src/main/resources/org/python/core/PySet$set___isub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..331b5efed8843552e92b5795cd92adc65629e9f5
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___isub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___iter___exposer.class b/src/main/resources/org/python/core/PySet$set___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fe1f443202beeae40b461f946e43aeecf73df4f
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___ixor___exposer.class b/src/main/resources/org/python/core/PySet$set___ixor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c8ac3fc5ffac711e4727a1feb01f3da8cf75c5b
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___ixor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___le___exposer.class b/src/main/resources/org/python/core/PySet$set___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb9ce63e9f67347460673d0bfefe09551e3daeba
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___len___exposer.class b/src/main/resources/org/python/core/PySet$set___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d14c1285538e1615e55e5aed0e00aef6dc7eb7a5
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___lt___exposer.class b/src/main/resources/org/python/core/PySet$set___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..495f1ede44a704bff62b6a645bb47c3397257203
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___ne___exposer.class b/src/main/resources/org/python/core/PySet$set___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..61ff286e7a575554ecc1e4cb6a3bf5af32f0a43c
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___or___exposer.class b/src/main/resources/org/python/core/PySet$set___or___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..77e7f638e794ef5980d1ce028ae714b0882c51e2
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___or___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___reduce___exposer.class b/src/main/resources/org/python/core/PySet$set___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4ed95e766a852d2a500f7db4590cdb0c6e94296
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___sub___exposer.class b/src/main/resources/org/python/core/PySet$set___sub___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf7dae5d5036378764e24c8a9663e4e7eb7d37dc
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___sub___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set___xor___exposer.class b/src/main/resources/org/python/core/PySet$set___xor___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cb20c9cc25e6f63bbf895a0cd2d962528fd6964
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set___xor___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_add_exposer.class b/src/main/resources/org/python/core/PySet$set_add_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..12df5faa16a2d9f6da17d045e6baab4725bdc7ce
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_add_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_clear_exposer.class b/src/main/resources/org/python/core/PySet$set_clear_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b8ef33e131846b5ba5973f75d09ac92cdcd3e4a
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_clear_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_copy_exposer.class b/src/main/resources/org/python/core/PySet$set_copy_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..949d202d350047b61db66adab8d043fdb64773d0
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_copy_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_difference_exposer.class b/src/main/resources/org/python/core/PySet$set_difference_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9290bd7e4102e0f01327bd5ec43f0a988fcc7b4
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_difference_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_difference_update_exposer.class b/src/main/resources/org/python/core/PySet$set_difference_update_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc6afb9027f0455b50824df204880e4e973fc3cd
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_difference_update_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_discard_exposer.class b/src/main/resources/org/python/core/PySet$set_discard_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f26d664b755bd9e49428ebedd959372f6cdd9b8b
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_discard_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_intersection_exposer.class b/src/main/resources/org/python/core/PySet$set_intersection_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f951d414fdc536b161367d5cdcbc86795a67b699
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_intersection_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_intersection_update_exposer.class b/src/main/resources/org/python/core/PySet$set_intersection_update_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae7e43424f79488abd11e832b1bf03e3b83ca90f
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_intersection_update_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_isdisjoint_exposer.class b/src/main/resources/org/python/core/PySet$set_isdisjoint_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..605b2e9b4684248a011d335b17c5ff151acefde8
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_isdisjoint_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_issubset_exposer.class b/src/main/resources/org/python/core/PySet$set_issubset_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f564ff2c31161c41407f6eb30d1766bff114ca5
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_issubset_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_issuperset_exposer.class b/src/main/resources/org/python/core/PySet$set_issuperset_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0115cfe14cc3900c8ea31ac0214d318962f8cfe3
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_issuperset_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_pop_exposer.class b/src/main/resources/org/python/core/PySet$set_pop_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d664fb26459c33256b4cf0a3c6da16ec5d16939
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_pop_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_remove_exposer.class b/src/main/resources/org/python/core/PySet$set_remove_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe71d6ee3742d294ac5e2d50e5ed880ca4427e0b
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_remove_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_symmetric_difference_exposer.class b/src/main/resources/org/python/core/PySet$set_symmetric_difference_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..61f91d17ee88c88d6ea80da15e022cbf349c33ef
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_symmetric_difference_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_symmetric_difference_update_exposer.class b/src/main/resources/org/python/core/PySet$set_symmetric_difference_update_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c902b9bf7c3eb4ed3c9ad48eafac1a7c266014b
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_symmetric_difference_update_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_toString_exposer.class b/src/main/resources/org/python/core/PySet$set_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3d1b745d9359b7fd11ccce2642270ab4a425493
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_union_exposer.class b/src/main/resources/org/python/core/PySet$set_union_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..19ad82a571063bb5531c92c72f21958d147718fd
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_union_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet$set_update_exposer.class b/src/main/resources/org/python/core/PySet$set_update_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a26cce57f361edc5c9561e4ef96ba62df5e68527
Binary files /dev/null and b/src/main/resources/org/python/core/PySet$set_update_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySet.class b/src/main/resources/org/python/core/PySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..525501f743f085ffa396e5696901b51991b61038
Binary files /dev/null and b/src/main/resources/org/python/core/PySet.class differ
diff --git a/src/main/resources/org/python/core/PySetDerived.class b/src/main/resources/org/python/core/PySetDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..27fd4ceb893a2d1312813608b6c620bf970a3995
Binary files /dev/null and b/src/main/resources/org/python/core/PySetDerived.class differ
diff --git a/src/main/resources/org/python/core/PySingleton.class b/src/main/resources/org/python/core/PySingleton.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0307d10a9afb1c30bc271b75e68bc746493c316
Binary files /dev/null and b/src/main/resources/org/python/core/PySingleton.class differ
diff --git a/src/main/resources/org/python/core/PySlice$PyExposer.class b/src/main/resources/org/python/core/PySlice$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfd94b20388e9220ffd7b75ab33124e36964dfb8
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PySlice$exposed___new__.class b/src/main/resources/org/python/core/PySlice$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fc2090ec217031b7a628513d120ab300c1f3eef
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PySlice$slice___hash___exposer.class b/src/main/resources/org/python/core/PySlice$slice___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cff59ff6775b2034980613f42f64fb1f37c46f00
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice$slice___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySlice$slice_indices_exposer.class b/src/main/resources/org/python/core/PySlice$slice_indices_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5fb3e440c5503b6329e8b35fe31e5f29cdcbbe48
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice$slice_indices_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySlice$slice_toString_exposer.class b/src/main/resources/org/python/core/PySlice$slice_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab8e5948d06c1eeb7f0c97003cbcd1356bceebdd
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice$slice_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PySlice$start_descriptor.class b/src/main/resources/org/python/core/PySlice$start_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..74a29d75f027ad15efda1910960e12a75b1e2183
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice$start_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PySlice$step_descriptor.class b/src/main/resources/org/python/core/PySlice$step_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ba8430d17ca993d733d5e8306329924548e8f26
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice$step_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PySlice$stop_descriptor.class b/src/main/resources/org/python/core/PySlice$stop_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c429deffe519c33e5f229b01045d1740e3e17917
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice$stop_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PySlice.class b/src/main/resources/org/python/core/PySlice.class
new file mode 100644
index 0000000000000000000000000000000000000000..542d06bf1802a7f8c059e4e8d4f091d74c51b942
Binary files /dev/null and b/src/main/resources/org/python/core/PySlice.class differ
diff --git a/src/main/resources/org/python/core/PySlot$PyExposer.class b/src/main/resources/org/python/core/PySlot$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa6f6ae406fa29f3dec5e5b4f9b05058220f71c5
Binary files /dev/null and b/src/main/resources/org/python/core/PySlot$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PySlot$__name___descriptor.class b/src/main/resources/org/python/core/PySlot$__name___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..761b0394ac8f37c98abbdf93235857820de5ce39
Binary files /dev/null and b/src/main/resources/org/python/core/PySlot$__name___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PySlot$__objclass___descriptor.class b/src/main/resources/org/python/core/PySlot$__objclass___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb1a93fa2ccf57e1bf74b4514b841fb4613e7db1
Binary files /dev/null and b/src/main/resources/org/python/core/PySlot$__objclass___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PySlot$member_descriptor___delete___exposer.class b/src/main/resources/org/python/core/PySlot$member_descriptor___delete___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b309778bab1e5609beedc44b038cccc0cb1c259d
Binary files /dev/null and b/src/main/resources/org/python/core/PySlot$member_descriptor___delete___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySlot$member_descriptor___get___exposer.class b/src/main/resources/org/python/core/PySlot$member_descriptor___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c586a635f70a9b82ba84d34f39cefe1d569e8d0
Binary files /dev/null and b/src/main/resources/org/python/core/PySlot$member_descriptor___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySlot$member_descriptor___set___exposer.class b/src/main/resources/org/python/core/PySlot$member_descriptor___set___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..99fbad30fb87ed4034dc9359a38e6dc433f99fea
Binary files /dev/null and b/src/main/resources/org/python/core/PySlot$member_descriptor___set___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySlot.class b/src/main/resources/org/python/core/PySlot.class
new file mode 100644
index 0000000000000000000000000000000000000000..272db9135116458075f2c81bd5ad3b52e5a38cbf
Binary files /dev/null and b/src/main/resources/org/python/core/PySlot.class differ
diff --git a/src/main/resources/org/python/core/PyStaticMethod$PyExposer.class b/src/main/resources/org/python/core/PyStaticMethod$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bfb9e3091d0aed419c3c4a03c71bdafa603d3d5
Binary files /dev/null and b/src/main/resources/org/python/core/PyStaticMethod$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyStaticMethod$exposed___new__.class b/src/main/resources/org/python/core/PyStaticMethod$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..2226db93b611a67a18150c7e2efa765d00790681
Binary files /dev/null and b/src/main/resources/org/python/core/PyStaticMethod$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyStaticMethod$staticmethod___get___exposer.class b/src/main/resources/org/python/core/PyStaticMethod$staticmethod___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..042c5c6248a965ec52c21c1394dbd5cb01d27485
Binary files /dev/null and b/src/main/resources/org/python/core/PyStaticMethod$staticmethod___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStaticMethod.class b/src/main/resources/org/python/core/PyStaticMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..97a91a615e5ec960a258e227a3414d6a2d39cd1f
Binary files /dev/null and b/src/main/resources/org/python/core/PyStaticMethod.class differ
diff --git a/src/main/resources/org/python/core/PyString$PyExposer.class b/src/main/resources/org/python/core/PyString$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..47101bec74d5faae341dfc9602e5ce3e31e9708e
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$exposed___new__.class b/src/main/resources/org/python/core/PyString$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..6df69fdcbd92f16f2a45b55f7017879f3d97bb13
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___add___exposer.class b/src/main/resources/org/python/core/PyString$str___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..762ba3bd53e52b6e62fb6368ca7a93539a9131b7
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___cmp___exposer.class b/src/main/resources/org/python/core/PyString$str___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8771638fa7f24dab70c5f780db436f1789dfa857
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___contains___exposer.class b/src/main/resources/org/python/core/PyString$str___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..63edb8b3be542b9098f3afa9c74679b62b4edfc2
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___eq___exposer.class b/src/main/resources/org/python/core/PyString$str___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d46680ae8953110943f33143527d93d4aac17efe
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___format___exposer.class b/src/main/resources/org/python/core/PyString$str___format___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a901988f1a39f1c055f438f5fb68b1ebffa0f355
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___format___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___ge___exposer.class b/src/main/resources/org/python/core/PyString$str___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1c74701b41b0e6913f3b385816f75849867879e
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___getitem___exposer.class b/src/main/resources/org/python/core/PyString$str___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..47aafbbe49bb961333364e98c4b02cb77a1373e6
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___getnewargs___exposer.class b/src/main/resources/org/python/core/PyString$str___getnewargs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d541b09c1368a159c9a3e2f1a02094ab80c7146
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___getnewargs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___getslice___exposer.class b/src/main/resources/org/python/core/PyString$str___getslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..149677cdb79df80ffe6f96fbe7c7aa09e8c407a6
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___getslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___gt___exposer.class b/src/main/resources/org/python/core/PyString$str___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d935cd93d3198eae5fb5cdf1809388d3852c5773
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___hash___exposer.class b/src/main/resources/org/python/core/PyString$str___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..247bcb2c8c9b89741f85f5450732f75bd4b607bd
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___le___exposer.class b/src/main/resources/org/python/core/PyString$str___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2867e7ebda3fed4e474bfb7a4b0da8cfcc9a82be
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___len___exposer.class b/src/main/resources/org/python/core/PyString$str___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ad5a2ecbd36236068d0ffd3646bf52c5120e037
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___lt___exposer.class b/src/main/resources/org/python/core/PyString$str___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..457ad35c1c68b9988e1ec45e9f270e06d822d887
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___mod___exposer.class b/src/main/resources/org/python/core/PyString$str___mod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e466261199944038a2479eb421855782629fdb5f
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___mod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___mul___exposer.class b/src/main/resources/org/python/core/PyString$str___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..db0e1bf4b40e77055d50c57bd079dba835755370
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___ne___exposer.class b/src/main/resources/org/python/core/PyString$str___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c633eb586cbeb29c175aa15a1111f3cc999f40c5
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___repr___exposer.class b/src/main/resources/org/python/core/PyString$str___repr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff63d24f99f1ba14d49c103203b581605e6fdd24
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___repr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___rmul___exposer.class b/src/main/resources/org/python/core/PyString$str___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0098326026748a091ed6f68a52799eedaf1fc921
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str___str___exposer.class b/src/main/resources/org/python/core/PyString$str___str___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d2d0e3a4db5ef60d111952fbf1715c93dc6ced6
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str___str___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str__formatter_field_name_split_exposer.class b/src/main/resources/org/python/core/PyString$str__formatter_field_name_split_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7251e325636febcccc4aed75f7369bbda8777a45
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str__formatter_field_name_split_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str__formatter_parser_exposer.class b/src/main/resources/org/python/core/PyString$str__formatter_parser_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4b2aea10b3ba98e0a42d4d9152302f50ca3e965
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str__formatter_parser_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_capitalize_exposer.class b/src/main/resources/org/python/core/PyString$str_capitalize_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9da2a8a4c600e0b1bd36b113a1ae0bed22f3847d
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_capitalize_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_center_exposer.class b/src/main/resources/org/python/core/PyString$str_center_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0de97d3c9a5b77549bb2b9a9eba8759e8a34892
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_center_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_count_exposer.class b/src/main/resources/org/python/core/PyString$str_count_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ffa5baf10f123e357af9452eb98f9817b53c896
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_count_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_decode_exposer.class b/src/main/resources/org/python/core/PyString$str_decode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..92a40e1a918377771b0f227f0f9e36e0b8742015
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_decode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_encode_exposer.class b/src/main/resources/org/python/core/PyString$str_encode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..082bdabb9bf2cc076992fdb3ae18600effa3a17f
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_encode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_endswith_exposer.class b/src/main/resources/org/python/core/PyString$str_endswith_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee007f234cd476591a92a06b50fd3d54ca85058e
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_endswith_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_expandtabs_exposer.class b/src/main/resources/org/python/core/PyString$str_expandtabs_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..23547d22ff6e79e311f5e7797d65c009b651625b
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_expandtabs_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_find_exposer.class b/src/main/resources/org/python/core/PyString$str_find_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5abc61bfd26cee01d4dca3c74db5cab030c43ea8
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_find_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_format_exposer.class b/src/main/resources/org/python/core/PyString$str_format_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..133364534f7cef7192457f546b400f6a1ef98cdc
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_format_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_index_exposer.class b/src/main/resources/org/python/core/PyString$str_index_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..20d42548ff443796d1338501bd9a54c9ca03d613
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_index_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_isalnum_exposer.class b/src/main/resources/org/python/core/PyString$str_isalnum_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3441f4df99bcece0b479ba3df5911e906f443851
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_isalnum_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_isalpha_exposer.class b/src/main/resources/org/python/core/PyString$str_isalpha_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..be7983ad443e26e139b8f6863095c98fb982fd30
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_isalpha_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_isdecimal_exposer.class b/src/main/resources/org/python/core/PyString$str_isdecimal_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..20123f79e0f57c6aeb1ea7959686e0fba5b64a42
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_isdecimal_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_isdigit_exposer.class b/src/main/resources/org/python/core/PyString$str_isdigit_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a2fc8918297def137bc2be11f3da271b44a7a59
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_isdigit_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_islower_exposer.class b/src/main/resources/org/python/core/PyString$str_islower_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d58af08e35ad2226a0b636622a24fbaf7fc6cd26
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_islower_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_isnumeric_exposer.class b/src/main/resources/org/python/core/PyString$str_isnumeric_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..12bc2b071b916df07a67c7ee2185b3bf74ba551d
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_isnumeric_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_isspace_exposer.class b/src/main/resources/org/python/core/PyString$str_isspace_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9fd6d58833bd3511cee7eafac256ae96e8cc119
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_isspace_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_istitle_exposer.class b/src/main/resources/org/python/core/PyString$str_istitle_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d13a027b1a980c5c1a552873a51cb4cc55ac047
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_istitle_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_isunicode_exposer.class b/src/main/resources/org/python/core/PyString$str_isunicode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd8c62fa77e188f4745de853d5d014a081305353
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_isunicode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_isupper_exposer.class b/src/main/resources/org/python/core/PyString$str_isupper_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..538b9dce5f5797290d395ced0aaaf4fda70f59f7
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_isupper_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_join_exposer.class b/src/main/resources/org/python/core/PyString$str_join_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a5d6e252340972352813337d191bcc2f98ea463
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_join_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_ljust_exposer.class b/src/main/resources/org/python/core/PyString$str_ljust_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd536fbd8b4ead2f58ea1251843b02ec4e248739
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_ljust_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_lower_exposer.class b/src/main/resources/org/python/core/PyString$str_lower_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b7c03a3e681ac6f68fbe53e0a418993ed6f83f1
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_lower_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_lstrip_exposer.class b/src/main/resources/org/python/core/PyString$str_lstrip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0f4e43196d4072313ebea39a0a8fc1757e762d1
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_lstrip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_partition_exposer.class b/src/main/resources/org/python/core/PyString$str_partition_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..74ffc80ad02324de50ef64b2cf74c69b67964f36
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_partition_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_replace_exposer.class b/src/main/resources/org/python/core/PyString$str_replace_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3844522d81f9fbfafe312385a207abc40cd07482
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_replace_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_rfind_exposer.class b/src/main/resources/org/python/core/PyString$str_rfind_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5453742ed3a79ccaf282dfb28f3df94e34242e1f
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_rfind_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_rindex_exposer.class b/src/main/resources/org/python/core/PyString$str_rindex_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff6375d79809b60671d5a826da8d3af96c942ba6
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_rindex_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_rjust_exposer.class b/src/main/resources/org/python/core/PyString$str_rjust_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c516aa5d0f110ccab40c47713432e1ba1f2a235
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_rjust_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_rpartition_exposer.class b/src/main/resources/org/python/core/PyString$str_rpartition_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ed3c52effed3d925f671cce4e0905eb342f6e51
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_rpartition_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_rsplit_exposer.class b/src/main/resources/org/python/core/PyString$str_rsplit_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9710bd4291bc4a25e711bb0c4e05f1183ebeda32
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_rsplit_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_rstrip_exposer.class b/src/main/resources/org/python/core/PyString$str_rstrip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..25de465b31126f7de1a585de854a7a96471b91a5
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_rstrip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_split_exposer.class b/src/main/resources/org/python/core/PyString$str_split_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..35c7fe618bd3473d8526c1867b4e990295d5aae3
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_split_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_splitlines_exposer.class b/src/main/resources/org/python/core/PyString$str_splitlines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6294218e486f3378fff3051b5467c4311ad3029f
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_splitlines_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_startswith_exposer.class b/src/main/resources/org/python/core/PyString$str_startswith_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..73e44790083caea2c16f62df705f59c8893edb52
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_startswith_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_strip_exposer.class b/src/main/resources/org/python/core/PyString$str_strip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9b11f3087634f5f2119a99006e38c2a1a2940bf
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_strip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_swapcase_exposer.class b/src/main/resources/org/python/core/PyString$str_swapcase_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3449cf027dc0724ec613ff33facdf0fd26bc456
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_swapcase_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_title_exposer.class b/src/main/resources/org/python/core/PyString$str_title_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..807be4291893fae5d67efaf2a9fc92b936a081d0
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_title_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_translate_exposer.class b/src/main/resources/org/python/core/PyString$str_translate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c722dbcbc3c97e94eab36c75d9b53bdd22ff05df
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_translate_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_upper_exposer.class b/src/main/resources/org/python/core/PyString$str_upper_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7231d444cdb36eb63f28d81d4ee13a0bfa66b86a
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_upper_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString$str_zfill_exposer.class b/src/main/resources/org/python/core/PyString$str_zfill_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5038b04e759c8ee48c016573ba5e7ac9e4fa1ce5
Binary files /dev/null and b/src/main/resources/org/python/core/PyString$str_zfill_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyString.class b/src/main/resources/org/python/core/PyString.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7a4e7371c193102b22548541414ee05853c4a58
Binary files /dev/null and b/src/main/resources/org/python/core/PyString.class differ
diff --git a/src/main/resources/org/python/core/PyStringDerived.class b/src/main/resources/org/python/core/PyStringDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c10ad563d3afe574830050042505cf7c63f95ea
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringDerived.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$ItemsIter.class b/src/main/resources/org/python/core/PyStringMap$ItemsIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..e4249e4257b01067458e48d414cd7edb2ceeb2f7
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$ItemsIter.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$KeysIter.class b/src/main/resources/org/python/core/PyStringMap$KeysIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..4162d7b29b9f2e0e9896a2306333df797cc2443e
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$KeysIter.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$PyExposer.class b/src/main/resources/org/python/core/PyStringMap$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f676842c709ebcd6edec6fb84102260a28b2bb74
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$StringMapIter.class b/src/main/resources/org/python/core/PyStringMap$StringMapIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..02be6d003cf20bc2f0367cd10a4ed530296ed24e
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$StringMapIter.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$ValuesIter.class b/src/main/resources/org/python/core/PyStringMap$ValuesIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8f45704a6721b1303b138815579b9254c49d597
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$ValuesIter.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$exposed___new__.class b/src/main/resources/org/python/core/PyStringMap$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..725e1b7e99431b5aac5bbbcb123d4e37f4e6d337
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap___cmp___exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..27685abbb03c01a5c4c3115239dfeb7d3904065a
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap___contains___exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b21ededd11953c94b4cbad541049a0d0554bcd28
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap___delitem___exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap___delitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..948639a96bde8c9b8ec9327f94e73a127bf7bb61
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap___delitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap___getitem___exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff577f2b50da6e51d45a3ada5581c8182a541618
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap___hash___exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fd0f41b9cb4b26386765f35e54fb5f445171605
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap___iter___exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..239a64c97a55558132b68f6bb730010a6ae9b500
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap___len___exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f58a9a975d566756a838563e237ef20e5bb2fa88
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap___setitem___exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap___setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..45231e681d51e6510e0a9c54f2dc5e3a88a88a93
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap___setitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_clear_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_clear_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea04cf4c91644478ba5c342194562c869c5f0ee1
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_clear_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_copy_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_copy_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..15ba761d8fc45e120222097de7d71bf8dc6ba3b4
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_copy_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_get_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_get_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..be02ea3473d52e928c3241ed69732c7e935b76ce
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_get_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_has_key_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_has_key_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ee81802fe5214baf871d8e03da7ecc22ccc1c7a
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_has_key_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_items_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_items_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e88b794d324645545f3b49f3707ab595ae9d668a
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_items_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_iteritems_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_iteritems_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..987904f4a2003e1560154a8fc025c676e941f455
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_iteritems_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_iterkeys_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_iterkeys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..98ab7265352093240787318f2ba23f8530861bad
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_iterkeys_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_itervalues_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_itervalues_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..97715b8ba8c66c2a0929e8cbe7dcb48b507041e3
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_itervalues_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_keys_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_keys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..25b4801b40655d038e2c12d79301ffdea9f28915
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_keys_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_pop_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_pop_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a559066d0608eb26f856081a973cca12971b9d3f
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_pop_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_popitem_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_popitem_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..48df05e5a7f6e928536104484385e93d5e953de2
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_popitem_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_setdefault_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_setdefault_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5db15700e26e7462bcea68d6e39887c921d88c58
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_setdefault_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_toString_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2955b23c49128f6e68b9cdf2f865225fd7b9c11a
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_update_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_update_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e967ffc35bef6d6fb9e3506720482004e10d8790
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_update_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap$stringmap_values_exposer.class b/src/main/resources/org/python/core/PyStringMap$stringmap_values_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9f3eeb0c187bb8682b5965df93a9836e5dfcaf5
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap$stringmap_values_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyStringMap.class b/src/main/resources/org/python/core/PyStringMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9557908a733f3f35d2f6f13a8526c17c9119d31
Binary files /dev/null and b/src/main/resources/org/python/core/PyStringMap.class differ
diff --git a/src/main/resources/org/python/core/PySuper$PyExposer.class b/src/main/resources/org/python/core/PySuper$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4addf72f10bd03bc9d43851d6ca36c989085a003
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PySuper$__self___descriptor.class b/src/main/resources/org/python/core/PySuper$__self___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1afa149bce119d26390b776d592fc23452dd1742
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper$__self___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PySuper$__self_class___descriptor.class b/src/main/resources/org/python/core/PySuper$__self_class___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0cdac85b1cd2db5a2e85d9b24c383f05ca5e13f
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper$__self_class___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PySuper$__thisclass___descriptor.class b/src/main/resources/org/python/core/PySuper$__thisclass___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dca562271ba84a7fe68bb8d146debf93d946f29
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper$__thisclass___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PySuper$exposed___new__.class b/src/main/resources/org/python/core/PySuper$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4eaaf5d95baff33c416648c9fcf66927e9e94d02
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PySuper$super___get___exposer.class b/src/main/resources/org/python/core/PySuper$super___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..35c8361071a616d2b7f60026a87463393eb55491
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper$super___get___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySuper$super___getattribute___exposer.class b/src/main/resources/org/python/core/PySuper$super___getattribute___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..78b187369d84b91069ca2709865502f7aa42eb45
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper$super___getattribute___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySuper$super___init___exposer.class b/src/main/resources/org/python/core/PySuper$super___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fdfd2ea90bbd23c392faaa60453096079e5ad2a
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper$super___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PySuper.class b/src/main/resources/org/python/core/PySuper.class
new file mode 100644
index 0000000000000000000000000000000000000000..72802f0d9fcdbc535e2c27dbdbbe519aa7e53ca8
Binary files /dev/null and b/src/main/resources/org/python/core/PySuper.class differ
diff --git a/src/main/resources/org/python/core/PySuperDerived.class b/src/main/resources/org/python/core/PySuperDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..eeda402c9034c41214fed35f4284b337a7553b82
Binary files /dev/null and b/src/main/resources/org/python/core/PySuperDerived.class differ
diff --git a/src/main/resources/org/python/core/PySyntaxError.class b/src/main/resources/org/python/core/PySyntaxError.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b653e039669d52ed233cb50dbf2807c18a30de5
Binary files /dev/null and b/src/main/resources/org/python/core/PySyntaxError.class differ
diff --git a/src/main/resources/org/python/core/PySystemState$1.class b/src/main/resources/org/python/core/PySystemState$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..75cbfcfc69265b3e014401cd98e6163100ec28d9
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemState$1.class differ
diff --git a/src/main/resources/org/python/core/PySystemState$DefaultBuiltinsHolder.class b/src/main/resources/org/python/core/PySystemState$DefaultBuiltinsHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff84bc9ace42fa4c76affbb2b6f24b7bf532dcfc
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemState$DefaultBuiltinsHolder.class differ
diff --git a/src/main/resources/org/python/core/PySystemState$PySystemStateCloser$ShutdownCloser.class b/src/main/resources/org/python/core/PySystemState$PySystemStateCloser$ShutdownCloser.class
new file mode 100644
index 0000000000000000000000000000000000000000..eadebf46fea43486b9cfa87141f0baac3641aac7
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemState$PySystemStateCloser$ShutdownCloser.class differ
diff --git a/src/main/resources/org/python/core/PySystemState$PySystemStateCloser.class b/src/main/resources/org/python/core/PySystemState$PySystemStateCloser.class
new file mode 100644
index 0000000000000000000000000000000000000000..ffba5fba18245574c1141128fd1a2158548d5d80
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemState$PySystemStateCloser.class differ
diff --git a/src/main/resources/org/python/core/PySystemState.class b/src/main/resources/org/python/core/PySystemState.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a03bd46942da805ca65b7b3d1ee41fbf0d80977
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemState.class differ
diff --git a/src/main/resources/org/python/core/PySystemStateFunctions.class b/src/main/resources/org/python/core/PySystemStateFunctions.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f8816b9261e2fc7841831b7e0789de6fb2d4a89
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemStateFunctions.class differ
diff --git a/src/main/resources/org/python/core/PySystemStateTest$TestJBossURLStreamHandler.class b/src/main/resources/org/python/core/PySystemStateTest$TestJBossURLStreamHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a8a50858ee2af3c5f9ab78475a35140f190a3ee
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemStateTest$TestJBossURLStreamHandler.class differ
diff --git a/src/main/resources/org/python/core/PySystemStateTest.class b/src/main/resources/org/python/core/PySystemStateTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9279382ed803c409945da3989b28c77126d2989
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemStateTest.class differ
diff --git a/src/main/resources/org/python/core/PySystemState_registry_Test.class b/src/main/resources/org/python/core/PySystemState_registry_Test.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea5b27b7062d1167e43b0d57c44c3698645da082
Binary files /dev/null and b/src/main/resources/org/python/core/PySystemState_registry_Test.class differ
diff --git a/src/main/resources/org/python/core/PyTableCode.class b/src/main/resources/org/python/core/PyTableCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c8872751976e37da124efffc149d3a948f57cba
Binary files /dev/null and b/src/main/resources/org/python/core/PyTableCode.class differ
diff --git a/src/main/resources/org/python/core/PyToJavaMapEntry.class b/src/main/resources/org/python/core/PyToJavaMapEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..b846ea06586eff76b181fb34114ba20e880bad44
Binary files /dev/null and b/src/main/resources/org/python/core/PyToJavaMapEntry.class differ
diff --git a/src/main/resources/org/python/core/PyTraceback$PyExposer.class b/src/main/resources/org/python/core/PyTraceback$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6ceae02903c5add3c11605619a926bdbd70a220
Binary files /dev/null and b/src/main/resources/org/python/core/PyTraceback$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyTraceback$tb_frame_descriptor.class b/src/main/resources/org/python/core/PyTraceback$tb_frame_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..11c3a02b2f19791bb0af00af834f9a04a39ce59e
Binary files /dev/null and b/src/main/resources/org/python/core/PyTraceback$tb_frame_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyTraceback$tb_lineno_descriptor.class b/src/main/resources/org/python/core/PyTraceback$tb_lineno_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c738a0716883c226d930583eb3653e2c85ae839
Binary files /dev/null and b/src/main/resources/org/python/core/PyTraceback$tb_lineno_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyTraceback$tb_next_descriptor.class b/src/main/resources/org/python/core/PyTraceback$tb_next_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..51d7b8e91b479ae75e5b9b846e2d9735f8309a42
Binary files /dev/null and b/src/main/resources/org/python/core/PyTraceback$tb_next_descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyTraceback.class b/src/main/resources/org/python/core/PyTraceback.class
new file mode 100644
index 0000000000000000000000000000000000000000..90c9972129e3e0f8994759baaedc99c7d59c8ae8
Binary files /dev/null and b/src/main/resources/org/python/core/PyTraceback.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$1.class b/src/main/resources/org/python/core/PyTuple$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dec959e2542752bcea5879ff249947086e1458f
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$1.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$2.class b/src/main/resources/org/python/core/PyTuple$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..f431586a2751c83386cdd8ce9ef56947cba0ee88
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$2.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$PyExposer.class b/src/main/resources/org/python/core/PyTuple$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..778f8ccf8d2068639496422b3c8934278bede4e2
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$exposed___new__.class b/src/main/resources/org/python/core/PyTuple$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e6af6e57e4aa67b1813768c6903e554c6228b11
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___add___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..88d8a0e6d74fe280c866f9f66396f62b9e976860
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___contains___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4f757efe0cbc58d5ab42a5cd1d4689cc8a14b2f
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___eq___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b835493e80d6141c042a53f7e20d6e58e248b47c
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___ge___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..696b3c6d26524799baa52403c7d8827640a02711
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___getitem___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d9e45c629d21eafa90eb93f0b2a4a72763fde56
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___getnewargs___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___getnewargs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6498dfeeda31073a10826f623658c66c9c99b0f2
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___getnewargs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___getslice___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___getslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..86ec78b530b2af9117733b63c6b6f4c9a4b7192f
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___getslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___gt___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e94009161fc02e8224a763411fe234330d06a7c
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___hash___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..495c64068918aa72b47e4fddc5813926c4ce3a2c
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___iter___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..07b5ac6dc71603d21c63ff76420066efa53d70a9
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___le___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a39bc958b8314b2da26b6e62a11c4327b949d966
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___len___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c503c594350f4f93c2d78ec00e4eff47b4cb8301
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___lt___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d05363623dafd003191a1face98c02034d903474
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___mul___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..395293667e81b0937656eec22bf9cd5dcf25883e
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___ne___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb5b75312ad804935b18630be689f6981e125320
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___repr___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___repr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3862da868e523da5fdb97ca4de920cc6e2bcc3e
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___repr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple___rmul___exposer.class b/src/main/resources/org/python/core/PyTuple$tuple___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8398c3003bdc7c9a24f123391e4387717f2dc17
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple_count_exposer.class b/src/main/resources/org/python/core/PyTuple$tuple_count_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d23dc0cdc133c8c7d27e6724a347a5324a8f3bc4
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple_count_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple$tuple_index_exposer.class b/src/main/resources/org/python/core/PyTuple$tuple_index_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..938a093755bf79c7b920a9589b83951fa2eef2a8
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple$tuple_index_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyTuple.class b/src/main/resources/org/python/core/PyTuple.class
new file mode 100644
index 0000000000000000000000000000000000000000..05b6d320884c282709e60fd76ccd8af60acd2ef7
Binary files /dev/null and b/src/main/resources/org/python/core/PyTuple.class differ
diff --git a/src/main/resources/org/python/core/PyTupleDerived.class b/src/main/resources/org/python/core/PyTupleDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d1d3599e06efbff78672d861d84def0db8b547a
Binary files /dev/null and b/src/main/resources/org/python/core/PyTupleDerived.class differ
diff --git a/src/main/resources/org/python/core/PyTupleTest.class b/src/main/resources/org/python/core/PyTupleTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..1100316fde5aeee1cc549b70951b14f77da22395
Binary files /dev/null and b/src/main/resources/org/python/core/PyTupleTest.class differ
diff --git a/src/main/resources/org/python/core/PyType$1.class b/src/main/resources/org/python/core/PyType$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d05fe1810a84a0b3abe95a8b57227cf3d6a9e5d6
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$1.class differ
diff --git a/src/main/resources/org/python/core/PyType$10.class b/src/main/resources/org/python/core/PyType$10.class
new file mode 100644
index 0000000000000000000000000000000000000000..641f1d2aa553e500980fbecec9ee0512ea7e0b47
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$10.class differ
diff --git a/src/main/resources/org/python/core/PyType$11.class b/src/main/resources/org/python/core/PyType$11.class
new file mode 100644
index 0000000000000000000000000000000000000000..31bf07f41d9a5a13935c8b2c458c1d912073414b
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$11.class differ
diff --git a/src/main/resources/org/python/core/PyType$12.class b/src/main/resources/org/python/core/PyType$12.class
new file mode 100644
index 0000000000000000000000000000000000000000..de70ec6984ece388291cbbb165cb4873d8b07c01
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$12.class differ
diff --git a/src/main/resources/org/python/core/PyType$2.class b/src/main/resources/org/python/core/PyType$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9be2453aee2f3e04a159afe6d3cd2dc2eb4eb22
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$2.class differ
diff --git a/src/main/resources/org/python/core/PyType$3.class b/src/main/resources/org/python/core/PyType$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d72c0b321a0bdb93eeb35ff9a301dbf3571b447
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$3.class differ
diff --git a/src/main/resources/org/python/core/PyType$4.class b/src/main/resources/org/python/core/PyType$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4300aaa68cc2e6dca0296f9b66e049c9fbe4604
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$4.class differ
diff --git a/src/main/resources/org/python/core/PyType$5.class b/src/main/resources/org/python/core/PyType$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4001fd587e7e521895e1ced3d3156c1a56d5de7
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$5.class differ
diff --git a/src/main/resources/org/python/core/PyType$6.class b/src/main/resources/org/python/core/PyType$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6c81b8f7ed75afc1b45b51cbdb4694ed7a9f5e8
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$6.class differ
diff --git a/src/main/resources/org/python/core/PyType$7.class b/src/main/resources/org/python/core/PyType$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3217361f7d4cb259274d8941481c4d6d7e3a1f0
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$7.class differ
diff --git a/src/main/resources/org/python/core/PyType$8.class b/src/main/resources/org/python/core/PyType$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee94b8febbc5f341512338376af36a9c457763b6
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$8.class differ
diff --git a/src/main/resources/org/python/core/PyType$9.class b/src/main/resources/org/python/core/PyType$9.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b0882bb60cfe0cf73e48f7fa39fc5bdebfc9662
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$9.class differ
diff --git a/src/main/resources/org/python/core/PyType$MROMergeState.class b/src/main/resources/org/python/core/PyType$MROMergeState.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5e7ca605670832f10dea1b64af78312b7e1d05c
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$MROMergeState.class differ
diff --git a/src/main/resources/org/python/core/PyType$MethodCache$MethodCacheEntry.class b/src/main/resources/org/python/core/PyType$MethodCache$MethodCacheEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..e55af0817386fc767658c5546cf6d8f9cf7b8c1c
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$MethodCache$MethodCacheEntry.class differ
diff --git a/src/main/resources/org/python/core/PyType$MethodCache.class b/src/main/resources/org/python/core/PyType$MethodCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..13c39a720ed40e280e7bb57a9a8deef6a7fa7eaa
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$MethodCache.class differ
diff --git a/src/main/resources/org/python/core/PyType$OnType.class b/src/main/resources/org/python/core/PyType$OnType.class
new file mode 100644
index 0000000000000000000000000000000000000000..486dc89036d55a2cd4e43cf73a7cd6640e3588d3
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$OnType.class differ
diff --git a/src/main/resources/org/python/core/PyType$PyExposer.class b/src/main/resources/org/python/core/PyType$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..612f635daf6fc33ae637ecdd719610fdda2a0b97
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$TypeResolver.class b/src/main/resources/org/python/core/PyType$TypeResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..a081fdd5d2187da4652598401c131b80164dfa07
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$TypeResolver.class differ
diff --git a/src/main/resources/org/python/core/PyType$__abstractmethods___descriptor.class b/src/main/resources/org/python/core/PyType$__abstractmethods___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f7640e39e8aa2fd55e0f9e4724361b3623c55af
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__abstractmethods___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$__base___descriptor.class b/src/main/resources/org/python/core/PyType$__base___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd1b1d383b57455a64033ed207afec79eb04718a
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__base___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$__bases___descriptor.class b/src/main/resources/org/python/core/PyType$__bases___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c05477fc5efb2f8a8f2cc3c43684aeab6c4f3323
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__bases___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$__dict___descriptor.class b/src/main/resources/org/python/core/PyType$__dict___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..debcd25ddab6e4696f8738b12e8cd751f3ac46d7
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__dict___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$__doc___descriptor.class b/src/main/resources/org/python/core/PyType$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6ea8c443d99e2c696f24e96b13a441fb27c1ab9
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$__flags___descriptor.class b/src/main/resources/org/python/core/PyType$__flags___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa53ec20c305104c6be94578062991c57bb529db
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__flags___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$__module___descriptor.class b/src/main/resources/org/python/core/PyType$__module___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ebfbddfd1e5ea7145a15f36bf7874a824ad4326d
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__module___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$__mro___descriptor.class b/src/main/resources/org/python/core/PyType$__mro___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c378ecc6eb6be76882a2bc48199092908886c07
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__mro___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$__name___descriptor.class b/src/main/resources/org/python/core/PyType$__name___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b61b6242d231d874cadf803544786030cd32e514
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$__name___descriptor.class differ
diff --git a/src/main/resources/org/python/core/PyType$exposed___new__.class b/src/main/resources/org/python/core/PyType$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9532f9282c0196eef8b83b9238c3e6ff33f5b27
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___call___exposer.class b/src/main/resources/org/python/core/PyType$type___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f15ce40fe5a68dae0f686916b0e4e56dbf6217d
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___call___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___delattr___exposer.class b/src/main/resources/org/python/core/PyType$type___delattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..60433596faaeff543e85b8d6dc4311e52521af6a
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___delattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___eq___exposer.class b/src/main/resources/org/python/core/PyType$type___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ba18b27f412f8afaaf4c0a1588820a5a57d5042
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___ge___exposer.class b/src/main/resources/org/python/core/PyType$type___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ee1081ce1da4ab60a11da8b893872191759d7ff
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___ge___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___getattribute___exposer.class b/src/main/resources/org/python/core/PyType$type___getattribute___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecf2797cbfc93dd1fc38d7425b758df5e83c17a3
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___getattribute___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___gt___exposer.class b/src/main/resources/org/python/core/PyType$type___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e13ea4ea4e5029051d0dd9674f87a444a15ef2b8
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___gt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___init___exposer.class b/src/main/resources/org/python/core/PyType$type___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e53ccba3a79716d8a5f17523952920df734d02d
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___init___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___le___exposer.class b/src/main/resources/org/python/core/PyType$type___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..720134e71b9314e9e6ca8f0a9f74fff48d3dc7f8
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___le___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___lt___exposer.class b/src/main/resources/org/python/core/PyType$type___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..367135ea947fca5982efc80fb8854032c8b73994
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___lt___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___ne___exposer.class b/src/main/resources/org/python/core/PyType$type___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..35452a31e248680c139c444117fc9117b03e7ecc
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___setattr___exposer.class b/src/main/resources/org/python/core/PyType$type___setattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9a97c1f8da383fbc2f7cea23e09833cfbfe3237
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___setattr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type___subclasses___exposer.class b/src/main/resources/org/python/core/PyType$type___subclasses___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..95888650f685068b9825e7ee949155d230621815
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type___subclasses___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type_mro_exposer.class b/src/main/resources/org/python/core/PyType$type_mro_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..553c693ffaa234f733cc6df721e4e7e086ef1d22
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type_mro_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType$type_toString_exposer.class b/src/main/resources/org/python/core/PyType$type_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..02b72c90cfd11984bc2130d8258ac120cdf743fe
Binary files /dev/null and b/src/main/resources/org/python/core/PyType$type_toString_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyType.class b/src/main/resources/org/python/core/PyType.class
new file mode 100644
index 0000000000000000000000000000000000000000..5010ce7d1959b9958da8d38440935706c02dc5e0
Binary files /dev/null and b/src/main/resources/org/python/core/PyType.class differ
diff --git a/src/main/resources/org/python/core/PyTypeDerived.class b/src/main/resources/org/python/core/PyTypeDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c2379756f29c6870296b7b89c47b9702a19026c
Binary files /dev/null and b/src/main/resources/org/python/core/PyTypeDerived.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$LineSplitIterator.class b/src/main/resources/org/python/core/PyUnicode$LineSplitIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..92830f77cd15c4ffae700abc68c5983e43ffc474
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$LineSplitIterator.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$PeekIterator.class b/src/main/resources/org/python/core/PyUnicode$PeekIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..02be21c7191401e1855f1ab8797eb749c1b4f712
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$PeekIterator.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$Plane.class b/src/main/resources/org/python/core/PyUnicode$Plane.class
new file mode 100644
index 0000000000000000000000000000000000000000..2232d5871736c8da16b541fb8ac244471ead2d55
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$Plane.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$PyExposer.class b/src/main/resources/org/python/core/PyUnicode$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d702f22d7c2a56afd5e585a231f373be02f9721
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$ReversedIterator.class b/src/main/resources/org/python/core/PyUnicode$ReversedIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea92249a60cb2e6e858381c05dce0886bbcdb9ef
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$ReversedIterator.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$SepSplitIterator.class b/src/main/resources/org/python/core/PyUnicode$SepSplitIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..05b14bed680827a237016404a6beb3ed88af0ff4
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$SepSplitIterator.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$SplitIterator.class b/src/main/resources/org/python/core/PyUnicode$SplitIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec5c04a46405463cb8687b9a14da59ab05c2d121
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$SplitIterator.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$SteppedIterator.class b/src/main/resources/org/python/core/PyUnicode$SteppedIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..500ede0f6684a16e6e0725bf0ce4a729ccace457
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$SteppedIterator.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$StripIterator.class b/src/main/resources/org/python/core/PyUnicode$StripIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..e04f282445856edf503ab6fbc95defd42e3fa817
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$StripIterator.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$SubsequenceIteratorImpl.class b/src/main/resources/org/python/core/PyUnicode$SubsequenceIteratorImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..c96ce99adf05a350e71295590b01c44abaf35ad0
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$SubsequenceIteratorImpl.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$WhitespaceSplitIterator.class b/src/main/resources/org/python/core/PyUnicode$WhitespaceSplitIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..3248483f89fde58aea7b70dd017df5a843551ae9
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$WhitespaceSplitIterator.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$exposed___new__.class b/src/main/resources/org/python/core/PyUnicode$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3e978b639f88e59ab4508ce3b528d4a1d5e3975
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___add___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___add___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f92e86fac3bcb9e6d390e84c874e163153e91cd7
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___add___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___cmp___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___cmp___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e96475dbdedaa19e71d40f06b9c2b981b74721e4
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___cmp___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___contains___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b8a252609a81b16715dfe339c8ba19dece39cf0
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___contains___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___eq___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a7b6bb7ddd20ef0c1863e6e6571df00edb4a779
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___eq___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___getitem___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..99c15084b98dc370582f6b0de5ddcdbb6a82e3b4
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___getnewargs___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___getnewargs___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a70b7b47457496f720955bf0758716bb5fafd180
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___getnewargs___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___getslice___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___getslice___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc0fcdba6a3092329a5687f1d2ffcf12c542aa3e
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___getslice___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___hash___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___hash___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fef6b3efb4bfb1555a41f9d42c9d21b3ffa21cc8
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___hash___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___len___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dc3bd5465751447c9be170d156be49fd428e706
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___mod___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___mod___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b04bc455ebd49f7194df2263b7f82d831818b0b9
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___mod___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___mul___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___mul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bd5aed156179b9eaed45996e945400e91039eeb
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___mul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___ne___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..049e3875e5b9d7f61dcddacc28881ffaac10b569
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___ne___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___repr___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___repr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb4753797bb5382d8ca6acf4720de808d3538cf5
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___repr___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___rmul___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___rmul___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8846702ebf51c7c5bc66cc9c134c57aa06b6c0f3
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___rmul___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode___str___exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode___str___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..14d29b38bf4587e32be634540212520c74704776
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode___str___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_capitalize_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_capitalize_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..78e34be0b940571f23a349977eb0554482bc66d1
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_capitalize_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_center_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_center_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..384b64388a879af59e02edfe24a73b487cdedffc
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_center_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_count_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_count_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4164165ea0a9dee54f03a74c23a80c5cbc09feed
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_count_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_decode_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_decode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b92c8748f4ad5f38f82bbafe3ccb6dc24d6b17b0
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_decode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_encode_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_encode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..23bccb563df0fd258c7b69c1db110f8780b3613b
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_encode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_endswith_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_endswith_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf0c04e68f3c8c8ef130a43e03ca815b79c625
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_endswith_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_expandtabs_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_expandtabs_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1933792af1fc43948b2011fc4149ed98767af368
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_expandtabs_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_find_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_find_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ad55b89edbccdb2f5c6975ff95ebb7c7241244d
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_find_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_format_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_format_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..839abe41328cb07bcefe834f2748837239069574
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_format_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_index_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_index_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf2727cea5fd32f4d8c28dd026ba43719a54447e
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_index_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_isalnum_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_isalnum_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..97e4343ea92ac7ba24d85950a86ae043706f9a05
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_isalnum_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_isalpha_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_isalpha_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6994fda705f1de101dc82d51372d83fbcec44067
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_isalpha_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_isdecimal_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_isdecimal_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5fa5309ce36afbbc10307f2196cdd484774d86f4
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_isdecimal_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_isdigit_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_isdigit_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e90399d21b7bc33a3ed2680ecd494ff757e626aa
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_isdigit_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_islower_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_islower_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..071ed9aa31bdb5f53fd45ca323f13ec90423597c
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_islower_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_isnumeric_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_isnumeric_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a9e7d777eb26e40888e90beb8dd506678cb5d7c
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_isnumeric_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_isspace_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_isspace_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..40a279570567d8d57968638890a80bd3657d4787
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_isspace_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_istitle_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_istitle_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..657f2e47fcfb5540f291eb26567732bb166aa964
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_istitle_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_isunicode_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_isunicode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..51f7eb5e22c1572495e6d4893d30e9bda59ee98a
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_isunicode_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_isupper_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_isupper_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0436993fa98382cd3a9a832d4927a9c9da73ee7
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_isupper_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_join_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_join_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e89abe6896278fd8114d6d4e400d19c49d9ce62
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_join_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_ljust_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_ljust_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..43bc095c1b22139cb612caf954011607da719e18
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_ljust_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_lower_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_lower_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cd8fa5caac4a5d21847a72784098253841a4439
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_lower_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_lstrip_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_lstrip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..41a3a24b430162b91dc27159ce034c141a8d8abd
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_lstrip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_partition_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_partition_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..faa918be7e3214be94b0933373b9341a9de61403
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_partition_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_replace_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_replace_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b06d980fc322995788b8c20c03b04c887b7647ac
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_replace_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_rfind_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_rfind_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d44705b5b57fb345c068424d20520a8b742c669f
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_rfind_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_rindex_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_rindex_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1afb0a073f8ff89186cff92656d2a9bda39c01a
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_rindex_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_rjust_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_rjust_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..46b51cf2fe97f5713ed3b27f107ca22a9f1aad45
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_rjust_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_rpartition_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_rpartition_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e16573818867b7c9c661ebee57565aa6d4abb87
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_rpartition_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_rsplit_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_rsplit_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2831284ec13f98e25d4308e10290c896744cfe2f
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_rsplit_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_rstrip_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_rstrip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d595e15dce3d3862160da5cf6c50ba2e206492a
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_rstrip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_split_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_split_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8da26b3d5a783bae86580e190e85c51877e87b6c
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_split_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_splitlines_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_splitlines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1160a32787e6da79ddae1631dc6cc474e49db7ff
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_splitlines_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_startswith_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_startswith_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3713e42a91502a33f863549f8827d78d15887cda
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_startswith_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_strip_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_strip_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e143eac1a6af54f788783e5202507a4eb537f926
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_strip_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_swapcase_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_swapcase_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3baea95eeb6172c076133620a5b0158c2a2b581b
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_swapcase_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_title_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_title_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8c581e4d32ec1e89b1df5280ae2813b576ca970
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_title_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_translate_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_translate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..64c975645735f953de213ed6757d97a093c404b2
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_translate_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_upper_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_upper_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..210956d78c4ad6152ee1b9e7141a83bff5aa42fc
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_upper_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode$unicode_zfill_exposer.class b/src/main/resources/org/python/core/PyUnicode$unicode_zfill_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1c6a504647eb7f56d1e226f8b6031c1cfac7765
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode$unicode_zfill_exposer.class differ
diff --git a/src/main/resources/org/python/core/PyUnicode.class b/src/main/resources/org/python/core/PyUnicode.class
new file mode 100644
index 0000000000000000000000000000000000000000..6999c7a954abf3ac01bf06197356f9121ddb46ea
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicode.class differ
diff --git a/src/main/resources/org/python/core/PyUnicodeDerived.class b/src/main/resources/org/python/core/PyUnicodeDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..459b2a15194a4682c1e5dae403d26135b5246c56
Binary files /dev/null and b/src/main/resources/org/python/core/PyUnicodeDerived.class differ
diff --git a/src/main/resources/org/python/core/PyXRange$PyExposer.class b/src/main/resources/org/python/core/PyXRange$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1220b819c9d2f2b456c577685292e56907c804de
Binary files /dev/null and b/src/main/resources/org/python/core/PyXRange$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/PyXRange$exposed___new__.class b/src/main/resources/org/python/core/PyXRange$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..40e6428c3cd04912404d8c8afb1b2d251d43f57f
Binary files /dev/null and b/src/main/resources/org/python/core/PyXRange$exposed___new__.class differ
diff --git a/src/main/resources/org/python/core/PyXRange$xrange___getitem___exposer.class b/src/main/resources/org/python/core/PyXRange$xrange___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c90768769b5fe1f36527df9f097035d077d953bf
Binary files /dev/null and b/src/main/resources/org/python/core/PyXRange$xrange___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyXRange$xrange___iter___exposer.class b/src/main/resources/org/python/core/PyXRange$xrange___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..12fdd43fe1e50696087973200cffd8478d9d4424
Binary files /dev/null and b/src/main/resources/org/python/core/PyXRange$xrange___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyXRange$xrange___len___exposer.class b/src/main/resources/org/python/core/PyXRange$xrange___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..532842f78a1bdb489e85610aeee03cfa31eaed95
Binary files /dev/null and b/src/main/resources/org/python/core/PyXRange$xrange___len___exposer.class differ
diff --git a/src/main/resources/org/python/core/PyXRange.class b/src/main/resources/org/python/core/PyXRange.class
new file mode 100644
index 0000000000000000000000000000000000000000..c33b245865411f6f074644584a10d23f2666090f
Binary files /dev/null and b/src/main/resources/org/python/core/PyXRange.class differ
diff --git a/src/main/resources/org/python/core/PythonCodeBundle.class b/src/main/resources/org/python/core/PythonCodeBundle.class
new file mode 100644
index 0000000000000000000000000000000000000000..c165a3841a5c17a6f33ce3a05f438ed35371124c
Binary files /dev/null and b/src/main/resources/org/python/core/PythonCodeBundle.class differ
diff --git a/src/main/resources/org/python/core/PythonCompiler.class b/src/main/resources/org/python/core/PythonCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e8df3863fed262b608cf3fab17ef6d92260952d
Binary files /dev/null and b/src/main/resources/org/python/core/PythonCompiler.class differ
diff --git a/src/main/resources/org/python/core/PythonTraceFunction.class b/src/main/resources/org/python/core/PythonTraceFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..a78b2e88e6ccff7289ec64c1cfe6bd9e5cf13edc
Binary files /dev/null and b/src/main/resources/org/python/core/PythonTraceFunction.class differ
diff --git a/src/main/resources/org/python/core/ReflectedArgs.class b/src/main/resources/org/python/core/ReflectedArgs.class
new file mode 100644
index 0000000000000000000000000000000000000000..66402aaad3f41070309ecfde43e558a926af5872
Binary files /dev/null and b/src/main/resources/org/python/core/ReflectedArgs.class differ
diff --git a/src/main/resources/org/python/core/ReflectedCallData.class b/src/main/resources/org/python/core/ReflectedCallData.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba7846f20bd7eb13781698689f75ab140a55e8f1
Binary files /dev/null and b/src/main/resources/org/python/core/ReflectedCallData.class differ
diff --git a/src/main/resources/org/python/core/RoundFunction.class b/src/main/resources/org/python/core/RoundFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a0887f70e1fc33acc57b08b482af119584d8241
Binary files /dev/null and b/src/main/resources/org/python/core/RoundFunction.class differ
diff --git a/src/main/resources/org/python/core/SequenceIndexDelegate.class b/src/main/resources/org/python/core/SequenceIndexDelegate.class
new file mode 100644
index 0000000000000000000000000000000000000000..3998d6f34fd17308e1a43b06a31d9773dd86b062
Binary files /dev/null and b/src/main/resources/org/python/core/SequenceIndexDelegate.class differ
diff --git a/src/main/resources/org/python/core/Shadow.class b/src/main/resources/org/python/core/Shadow.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e72258986cdad3d55ef7005e97b67098e10d9d3
Binary files /dev/null and b/src/main/resources/org/python/core/Shadow.class differ
diff --git a/src/main/resources/org/python/core/SimpleEntry.class b/src/main/resources/org/python/core/SimpleEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa9b73102f1f8a10c179f5f7c0af96b6137caa6c
Binary files /dev/null and b/src/main/resources/org/python/core/SimpleEntry.class differ
diff --git a/src/main/resources/org/python/core/Slotted.class b/src/main/resources/org/python/core/Slotted.class
new file mode 100644
index 0000000000000000000000000000000000000000..8970659e279c3963fd806fa745096511401e90df
Binary files /dev/null and b/src/main/resources/org/python/core/Slotted.class differ
diff --git a/src/main/resources/org/python/core/SortedFunction.class b/src/main/resources/org/python/core/SortedFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..33b82f994f0a9fd0ca19ae200f8ea163433d005b
Binary files /dev/null and b/src/main/resources/org/python/core/SortedFunction.class differ
diff --git a/src/main/resources/org/python/core/StderrWrapper.class b/src/main/resources/org/python/core/StderrWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a5dcfc9354e533691c83388ee3d784c152399b1
Binary files /dev/null and b/src/main/resources/org/python/core/StderrWrapper.class differ
diff --git a/src/main/resources/org/python/core/StdoutWrapper.class b/src/main/resources/org/python/core/StdoutWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..59a238c09a0807e481a45086e816bbae82362da2
Binary files /dev/null and b/src/main/resources/org/python/core/StdoutWrapper.class differ
diff --git a/src/main/resources/org/python/core/StringFormatTest.class b/src/main/resources/org/python/core/StringFormatTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..182d75466b99686678e30e3ae6542693fd5be6a4
Binary files /dev/null and b/src/main/resources/org/python/core/StringFormatTest.class differ
diff --git a/src/main/resources/org/python/core/StringFormatter$DecimalFormatTemplate.class b/src/main/resources/org/python/core/StringFormatter$DecimalFormatTemplate.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b0a698ac569a58708c4a8984bbd959c484f460e
Binary files /dev/null and b/src/main/resources/org/python/core/StringFormatter$DecimalFormatTemplate.class differ
diff --git a/src/main/resources/org/python/core/StringFormatter.class b/src/main/resources/org/python/core/StringFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..24554ce4a08a6fe2c4272f3700ddcdd655fb1f73
Binary files /dev/null and b/src/main/resources/org/python/core/StringFormatter.class differ
diff --git a/src/main/resources/org/python/core/StringSubsequenceIterator.class b/src/main/resources/org/python/core/StringSubsequenceIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..20fc1b4b713b87fb4ea8d4539e25c79d37f98082
Binary files /dev/null and b/src/main/resources/org/python/core/StringSubsequenceIterator.class differ
diff --git a/src/main/resources/org/python/core/SyspathArchive.class b/src/main/resources/org/python/core/SyspathArchive.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6d72fdaac82bccb6ba3a8f9aa12436d51c3885b
Binary files /dev/null and b/src/main/resources/org/python/core/SyspathArchive.class differ
diff --git a/src/main/resources/org/python/core/SyspathJavaLoader.class b/src/main/resources/org/python/core/SyspathJavaLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd8fd5c7eae2059da26ece6832f80a60ff4606a8
Binary files /dev/null and b/src/main/resources/org/python/core/SyspathJavaLoader.class differ
diff --git a/src/main/resources/org/python/core/ThreadContext.class b/src/main/resources/org/python/core/ThreadContext.class
new file mode 100644
index 0000000000000000000000000000000000000000..0163212198bd39d9f7bd8cc8f6c9c9fdbe907c05
Binary files /dev/null and b/src/main/resources/org/python/core/ThreadContext.class differ
diff --git a/src/main/resources/org/python/core/ThreadState.class b/src/main/resources/org/python/core/ThreadState.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d78aee59b4d87e40148c59916a442da0402de08
Binary files /dev/null and b/src/main/resources/org/python/core/ThreadState.class differ
diff --git a/src/main/resources/org/python/core/ThreadStateMapping.class b/src/main/resources/org/python/core/ThreadStateMapping.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4656fc69b5ab151a1b0b78968ca47147de3c73d
Binary files /dev/null and b/src/main/resources/org/python/core/ThreadStateMapping.class differ
diff --git a/src/main/resources/org/python/core/ThreadStateMapping.class-bak.class b/src/main/resources/org/python/core/ThreadStateMapping.class-bak.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2f9fbddd2f51e393dd3ba32d8144ed50271be76
Binary files /dev/null and b/src/main/resources/org/python/core/ThreadStateMapping.class-bak.class differ
diff --git a/src/main/resources/org/python/core/TraceFunction.class b/src/main/resources/org/python/core/TraceFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..6851a9b38dd7fe119d9851943efe596363531912
Binary files /dev/null and b/src/main/resources/org/python/core/TraceFunction.class differ
diff --git a/src/main/resources/org/python/core/WrappedBooleanTest$WrappedBoolean.class b/src/main/resources/org/python/core/WrappedBooleanTest$WrappedBoolean.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb430a44589eaa2e3613717edbb56a41c42cf9fa
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedBooleanTest$WrappedBoolean.class differ
diff --git a/src/main/resources/org/python/core/WrappedBooleanTest.class b/src/main/resources/org/python/core/WrappedBooleanTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd6cfc9b0727cdde6949318634c5dbca1fc3f792
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedBooleanTest.class differ
diff --git a/src/main/resources/org/python/core/WrappedFloatTest$WrappedFloat.class b/src/main/resources/org/python/core/WrappedFloatTest$WrappedFloat.class
new file mode 100644
index 0000000000000000000000000000000000000000..caa7d43597427d0b89caf4be325a180620086ac2
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedFloatTest$WrappedFloat.class differ
diff --git a/src/main/resources/org/python/core/WrappedFloatTest.class b/src/main/resources/org/python/core/WrappedFloatTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..487290a3f0cb02ed487b6d386a920fd496bd6f59
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedFloatTest.class differ
diff --git a/src/main/resources/org/python/core/WrappedIntegerTest$WrappedInteger.class b/src/main/resources/org/python/core/WrappedIntegerTest$WrappedInteger.class
new file mode 100644
index 0000000000000000000000000000000000000000..d493bb04f2f0947fb6422d310a2e4d9cb1c04db3
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedIntegerTest$WrappedInteger.class differ
diff --git a/src/main/resources/org/python/core/WrappedIntegerTest.class b/src/main/resources/org/python/core/WrappedIntegerTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..49a25e9fe13791313b79bdbd12b11fddad8043af
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedIntegerTest.class differ
diff --git a/src/main/resources/org/python/core/WrappedIterIterator.class b/src/main/resources/org/python/core/WrappedIterIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..f39ec224d05fb57bcf581217127fd00bc48b7e43
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedIterIterator.class differ
diff --git a/src/main/resources/org/python/core/WrappedLongTest$WrappedLong.class b/src/main/resources/org/python/core/WrappedLongTest$WrappedLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d01696a99c2c1310f5ceb9fc0b434c9b0d9a9df
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedLongTest$WrappedLong.class differ
diff --git a/src/main/resources/org/python/core/WrappedLongTest.class b/src/main/resources/org/python/core/WrappedLongTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef6aa0bfb75f0911e98d2e9f782d8c1dba7fcc6d
Binary files /dev/null and b/src/main/resources/org/python/core/WrappedLongTest.class differ
diff --git a/src/main/resources/org/python/core/__builtin__.class b/src/main/resources/org/python/core/__builtin__.class
new file mode 100644
index 0000000000000000000000000000000000000000..fce130c685edbf9d87c1dba739654d126886d26b
Binary files /dev/null and b/src/main/resources/org/python/core/__builtin__.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassAdapter.class b/src/main/resources/org/python/core/adapter/ClassAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..449b1e9544d03df7ab56a47fcdb2598722328895
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassAdapter.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$1.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..464e802a7fde3879b79e87ff00085bf608361a8f
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$1.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$2.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc1e53376aa96629cebfed1398427d34bfc48678
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$2.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$3.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..def05e6987fc0ddc35f6a74c249a73a9d4e82fd2
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$3.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$4.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ca84a8d0ccd52c10f902fb739c1f558da0bbc5b
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$4.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$5.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce99ad1a8acd957c6237227d0dc5913a9ed6c3d0
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$5.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$6.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..948a7669240f4d5467a9449980e3109edf5561a8
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$6.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$7.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a2b019b28481e34234638960efde021eb7c9a87
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$7.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$8.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cca7d97703d4de4b0b6395196921b0e7dd9fdbb
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$8.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$9.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$9.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad2eaed4efe7d23ad96fe388f6fb0adbbc9c41f8
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$9.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$NumberToPyFloat.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$NumberToPyFloat.class
new file mode 100644
index 0000000000000000000000000000000000000000..6215ea02d882563b43c58cfef9066d9dcf2379c1
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$NumberToPyFloat.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$NumberToPyInteger.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$NumberToPyInteger.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc71a99b2cc89a2e67f8d17440a513d515625966
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter$NumberToPyInteger.class differ
diff --git a/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter.class b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c561e4051c9c783c27be34a0d0bdd79b8971d945
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ClassicPyObjectAdapter.class differ
diff --git a/src/main/resources/org/python/core/adapter/ExtensiblePyObjectAdapter.class b/src/main/resources/org/python/core/adapter/ExtensiblePyObjectAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf83707578f276143810c24083145ebc8f82f5eb
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/ExtensiblePyObjectAdapter.class differ
diff --git a/src/main/resources/org/python/core/adapter/PyObjectAdapter.class b/src/main/resources/org/python/core/adapter/PyObjectAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9796cd70e51988152d63f44988f2b78a354b0bd
Binary files /dev/null and b/src/main/resources/org/python/core/adapter/PyObjectAdapter.class differ
diff --git a/src/main/resources/org/python/core/buffer/BaseBuffer.class b/src/main/resources/org/python/core/buffer/BaseBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac1130ee4e63709da32430c0961582ca276f028b
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/BaseBuffer.class differ
diff --git a/src/main/resources/org/python/core/buffer/SimpleBuffer$SimpleView.class b/src/main/resources/org/python/core/buffer/SimpleBuffer$SimpleView.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ca53788d1ed4e988aedf6044a726e08e182043b
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/SimpleBuffer$SimpleView.class differ
diff --git a/src/main/resources/org/python/core/buffer/SimpleBuffer.class b/src/main/resources/org/python/core/buffer/SimpleBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4df6d993531faa7511af2a39ff72f0b3986c8ce9
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/SimpleBuffer.class differ
diff --git a/src/main/resources/org/python/core/buffer/SimpleStringBuffer$SimpleStringView.class b/src/main/resources/org/python/core/buffer/SimpleStringBuffer$SimpleStringView.class
new file mode 100644
index 0000000000000000000000000000000000000000..3eb04a8edc28ce7ffc99513a9eab0fa977016974
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/SimpleStringBuffer$SimpleStringView.class differ
diff --git a/src/main/resources/org/python/core/buffer/SimpleStringBuffer.class b/src/main/resources/org/python/core/buffer/SimpleStringBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fdc3cb157a8f492be6756a097e07c338b3bf46b7
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/SimpleStringBuffer.class differ
diff --git a/src/main/resources/org/python/core/buffer/SimpleWritableBuffer$SimpleView.class b/src/main/resources/org/python/core/buffer/SimpleWritableBuffer$SimpleView.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e865e37b0baf44ed4b1a6577aa832d4f496ca85
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/SimpleWritableBuffer$SimpleView.class differ
diff --git a/src/main/resources/org/python/core/buffer/SimpleWritableBuffer.class b/src/main/resources/org/python/core/buffer/SimpleWritableBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6afad8056725a1f2dc2cb92a9038194ea3b9dcd
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/SimpleWritableBuffer.class differ
diff --git a/src/main/resources/org/python/core/buffer/Strided1DBuffer$SlicedView.class b/src/main/resources/org/python/core/buffer/Strided1DBuffer$SlicedView.class
new file mode 100644
index 0000000000000000000000000000000000000000..df1cc9dc767e9d2c7bf1aaa684ca78d7090dd7b1
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/Strided1DBuffer$SlicedView.class differ
diff --git a/src/main/resources/org/python/core/buffer/Strided1DBuffer.class b/src/main/resources/org/python/core/buffer/Strided1DBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5867e8c0fb605675ec8b9d35647ff64bad5972f5
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/Strided1DBuffer.class differ
diff --git a/src/main/resources/org/python/core/buffer/Strided1DWritableBuffer$SlicedView.class b/src/main/resources/org/python/core/buffer/Strided1DWritableBuffer$SlicedView.class
new file mode 100644
index 0000000000000000000000000000000000000000..498d9405f3cb8a52a974b6e494d063e772cf53b8
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/Strided1DWritableBuffer$SlicedView.class differ
diff --git a/src/main/resources/org/python/core/buffer/Strided1DWritableBuffer.class b/src/main/resources/org/python/core/buffer/Strided1DWritableBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9813dbcb7b3fea3caffb69e0bf36cc501cfcc63
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/Strided1DWritableBuffer.class differ
diff --git a/src/main/resources/org/python/core/buffer/ZeroByteBuffer$View.class b/src/main/resources/org/python/core/buffer/ZeroByteBuffer$View.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4f9829fb28c02790839d6198a3a6589c87bfb86
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/ZeroByteBuffer$View.class differ
diff --git a/src/main/resources/org/python/core/buffer/ZeroByteBuffer.class b/src/main/resources/org/python/core/buffer/ZeroByteBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c343139389c737bfae602734b8793ad98382eee1
Binary files /dev/null and b/src/main/resources/org/python/core/buffer/ZeroByteBuffer.class differ
diff --git a/src/main/resources/org/python/core/codecs$CodecState.class b/src/main/resources/org/python/core/codecs$CodecState.class
new file mode 100644
index 0000000000000000000000000000000000000000..f887603a84f08262be13680f267d362f8949c21b
Binary files /dev/null and b/src/main/resources/org/python/core/codecs$CodecState.class differ
diff --git a/src/main/resources/org/python/core/codecs$Punycode.class b/src/main/resources/org/python/core/codecs$Punycode.class
new file mode 100644
index 0000000000000000000000000000000000000000..13a595f0e0f46b38d01a06f6989c301b2370eade
Binary files /dev/null and b/src/main/resources/org/python/core/codecs$Punycode.class differ
diff --git a/src/main/resources/org/python/core/codecs$UTF7Error.class b/src/main/resources/org/python/core/codecs$UTF7Error.class
new file mode 100644
index 0000000000000000000000000000000000000000..5bce4b14bdf22ea8a87e8d04d9738cbdb2a97403
Binary files /dev/null and b/src/main/resources/org/python/core/codecs$UTF7Error.class differ
diff --git a/src/main/resources/org/python/core/codecs.class b/src/main/resources/org/python/core/codecs.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc3f39d47fae3738f94142d2a062088d89ae9987
Binary files /dev/null and b/src/main/resources/org/python/core/codecs.class differ
diff --git a/src/main/resources/org/python/core/exceptions$BoundStaticJavaMethod.class b/src/main/resources/org/python/core/exceptions$BoundStaticJavaMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b6d937bb7cb09546f4b5f4f26e52417c1d31fd2
Binary files /dev/null and b/src/main/resources/org/python/core/exceptions$BoundStaticJavaMethod.class differ
diff --git a/src/main/resources/org/python/core/exceptions.class b/src/main/resources/org/python/core/exceptions.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c7f56e206d13783e6d381df0bfc666a7c920a8f
Binary files /dev/null and b/src/main/resources/org/python/core/exceptions.class differ
diff --git a/src/main/resources/org/python/core/imp.class b/src/main/resources/org/python/core/imp.class
new file mode 100644
index 0000000000000000000000000000000000000000..b52bc1459842378e6a868429cb56066f4e52cb63
Binary files /dev/null and b/src/main/resources/org/python/core/imp.class differ
diff --git a/src/main/resources/org/python/core/io/BinaryIOWrapper.class b/src/main/resources/org/python/core/io/BinaryIOWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f3696835392c9bc049c4fc075b7dd1d500d993e
Binary files /dev/null and b/src/main/resources/org/python/core/io/BinaryIOWrapper.class differ
diff --git a/src/main/resources/org/python/core/io/BufferedIOBase.class b/src/main/resources/org/python/core/io/BufferedIOBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..5aeff03bd3b863fcd7883c553d4bb0484f78762f
Binary files /dev/null and b/src/main/resources/org/python/core/io/BufferedIOBase.class differ
diff --git a/src/main/resources/org/python/core/io/BufferedIOMixin.class b/src/main/resources/org/python/core/io/BufferedIOMixin.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ca65b6b9d0581b76e97921eeb71a59560266d4c
Binary files /dev/null and b/src/main/resources/org/python/core/io/BufferedIOMixin.class differ
diff --git a/src/main/resources/org/python/core/io/BufferedRandom.class b/src/main/resources/org/python/core/io/BufferedRandom.class
new file mode 100644
index 0000000000000000000000000000000000000000..def0d6eb8e189bb5ed2d70dc62a0617b02530132
Binary files /dev/null and b/src/main/resources/org/python/core/io/BufferedRandom.class differ
diff --git a/src/main/resources/org/python/core/io/BufferedReader.class b/src/main/resources/org/python/core/io/BufferedReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fb8a37dba18cbe5d6457b2f57058549d8710529
Binary files /dev/null and b/src/main/resources/org/python/core/io/BufferedReader.class differ
diff --git a/src/main/resources/org/python/core/io/BufferedWriter.class b/src/main/resources/org/python/core/io/BufferedWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..111a7f527946ac91ef1cdb84b3fb9b51bcb9df36
Binary files /dev/null and b/src/main/resources/org/python/core/io/BufferedWriter.class differ
diff --git a/src/main/resources/org/python/core/io/DatagramSocketIO.class b/src/main/resources/org/python/core/io/DatagramSocketIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..51fbb5fb8454dddf08d82a9171794075a8f30d0f
Binary files /dev/null and b/src/main/resources/org/python/core/io/DatagramSocketIO.class differ
diff --git a/src/main/resources/org/python/core/io/FileDescriptors.class b/src/main/resources/org/python/core/io/FileDescriptors.class
new file mode 100644
index 0000000000000000000000000000000000000000..636108b4650db095d80d982b2a00a77aff073a02
Binary files /dev/null and b/src/main/resources/org/python/core/io/FileDescriptors.class differ
diff --git a/src/main/resources/org/python/core/io/FileIO.class b/src/main/resources/org/python/core/io/FileIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..d40597f6c3f0e22a69717571833e470a98270389
Binary files /dev/null and b/src/main/resources/org/python/core/io/FileIO.class differ
diff --git a/src/main/resources/org/python/core/io/IOBase.class b/src/main/resources/org/python/core/io/IOBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1860bd30f649ff794c8b180cc417881aa15e4c9
Binary files /dev/null and b/src/main/resources/org/python/core/io/IOBase.class differ
diff --git a/src/main/resources/org/python/core/io/LineBufferedRandom.class b/src/main/resources/org/python/core/io/LineBufferedRandom.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e2b5d36c38e240b19f53ba73e3c15fe1704dc76
Binary files /dev/null and b/src/main/resources/org/python/core/io/LineBufferedRandom.class differ
diff --git a/src/main/resources/org/python/core/io/LineBufferedWriter.class b/src/main/resources/org/python/core/io/LineBufferedWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa72c9583e9dcee6768f6f941ddee842c4b27ac4
Binary files /dev/null and b/src/main/resources/org/python/core/io/LineBufferedWriter.class differ
diff --git a/src/main/resources/org/python/core/io/RawIOBase.class b/src/main/resources/org/python/core/io/RawIOBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..dac845d27a58af0d90b3031292609492b43e14fd
Binary files /dev/null and b/src/main/resources/org/python/core/io/RawIOBase.class differ
diff --git a/src/main/resources/org/python/core/io/ServerSocketIO.class b/src/main/resources/org/python/core/io/ServerSocketIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a029cfed4d1b7a8c8b6c088fa30f7b28ba144c3
Binary files /dev/null and b/src/main/resources/org/python/core/io/ServerSocketIO.class differ
diff --git a/src/main/resources/org/python/core/io/SocketIO.class b/src/main/resources/org/python/core/io/SocketIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f46ccd3eee8addf2dd45c3885993ddffea33cb0
Binary files /dev/null and b/src/main/resources/org/python/core/io/SocketIO.class differ
diff --git a/src/main/resources/org/python/core/io/SocketIOBase.class b/src/main/resources/org/python/core/io/SocketIOBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..400feec83dfebe208e3bc720d6dfc5f2a317010c
Binary files /dev/null and b/src/main/resources/org/python/core/io/SocketIOBase.class differ
diff --git a/src/main/resources/org/python/core/io/StreamIO.class b/src/main/resources/org/python/core/io/StreamIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..567712a1b88c27f47cfe2674ba2b0e86d6236e82
Binary files /dev/null and b/src/main/resources/org/python/core/io/StreamIO.class differ
diff --git a/src/main/resources/org/python/core/io/TextIOBase.class b/src/main/resources/org/python/core/io/TextIOBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c0ae5d040845ea82ad1e3960f1f034eca968fb9
Binary files /dev/null and b/src/main/resources/org/python/core/io/TextIOBase.class differ
diff --git a/src/main/resources/org/python/core/io/TextIOInputStream.class b/src/main/resources/org/python/core/io/TextIOInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..da8348dfb75eb1af7f9456b4458f49862f6d8aa0
Binary files /dev/null and b/src/main/resources/org/python/core/io/TextIOInputStream.class differ
diff --git a/src/main/resources/org/python/core/io/TextIOWrapper.class b/src/main/resources/org/python/core/io/TextIOWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..152c30fec022e0d50b21a81b691343ee097af2b0
Binary files /dev/null and b/src/main/resources/org/python/core/io/TextIOWrapper.class differ
diff --git a/src/main/resources/org/python/core/io/UniversalIOWrapper$Newline.class b/src/main/resources/org/python/core/io/UniversalIOWrapper$Newline.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3ef529c678b0823f68000ccc7428dc733e84e15
Binary files /dev/null and b/src/main/resources/org/python/core/io/UniversalIOWrapper$Newline.class differ
diff --git a/src/main/resources/org/python/core/io/UniversalIOWrapper.class b/src/main/resources/org/python/core/io/UniversalIOWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..257650b62821f904a42b86cd7884d5edb32fee14
Binary files /dev/null and b/src/main/resources/org/python/core/io/UniversalIOWrapper.class differ
diff --git a/src/main/resources/org/python/core/packagecache/CachedJarsOver64kTest$TestCachePackageManager.class b/src/main/resources/org/python/core/packagecache/CachedJarsOver64kTest$TestCachePackageManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..0115b2cc65ab65db57400c70df939be4ecc1ad8b
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/CachedJarsOver64kTest$TestCachePackageManager.class differ
diff --git a/src/main/resources/org/python/core/packagecache/CachedJarsOver64kTest.class b/src/main/resources/org/python/core/packagecache/CachedJarsOver64kTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..7004d10144885ac20568f5612cdc9eb13ffc50f0
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/CachedJarsOver64kTest.class differ
diff --git a/src/main/resources/org/python/core/packagecache/CachedJarsPackageManager$JarXEntry.class b/src/main/resources/org/python/core/packagecache/CachedJarsPackageManager$JarXEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..416a36389e405f7d8cacffedec9b6154c2658b69
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/CachedJarsPackageManager$JarXEntry.class differ
diff --git a/src/main/resources/org/python/core/packagecache/CachedJarsPackageManager.class b/src/main/resources/org/python/core/packagecache/CachedJarsPackageManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..987abe2d3bf9422016fbea624467666b304ebaff
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/CachedJarsPackageManager.class differ
diff --git a/src/main/resources/org/python/core/packagecache/PackageManager.class b/src/main/resources/org/python/core/packagecache/PackageManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c7bfea2f86e32fc69a8c4acc14668e0d465dc52
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/PackageManager.class differ
diff --git a/src/main/resources/org/python/core/packagecache/PathPackageManager$1.class b/src/main/resources/org/python/core/packagecache/PathPackageManager$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c99bb2da19bb2af6efd8ba9805cf50c83737f219
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/PathPackageManager$1.class differ
diff --git a/src/main/resources/org/python/core/packagecache/PathPackageManager$PackageExistsFileFilter.class b/src/main/resources/org/python/core/packagecache/PathPackageManager$PackageExistsFileFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccc4c9b5a3c26103eb23f582253e880f732f7073
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/PathPackageManager$PackageExistsFileFilter.class differ
diff --git a/src/main/resources/org/python/core/packagecache/PathPackageManager.class b/src/main/resources/org/python/core/packagecache/PathPackageManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..66f55db350f929b11fb53808c9e0b4a49574e79d
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/PathPackageManager.class differ
diff --git a/src/main/resources/org/python/core/packagecache/SysPackageManager.class b/src/main/resources/org/python/core/packagecache/SysPackageManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdf9505b2e6e563358a09dd01f62b8cb6fa91f8f
Binary files /dev/null and b/src/main/resources/org/python/core/packagecache/SysPackageManager.class differ
diff --git a/src/main/resources/org/python/core/stringlib/FieldNameIterator$Chunk.class b/src/main/resources/org/python/core/stringlib/FieldNameIterator$Chunk.class
new file mode 100644
index 0000000000000000000000000000000000000000..3049b04bd2c66407208fc4155cd266bef9e6c861
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/FieldNameIterator$Chunk.class differ
diff --git a/src/main/resources/org/python/core/stringlib/FieldNameIterator$PyExposer.class b/src/main/resources/org/python/core/stringlib/FieldNameIterator$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..00b3bbe654e995afa0a65db50be64f75034f1f2d
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/FieldNameIterator$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/stringlib/FieldNameIterator$fieldnameiterator___iter___exposer.class b/src/main/resources/org/python/core/stringlib/FieldNameIterator$fieldnameiterator___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a093534478f86e552a05e076dfaa4f1afd2e6643
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/FieldNameIterator$fieldnameiterator___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/stringlib/FieldNameIterator$fieldnameiterator___iternext___exposer.class b/src/main/resources/org/python/core/stringlib/FieldNameIterator$fieldnameiterator___iternext___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..113e707eaf3d93767179d250e36a8d90d5ebd769
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/FieldNameIterator$fieldnameiterator___iternext___exposer.class differ
diff --git a/src/main/resources/org/python/core/stringlib/FieldNameIterator.class b/src/main/resources/org/python/core/stringlib/FieldNameIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d055a0cc98811bd199189cfa685d9ca5d95fd8a
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/FieldNameIterator.class differ
diff --git a/src/main/resources/org/python/core/stringlib/Formatter.class b/src/main/resources/org/python/core/stringlib/Formatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe871a23234fd4066a4079421610d7c86e2cac51
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/Formatter.class differ
diff --git a/src/main/resources/org/python/core/stringlib/InternalFormatSpec.class b/src/main/resources/org/python/core/stringlib/InternalFormatSpec.class
new file mode 100644
index 0000000000000000000000000000000000000000..22dbec834a17b006d1523c5743001077c9aa9dc4
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/InternalFormatSpec.class differ
diff --git a/src/main/resources/org/python/core/stringlib/InternalFormatSpecParser.class b/src/main/resources/org/python/core/stringlib/InternalFormatSpecParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..36d19bb45fe650da785a8c8c19a4f0c1c07f74c9
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/InternalFormatSpecParser.class differ
diff --git a/src/main/resources/org/python/core/stringlib/InternalFormatter$DecimalFormatTemplate.class b/src/main/resources/org/python/core/stringlib/InternalFormatter$DecimalFormatTemplate.class
new file mode 100644
index 0000000000000000000000000000000000000000..86961cdc44e327c52aa15b5d6e4f9c5255001b07
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/InternalFormatter$DecimalFormatTemplate.class differ
diff --git a/src/main/resources/org/python/core/stringlib/InternalFormatter$PercentageFormatTemplate.class b/src/main/resources/org/python/core/stringlib/InternalFormatter$PercentageFormatTemplate.class
new file mode 100644
index 0000000000000000000000000000000000000000..35197edaccfe7881eaa97f6643bb35763a8314d3
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/InternalFormatter$PercentageFormatTemplate.class differ
diff --git a/src/main/resources/org/python/core/stringlib/InternalFormatter.class b/src/main/resources/org/python/core/stringlib/InternalFormatter.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa81f04ce62d477134ad27dbaa13ef46c20f9c73
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/InternalFormatter.class differ
diff --git a/src/main/resources/org/python/core/stringlib/MarkupIterator$Chunk.class b/src/main/resources/org/python/core/stringlib/MarkupIterator$Chunk.class
new file mode 100644
index 0000000000000000000000000000000000000000..db244075f2c5b78ece5496be9708ce3de15ee1be
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/MarkupIterator$Chunk.class differ
diff --git a/src/main/resources/org/python/core/stringlib/MarkupIterator$FieldNumbering.class b/src/main/resources/org/python/core/stringlib/MarkupIterator$FieldNumbering.class
new file mode 100644
index 0000000000000000000000000000000000000000..0374ef22fe47bd020b850e1e094ed4ad2af0b8c5
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/MarkupIterator$FieldNumbering.class differ
diff --git a/src/main/resources/org/python/core/stringlib/MarkupIterator$PyExposer.class b/src/main/resources/org/python/core/stringlib/MarkupIterator$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb4908059555a748e31c4f4b163272145cbce8bc
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/MarkupIterator$PyExposer.class differ
diff --git a/src/main/resources/org/python/core/stringlib/MarkupIterator$formatteriterator___iter___exposer.class b/src/main/resources/org/python/core/stringlib/MarkupIterator$formatteriterator___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..12f17b254c421d2c27c6719ef659bc24384c1820
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/MarkupIterator$formatteriterator___iter___exposer.class differ
diff --git a/src/main/resources/org/python/core/stringlib/MarkupIterator$formatteriterator___iternext___exposer.class b/src/main/resources/org/python/core/stringlib/MarkupIterator$formatteriterator___iternext___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9731518bdabe888aaef57ef1fd0703318f55404a
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/MarkupIterator$formatteriterator___iternext___exposer.class differ
diff --git a/src/main/resources/org/python/core/stringlib/MarkupIterator.class b/src/main/resources/org/python/core/stringlib/MarkupIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6afed91fa342baf58197d7295b351207fbcfbb5
Binary files /dev/null and b/src/main/resources/org/python/core/stringlib/MarkupIterator.class differ
diff --git a/src/main/resources/org/python/core/ucnhashAPI.class b/src/main/resources/org/python/core/ucnhashAPI.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5d516abe24f058f5f4a3634abdaf165809ffe72
Binary files /dev/null and b/src/main/resources/org/python/core/ucnhashAPI.class differ
diff --git a/src/main/resources/org/python/core/util/ByteSwapper.class b/src/main/resources/org/python/core/util/ByteSwapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..5375e9581e1d4ac4ce161326db02fb3f8f56c713
Binary files /dev/null and b/src/main/resources/org/python/core/util/ByteSwapper.class differ
diff --git a/src/main/resources/org/python/core/util/ExtraMath.class b/src/main/resources/org/python/core/util/ExtraMath.class
new file mode 100644
index 0000000000000000000000000000000000000000..634481b7f3e4fdb9c6816b31d86ac98089450687
Binary files /dev/null and b/src/main/resources/org/python/core/util/ExtraMath.class differ
diff --git a/src/main/resources/org/python/core/util/FileUtil.class b/src/main/resources/org/python/core/util/FileUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..846eb48fd5074051505798b92ea143826d0a1db3
Binary files /dev/null and b/src/main/resources/org/python/core/util/FileUtil.class differ
diff --git a/src/main/resources/org/python/core/util/PlatformUtil.class b/src/main/resources/org/python/core/util/PlatformUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ee141e7e8c30e6c846f0bd47671b2f8770ba2fb
Binary files /dev/null and b/src/main/resources/org/python/core/util/PlatformUtil.class differ
diff --git a/src/main/resources/org/python/core/util/RelativeFile.class b/src/main/resources/org/python/core/util/RelativeFile.class
new file mode 100644
index 0000000000000000000000000000000000000000..33ca17a15f7d4b1c4271ad234ed7340210c7eb48
Binary files /dev/null and b/src/main/resources/org/python/core/util/RelativeFile.class differ
diff --git a/src/main/resources/org/python/core/util/StringUtil.class b/src/main/resources/org/python/core/util/StringUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..064fc5264d28858821ed1456d532aa4136a87ecb
Binary files /dev/null and b/src/main/resources/org/python/core/util/StringUtil.class differ
diff --git a/src/main/resources/org/python/core/util/importer$Bundle.class b/src/main/resources/org/python/core/util/importer$Bundle.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8acae9ae080ea6dd9ff4336a251da98bc691d1a
Binary files /dev/null and b/src/main/resources/org/python/core/util/importer$Bundle.class differ
diff --git a/src/main/resources/org/python/core/util/importer$EntryType.class b/src/main/resources/org/python/core/util/importer$EntryType.class
new file mode 100644
index 0000000000000000000000000000000000000000..11fcd829669d6902449d320b1e85c5b3880be679
Binary files /dev/null and b/src/main/resources/org/python/core/util/importer$EntryType.class differ
diff --git a/src/main/resources/org/python/core/util/importer$ModuleCodeData.class b/src/main/resources/org/python/core/util/importer$ModuleCodeData.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3335f93107c558281be86ba26679cbc7d13c3d5
Binary files /dev/null and b/src/main/resources/org/python/core/util/importer$ModuleCodeData.class differ
diff --git a/src/main/resources/org/python/core/util/importer$ModuleInfo.class b/src/main/resources/org/python/core/util/importer$ModuleInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ad1e36dddc4ad23e0d93a759e10e0ee7e494b64
Binary files /dev/null and b/src/main/resources/org/python/core/util/importer$ModuleInfo.class differ
diff --git a/src/main/resources/org/python/core/util/importer$SearchOrderEntry.class b/src/main/resources/org/python/core/util/importer$SearchOrderEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..78c8c0a6f5614bb7323fc469b0d579622b531884
Binary files /dev/null and b/src/main/resources/org/python/core/util/importer$SearchOrderEntry.class differ
diff --git a/src/main/resources/org/python/core/util/importer.class b/src/main/resources/org/python/core/util/importer.class
new file mode 100644
index 0000000000000000000000000000000000000000..482875bf031b901c74ba1826e084e569126e2439
Binary files /dev/null and b/src/main/resources/org/python/core/util/importer.class differ
diff --git a/src/main/resources/org/python/expose/BaseTypeBuilder.class b/src/main/resources/org/python/expose/BaseTypeBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f1df4f7c705d31cc1ff059308a84f1cc484ad6c
Binary files /dev/null and b/src/main/resources/org/python/expose/BaseTypeBuilder.class differ
diff --git a/src/main/resources/org/python/expose/ExposeAsSuperclass.class b/src/main/resources/org/python/expose/ExposeAsSuperclass.class
new file mode 100644
index 0000000000000000000000000000000000000000..27ec6058abeaca8c0e1923dc5f4360ac06fd1206
Binary files /dev/null and b/src/main/resources/org/python/expose/ExposeAsSuperclass.class differ
diff --git a/src/main/resources/org/python/expose/ExposedClassMethod.class b/src/main/resources/org/python/expose/ExposedClassMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ef1aba298a7184d91bfe4de445ff06e53d72d46
Binary files /dev/null and b/src/main/resources/org/python/expose/ExposedClassMethod.class differ
diff --git a/src/main/resources/org/python/expose/ExposedDelete.class b/src/main/resources/org/python/expose/ExposedDelete.class
new file mode 100644
index 0000000000000000000000000000000000000000..b304910664db0aa7d6bca317a684d5b4763c8be5
Binary files /dev/null and b/src/main/resources/org/python/expose/ExposedDelete.class differ
diff --git a/src/main/resources/org/python/expose/ExposedGet.class b/src/main/resources/org/python/expose/ExposedGet.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ebac9e828e0599042a73fdb3d8416d01651fe1a
Binary files /dev/null and b/src/main/resources/org/python/expose/ExposedGet.class differ
diff --git a/src/main/resources/org/python/expose/ExposedMethod.class b/src/main/resources/org/python/expose/ExposedMethod.class
new file mode 100644
index 0000000000000000000000000000000000000000..19eb885868c34e2a6af0deac9d0cf787830cd875
Binary files /dev/null and b/src/main/resources/org/python/expose/ExposedMethod.class differ
diff --git a/src/main/resources/org/python/expose/ExposedNew.class b/src/main/resources/org/python/expose/ExposedNew.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb51499ef58d6f7bb47480a737ba30c19a12cc64
Binary files /dev/null and b/src/main/resources/org/python/expose/ExposedNew.class differ
diff --git a/src/main/resources/org/python/expose/ExposedSet.class b/src/main/resources/org/python/expose/ExposedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..00355f20f68d331b2977a612fb672925fbd428dd
Binary files /dev/null and b/src/main/resources/org/python/expose/ExposedSet.class differ
diff --git a/src/main/resources/org/python/expose/ExposedType.class b/src/main/resources/org/python/expose/ExposedType.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b64e71ea550d25acbf30f1d2cc5503735849a4a
Binary files /dev/null and b/src/main/resources/org/python/expose/ExposedType.class differ
diff --git a/src/main/resources/org/python/expose/MethodType.class b/src/main/resources/org/python/expose/MethodType.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a7b068f17ccf5e466ac41fa2126254ce8eca8ce
Binary files /dev/null and b/src/main/resources/org/python/expose/MethodType.class differ
diff --git a/src/main/resources/org/python/expose/TypeBuilder.class b/src/main/resources/org/python/expose/TypeBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..c85376144aa09d60e381bb55f0003c62e03a44eb
Binary files /dev/null and b/src/main/resources/org/python/expose/TypeBuilder.class differ
diff --git a/src/main/resources/org/python/google/common/annotations/Beta.class b/src/main/resources/org/python/google/common/annotations/Beta.class
new file mode 100644
index 0000000000000000000000000000000000000000..72047a72c02ea99b086880f43e2d7160413e615d
Binary files /dev/null and b/src/main/resources/org/python/google/common/annotations/Beta.class differ
diff --git a/src/main/resources/org/python/google/common/annotations/GwtCompatible.class b/src/main/resources/org/python/google/common/annotations/GwtCompatible.class
new file mode 100644
index 0000000000000000000000000000000000000000..a02089e539ea01ffc01dd11d2b19755882068869
Binary files /dev/null and b/src/main/resources/org/python/google/common/annotations/GwtCompatible.class differ
diff --git a/src/main/resources/org/python/google/common/annotations/GwtIncompatible.class b/src/main/resources/org/python/google/common/annotations/GwtIncompatible.class
new file mode 100644
index 0000000000000000000000000000000000000000..22307227a90d508e8c114f8595d9ccca12aabdf9
Binary files /dev/null and b/src/main/resources/org/python/google/common/annotations/GwtIncompatible.class differ
diff --git a/src/main/resources/org/python/google/common/annotations/VisibleForTesting.class b/src/main/resources/org/python/google/common/annotations/VisibleForTesting.class
new file mode 100644
index 0000000000000000000000000000000000000000..96365e88f43f59f54ac97b25bc148aad2cca6863
Binary files /dev/null and b/src/main/resources/org/python/google/common/annotations/VisibleForTesting.class differ
diff --git a/src/main/resources/org/python/google/common/base/Absent.class b/src/main/resources/org/python/google/common/base/Absent.class
new file mode 100644
index 0000000000000000000000000000000000000000..70749380eb5d97cd468c7a0927c2c16bc3c0a4b8
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Absent.class differ
diff --git a/src/main/resources/org/python/google/common/base/AbstractIterator$1.class b/src/main/resources/org/python/google/common/base/AbstractIterator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d899b50facec9e29295784fdc1c2712203f56a79
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/AbstractIterator$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/AbstractIterator$State.class b/src/main/resources/org/python/google/common/base/AbstractIterator$State.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b7f921946f2a9211bf036315b4116bea215e984
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/AbstractIterator$State.class differ
diff --git a/src/main/resources/org/python/google/common/base/AbstractIterator.class b/src/main/resources/org/python/google/common/base/AbstractIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6f452c20e6bfb785227925a7e2db3287a779dc8
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/AbstractIterator.class differ
diff --git a/src/main/resources/org/python/google/common/base/Ascii.class b/src/main/resources/org/python/google/common/base/Ascii.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcdb9a793d3bcd0f7cc9fc68c1298698ffea2454
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Ascii.class differ
diff --git a/src/main/resources/org/python/google/common/base/CaseFormat$1.class b/src/main/resources/org/python/google/common/base/CaseFormat$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e713713034f3a3a88945d0a905c3484f3e4e342
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CaseFormat$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/CaseFormat.class b/src/main/resources/org/python/google/common/base/CaseFormat.class
new file mode 100644
index 0000000000000000000000000000000000000000..e737d9c235422f15988ff391995c56896992d679
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CaseFormat.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$1.class b/src/main/resources/org/python/google/common/base/CharMatcher$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a04a85bb3fee19b5600418762cbd78cfafbea1f
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$10.class b/src/main/resources/org/python/google/common/base/CharMatcher$10.class
new file mode 100644
index 0000000000000000000000000000000000000000..442e6e97d6b176881ce75a339e66d245cccb64c7
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$10.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$11.class b/src/main/resources/org/python/google/common/base/CharMatcher$11.class
new file mode 100644
index 0000000000000000000000000000000000000000..b493a55cc2270a471bd2666b7f62a3332dabab69
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$11.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$12.class b/src/main/resources/org/python/google/common/base/CharMatcher$12.class
new file mode 100644
index 0000000000000000000000000000000000000000..71e011d4ca83ff70cbbebbd4bf2dd76d3b30c18a
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$12.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$13.class b/src/main/resources/org/python/google/common/base/CharMatcher$13.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9b0b6db3c6db44ceb4c116b86879b62a9997e4a
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$13.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$14.class b/src/main/resources/org/python/google/common/base/CharMatcher$14.class
new file mode 100644
index 0000000000000000000000000000000000000000..60ed0fc674087c7231ffe1e85ca0e6920b1f682f
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$14.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$15.class b/src/main/resources/org/python/google/common/base/CharMatcher$15.class
new file mode 100644
index 0000000000000000000000000000000000000000..461390b3767f521d46c69ead2bf18a01d76d9c49
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$15.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$16.class b/src/main/resources/org/python/google/common/base/CharMatcher$16.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9b45c92b564bd9f8aec5376f99ec08956dc0d83
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$16.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$2.class b/src/main/resources/org/python/google/common/base/CharMatcher$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..f45be85d32f5c2c6ff3a8145e727bbb9b18e4853
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$2.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$3.class b/src/main/resources/org/python/google/common/base/CharMatcher$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..f7ef18506fec0bad5eae4cc33a642ec3a94948be
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$3.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$4.class b/src/main/resources/org/python/google/common/base/CharMatcher$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..d20c35112126f4c31da35227f2f49768715ac6ba
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$4.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$5.class b/src/main/resources/org/python/google/common/base/CharMatcher$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd016b5ea4d3aa4e6ab440c2d1aacb4f7e971557
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$5.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$6.class b/src/main/resources/org/python/google/common/base/CharMatcher$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..f33d40cd2eaa1803cd45efb28a7f63fa64a4437b
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$6.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$7.class b/src/main/resources/org/python/google/common/base/CharMatcher$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..0683ef436882b4dc57176f3cd8f444d0aacf2a53
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$7.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$8.class b/src/main/resources/org/python/google/common/base/CharMatcher$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..83c68af3e7877684250a865b7192051cb7c183e4
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$8.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$9.class b/src/main/resources/org/python/google/common/base/CharMatcher$9.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec3bde50e10bc47a71a26867236329e1fd4e964b
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$9.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$And.class b/src/main/resources/org/python/google/common/base/CharMatcher$And.class
new file mode 100644
index 0000000000000000000000000000000000000000..197bc8a8ac9ef6cf6483d5985a270dd56d0560bb
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$And.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$LookupTable.class b/src/main/resources/org/python/google/common/base/CharMatcher$LookupTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1d63dd7c1f0f770eaa590af178426b6c669ea05
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$LookupTable.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher$Or.class b/src/main/resources/org/python/google/common/base/CharMatcher$Or.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f439b316f44182b647ab8f7ab9a1c56031cf745
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher$Or.class differ
diff --git a/src/main/resources/org/python/google/common/base/CharMatcher.class b/src/main/resources/org/python/google/common/base/CharMatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..83e7083fecb6ec8a6f4073f3bceb7771a63c37fc
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/CharMatcher.class differ
diff --git a/src/main/resources/org/python/google/common/base/Charsets.class b/src/main/resources/org/python/google/common/base/Charsets.class
new file mode 100644
index 0000000000000000000000000000000000000000..2080efdfaeb0f2836f5d68c9aa498e9e8a214f2c
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Charsets.class differ
diff --git a/src/main/resources/org/python/google/common/base/Defaults.class b/src/main/resources/org/python/google/common/base/Defaults.class
new file mode 100644
index 0000000000000000000000000000000000000000..73f7a48c4f5a3a1287322ca5034e7dbbaa8c3e5a
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Defaults.class differ
diff --git a/src/main/resources/org/python/google/common/base/Enums$1.class b/src/main/resources/org/python/google/common/base/Enums$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e3cbdba29a7f1cc40f2ca0a7daa544a327a13b3
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Enums$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Enums$ValueOfFunction.class b/src/main/resources/org/python/google/common/base/Enums$ValueOfFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..82b2e44ee50ebe33dbfca2325a538fb70a3e01e5
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Enums$ValueOfFunction.class differ
diff --git a/src/main/resources/org/python/google/common/base/Enums.class b/src/main/resources/org/python/google/common/base/Enums.class
new file mode 100644
index 0000000000000000000000000000000000000000..117e3cea86e429abe0e10257f9986c365b674df2
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Enums.class differ
diff --git a/src/main/resources/org/python/google/common/base/Equivalence$1.class b/src/main/resources/org/python/google/common/base/Equivalence$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9441a5d6a8e38aecdb7ebc64699358c612132646
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Equivalence$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Equivalence$Equals.class b/src/main/resources/org/python/google/common/base/Equivalence$Equals.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd01796b2e18bfb25503040519e166d2026bd5a4
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Equivalence$Equals.class differ
diff --git a/src/main/resources/org/python/google/common/base/Equivalence$EquivalentToPredicate.class b/src/main/resources/org/python/google/common/base/Equivalence$EquivalentToPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e3548a46a98d16fa93eb69621ce868d019baa0b
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Equivalence$EquivalentToPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Equivalence$Identity.class b/src/main/resources/org/python/google/common/base/Equivalence$Identity.class
new file mode 100644
index 0000000000000000000000000000000000000000..2fccc0fda38b5475b8c099ff4edb874a0bc24aae
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Equivalence$Identity.class differ
diff --git a/src/main/resources/org/python/google/common/base/Equivalence$Wrapper.class b/src/main/resources/org/python/google/common/base/Equivalence$Wrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..031062f65b5c4f686112e5c73db418b76302b058
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Equivalence$Wrapper.class differ
diff --git a/src/main/resources/org/python/google/common/base/Equivalence.class b/src/main/resources/org/python/google/common/base/Equivalence.class
new file mode 100644
index 0000000000000000000000000000000000000000..7697da83eed7bc9a3faeb0f600449af8d975e00b
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Equivalence.class differ
diff --git a/src/main/resources/org/python/google/common/base/Equivalences.class b/src/main/resources/org/python/google/common/base/Equivalences.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a6ca717e1c7009eeab6b8fbe89feb6591f0fd00
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Equivalences.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizablePhantomReference.class b/src/main/resources/org/python/google/common/base/FinalizablePhantomReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d0769ca8e796924be4409696c7badb4e5782a49
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizablePhantomReference.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizableReference.class b/src/main/resources/org/python/google/common/base/FinalizableReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..c581f32773a002b9b98038a10bfe196d287a491d
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizableReference.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$DecoupledLoader.class b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$DecoupledLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a0221ba6c2beaed399820f32aea6b15b205678b
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$DecoupledLoader.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$DirectLoader.class b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$DirectLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..a88abac5d03a674329268f423f3d884561826300
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$DirectLoader.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$FinalizerLoader.class b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$FinalizerLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..519c48e4282a1026ef1b90d446245628c6879392
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$FinalizerLoader.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$SystemLoader.class b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$SystemLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca4bdce94c2ed98b0a4444e5e3e1e123572f2d8d
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue$SystemLoader.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue.class b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1ed04d9a50ecc34dda7ea5b5fcd717ad62476f2
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizableReferenceQueue.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizableSoftReference.class b/src/main/resources/org/python/google/common/base/FinalizableSoftReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..54be4418a7f65b9e0f9153a5492ff830a264677f
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizableSoftReference.class differ
diff --git a/src/main/resources/org/python/google/common/base/FinalizableWeakReference.class b/src/main/resources/org/python/google/common/base/FinalizableWeakReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..5db4b27427c70f5c67183b71e035973a6a470a47
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FinalizableWeakReference.class differ
diff --git a/src/main/resources/org/python/google/common/base/Function.class b/src/main/resources/org/python/google/common/base/Function.class
new file mode 100644
index 0000000000000000000000000000000000000000..174675645d639ddff2817dd0caf903b4d0873947
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Function.class differ
diff --git a/src/main/resources/org/python/google/common/base/FunctionalEquivalence.class b/src/main/resources/org/python/google/common/base/FunctionalEquivalence.class
new file mode 100644
index 0000000000000000000000000000000000000000..7139740d42ea401a839663f9d835ed6a365dadc8
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/FunctionalEquivalence.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$1.class b/src/main/resources/org/python/google/common/base/Functions$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9846a3885fd277923e2f8351d49d9e9b6a0625a2
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$ConstantFunction.class b/src/main/resources/org/python/google/common/base/Functions$ConstantFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..949ac796918c2493f9498d300e3a73c96be10f00
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$ConstantFunction.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$ForMapWithDefault.class b/src/main/resources/org/python/google/common/base/Functions$ForMapWithDefault.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a3b1a65e6937612cb8b0c61cd8670c5909c97c9
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$ForMapWithDefault.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$FunctionComposition.class b/src/main/resources/org/python/google/common/base/Functions$FunctionComposition.class
new file mode 100644
index 0000000000000000000000000000000000000000..c15607858ab1bd8073d6e586df8c7a44d80f4cc0
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$FunctionComposition.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$FunctionForMapNoDefault.class b/src/main/resources/org/python/google/common/base/Functions$FunctionForMapNoDefault.class
new file mode 100644
index 0000000000000000000000000000000000000000..a16dab34883dbc12bdcb637f88329788aad15b1d
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$FunctionForMapNoDefault.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$IdentityFunction.class b/src/main/resources/org/python/google/common/base/Functions$IdentityFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbdc3697a8cac4b3d049d77753a23110a32baf62
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$IdentityFunction.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$PredicateFunction.class b/src/main/resources/org/python/google/common/base/Functions$PredicateFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..472402bd4a8ee925ad6d49889e9ce8c3d86a0257
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$PredicateFunction.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$SupplierFunction.class b/src/main/resources/org/python/google/common/base/Functions$SupplierFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..eae29b2de317a5c1d5055012a1fa9c5724407e65
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$SupplierFunction.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions$ToStringFunction.class b/src/main/resources/org/python/google/common/base/Functions$ToStringFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..674d7d21aa9a1185dbee13ccba00aade60f87392
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions$ToStringFunction.class differ
diff --git a/src/main/resources/org/python/google/common/base/Functions.class b/src/main/resources/org/python/google/common/base/Functions.class
new file mode 100644
index 0000000000000000000000000000000000000000..95605f01ab27e30d450342c1b21dcec28cd40942
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Functions.class differ
diff --git a/src/main/resources/org/python/google/common/base/Joiner$1.class b/src/main/resources/org/python/google/common/base/Joiner$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa65dbce592119a173a5219806e71fa1ebc700df
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Joiner$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Joiner$2.class b/src/main/resources/org/python/google/common/base/Joiner$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..e4c53c40b3a656165048666120d1b520e97abfe8
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Joiner$2.class differ
diff --git a/src/main/resources/org/python/google/common/base/Joiner$3.class b/src/main/resources/org/python/google/common/base/Joiner$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a5bc9295c63a49afd21e32bbd4aff2e1b23464a
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Joiner$3.class differ
diff --git a/src/main/resources/org/python/google/common/base/Joiner$MapJoiner.class b/src/main/resources/org/python/google/common/base/Joiner$MapJoiner.class
new file mode 100644
index 0000000000000000000000000000000000000000..e01baa543bd243db58a510c48eb61f784549be57
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Joiner$MapJoiner.class differ
diff --git a/src/main/resources/org/python/google/common/base/Joiner.class b/src/main/resources/org/python/google/common/base/Joiner.class
new file mode 100644
index 0000000000000000000000000000000000000000..d922340969c779fbe2858aee6d71cee0b42e8c01
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Joiner.class differ
diff --git a/src/main/resources/org/python/google/common/base/MediumCharMatcher.class b/src/main/resources/org/python/google/common/base/MediumCharMatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ac5f2bd694e2fcbfe0929e8dd012ea264f51d70
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/MediumCharMatcher.class differ
diff --git a/src/main/resources/org/python/google/common/base/Objects$1.class b/src/main/resources/org/python/google/common/base/Objects$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9670b71a992555ae37bc7fc2b74e94e4f9cb86da
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Objects$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Objects$ToStringHelper$ValueHolder.class b/src/main/resources/org/python/google/common/base/Objects$ToStringHelper$ValueHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e69f8703312f153705019a2d9f17f86883fdd34
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Objects$ToStringHelper$ValueHolder.class differ
diff --git a/src/main/resources/org/python/google/common/base/Objects$ToStringHelper.class b/src/main/resources/org/python/google/common/base/Objects$ToStringHelper.class
new file mode 100644
index 0000000000000000000000000000000000000000..e42aa57f32ab96bcff8a59ddcbe7a73e62cd0485
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Objects$ToStringHelper.class differ
diff --git a/src/main/resources/org/python/google/common/base/Objects.class b/src/main/resources/org/python/google/common/base/Objects.class
new file mode 100644
index 0000000000000000000000000000000000000000..1553d734fc2c44bc6810b1aa3cf6f5afe2641ecb
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Objects.class differ
diff --git a/src/main/resources/org/python/google/common/base/Optional$1$1.class b/src/main/resources/org/python/google/common/base/Optional$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e977e3995eba9010f1db07e78d3b186f240cbc7b
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Optional$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Optional$1.class b/src/main/resources/org/python/google/common/base/Optional$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..927b31d860a2572a1deca8f35269b7a766c58d6a
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Optional$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Optional.class b/src/main/resources/org/python/google/common/base/Optional.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6e6a0b18c17d3151301e07d4b1b64cd6856cf9a
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Optional.class differ
diff --git a/src/main/resources/org/python/google/common/base/PairwiseEquivalence.class b/src/main/resources/org/python/google/common/base/PairwiseEquivalence.class
new file mode 100644
index 0000000000000000000000000000000000000000..467df3ed3fb799efe74f8f4d3646e7d61d03a27e
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/PairwiseEquivalence.class differ
diff --git a/src/main/resources/org/python/google/common/base/Platform$1.class b/src/main/resources/org/python/google/common/base/Platform$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..afca56ec2ec036fc20558de77bf447bb929def7d
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Platform$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Platform.class b/src/main/resources/org/python/google/common/base/Platform.class
new file mode 100644
index 0000000000000000000000000000000000000000..46b0d8f957e85ed8069cff1c3483912a89619493
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Platform.class differ
diff --git a/src/main/resources/org/python/google/common/base/Preconditions.class b/src/main/resources/org/python/google/common/base/Preconditions.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d09eeb57cf4381eb5e0819cefe50b223dc212a2
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Preconditions.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicate.class b/src/main/resources/org/python/google/common/base/Predicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e0d2f89a01437507d070199316c66377f7e8839
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$1.class b/src/main/resources/org/python/google/common/base/Predicates$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..97b769cb98770ad2ddf6c877c0eb2c497864350d
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$AndPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$AndPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..5310a1407ff27ed9995295a2298489b38ea137aa
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$AndPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$AssignableFromPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$AssignableFromPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5349d465a9738e7c1cd4ee54aeea44f1d3d45fb
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$AssignableFromPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$CompositionPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$CompositionPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae8da7545cda88fe4709a6252bf02690747ab289
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$CompositionPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$ContainsPatternPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$ContainsPatternPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..43b13db11862f6b2b93b2786b1a00e7e8e69b982
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$ContainsPatternPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$InPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$InPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..5de33b959594f8d415ab57c05c7e3191f0c1b274
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$InPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$InstanceOfPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$InstanceOfPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..326c01cf73ab65dc60b1814cdb55b9bdaec11486
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$InstanceOfPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$IsEqualToPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$IsEqualToPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..644aa95fcbd5861dcdb6cdb0ec63becf814f32e3
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$IsEqualToPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$NotPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$NotPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc25f7fd70e98c722c2001de15fa902206d8bf35
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$NotPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$1.class b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7b8b594557584497a9657e712842c537c54c20f
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$2.class b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7768b9843ca53fff3547f70bcc70190e4019e70
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$2.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$3.class b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c3b661d0a92a0607a5a6f4f2fadb01d19220426
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$3.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$4.class b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc66afbdceb6d6bdb3c83218d763ca531757904d
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate$4.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..611d070174fcff396217b517e3a9b2d6260461ba
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$ObjectPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates$OrPredicate.class b/src/main/resources/org/python/google/common/base/Predicates$OrPredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fdf64a16abeda4c64539fac9c6f1a00fced097c
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates$OrPredicate.class differ
diff --git a/src/main/resources/org/python/google/common/base/Predicates.class b/src/main/resources/org/python/google/common/base/Predicates.class
new file mode 100644
index 0000000000000000000000000000000000000000..35517e25a09e27f778109355be75452510f4e721
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Predicates.class differ
diff --git a/src/main/resources/org/python/google/common/base/Present.class b/src/main/resources/org/python/google/common/base/Present.class
new file mode 100644
index 0000000000000000000000000000000000000000..b470d66d67cb5e855d7da2e94592cea0572a94a1
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Present.class differ
diff --git a/src/main/resources/org/python/google/common/base/SmallCharMatcher.class b/src/main/resources/org/python/google/common/base/SmallCharMatcher.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a204367586bcdc602dd64600680379e8133c58d
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/SmallCharMatcher.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$1$1.class b/src/main/resources/org/python/google/common/base/Splitter$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..eab5a3c0b0aa96e774219780a0c1a09d47b8c5c5
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$1.class b/src/main/resources/org/python/google/common/base/Splitter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5256949b3e447fc4fbead287ec53ff83e9b61416
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$2$1.class b/src/main/resources/org/python/google/common/base/Splitter$2$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b63a96ff107f4c238e833bd77c4c44b945317d4
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$2$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$2.class b/src/main/resources/org/python/google/common/base/Splitter$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..78056854337e5237b7e0c3f86643d94fd33d690a
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$2.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$3$1.class b/src/main/resources/org/python/google/common/base/Splitter$3$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ecb53d991052b17b1dab0de48dd66f3bf359f09
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$3$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$3.class b/src/main/resources/org/python/google/common/base/Splitter$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..e69f4d6db9f7cba6577cd61dfe4e7307da8f79c3
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$3.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$4$1.class b/src/main/resources/org/python/google/common/base/Splitter$4$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5615c34d0211ae41bc6620d10e378a0affb8c91a
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$4$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$4.class b/src/main/resources/org/python/google/common/base/Splitter$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..71e4b826f96befc68739002be4c0550904c53e94
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$4.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$5.class b/src/main/resources/org/python/google/common/base/Splitter$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d5c3823f997fd7cc540ddd51a2a0f21cfbb32ce
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$5.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$MapSplitter.class b/src/main/resources/org/python/google/common/base/Splitter$MapSplitter.class
new file mode 100644
index 0000000000000000000000000000000000000000..28c4cd7bff791520f9358ebbe51c796b664a18c0
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$MapSplitter.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$SplittingIterator.class b/src/main/resources/org/python/google/common/base/Splitter$SplittingIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..f82e55226f6e1bed6179bf3710aba031bd0942f5
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$SplittingIterator.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter$Strategy.class b/src/main/resources/org/python/google/common/base/Splitter$Strategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae34cb59b0bf733829e5b816cb556b6cc983106f
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter$Strategy.class differ
diff --git a/src/main/resources/org/python/google/common/base/Splitter.class b/src/main/resources/org/python/google/common/base/Splitter.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bb83ab9889f9364627b3e3a019722d9df022df4
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Splitter.class differ
diff --git a/src/main/resources/org/python/google/common/base/Stopwatch$1.class b/src/main/resources/org/python/google/common/base/Stopwatch$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1ad9acf4e64005ccda9dcdfba06b74e072e38bf
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Stopwatch$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Stopwatch.class b/src/main/resources/org/python/google/common/base/Stopwatch.class
new file mode 100644
index 0000000000000000000000000000000000000000..04f60a42f443609395624ab6781e33d464cbaa02
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Stopwatch.class differ
diff --git a/src/main/resources/org/python/google/common/base/Strings.class b/src/main/resources/org/python/google/common/base/Strings.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d5d249f6a9f262fec90822ddbf2d2d20285c68e
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Strings.class differ
diff --git a/src/main/resources/org/python/google/common/base/Supplier.class b/src/main/resources/org/python/google/common/base/Supplier.class
new file mode 100644
index 0000000000000000000000000000000000000000..90d22a0d85867d2f3b4e09ec1e8b9610c9b92409
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Supplier.class differ
diff --git a/src/main/resources/org/python/google/common/base/Suppliers$ExpiringMemoizingSupplier.class b/src/main/resources/org/python/google/common/base/Suppliers$ExpiringMemoizingSupplier.class
new file mode 100644
index 0000000000000000000000000000000000000000..19977af50ea7ad4eced429b23361bd98c1df772f
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Suppliers$ExpiringMemoizingSupplier.class differ
diff --git a/src/main/resources/org/python/google/common/base/Suppliers$MemoizingSupplier.class b/src/main/resources/org/python/google/common/base/Suppliers$MemoizingSupplier.class
new file mode 100644
index 0000000000000000000000000000000000000000..5afd75deba240e595830570944f480c2de1a4439
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Suppliers$MemoizingSupplier.class differ
diff --git a/src/main/resources/org/python/google/common/base/Suppliers$SupplierComposition.class b/src/main/resources/org/python/google/common/base/Suppliers$SupplierComposition.class
new file mode 100644
index 0000000000000000000000000000000000000000..b11e3fcbbac6216b6750509d382ba0204620ffc0
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Suppliers$SupplierComposition.class differ
diff --git a/src/main/resources/org/python/google/common/base/Suppliers$SupplierFunction.class b/src/main/resources/org/python/google/common/base/Suppliers$SupplierFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..de1ec1ef05681987344f0cc7f038af22e60928c1
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Suppliers$SupplierFunction.class differ
diff --git a/src/main/resources/org/python/google/common/base/Suppliers$SupplierOfInstance.class b/src/main/resources/org/python/google/common/base/Suppliers$SupplierOfInstance.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d4d1a5ed0e4199fb6f5b86e9329361314a65096
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Suppliers$SupplierOfInstance.class differ
diff --git a/src/main/resources/org/python/google/common/base/Suppliers$ThreadSafeSupplier.class b/src/main/resources/org/python/google/common/base/Suppliers$ThreadSafeSupplier.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e6b6b77d4a9c2b7779b2ff464b6b676a4d06c51
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Suppliers$ThreadSafeSupplier.class differ
diff --git a/src/main/resources/org/python/google/common/base/Suppliers.class b/src/main/resources/org/python/google/common/base/Suppliers.class
new file mode 100644
index 0000000000000000000000000000000000000000..8462aa545885745345aa1afa3da3d5c212a9d55c
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Suppliers.class differ
diff --git a/src/main/resources/org/python/google/common/base/Throwables.class b/src/main/resources/org/python/google/common/base/Throwables.class
new file mode 100644
index 0000000000000000000000000000000000000000..11b85c5ea0cf07c3d633ea837eb68b569a269103
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Throwables.class differ
diff --git a/src/main/resources/org/python/google/common/base/Ticker$1.class b/src/main/resources/org/python/google/common/base/Ticker$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c520cc5fa78c710562887b8f4192aaa52b30720
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Ticker$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/Ticker.class b/src/main/resources/org/python/google/common/base/Ticker.class
new file mode 100644
index 0000000000000000000000000000000000000000..364b8f486b08ef91a2fe0003352c65dfdd525d5c
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/Ticker.class differ
diff --git a/src/main/resources/org/python/google/common/base/internal/Finalizer$1.class b/src/main/resources/org/python/google/common/base/internal/Finalizer$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..90062bb3a7db44011ee145f34cf0f9b3e314ccae
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/internal/Finalizer$1.class differ
diff --git a/src/main/resources/org/python/google/common/base/internal/Finalizer$ShutDown.class b/src/main/resources/org/python/google/common/base/internal/Finalizer$ShutDown.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b04c19a358bdb9cc5f9a23a49c41faae1659525
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/internal/Finalizer$ShutDown.class differ
diff --git a/src/main/resources/org/python/google/common/base/internal/Finalizer.class b/src/main/resources/org/python/google/common/base/internal/Finalizer.class
new file mode 100644
index 0000000000000000000000000000000000000000..792a2a08ff61a0edcf28ac3016701322eadfdf7f
Binary files /dev/null and b/src/main/resources/org/python/google/common/base/internal/Finalizer.class differ
diff --git a/src/main/resources/org/python/google/common/cache/AbstractCache$SimpleStatsCounter.class b/src/main/resources/org/python/google/common/cache/AbstractCache$SimpleStatsCounter.class
new file mode 100644
index 0000000000000000000000000000000000000000..89d49418c4f16fc3f1cf5a3e7aa992c10566d52d
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/AbstractCache$SimpleStatsCounter.class differ
diff --git a/src/main/resources/org/python/google/common/cache/AbstractCache$StatsCounter.class b/src/main/resources/org/python/google/common/cache/AbstractCache$StatsCounter.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c9be8c4901f182f8007c8c317b0c581e602cce1
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/AbstractCache$StatsCounter.class differ
diff --git a/src/main/resources/org/python/google/common/cache/AbstractCache.class b/src/main/resources/org/python/google/common/cache/AbstractCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..68b277ac968303556a1c5d2548c47879097fe6be
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/AbstractCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/AbstractLoadingCache.class b/src/main/resources/org/python/google/common/cache/AbstractLoadingCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8d4d4c1325b1c4349b0547111a627aa88a8c214
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/AbstractLoadingCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/Cache.class b/src/main/resources/org/python/google/common/cache/Cache.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc164a6c060193a455f5253beb609c9b92d8f107
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/Cache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilder$1.class b/src/main/resources/org/python/google/common/cache/CacheBuilder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e397d6446df97189f60e30826f8bc6c37198b0be
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilder$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilder$2.class b/src/main/resources/org/python/google/common/cache/CacheBuilder$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..afc2e0c19eacbbd1d2f34d206deb55cdf8f38920
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilder$2.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilder$3.class b/src/main/resources/org/python/google/common/cache/CacheBuilder$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..24ea0564e70a187bf371379ecb40174e40e969e3
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilder$3.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilder$NullListener.class b/src/main/resources/org/python/google/common/cache/CacheBuilder$NullListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..09a488bd9ddc0048a4625c6bb0db24b8d4aab54f
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilder$NullListener.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilder$OneWeigher.class b/src/main/resources/org/python/google/common/cache/CacheBuilder$OneWeigher.class
new file mode 100644
index 0000000000000000000000000000000000000000..affb6c98d8250d3de4f3f7a799a4d9554cbdafb5
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilder$OneWeigher.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilder.class b/src/main/resources/org/python/google/common/cache/CacheBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..621d1b4b3de6f0bf03b1d450c97a41d480d16b4d
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilder.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$1.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..654c3f02f67358c71b421b8d669eb24814e56850
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$AccessDurationParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$AccessDurationParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..36a762238337f0da35ef976b60decd09779cf8b9
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$AccessDurationParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ConcurrencyLevelParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ConcurrencyLevelParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3d4b95c000aafc6383e442f8c9af6b7f54350dd
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ConcurrencyLevelParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$DurationParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$DurationParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e0ce6b07b2cac07bd3f4911f5e8adb1052d8065
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$DurationParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$InitialCapacityParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$InitialCapacityParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..967b553cead62929463527c1eff752ef03d327f2
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$InitialCapacityParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$IntegerParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$IntegerParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..10a15d4cd8abd301dcf59114f1f9fefd91e2bfa5
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$IntegerParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$KeyStrengthParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$KeyStrengthParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..9655caa70f0ec8f26bf32bf19789693086fee2b1
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$KeyStrengthParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$LongParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$LongParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..34bfc765dcb04c4f758a6eba224209a698482e74
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$LongParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$MaximumSizeParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$MaximumSizeParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c10b3b492f1403088b3d476a268f98beca96ae4
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$MaximumSizeParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$MaximumWeightParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$MaximumWeightParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..8dd2c5de0431aec35aeb47d720f2ea788ce8094d
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$MaximumWeightParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$RefreshDurationParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$RefreshDurationParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..41319c3526a748fa67da63c8f9c5a0b282725f58
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$RefreshDurationParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ValueParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ValueParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ae350fbb4b4273da98f17319b4f3c52cc6b6590
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ValueParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ValueStrengthParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ValueStrengthParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..59052de5f590246e4bb1ae63430eadf2432a7757
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$ValueStrengthParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$WriteDurationParser.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$WriteDurationParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a45ee1b4902015959906e441b1e64c76397d483
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec$WriteDurationParser.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheBuilderSpec.class b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb13402f2aae869d1fca03c867a610240f617e14
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheBuilderSpec.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheLoader$FunctionToCacheLoader.class b/src/main/resources/org/python/google/common/cache/CacheLoader$FunctionToCacheLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..934e632fcaeb0f60e2d8d6d47157a18c571d9ade
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheLoader$FunctionToCacheLoader.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheLoader$InvalidCacheLoadException.class b/src/main/resources/org/python/google/common/cache/CacheLoader$InvalidCacheLoadException.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d17bfd3948dd74c5420287155918f73cc219ab3
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheLoader$InvalidCacheLoadException.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheLoader$SupplierToCacheLoader.class b/src/main/resources/org/python/google/common/cache/CacheLoader$SupplierToCacheLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..160f2f351320b4138e05f04e3556eb4086fadf73
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheLoader$SupplierToCacheLoader.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheLoader$UnsupportedLoadingOperationException.class b/src/main/resources/org/python/google/common/cache/CacheLoader$UnsupportedLoadingOperationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..33c2b5881d5ad849030bc41225b1ea1035f0d931
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheLoader$UnsupportedLoadingOperationException.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheLoader.class b/src/main/resources/org/python/google/common/cache/CacheLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b643ffe0944f8fe29bf8fcd41c5779ba9b85927
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheLoader.class differ
diff --git a/src/main/resources/org/python/google/common/cache/CacheStats.class b/src/main/resources/org/python/google/common/cache/CacheStats.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a01eada883fad946b6328be729ee752a1c51934
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/CacheStats.class differ
diff --git a/src/main/resources/org/python/google/common/cache/ForwardingCache$SimpleForwardingCache.class b/src/main/resources/org/python/google/common/cache/ForwardingCache$SimpleForwardingCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..508ccca7b519d42eae8abd9eff1d3cce110648d2
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/ForwardingCache$SimpleForwardingCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/ForwardingCache.class b/src/main/resources/org/python/google/common/cache/ForwardingCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..941f79dc2670b22e1de4fd2bbdad69d0226b223f
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/ForwardingCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/ForwardingLoadingCache$SimpleForwardingLoadingCache.class b/src/main/resources/org/python/google/common/cache/ForwardingLoadingCache$SimpleForwardingLoadingCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..69db09520b15ae640befe411b39786344e98491f
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/ForwardingLoadingCache$SimpleForwardingLoadingCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/ForwardingLoadingCache.class b/src/main/resources/org/python/google/common/cache/ForwardingLoadingCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..10208074bff2c5ad93ac3101ea527d6c6585312c
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/ForwardingLoadingCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LoadingCache.class b/src/main/resources/org/python/google/common/cache/LoadingCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..f95f0b7f0e7ba47b2638e2113b0bcacedae6e587
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LoadingCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$1.class b/src/main/resources/org/python/google/common/cache/LocalCache$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c2205787aa22fc0431aca3652523cad2b14f423
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$2.class b/src/main/resources/org/python/google/common/cache/LocalCache$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..9dc53021363f3308920312a503c07c820ab01ac0
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$2.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$AbstractReferenceEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$AbstractReferenceEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f0599c362551350e333dae534c12daf8e72b1ec
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$AbstractReferenceEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue$1.class b/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fb513d6f8265e56d8da1a6371969594331931d8
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue$2.class b/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..572c0221f282e9d8ed2befd2c37cda6dd740f0ff
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue$2.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue.class b/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..63c82d006536865db27337b99c529e9eaa8b2513
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$AccessQueue.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$1.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb2682be7f6e6f757cac7cf320cbc4b70acc0d92
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$2.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..42282ede62e2ccdd172d4d47d3783e9d8d987cc4
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$2.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$3.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..230dd8c596ecde4ba1771311d75e983cf5967a59
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$3.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$4.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..aaf7fffe0a73b66f892ed8ed692dfda23726887c
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$4.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$5.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe0fcdeb5aa9b6cdaa8428e035ecf093d4cf1545
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$5.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$6.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..0fd832335eafaaccfc5cbb50dc49522f1935bed7
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$6.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$7.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..b705af571929a660b50f9dbf53f9fa301fc88f67
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$7.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$8.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..583ae31a4b3350a20b13c4d3d8cdcb619d50e7ce
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory$8.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..d256cecb6d5644fbe305eeaf395fbfac657c80d6
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryFactory.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntryIterator.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntryIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..27051a0424dbefcc7f016a45063d01c6d58a7857
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntryIterator.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$EntrySet.class b/src/main/resources/org/python/google/common/cache/LocalCache$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..0781219be32aac138981f25a971a4c7becdb1474
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$HashIterator.class b/src/main/resources/org/python/google/common/cache/LocalCache$HashIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6dfa306101ca781fa8998871fc5a3f9fba1cd446
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$HashIterator.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$KeyIterator.class b/src/main/resources/org/python/google/common/cache/LocalCache$KeyIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..069df75fa98841cdfd0c96d1d55fc5c8d55c2773
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$KeyIterator.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$KeySet.class b/src/main/resources/org/python/google/common/cache/LocalCache$KeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe8a0962ede3922a4027a4c4747af295b90136fb
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$KeySet.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$LoadingSerializationProxy.class b/src/main/resources/org/python/google/common/cache/LocalCache$LoadingSerializationProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6969a6d36a83b04bc3dc8ee0d341cacc43fbdf5
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$LoadingSerializationProxy.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$LoadingValueReference.class b/src/main/resources/org/python/google/common/cache/LocalCache$LoadingValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..9855bf083a0ef6d5f8d23a8904058f62a2373f39
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$LoadingValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$LocalLoadingCache.class b/src/main/resources/org/python/google/common/cache/LocalCache$LocalLoadingCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..7346181b2ae471c6bfa94cbf8c0d16be8aa68ed3
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$LocalLoadingCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$LocalManualCache$1.class b/src/main/resources/org/python/google/common/cache/LocalCache$LocalManualCache$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d168ccfa83e04af861b78ab0c51f65dd3a96d087
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$LocalManualCache$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$LocalManualCache.class b/src/main/resources/org/python/google/common/cache/LocalCache$LocalManualCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fba479c9c0c3bff0114bef6c03908a3591450c0
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$LocalManualCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$ManualSerializationProxy.class b/src/main/resources/org/python/google/common/cache/LocalCache$ManualSerializationProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..b99b5d71745ab7af565af4550bde6164846ef6ae
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$ManualSerializationProxy.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$NullEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$NullEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d353ff79d9b169b4e8fbbed990cf933ff479ca9
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$NullEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$ReferenceEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$ReferenceEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..f07b73b3e101a2b9185a86b74e3df57d2509c31f
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$ReferenceEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$Segment$1.class b/src/main/resources/org/python/google/common/cache/LocalCache$Segment$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f15483dcc3a87c83ed3f515d848382f986239d9
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$Segment$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$Segment.class b/src/main/resources/org/python/google/common/cache/LocalCache$Segment.class
new file mode 100644
index 0000000000000000000000000000000000000000..6bc99d42d359ee4f7b70cd8bd68d9c4eee4d3800
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$Segment.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$SoftValueReference.class b/src/main/resources/org/python/google/common/cache/LocalCache$SoftValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6a27de06635a7ec94d8cedeff508a5476a387be
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$SoftValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$Strength$1.class b/src/main/resources/org/python/google/common/cache/LocalCache$Strength$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..153ffc04ec959a721e35117c91d9cc0e20a4420c
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$Strength$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$Strength$2.class b/src/main/resources/org/python/google/common/cache/LocalCache$Strength$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3c242796959b6d6b1c7a9267b01251725852d45
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$Strength$2.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$Strength$3.class b/src/main/resources/org/python/google/common/cache/LocalCache$Strength$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..353a82fc3d82d472b9996d047d787c1cc97659dd
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$Strength$3.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$Strength.class b/src/main/resources/org/python/google/common/cache/LocalCache$Strength.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e4cc363546b5ef4b6a830592483ca71b1991422
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$Strength.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$StrongAccessEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$StrongAccessEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..0dd563318df596a4ce7627ca7a173e9513f223d4
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$StrongAccessEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$StrongAccessWriteEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$StrongAccessWriteEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..a07e48c7bf4c4ffb1b2a10b525e7b4d26fed0d75
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$StrongAccessWriteEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$StrongEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$StrongEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..0634fb89e0bbaf50990a03f6a0f67417f08485ab
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$StrongEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$StrongValueReference.class b/src/main/resources/org/python/google/common/cache/LocalCache$StrongValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f9d6426b9aba98f9df50fb890a8ca5f312ecc7e
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$StrongValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$StrongWriteEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$StrongWriteEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..481ad307fbd91835f0111a7bbc4c74bf37a7ebe6
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$StrongWriteEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$ValueIterator.class b/src/main/resources/org/python/google/common/cache/LocalCache$ValueIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f3b4fd44a24a777362dc3cd3b3f52bf0b1634d7
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$ValueIterator.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$ValueReference.class b/src/main/resources/org/python/google/common/cache/LocalCache$ValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..59bf0874423f3a77d1105e14e4d1cd942a6463e8
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$ValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$Values.class b/src/main/resources/org/python/google/common/cache/LocalCache$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..270299803086c66808b700e8db19327a9eb165a5
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$Values.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WeakAccessEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$WeakAccessEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab448b4e515fa23e8bef94a97239f77219c793b4
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WeakAccessEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WeakAccessWriteEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$WeakAccessWriteEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5c29865fae0d065ffa547ccea0b4f2c782fb2cb
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WeakAccessWriteEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WeakEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$WeakEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dc8ce9fb26429c251f8561acaa2a93db829398f
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WeakEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WeakValueReference.class b/src/main/resources/org/python/google/common/cache/LocalCache$WeakValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fb3b23a3ee3f4fa022b40b8d09a782ab517ca8f
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WeakValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WeakWriteEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$WeakWriteEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..0601108d874e5f5a72d2043d075958a88e7252f1
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WeakWriteEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WeightedSoftValueReference.class b/src/main/resources/org/python/google/common/cache/LocalCache$WeightedSoftValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..44f58cdd9aa2d0e76456cab4eb21a521570f0165
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WeightedSoftValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WeightedStrongValueReference.class b/src/main/resources/org/python/google/common/cache/LocalCache$WeightedStrongValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..0354d21dd3f9f5c4f35c7018502e3e015d99f5d1
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WeightedStrongValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WeightedWeakValueReference.class b/src/main/resources/org/python/google/common/cache/LocalCache$WeightedWeakValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcb4b3ad3baba68ed7b6d0c8ea1ca5f68f4102cd
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WeightedWeakValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue$1.class b/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..78df33d44a8ba8d9a3da66b7e09104bd6e6afe9e
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue$2.class b/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..6800fc5db8074033b7830de23ef04b974c6e2ba3
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue$2.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue.class b/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f3ef6cbf809f581da8facd4e4f9c1203dd6f1c1
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WriteQueue.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache$WriteThroughEntry.class b/src/main/resources/org/python/google/common/cache/LocalCache$WriteThroughEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..f23c859ebb4cc2805b6b8adb145be09a36e83e1b
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache$WriteThroughEntry.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LocalCache.class b/src/main/resources/org/python/google/common/cache/LocalCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..887d68c922731381ffced78d35af3cc4b9739c06
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LocalCache.class differ
diff --git a/src/main/resources/org/python/google/common/cache/LongAdder.class b/src/main/resources/org/python/google/common/cache/LongAdder.class
new file mode 100644
index 0000000000000000000000000000000000000000..701838234768fb24f0fe0839dc138f267ba96b00
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/LongAdder.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalCause$1.class b/src/main/resources/org/python/google/common/cache/RemovalCause$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..481651ec713dc0decd0d1a17fe25c38d170a8be3
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalCause$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalCause$2.class b/src/main/resources/org/python/google/common/cache/RemovalCause$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..e590bd80a165eb941a07bd04bb5a7da82238e6cc
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalCause$2.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalCause$3.class b/src/main/resources/org/python/google/common/cache/RemovalCause$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..60a29ce4e3cbf7069df13059902794f466502644
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalCause$3.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalCause$4.class b/src/main/resources/org/python/google/common/cache/RemovalCause$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8c22b5a469c642167920628ac2faa125eec44de
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalCause$4.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalCause$5.class b/src/main/resources/org/python/google/common/cache/RemovalCause$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5dc8ccda0bf297d0bb7679cc805a2f4e782c10d
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalCause$5.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalCause.class b/src/main/resources/org/python/google/common/cache/RemovalCause.class
new file mode 100644
index 0000000000000000000000000000000000000000..ebc5cde39234acca2310305f867901fc97e92c27
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalCause.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalListener.class b/src/main/resources/org/python/google/common/cache/RemovalListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..537d647d7af4c5f90bdc3ca46546e3eb3f6b59fa
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalListener.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalListeners$1$1.class b/src/main/resources/org/python/google/common/cache/RemovalListeners$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cd363711ac09402b0baff2016f17188a16876ec
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalListeners$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalListeners$1.class b/src/main/resources/org/python/google/common/cache/RemovalListeners$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a91883434088e04d4fe3f5756ace3c6891b4acae
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalListeners$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalListeners.class b/src/main/resources/org/python/google/common/cache/RemovalListeners.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3f94ef74a424da71ffcd5ac70524be555b40d24
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalListeners.class differ
diff --git a/src/main/resources/org/python/google/common/cache/RemovalNotification.class b/src/main/resources/org/python/google/common/cache/RemovalNotification.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f2d1c9ddff67eaade372c63d029fdee2b077d34
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/RemovalNotification.class differ
diff --git a/src/main/resources/org/python/google/common/cache/Striped64$1.class b/src/main/resources/org/python/google/common/cache/Striped64$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..efdb97366a828e6b09fd486cb43f71480fe8ec95
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/Striped64$1.class differ
diff --git a/src/main/resources/org/python/google/common/cache/Striped64$Cell.class b/src/main/resources/org/python/google/common/cache/Striped64$Cell.class
new file mode 100644
index 0000000000000000000000000000000000000000..c23fc26f77d7b3d337761e3a555e99a508c9ad53
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/Striped64$Cell.class differ
diff --git a/src/main/resources/org/python/google/common/cache/Striped64$HashCode.class b/src/main/resources/org/python/google/common/cache/Striped64$HashCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..5922e661de110b887e110e556b9b5a4c1724881f
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/Striped64$HashCode.class differ
diff --git a/src/main/resources/org/python/google/common/cache/Striped64$ThreadHashCode.class b/src/main/resources/org/python/google/common/cache/Striped64$ThreadHashCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..94c70a5623b3fc44b01328628958a6aafd467c4f
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/Striped64$ThreadHashCode.class differ
diff --git a/src/main/resources/org/python/google/common/cache/Striped64.class b/src/main/resources/org/python/google/common/cache/Striped64.class
new file mode 100644
index 0000000000000000000000000000000000000000..221552ee2ec0182658ff64357de285c4fe7a2a59
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/Striped64.class differ
diff --git a/src/main/resources/org/python/google/common/cache/Weigher.class b/src/main/resources/org/python/google/common/cache/Weigher.class
new file mode 100644
index 0000000000000000000000000000000000000000..78105e97f0112f0ea7c160f3891f5b880764ad90
Binary files /dev/null and b/src/main/resources/org/python/google/common/cache/Weigher.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractBiMap$1.class b/src/main/resources/org/python/google/common/collect/AbstractBiMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d1e8189041e738392281a7818c15ad6b42e18a9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractBiMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet$1$1.class b/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d8d4bf309ed726b01837766a355cf9da9075c60
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0ee0c377c76909e80cb45714e5a1afffe0cb6b6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..101ef1b430f46ba8d18bb587a2aa518afa374d4a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractBiMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractBiMap$Inverse.class b/src/main/resources/org/python/google/common/collect/AbstractBiMap$Inverse.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e3c28dab90dd5e5cbfb11e8cf6147aff44b1054
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractBiMap$Inverse.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractBiMap$KeySet.class b/src/main/resources/org/python/google/common/collect/AbstractBiMap$KeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..947ad5b7fc15976f8c3e75dc36f3c31ae41bbee6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractBiMap$KeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractBiMap$ValueSet.class b/src/main/resources/org/python/google/common/collect/AbstractBiMap$ValueSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..13d865d357dc4f96cd2ae4dd7ecf55f91c02c306
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractBiMap$ValueSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractBiMap.class b/src/main/resources/org/python/google/common/collect/AbstractBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..20d7024fcaef10020c6b958af1dba411ef08c3f0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractIndexedListIterator.class b/src/main/resources/org/python/google/common/collect/AbstractIndexedListIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..228f51e6d9492f2de6f50714972282349be45155
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractIndexedListIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractIterator$1.class b/src/main/resources/org/python/google/common/collect/AbstractIterator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b2cef041d0704e43f11b39782d8ef7074f9d8b0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractIterator$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractIterator$State.class b/src/main/resources/org/python/google/common/collect/AbstractIterator$State.class
new file mode 100644
index 0000000000000000000000000000000000000000..82d8d09603403169e2763efa5d8ed5086894aecd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractIterator$State.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractIterator.class b/src/main/resources/org/python/google/common/collect/AbstractIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..81a64875515c86a684f678954d0bea7e68e249a2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractLinkedIterator.class b/src/main/resources/org/python/google/common/collect/AbstractLinkedIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecb758d4c7a23dc25d62370b1819c0a5345c413c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractLinkedIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractListMultimap.class b/src/main/resources/org/python/google/common/collect/AbstractListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..186aaf3ee0cad8ca05a56c8391b1f822d573761e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$1$1.class b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0abb004dc41eeb59693b92d17f6488181c552980
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$1.class b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b128feaeeb56e6eee0aed060073a0e314e38fbc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$MapBasedElementSet.class b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$MapBasedElementSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..96229736cf7919ee3adf1e34c6edfee7d8a441ab
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$MapBasedElementSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$MapBasedMultisetIterator.class b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$MapBasedMultisetIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6894cf325d8996b46f928abe8cecb0e394ad1c0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset$MapBasedMultisetIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset.class b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..0857a85933ef7231b07e97b558e5010f65cb7b5e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMapBasedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMapEntry.class b/src/main/resources/org/python/google/common/collect/AbstractMapEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..aaa3b6f730fa395d0f63c539775907ac4849fa95
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMapEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$1.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a766fee5199346b410447c58d3d3dc1561796e34
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$2.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..d60e0c41e733fec8d1bcb3aca9c1f223899b70d2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$3.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..0399748a63e82dc3a664af8b66861a003c1a7c4f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$4.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..23c9a04013106d0a35c707217d45154d0243bcf2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap$AsMapEntries.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap$AsMapEntries.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fd444f88789fa2e35de80be2981893b943eaad4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap$AsMapEntries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap$AsMapIterator.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap$AsMapIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8c3b4bcd83e1cade581a91dc81f91dee08e9738
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap$AsMapIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae013f514b1da0025fb7b76f6ff1006bfbfbeca7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$AsMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$EntryIterator.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$EntryIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7e2d030d21e41c3f38c13d52ed48ccabdf41952
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$EntryIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$KeySet$1.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$KeySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc54399fefd84acd25f4536a199aa99c556c1b6d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$KeySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$KeySet.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$KeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..28d7fc1d5a9d961c25a37fa88207b3153ae823c7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$KeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$RandomAccessWrappedList.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$RandomAccessWrappedList.class
new file mode 100644
index 0000000000000000000000000000000000000000..08b8b01acbb283fbe00cc01bd54bcbbab961ab45
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$RandomAccessWrappedList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$SortedAsMap.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$SortedAsMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..7eaf12080c360e14d40314a98d83e66c8038f2df
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$SortedAsMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$SortedKeySet.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$SortedKeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..a16243945d52ba2126150659166711fc378379b9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$SortedKeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedCollection$WrappedIterator.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedCollection$WrappedIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..d24dfa66c8613dabc0fb68b4a11a984dbfa14ffb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedCollection$WrappedIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedCollection.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..af5af6855eef210bf86d79b80f34bf5dcfde4684
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedList$WrappedListIterator.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedList$WrappedListIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..daf18dff89072e9ceb87cf2d2642816cb87df6ba
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedList$WrappedListIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedList.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedList.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b91dee9334bc2a8a499c7748d8b32b1ab16de1c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedSet.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1540784f1a06ebc2eef8392eee637e1c276899e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedSortedSet.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedSortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..212d4ae35bf8ad33792f820e0dee34cda94d0142
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap$WrappedSortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultimap.class b/src/main/resources/org/python/google/common/collect/AbstractMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bc015a2e5624210a28000efdd1e69b556ea636e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultiset$ElementSet.class b/src/main/resources/org/python/google/common/collect/AbstractMultiset$ElementSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fb173cf9fd28a59c9f35dcc3f558336bb039f31
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultiset$ElementSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultiset$EntrySet.class b/src/main/resources/org/python/google/common/collect/AbstractMultiset$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..9642f0027fa909ae18210907339f81e17fed75f3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultiset$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractMultiset.class b/src/main/resources/org/python/google/common/collect/AbstractMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..b57173c42052d765acb5b815b837502a2cd80b1d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractSequentialIterator.class b/src/main/resources/org/python/google/common/collect/AbstractSequentialIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc3af9e510f0095a66a73078f51c2f71a7336f41
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractSequentialIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractSetMultimap.class b/src/main/resources/org/python/google/common/collect/AbstractSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..95ab54f4db6e6dc95f76e28cc7b2f3a50d42eccb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset$1.class b/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a974c8aad0c14fb65faaaf5b0cc647c9bb712d0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset$2.class b/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f582a2dfe05077c9de76f38830327ad5fee427d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset.class b/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c5ead66d90c836369f55ba98a1d7d342982af60
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractSortedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AbstractSortedSetMultimap.class b/src/main/resources/org/python/google/common/collect/AbstractSortedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..b05909c31548efcf542edbab05888b7d276efc99
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AbstractSortedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AllEqualOrdering.class b/src/main/resources/org/python/google/common/collect/AllEqualOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..81880f72da244a64a0fb6a3d63cc6c80a38199c8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AllEqualOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayListMultimap.class b/src/main/resources/org/python/google/common/collect/ArrayListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9e2155985d0e89e4bcadf86b194d59fb81e3007
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$1.class b/src/main/resources/org/python/google/common/collect/ArrayTable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c376b4016c8c00e6d88d6dec7324dfd95605d1e4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1$1$1.class b/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c46be845bd42bad599081202414c340e8a649bdc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1$1.class b/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9527d92e661685cc5f075a4280c28a722880acf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1.class b/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8ead6df2292f6fc5f109bbd9e821314ed5af390
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap.class b/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..99d69b0d027cebd5e1301e88ae54408310dcc125
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$ArrayMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet$1$1.class b/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..72f647224aec736ce9fa4c4e2c8a5eb74a5af882
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet$1.class b/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9dcf1e2b75f4e5bade8ece5292b7a2241707f4fb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet.class b/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2e219652b4cf066df1e1a386cbdcb878fc527a3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$CellSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$Column.class b/src/main/resources/org/python/google/common/collect/ArrayTable$Column.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d77a4e5afedb0ed799423b1bf953efed790b6c9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$Column.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$ColumnMap.class b/src/main/resources/org/python/google/common/collect/ArrayTable$ColumnMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..139f1b663550eadde5b5391bce3aef233661d14c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$ColumnMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$Row.class b/src/main/resources/org/python/google/common/collect/ArrayTable$Row.class
new file mode 100644
index 0000000000000000000000000000000000000000..bfdd3aa90a90c252e2b1684ef50bf42945cb5b9c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$Row.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$RowMap.class b/src/main/resources/org/python/google/common/collect/ArrayTable$RowMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..69928c8c493124fb0b8d475365a0f1e16fd96e2a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$RowMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$Values$1.class b/src/main/resources/org/python/google/common/collect/ArrayTable$Values$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1500fa9f104fbc64396c4185903da5be90edce5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$Values$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable$Values.class b/src/main/resources/org/python/google/common/collect/ArrayTable$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ae1e5042413fec6d335470d54f2b141aaf7f88a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ArrayTable.class b/src/main/resources/org/python/google/common/collect/ArrayTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a986381f5cccca48b7ade08e4bb43514d920e12
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ArrayTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/AsynchronousComputationException.class b/src/main/resources/org/python/google/common/collect/AsynchronousComputationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2d6dde8e7e00014a41ebd0f77784853459853e9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/AsynchronousComputationException.class differ
diff --git a/src/main/resources/org/python/google/common/collect/BiMap.class b/src/main/resources/org/python/google/common/collect/BiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8a5763066fe74c588a16ccf38d6bdf8d0e4f88e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/BiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/BoundType$1.class b/src/main/resources/org/python/google/common/collect/BoundType$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f82dff4193b30c4cb9a338d898e5de25bd80dc7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/BoundType$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/BoundType$2.class b/src/main/resources/org/python/google/common/collect/BoundType$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..daa63e8d77a90be105c1d986e513b2e14380cad0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/BoundType$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/BoundType.class b/src/main/resources/org/python/google/common/collect/BoundType.class
new file mode 100644
index 0000000000000000000000000000000000000000..c27e662b268594c36f0ea05a15caa472ba3bc1b1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/BoundType.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ByFunctionOrdering.class b/src/main/resources/org/python/google/common/collect/ByFunctionOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..afa4709c28edc651b7d37b6c9f03d166ed461835
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ByFunctionOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ClassToInstanceMap.class b/src/main/resources/org/python/google/common/collect/ClassToInstanceMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc992fb7524c0922198524deb54a7acd65ef5acc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ClassToInstanceMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$1.class b/src/main/resources/org/python/google/common/collect/Collections2$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..838e19a2d74621390a9d60721b143a8e47387777
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection$1.class b/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef6ea25a3d56542573167b32aede024eeb7dc0dc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection$2.class b/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fed5221de64a487dd08cc325d9b083bfb452d95
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection.class b/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fc4b0c105da03f3d121d6204a514ca273bdeb2a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$FilteredCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$OrderedPermutationCollection.class b/src/main/resources/org/python/google/common/collect/Collections2$OrderedPermutationCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d69bafb9fcbd09ab97df37a4212bd8fce3a9a0e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$OrderedPermutationCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$OrderedPermutationIterator.class b/src/main/resources/org/python/google/common/collect/Collections2$OrderedPermutationIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..1689cdbd6168ae2672497d602fb6efdef88a4bb1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$OrderedPermutationIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$PermutationCollection.class b/src/main/resources/org/python/google/common/collect/Collections2$PermutationCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..133851e7b4998402ba4f2ff48a5d575f48cec140
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$PermutationCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$PermutationIterator.class b/src/main/resources/org/python/google/common/collect/Collections2$PermutationIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..96bb3c7e5a7d49a29bbf4a14553afaf3f981f1d3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$PermutationIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2$TransformedCollection.class b/src/main/resources/org/python/google/common/collect/Collections2$TransformedCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..17fa22a590a97bee408fa911243ce2fbc6443bd1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2$TransformedCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Collections2.class b/src/main/resources/org/python/google/common/collect/Collections2.class
new file mode 100644
index 0000000000000000000000000000000000000000..a547febf70d4ce475b5d1c3af22bef05697133ec
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Collections2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComparatorOrdering.class b/src/main/resources/org/python/google/common/collect/ComparatorOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..c57f9a95172420e346d8612bf92383666b802aa1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComparatorOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComparisonChain$1.class b/src/main/resources/org/python/google/common/collect/ComparisonChain$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..66216abaefcc7fe7f5a769c61effba9ec9249c8b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComparisonChain$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComparisonChain$InactiveComparisonChain.class b/src/main/resources/org/python/google/common/collect/ComparisonChain$InactiveComparisonChain.class
new file mode 100644
index 0000000000000000000000000000000000000000..283c0f8663b140f78f36ff50443b7c6dc105129e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComparisonChain$InactiveComparisonChain.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComparisonChain.class b/src/main/resources/org/python/google/common/collect/ComparisonChain.class
new file mode 100644
index 0000000000000000000000000000000000000000..5396fde12080e342efd12466307d33a268085662
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComparisonChain.class differ
diff --git a/src/main/resources/org/python/google/common/collect/CompoundOrdering.class b/src/main/resources/org/python/google/common/collect/CompoundOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a6ed8c262d4ef248de960f4c908367f560813aa
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/CompoundOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComputationException.class b/src/main/resources/org/python/google/common/collect/ComputationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..595b61fe84d6ca48540656bf4e74531be820715e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComputationException.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputationExceptionReference.class b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputationExceptionReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e7ba39feba29cb2ecfada0e8c898242c263bc7c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputationExceptionReference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputedReference.class b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputedReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..283dee669e539a4a3792cb425244be3ef9c25048
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputedReference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingMapAdapter.class b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingMapAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..244fcbb69fe63c59a340c58d34cd3fa181315a9c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingMapAdapter.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingSegment.class b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingSegment.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc38034580f59738461043929923b980308dd7cd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingSegment.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingSerializationProxy.class b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingSerializationProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ac50459c2c35d74048771d1180397b4a3319463
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingSerializationProxy.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingValueReference.class b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..c81dfe0951324ee7f628770b823ccda43bf86b76
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap$ComputingValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap.class b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6a2718c71a600376ea18f4f8996363cd9784727
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ComputingConcurrentHashMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$1.class b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..50290d5af5c4bc4c413eeaf8d0531f2b7d4f6631
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$2.class b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..36bd26a3be43a484a8f1d2dd1bbd691c000266f8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$3.class b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3f8bd0038f52c6c8e96e7fe2ea67b5be2d7bd17
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$EntrySet.class b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5b32e13301d881cf4b3910b46cd5968ff59039f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$FieldSettersHolder.class b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$FieldSettersHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..680e24a4033ad60a1fecf6a01073d3950c7ae68b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset$FieldSettersHolder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset.class b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..6dbb85953cb041ef05ea9979ae34d934dd7d0e0d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ConcurrentHashMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraint.class b/src/main/resources/org/python/google/common/collect/Constraint.class
new file mode 100644
index 0000000000000000000000000000000000000000..f09637f245a9c0d8b152124b4a934d2a597e23c4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraint.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedCollection.class b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc05247b06394532ba53777aae341981a14aae86
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedList.class b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedList.class
new file mode 100644
index 0000000000000000000000000000000000000000..4979f8fa297a77c541431dc44128c49f97a3fa73
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedListIterator.class b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedListIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..90dfdb768289c7120db9f2bafc7458f30ae59aee
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedListIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedMultiset.class b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ec7c0b2ac724a72bf4b895658eae7f3757b1fc0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedRandomAccessList.class b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedRandomAccessList.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad48aa2f7699e5fae030d612058e3f1f7b5a15b5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedRandomAccessList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedSet.class b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ee92f7385177cbcdff9adb9f5b0e132b6125c4a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedSortedSet.class b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedSortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ec858076194bb978355c7f0a14a176fff86454c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints$ConstrainedSortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints$NotNullConstraint.class b/src/main/resources/org/python/google/common/collect/Constraints$NotNullConstraint.class
new file mode 100644
index 0000000000000000000000000000000000000000..52545d6a99bdfa0d07aab5c6f5b5c271245958b5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints$NotNullConstraint.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Constraints.class b/src/main/resources/org/python/google/common/collect/Constraints.class
new file mode 100644
index 0000000000000000000000000000000000000000..58f97e958c214e95d208a2c9819547f1c91a2e7d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Constraints.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ContiguousSet.class b/src/main/resources/org/python/google/common/collect/ContiguousSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..83670790fb88db4cd0be1c20238fb34b7be0e5e1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ContiguousSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Count.class b/src/main/resources/org/python/google/common/collect/Count.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4002c317afbcd21eba81a5e968c055d31f8d22d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Count.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Cut$1.class b/src/main/resources/org/python/google/common/collect/Cut$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..86ac65e249046f3a828802bccbdb3772af39c831
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Cut$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Cut$AboveAll.class b/src/main/resources/org/python/google/common/collect/Cut$AboveAll.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5b96e1fc8b64029270ab8066a93e35f5832a417
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Cut$AboveAll.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Cut$AboveValue.class b/src/main/resources/org/python/google/common/collect/Cut$AboveValue.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb1c3d64533d3e425f02c80595ced2ca82754800
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Cut$AboveValue.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Cut$BelowAll.class b/src/main/resources/org/python/google/common/collect/Cut$BelowAll.class
new file mode 100644
index 0000000000000000000000000000000000000000..6df4d8d6ba51cc675905f385a82f74c7301f992d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Cut$BelowAll.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Cut$BelowValue.class b/src/main/resources/org/python/google/common/collect/Cut$BelowValue.class
new file mode 100644
index 0000000000000000000000000000000000000000..42a992b3c8cd6af41927b3d5475f4555f606406c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Cut$BelowValue.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Cut.class b/src/main/resources/org/python/google/common/collect/Cut.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0aa114834be359e2da6e7fca63c9274ccf480e3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Cut.class differ
diff --git a/src/main/resources/org/python/google/common/collect/DescendingImmutableSortedMultiset$1.class b/src/main/resources/org/python/google/common/collect/DescendingImmutableSortedMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..737ef47e565472d7f466390f575f25d118d3fa5c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/DescendingImmutableSortedMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/DescendingImmutableSortedMultiset.class b/src/main/resources/org/python/google/common/collect/DescendingImmutableSortedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..46d35374b50bda14f830dbfd55af140ecbefc659
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/DescendingImmutableSortedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/DiscreteDomain.class b/src/main/resources/org/python/google/common/collect/DiscreteDomain.class
new file mode 100644
index 0000000000000000000000000000000000000000..31688d5f4a26e50f999d346cfdbe16a7c679ecc4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/DiscreteDomain.class differ
diff --git a/src/main/resources/org/python/google/common/collect/DiscreteDomains$BigIntegerDomain.class b/src/main/resources/org/python/google/common/collect/DiscreteDomains$BigIntegerDomain.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2ebe66f3ba9ac909542477f73a9ad2412421d85
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/DiscreteDomains$BigIntegerDomain.class differ
diff --git a/src/main/resources/org/python/google/common/collect/DiscreteDomains$IntegerDomain.class b/src/main/resources/org/python/google/common/collect/DiscreteDomains$IntegerDomain.class
new file mode 100644
index 0000000000000000000000000000000000000000..4dc0bc74a1e130b39611e3c343a83b83c7a38352
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/DiscreteDomains$IntegerDomain.class differ
diff --git a/src/main/resources/org/python/google/common/collect/DiscreteDomains$LongDomain.class b/src/main/resources/org/python/google/common/collect/DiscreteDomains$LongDomain.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b92d8c6aa19cce4bac7f2b9444e3bbd96acea81
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/DiscreteDomains$LongDomain.class differ
diff --git a/src/main/resources/org/python/google/common/collect/DiscreteDomains.class b/src/main/resources/org/python/google/common/collect/DiscreteDomains.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8babbc8ce5eb7a53389e2f0d9cccf758d71d3e9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/DiscreteDomains.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyContiguousSet$1.class b/src/main/resources/org/python/google/common/collect/EmptyContiguousSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c083ae0354b0deab1f6bdd0b5c80b77da47d19fb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyContiguousSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyContiguousSet$SerializedForm.class b/src/main/resources/org/python/google/common/collect/EmptyContiguousSet$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..43d02e07cbef57b9fb5b4a88436ae6eb5a60031c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyContiguousSet$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyContiguousSet.class b/src/main/resources/org/python/google/common/collect/EmptyContiguousSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b7cc8f87ac512ac9694ad20bd26fe4d9a636f59
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyContiguousSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableBiMap.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..4035fc4a6cd74ed6c28e3e768ecd8c2ed6c7c8bb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableList.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableList.class
new file mode 100644
index 0000000000000000000000000000000000000000..c695c7c91584504b56cea4641d8befc458195489
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableListMultimap.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..e4b7b9be3dda9445a49e68f2789ca48b2d55123f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableMap.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0040cc803ca2ee311a6d13971c9f77da7bc5afd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableMultiset.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbd0dc947783bb681e787604be9f4f6b89d3d96b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableSet.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0170d64671a3c46ddae04628ca3dc58b20edb86
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableSetMultimap.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..b85b6a77870ca70e75abffcf129061a0ec3fdc40
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedMap.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5d2819ea968b6ba51abb5d6d7a505e3df8e5756
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedMultiset.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..f61c9f9f8a00d10f69d7b08042b41506e009caff
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedSet.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..44df59a2a12d8dabea3519541f3f811b47f4dd1a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableSortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EmptyImmutableTable.class b/src/main/resources/org/python/google/common/collect/EmptyImmutableTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9d5e2f77f4422128d5455b8bd9d3e5cd0715295
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EmptyImmutableTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EnumBiMap.class b/src/main/resources/org/python/google/common/collect/EnumBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..17dedda35daf8b150f1e86027a0c8078d132e576
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EnumBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EnumHashBiMap.class b/src/main/resources/org/python/google/common/collect/EnumHashBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca73ea9c8fdbd21bae0cf908fed81c1b991db235
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EnumHashBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/EnumMultiset.class b/src/main/resources/org/python/google/common/collect/EnumMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..4dd12c4bee389e08c87e942e7fc5df9a12ba0a58
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/EnumMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ExplicitOrdering.class b/src/main/resources/org/python/google/common/collect/ExplicitOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6d7fdc07e3f2a916339f98cfbecda0c8e8dc0b3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ExplicitOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/FluentIterable$1.class b/src/main/resources/org/python/google/common/collect/FluentIterable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d4472fd2f81bc0f80ca4c81ad03f10b19cec015
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/FluentIterable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/FluentIterable$FromIterableFunction.class b/src/main/resources/org/python/google/common/collect/FluentIterable$FromIterableFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..a688373e41802a501039deb525e4c018b3b458ba
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/FluentIterable$FromIterableFunction.class differ
diff --git a/src/main/resources/org/python/google/common/collect/FluentIterable.class b/src/main/resources/org/python/google/common/collect/FluentIterable.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6b1b409362ee9431bd18722a8e63ddd26e4be94
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/FluentIterable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingCollection.class b/src/main/resources/org/python/google/common/collect/ForwardingCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ecbe79cb5d284a315fe3fd1283a63a9a0b9a58e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingConcurrentMap.class b/src/main/resources/org/python/google/common/collect/ForwardingConcurrentMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c8355f361d9c1381b120fea3b82cea585a823fa
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingConcurrentMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingDeque.class b/src/main/resources/org/python/google/common/collect/ForwardingDeque.class
new file mode 100644
index 0000000000000000000000000000000000000000..f381edbfa4f1aaa37af9b9e98a13bc03f077c09a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingDeque.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingImmutableList.class b/src/main/resources/org/python/google/common/collect/ForwardingImmutableList.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2097c91996ba175f8d2a7e5edd49110edb2081b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingImmutableList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingImmutableMap.class b/src/main/resources/org/python/google/common/collect/ForwardingImmutableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..2edc394e73424386bf1e90abf167a55cb5c8078a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingImmutableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingImmutableSet.class b/src/main/resources/org/python/google/common/collect/ForwardingImmutableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b6a5e7bc61dae3b740df96b14d828b1a8b93797
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingImmutableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingIterator.class b/src/main/resources/org/python/google/common/collect/ForwardingIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..30906319941301982984ac73a78d70feb194f331
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingList.class b/src/main/resources/org/python/google/common/collect/ForwardingList.class
new file mode 100644
index 0000000000000000000000000000000000000000..a96db0747d93e8aa81572c44aaf0742cb444000f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingListIterator.class b/src/main/resources/org/python/google/common/collect/ForwardingListIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..01213b3450b9bc06a3181e422c1a1b65b96e6468
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingListIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingListMultimap.class b/src/main/resources/org/python/google/common/collect/ForwardingListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b471430077f15728f4c9a81a4552aa6de53ffc9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardEntrySet.class b/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c1d8fafb9b40556c40408e5ad2c5c97610d619c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardEntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardKeySet.class b/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardKeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..64ab3a7c09791540fce1eb8c1f7f551431ac0c8c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardKeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardValues.class b/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardValues.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ccdb1e24344d0775044d0259d4d1014caf54f0f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingMap$StandardValues.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingMap.class b/src/main/resources/org/python/google/common/collect/ForwardingMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..7de32c4bad13ae3c4ee7dfa498f9de05360f07e0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingMapEntry.class b/src/main/resources/org/python/google/common/collect/ForwardingMapEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..96f168f37448037c4347eb51770c3a0c6e358b2a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingMapEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingMultimap.class b/src/main/resources/org/python/google/common/collect/ForwardingMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..1836dfc1f7d57a6fa065f8112d1b66cf194d1441
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingMultiset$StandardElementSet.class b/src/main/resources/org/python/google/common/collect/ForwardingMultiset$StandardElementSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3fb1daf8f5baa0c3097930248825a92faf2babd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingMultiset$StandardElementSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingMultiset.class b/src/main/resources/org/python/google/common/collect/ForwardingMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e24d759e7929678b531fbd75b347bac37698830
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardDescendingMap$1.class b/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardDescendingMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d729aa65eb1a10a38bc2ba323dc48d2de6d9ac43
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardDescendingMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardDescendingMap.class b/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardDescendingMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..420ea5b1d14729d9645125491eb9ecb5646ef8ee
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardDescendingMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardNavigableKeySet.class b/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardNavigableKeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fc5fdbb9420a66d362a1821b3bed279be6800ca
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap$StandardNavigableKeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap.class b/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5d50c27e3e8622b3961e6d2907a2bf3852473a6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingNavigableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingNavigableSet$StandardDescendingSet.class b/src/main/resources/org/python/google/common/collect/ForwardingNavigableSet$StandardDescendingSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..45bf66deed9365f8f64cee20ae6b5227d27981d4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingNavigableSet$StandardDescendingSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingNavigableSet.class b/src/main/resources/org/python/google/common/collect/ForwardingNavigableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f45076520aa69a5af1b4ecf020f6ed5e0064690
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingNavigableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingObject.class b/src/main/resources/org/python/google/common/collect/ForwardingObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..61ef2454bd4a3bc776706bf88733ba3c2025e5d9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingObject.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingQueue.class b/src/main/resources/org/python/google/common/collect/ForwardingQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..c794ec9db5cc08b490fcb107e3eddffb7ac3a24d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingQueue.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingSet.class b/src/main/resources/org/python/google/common/collect/ForwardingSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..a420039f622d95bb33af1c9a5bbc096b491ad03d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingSetMultimap.class b/src/main/resources/org/python/google/common/collect/ForwardingSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..d63de8c3689187b6efcdf032b74431a829e28cdf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingSortedMap.class b/src/main/resources/org/python/google/common/collect/ForwardingSortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ad5349daa69e463f04a08d95b1e230ee9fe8f55
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingSortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingSortedSet.class b/src/main/resources/org/python/google/common/collect/ForwardingSortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6ff8510bca4eea461d571499cd673d76b201ce2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingSortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingSortedSetMultimap.class b/src/main/resources/org/python/google/common/collect/ForwardingSortedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..dfaf7828ced07ef030b0811b6f46192bf36c440b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingSortedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ForwardingTable.class b/src/main/resources/org/python/google/common/collect/ForwardingTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..42926ec5b754b980a7c240dc30e671e7c8e309cf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ForwardingTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/GeneralRange$1.class b/src/main/resources/org/python/google/common/collect/GeneralRange$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..891557c54cfb8d3fcd33b73730440d8730f6ad86
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/GeneralRange$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/GeneralRange.class b/src/main/resources/org/python/google/common/collect/GeneralRange.class
new file mode 100644
index 0000000000000000000000000000000000000000..814e9606947ef6c969d8b1d4346f7f5011167343
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/GeneralRange.class differ
diff --git a/src/main/resources/org/python/google/common/collect/GenericMapMaker$NullListener.class b/src/main/resources/org/python/google/common/collect/GenericMapMaker$NullListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f59adc9726066db8b42d0f86b99002c58e5fc1f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/GenericMapMaker$NullListener.class differ
diff --git a/src/main/resources/org/python/google/common/collect/GenericMapMaker.class b/src/main/resources/org/python/google/common/collect/GenericMapMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..0503fb46b191a7412f4c0238bef5956d936c178a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/GenericMapMaker.class differ
diff --git a/src/main/resources/org/python/google/common/collect/GwtTransient.class b/src/main/resources/org/python/google/common/collect/GwtTransient.class
new file mode 100644
index 0000000000000000000000000000000000000000..46c9b0be582ccb8aa5b54a1b2fc57c19d8b89bc3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/GwtTransient.class differ
diff --git a/src/main/resources/org/python/google/common/collect/HashBasedTable$Factory.class b/src/main/resources/org/python/google/common/collect/HashBasedTable$Factory.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5520f2ca39172487308452ef57b22a5f5a09ca0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/HashBasedTable$Factory.class differ
diff --git a/src/main/resources/org/python/google/common/collect/HashBasedTable.class b/src/main/resources/org/python/google/common/collect/HashBasedTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c1f9e3886d1e5d0568a6577f0c92279f4695054
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/HashBasedTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/HashBiMap.class b/src/main/resources/org/python/google/common/collect/HashBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..1261d02cd67c88fb3b5f55c18dd53295c1599af3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/HashBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/HashMultimap.class b/src/main/resources/org/python/google/common/collect/HashMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..60878c29666ed7c3c25231eee835e3e5a667d020
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/HashMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/HashMultiset.class b/src/main/resources/org/python/google/common/collect/HashMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d1d3d04685ef8cfecb0190b82c5d24f80324bd4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/HashMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Hashing.class b/src/main/resources/org/python/google/common/collect/Hashing.class
new file mode 100644
index 0000000000000000000000000000000000000000..feadaf9f6fba1fb342f026852c4f440f34dd68cb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Hashing.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableAsList$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableAsList$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..0255601384a075289d0e5f6191fbad1430d119b2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableAsList$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableAsList.class b/src/main/resources/org/python/google/common/collect/ImmutableAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..15676391c8fffcd6ead2f5e102bda6eb13681634
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableAsList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableBiMap$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableBiMap$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..38296f277ca930489de13fb98fa051eb469f9bcc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableBiMap$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableBiMap$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableBiMap$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f60a0d502b676441d84c9afa5f90b6c5ca40216
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableBiMap$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableBiMap.class b/src/main/resources/org/python/google/common/collect/ImmutableBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e508c2df47c3ab54c7c53cb22ba92baedaa88d6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap$1.class b/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..fca703d6756046aab86e154d1a92ee72c7d2e063
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ce100d03bb9cbd4ccdf5a933070b67a8e6ffe8f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap.class b/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..3468b838a1e1d24defbbfe9dd68eb82af60a4dfc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableClassToInstanceMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableCollection$1.class b/src/main/resources/org/python/google/common/collect/ImmutableCollection$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c2c93e2daba36fa10d1e7f50f53c163875aa0aa
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableCollection$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableCollection$ArrayImmutableCollection.class b/src/main/resources/org/python/google/common/collect/ImmutableCollection$ArrayImmutableCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..a875f2ea42d366dd9cdeb1be0ea6d4a03aee5ab1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableCollection$ArrayImmutableCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableCollection$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableCollection$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1ebdf60bf55f8dd29170ef6aa3dc071a8f65c2c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableCollection$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableCollection$EmptyImmutableCollection.class b/src/main/resources/org/python/google/common/collect/ImmutableCollection$EmptyImmutableCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..d456291d0c703a87c5204fa4ac0f666be8efae26
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableCollection$EmptyImmutableCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableCollection$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableCollection$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..75a2aa3233aedaf28504c7e6127309b37b66f74e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableCollection$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableCollection.class b/src/main/resources/org/python/google/common/collect/ImmutableCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a173d8e1353d40b7a9dbd7c4f0c49eb883d67e5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableEntry.class b/src/main/resources/org/python/google/common/collect/ImmutableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0d3248ca39c7e82d832116bd0c4ca989ab192d9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableEnumSet$EnumSerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableEnumSet$EnumSerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..04a40c375f7fcb404e3de83f2deee073ed56c51d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableEnumSet$EnumSerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableEnumSet.class b/src/main/resources/org/python/google/common/collect/ImmutableEnumSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..78edd4eeb34a0194534561a0ec7a2854d8d3a488
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableEnumSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableList$1.class b/src/main/resources/org/python/google/common/collect/ImmutableList$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc306bf955e405964306615b456880cdb76726ab
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableList$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableList$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableList$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..5282c1ee776dbc347c2023b89796220f60536ad1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableList$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableList$ReverseImmutableList$1.class b/src/main/resources/org/python/google/common/collect/ImmutableList$ReverseImmutableList$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..665fb9db52d16163fc7d43257bb61b2db3917fd3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableList$ReverseImmutableList$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableList$ReverseImmutableList.class b/src/main/resources/org/python/google/common/collect/ImmutableList$ReverseImmutableList.class
new file mode 100644
index 0000000000000000000000000000000000000000..b487784f72a2f45f1e8907366bf3453e7ff20f8b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableList$ReverseImmutableList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableList$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableList$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f9016ac8c6033fe345b80ef57c6eb260b35bec5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableList$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableList$SubList.class b/src/main/resources/org/python/google/common/collect/ImmutableList$SubList.class
new file mode 100644
index 0000000000000000000000000000000000000000..bceecd884515aa81184fdd56aa52ca5e329fe077
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableList$SubList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableList.class b/src/main/resources/org/python/google/common/collect/ImmutableList.class
new file mode 100644
index 0000000000000000000000000000000000000000..138467296a8c6ae719cc2007467a8e8e1d0d6a1a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableListMultimap$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableListMultimap$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..5817dc8e95f0ebde9f08a33938e7e66591d7d5a0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableListMultimap$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableListMultimap.class b/src/main/resources/org/python/google/common/collect/ImmutableListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..8979d395961db09d3ad0942f06b827001d9dc68e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMap$1.class b/src/main/resources/org/python/google/common/collect/ImmutableMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c02aa282d1e7bfbe0b48e01c758d88cd97902c05
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMap$2.class b/src/main/resources/org/python/google/common/collect/ImmutableMap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba8cb89ce549617bb8b2716010baa0e4f6a3ce0a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMap$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableMap$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..a75e1d690e1e5b6aa89ccc20e10e4abe9870c28e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMap$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMap$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableMap$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..78ca73d063f2851f8a1526efe231a9f8b6e5f207
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMap$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMap.class b/src/main/resources/org/python/google/common/collect/ImmutableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..501b1e8ec73961be108d7324f1b42c8acbc06880
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMapEntrySet$EntrySetSerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableMapEntrySet$EntrySetSerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ba0a4244fbb9815580390173525533b8427929f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMapEntrySet$EntrySetSerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMapEntrySet.class b/src/main/resources/org/python/google/common/collect/ImmutableMapEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..88c615a500ff52575afb3364fe73613196f50dd4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMapEntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet$1.class b/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..40cd4e2c1b791db7d6dfa826a5337724a25f5ea6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet$KeySetSerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet$KeySetSerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b553f10eea6c4021aa78f45ef72068dbbf18140
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet$KeySetSerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet.class b/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f590b971d66c296bc3959a3963bd51964ac5e8c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMapKeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMapValues$1.class b/src/main/resources/org/python/google/common/collect/ImmutableMapValues$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..35e50019419c0d1223c0b1b444583fd86055c8f8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMapValues$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMapValues$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableMapValues$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..f643c7921f295d9a5a13990d1cb720c5d897c3f9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMapValues$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMapValues.class b/src/main/resources/org/python/google/common/collect/ImmutableMapValues.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c304feca55247946e1348c8a019265f153ce68a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMapValues.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$1.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..66f5095629880d6158075f14433a72cb8eb88822
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Builder$1.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Builder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8765ba8e08d1440be17baeba921b0cf4a2075aa3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Builder$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..3faed4d300cb48832c28450a36be7bad91921f6a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$BuilderMultimap.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$BuilderMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..b949f1427bd536cb3c3dbf2f96ac7938e875368b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$BuilderMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$EntryCollection$1.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$EntryCollection$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0384ef62c78f8da746e12b063ddc28fd23da7376
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$EntryCollection$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$EntryCollection.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$EntryCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..37fea93708ce9188d9ba27f72865775ae3943938
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$EntryCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$FieldSettersHolder.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$FieldSettersHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..da18ce2d6adc145b90f8b7c586d21e57e4171a3a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$FieldSettersHolder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys$KeysEntrySet$1.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys$KeysEntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..046338953ba85d1c0681824190b4ca4843a9165c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys$KeysEntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys$KeysEntrySet.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys$KeysEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4128da10e2147208b3b03fc7a0c03fab2c942ef
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys$KeysEntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys.class
new file mode 100644
index 0000000000000000000000000000000000000000..d825250fec76717a1a54e8b2b6f9e4a82e3ecbd9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Keys.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Values.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..f08273034ba9ad57db0c1a6031c0882f7f565d2d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultimap.class b/src/main/resources/org/python/google/common/collect/ImmutableMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bd9abe3ff7f330421c6b7b93beb2b9cc4c56154
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultiset$1.class b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..63692f119b610d998e801a65d7da28a4e6f555d9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultiset$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..9635bc3abd338f9cd50200d5c9077e4367162489
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultiset$EntrySet.class b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..a666d373fc0862714fb5f8317c8f74cf84e77755
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultiset$EntrySetSerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$EntrySetSerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..0477c7420e25b6e0738dc21ac587107934387d8e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$EntrySetSerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultiset$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..c05913e174ff05c07c3fef24759cf138ce883dc9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultiset$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableMultiset.class b/src/main/resources/org/python/google/common/collect/ImmutableMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f95febfdd08bd3c521b1af21269e9ec704dedb6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSet$ArrayImmutableSet.class b/src/main/resources/org/python/google/common/collect/ImmutableSet$ArrayImmutableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..43d6828973ab8bce291137d7a3a3f7c7f962c4ff
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSet$ArrayImmutableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSet$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableSet$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..546608d71b80ff6041135726244df43754ce942c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSet$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSet$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableSet$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..68134c37f17b21672e62ef29050a5c0f83a681ad
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSet$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSet.class b/src/main/resources/org/python/google/common/collect/ImmutableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f8ba811e5202c9a9c98e537e6d1e1f2b16d17d4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$Builder$1.class b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$Builder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b37ca8551d981506d099481a4629502a2ae713e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$Builder$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..01b0dd1928c5f53c2aa484229c86880f61b091f4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$BuilderMultimap.class b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$BuilderMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..41875ddeb2a52fe569f63cdb956b86be20fb1270
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$BuilderMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$SortedKeyBuilderMultimap.class b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$SortedKeyBuilderMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..eaf1c63ffce41d6e8b89d94ed39b9c375a355760
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap$SortedKeyBuilderMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap.class b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..12f1a3f38851ca23e00ddb19b3d53220f4b4c792
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedAsList.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d38826e591b238d0315659a3f234ba88ecdf011
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedAsList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$1.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..464ae55fea24cebee7565ff4155b444229e170bb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6c56e9ce3fbb3d019092e2a5e7c0a6115618b2d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0b346954253241057d6458e73d3c6dcae0e480b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMap$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMap.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..eaa9db817099a6e8614e649758bda79ee28557ce
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMapFauxverideShim.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMapFauxverideShim.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ee1695c198cc2975df213ac0d196b9cf741185f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMapFauxverideShim.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..829b2384dfeed389192e10f1c0604c25c7f5ece0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5ebd775c8a2788ecdc1e026f68d5914bc6673af
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..9655cafe7f39b9afbb2cef6262689e42e2568592
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedMultisetFauxverideShim.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedMultisetFauxverideShim.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a898ac3aa8cbdfda5f93231dc8a06d7f46bb916
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedMultisetFauxverideShim.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedSet$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedSet$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..758c685091e8a1fafad450761473034fbb542b38
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedSet$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedSet$SerializedForm.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedSet$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..b67a126e26bea5397a956253c0f61cba381a1513
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedSet$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedSet.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7b5431159a0e503643eea8f89dbe2046f7c487e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableSortedSetFauxverideShim.class b/src/main/resources/org/python/google/common/collect/ImmutableSortedSetFauxverideShim.class
new file mode 100644
index 0000000000000000000000000000000000000000..949eb6b489c9f9f8ef270fdd1c39c8faa361ae13
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableSortedSetFauxverideShim.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableTable$Builder.class b/src/main/resources/org/python/google/common/collect/ImmutableTable$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..1eebc948bce148727052207efe252d9b5cb7ef82
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableTable$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ImmutableTable.class b/src/main/resources/org/python/google/common/collect/ImmutableTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bc2759c41e02bcfd75475870a56cd523ed20c56
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ImmutableTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Interner.class b/src/main/resources/org/python/google/common/collect/Interner.class
new file mode 100644
index 0000000000000000000000000000000000000000..312259c91fadf96df5f2b23a139af9d5662e15ff
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Interner.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Interners$1.class b/src/main/resources/org/python/google/common/collect/Interners$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..20dceba65f84c125f5a15687d9d3c6676537854c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Interners$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Interners$InternerFunction.class b/src/main/resources/org/python/google/common/collect/Interners$InternerFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..da5aa946dd27b58ce05a3052686c160fd8f9618c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Interners$InternerFunction.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Interners$WeakInterner$Dummy.class b/src/main/resources/org/python/google/common/collect/Interners$WeakInterner$Dummy.class
new file mode 100644
index 0000000000000000000000000000000000000000..bec9c1ec412d7d6c98f94b58a0d6a485bca2ff7e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Interners$WeakInterner$Dummy.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Interners$WeakInterner.class b/src/main/resources/org/python/google/common/collect/Interners$WeakInterner.class
new file mode 100644
index 0000000000000000000000000000000000000000..50ae3440f1f0ce2ab3e7877f0dfe2e159de8dc41
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Interners$WeakInterner.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Interners.class b/src/main/resources/org/python/google/common/collect/Interners.class
new file mode 100644
index 0000000000000000000000000000000000000000..97ddf7ff1063202d86acffcef491a9aba6aac773
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Interners.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$1.class b/src/main/resources/org/python/google/common/collect/Iterables$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..22c1c669c0b12d68f73502c4a1ecddbe0cca42d3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$10$1.class b/src/main/resources/org/python/google/common/collect/Iterables$10$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..927a57a5b98f6dd78bc89c987fd573288e4f8496
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$10$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$10.class b/src/main/resources/org/python/google/common/collect/Iterables$10.class
new file mode 100644
index 0000000000000000000000000000000000000000..491dc6e5e86e879e08acb264a3174a928e0b6840
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$10.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$11.class b/src/main/resources/org/python/google/common/collect/Iterables$11.class
new file mode 100644
index 0000000000000000000000000000000000000000..019fb29854c9cd3ba626e54ee08c2bfdcba32624
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$11.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$12.class b/src/main/resources/org/python/google/common/collect/Iterables$12.class
new file mode 100644
index 0000000000000000000000000000000000000000..533ed3448ef54baac3bebe215c448c0ce1871105
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$12.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$13.class b/src/main/resources/org/python/google/common/collect/Iterables$13.class
new file mode 100644
index 0000000000000000000000000000000000000000..aaf4578f04e99be83138943b9356a4c87c8aa880
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$13.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$14.class b/src/main/resources/org/python/google/common/collect/Iterables$14.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f2bf9e3bb07fc07a9eda13132aadda2d29f2be8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$14.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$15.class b/src/main/resources/org/python/google/common/collect/Iterables$15.class
new file mode 100644
index 0000000000000000000000000000000000000000..a74c4e8ae80a32fee9e5b912fff950822fc55e70
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$15.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$2.class b/src/main/resources/org/python/google/common/collect/Iterables$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..396ad4c1eb149b06294f00a0498821e8e39a4aa3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$3.class b/src/main/resources/org/python/google/common/collect/Iterables$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..9408ab99118debb7da98da2125976c70b3d2c77b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$4.class b/src/main/resources/org/python/google/common/collect/Iterables$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..de6137d3f037daa12a31e786ce4480d3a45ff360
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$5.class b/src/main/resources/org/python/google/common/collect/Iterables$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..23591cfdc2de3b1101822709b993061d0ebabbd8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$5.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$6.class b/src/main/resources/org/python/google/common/collect/Iterables$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8a264e768ec75c903c681f46ec0ef6206612d13
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$6.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$7.class b/src/main/resources/org/python/google/common/collect/Iterables$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..d02dd04adfc1f3c89b47c88b70e05f376f44f49b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$7.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$8.class b/src/main/resources/org/python/google/common/collect/Iterables$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f6e3c11586429f6ae01e6a030f62a8633f21dd3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$8.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$9.class b/src/main/resources/org/python/google/common/collect/Iterables$9.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0a8083352ceb239685a620475b585a6ca894788
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$9.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$ConsumingQueueIterator.class b/src/main/resources/org/python/google/common/collect/Iterables$ConsumingQueueIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6713f1952590ec2ee3a8de357866946abcfdf7a5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$ConsumingQueueIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables$UnmodifiableIterable.class b/src/main/resources/org/python/google/common/collect/Iterables$UnmodifiableIterable.class
new file mode 100644
index 0000000000000000000000000000000000000000..4717be65b8c1ca55f2c4cb7857c1f4376f945533
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables$UnmodifiableIterable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterables.class b/src/main/resources/org/python/google/common/collect/Iterables.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d10189b828d44695113b87fdd040b451213e02f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterables.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$1.class b/src/main/resources/org/python/google/common/collect/Iterators$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bcdeca93cdf4d268b7abde1a8c23fc4b8a896b4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$10.class b/src/main/resources/org/python/google/common/collect/Iterators$10.class
new file mode 100644
index 0000000000000000000000000000000000000000..e44ccc3d240bf45eb9c569fce5f121175e3b15f7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$10.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$11.class b/src/main/resources/org/python/google/common/collect/Iterators$11.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc3e78fb81bd017fff665238ac9f6565e85f42b6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$11.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$12.class b/src/main/resources/org/python/google/common/collect/Iterators$12.class
new file mode 100644
index 0000000000000000000000000000000000000000..1208fcfe5966e113f11f609b53ed21d373f0b7fb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$12.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$13.class b/src/main/resources/org/python/google/common/collect/Iterators$13.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef87bbe8ae7142f6baebccc5ae308b43c1814855
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$13.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$14.class b/src/main/resources/org/python/google/common/collect/Iterators$14.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2fcc9aba8bbcf7cbb4b0707fb8fbc49ce7c0a89
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$14.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$15.class b/src/main/resources/org/python/google/common/collect/Iterators$15.class
new file mode 100644
index 0000000000000000000000000000000000000000..48e9740dc30da993ea714ae25cf24de729d753af
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$15.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$16.class b/src/main/resources/org/python/google/common/collect/Iterators$16.class
new file mode 100644
index 0000000000000000000000000000000000000000..8dc9a87d23db66fac5a3ed88738416ae2e308742
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$16.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$2.class b/src/main/resources/org/python/google/common/collect/Iterators$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c7a6c326e03b9ddc5ceb5e906c94fc879e5b6a4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$3.class b/src/main/resources/org/python/google/common/collect/Iterators$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..59c0af6a7db032b2f175e6fcf84a8e1b835a2f2f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$4.class b/src/main/resources/org/python/google/common/collect/Iterators$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..b081a837bd24df49a6b30b360d4da0ad3a2373ea
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$5.class b/src/main/resources/org/python/google/common/collect/Iterators$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..875bc1b2f586e1ccc7bbe48e705ad8538974ec47
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$5.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$6.class b/src/main/resources/org/python/google/common/collect/Iterators$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..0dd150cdf0362ea9ba96bee869bb230ba7fecb02
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$6.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$7.class b/src/main/resources/org/python/google/common/collect/Iterators$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..5093c865a0574008f17ef85208abebc2ba3594aa
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$7.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$8.class b/src/main/resources/org/python/google/common/collect/Iterators$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..783fb42a9031bcf21140fd0833055c154a85dbd7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$8.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$9.class b/src/main/resources/org/python/google/common/collect/Iterators$9.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbd965d7e36992b02a8c96e76256a7b892dbbc74
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$9.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$MergingIterator$1.class b/src/main/resources/org/python/google/common/collect/Iterators$MergingIterator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d97faec154cecc8c29c0b50156841a87b2627cc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$MergingIterator$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$MergingIterator.class b/src/main/resources/org/python/google/common/collect/Iterators$MergingIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..05ec86a9f36c68f08d510faac583f1fb85ecd125
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$MergingIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators$PeekingImpl.class b/src/main/resources/org/python/google/common/collect/Iterators$PeekingImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..b270db7a84506faf20788ca14ac7b35b00e7edcb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators$PeekingImpl.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Iterators.class b/src/main/resources/org/python/google/common/collect/Iterators.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4178b68042bd149d5245e927017bbb1a0ffa508
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Iterators.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LexicographicalOrdering.class b/src/main/resources/org/python/google/common/collect/LexicographicalOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca290fcd8a08146ff6d51b7ae36487de57417559
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LexicographicalOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$1.class b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cdf95770f2284e1548b108c173f3b10dbea05ad
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueEntry.class b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..47596f630d039e79f1eff0451932c15ef32c98a9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSet$1.class b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..310a4cc0ca6b2a82cc8958450e1eaf0fba32c547
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSet.class b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c038387cc0a4aed4463aceede0d22c4533cfe53
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSetLink.class b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSetLink.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cde605cec1c86153c9042167d2e97c19a000e54
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap$ValueSetLink.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedHashMultimap.class b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..333fd658868f4ad5992792ad19df1fe55a2ff3ed
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedHashMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedHashMultiset.class b/src/main/resources/org/python/google/common/collect/LinkedHashMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc17a0d0242f781beb0b6b359dd43f4251b1cae8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedHashMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$1.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a679a67908b74c1bb5f9bf5f0ee8e9aa00d661d6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$2.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d45f54b413fbed6ca92b3750d468de296fcfb2a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$3$1.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$3$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..031a06bbea319c1452da0f91cf1303da5d86ef22
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$3$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$3.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..9295a862c0164bcacc8e08a11367ae69b522ab3f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$4.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..79e3dc369b996ef5da85e99683ea090729546db2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$5$1.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$5$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1aab7cfceb35c0d1d95014efc9deb33ffa55b8b8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$5$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$5.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..af656e4170ce0fff75e9e1d43963d1bdd7f1e86b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$5.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6$1$1.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8aa4a75caf8c73de8f494b2c9b5556e91ab9f010
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6$1.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c6199cae89db5d95e1d689900e407d268a8e31e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..9180a0bb1409189288af9ff02ac330a7b4481440
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$6.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$DistinctKeyIterator.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$DistinctKeyIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..d1533fd52c33f2655b29c46a742671b8589d0004
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$DistinctKeyIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$1$1.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8d146dbc7627999c5cdd651fd21d7963d0f6122
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$1.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e90fd99f695e0007c3769f31967ca445b77e82a3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$2.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..d30da1152d2d70a43d9a982f05d17e03e91a3776
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView.class
new file mode 100644
index 0000000000000000000000000000000000000000..57de665c2c4887cf16d56b9bdf794ba919d2be33
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$MultisetView.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$Node.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$Node.class
new file mode 100644
index 0000000000000000000000000000000000000000..22325cbf776a9a590608946c335d4fdebafa1d99
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$Node.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$NodeIterator.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$NodeIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6488858ddb074f9aaabb4de5cf45c40e466b0706
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$NodeIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap$ValueForKeyIterator.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$ValueForKeyIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a8615bb9c09d47904475bd3a312e738dbfe802b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap$ValueForKeyIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/LinkedListMultimap.class b/src/main/resources/org/python/google/common/collect/LinkedListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b5402de055497e48c5d84aec2ded519c21ee62f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/LinkedListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ListMultimap.class b/src/main/resources/org/python/google/common/collect/ListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..26bc53468efe3cc307f6dd4afc00f4cef480fa0b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$1.class b/src/main/resources/org/python/google/common/collect/Lists$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..03f373c649cad2a0117536b30b386507769300bd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$2.class b/src/main/resources/org/python/google/common/collect/Lists$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..6dbd216be24dfe0a943bf4c7d84664fd47fc79fb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$AbstractListWrapper.class b/src/main/resources/org/python/google/common/collect/Lists$AbstractListWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..d352b8bd8050ce18cb920934e4ae0d7c714ec3f4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$AbstractListWrapper.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$CharSequenceAsList.class b/src/main/resources/org/python/google/common/collect/Lists$CharSequenceAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1da28fad083907f59e76fbc8c29ed6086854165
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$CharSequenceAsList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$OnePlusArrayList.class b/src/main/resources/org/python/google/common/collect/Lists$OnePlusArrayList.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d7a04430ce2417c14b6461b72d653dce8390531
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$OnePlusArrayList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$Partition.class b/src/main/resources/org/python/google/common/collect/Lists$Partition.class
new file mode 100644
index 0000000000000000000000000000000000000000..dac08a6e11d66a43f60f1ace1bc9ad8d49ad23d8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$Partition.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$RandomAccessListWrapper.class b/src/main/resources/org/python/google/common/collect/Lists$RandomAccessListWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..b84ed51ea36de748fdf40d0e3cb13b276bee54ce
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$RandomAccessListWrapper.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$RandomAccessPartition.class b/src/main/resources/org/python/google/common/collect/Lists$RandomAccessPartition.class
new file mode 100644
index 0000000000000000000000000000000000000000..44c6b8e505a436985d65b3544c9a27f055ccf10d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$RandomAccessPartition.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$RandomAccessReverseList.class b/src/main/resources/org/python/google/common/collect/Lists$RandomAccessReverseList.class
new file mode 100644
index 0000000000000000000000000000000000000000..f15b3339ec3f230e758f40b0c8a68d7e596b76f8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$RandomAccessReverseList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$ReverseList$1.class b/src/main/resources/org/python/google/common/collect/Lists$ReverseList$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..84bba6c52ed851c911ead23f62115a7cde2a65a2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$ReverseList$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$ReverseList.class b/src/main/resources/org/python/google/common/collect/Lists$ReverseList.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed0f14f3c1232c87fab74e08ac13f6772a50c2e9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$ReverseList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$StringAsImmutableList.class b/src/main/resources/org/python/google/common/collect/Lists$StringAsImmutableList.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e1ce9f813c5115f9e62e3920e504383df4b5193
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$StringAsImmutableList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$TransformingRandomAccessList.class b/src/main/resources/org/python/google/common/collect/Lists$TransformingRandomAccessList.class
new file mode 100644
index 0000000000000000000000000000000000000000..e96caf77b5910a2654f5137578f47fcc8af10adc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$TransformingRandomAccessList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$TransformingSequentialList$1.class b/src/main/resources/org/python/google/common/collect/Lists$TransformingSequentialList$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca4b48a714675b2e02ff6b971ab21ed511bb2efb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$TransformingSequentialList$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$TransformingSequentialList.class b/src/main/resources/org/python/google/common/collect/Lists$TransformingSequentialList.class
new file mode 100644
index 0000000000000000000000000000000000000000..9bc1799e7a9e624c0d4abd8f7745c1eeb8ea74a7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$TransformingSequentialList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists$TwoPlusArrayList.class b/src/main/resources/org/python/google/common/collect/Lists$TwoPlusArrayList.class
new file mode 100644
index 0000000000000000000000000000000000000000..711ab52966af7184adc47aa07fde8b0126801243
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists$TwoPlusArrayList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Lists.class b/src/main/resources/org/python/google/common/collect/Lists.class
new file mode 100644
index 0000000000000000000000000000000000000000..26ecc1a8fb001346a9ea1809198fef39a036235a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Lists.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraint.class b/src/main/resources/org/python/google/common/collect/MapConstraint.class
new file mode 100644
index 0000000000000000000000000000000000000000..8db59e80bc5536219e21c0e3caddd69639dac979
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraint.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$1.class b/src/main/resources/org/python/google/common/collect/MapConstraints$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..77d8ee5365d2b0cc356774c300a8b9db0ba227f6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$2$1.class b/src/main/resources/org/python/google/common/collect/MapConstraints$2$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a682114015d897978686d7e6f4b5f31c92e2dd6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$2$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$2.class b/src/main/resources/org/python/google/common/collect/MapConstraints$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..1accaa4184a4a50fcf08ac46d533083a472fa761
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapEntries$1.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapEntries$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..903a2d95c6e85411e89d353a9c6c6c846dca2f76
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapEntries$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapEntries.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapEntries.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b1ab09e7826e03df6e195e11691e6b3143bfaee
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapEntries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapValues$1.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapValues$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e79a4bbec7ddc281964f72ace8cdad990a97359
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapValues$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapValues.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapValues.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8d218f078627d6f0c7e50fe2949e2b4461c2689
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedAsMapValues.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedBiMap.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae2c4f924bac7f49854d3f24e657e9727b5ef823
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntries$1.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntries$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a2a0fb998f501e1c0fa419a9f8bd6dab404909f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntries$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntries.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntries.class
new file mode 100644
index 0000000000000000000000000000000000000000..38aa438c1c956ea3824c488646d9f81ff02a017a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntrySet.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..699df4784da93907b3abc1c9d3a3a480c6881fd7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedEntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedListMultimap.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..435d6600e6f9eada9539af503d1d49822c95319f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMap.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..249ccb64d79924186712c69d6a0a32701324325c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap$1.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3e6969b85beec10b12334b522132ddcba8ed545
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap$2.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b78d26676ff6c9e66f22817136c9260cbba6457
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7b021737d808309f82d4919e841c874ae5f84bd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedSetMultimap.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d71026674d30ab74031d19718507d81b184a5b5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedSortedSetMultimap.class b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedSortedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..de76b29e04c965e536d71695a8064a10ca986f73
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$ConstrainedSortedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$InverseConstraint.class b/src/main/resources/org/python/google/common/collect/MapConstraints$InverseConstraint.class
new file mode 100644
index 0000000000000000000000000000000000000000..102489c9f272f8820a3c06a43ef84bac9f093df1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$InverseConstraint.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints$NotNullMapConstraint.class b/src/main/resources/org/python/google/common/collect/MapConstraints$NotNullMapConstraint.class
new file mode 100644
index 0000000000000000000000000000000000000000..b46c0d6f988eac9692480ed3909cc23eef220987
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints$NotNullMapConstraint.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapConstraints.class b/src/main/resources/org/python/google/common/collect/MapConstraints.class
new file mode 100644
index 0000000000000000000000000000000000000000..92fba84e53a5b6ea43e6278a90a73963e811635c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapConstraints.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapDifference$ValueDifference.class b/src/main/resources/org/python/google/common/collect/MapDifference$ValueDifference.class
new file mode 100644
index 0000000000000000000000000000000000000000..c54ba1860a9f89f4396b3583b4e54e9d8cb77bcb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapDifference$ValueDifference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapDifference.class b/src/main/resources/org/python/google/common/collect/MapDifference.class
new file mode 100644
index 0000000000000000000000000000000000000000..02a6d26144b2b31be2049bbc6755c4ae1b8929af
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapDifference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$1.class b/src/main/resources/org/python/google/common/collect/MapMaker$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..58678e018abb74ed49e39326291c72c9b5307858
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$NullComputingConcurrentMap.class b/src/main/resources/org/python/google/common/collect/MapMaker$NullComputingConcurrentMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..43958833ac942c5911638584d1102fe44bab6728
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$NullComputingConcurrentMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$NullConcurrentMap.class b/src/main/resources/org/python/google/common/collect/MapMaker$NullConcurrentMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..54c6d8d41321e4ad2d173f404780019eca03a5e6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$NullConcurrentMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$1.class b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0b2778118fe7a0f101e5de6e7ed922765d57860
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$2.class b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b043789a9704d3650ea49cec6999bfc06b4f1e9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$3.class b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..c599272f6fc00408051299326dcb36495f142222
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$4.class b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..068975965b9f6d59aff76d48ef4726a13a9d8007
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$5.class b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d28ebbd58f8eabc02ee519ef75b6427d3799ece
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause$5.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause.class b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1fda4c7183bb8ff0bb033d9f4e4707bd66118e5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalCause.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$RemovalListener.class b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..23c081db817b8592b8a2272ecba9852f57310708
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalListener.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker$RemovalNotification.class b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalNotification.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee6ad10fa353368bacb03351531e253256034e39
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker$RemovalNotification.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMaker.class b/src/main/resources/org/python/google/common/collect/MapMaker.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab6346fb31fe294629e36b26b50026f92f7b855b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMaker.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$1.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..78c3f86db8f588a388990ce4ddc5468b89823dfd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$2.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb1bb993cc942ec27858955d0e6dea9f566dd980
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$AbstractReferenceEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$AbstractReferenceEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..37785a675e34f11fd3c77064d767470df66e40d0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$AbstractReferenceEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$AbstractSerializationProxy.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$AbstractSerializationProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9388092150d38654833993fbca164656c0e55f9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$AbstractSerializationProxy.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$CleanupMapTask.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$CleanupMapTask.class
new file mode 100644
index 0000000000000000000000000000000000000000..7986b6a57209b7f4848a0074f436255d3bbe8c88
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$CleanupMapTask.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$1.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d7085098fde34fb9b21b89c94223035fe00812b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$10.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$10.class
new file mode 100644
index 0000000000000000000000000000000000000000..0483a2e4d412cbbd3ef71b2ab9be467febb998cb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$10.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$11.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$11.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5f9916a7cee2423d90c55ae71e2d4ad931aaf7b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$11.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$12.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$12.class
new file mode 100644
index 0000000000000000000000000000000000000000..802e2b3d9f9de23d9538baaa134ea779a8bd643a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$12.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$2.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..164a2ce7ccb862b0b94e01ae8ebc72cc8f05244b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$3.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e23c4dd7b09181925ef4c6752cf849f0661a021
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$4.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..36280ed74ff0051e99629dbea85366dc620efbd4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$5.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..03cc7dc69d972845cad7177e8e46ec1c6dde94f6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$5.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$6.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a75bef1ea0004e3cb15bb9d72b5b794ec4f08a3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$6.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$7.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..750304f19872bf9735491a99b93eca9b2bce6511
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$7.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$8.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..d10319074b98ac6bb8c1a1400cf26868df3d0a79
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$8.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$9.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$9.class
new file mode 100644
index 0000000000000000000000000000000000000000..71a127ea76789904cc0f21e2dec275560883cfde
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory$9.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..701ecf52ca9b85d5c71eea1e62e44172760f89e4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryFactory.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryIterator.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..09ec679635e64c22035ddde1c351661a089f0ecb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntryIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..95598db9ff366d5c0c236ab1f4786d4a7aad0b3b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue$1.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..49aeaf15cdc28277d12b51cfcd608fdc46ccbacf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue$2.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f3e4f14003e6662f91be44143c76b8345e66fc1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..c96683dfe2cb2f13c7b4a0a44747d825f7fae7d4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$EvictionQueue.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue$1.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5c53466e70dd9f1f23c3c78595ba4fd3c88bc0f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue$2.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b8fc36d2099fde970fffd162f93b8759417fd22
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..083cadc0ce0a6f5291e6a81edafb58763068f557
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ExpirationQueue.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$HashIterator.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$HashIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..62ed43b65b2129cc3b433b745ed76b8e43684430
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$HashIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$KeyIterator.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$KeyIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..c11b5a0b07e33d671c5546f402607170e8f98d73
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$KeyIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$KeySet.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$KeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..abc3c85f3ea29b02cb0b4a99a9c6d72fb637d380
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$KeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$NullEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$NullEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..5385e90352a0f3f4bced65343243d7be3f87f049
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$NullEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ReferenceEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ReferenceEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..e806b4ce9e765aa07bcc55919f57bcccdfbf18a5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ReferenceEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Segment.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Segment.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b60f7496306ac0b464c6f671e4fc6c97fc49897
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Segment.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SerializationProxy.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SerializationProxy.class
new file mode 100644
index 0000000000000000000000000000000000000000..8508f391eb3d4fe6504fe502bb0fb4539acc2bdb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SerializationProxy.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..681aa91286aad6288f7648cb3758a8f3578d5c10
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftEvictableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftEvictableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a73e6b455c6e00d9be1c02db15dc37ac19855af
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftEvictableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftExpirableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftExpirableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..3955c45657e31c4b7016c76ad16e315e0af87ade
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftExpirableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftExpirableEvictableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftExpirableEvictableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..049687c1e90887ee3e3d8931c7cfe8cb30ebf7eb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftExpirableEvictableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftValueReference.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b01622c12f9fccb9a59bd69a6ef7606bc923674
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$SoftValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$1.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..27512d3ad7228ab72409bd023c5f8e9dfbab682b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$2.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..0474f0a4f33abd4c568ee9f8dd07a3cd3c6e3c19
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$3.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..8aeed866e7c1a8643fee32b79aed2c4340b9cefe
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fd77687cc9ad5a5c474ab83df8132defa5aa579
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Strength.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..096ac32b899a60c51656049f9542ccf1add937f8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongEvictableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongEvictableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..36d71888932cf591c9f4e4b2316ecbcd9839cd4e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongEvictableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongExpirableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongExpirableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..83131e5f4258ddb4b10ef47f9dbf608655544a82
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongExpirableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongExpirableEvictableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongExpirableEvictableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..59b176b2ba07d41117500ebd8b8550b5087a62a2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongExpirableEvictableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongValueReference.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..356da45d26afcea3404f6f33456a0763292a35c1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$StrongValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ValueIterator.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ValueIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bacd97b3d174bdff24ae672a8c3fab0d78c8797
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ValueIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ValueReference.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..db2de853e6d165cdb31a79f64f1ece6c6a94592c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$ValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Values.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..9de3586d1ce20654a2f991e3e055df89ff2e16d8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..3854ebaecc0d0af7e554b30fb878227e3d7dfaf7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakEvictableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakEvictableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..4804c1cb447d30737d7b555c8b0f4d5725e8dda5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakEvictableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakExpirableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakExpirableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fee5529f3895aad0863fe620a99915782aedb8f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakExpirableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakExpirableEvictableEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakExpirableEvictableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..a79c51df91cab82602ea00cddf0f13f7af37f20a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakExpirableEvictableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakValueReference.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakValueReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb973cdb0dba4c27b4ab67091eae946668c8b1f5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WeakValueReference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WriteThroughEntry.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WriteThroughEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b6cd166bd825642aeece0bef71734610d4d42f6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap$WriteThroughEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MapMakerInternalMap.class b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..41d934262d73ef4c141d63d3a349073109ae645a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MapMakerInternalMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$1.class b/src/main/resources/org/python/google/common/collect/Maps$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..922daf21d623fbd80541b32c07fbfee37ac6a830
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$2.class b/src/main/resources/org/python/google/common/collect/Maps$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c7f8a91bfbfd1173ad972f3d73d908383e31c8f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$3.class b/src/main/resources/org/python/google/common/collect/Maps$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d05aaf1c65adf6e3d008c222b6dbf96c457fc4e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$4.class b/src/main/resources/org/python/google/common/collect/Maps$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..4c8c4be43de13579614e0214c774c54038656523
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$5.class b/src/main/resources/org/python/google/common/collect/Maps$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..a176c41387572b5845c6a95dc818fcd2042856d0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$5.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$6.class b/src/main/resources/org/python/google/common/collect/Maps$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..b75619bcb42b962b7d203ecd2c6ec91db91cd3a5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$6.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$7.class b/src/main/resources/org/python/google/common/collect/Maps$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..dce30f07df38bd09fb6221ad2446b5c1ffff108f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$7.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$8.class b/src/main/resources/org/python/google/common/collect/Maps$8.class
new file mode 100644
index 0000000000000000000000000000000000000000..165d3e1595c83558744a45b059cdc7c017adcefe
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$8.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$9.class b/src/main/resources/org/python/google/common/collect/Maps$9.class
new file mode 100644
index 0000000000000000000000000000000000000000..41383f289de07126b951821ca9adbdf4ecb1017e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$9.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap$Values$1.class b/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap$Values$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7943923da25d2e3d5567a723961553c09892c32
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap$Values$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap$Values.class b/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..46334874f6e0040c1203d978b6d922aeba62602c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap.class b/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..8316481666011e44790d35f47181353d56b3d622
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$AbstractFilteredMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$AsMapView$1.class b/src/main/resources/org/python/google/common/collect/Maps$AsMapView$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2ef8392996048c5c352e8f91b922e435fcbaf35
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$AsMapView$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$AsMapView$2$1.class b/src/main/resources/org/python/google/common/collect/Maps$AsMapView$2$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..71e31cd948eeb9b9476d5fecaadbb03dfc1c1817
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$AsMapView$2$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$AsMapView$2.class b/src/main/resources/org/python/google/common/collect/Maps$AsMapView$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfd6eee73501f4d9d10a49031ccf5e3b3566155d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$AsMapView$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$AsMapView.class b/src/main/resources/org/python/google/common/collect/Maps$AsMapView.class
new file mode 100644
index 0000000000000000000000000000000000000000..afa56e234e7df51c0ce847f708aef98d87aa7856
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$AsMapView.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$1.class b/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8c5bcda86563b10d57e2053a73215ac85fd35d9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$2.class b/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fd14afdea900e7b9309bf7e6a55b3228cfac299
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$3.class b/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c040069adc81754ebd53e445753e1c1230cfa71
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$DescendingMap$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$DescendingMap.class b/src/main/resources/org/python/google/common/collect/Maps$DescendingMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d4fdba2c1a94dc5b4ef035e7661d96eceed0646
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$DescendingMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$EntrySet.class b/src/main/resources/org/python/google/common/collect/Maps$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..65ec99622b40e4d573965f81ab043df4f1f3174c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$EntryTransformer.class b/src/main/resources/org/python/google/common/collect/Maps$EntryTransformer.class
new file mode 100644
index 0000000000000000000000000000000000000000..850d15e2208691951820b043ab76722e07ab83fe
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$EntryTransformer.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet$1$1.class b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..084d65ef9fd1c7a24d6392e96c6cb5410ad31f09
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a134a4b13b3edfb0e0c2d72b4009c63f6d6d8d29
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..37600130811a217352d2894689ab0d0ffc19f1da
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$KeySet$1.class b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$KeySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecf960f5a984f6dd983921a6b6821e317f5c3b6e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$KeySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$KeySet.class b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$KeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..0164fbef7740f99161fa587f4057e16a0482e412
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap$KeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap.class b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d9f2ac48afa9b3c7d5db6d5d676f79c9b812888
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntryMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$FilteredEntrySortedMap.class b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntrySortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..36a79450ceb73a8658ffdd6dcb3d43577240f9df
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$FilteredEntrySortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$FilteredKeyMap.class b/src/main/resources/org/python/google/common/collect/Maps$FilteredKeyMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2af6c56bd4163273f8417870f83ada5b54cf62b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$FilteredKeyMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap$1.class b/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..371db6ed637d9b72f7ca34ebafe22249e347cb48
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap$2.class b/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..59e6955e09d986212d463d50f885fab98a122275
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap.class b/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..d923b9605062a1d77195925670a72bb62218ef49
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$ImprovedAbstractMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$KeySet.class b/src/main/resources/org/python/google/common/collect/Maps$KeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a321a819ba0fd5a336955e8c1c217fd06b693f6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$KeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$MapDifferenceImpl.class b/src/main/resources/org/python/google/common/collect/Maps$MapDifferenceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..162ead3ee17b92a531b277e197511fc963c09d0c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$MapDifferenceImpl.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$NavigableKeySet.class b/src/main/resources/org/python/google/common/collect/Maps$NavigableKeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..12f1179adbd94e89acf3a501fe7b8b4949f91c4f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$NavigableKeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$SortedAsMapView.class b/src/main/resources/org/python/google/common/collect/Maps$SortedAsMapView.class
new file mode 100644
index 0000000000000000000000000000000000000000..28443f913ec71138f017c3a2f406bf7ccdba5060
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$SortedAsMapView.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$SortedMapDifferenceImpl.class b/src/main/resources/org/python/google/common/collect/Maps$SortedMapDifferenceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..f75958d678bcb84d3fc8c198593b4b0452e3e36f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$SortedMapDifferenceImpl.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1$1$1.class b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..dfe9d71c0c6a5bdb191f77c101865d3da9af2218
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1$1.class b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cae9224b8f4c36ab2139d024d0205e6f97d60ebc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1.class b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5218629aa4a791e2386eedeaab9daf5ea7615675
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$2.class b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..0507b17d9be3ed19a9478bff0244c3bb2ade227e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap.class b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..22a33408c5cc93db2e3105bdf8c5abcbc3253373
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesNavigableMap.class b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesNavigableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..5147c6e83644d9e1245e828574653f41000c2c65
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesNavigableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesSortedMap.class b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesSortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..50f8dcf115b316a86f903402730690cade3f1679
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$TransformedEntriesSortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableBiMap.class b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..8102ab497fa8de05c8ae92dcba94c3531e549cde
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntries$1.class b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntries$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..676e354fc9e2c79e761137005864704ef42ed43a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntries$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntries.class b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntries.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ad4b7b3194a991ee6b330960386d4d4bedd9a42
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntrySet.class b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fdd9fdaddda9bc1593b971a102b143969fbf478
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableEntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableNavigableMap.class b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableNavigableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..7084e23bd0bc73fb22e25c6573e76560e64a59e9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$UnmodifiableNavigableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$ValueDifferenceImpl.class b/src/main/resources/org/python/google/common/collect/Maps$ValueDifferenceImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..87e48830c9c752ee44d9e0ecda9df397a85ea899
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$ValueDifferenceImpl.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps$Values.class b/src/main/resources/org/python/google/common/collect/Maps$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..f82627d81414b31f1b8f77ed941ac1d8869e65b7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Maps.class b/src/main/resources/org/python/google/common/collect/Maps.class
new file mode 100644
index 0000000000000000000000000000000000000000..05cf420219bd65a01d0631e0b37d9a3b9f98c9b0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Maps.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$1.class b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e3564afa9f8516ab9ccbd0ecd240c2fdfdd9398
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$Builder.class b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..c29479a267a3c2c2ce7f8354a92318c48af58f80
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$Heap.class b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$Heap.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dd42acc751d610bcf107053812893971b02dd0c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$Heap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$MoveDesc.class b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$MoveDesc.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d0932c5f96e6788d4b7a37d6f6a002d35590179
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$MoveDesc.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$QueueIterator.class b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$QueueIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..15203d0f4c07cb1d4667f6b31419904f56bfdcfa
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue$QueueIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue.class b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..560933721e8e7654bf3b7f1aeb620f1527eba627
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MinMaxPriorityQueue.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimap.class b/src/main/resources/org/python/google/common/collect/Multimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8c6fd92172fa23e970e761a8e783ed4c899643e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a21bbaf243c9ee98802d3bd8aa0c93e829c024e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$2.class b/src/main/resources/org/python/google/common/collect/Multimaps$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..44c4faea51a67a3a29f64e55fed6f6dff4c87516
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$3.class b/src/main/resources/org/python/google/common/collect/Multimaps$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e83f592e50e468a2e9fc65cea42b706d1903026
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$4.class b/src/main/resources/org/python/google/common/collect/Multimaps$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e46d467056c585998cad4a6b631905a70b266b9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$5.class b/src/main/resources/org/python/google/common/collect/Multimaps$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab828502f98c05f1985c84bde957db3ae29fb064
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$5.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$AsMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/Multimaps$AsMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..bea2537787822cb3d5dfe17151ca924700724028
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$AsMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$AsMap.class b/src/main/resources/org/python/google/common/collect/Multimaps$AsMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..a723baf36dfbe64be063db29ee1abb3a550e140a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$AsMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$CustomListMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$CustomListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..54e2ba5ae5cc8ebff3d243a40416d387cc25e8db
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$CustomListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$CustomMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$CustomMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9681f258ed17fd2816535d17b5d2b0133bc292b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$CustomMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$CustomSetMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$CustomSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..92380a67b7b9f8106e82680d0bbb67137eb103b4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$CustomSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$CustomSortedSetMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$CustomSortedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..b0764477e66038a71c9dfffbfd3b80345c97b909
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$CustomSortedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$Entries.class b/src/main/resources/org/python/google/common/collect/Multimaps$Entries.class
new file mode 100644
index 0000000000000000000000000000000000000000..48e374d3cb3d5064607371e4678d2c7b2158f135
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$Entries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$EntrySet.class b/src/main/resources/org/python/google/common/collect/Multimaps$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c4b6f533afa352c75b28d10a373e3c1e8796569
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4187d9930112c46de8ca7de44e382ff9242f57a2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$2.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b6ef9757fdbdf394e0371d074dcf20bbc56d81c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa3bb680d788cc5bb6b9347c6f581e5e2942813f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..f08bc8541c6f6c05ab627c1688195ab604f000f2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$KeySet$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$KeySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..926f3b6b98e1cc20350960bfdfae5326d8bc00e7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$KeySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$KeySet.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$KeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..52af95a0a9903237b493d202abf9269421483903
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$KeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6933f28a705f9dc6bdac40a0a954addb33ef2539
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values$2.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b402b7dfad39513689c259a2ee601f180869f30
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..366ab1bca26bdbd19858441f16d09cd09c918dd8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..1bd919add85e83251cbd672e4ea7c95b5ba40b2a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$AsMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f61dc9f58098a993193b7e59543b22ede78e3894
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys$EntrySet.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbc76023086d1d62212b12f6c1d6a37a08989cf0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c3dec67d88c651d2056113ccea4ffff4bfdc61d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Keys.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$ValuePredicate.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$ValuePredicate.class
new file mode 100644
index 0000000000000000000000000000000000000000..1545bdecf08616fedabea86014c736f5bd39a770
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$ValuePredicate.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Values.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a6140e1c9941749189c280a53c66f2a069fdd7e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..05ec518dc60ae9ea9ef50d880c39feb1b7f49f9a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$FilteredMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$Keys$1$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$Keys$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a44d9b860300f970bb87f3905e1ac34baf7dc0c0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$Keys$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$Keys$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$Keys$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e653ddb8f0db20e4bb02deabc625f51c8638dc17
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$Keys$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$Keys$KeysEntrySet.class b/src/main/resources/org/python/google/common/collect/Multimaps$Keys$KeysEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..4dbe5720137a84da1c2a6dbffe30feef2f913ef3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$Keys$KeysEntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$Keys.class b/src/main/resources/org/python/google/common/collect/Multimaps$Keys.class
new file mode 100644
index 0000000000000000000000000000000000000000..80a97f051457e47e3bf732b9f9ed2694ff13d16a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$Keys.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$1$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..51e533a99407c9885228455f51066ffe7935ed01
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c8bda3d2d8cff211adebc0c8588c409cfa9450c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMap.class b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..39e827f55f5d4e9a84fbe1553b167ca07cd8c704
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries$1$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..568bbbb8b27d185eaabe3a47d7ba7a538f762cdc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..79e1c562108fe1d86675dedb5bc075a9b743dbd2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries.class b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries.class
new file mode 100644
index 0000000000000000000000000000000000000000..79a2a0edbc92d8f72159c5e7ce2963305b9b2923
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap$AsMapEntries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..77a67083d03cdb2e58fc5b3ac65e366a5271cdba
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$MapMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesListMultimap$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesListMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..24c048a1bd4d21d7f78862239d251f696afebe06
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesListMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesListMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..5020662a4deafd4c18e167d1267d961be7cd5257
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cb1e80d52594868aa3d7bc7355d0e3059d692bf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$2.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..5746c0e85e4bd2dfe7c30eaa6378d64aeb07e776
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$3.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..26a73676954afc7f3566e8e14d377ec174dbdb4a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries$1$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..73b0eca41004040286a6247395fb73688adbb2e2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6604522e7c5f2e2d187449b836c84dc333528b6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries.class
new file mode 100644
index 0000000000000000000000000000000000000000..f402ccf8fd8ce9ce0ead10e00adb12d9304b438c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap$TransformedEntries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..953e227b33879970a061aaf5ee6076d2cff82c19
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$TransformedEntriesMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapEntries$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapEntries$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba6d62b7dc1515c67fedc2827e1a7952e7ff9b69
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapEntries$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapEntries.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapEntries.class
new file mode 100644
index 0000000000000000000000000000000000000000..6511f746a9b3acfcfdc6138fd818343a40b936c7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapEntries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapValues$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapValues$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e33b1a1c0dff65dd415e4a65ab7b4cde809d9145
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapValues$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapValues.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapValues.class
new file mode 100644
index 0000000000000000000000000000000000000000..651e1e37b5b540bc2b65a45b067d0fd3a4d47de3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableAsMapValues.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableListMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..9328b7f5a421ff3ff25faa9f51fa6b03d0353cfe
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableMultimap$1.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableMultimap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd60bda161695fb10e84eece49db379e413846d2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableMultimap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..0188e1a198795c8e1b49b18cc56d1813202611d7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableSetMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e8da8fbaa720136e201e379ba2ef15cd906b5db
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableSortedSetMultimap.class b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableSortedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a5276f4ee5a9b14d280da37e866f37a0dae63d0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$UnmodifiableSortedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps$Values.class b/src/main/resources/org/python/google/common/collect/Multimaps$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fdad4a4dd34c627c1c7dec683d16f1c7860fadd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multimaps.class b/src/main/resources/org/python/google/common/collect/Multimaps.class
new file mode 100644
index 0000000000000000000000000000000000000000..63be2fad9cd905b1179012cb2186ac55f47e7013
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multimaps.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multiset$Entry.class b/src/main/resources/org/python/google/common/collect/Multiset$Entry.class
new file mode 100644
index 0000000000000000000000000000000000000000..6599492089236e53c32446a930ba4016dfef7683
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multiset$Entry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multiset.class b/src/main/resources/org/python/google/common/collect/Multiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a0437ac9f798b815b63709154078f6c450ec8bd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$1$1.class b/src/main/resources/org/python/google/common/collect/Multisets$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..773ccd9d3ad94f19d4989cc2fe52d4551eb80f1e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$1.class b/src/main/resources/org/python/google/common/collect/Multisets$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3e70cc0fa4d3f5bf54adc46606263c203c58da1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$2.class b/src/main/resources/org/python/google/common/collect/Multisets$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c68ca3d29b26503dc521f95d3493addf7265581f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$AbstractEntry.class b/src/main/resources/org/python/google/common/collect/Multisets$AbstractEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..87ea7c40c1d0998692698342f2088f731639dd95
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$AbstractEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$ElementSet$1.class b/src/main/resources/org/python/google/common/collect/Multisets$ElementSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a96a3dc062e5795ccca6234d80014b860727274f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$ElementSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$ElementSet.class b/src/main/resources/org/python/google/common/collect/Multisets$ElementSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..feb187fb55e2683985ecf98b21a7808ec2b1b99a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$ElementSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$EntrySet.class b/src/main/resources/org/python/google/common/collect/Multisets$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..97f5d2863f6242aa24ea92390cc21fde27bae1af
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$ImmutableEntry.class b/src/main/resources/org/python/google/common/collect/Multisets$ImmutableEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f85415e4aef6b38caf80d58d97ed124abf022dc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$ImmutableEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$MultisetIteratorImpl.class b/src/main/resources/org/python/google/common/collect/Multisets$MultisetIteratorImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..58ededdd4ddfd5c271632fe0a402b3288edff8eb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$MultisetIteratorImpl.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$1$1.class b/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3a25c56188e978a17c0311088c6dfd399b75fc8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$1.class b/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..294b7bd67e8a2447d3b3b8c35ad4bf5c2a85e69b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$ElementSet.class b/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$ElementSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5e9742c95cf3b3c391fbdba50e26af6da615792
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset$ElementSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset.class b/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..97834d6d4c92a0a719ca1191a356b26d82cff67f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$SetMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$UnmodifiableMultiset.class b/src/main/resources/org/python/google/common/collect/Multisets$UnmodifiableMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..2310196f941363a1c655fe5a83bd471b0a922645
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$UnmodifiableMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets$UnmodifiableSortedMultiset.class b/src/main/resources/org/python/google/common/collect/Multisets$UnmodifiableSortedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e198b06f7507c82bb1489235ff4d854fe9d5eca
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets$UnmodifiableSortedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Multisets.class b/src/main/resources/org/python/google/common/collect/Multisets.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bb7c291c19569af217d6b7f0598637a2fda8ec3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Multisets.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MutableClassToInstanceMap$1.class b/src/main/resources/org/python/google/common/collect/MutableClassToInstanceMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e23d60fc6dab28c75ec7dde2fd32c86fe872790
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MutableClassToInstanceMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/MutableClassToInstanceMap.class b/src/main/resources/org/python/google/common/collect/MutableClassToInstanceMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..583f1003d90f63b36e5c47dfa0ce49f88b4f70e5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/MutableClassToInstanceMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/NaturalOrdering.class b/src/main/resources/org/python/google/common/collect/NaturalOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb23b811eabaf73078d14d9072387276b260678c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/NaturalOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/NullsFirstOrdering.class b/src/main/resources/org/python/google/common/collect/NullsFirstOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..a594df2525f4e4558ed077ab6bedb01c13bf548d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/NullsFirstOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/NullsLastOrdering.class b/src/main/resources/org/python/google/common/collect/NullsLastOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..c930ff9e8a82e52bbbca6ddac70a023c5ad17952
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/NullsLastOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ObjectArrays.class b/src/main/resources/org/python/google/common/collect/ObjectArrays.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a0da04e0c693194c2af115bf056b7724dd77419
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ObjectArrays.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrdering$1.class b/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrdering$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8ef2469077e5729238d9b8ca38fb03db48e4cca
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrdering$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrdering.class b/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a7eb4095afec3ce332b2e46d5b7da85c87b2df5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrderingHolder.class b/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrderingHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..e772d780c85b4402c4713c25d7c071283cbab779
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Ordering$ArbitraryOrderingHolder.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Ordering$IncomparableValueException.class b/src/main/resources/org/python/google/common/collect/Ordering$IncomparableValueException.class
new file mode 100644
index 0000000000000000000000000000000000000000..6dafc8745fca26215a32847d337a846f9e219bec
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Ordering$IncomparableValueException.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Ordering.class b/src/main/resources/org/python/google/common/collect/Ordering.class
new file mode 100644
index 0000000000000000000000000000000000000000..47c9ea5118060c2cacf3f28cb4bc023e8a2a802a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Ordering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/PeekingIterator.class b/src/main/resources/org/python/google/common/collect/PeekingIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfa7f2bc3d7bdc82f2ad0e342f24242f793d425e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/PeekingIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Platform.class b/src/main/resources/org/python/google/common/collect/Platform.class
new file mode 100644
index 0000000000000000000000000000000000000000..96df37a396751296df622d8cf368d317b8f55467
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Platform.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Queues.class b/src/main/resources/org/python/google/common/collect/Queues.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bd4dcbc6ea3366149f8e16d590411493473e9ee
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Queues.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Range.class b/src/main/resources/org/python/google/common/collect/Range.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cc5337f87706610d1d4a93dcbf3f011dfc68bf0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Range.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RangeMap$RangeValue.class b/src/main/resources/org/python/google/common/collect/RangeMap$RangeValue.class
new file mode 100644
index 0000000000000000000000000000000000000000..db4b88c01e80a7d76c537d7def5ee64c64bbf3f1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RangeMap$RangeValue.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RangeMap.class b/src/main/resources/org/python/google/common/collect/RangeMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..7be1fe858eceea24eb6c06172e0353cdd46c2cfa
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RangeMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement$1$1.class b/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4731c4f4cd9ec1e6ab0b8494672589f80536b82
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement$1.class b/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..37fa71aae4a14a65fb69a264c3e2827e153ade7d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement.class b/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement.class
new file mode 100644
index 0000000000000000000000000000000000000000..001383c16df90eb7d5de3ff9379bdeb541cec8c6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RangeSet$StandardComplement.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RangeSet.class b/src/main/resources/org/python/google/common/collect/RangeSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..0eac740ec7a389a09663ff0e67a5d15d0e1658cd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RangeSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Ranges$1.class b/src/main/resources/org/python/google/common/collect/Ranges$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b45ae213fd4fd3f2ade8934de7a46967135aa7a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Ranges$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Ranges.class b/src/main/resources/org/python/google/common/collect/Ranges.class
new file mode 100644
index 0000000000000000000000000000000000000000..723116dc370759d8810e8e64d454b4b0f50075da
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Ranges.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularContiguousSet$1.class b/src/main/resources/org/python/google/common/collect/RegularContiguousSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8bf710dae8638b13e996b853062a2a2c0bed4d7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularContiguousSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularContiguousSet$DescendingContiguousSet$1.class b/src/main/resources/org/python/google/common/collect/RegularContiguousSet$DescendingContiguousSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea142736d02703c4c38fd6e070e0c0b5cf50ce68
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularContiguousSet$DescendingContiguousSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularContiguousSet$DescendingContiguousSet.class b/src/main/resources/org/python/google/common/collect/RegularContiguousSet$DescendingContiguousSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..24d54ae393c60e672273a5c30b724120693512b1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularContiguousSet$DescendingContiguousSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularContiguousSet$SerializedForm.class b/src/main/resources/org/python/google/common/collect/RegularContiguousSet$SerializedForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..31eb577962359b4d72ea75633705247014a3fa78
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularContiguousSet$SerializedForm.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularContiguousSet.class b/src/main/resources/org/python/google/common/collect/RegularContiguousSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..46c380f3b2b8cff01f0b1741d10ca83b757fbd48
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularContiguousSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableAsList.class b/src/main/resources/org/python/google/common/collect/RegularImmutableAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..048cd63faeacf9756ca6f3670c193fa9a5557189
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableAsList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableBiMap.class b/src/main/resources/org/python/google/common/collect/RegularImmutableBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..37ae85dded75e66f6c35ba61ec520680c037a5cd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableList.class b/src/main/resources/org/python/google/common/collect/RegularImmutableList.class
new file mode 100644
index 0000000000000000000000000000000000000000..49fce3d8d0332aa4c00ba481dc2b8b842423e81b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMap$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..80d973ccd75e8b79069bb85786cca27d0875e0f2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..c43cc57e01f83874b7c4535f983e8efbfb3d1812
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMap$LinkedEntry.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$LinkedEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4d9de03919d1af99b4bf3572b31640778e7ee13
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$LinkedEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMap$NonTerminalEntry.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$NonTerminalEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..de310afa986549012f15c3ffee335b51bf54a6a5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$NonTerminalEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMap$TerminalEntry.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$TerminalEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..90c31e2936ee1af026c6b75cb434df656e98cf2e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMap$TerminalEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMap.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..79ed4a13416fee9af1d03059e104095651eaaed9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..edf5ec05b8d5b369dbb3573d15e046a0016eec34
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a54c9745b778fac0c69e853a03a7ccab75356612
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$EntrySet.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..5434fc3a4f4de1f89367ec07cb7958b431b955c0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset.class b/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..02273df2170c5d63dfc5f649fcaf356b457ee1f1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSet.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..47c19c897456e221a3b7c090c052092335e60afc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd8c4803b1117434bc2ee01bb67da30d9981d1f8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f2f790afe8eb544bcfa321c48b646c871c8b56d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..22885c08c338b5bda5989fbbe688715c19b787ba
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..da401100a3057e6a4c09e382b45b855d8a58ea5e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e05d2b9fd07fc198516d31d489e68d08d754b8f0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a5aca13723c96264a6ea8bc92d5f5cfef23f409
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$EntrySet.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..93ea9d1560b779ac602eeb31404b7f07e6884232
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ecbd9a45f6eabc51ba65a060ce653b4871665d7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableSortedSet.class b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..407821718d937e8d9c8ff4610a1dbb9ab327bd92
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableSortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6d8fce2e84e3494fcdc137fa2f5f2afd34ac6e5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$2.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6ba0192253c98cc212b767506dceb44aa9a8850
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$Column.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$Column.class
new file mode 100644
index 0000000000000000000000000000000000000000..2657357a110a443cb83bb323f32aefe5ff35a551
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$Column.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$ColumnMap.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$ColumnMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..e1cd92ba93d005ff8a570762f9465ff75bccdf6f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$ColumnMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$Row.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$Row.class
new file mode 100644
index 0000000000000000000000000000000000000000..068c0b2d62508304a3766f70df8cd1642755fd33
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$Row.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$RowMap.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$RowMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..149bca5176a5776a3bdf7331608a42b336d23ade
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable$RowMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..2499870cddfa47142cea785b4919377b376e5570
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$DenseImmutableTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$1$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e06bf208f61d80486b95dcc809cbc017166a43e4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..60b9f3549223f9947d1a4b1dee3c1ba321918a83
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$2$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$2$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..682ff36ece531e357aaa583d8636a969c8285d7f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$2$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$2.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..5270904618ce92c388a234ab51ce5252713caef2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..957e9f6bc1799d659fb81fd644abff48b9f4992f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$ImmutableArrayMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$SparseImmutableTable$1.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$SparseImmutableTable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4cc348d5d1973d4a12102b75ed3f4811c050ef1b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$SparseImmutableTable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable$SparseImmutableTable.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$SparseImmutableTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0c459bc332870dcd37a8158617feb15933e6ab4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable$SparseImmutableTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RegularImmutableTable.class b/src/main/resources/org/python/google/common/collect/RegularImmutableTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..32ae9f80cef1a53cd1aed9f979b299a64f5149fc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RegularImmutableTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ReverseNaturalOrdering.class b/src/main/resources/org/python/google/common/collect/ReverseNaturalOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..518353e7f98561d39564dfc52eceeda2a5e79fac
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ReverseNaturalOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/ReverseOrdering.class b/src/main/resources/org/python/google/common/collect/ReverseOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e0c5057168ebc9ab82d2ee954737db6caf96952
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/ReverseOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/RowSortedTable.class b/src/main/resources/org/python/google/common/collect/RowSortedTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..b19f69c78408dd28b588bc28f30b7ff2d61dbc16
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/RowSortedTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Serialization$1.class b/src/main/resources/org/python/google/common/collect/Serialization$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7a1bf14588835fa1857fc0d13470a35715c844a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Serialization$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Serialization$FieldSetter.class b/src/main/resources/org/python/google/common/collect/Serialization$FieldSetter.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b33864aa7d86ad9c0fb369f2ff472df2dea5f84
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Serialization$FieldSetter.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Serialization.class b/src/main/resources/org/python/google/common/collect/Serialization.class
new file mode 100644
index 0000000000000000000000000000000000000000..d74b2d66a191655e9f48c2b546bcbfb9ea5a22f3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Serialization.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SetMultimap.class b/src/main/resources/org/python/google/common/collect/SetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..d66d3c99c22bbdf004a44877f2cf8727b7cad817
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$1.class b/src/main/resources/org/python/google/common/collect/Sets$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d5d9e44417a677f428a0c99c825a67ca5422f8f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$2.class b/src/main/resources/org/python/google/common/collect/Sets$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..33ad30239bb72415dfbd52eb89ec62f18bbe408b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$3.class b/src/main/resources/org/python/google/common/collect/Sets$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b4179a300d1f0172ed08a0d50f9398478e6b00a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$CartesianSet$1.class b/src/main/resources/org/python/google/common/collect/Sets$CartesianSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc544502a02cb7c8d6d2c4e2a3288394f88b1780
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$CartesianSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$CartesianSet$Axis.class b/src/main/resources/org/python/google/common/collect/Sets$CartesianSet$Axis.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc76806a7fe23ecfe1367494280f17b1565aa0bf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$CartesianSet$Axis.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$CartesianSet.class b/src/main/resources/org/python/google/common/collect/Sets$CartesianSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..eda1a39960bd7226774c22d0acf916f301da9eeb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$CartesianSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$DescendingSet.class b/src/main/resources/org/python/google/common/collect/Sets$DescendingSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff67555da95cb15fd2bea8df12028b8645dcafaf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$DescendingSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$FilteredSet.class b/src/main/resources/org/python/google/common/collect/Sets$FilteredSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ff473d3df5f504bfa898442ae20e606ef34b600
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$FilteredSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$FilteredSortedSet.class b/src/main/resources/org/python/google/common/collect/Sets$FilteredSortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..817cf6497b2e2732ef1d96c5fb72358e4700a56c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$FilteredSortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$ImprovedAbstractSet.class b/src/main/resources/org/python/google/common/collect/Sets$ImprovedAbstractSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3eed402845f133da37ed8884fb918f7a66421dd
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$ImprovedAbstractSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$PowerSet$1$1.class b/src/main/resources/org/python/google/common/collect/Sets$PowerSet$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..33c87fa63a8ab2826173f2fb704fbe6081880802
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$PowerSet$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$PowerSet$1.class b/src/main/resources/org/python/google/common/collect/Sets$PowerSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a7d75801c6bc8ae9503e4d2531b7d1048de0ee4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$PowerSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$PowerSet$BitFilteredSetIterator.class b/src/main/resources/org/python/google/common/collect/Sets$PowerSet$BitFilteredSetIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4a63715633be8d37e018d38081e2ae4352f5278
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$PowerSet$BitFilteredSetIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$PowerSet.class b/src/main/resources/org/python/google/common/collect/Sets$PowerSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccf1f514c3e0946537617b791ecc59c2b120a793
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$PowerSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$SetFromMap.class b/src/main/resources/org/python/google/common/collect/Sets$SetFromMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5e25e8533d776a32ddc8939fe268f7dcf5f48a0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$SetFromMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$SetView.class b/src/main/resources/org/python/google/common/collect/Sets$SetView.class
new file mode 100644
index 0000000000000000000000000000000000000000..49b6f0d45352094c7df8fcdf9cefcbb77538f5e3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$SetView.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets$UnmodifiableNavigableSet.class b/src/main/resources/org/python/google/common/collect/Sets$UnmodifiableNavigableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f907efc3f92cea9ff4bc1e517aabbd7e603f356
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets$UnmodifiableNavigableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Sets.class b/src/main/resources/org/python/google/common/collect/Sets.class
new file mode 100644
index 0000000000000000000000000000000000000000..7feb12030b00d54a6ff5eba023c15e7771592290
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Sets.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SingletonImmutableList.class b/src/main/resources/org/python/google/common/collect/SingletonImmutableList.class
new file mode 100644
index 0000000000000000000000000000000000000000..8841960b348fb27b719da8a0c697d5a2aec3492e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SingletonImmutableList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SingletonImmutableMap.class b/src/main/resources/org/python/google/common/collect/SingletonImmutableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..eec2da7c176f4f625e89b570ab0d7330794d5273
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SingletonImmutableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SingletonImmutableSet.class b/src/main/resources/org/python/google/common/collect/SingletonImmutableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..eab07a6ab9f0993204867079eb518981e3b4abde
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SingletonImmutableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SingletonImmutableTable.class b/src/main/resources/org/python/google/common/collect/SingletonImmutableTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..1942352d1d4e7137643c1b7cb514acb093c0f69f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SingletonImmutableTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedIterable.class b/src/main/resources/org/python/google/common/collect/SortedIterable.class
new file mode 100644
index 0000000000000000000000000000000000000000..e930d038eb56acb13f6b8b18e67aaeea593f0f2d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedIterable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedIterables.class b/src/main/resources/org/python/google/common/collect/SortedIterables.class
new file mode 100644
index 0000000000000000000000000000000000000000..8bff407f9ad78236358a03ae2b5d09bb76db0d37
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedIterables.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$1.class b/src/main/resources/org/python/google/common/collect/SortedLists$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ca87ed162e65a05c96559ba532608ff233ce37d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$1.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..92bfd947da9429c6fd3cd53c16a906ffb587b1b3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$2.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..898987ce68ee5a8414406f568e2b501432218080
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$3.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4235dbb04a4554c365b898b23123d213f39fa01
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior.class
new file mode 100644
index 0000000000000000000000000000000000000000..9097292965e6ba1bffd527412750c9955c2f2f09
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyAbsentBehavior.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$1.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e921e6f22a309532e43b96142c189cc3fa6de933
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$2.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..11853a458cbf9b8891a69c3e9f217bab7b7a0e9c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$3.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..d643e77d383da0cabb0dbad2ec4675e8b1d26c0d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$4.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..141eb30e5220020a4474d8b11114eb62a02e93ea
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$5.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..e657106156e046f1eb68604a9b4249eebff79c4b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior$5.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior.class b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e1614620a6c0b84cebae3bf3df8f18c45de9339
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists$KeyPresentBehavior.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedLists.class b/src/main/resources/org/python/google/common/collect/SortedLists.class
new file mode 100644
index 0000000000000000000000000000000000000000..4694f4380f1d8f569da60cbf1d3823a0b9b927c1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedLists.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedMapDifference.class b/src/main/resources/org/python/google/common/collect/SortedMapDifference.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f0cac1e2c7d073ad5ad45125cb1631f3f159268
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedMapDifference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedMultiset.class b/src/main/resources/org/python/google/common/collect/SortedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ef038f895264c718aee921cdc9c34872cc7edf8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset$1.class b/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..165e5095707b5ad50f26e2338ff2bfc324e142e0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset$2.class b/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4010df07970366d6eec6a9b362319f7044f94e8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset.class b/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2b6f9386f356d5aa7f72ff315d3b8d1820f2265
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedMultisets$DescendingMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedMultisets$ElementSet.class b/src/main/resources/org/python/google/common/collect/SortedMultisets$ElementSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..70173a674f0116757725ae455e6cfc09332238b0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedMultisets$ElementSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedMultisets.class b/src/main/resources/org/python/google/common/collect/SortedMultisets.class
new file mode 100644
index 0000000000000000000000000000000000000000..d578e6128af20f24f716f3a16fc710dc04546b9e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedMultisets.class differ
diff --git a/src/main/resources/org/python/google/common/collect/SortedSetMultimap.class b/src/main/resources/org/python/google/common/collect/SortedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..daf26415446dc10d81808930f5a524ba20703492
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/SortedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$1.class b/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2812c15ff07611e9306b97bca5bdc24e320c6b65
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$RowKeySortedSet.class b/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$RowKeySortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..89527df1f71d33a2e3204e08d55c8d26cae38e9c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$RowKeySortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$RowSortedMap.class b/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$RowSortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..6648b353019874ffb8c8793540b25cc89d35cd22
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardRowSortedTable$RowSortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardRowSortedTable.class b/src/main/resources/org/python/google/common/collect/StandardRowSortedTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8c2cbdc94f4fc47f04392c430c2a014717942cf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardRowSortedTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2fff7fea4c6e8a4f7e8dc1979c8cb09fc0f803e3
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$CellIterator.class b/src/main/resources/org/python/google/common/collect/StandardTable$CellIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..15d3f328d56bcdd619636e46082c6a994ce60ad2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$CellIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$CellSet.class b/src/main/resources/org/python/google/common/collect/StandardTable$CellSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a2f81e14fe56f660e7e46d89bf2e66ae29fb228
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$CellSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySet.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..92942972a61ea2e55e38ee8c82356d138dbc03f9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySetIterator$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySetIterator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd47bcd71cdaf7f161bba2e9a8891fc1f5eeca4b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySetIterator$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySetIterator.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySetIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ee33d64bbfd3d08e06c2c570dcdefd63fd02b66
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column$EntrySetIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column$KeySet$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column$KeySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0195ec1be8e32b9961d16650d1493a369188036
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column$KeySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column$KeySet.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column$KeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..78c1903105b7b97944f61d0ab5266fc9b18722b9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column$KeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f1d59ca57ea6f8f246093eb625956da6e38c55c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values$2.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..14eba697720aa0700defecb921d6bff19837f140
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..dffef33d5c06d4c146b8a998df4d07df9c724b23
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Column.class b/src/main/resources/org/python/google/common/collect/StandardTable$Column.class
new file mode 100644
index 0000000000000000000000000000000000000000..590352fc28eeeb2131184bd8b1ea41824f80194d
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Column.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$ColumnKeyIterator.class b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnKeyIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..288c85659c3a5ee1c7a9cfaafaf603c4abbb7782
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnKeyIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$ColumnKeySet.class b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnKeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b9c46e79d203fe433d1b8b394ad846b66afb2b4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnKeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapEntrySet$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapEntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..87ab8bc98c55563a1538988edabe6104ce66297c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapEntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapEntrySet.class b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5e9ce35bb58acc0a1c42873fc5beda1123d0626
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapEntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapValues.class b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapValues.class
new file mode 100644
index 0000000000000000000000000000000000000000..883dcd8f84589f70e4d6ca6639aa187fe896e539
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap$ColumnMapValues.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap.class b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..8dc9008ec794487ad6ef728a2876742494b46e1f
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$ColumnMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Row$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$Row$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba5556de2fa4adcf3bcf477decd0292c6c0e437b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Row$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet$1$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4d5903ac062d4243effc66d510cbfbe4dff12dc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ea66b4d8b0095971e391f69baf3827579e259e8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet.class b/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3dcae3a82768eae351eff4cda327392e8a11489
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Row$RowEntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Row.class b/src/main/resources/org/python/google/common/collect/StandardTable$Row.class
new file mode 100644
index 0000000000000000000000000000000000000000..225b5e28708ea0c04dded8546e6dc7bf9cd63560
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Row.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$RowKeySet.class b/src/main/resources/org/python/google/common/collect/StandardTable$RowKeySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccacf9abab9eee2287bcdb81222d2d014dc6c3a4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$RowKeySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$RowMap$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$RowMap$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c37c2cda018a0accbf4cbbe5775292c850eaa4b
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$RowMap$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$RowMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/StandardTable$RowMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb0986ab948a6cc6971e42550cb0c41b12a21ea0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$RowMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$RowMap.class b/src/main/resources/org/python/google/common/collect/StandardTable$RowMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fae315223f55f2c0174b7073a2ef503b884b4df
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$RowMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$TableCollection.class b/src/main/resources/org/python/google/common/collect/StandardTable$TableCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e1de2009d1ba6801d202135f1e669d1e8226fb4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$TableCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$TableSet.class b/src/main/resources/org/python/google/common/collect/StandardTable$TableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..f09a8343eea1ba94f7a5b363412af3464be3a8e5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$TableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Values$1.class b/src/main/resources/org/python/google/common/collect/StandardTable$Values$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..47a5dfc331333f6932a3e6a13273750423715914
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Values$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable$Values.class b/src/main/resources/org/python/google/common/collect/StandardTable$Values.class
new file mode 100644
index 0000000000000000000000000000000000000000..8845a59947dc5fc3fbd65e8b3090f19f0d56de7c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable$Values.class differ
diff --git a/src/main/resources/org/python/google/common/collect/StandardTable.class b/src/main/resources/org/python/google/common/collect/StandardTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbbd0e4436858069290c9b3849886055413ecf3c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/StandardTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$1.class b/src/main/resources/org/python/google/common/collect/Synchronized$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..91e0b7c5b6a74dde5740804706e7249c62b29785
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..5be42037b770e5907a239a7a156624ba0e5a38bb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries$1$1.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6eff1059b90ecaf58abd83b02153a97536c264cb
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries$1.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5de8ff4fabcca439aaa9298719c63bac28e43083
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb60caeab26e4f6b718084e7ebc14352c35f4577
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapEntries.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapValues$1.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapValues$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..60bc80670c7e3b5d09a443e8db5f73349a235f47
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapValues$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapValues.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapValues.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a9cb8c1c4ffa5a0c5ad49546e8d2927bbd5ed6c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedAsMapValues.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedBiMap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedBiMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e12e60bb18c4120d4d3d723745fa1aac5a85c27
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedBiMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedCollection.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e4dce12a7d4d85072058211a8c099cd555ab09a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedCollection.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedEntry.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..f329199716d244a5660e798d9eca38bb018d4df2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedEntry.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedList.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedList.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1e98b6e1ef814b909d375542c6447894007f2df
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedListMultimap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedListMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c0f8c1e1e19b8c0df9496aea7b7e84bfc9541e8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedListMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4379829a3dbf6c4d8109037d9c01cad7fa5e7ab
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMultimap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa411df5ca67dc3274aaf0696caa393b42e20c98
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMultiset.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ad4ea1e3417c5283e10aff78c4faf7d7f36c5cc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedNavigableMap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedNavigableMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..924de3b7e92fa26155ebfbf5f0a03bea490bde04
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedNavigableMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedNavigableSet.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedNavigableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..285b0ac56db35dc8cd83b3a47ea8fcf0cc059a41
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedNavigableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedObject.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..72db82b63dc2d386dbfd66da0944122f438f4ef0
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedObject.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedRandomAccessList.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedRandomAccessList.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dc6a435a8a113f13e3bdbfe756dac16dc3e85a7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedRandomAccessList.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSet.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b43248b68daca01716a9e985638fe1fbebd3fe7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSetMultimap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..9975c97ae56ec4fafe098400f87390bfd6cfe320
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedMap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..61f70db0fdd9ef4b8751bf61b4d01f20a12c8416
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedSet.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..063ce58746f19ceab1c41607f69f771a6a5c29c5
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedSetMultimap.class b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedSetMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..bdbc1550c1141b8339f77ed91a0940c25193952e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized$SynchronizedSortedSetMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Synchronized.class b/src/main/resources/org/python/google/common/collect/Synchronized.class
new file mode 100644
index 0000000000000000000000000000000000000000..87cf8d0ae44813f1e42a849851bcd0ca97b8f1da
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Synchronized.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Table$Cell.class b/src/main/resources/org/python/google/common/collect/Table$Cell.class
new file mode 100644
index 0000000000000000000000000000000000000000..27237d6d18dc795ce3e94641320c310495ea98b1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Table$Cell.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Table.class b/src/main/resources/org/python/google/common/collect/Table.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4faabe2383e1e0dd1a6acbe33591128e2913097
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Table.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$1.class b/src/main/resources/org/python/google/common/collect/Tables$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc431db0bd88a6114986547ffe5c73ca2dd6661c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$AbstractCell.class b/src/main/resources/org/python/google/common/collect/Tables$AbstractCell.class
new file mode 100644
index 0000000000000000000000000000000000000000..556d08bd888f2d7dac1f92fce2ba95de9e7b4ed7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$AbstractCell.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$ImmutableCell.class b/src/main/resources/org/python/google/common/collect/Tables$ImmutableCell.class
new file mode 100644
index 0000000000000000000000000000000000000000..33530b6f79802c2037175df13da65ec2c1c55351
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$ImmutableCell.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$1.class b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..35fd1831baecabf08a326a6b5f081d0b6818acff
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$2.class b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6eb683d466aa0358ff37d063503ac1df65f9078
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$3.class b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e0aeaddc774ad68cee28d9db06099ccdfefab52
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$CellSet.class b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$CellSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ca2e45e9b00eec043add3d7bf905f05304bd707
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable$CellSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$TransformedTable.class b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..185c06cf00ffa938def93ce90981362218c18c60
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$TransformedTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$TransposeTable$1.class b/src/main/resources/org/python/google/common/collect/Tables$TransposeTable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac3491b4f0c8e1d7e2e34240ab19bb86ff81abaf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$TransposeTable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$TransposeTable$CellSet.class b/src/main/resources/org/python/google/common/collect/Tables$TransposeTable$CellSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cf05d8cd6db50c23fb648deb419353a7801d9ef
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$TransposeTable$CellSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$TransposeTable.class b/src/main/resources/org/python/google/common/collect/Tables$TransposeTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..412201d37357d54a5a247343b64a15242941ce82
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$TransposeTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$UnmodifiableRowSortedMap.class b/src/main/resources/org/python/google/common/collect/Tables$UnmodifiableRowSortedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..3605df696b9189445e5462ac818f2c9ce68448e1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$UnmodifiableRowSortedMap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables$UnmodifiableTable.class b/src/main/resources/org/python/google/common/collect/Tables$UnmodifiableTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7709916caa51614fc5d8edb02c71621a6f725a8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables$UnmodifiableTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/Tables.class b/src/main/resources/org/python/google/common/collect/Tables.class
new file mode 100644
index 0000000000000000000000000000000000000000..667b6df6314928bc1f8d1ab9b39027e3b2e6f3a6
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/Tables.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TransformedImmutableSet$1.class b/src/main/resources/org/python/google/common/collect/TransformedImmutableSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c42fb79fc75235c5c0141d6028ef62845cec0baf
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TransformedImmutableSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TransformedImmutableSet.class b/src/main/resources/org/python/google/common/collect/TransformedImmutableSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..c928495827add6d1081ad8c9d9ba47c0075ba833
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TransformedImmutableSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TransformedIterator.class b/src/main/resources/org/python/google/common/collect/TransformedIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..f19fdc35e35665b5c26adc893377531b6214fbd7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TransformedIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TransformedListIterator.class b/src/main/resources/org/python/google/common/collect/TransformedListIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..346587e7f9b2f3ef64304ff2aeb3b27a54320056
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TransformedListIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeBasedTable$1.class b/src/main/resources/org/python/google/common/collect/TreeBasedTable$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0021e44c2f25c34891e03d74fb0b7036be5118bc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeBasedTable$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeBasedTable$2.class b/src/main/resources/org/python/google/common/collect/TreeBasedTable$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..8607c62a761cdd3902516a5276a5925974d618e1
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeBasedTable$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeBasedTable$Factory.class b/src/main/resources/org/python/google/common/collect/TreeBasedTable$Factory.class
new file mode 100644
index 0000000000000000000000000000000000000000..c41b5f84ae777863e2b8739a07b687d15a7f1137
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeBasedTable$Factory.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeBasedTable$TreeRow.class b/src/main/resources/org/python/google/common/collect/TreeBasedTable$TreeRow.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bced65044585bceb8c851057be4ca150ae75f2e
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeBasedTable$TreeRow.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeBasedTable.class b/src/main/resources/org/python/google/common/collect/TreeBasedTable.class
new file mode 100644
index 0000000000000000000000000000000000000000..467cad4b15b956254337fe4db350d8f5772c9a62
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeBasedTable.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultimap.class b/src/main/resources/org/python/google/common/collect/TreeMultimap.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba5a30a0a4eb3278ae1f35a59e641dd2044513e7
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultimap.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$1.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3444d9857cabe3628e2a61407a9cfc79a2003055
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$2.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..23f2dc55378ede7e983f988ae5cde7d849dd5136
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$3.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5ba2b04f69d4990bdb687cf724d4abc45a59682
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$3.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$4.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..24d25100d6944809b0c59f2b18f8262fb2ee9fbc
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$4.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate$1.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ee49897bb2c35dd33fb28525e0b91fda5ad6ed9
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate$2.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..19aa508a6980b679bfbcfdb0100278ed3e404d39
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate$2.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate.class
new file mode 100644
index 0000000000000000000000000000000000000000..c869dfcacbc4682624b64b6df526d62a237eb48c
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$Aggregate.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$AvlNode.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$AvlNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba69dd6fa44ca0d7d23d1d444a8e3ef81fefef05
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$AvlNode.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset$Reference.class b/src/main/resources/org/python/google/common/collect/TreeMultiset$Reference.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d4e0d713e8ef37c7af0ed1decd9efdcc42d0724
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset$Reference.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeMultiset.class b/src/main/resources/org/python/google/common/collect/TreeMultiset.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d6329eb9e6646f4e8be5952b10c1f9208eadd66
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeMultiset.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeRangeSet$AsRanges.class b/src/main/resources/org/python/google/common/collect/TreeRangeSet$AsRanges.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc6e6b6f066ea101583ec08f4dfb1176007f4f77
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeRangeSet$AsRanges.class differ
diff --git a/src/main/resources/org/python/google/common/collect/TreeRangeSet.class b/src/main/resources/org/python/google/common/collect/TreeRangeSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..e05e731053f4366d9a7e5a6dd2f94a5a6f496218
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/TreeRangeSet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/UnmodifiableIterator.class b/src/main/resources/org/python/google/common/collect/UnmodifiableIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f1e747d5a151de1e438463b39a3092db8f7021a
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/UnmodifiableIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/UnmodifiableListIterator.class b/src/main/resources/org/python/google/common/collect/UnmodifiableListIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..29c6509a7720918a4d9a62b8c9bef5d39e3044e8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/UnmodifiableListIterator.class differ
diff --git a/src/main/resources/org/python/google/common/collect/UsingToStringOrdering.class b/src/main/resources/org/python/google/common/collect/UsingToStringOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ac0f68c8beba16d32ea5da42779a46c801bc4a4
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/UsingToStringOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/collect/WellBehavedMap$1.class b/src/main/resources/org/python/google/common/collect/WellBehavedMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..aef6e8d31665fcbf5cab9ec65b0126211d5f66ee
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/WellBehavedMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet$1$1.class b/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8db3bfce236fcba15e35f6d0ec071d9fa894bc95
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet$1.class b/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c871dcff002df4c89b2a8e1abcad0d33ccf96c2
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet$1.class differ
diff --git a/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet.class b/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d75bdbb6c7850e33d14b9c21ce8e71a4ffd8095
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/WellBehavedMap$EntrySet.class differ
diff --git a/src/main/resources/org/python/google/common/collect/WellBehavedMap.class b/src/main/resources/org/python/google/common/collect/WellBehavedMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..952daec2dba4ec0a0fb4610eac81a73e1a5f9ee8
Binary files /dev/null and b/src/main/resources/org/python/google/common/collect/WellBehavedMap.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/AllowConcurrentEvents.class b/src/main/resources/org/python/google/common/eventbus/AllowConcurrentEvents.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a1800026b62465f7980a95640db2fb6fda59fa3
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/AllowConcurrentEvents.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/AnnotatedHandlerFinder.class b/src/main/resources/org/python/google/common/eventbus/AnnotatedHandlerFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..02d961344b426b3413c9fa8bbe52aa872a518350
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/AnnotatedHandlerFinder.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/AsyncEventBus$1.class b/src/main/resources/org/python/google/common/eventbus/AsyncEventBus$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..77354dbe34267136dd0a565d99b3403b4d1779f6
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/AsyncEventBus$1.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/AsyncEventBus.class b/src/main/resources/org/python/google/common/eventbus/AsyncEventBus.class
new file mode 100644
index 0000000000000000000000000000000000000000..6402d725b129620b6fb06d0330a30a2969c7adda
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/AsyncEventBus.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/DeadEvent.class b/src/main/resources/org/python/google/common/eventbus/DeadEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..72741cbe381425bce1de66bb8f25c74f900f59ca
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/DeadEvent.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/EventBus$1.class b/src/main/resources/org/python/google/common/eventbus/EventBus$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a5b83f606295949e21dc9488648b07686c271a3
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/EventBus$1.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/EventBus$2.class b/src/main/resources/org/python/google/common/eventbus/EventBus$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..d55ec48b07b05922b4d2eabec3387999c0fd3a6f
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/EventBus$2.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/EventBus$3.class b/src/main/resources/org/python/google/common/eventbus/EventBus$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..93a91c76f3e5151f3dbf26ced997b6d861d3cc18
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/EventBus$3.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/EventBus$4.class b/src/main/resources/org/python/google/common/eventbus/EventBus$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..00a90159f24089c29589070d98d33a61e4ab459a
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/EventBus$4.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/EventBus$EventWithHandler.class b/src/main/resources/org/python/google/common/eventbus/EventBus$EventWithHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..f64a7e8ad33396abb0ba865cb727f1a0c61a498d
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/EventBus$EventWithHandler.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/EventBus.class b/src/main/resources/org/python/google/common/eventbus/EventBus.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a592f6f16cf8323766ac550f8b0ed6730badb8c
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/EventBus.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/EventHandler.class b/src/main/resources/org/python/google/common/eventbus/EventHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..453360eeb83024274b056de6d810e398d9aeb705
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/EventHandler.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/HandlerFindingStrategy.class b/src/main/resources/org/python/google/common/eventbus/HandlerFindingStrategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..729fdae523b87668bf2c341454e20d9bdfcb51cd
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/HandlerFindingStrategy.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/Subscribe.class b/src/main/resources/org/python/google/common/eventbus/Subscribe.class
new file mode 100644
index 0000000000000000000000000000000000000000..332429b43e1af733e90b1631e52d8559103676b0
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/Subscribe.class differ
diff --git a/src/main/resources/org/python/google/common/eventbus/SynchronizedEventHandler.class b/src/main/resources/org/python/google/common/eventbus/SynchronizedEventHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf7e3b5829fd717290e961aaa7fd7f0ab49d51c5
Binary files /dev/null and b/src/main/resources/org/python/google/common/eventbus/SynchronizedEventHandler.class differ
diff --git a/src/main/resources/org/python/google/common/hash/AbstractCompositeHashFunction$1.class b/src/main/resources/org/python/google/common/hash/AbstractCompositeHashFunction$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b9cb8e52a4b2b6b947bd2828023dc8c59a48536
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/AbstractCompositeHashFunction$1.class differ
diff --git a/src/main/resources/org/python/google/common/hash/AbstractCompositeHashFunction.class b/src/main/resources/org/python/google/common/hash/AbstractCompositeHashFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c863dce1e6341674803ce366402de4810757f35
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/AbstractCompositeHashFunction.class differ
diff --git a/src/main/resources/org/python/google/common/hash/AbstractHasher.class b/src/main/resources/org/python/google/common/hash/AbstractHasher.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef5c4c24d3b25a0f5aaadb4a70ca08f8b66b63e8
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/AbstractHasher.class differ
diff --git a/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction$BufferingHasher.class b/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction$BufferingHasher.class
new file mode 100644
index 0000000000000000000000000000000000000000..0df7cf9a0a9eb4b97d2a6e543b07939501ea9d07
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction$BufferingHasher.class differ
diff --git a/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction$ExposedByteArrayOutputStream.class b/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction$ExposedByteArrayOutputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0e6849dfbdd29ed3875131fb0f60729ed3c7f3c
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction$ExposedByteArrayOutputStream.class differ
diff --git a/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction.class b/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..8fb28a020092d20f55daecc12096a126d2ddbff2
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/AbstractNonStreamingHashFunction.class differ
diff --git a/src/main/resources/org/python/google/common/hash/AbstractStreamingHashFunction$AbstractStreamingHasher.class b/src/main/resources/org/python/google/common/hash/AbstractStreamingHashFunction$AbstractStreamingHasher.class
new file mode 100644
index 0000000000000000000000000000000000000000..0009ed0cb44bb40b6e95032c6e813a339f989585
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/AbstractStreamingHashFunction$AbstractStreamingHasher.class differ
diff --git a/src/main/resources/org/python/google/common/hash/AbstractStreamingHashFunction.class b/src/main/resources/org/python/google/common/hash/AbstractStreamingHashFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..579b8326d7da830c4556db6ec6c011b66a371fbe
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/AbstractStreamingHashFunction.class differ
diff --git a/src/main/resources/org/python/google/common/hash/BloomFilter$1.class b/src/main/resources/org/python/google/common/hash/BloomFilter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b94c70f9f232f291715f04e866c1680632af361
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/BloomFilter$1.class differ
diff --git a/src/main/resources/org/python/google/common/hash/BloomFilter$SerialForm.class b/src/main/resources/org/python/google/common/hash/BloomFilter$SerialForm.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2835d84aacb16999d7e5efff3d84cf05e310e9f
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/BloomFilter$SerialForm.class differ
diff --git a/src/main/resources/org/python/google/common/hash/BloomFilter$Strategy.class b/src/main/resources/org/python/google/common/hash/BloomFilter$Strategy.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e28e940354f0340ca22f8200570487a40c23c0f
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/BloomFilter$Strategy.class differ
diff --git a/src/main/resources/org/python/google/common/hash/BloomFilter.class b/src/main/resources/org/python/google/common/hash/BloomFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..99cfc3ba00cd40a22de736c01afb7ad6c8973ce6
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/BloomFilter.class differ
diff --git a/src/main/resources/org/python/google/common/hash/BloomFilterStrategies$1.class b/src/main/resources/org/python/google/common/hash/BloomFilterStrategies$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c96fd214fdbdb204f577c2c060d2e05228ca0d9
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/BloomFilterStrategies$1.class differ
diff --git a/src/main/resources/org/python/google/common/hash/BloomFilterStrategies$BitArray.class b/src/main/resources/org/python/google/common/hash/BloomFilterStrategies$BitArray.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8ab2fc378d50f1ccff71abc60283f79e4a3977a
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/BloomFilterStrategies$BitArray.class differ
diff --git a/src/main/resources/org/python/google/common/hash/BloomFilterStrategies.class b/src/main/resources/org/python/google/common/hash/BloomFilterStrategies.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d49d4ce6218f542ebf584c8a4bf859628d93fa2
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/BloomFilterStrategies.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Funnel.class b/src/main/resources/org/python/google/common/hash/Funnel.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c0bc9aeb888c19a8a6e20792e6374760700aa5a
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Funnel.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Funnels$ByteArrayFunnel.class b/src/main/resources/org/python/google/common/hash/Funnels$ByteArrayFunnel.class
new file mode 100644
index 0000000000000000000000000000000000000000..d205284d032246964c787386ccc1cb1086297558
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Funnels$ByteArrayFunnel.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Funnels$IntegerFunnel.class b/src/main/resources/org/python/google/common/hash/Funnels$IntegerFunnel.class
new file mode 100644
index 0000000000000000000000000000000000000000..816b5c9fdabf6a2aa6c399d5f777f968e6905beb
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Funnels$IntegerFunnel.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Funnels$LongFunnel.class b/src/main/resources/org/python/google/common/hash/Funnels$LongFunnel.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d08cb1533e1e6ebbeebdad0c08354c773551dfb
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Funnels$LongFunnel.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Funnels$SinkAsStream.class b/src/main/resources/org/python/google/common/hash/Funnels$SinkAsStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc760ba992fdfa9d01271e4c2be2936e280c1800
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Funnels$SinkAsStream.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Funnels$StringFunnel.class b/src/main/resources/org/python/google/common/hash/Funnels$StringFunnel.class
new file mode 100644
index 0000000000000000000000000000000000000000..05f25820fc52714ea05fa58b6ec460eab17a3407
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Funnels$StringFunnel.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Funnels.class b/src/main/resources/org/python/google/common/hash/Funnels.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe4ddfe5ce912dcc346041016e113baaf9c4e1ea
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Funnels.class differ
diff --git a/src/main/resources/org/python/google/common/hash/HashCode.class b/src/main/resources/org/python/google/common/hash/HashCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..741225597910650d56ae1389c4268bb27065e033
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/HashCode.class differ
diff --git a/src/main/resources/org/python/google/common/hash/HashCodes$BytesHashCode.class b/src/main/resources/org/python/google/common/hash/HashCodes$BytesHashCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2fa2fc7e519515ac2317cdc3508a53dc9076bcb
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/HashCodes$BytesHashCode.class differ
diff --git a/src/main/resources/org/python/google/common/hash/HashCodes$IntHashCode.class b/src/main/resources/org/python/google/common/hash/HashCodes$IntHashCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..88c2070b32a7f3806fc8769d3d55f7473771865f
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/HashCodes$IntHashCode.class differ
diff --git a/src/main/resources/org/python/google/common/hash/HashCodes$LongHashCode.class b/src/main/resources/org/python/google/common/hash/HashCodes$LongHashCode.class
new file mode 100644
index 0000000000000000000000000000000000000000..933edbf4d669cc1adc18eb7cdb5f277f23a2a694
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/HashCodes$LongHashCode.class differ
diff --git a/src/main/resources/org/python/google/common/hash/HashCodes.class b/src/main/resources/org/python/google/common/hash/HashCodes.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fb6dfb2b4825225f6f07bae32532913cf828cf0
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/HashCodes.class differ
diff --git a/src/main/resources/org/python/google/common/hash/HashFunction.class b/src/main/resources/org/python/google/common/hash/HashFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..98d18725c9f3dc4f13aad844d3665b0b95376959
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/HashFunction.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Hasher.class b/src/main/resources/org/python/google/common/hash/Hasher.class
new file mode 100644
index 0000000000000000000000000000000000000000..47e5f4ce709a7c1d22215bee45cfae91d5de6321
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Hasher.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Hashing$ConcatenatedHashFunction.class b/src/main/resources/org/python/google/common/hash/Hashing$ConcatenatedHashFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..426f54e9cffa4c1ede3b8016323d14dc86aca5ad
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Hashing$ConcatenatedHashFunction.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Hashing$LinearCongruentialGenerator.class b/src/main/resources/org/python/google/common/hash/Hashing$LinearCongruentialGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d84ead602f41e5b49f4a0cf2326c0b40055b6d6
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Hashing$LinearCongruentialGenerator.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Hashing.class b/src/main/resources/org/python/google/common/hash/Hashing.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e38a1e35932ab5605144d84c0fe71e5b20bd81c
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Hashing.class differ
diff --git a/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction$1.class b/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..91345ae25aff699cb97e3b3346c1280547902146
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction$1.class differ
diff --git a/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction$MessageDigestHasher.class b/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction$MessageDigestHasher.class
new file mode 100644
index 0000000000000000000000000000000000000000..1acde7005c2dfcd68071865a3197a71d4a9a5bba
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction$MessageDigestHasher.class differ
diff --git a/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction.class b/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..338a9534fa68a6029b0ad2809d2ca93df180b1ae
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/MessageDigestHashFunction.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Murmur3_128HashFunction$Murmur3_128Hasher.class b/src/main/resources/org/python/google/common/hash/Murmur3_128HashFunction$Murmur3_128Hasher.class
new file mode 100644
index 0000000000000000000000000000000000000000..3928492c09ead0e961fc1ba6a87b983dc8889bec
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Murmur3_128HashFunction$Murmur3_128Hasher.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Murmur3_128HashFunction.class b/src/main/resources/org/python/google/common/hash/Murmur3_128HashFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3bc282c5848a8ab67ea87554a7b9d930f631f66
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Murmur3_128HashFunction.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Murmur3_32HashFunction$Murmur3_32Hasher.class b/src/main/resources/org/python/google/common/hash/Murmur3_32HashFunction$Murmur3_32Hasher.class
new file mode 100644
index 0000000000000000000000000000000000000000..0904db23df55f79c76fe88ff0a12e538433c0680
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Murmur3_32HashFunction$Murmur3_32Hasher.class differ
diff --git a/src/main/resources/org/python/google/common/hash/Murmur3_32HashFunction.class b/src/main/resources/org/python/google/common/hash/Murmur3_32HashFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..704156ec016420daeb525ff6f335752ddbbb41ba
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/Murmur3_32HashFunction.class differ
diff --git a/src/main/resources/org/python/google/common/hash/PrimitiveSink.class b/src/main/resources/org/python/google/common/hash/PrimitiveSink.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7a391a4b93a89821933a3f79438b82812352111
Binary files /dev/null and b/src/main/resources/org/python/google/common/hash/PrimitiveSink.class differ
diff --git a/src/main/resources/org/python/google/common/io/AppendableWriter.class b/src/main/resources/org/python/google/common/io/AppendableWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a93f43af1b6d5d811ec59f689bd76349624e51d
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/AppendableWriter.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteArrayDataInput.class b/src/main/resources/org/python/google/common/io/ByteArrayDataInput.class
new file mode 100644
index 0000000000000000000000000000000000000000..a76c0a7b438d1ed0e51fa080ac33114c8b583387
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteArrayDataInput.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteArrayDataOutput.class b/src/main/resources/org/python/google/common/io/ByteArrayDataOutput.class
new file mode 100644
index 0000000000000000000000000000000000000000..dc9c48d74e00e5c3d41b0fdcf036a27112deed35
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteArrayDataOutput.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteProcessor.class b/src/main/resources/org/python/google/common/io/ByteProcessor.class
new file mode 100644
index 0000000000000000000000000000000000000000..713043b7a6ce5352d244255566b01d4d48cac0f8
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteProcessor.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteStreams$1.class b/src/main/resources/org/python/google/common/io/ByteStreams$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0798f1eca2b3f2fff9cca7bebe1b9dc6a98d0bcd
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteStreams$1.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteStreams$2.class b/src/main/resources/org/python/google/common/io/ByteStreams$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..013fee5e1869a7d1bb669875c221bfac59bab3b0
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteStreams$2.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteStreams$3.class b/src/main/resources/org/python/google/common/io/ByteStreams$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..41014b4d5ded6fcd62c5b7a78b264c2aaac20da1
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteStreams$3.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteStreams$4.class b/src/main/resources/org/python/google/common/io/ByteStreams$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..9216c77182dcb8200f3390b72fae8c1d4c244b36
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteStreams$4.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteStreams$ByteArrayDataInputStream.class b/src/main/resources/org/python/google/common/io/ByteStreams$ByteArrayDataInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecbd61602bfcd9529443291b836b17fb6e972b46
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteStreams$ByteArrayDataInputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteStreams$ByteArrayDataOutputStream.class b/src/main/resources/org/python/google/common/io/ByteStreams$ByteArrayDataOutputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ccf3b5f87b01a44d8dac29da44c47a937d8e11a
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteStreams$ByteArrayDataOutputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/ByteStreams.class b/src/main/resources/org/python/google/common/io/ByteStreams.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d668227ef2475bfae522a0974435a80c51c295d
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/ByteStreams.class differ
diff --git a/src/main/resources/org/python/google/common/io/CharStreams$1.class b/src/main/resources/org/python/google/common/io/CharStreams$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5908760bd13e63a35f0ab0892b850262f840cedc
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/CharStreams$1.class differ
diff --git a/src/main/resources/org/python/google/common/io/CharStreams$2.class b/src/main/resources/org/python/google/common/io/CharStreams$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..35325125429040e2e71ed721b9cd7687c3201987
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/CharStreams$2.class differ
diff --git a/src/main/resources/org/python/google/common/io/CharStreams$3.class b/src/main/resources/org/python/google/common/io/CharStreams$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..693a74f2522303ad0f82ecb3c2d67765cf39ddbd
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/CharStreams$3.class differ
diff --git a/src/main/resources/org/python/google/common/io/CharStreams$4.class b/src/main/resources/org/python/google/common/io/CharStreams$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b54264c31b4dbadeef56683aedab7bf30b25b4b
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/CharStreams$4.class differ
diff --git a/src/main/resources/org/python/google/common/io/CharStreams.class b/src/main/resources/org/python/google/common/io/CharStreams.class
new file mode 100644
index 0000000000000000000000000000000000000000..4dc080caca998418c47bba17d19e9de367a4bcb7
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/CharStreams.class differ
diff --git a/src/main/resources/org/python/google/common/io/Closeables.class b/src/main/resources/org/python/google/common/io/Closeables.class
new file mode 100644
index 0000000000000000000000000000000000000000..5aa8e89364781ea9180f72dc643723a26a2cf381
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/Closeables.class differ
diff --git a/src/main/resources/org/python/google/common/io/CountingInputStream.class b/src/main/resources/org/python/google/common/io/CountingInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..9db8d0eda6df3a3027f50a574027e921cd1c3505
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/CountingInputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/CountingOutputStream.class b/src/main/resources/org/python/google/common/io/CountingOutputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..9376c9c97aa0bd4da7dca29dc170198dc0ccac57
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/CountingOutputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/FileBackedOutputStream$1.class b/src/main/resources/org/python/google/common/io/FileBackedOutputStream$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d5d72b804f5176b25ad3058381a819c17f26636
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/FileBackedOutputStream$1.class differ
diff --git a/src/main/resources/org/python/google/common/io/FileBackedOutputStream$2.class b/src/main/resources/org/python/google/common/io/FileBackedOutputStream$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba5a81c5a200ac91b6691f427fceefae6ea2c9bc
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/FileBackedOutputStream$2.class differ
diff --git a/src/main/resources/org/python/google/common/io/FileBackedOutputStream$MemoryOutput.class b/src/main/resources/org/python/google/common/io/FileBackedOutputStream$MemoryOutput.class
new file mode 100644
index 0000000000000000000000000000000000000000..d493bd490a33dbe3235dc3bbd0321d8d42989099
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/FileBackedOutputStream$MemoryOutput.class differ
diff --git a/src/main/resources/org/python/google/common/io/FileBackedOutputStream.class b/src/main/resources/org/python/google/common/io/FileBackedOutputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..c74cd828f3e3a6e655ad75a0898c9a09f6641cd5
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/FileBackedOutputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/Files$1.class b/src/main/resources/org/python/google/common/io/Files$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f898a468b43ae8e03abba7b0f205141d3c44c9c3
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/Files$1.class differ
diff --git a/src/main/resources/org/python/google/common/io/Files$2.class b/src/main/resources/org/python/google/common/io/Files$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..6a9d2c5b6aefda8a7d0aba603af7e946f8e78136
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/Files$2.class differ
diff --git a/src/main/resources/org/python/google/common/io/Files.class b/src/main/resources/org/python/google/common/io/Files.class
new file mode 100644
index 0000000000000000000000000000000000000000..b765a30beee2302f2f687eab8e9ab6fc01647518
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/Files.class differ
diff --git a/src/main/resources/org/python/google/common/io/Flushables.class b/src/main/resources/org/python/google/common/io/Flushables.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e61052283a6201659a2649c26c5bd12513a2a70
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/Flushables.class differ
diff --git a/src/main/resources/org/python/google/common/io/InputSupplier.class b/src/main/resources/org/python/google/common/io/InputSupplier.class
new file mode 100644
index 0000000000000000000000000000000000000000..fdd113521babe4343653d565f99088a731ee462b
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/InputSupplier.class differ
diff --git a/src/main/resources/org/python/google/common/io/LimitInputStream.class b/src/main/resources/org/python/google/common/io/LimitInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..7047a248f7b3a0b0300cf1bf7b15348c537818ce
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/LimitInputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/LineBuffer.class b/src/main/resources/org/python/google/common/io/LineBuffer.class
new file mode 100644
index 0000000000000000000000000000000000000000..13df316854d9a905118c7822d35b294527e21211
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/LineBuffer.class differ
diff --git a/src/main/resources/org/python/google/common/io/LineProcessor.class b/src/main/resources/org/python/google/common/io/LineProcessor.class
new file mode 100644
index 0000000000000000000000000000000000000000..707a2c1174aa9644e8d786a4ba6a0eb64758ef65
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/LineProcessor.class differ
diff --git a/src/main/resources/org/python/google/common/io/LineReader$1.class b/src/main/resources/org/python/google/common/io/LineReader$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0805a85598899f433b6b2f2e714b5119d9271d24
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/LineReader$1.class differ
diff --git a/src/main/resources/org/python/google/common/io/LineReader.class b/src/main/resources/org/python/google/common/io/LineReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..e9aa63856399a0469903a81cb80028303f5419e1
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/LineReader.class differ
diff --git a/src/main/resources/org/python/google/common/io/LittleEndianDataInputStream.class b/src/main/resources/org/python/google/common/io/LittleEndianDataInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6bbff381dab9e13ba084a24d96d178b4cf9cc4e
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/LittleEndianDataInputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/LittleEndianDataOutputStream.class b/src/main/resources/org/python/google/common/io/LittleEndianDataOutputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c0a6c4796eec839e75c21de22217d6c0ae70c3d
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/LittleEndianDataOutputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/MultiInputStream.class b/src/main/resources/org/python/google/common/io/MultiInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8c8f010855bb236839f26f25653271d96e300b4
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/MultiInputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/MultiReader.class b/src/main/resources/org/python/google/common/io/MultiReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..71357b3a75c6fe75fcc9727103a3feaebfd4d2ca
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/MultiReader.class differ
diff --git a/src/main/resources/org/python/google/common/io/NullOutputStream.class b/src/main/resources/org/python/google/common/io/NullOutputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..61f534748f606babd1a3f8cfdb502ed134b7db1b
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/NullOutputStream.class differ
diff --git a/src/main/resources/org/python/google/common/io/OutputSupplier.class b/src/main/resources/org/python/google/common/io/OutputSupplier.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c3f292dec3c6e4621ae368ba452d37a31b1d0ac
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/OutputSupplier.class differ
diff --git a/src/main/resources/org/python/google/common/io/PatternFilenameFilter.class b/src/main/resources/org/python/google/common/io/PatternFilenameFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..571f283025a7f7fadefeff7ca03dc23f18b7786a
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/PatternFilenameFilter.class differ
diff --git a/src/main/resources/org/python/google/common/io/Resources$1.class b/src/main/resources/org/python/google/common/io/Resources$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc00bb112e6cff393d2dfc4631dbdd180fe6e474
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/Resources$1.class differ
diff --git a/src/main/resources/org/python/google/common/io/Resources.class b/src/main/resources/org/python/google/common/io/Resources.class
new file mode 100644
index 0000000000000000000000000000000000000000..92152be59974ab4ed62e8c894b33095b85e49aa5
Binary files /dev/null and b/src/main/resources/org/python/google/common/io/Resources.class differ
diff --git a/src/main/resources/org/python/google/common/math/BigIntegerMath$1.class b/src/main/resources/org/python/google/common/math/BigIntegerMath$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcc29aa88e23d656836a32352feb6a81e0c178ed
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/BigIntegerMath$1.class differ
diff --git a/src/main/resources/org/python/google/common/math/BigIntegerMath.class b/src/main/resources/org/python/google/common/math/BigIntegerMath.class
new file mode 100644
index 0000000000000000000000000000000000000000..822afd8f188a8e32b43800284993f9a999ad09e8
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/BigIntegerMath.class differ
diff --git a/src/main/resources/org/python/google/common/math/DoubleMath$1.class b/src/main/resources/org/python/google/common/math/DoubleMath$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6c56743cc5eeb7a355d60a82a3fc3625d935d4c
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/DoubleMath$1.class differ
diff --git a/src/main/resources/org/python/google/common/math/DoubleMath.class b/src/main/resources/org/python/google/common/math/DoubleMath.class
new file mode 100644
index 0000000000000000000000000000000000000000..726f3ee0365fbebdd4f9d862442ea62bb7623188
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/DoubleMath.class differ
diff --git a/src/main/resources/org/python/google/common/math/DoubleUtils.class b/src/main/resources/org/python/google/common/math/DoubleUtils.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b76821aa8e52e088e692449df27f8bb1daf76f5
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/DoubleUtils.class differ
diff --git a/src/main/resources/org/python/google/common/math/IntMath$1.class b/src/main/resources/org/python/google/common/math/IntMath$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0165fe1002da86c610889b558d8d7c53cbd5eeed
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/IntMath$1.class differ
diff --git a/src/main/resources/org/python/google/common/math/IntMath.class b/src/main/resources/org/python/google/common/math/IntMath.class
new file mode 100644
index 0000000000000000000000000000000000000000..397c2bd585447823b5e146f5496128a7063cc1d5
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/IntMath.class differ
diff --git a/src/main/resources/org/python/google/common/math/LongMath$1.class b/src/main/resources/org/python/google/common/math/LongMath$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf227c969c25ae24e32479643e5f766ea8a7d0e1
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/LongMath$1.class differ
diff --git a/src/main/resources/org/python/google/common/math/LongMath.class b/src/main/resources/org/python/google/common/math/LongMath.class
new file mode 100644
index 0000000000000000000000000000000000000000..e48edba6f46cb8f1adac2f3774f8c323be2c2ecc
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/LongMath.class differ
diff --git a/src/main/resources/org/python/google/common/math/MathPreconditions.class b/src/main/resources/org/python/google/common/math/MathPreconditions.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbd358a1dd9c3b36c074ee07f16ed22ff5f533b4
Binary files /dev/null and b/src/main/resources/org/python/google/common/math/MathPreconditions.class differ
diff --git a/src/main/resources/org/python/google/common/net/HostAndPort.class b/src/main/resources/org/python/google/common/net/HostAndPort.class
new file mode 100644
index 0000000000000000000000000000000000000000..da4de1ab37b0908b30bfbf3ef0e35d24ec02b68f
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/HostAndPort.class differ
diff --git a/src/main/resources/org/python/google/common/net/HostSpecifier.class b/src/main/resources/org/python/google/common/net/HostSpecifier.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cc2cb86d7b07721d4a3677f1d6799262ba5e2b1
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/HostSpecifier.class differ
diff --git a/src/main/resources/org/python/google/common/net/HttpHeaders.class b/src/main/resources/org/python/google/common/net/HttpHeaders.class
new file mode 100644
index 0000000000000000000000000000000000000000..67200738b44001f571c7fc218436fe594d271ea9
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/HttpHeaders.class differ
diff --git a/src/main/resources/org/python/google/common/net/InetAddresses$TeredoInfo.class b/src/main/resources/org/python/google/common/net/InetAddresses$TeredoInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..49d79186a6d86771601f357b4612aebf2ecccecf
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/InetAddresses$TeredoInfo.class differ
diff --git a/src/main/resources/org/python/google/common/net/InetAddresses.class b/src/main/resources/org/python/google/common/net/InetAddresses.class
new file mode 100644
index 0000000000000000000000000000000000000000..6cec7807424d93e31085d5ec435b0f172bfe3b42
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/InetAddresses.class differ
diff --git a/src/main/resources/org/python/google/common/net/InternetDomainName.class b/src/main/resources/org/python/google/common/net/InternetDomainName.class
new file mode 100644
index 0000000000000000000000000000000000000000..c412e780ef5fd1d634d59e1220d8b9d02269d59c
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/InternetDomainName.class differ
diff --git a/src/main/resources/org/python/google/common/net/MediaType$1.class b/src/main/resources/org/python/google/common/net/MediaType$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3398a6156f1d050dafe601134dcfcb8ab90cdc5
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/MediaType$1.class differ
diff --git a/src/main/resources/org/python/google/common/net/MediaType$2.class b/src/main/resources/org/python/google/common/net/MediaType$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb5f4d8acb5ab4ed1e42317cd37cfb0d2702def2
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/MediaType$2.class differ
diff --git a/src/main/resources/org/python/google/common/net/MediaType$Tokenizer.class b/src/main/resources/org/python/google/common/net/MediaType$Tokenizer.class
new file mode 100644
index 0000000000000000000000000000000000000000..463c50892a201f590ea7461fa4a1083aa966a1ee
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/MediaType$Tokenizer.class differ
diff --git a/src/main/resources/org/python/google/common/net/MediaType.class b/src/main/resources/org/python/google/common/net/MediaType.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9aafa0431e0d05bd4b51edfc6ac9ce2d921a7e5
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/MediaType.class differ
diff --git a/src/main/resources/org/python/google/common/net/TldPatterns.class b/src/main/resources/org/python/google/common/net/TldPatterns.class
new file mode 100644
index 0000000000000000000000000000000000000000..b53ec9a869dccdbc67eaec6d0f0d1f9ae5aecd5e
Binary files /dev/null and b/src/main/resources/org/python/google/common/net/TldPatterns.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/AndroidInteger.class b/src/main/resources/org/python/google/common/primitives/AndroidInteger.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a39b261983cd9aaede6de7dbd09f65855df7503
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/AndroidInteger.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Booleans$BooleanArrayAsList.class b/src/main/resources/org/python/google/common/primitives/Booleans$BooleanArrayAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c31b7dfee4b92ab8532b584920b69d9ed5e9643
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Booleans$BooleanArrayAsList.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Booleans$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/Booleans$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..d60c5be4baca255997ec870066f6be080b7e26b0
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Booleans$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Booleans.class b/src/main/resources/org/python/google/common/primitives/Booleans.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b39cc9b14b1e262b3ec63382646191e8ca06455
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Booleans.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Bytes$ByteArrayAsList.class b/src/main/resources/org/python/google/common/primitives/Bytes$ByteArrayAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..e92e281a352a56f177e104e0fb801faadc01f40a
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Bytes$ByteArrayAsList.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Bytes.class b/src/main/resources/org/python/google/common/primitives/Bytes.class
new file mode 100644
index 0000000000000000000000000000000000000000..30fd97a05965bd1180f504adc7b12eadf77c549f
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Bytes.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Chars$CharArrayAsList.class b/src/main/resources/org/python/google/common/primitives/Chars$CharArrayAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..634dc42c2f7d7a320239df572f5f6ac3de8d6e56
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Chars$CharArrayAsList.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Chars$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/Chars$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e2f50420d3025511e5c4e125634b1ba5931bf2e
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Chars$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Chars.class b/src/main/resources/org/python/google/common/primitives/Chars.class
new file mode 100644
index 0000000000000000000000000000000000000000..98bda21c5682accac2cdf739d8d6e17014d846b2
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Chars.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Doubles$DoubleArrayAsList.class b/src/main/resources/org/python/google/common/primitives/Doubles$DoubleArrayAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b06d96b2ad1896729b35500695ae014b33a3e18
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Doubles$DoubleArrayAsList.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Doubles$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/Doubles$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..91157b6f6b249ac07be70b29d892e0e6997b31f6
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Doubles$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Doubles.class b/src/main/resources/org/python/google/common/primitives/Doubles.class
new file mode 100644
index 0000000000000000000000000000000000000000..68d524f8f375c10d1a12d8f2a97ed7cf69cf6583
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Doubles.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Floats$FloatArrayAsList.class b/src/main/resources/org/python/google/common/primitives/Floats$FloatArrayAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..a940839a97c714e64b565e913f8bfe92a10613fb
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Floats$FloatArrayAsList.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Floats$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/Floats$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f67ce39fdca97638fa37ff42b6567340c281cde
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Floats$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Floats.class b/src/main/resources/org/python/google/common/primitives/Floats.class
new file mode 100644
index 0000000000000000000000000000000000000000..0646981774ae7bfaaa182055b28b768b30856ff1
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Floats.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Ints$IntArrayAsList.class b/src/main/resources/org/python/google/common/primitives/Ints$IntArrayAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..81051237e87dce8deff45516eb82d57c88a4911b
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Ints$IntArrayAsList.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Ints$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/Ints$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..3108f91d709afa326a252b0207dd0a902eb0e211
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Ints$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Ints.class b/src/main/resources/org/python/google/common/primitives/Ints.class
new file mode 100644
index 0000000000000000000000000000000000000000..8256e510fd5a8dfb88a3b719697993023e1d48e1
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Ints.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Longs$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/Longs$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..23396fb0fa7a78417582bad82d8a423666cb7a60
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Longs$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Longs$LongArrayAsList.class b/src/main/resources/org/python/google/common/primitives/Longs$LongArrayAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..859a4a98d7ef14db8ddbfcb60325daaec4ad7813
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Longs$LongArrayAsList.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Longs.class b/src/main/resources/org/python/google/common/primitives/Longs.class
new file mode 100644
index 0000000000000000000000000000000000000000..547250c9e1bdf6e685f30f41581df749fb1f9203
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Longs.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/ParseRequest.class b/src/main/resources/org/python/google/common/primitives/ParseRequest.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce06babc5fdd320f926b67da8348d2da0cf4acc7
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/ParseRequest.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Primitives.class b/src/main/resources/org/python/google/common/primitives/Primitives.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3928d70f1c7e9bc45ea7e95504103c6885aaad3
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Primitives.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Shorts$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/Shorts$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..b21a33c15cc9f6e7f22db63cfb0eea35a20b5c6a
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Shorts$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Shorts$ShortArrayAsList.class b/src/main/resources/org/python/google/common/primitives/Shorts$ShortArrayAsList.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fe685f2847568eac0d7ab37f058f925319c804f
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Shorts$ShortArrayAsList.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/Shorts.class b/src/main/resources/org/python/google/common/primitives/Shorts.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c0770dab1ac1a27067d80de72b650f61345c149
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/Shorts.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/SignedBytes$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/SignedBytes$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f01ec24218ae7cdaec942fa28e89c2bff2c11a0
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/SignedBytes$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/SignedBytes.class b/src/main/resources/org/python/google/common/primitives/SignedBytes.class
new file mode 100644
index 0000000000000000000000000000000000000000..e45903aa2f1014b2bb9a5a9aadaed3b0dc94f0dc
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/SignedBytes.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator.class b/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ede688f9c183fa8e04faa58195ee3be2f619fa10
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator$1.class b/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..997dc2c9dfb3d8f29b042fbfeee83b05f850624e
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator$1.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator.class b/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..49d723abc564d7ad0cab4a3312ff778b572a69eb
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder.class b/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..fa0c524cd94aef563d91e9f3b2fe4e6e05a06979
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedBytes$LexicographicalComparatorHolder.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedBytes.class b/src/main/resources/org/python/google/common/primitives/UnsignedBytes.class
new file mode 100644
index 0000000000000000000000000000000000000000..236168365ef4cd7f29c35aa788227bb5305e3bd7
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedBytes.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedInteger.class b/src/main/resources/org/python/google/common/primitives/UnsignedInteger.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fb7acb9c30ecb43a76fde1847a316d8edc520ac
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedInteger.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedInts$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/UnsignedInts$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..52b94b314877a0288774159e1923743cca6d3f7b
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedInts$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedInts.class b/src/main/resources/org/python/google/common/primitives/UnsignedInts.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf42f8ca3b72a832dd8afe15e6335073587d3ade
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedInts.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedLong.class b/src/main/resources/org/python/google/common/primitives/UnsignedLong.class
new file mode 100644
index 0000000000000000000000000000000000000000..d26d7b0eefc05e631bd270be91e8d5e9218c8f0f
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedLong.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedLongs$LexicographicalComparator.class b/src/main/resources/org/python/google/common/primitives/UnsignedLongs$LexicographicalComparator.class
new file mode 100644
index 0000000000000000000000000000000000000000..98d562906ff78f5fc64de1e401ff6f5036505ffe
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedLongs$LexicographicalComparator.class differ
diff --git a/src/main/resources/org/python/google/common/primitives/UnsignedLongs.class b/src/main/resources/org/python/google/common/primitives/UnsignedLongs.class
new file mode 100644
index 0000000000000000000000000000000000000000..889a6b9ef2be62508a9179e61987b3cb50ab2891
Binary files /dev/null and b/src/main/resources/org/python/google/common/primitives/UnsignedLongs.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/AbstractInvocationHandler.class b/src/main/resources/org/python/google/common/reflect/AbstractInvocationHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ee00aa2f13c45408a06774aed86aea8bfe9981e
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/AbstractInvocationHandler.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap$1.class b/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecd732e7a19a4117f3a98aa96c8dadca519872cf
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap$Builder.class b/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap$Builder.class
new file mode 100644
index 0000000000000000000000000000000000000000..8183ab2422d98fa31ed6027a6a0781552ef471d1
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap$Builder.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap.class b/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..341ed0b3089d9694b04722ca57df910fce97f44d
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/ImmutableTypeToInstanceMap.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/MutableTypeToInstanceMap.class b/src/main/resources/org/python/google/common/reflect/MutableTypeToInstanceMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..2603e2062b0f4d39c0d63ddc67bba8c1ae43ddf5
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/MutableTypeToInstanceMap.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Reflection.class b/src/main/resources/org/python/google/common/reflect/Reflection.class
new file mode 100644
index 0000000000000000000000000000000000000000..efe14446dea4874ab0ca4cab0b78de988aff6657
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Reflection.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeCapture.class b/src/main/resources/org/python/google/common/reflect/TypeCapture.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a1f0fa98ca37c25adb5501a76c4ca34d046f6a3
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeCapture.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeParameter.class b/src/main/resources/org/python/google/common/reflect/TypeParameter.class
new file mode 100644
index 0000000000000000000000000000000000000000..85f9021eef9dd0ee4d743257a88d045c0d441780
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeParameter.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeResolver$1.class b/src/main/resources/org/python/google/common/reflect/TypeResolver$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e34e092082806d964df89041341872371c8661e
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeResolver$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeResolver$TypeMappingIntrospector.class b/src/main/resources/org/python/google/common/reflect/TypeResolver$TypeMappingIntrospector.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5ebd17be5d50b4366cf6db72ce9eb776cd294b5
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeResolver$TypeMappingIntrospector.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeResolver$WildcardCapturer.class b/src/main/resources/org/python/google/common/reflect/TypeResolver$WildcardCapturer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f88996997362e6caea0cc30bd38e415149980f86
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeResolver$WildcardCapturer.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeResolver.class b/src/main/resources/org/python/google/common/reflect/TypeResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..5022ef053842d32f12512a269ebc63813be3a024
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeResolver.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToInstanceMap.class b/src/main/resources/org/python/google/common/reflect/TypeToInstanceMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..2368db5c1456a59833d510f36cc61886686b0828
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToInstanceMap.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$1.class b/src/main/resources/org/python/google/common/reflect/TypeToken$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cbd8ec2cdbff60fbdc0b1867a6a3ab06564470fb
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$ClassSet.class b/src/main/resources/org/python/google/common/reflect/TypeToken$ClassSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..c066d9bb770d09f367a8a721af0bb5dfabfdfa0f
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$ClassSet.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$InterfaceSet$1.class b/src/main/resources/org/python/google/common/reflect/TypeToken$InterfaceSet$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..8982a7772357343a4a81e8efce0f1574f89011c3
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$InterfaceSet$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$InterfaceSet.class b/src/main/resources/org/python/google/common/reflect/TypeToken$InterfaceSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..93e60e86315bc4b372d607f0612f19dabde51062
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$InterfaceSet.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$SimpleTypeToken.class b/src/main/resources/org/python/google/common/reflect/TypeToken$SimpleTypeToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..da538d44e2eded7deb00fb114879f5e151111fe7
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$SimpleTypeToken.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$1.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a5e5c0ea5aa56c8d8606134d3fa2d2bb8796b05
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$2.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ad88ea9f63b1a1d848ab3de9656e27873aa2a23
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$2.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$3.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..45e2643febc6a76d618af43eafbaae621f6a03bc
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$3.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$4.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d7d64b351ecb30458f19af9379ce02f697af0c8
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$4.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$ForwardingTypeCollector.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$ForwardingTypeCollector.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc0d36d3062279279f0924e764efbe81b9484ed8
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector$ForwardingTypeCollector.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector.class
new file mode 100644
index 0000000000000000000000000000000000000000..b60050a87d3d1ecfe3ce750530735138aa1d5659
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeCollector.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter$1.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8f2208ec1f6dfb5f245802d8f6c8465d40bd557
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter$2.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..53b159597254bbc9fe1aa33fdbfa52c869bd3c06
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter$2.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea42a16c5890221a202c7d5a349f25cf78ef1ec7
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeFilter.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken$TypeSet.class b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeSet.class
new file mode 100644
index 0000000000000000000000000000000000000000..91ea04f0c5525b46b3a42b8284f8d0bbc8c1d96d
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken$TypeSet.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/TypeToken.class b/src/main/resources/org/python/google/common/reflect/TypeToken.class
new file mode 100644
index 0000000000000000000000000000000000000000..09e02fa4d7701776f83ee4e8aac57cd502c9c99c
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/TypeToken.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$1.class b/src/main/resources/org/python/google/common/reflect/Types$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c80b0d9d5bd31ead91c1bdf174344bc75fd68d5
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$1.class b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c7a69ecab56928a99803d20b3937900b1b1b318
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$1LocalClass.class b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$1LocalClass.class
new file mode 100644
index 0000000000000000000000000000000000000000..86418ce8b9ab2558fa72c5c041c5605eaebea6fd
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$1LocalClass.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$2.class b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..246218b4a07dc799cb0f5c52310d37aedf583db8
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$2.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$3.class b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0eb49cc34166752fd33a55b41c2361ea4452e17
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership$3.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership.class b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership.class
new file mode 100644
index 0000000000000000000000000000000000000000..1181901e8cf10ad87a453b10d84a6755c3793c5e
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$ClassOwnership.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$GenericArrayTypeImpl.class b/src/main/resources/org/python/google/common/reflect/Types$GenericArrayTypeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dbc41f529ea5af995ca53d2a1975c58d5fb67a5
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$GenericArrayTypeImpl.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$1.class b/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b1c0f0fef2aff85fe02848c1e7da99e7501fce9
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$1.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$2.class b/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..b0aa268d6ace791bf1577f2a7259fefe56193035
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$2.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$3.class b/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..3db52b1ed4440821eb99c7466025b75b44cb2b65
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$JavaVersion$3.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$JavaVersion.class b/src/main/resources/org/python/google/common/reflect/Types$JavaVersion.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c7c83fb5a67b1de9327977fd24ffe7ffbdca63b
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$JavaVersion.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$ParameterizedTypeImpl.class b/src/main/resources/org/python/google/common/reflect/Types$ParameterizedTypeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..02d205addd5b74d0bbf40da92b1df5c5f2887a94
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$ParameterizedTypeImpl.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$TypeVariableImpl.class b/src/main/resources/org/python/google/common/reflect/Types$TypeVariableImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..7909c66e0912c6d86c0305e09a29defe3d557287
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$TypeVariableImpl.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types$WildcardTypeImpl.class b/src/main/resources/org/python/google/common/reflect/Types$WildcardTypeImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..1346ed39b23b3cb92a8014b43dbaaa2d5b54dd97
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types$WildcardTypeImpl.class differ
diff --git a/src/main/resources/org/python/google/common/reflect/Types.class b/src/main/resources/org/python/google/common/reflect/Types.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e61f42f18b753aa47c61f55255fbc728ea37aea
Binary files /dev/null and b/src/main/resources/org/python/google/common/reflect/Types.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractCheckedFuture.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractCheckedFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..053fc6767a6c55695cb5059dc6069ffa32ffcb95
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractCheckedFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$1$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a31c2878cd64ae043e3fa01fd6dc4b0328bb3fa
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d181ce0fa6017cd1cdb0c314991b8ae0982be4a4
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$2.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..a54c743482113359c39adeb1faf60787059df57a
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff58c83fa0d267ee8a4e87adec90e51f2c548529
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractExecutionThreadService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractFuture$Sync.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractFuture$Sync.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b90a57697a1e2823ea75e2753783b0f25e434ea
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractFuture$Sync.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractFuture.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..841924bbc5c5255d021a5cf453f752e7acdb30ae
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..356c969e68acbea0937485c985d33f9477b1faa4
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1$2.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..450b8a77a3f6f4ff342980edca0021b82064aa39
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..69bd8a015a9ab4d4bcf07db5d52cf04e4b7aa0d5
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$2.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6efaf6ae2842043b1e9e077ebecb928663a55f2
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e648a80909217a2ebe3a43bdb58e56c5967c902
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractIdleService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractListeningExecutorService.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractListeningExecutorService.class
new file mode 100644
index 0000000000000000000000000000000000000000..df7f80a67e05f3e721cc6a6af66ad15b4d7d92f5
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractListeningExecutorService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fe032671d88468eb3f8c9188ebe4c689bdab8ae
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$2.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..84e0ea701d39550f7e156851349304aef577a0fc
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$3.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ce961715b25b49eec08d5fade87d93dadf178ca
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1$3.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4297c82193a40b7b97526a1cb46d109b192d39b
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler$ReschedulableCallable.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler$ReschedulableCallable.class
new file mode 100644
index 0000000000000000000000000000000000000000..66ce99b6f80aa9a892f5d0bb56d25a88e0f20e76
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler$ReschedulableCallable.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler$Schedule.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler$Schedule.class
new file mode 100644
index 0000000000000000000000000000000000000000..77881a7baa10ecd85b807072d19495596802d20f
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler$Schedule.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e9274836a98d54784ee075fb0857bbb8ad96e32
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$CustomScheduler.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..49d9a90bc5c980413a76a614a3c480606fc282be
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler$2.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..38279170bcecf561e1900407c5c5b6b3fc78d7c7
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler.class
new file mode 100644
index 0000000000000000000000000000000000000000..08dca32040fa908fdeacd03cf341e133ce047017
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService$Scheduler.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e6e29b9eb8a2356667ceec510f3d0c15e590d87
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractScheduledService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..775d3c3406a9a86a7fc8df9abf83d61ced4e3eb2
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$2$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$2$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a29db1b2852180ff4a577c2e74165cf89ff3b702
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$2$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$2.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc522b9b2fab5f6c259e335de160f85b586ce835
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$3$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$3$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..923418a5c0fd088dabcccd176c6e4ddf4f7e9b94
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$3$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$3.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..83d359d457067b79292aa659420d954390def2b2
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$3.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$4$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$4$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa350f608822aee40fb164b23a9e094a85e79979
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$4$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$4.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c110fa5426825b2422ab4b49a12670b2e177a61
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$4.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$5$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$5$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0cbdfd9640d34e71e49fcabe9a66ccad3a29a325
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$5$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$5.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..83c4a97caa3d436c3979ae80f8c75c4bd8c5b28e
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$5.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$6$1.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$6$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6821d22aaeb5d0df18d1d82cdb1f2fff03148111
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$6$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$6.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..68725e065bc0de9368c936b6cc5f68165a1a56e1
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$6.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$7.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..63ee9fa2a66cbbeea801908ee794d233f535a0fd
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$7.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$ListenerExecutorPair.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$ListenerExecutorPair.class
new file mode 100644
index 0000000000000000000000000000000000000000..aae3ab60a8c90bf445647c21eea0e095be871b27
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$ListenerExecutorPair.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$StateSnapshot.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$StateSnapshot.class
new file mode 100644
index 0000000000000000000000000000000000000000..550d9f6dcbb99bd4b380e370d0a280ce491b81b6
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$StateSnapshot.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService$Transition.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$Transition.class
new file mode 100644
index 0000000000000000000000000000000000000000..8413b4dd1ebb2f491904257264b81010a816c11c
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService$Transition.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AbstractService.class b/src/main/resources/org/python/google/common/util/concurrent/AbstractService.class
new file mode 100644
index 0000000000000000000000000000000000000000..a98a57fbc806355025315135a48aa27e54474225
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AbstractService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AsyncFunction.class b/src/main/resources/org/python/google/common/util/concurrent/AsyncFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1970f6ac58435c2f6cae0228d773c04308c3e76
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AsyncFunction.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AtomicDouble.class b/src/main/resources/org/python/google/common/util/concurrent/AtomicDouble.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d18a8717418f2151c5c4b5261cdd68ad5905143
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AtomicDouble.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AtomicDoubleArray.class b/src/main/resources/org/python/google/common/util/concurrent/AtomicDoubleArray.class
new file mode 100644
index 0000000000000000000000000000000000000000..3867af7e2a32281b0f3f139157853511bf0e6f76
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AtomicDoubleArray.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AtomicLongMap$1.class b/src/main/resources/org/python/google/common/util/concurrent/AtomicLongMap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..68cd46f30a088cfd90a31451ebf42a623af3a6e3
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AtomicLongMap$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/AtomicLongMap.class b/src/main/resources/org/python/google/common/util/concurrent/AtomicLongMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d61694902bacb475187de08ec44a4b7552736c2
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/AtomicLongMap.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Atomics.class b/src/main/resources/org/python/google/common/util/concurrent/Atomics.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8c8018592afe7ec2d91f3d73be45975edb334db
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Atomics.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Callables$1.class b/src/main/resources/org/python/google/common/util/concurrent/Callables$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ccee81bee108bfd20328dcabd843fb1cd52be0d2
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Callables$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Callables.class b/src/main/resources/org/python/google/common/util/concurrent/Callables.class
new file mode 100644
index 0000000000000000000000000000000000000000..9cb042ef533dda0031f50fd6fc0e3a6914c9b5f1
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Callables.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CheckedFuture.class b/src/main/resources/org/python/google/common/util/concurrent/CheckedFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..04228e15a81c730164528194ed1245a90002626d
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CheckedFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$1.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9affcbb924d769a65f5b0636c1b7535f6c059c7
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingLock.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingLock.class
new file mode 100644
index 0000000000000000000000000000000000000000..b268ab819df4feb8a01850b3eec04497021435f4
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingLock.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantLock.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantLock.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a3d21bd8becfa91b2d1cf8fd2b898093cde5a2a
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantLock.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantReadLock.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantReadLock.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2f3e8507f5e79507345a9a461e349d3428bf712
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantReadLock.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantReadWriteLock.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantReadWriteLock.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b845220f866bfd627981a80aafdb8ab19af929c
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantReadWriteLock.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantWriteLock.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantWriteLock.class
new file mode 100644
index 0000000000000000000000000000000000000000..346aff7e143fecdddda2c7916a41126c52841241
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$CycleDetectingReentrantWriteLock.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$ExampleStackTrace.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$ExampleStackTrace.class
new file mode 100644
index 0000000000000000000000000000000000000000..be81431237c330da5c426cc9526f91dba10ed1b6
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$ExampleStackTrace.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$LockGraphNode.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$LockGraphNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..3aad7f02a79836a0d3dee0808a9e91a7bfaeb82f
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$LockGraphNode.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$OrderedLockGraphNodesCreator.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$OrderedLockGraphNodesCreator.class
new file mode 100644
index 0000000000000000000000000000000000000000..c25f2545cab7f567602cf704375d49e8a30f2bc3
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$OrderedLockGraphNodesCreator.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$1.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..74271675c579919f3e22951c38b9024f262b4f0b
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$2.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f83efc821d785cbfdd88d40f5009a5ecd12a6db
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$3.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..df18251f8d01b0fb4beda98b67e66dfe3ceeb45c
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies$3.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8305147e8bb0f0b3de0070d100a4c3946f498df
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policies.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policy.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policy.class
new file mode 100644
index 0000000000000000000000000000000000000000..13975d4846813ff1891ad51310a5d942756ee9b0
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$Policy.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$PotentialDeadlockException.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$PotentialDeadlockException.class
new file mode 100644
index 0000000000000000000000000000000000000000..e13a953dbcd5e07d46d0ae3ae3e1217306c32eb1
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$PotentialDeadlockException.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$WithExplicitOrdering.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$WithExplicitOrdering.class
new file mode 100644
index 0000000000000000000000000000000000000000..20af23507625ea7d0fdf324a22ed3517ebfff671
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory$WithExplicitOrdering.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory.class b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0da210adb99a74afbe4cdabbac6749ccb1ca353
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/CycleDetectingLockFactory.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ExecutionError.class b/src/main/resources/org/python/google/common/util/concurrent/ExecutionError.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4d6d52f8a564020dc062f622f621b0d143c5361
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ExecutionError.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ExecutionList$RunnableExecutorPair.class b/src/main/resources/org/python/google/common/util/concurrent/ExecutionList$RunnableExecutorPair.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8702ed56b32b83c23bcc1020e25de1a1cad442e
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ExecutionList$RunnableExecutorPair.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ExecutionList.class b/src/main/resources/org/python/google/common/util/concurrent/ExecutionList.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5bea9628e2ff0a155b41600eebc75301948505a
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ExecutionList.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/FakeTimeLimiter.class b/src/main/resources/org/python/google/common/util/concurrent/FakeTimeLimiter.class
new file mode 100644
index 0000000000000000000000000000000000000000..195160892b9a54ef3c1b92b361b27cf8b3a7de9e
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/FakeTimeLimiter.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingBlockingQueue.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingBlockingQueue.class
new file mode 100644
index 0000000000000000000000000000000000000000..532c3366ee66edd190a6cfe0afab5cb95cbf2af5
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingBlockingQueue.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingCheckedFuture$SimpleForwardingCheckedFuture.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingCheckedFuture$SimpleForwardingCheckedFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bee9b226ab835032812a786bb757e92684c4853
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingCheckedFuture$SimpleForwardingCheckedFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingCheckedFuture.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingCheckedFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..2af118e0cf8f6dede3fe125869f3e60e4675c426
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingCheckedFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingExecutorService.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingExecutorService.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8077e30d647d72379b241a196a483636f413106
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingExecutorService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingFuture$SimpleForwardingFuture.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingFuture$SimpleForwardingFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4bb860ff507c9af44cb871eccaf4b005d1fd918
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingFuture$SimpleForwardingFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingFuture.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..55315f6026eaeba4be08d55db867ac0924a0c718
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingListenableFuture$SimpleForwardingListenableFuture.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingListenableFuture$SimpleForwardingListenableFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..7888652ec000493b348487f14d66ee50e26f9796
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingListenableFuture$SimpleForwardingListenableFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingListenableFuture.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingListenableFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..502e1574b31a4072cbd4db8a3efb082e9e2f22df
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingListenableFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingListeningExecutorService.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingListeningExecutorService.class
new file mode 100644
index 0000000000000000000000000000000000000000..0304338592554c32bb51bed872a363e83b333be2
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingListeningExecutorService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ForwardingService.class b/src/main/resources/org/python/google/common/util/concurrent/ForwardingService.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f4bf1cc0891a282465f330d8358a1343a8c312b
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ForwardingService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/FutureCallback.class b/src/main/resources/org/python/google/common/util/concurrent/FutureCallback.class
new file mode 100644
index 0000000000000000000000000000000000000000..8488f245aeda811ade971238802acb2264ea4574
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/FutureCallback.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$1.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..71b4539da0e48df712d667846e34cf750de870f7
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$2.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..cabe6c81c5515af925234e9268c498f57a833211
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$3.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..bebf6bb18fddcdd14699a55792c3593184c07b19
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$3.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$4.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..c62bce9c72c95a91c65cb6dd003f4f4de93eeed6
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$4.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$5.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ffa333200a342ab9f98c9cd3c11e05e0ec57816
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$5.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$6.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$6.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c51f1719aa5507cce4236bc83800ca7b0df5e33
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$6.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$7.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$7.class
new file mode 100644
index 0000000000000000000000000000000000000000..c621e3a99ab0019b91a3d28fafa774a57c06ef26
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$7.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$ChainingListenableFuture$1.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$ChainingListenableFuture$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..449dab624e5d789823b99cc77ae59995b46e2027
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$ChainingListenableFuture$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$ChainingListenableFuture.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$ChainingListenableFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..13fe6835dd375f40ce0592905f4466d28dac3d17
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$ChainingListenableFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture$1.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f5f5abb96ad09c3c6cbb720b3dea1831f84a7ea
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture$2.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..689dc0e55a5435ccceb105a28376aec573a43996
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..665de7edb1df30fe0dd02ca539c6763b42f8c7f6
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$ListFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures$MappingCheckedFuture.class b/src/main/resources/org/python/google/common/util/concurrent/Futures$MappingCheckedFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e46ffae09c1e42b625ea12899b3fb81c5e95256
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures$MappingCheckedFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Futures.class b/src/main/resources/org/python/google/common/util/concurrent/Futures.class
new file mode 100644
index 0000000000000000000000000000000000000000..472536367bc1a19a675601321164cac9f9057eae
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Futures.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters$ListenableFutureAdapter$1.class b/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters$ListenableFutureAdapter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..020bcf97aa425e43ad3323fb387feb0955c86181
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters$ListenableFutureAdapter$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters$ListenableFutureAdapter.class b/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters$ListenableFutureAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..3381e680d618257979919d71c3c3d2f48dd142d4
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters$ListenableFutureAdapter.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters.class b/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters.class
new file mode 100644
index 0000000000000000000000000000000000000000..a29fe224a1482c1d0f19deb803789f926baff352
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/JdkFutureAdapters.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ListenableFuture.class b/src/main/resources/org/python/google/common/util/concurrent/ListenableFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..76d501b8c08e91ad3605048242585d86e1fcc9d3
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ListenableFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ListenableFutureTask.class b/src/main/resources/org/python/google/common/util/concurrent/ListenableFutureTask.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe2c5479951b1aa6ee58638adc4a9af2514be856
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ListenableFutureTask.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ListeningExecutorService.class b/src/main/resources/org/python/google/common/util/concurrent/ListeningExecutorService.class
new file mode 100644
index 0000000000000000000000000000000000000000..98d9c5255a7228b0d891b84167cfda9cf9610037
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ListeningExecutorService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ListeningScheduledExecutorService.class b/src/main/resources/org/python/google/common/util/concurrent/ListeningScheduledExecutorService.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0d28264ca6dd78a7a9d279ed2dadebb92024554
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ListeningScheduledExecutorService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Monitor$Guard.class b/src/main/resources/org/python/google/common/util/concurrent/Monitor$Guard.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd6f0494787500f5837eeca1cbf12889e02a1e41
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Monitor$Guard.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Monitor.class b/src/main/resources/org/python/google/common/util/concurrent/Monitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b8254d08a5686e2659b4497bc948228f1ef856d
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Monitor.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$1.class b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c09f4841891d088e8e521e4f37fd307a909b0e2f
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$2.class b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c08057b56d22f45e92531b637ac1e5bf20e23d5e
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$ListeningDecorator.class b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$ListeningDecorator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae8d5d77471f65c2fbd1181ac57f6ac93032e5ed
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$ListeningDecorator.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService.class b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca20571a3793c83304601b2685933a2c7bcecb18
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$ScheduledListeningDecorator.class b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$ScheduledListeningDecorator.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e815bedd246232160242494126f0fcbdab34294
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors$ScheduledListeningDecorator.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors.class b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors.class
new file mode 100644
index 0000000000000000000000000000000000000000..58fde63315b44e176e26f15ad7b05aa4dccb5767
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/MoreExecutors.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$1.class b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b359b9ae2801193d51bfc09158eae3962d5a550
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$Bursty.class b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$Bursty.class
new file mode 100644
index 0000000000000000000000000000000000000000..b27706cb170abdce94e15da52fb2e99122ab3fb9
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$Bursty.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$SleepingTicker$1.class b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$SleepingTicker$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b3192a7677428c4d0c0e61a0431c4977adb53d8
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$SleepingTicker$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$SleepingTicker.class b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$SleepingTicker.class
new file mode 100644
index 0000000000000000000000000000000000000000..116ba3305c9ca6e9761076aa6c0a4c4306c2bcce
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$SleepingTicker.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$WarmingUp.class b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$WarmingUp.class
new file mode 100644
index 0000000000000000000000000000000000000000..672501993341288eb45350de05e27911fcfb17c7
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter$WarmingUp.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/RateLimiter.class b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter.class
new file mode 100644
index 0000000000000000000000000000000000000000..00eb37c0223710728d861af4b3a7ed9f64be5e16
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/RateLimiter.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Service$Listener.class b/src/main/resources/org/python/google/common/util/concurrent/Service$Listener.class
new file mode 100644
index 0000000000000000000000000000000000000000..3dc96d38ddef9760f5827f3ad63bd48f7cabc2d9
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Service$Listener.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Service$State.class b/src/main/resources/org/python/google/common/util/concurrent/Service$State.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecf8931208f81115ac685e561829a7892ccf7d97
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Service$State.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Service.class b/src/main/resources/org/python/google/common/util/concurrent/Service.class
new file mode 100644
index 0000000000000000000000000000000000000000..18dfe1c4413eabe0addd57ba90bcb6e9637e93b9
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Service.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/SettableFuture.class b/src/main/resources/org/python/google/common/util/concurrent/SettableFuture.class
new file mode 100644
index 0000000000000000000000000000000000000000..9aeea8cd74ddfe2205125f6eed658918d6b5814c
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/SettableFuture.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter$1$1.class b/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter$1$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..323227acaf666a250a92cd5c56f665a4d0893671
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter$1$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter$1.class b/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea4c9ae4a1865914e3e4b3483d03976089dddb8f
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter.class b/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter.class
new file mode 100644
index 0000000000000000000000000000000000000000..e88d3e096061c68a315d2597f6135d682caf1079
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/SimpleTimeLimiter.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$1.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e0cfdefbb7ff8e75a6d8d32519fd6456aeca877
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$2.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c0d6bcbbd5e80a99ec39f39fb26c0fa533c6f9a
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$2.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$3.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e6a10282d0ca413b6c3d38a705f772d8993e178
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$3.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$4.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8fb7efd9e2891740515ebc10076045302c2157e
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$4.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$5.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$5.class
new file mode 100644
index 0000000000000000000000000000000000000000..54e519cdbd4677635418d775796a1f26459ccff6
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$5.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$CompactStriped.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$CompactStriped.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2bc006ad7e74e14e39616784872322015d9b734
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$CompactStriped.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$LazyStriped.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$LazyStriped.class
new file mode 100644
index 0000000000000000000000000000000000000000..431c0be4006c20c67f076a31969d796adac229aa
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$LazyStriped.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$PaddedLock.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$PaddedLock.class
new file mode 100644
index 0000000000000000000000000000000000000000..d1bd469a7134394dd378ec81a9ea7e6d7cf20372
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$PaddedLock.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$PaddedSemaphore.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$PaddedSemaphore.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9331fd8153d76c9f6d8d5f386a08cb747a7a5c2
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$PaddedSemaphore.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped$PowerOfTwoStriped.class b/src/main/resources/org/python/google/common/util/concurrent/Striped$PowerOfTwoStriped.class
new file mode 100644
index 0000000000000000000000000000000000000000..69c81a7718f700d46475e2f68fc049a52d58e09a
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped$PowerOfTwoStriped.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Striped.class b/src/main/resources/org/python/google/common/util/concurrent/Striped.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8d0dc304b25d3a1072e0046d0aac8beeedca4ef
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Striped.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ThreadFactoryBuilder$1.class b/src/main/resources/org/python/google/common/util/concurrent/ThreadFactoryBuilder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..108b115aec0942ff81f8f3d5baff0fccbaee34e4
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ThreadFactoryBuilder$1.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/ThreadFactoryBuilder.class b/src/main/resources/org/python/google/common/util/concurrent/ThreadFactoryBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..0165cabcef538d707c53406bd5c83052f0dadd53
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/ThreadFactoryBuilder.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/TimeLimiter.class b/src/main/resources/org/python/google/common/util/concurrent/TimeLimiter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0a55797f8bb6d817171a2ca9d4bc0fa13553b00
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/TimeLimiter.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/UncaughtExceptionHandlers$Exiter.class b/src/main/resources/org/python/google/common/util/concurrent/UncaughtExceptionHandlers$Exiter.class
new file mode 100644
index 0000000000000000000000000000000000000000..91247a98bba7d05d51d7234744126d06e38b63a1
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/UncaughtExceptionHandlers$Exiter.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/UncaughtExceptionHandlers.class b/src/main/resources/org/python/google/common/util/concurrent/UncaughtExceptionHandlers.class
new file mode 100644
index 0000000000000000000000000000000000000000..e31e08e8abceb9ecc6e9db6acbb24845a1ee763c
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/UncaughtExceptionHandlers.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/UncheckedExecutionException.class b/src/main/resources/org/python/google/common/util/concurrent/UncheckedExecutionException.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1c54a77fdc9eec0196098ca26e9e2b22885608c
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/UncheckedExecutionException.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/UncheckedTimeoutException.class b/src/main/resources/org/python/google/common/util/concurrent/UncheckedTimeoutException.class
new file mode 100644
index 0000000000000000000000000000000000000000..8412197ad799db729eadae7327852b7ab852588f
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/UncheckedTimeoutException.class differ
diff --git a/src/main/resources/org/python/google/common/util/concurrent/Uninterruptibles.class b/src/main/resources/org/python/google/common/util/concurrent/Uninterruptibles.class
new file mode 100644
index 0000000000000000000000000000000000000000..a426317232f4ba964aa33eca378c2c713249761b
Binary files /dev/null and b/src/main/resources/org/python/google/common/util/concurrent/Uninterruptibles.class differ
diff --git a/src/main/resources/org/python/indexer/AstCache.class b/src/main/resources/org/python/indexer/AstCache.class
new file mode 100644
index 0000000000000000000000000000000000000000..af98163865b879471c3891511627c5376169ab2b
Binary files /dev/null and b/src/main/resources/org/python/indexer/AstCache.class differ
diff --git a/src/main/resources/org/python/indexer/AstConverter$1.class b/src/main/resources/org/python/indexer/AstConverter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1dca57b4cc6a85c141ec023f48915cd6233d4fc0
Binary files /dev/null and b/src/main/resources/org/python/indexer/AstConverter$1.class differ
diff --git a/src/main/resources/org/python/indexer/AstConverter.class b/src/main/resources/org/python/indexer/AstConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..4678908d7bf240c5c507d1540b32a2109b77597e
Binary files /dev/null and b/src/main/resources/org/python/indexer/AstConverter.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ArrayModule.class b/src/main/resources/org/python/indexer/Builtins$ArrayModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..87e0ca8490d21dd8711aec68c9e48c23b3554e22
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ArrayModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$AudioopModule.class b/src/main/resources/org/python/indexer/Builtins$AudioopModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..680d8c3eb055990e7b6198de81a97f3e1a7e991d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$AudioopModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$BinasciiModule.class b/src/main/resources/org/python/indexer/Builtins$BinasciiModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0f58f452ca1e26e098a54393fa63700e9b537e2
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$BinasciiModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$BuiltinsModule.class b/src/main/resources/org/python/indexer/Builtins$BuiltinsModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..85ae7525cd1b544d4e66c0ad9a1c8ee3bcba601c
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$BuiltinsModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$Bz2Module.class b/src/main/resources/org/python/indexer/Builtins$Bz2Module.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d3bb5404da3b04b4af5e15a4f35120ed465dbff
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$Bz2Module.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$CMathModule.class b/src/main/resources/org/python/indexer/Builtins$CMathModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..837a5274fe04cd8a929685f550bc835b35434c43
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$CMathModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$CPickleModule.class b/src/main/resources/org/python/indexer/Builtins$CPickleModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..ceedda039af8fee7182a89ea95f4b3365efc0d9a
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$CPickleModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$CStringIOModule.class b/src/main/resources/org/python/indexer/Builtins$CStringIOModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..42980e46042e16872f620e531117111537b9bbb6
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$CStringIOModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$CTypesModule.class b/src/main/resources/org/python/indexer/Builtins$CTypesModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..cdceb80f7d77ef64ba940574a6125524bdd8cc3d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$CTypesModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$CollectionsModule.class b/src/main/resources/org/python/indexer/Builtins$CollectionsModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b229aff0403b28c7b451754870f721756d7d73f
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$CollectionsModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$CryptModule.class b/src/main/resources/org/python/indexer/Builtins$CryptModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..49a7e9f14ae871f9621aea33a69e5ec1529d0444
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$CryptModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$DatetimeModule.class b/src/main/resources/org/python/indexer/Builtins$DatetimeModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..0457a0669e3914f3a37ff8d7c6f4b759a2d41237
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$DatetimeModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$DbmModule.class b/src/main/resources/org/python/indexer/Builtins$DbmModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c3ea28c8800e0c5df4cd154a6442ae39091924d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$DbmModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ErrnoModule.class b/src/main/resources/org/python/indexer/Builtins$ErrnoModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3481173b0ae051c96347c899364df02e5e3c02a
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ErrnoModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ExceptionsModule.class b/src/main/resources/org/python/indexer/Builtins$ExceptionsModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..98da22237838feac2b1114ce90cdb771ce37ce59
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ExceptionsModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$FcntlModule.class b/src/main/resources/org/python/indexer/Builtins$FcntlModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1961fb21810c4e39db0b1c95d16af1e16f18843
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$FcntlModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$FpectlModule.class b/src/main/resources/org/python/indexer/Builtins$FpectlModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..00ca080f6e5064a9ab831fc7502efaf68bc42cdc
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$FpectlModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$GcModule.class b/src/main/resources/org/python/indexer/Builtins$GcModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..64a212c34580a2997a87405d45cc90b95a75479d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$GcModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$GdbmModule.class b/src/main/resources/org/python/indexer/Builtins$GdbmModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..b36bd38421f9ed2aaad41aa8d9020a419636f775
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$GdbmModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$GrpModule.class b/src/main/resources/org/python/indexer/Builtins$GrpModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b0ac835322915007c4471b3e90e7c39fadce81d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$GrpModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ImpModule.class b/src/main/resources/org/python/indexer/Builtins$ImpModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..9be869a5e96987357a3362d4189f0f8747725d9c
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ImpModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ItertoolsModule.class b/src/main/resources/org/python/indexer/Builtins$ItertoolsModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..78ad7d7970346eeb65db447fc77f40627eedec2c
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ItertoolsModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$MarshalModule.class b/src/main/resources/org/python/indexer/Builtins$MarshalModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac68dff90cf60f0603c388ac084496ffa8f2e50a
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$MarshalModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$MathModule.class b/src/main/resources/org/python/indexer/Builtins$MathModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3e01a45e400357d6e8e9de888ff2832a853e62d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$MathModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$Md5Module.class b/src/main/resources/org/python/indexer/Builtins$Md5Module.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e138838509a6188153136d570cc241bb73bbadf
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$Md5Module.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$MmapModule.class b/src/main/resources/org/python/indexer/Builtins$MmapModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..491a6e4b8cfc51100b17d21c216ff3cc91c3e865
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$MmapModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$NativeModule.class b/src/main/resources/org/python/indexer/Builtins$NativeModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc1cb1b25c3099549fe08fc81d7b19ad17b87251
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$NativeModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$NisModule.class b/src/main/resources/org/python/indexer/Builtins$NisModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8fa103da3fada113f08a3f29828c6dae9ede494
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$NisModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$OperatorModule.class b/src/main/resources/org/python/indexer/Builtins$OperatorModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a3b65fbd9e86af939289721653387b1ab6d54b7
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$OperatorModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$OsModule.class b/src/main/resources/org/python/indexer/Builtins$OsModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2461699e1080e89ca595c42f6ee3721b1122178
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$OsModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ParserModule.class b/src/main/resources/org/python/indexer/Builtins$ParserModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd8149646a810842b204a0d1da4fea9ad3a19438
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ParserModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$PosixModule.class b/src/main/resources/org/python/indexer/Builtins$PosixModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..57b150b9330110c974e2326e3ded77dbe755bffa
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$PosixModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$PwdModule.class b/src/main/resources/org/python/indexer/Builtins$PwdModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ea3059c2b8aaa9c7eed93e2d88c311940bebddd
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$PwdModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$PyexpatModule.class b/src/main/resources/org/python/indexer/Builtins$PyexpatModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..c188f46c915c129fda77f5630c4ee74dbfbd7b0f
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$PyexpatModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ReadlineModule.class b/src/main/resources/org/python/indexer/Builtins$ReadlineModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce9893a830e9d6d3fb0f14da1c56ccf819047885
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ReadlineModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ResourceModule.class b/src/main/resources/org/python/indexer/Builtins$ResourceModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..735223a8fb35fe844e74b801845b5461856ce02b
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ResourceModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$SelectModule.class b/src/main/resources/org/python/indexer/Builtins$SelectModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c27998ef5ba4e31960635a79524f483c878260b
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$SelectModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ShaModule.class b/src/main/resources/org/python/indexer/Builtins$ShaModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b0561f8ebca599bafd72b1e11fcfb90b069f97d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ShaModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$SignalModule.class b/src/main/resources/org/python/indexer/Builtins$SignalModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9de8774ef9c0beea03a9f29d3b0ed337fd7a1a8
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$SignalModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$SpwdModule.class b/src/main/resources/org/python/indexer/Builtins$SpwdModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ebec0aacd6510b16b4adce03b96e4d5a96c98a4
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$SpwdModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$StropModule.class b/src/main/resources/org/python/indexer/Builtins$StropModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..9684eb0585b5cf71cebf0d652f024040700089dd
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$StropModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$StructModule.class b/src/main/resources/org/python/indexer/Builtins$StructModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c3c3a580adccb92e04eb443782b4f4f2fd425ca
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$StructModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$SysModule.class b/src/main/resources/org/python/indexer/Builtins$SysModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9bcc8746f4140a94b15f9ad1732cec92631e55b
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$SysModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$SyslogModule.class b/src/main/resources/org/python/indexer/Builtins$SyslogModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..954617e1b3a01bd42be39d17fba17dde284773c4
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$SyslogModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$TermiosModule.class b/src/main/resources/org/python/indexer/Builtins$TermiosModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..090aeaddb655e636fcfc55dfcf93fc36f5d155e4
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$TermiosModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ThreadModule.class b/src/main/resources/org/python/indexer/Builtins$ThreadModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..945507936898f09f93d9904c0c1b8c0b4083d05e
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ThreadModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$TimeModule.class b/src/main/resources/org/python/indexer/Builtins$TimeModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..0adf0e66b3a2b63db306ab1613da42c54d3db75c
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$TimeModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$UnicodedataModule.class b/src/main/resources/org/python/indexer/Builtins$UnicodedataModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3565f8e3d0a15fb6502c3b193cade747b70bad4
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$UnicodedataModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ZipimportModule.class b/src/main/resources/org/python/indexer/Builtins$ZipimportModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ab952f4831e633496612b456f8d1da5c4038ce4
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ZipimportModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins$ZlibModule.class b/src/main/resources/org/python/indexer/Builtins$ZlibModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..bfc5878f692abd6fe8fa308145c92f2fc607b0c4
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins$ZlibModule.class differ
diff --git a/src/main/resources/org/python/indexer/Builtins.class b/src/main/resources/org/python/indexer/Builtins.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bc2cf663b3cf2d14f3329c1f47175557c513b15
Binary files /dev/null and b/src/main/resources/org/python/indexer/Builtins.class differ
diff --git a/src/main/resources/org/python/indexer/Def.class b/src/main/resources/org/python/indexer/Def.class
new file mode 100644
index 0000000000000000000000000000000000000000..97658a33d7b9a6857f246455532e2e6cc63d2c20
Binary files /dev/null and b/src/main/resources/org/python/indexer/Def.class differ
diff --git a/src/main/resources/org/python/indexer/Diagnostic$Type.class b/src/main/resources/org/python/indexer/Diagnostic$Type.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9547b6581bb91ae3d311991748ff4d2a130cbf6
Binary files /dev/null and b/src/main/resources/org/python/indexer/Diagnostic$Type.class differ
diff --git a/src/main/resources/org/python/indexer/Diagnostic.class b/src/main/resources/org/python/indexer/Diagnostic.class
new file mode 100644
index 0000000000000000000000000000000000000000..b61bbe456a33db7f4f22022781c892fcbb94cc0d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Diagnostic.class differ
diff --git a/src/main/resources/org/python/indexer/Indexer.class b/src/main/resources/org/python/indexer/Indexer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6a5d65396730f382345ed4cc80327a29aab928e
Binary files /dev/null and b/src/main/resources/org/python/indexer/Indexer.class differ
diff --git a/src/main/resources/org/python/indexer/IndexerTest.class b/src/main/resources/org/python/indexer/IndexerTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..81862caa95685eb3735254c69f50625127e25558
Binary files /dev/null and b/src/main/resources/org/python/indexer/IndexerTest.class differ
diff --git a/src/main/resources/org/python/indexer/IndexingException.class b/src/main/resources/org/python/indexer/IndexingException.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c2caa27d427532b0f92a9ba00edcf6d202bf1af
Binary files /dev/null and b/src/main/resources/org/python/indexer/IndexingException.class differ
diff --git a/src/main/resources/org/python/indexer/NBinding$Kind.class b/src/main/resources/org/python/indexer/NBinding$Kind.class
new file mode 100644
index 0000000000000000000000000000000000000000..96bd9061445c721d632d561dfd101d2523010034
Binary files /dev/null and b/src/main/resources/org/python/indexer/NBinding$Kind.class differ
diff --git a/src/main/resources/org/python/indexer/NBinding.class b/src/main/resources/org/python/indexer/NBinding.class
new file mode 100644
index 0000000000000000000000000000000000000000..87d942760ef149e852069e795afa37462b97aba0
Binary files /dev/null and b/src/main/resources/org/python/indexer/NBinding.class differ
diff --git a/src/main/resources/org/python/indexer/Outliner$Branch.class b/src/main/resources/org/python/indexer/Outliner$Branch.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce0b1a740fe1b65acfe6eb5d0a81e3bf3a90bb42
Binary files /dev/null and b/src/main/resources/org/python/indexer/Outliner$Branch.class differ
diff --git a/src/main/resources/org/python/indexer/Outliner$Entry.class b/src/main/resources/org/python/indexer/Outliner$Entry.class
new file mode 100644
index 0000000000000000000000000000000000000000..7dfef1171e27d68eb6bc9c2e622f8a36e3aae360
Binary files /dev/null and b/src/main/resources/org/python/indexer/Outliner$Entry.class differ
diff --git a/src/main/resources/org/python/indexer/Outliner$Leaf.class b/src/main/resources/org/python/indexer/Outliner$Leaf.class
new file mode 100644
index 0000000000000000000000000000000000000000..ada8fa15339ea675ea6350b38a8c42d73bd7c90d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Outliner$Leaf.class differ
diff --git a/src/main/resources/org/python/indexer/Outliner.class b/src/main/resources/org/python/indexer/Outliner.class
new file mode 100644
index 0000000000000000000000000000000000000000..46b4beabe3367d401fe0001ff0ae7cfca44c2143
Binary files /dev/null and b/src/main/resources/org/python/indexer/Outliner.class differ
diff --git a/src/main/resources/org/python/indexer/Ref.class b/src/main/resources/org/python/indexer/Ref.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e0dacfe992388f639d6cec017bd1048390ca4bf
Binary files /dev/null and b/src/main/resources/org/python/indexer/Ref.class differ
diff --git a/src/main/resources/org/python/indexer/Scope$1.class b/src/main/resources/org/python/indexer/Scope$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..15c97b62b260ba179440e96d785bb10dbccde08d
Binary files /dev/null and b/src/main/resources/org/python/indexer/Scope$1.class differ
diff --git a/src/main/resources/org/python/indexer/Scope$Type.class b/src/main/resources/org/python/indexer/Scope$Type.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8d4f399a5021cd9f45954c4276a520d1299fc69
Binary files /dev/null and b/src/main/resources/org/python/indexer/Scope$Type.class differ
diff --git a/src/main/resources/org/python/indexer/Scope.class b/src/main/resources/org/python/indexer/Scope.class
new file mode 100644
index 0000000000000000000000000000000000000000..db2888239ddef0ca95329370a2a8f2d6e61ff5ae
Binary files /dev/null and b/src/main/resources/org/python/indexer/Scope.class differ
diff --git a/src/main/resources/org/python/indexer/StyleRun$Type.class b/src/main/resources/org/python/indexer/StyleRun$Type.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe57d4ae544fcdf8be510848b364592f6ee3dab0
Binary files /dev/null and b/src/main/resources/org/python/indexer/StyleRun$Type.class differ
diff --git a/src/main/resources/org/python/indexer/StyleRun.class b/src/main/resources/org/python/indexer/StyleRun.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d1fd0efe0025d0fc4da07838ba0bdbe108b6063
Binary files /dev/null and b/src/main/resources/org/python/indexer/StyleRun.class differ
diff --git a/src/main/resources/org/python/indexer/TestBase.class b/src/main/resources/org/python/indexer/TestBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc149239041efae8dad5e66c341f584b4b9b2c20
Binary files /dev/null and b/src/main/resources/org/python/indexer/TestBase.class differ
diff --git a/src/main/resources/org/python/indexer/Util.class b/src/main/resources/org/python/indexer/Util.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9bf2b8e37e81e09393aac25ccec671f1bf13104
Binary files /dev/null and b/src/main/resources/org/python/indexer/Util.class differ
diff --git a/src/main/resources/org/python/indexer/ast/BindingFinder.class b/src/main/resources/org/python/indexer/ast/BindingFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..f8e34d4b1bfef32a178ca1ed5cb9c381b695b8ce
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/BindingFinder.class differ
diff --git a/src/main/resources/org/python/indexer/ast/DefaultNodeVisitor.class b/src/main/resources/org/python/indexer/ast/DefaultNodeVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf7301a3e4755be98750d19a1f65fb4ed614e068
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/DefaultNodeVisitor.class differ
diff --git a/src/main/resources/org/python/indexer/ast/GenericNodeVisitor.class b/src/main/resources/org/python/indexer/ast/GenericNodeVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3640c9382b73efe3000d6bbd0ebaf27b280fdbf2
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/GenericNodeVisitor.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NAlias.class b/src/main/resources/org/python/indexer/ast/NAlias.class
new file mode 100644
index 0000000000000000000000000000000000000000..a831a76d3ba5ee97e7bcfb1009217d73b46644c0
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NAlias.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NAssert.class b/src/main/resources/org/python/indexer/ast/NAssert.class
new file mode 100644
index 0000000000000000000000000000000000000000..9186ae0e507861163c5d6162bb1c413877c9cddd
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NAssert.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NAssign.class b/src/main/resources/org/python/indexer/ast/NAssign.class
new file mode 100644
index 0000000000000000000000000000000000000000..320f41ea397eaac92cfd2dc9f02857f4becba348
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NAssign.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NAttribute.class b/src/main/resources/org/python/indexer/ast/NAttribute.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fb00f8c4879470bf9c118a3cb3d712fe5c12af0
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NAttribute.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NAugAssign.class b/src/main/resources/org/python/indexer/ast/NAugAssign.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4d33a6ab442dd2f3b8b802f848e1f5720178a0c
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NAugAssign.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NBinOp.class b/src/main/resources/org/python/indexer/ast/NBinOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..198af209a3d552ff34cfb52b3032ac2bfd8bfafd
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NBinOp.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NBlock.class b/src/main/resources/org/python/indexer/ast/NBlock.class
new file mode 100644
index 0000000000000000000000000000000000000000..51f6da529584adeec7ce84bebe1f554e1ae45d3c
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NBlock.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NBody$GlobalFinder.class b/src/main/resources/org/python/indexer/ast/NBody$GlobalFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..69147ce1a8358b4b0457e4d96f603d3c6b6af49a
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NBody$GlobalFinder.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NBody.class b/src/main/resources/org/python/indexer/ast/NBody.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e6f86705c83c2b30edcc664c2db47d6a7d8b2b9
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NBody.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NBoolOp$OpType.class b/src/main/resources/org/python/indexer/ast/NBoolOp$OpType.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a91765508e8853765b328943b1cf8452fcf2500
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NBoolOp$OpType.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NBoolOp.class b/src/main/resources/org/python/indexer/ast/NBoolOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..dac3c6dcd6e1e2ba99159682c4daf8a52935fac3
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NBoolOp.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NBreak.class b/src/main/resources/org/python/indexer/ast/NBreak.class
new file mode 100644
index 0000000000000000000000000000000000000000..079ccbbb581729bfa6dc6edb66e19f7a73d69da8
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NBreak.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NCall.class b/src/main/resources/org/python/indexer/ast/NCall.class
new file mode 100644
index 0000000000000000000000000000000000000000..287f64093d96b63dfcb70401bdf7ccc295c45d50
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NCall.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NClassDef.class b/src/main/resources/org/python/indexer/ast/NClassDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..4727caa44715ac4fb4465e94f25d1ad5c3e3779a
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NClassDef.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NCompare.class b/src/main/resources/org/python/indexer/ast/NCompare.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd6715fd8eefa7d787af8c18ace99e013c7c9e4e
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NCompare.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NComprehension.class b/src/main/resources/org/python/indexer/ast/NComprehension.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8141e2b5083d601480a3225e8da0585ee04a7a0
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NComprehension.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NContinue.class b/src/main/resources/org/python/indexer/ast/NContinue.class
new file mode 100644
index 0000000000000000000000000000000000000000..1bbdd69885843fc395159e5c2471e16234ab7a7b
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NContinue.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NDelete.class b/src/main/resources/org/python/indexer/ast/NDelete.class
new file mode 100644
index 0000000000000000000000000000000000000000..9623a008ba033bade52145e8453acd770bca94fa
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NDelete.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NDict.class b/src/main/resources/org/python/indexer/ast/NDict.class
new file mode 100644
index 0000000000000000000000000000000000000000..955ecce70c7d6b12fe53e52acb498955f8613059
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NDict.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NEllipsis.class b/src/main/resources/org/python/indexer/ast/NEllipsis.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c74c1a7791c4ec0806522867377362c1111752c
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NEllipsis.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NExceptHandler.class b/src/main/resources/org/python/indexer/ast/NExceptHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..a28fe9fd7a2e1b71c9ff3fd1ebd240bc56834ea2
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NExceptHandler.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NExec.class b/src/main/resources/org/python/indexer/ast/NExec.class
new file mode 100644
index 0000000000000000000000000000000000000000..d89c41c8885fb753019dd53fdd2f1d51e8d0ff54
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NExec.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NExprStmt.class b/src/main/resources/org/python/indexer/ast/NExprStmt.class
new file mode 100644
index 0000000000000000000000000000000000000000..d688fb4d6e68de5ae977df173e241878d67a3c88
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NExprStmt.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NFor.class b/src/main/resources/org/python/indexer/ast/NFor.class
new file mode 100644
index 0000000000000000000000000000000000000000..22687d1d3f2f490da25cae9b7e876cff26d64353
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NFor.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NFunctionDef.class b/src/main/resources/org/python/indexer/ast/NFunctionDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..c097d8c70ef4352d9a9f801b7785b438f608e508
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NFunctionDef.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NGeneratorExp.class b/src/main/resources/org/python/indexer/ast/NGeneratorExp.class
new file mode 100644
index 0000000000000000000000000000000000000000..548ab7d72f3ea910a261b922e69062972a3ac752
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NGeneratorExp.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NGlobal.class b/src/main/resources/org/python/indexer/ast/NGlobal.class
new file mode 100644
index 0000000000000000000000000000000000000000..da91a0a1e5366e5a01faefa9e44b9750db6ade63
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NGlobal.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NIf.class b/src/main/resources/org/python/indexer/ast/NIf.class
new file mode 100644
index 0000000000000000000000000000000000000000..3aaf6b4f324fb734cb53e502097f42eddccf4447
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NIf.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NIfExp.class b/src/main/resources/org/python/indexer/ast/NIfExp.class
new file mode 100644
index 0000000000000000000000000000000000000000..611a0192d371639287a5908f923dd514df386e66
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NIfExp.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NImport.class b/src/main/resources/org/python/indexer/ast/NImport.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c39baf0f3d05f45fa6814657a0aff7393d42f36
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NImport.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NImportFrom.class b/src/main/resources/org/python/indexer/ast/NImportFrom.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2b1312b096d435f4a935dbff10857b91016b0f4
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NImportFrom.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NIndex.class b/src/main/resources/org/python/indexer/ast/NIndex.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a80541880850e269e82ca8fbea23c95a102e62d
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NIndex.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NKeyword.class b/src/main/resources/org/python/indexer/ast/NKeyword.class
new file mode 100644
index 0000000000000000000000000000000000000000..63930637898efa26725267a5c9f13e4f80ba51df
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NKeyword.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NLambda.class b/src/main/resources/org/python/indexer/ast/NLambda.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb93567cacc63a0ae1787804ca6fc57dd1a9138d
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NLambda.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NList.class b/src/main/resources/org/python/indexer/ast/NList.class
new file mode 100644
index 0000000000000000000000000000000000000000..99609f875ee5b799640e6a2412ca21b65981665d
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NList.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NListComp.class b/src/main/resources/org/python/indexer/ast/NListComp.class
new file mode 100644
index 0000000000000000000000000000000000000000..006967ff5e0eda76f5d5d9d2a3df3520ccf8b363
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NListComp.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NModule.class b/src/main/resources/org/python/indexer/ast/NModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a0ae963c9242c39bfe10909dd3a4d9053db91b3
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NModule.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NName.class b/src/main/resources/org/python/indexer/ast/NName.class
new file mode 100644
index 0000000000000000000000000000000000000000..03dbee4c6d0f85b95bda75567768f0abc3d48f30
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NName.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NNode$DeepestOverlappingNodeFinder.class b/src/main/resources/org/python/indexer/ast/NNode$DeepestOverlappingNodeFinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..dadf73808892238252065d723216794f2b1ea52d
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NNode$DeepestOverlappingNodeFinder.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NNode.class b/src/main/resources/org/python/indexer/ast/NNode.class
new file mode 100644
index 0000000000000000000000000000000000000000..224168a6caee83aad27a43a50b54d02b8fd14295
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NNode.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NNodeVisitor$StopIterationException.class b/src/main/resources/org/python/indexer/ast/NNodeVisitor$StopIterationException.class
new file mode 100644
index 0000000000000000000000000000000000000000..abe4a7f6d06e5e7be3d913d08cba0492f6b8ef0d
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NNodeVisitor$StopIterationException.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NNodeVisitor.class b/src/main/resources/org/python/indexer/ast/NNodeVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1589a4d0e1e30d976d74603db6bca04a68a97ffc
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NNodeVisitor.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NNum.class b/src/main/resources/org/python/indexer/ast/NNum.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e61423ecf3447524ac664e26def686f67e29774
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NNum.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NPass.class b/src/main/resources/org/python/indexer/ast/NPass.class
new file mode 100644
index 0000000000000000000000000000000000000000..65bcd6bfb6fdf9dfe79f7cbc934bdd4e0a089b89
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NPass.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NPlaceHolder.class b/src/main/resources/org/python/indexer/ast/NPlaceHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..12a98481c86a927bfb83c03d1aeaab0d1d2156d8
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NPlaceHolder.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NPrint.class b/src/main/resources/org/python/indexer/ast/NPrint.class
new file mode 100644
index 0000000000000000000000000000000000000000..f76994e5b0357790b9d960c18d936b9b67ba9c57
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NPrint.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NQname.class b/src/main/resources/org/python/indexer/ast/NQname.class
new file mode 100644
index 0000000000000000000000000000000000000000..a22471827f1c7873da4e370805ad6406ec980823
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NQname.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NRaise.class b/src/main/resources/org/python/indexer/ast/NRaise.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ef8e0a4f8a26d739f68ca59a030731cfa7f62cd
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NRaise.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NRepr.class b/src/main/resources/org/python/indexer/ast/NRepr.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd94e9c42985722b7cecca06016e3cf1c379f53a
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NRepr.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NReturn.class b/src/main/resources/org/python/indexer/ast/NReturn.class
new file mode 100644
index 0000000000000000000000000000000000000000..16e4eeca704b2134cb4a5e45f1fa05407533f4da
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NReturn.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NSequence.class b/src/main/resources/org/python/indexer/ast/NSequence.class
new file mode 100644
index 0000000000000000000000000000000000000000..28f2acdc99f947e77e3d71ffba92e1694da7e681
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NSequence.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NSlice.class b/src/main/resources/org/python/indexer/ast/NSlice.class
new file mode 100644
index 0000000000000000000000000000000000000000..0fe706dca0f881d0f534b0e13aab49eccc7d388f
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NSlice.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NStr.class b/src/main/resources/org/python/indexer/ast/NStr.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0632b97fbe76240f55789b260de82db1e1b055c
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NStr.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NSubscript.class b/src/main/resources/org/python/indexer/ast/NSubscript.class
new file mode 100644
index 0000000000000000000000000000000000000000..a850468f1a3a3509a2fa3d05687d5ba05351fcf3
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NSubscript.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NTryExcept.class b/src/main/resources/org/python/indexer/ast/NTryExcept.class
new file mode 100644
index 0000000000000000000000000000000000000000..4824c17349f8ff15b76c1349876655883bbd9a19
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NTryExcept.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NTryFinally.class b/src/main/resources/org/python/indexer/ast/NTryFinally.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e4f7c7f770bdccffb65ffb23cd370a79dfa10fd
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NTryFinally.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NTuple.class b/src/main/resources/org/python/indexer/ast/NTuple.class
new file mode 100644
index 0000000000000000000000000000000000000000..267e12d526a00f2232a09913c56b27b41ec26528
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NTuple.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NUnaryOp.class b/src/main/resources/org/python/indexer/ast/NUnaryOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bbad25d6ee5722596681f04261419ac98e0fc31
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NUnaryOp.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NUrl.class b/src/main/resources/org/python/indexer/ast/NUrl.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e20ba0b39d965384028ef589fc82680a583ca8a
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NUrl.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NWhile.class b/src/main/resources/org/python/indexer/ast/NWhile.class
new file mode 100644
index 0000000000000000000000000000000000000000..db6ac36e1745d3d6c328affb579cfede8afd3d13
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NWhile.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NWith.class b/src/main/resources/org/python/indexer/ast/NWith.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2fd133705883c1ee6d6b40695a71727f58db7eb
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NWith.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NYield.class b/src/main/resources/org/python/indexer/ast/NYield.class
new file mode 100644
index 0000000000000000000000000000000000000000..be9d768f7b0ba6ec9dfeedfb9dc190c06a595ba5
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NYield.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NameBinder$1.class b/src/main/resources/org/python/indexer/ast/NameBinder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..573e169c7c70dfd421fc3113c41c02d106f14f21
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NameBinder$1.class differ
diff --git a/src/main/resources/org/python/indexer/ast/NameBinder.class b/src/main/resources/org/python/indexer/ast/NameBinder.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f7caaa8bc30f0915524e256889fa26f8c4077df
Binary files /dev/null and b/src/main/resources/org/python/indexer/ast/NameBinder.class differ
diff --git a/src/main/resources/org/python/indexer/demos/DocStringParser.class b/src/main/resources/org/python/indexer/demos/DocStringParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..86098d90d954fe3015a3220757b7e0abffb9a933
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/DocStringParser.class differ
diff --git a/src/main/resources/org/python/indexer/demos/HtmlDemo.class b/src/main/resources/org/python/indexer/demos/HtmlDemo.class
new file mode 100644
index 0000000000000000000000000000000000000000..6bc748d00628ca0c2daad6e8eea1f70103b80f86
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/HtmlDemo.class differ
diff --git a/src/main/resources/org/python/indexer/demos/HtmlOutline$1.class b/src/main/resources/org/python/indexer/demos/HtmlOutline$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4cee617994cbe78f1d48800b2fcd755750ea04fe
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/HtmlOutline$1.class differ
diff --git a/src/main/resources/org/python/indexer/demos/HtmlOutline.class b/src/main/resources/org/python/indexer/demos/HtmlOutline.class
new file mode 100644
index 0000000000000000000000000000000000000000..f0a10bfcb8d52626b330b3515d9154434d47af2c
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/HtmlOutline.class differ
diff --git a/src/main/resources/org/python/indexer/demos/Linker$1.class b/src/main/resources/org/python/indexer/demos/Linker$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ba36d775295835824826bdcdc1046cd54b0cb5f1
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/Linker$1.class differ
diff --git a/src/main/resources/org/python/indexer/demos/Linker.class b/src/main/resources/org/python/indexer/demos/Linker.class
new file mode 100644
index 0000000000000000000000000000000000000000..2440acf7339a0b7e66311917ca201feac6cc2d81
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/Linker.class differ
diff --git a/src/main/resources/org/python/indexer/demos/StyleApplier$1.class b/src/main/resources/org/python/indexer/demos/StyleApplier$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d611a299ea3885d89389038e24c7dea2dc92bc4
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/StyleApplier$1.class differ
diff --git a/src/main/resources/org/python/indexer/demos/StyleApplier$EndTag.class b/src/main/resources/org/python/indexer/demos/StyleApplier$EndTag.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9b951fb45323265fa874a651d5b982fd8a4194a
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/StyleApplier$EndTag.class differ
diff --git a/src/main/resources/org/python/indexer/demos/StyleApplier$StartTag.class b/src/main/resources/org/python/indexer/demos/StyleApplier$StartTag.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e6bee64599dabee180bc14cd929cb4767443201
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/StyleApplier$StartTag.class differ
diff --git a/src/main/resources/org/python/indexer/demos/StyleApplier$Tag.class b/src/main/resources/org/python/indexer/demos/StyleApplier$Tag.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3f533d3731b6b7ecd938c79d24711a132502316
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/StyleApplier$Tag.class differ
diff --git a/src/main/resources/org/python/indexer/demos/StyleApplier.class b/src/main/resources/org/python/indexer/demos/StyleApplier.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f7f61eafb465bae604f02aff9576ef0e5119cc4
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/StyleApplier.class differ
diff --git a/src/main/resources/org/python/indexer/demos/Styler$1.class b/src/main/resources/org/python/indexer/demos/Styler$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa036636ddc75051be82da664708cd14f7f0cc5b
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/Styler$1.class differ
diff --git a/src/main/resources/org/python/indexer/demos/Styler$2.class b/src/main/resources/org/python/indexer/demos/Styler$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0619ab57f184ce0895ea6bedf6228d7f0b4ac1b
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/Styler$2.class differ
diff --git a/src/main/resources/org/python/indexer/demos/Styler.class b/src/main/resources/org/python/indexer/demos/Styler.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f772a8aa89d2176a7a3fd6ef146be75661044ae
Binary files /dev/null and b/src/main/resources/org/python/indexer/demos/Styler.class differ
diff --git a/src/main/resources/org/python/indexer/types/NClassType.class b/src/main/resources/org/python/indexer/types/NClassType.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f43a3bfc358bef7417a2e40034b7f1d1b632f16
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NClassType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NDictType.class b/src/main/resources/org/python/indexer/types/NDictType.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fea4719e0eee6916ec156eb362220557ad66195
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NDictType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NFuncType.class b/src/main/resources/org/python/indexer/types/NFuncType.class
new file mode 100644
index 0000000000000000000000000000000000000000..041f4c0875d46e55392bafacc6cc512dfae6f5b6
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NFuncType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NInstanceType.class b/src/main/resources/org/python/indexer/types/NInstanceType.class
new file mode 100644
index 0000000000000000000000000000000000000000..5069a2b98bc2eababa812781d4f6749db982f7e8
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NInstanceType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NListType.class b/src/main/resources/org/python/indexer/types/NListType.class
new file mode 100644
index 0000000000000000000000000000000000000000..65aab83926d6997efc40f3399eac310e586d303b
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NListType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NModuleType.class b/src/main/resources/org/python/indexer/types/NModuleType.class
new file mode 100644
index 0000000000000000000000000000000000000000..5bf1a558a790d75edebeef83053c137165cdd770
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NModuleType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NTupleType.class b/src/main/resources/org/python/indexer/types/NTupleType.class
new file mode 100644
index 0000000000000000000000000000000000000000..3422164975cfc23fbff33616f97031005be0c16d
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NTupleType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NType$CyclicTypeRecorder.class b/src/main/resources/org/python/indexer/types/NType$CyclicTypeRecorder.class
new file mode 100644
index 0000000000000000000000000000000000000000..64634ee5172442e9002ea32400aedcdb1970f82e
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NType$CyclicTypeRecorder.class differ
diff --git a/src/main/resources/org/python/indexer/types/NType.class b/src/main/resources/org/python/indexer/types/NType.class
new file mode 100644
index 0000000000000000000000000000000000000000..19355437d3aab7a8d788490737aab203a87716ff
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NUnionType.class b/src/main/resources/org/python/indexer/types/NUnionType.class
new file mode 100644
index 0000000000000000000000000000000000000000..7b1278c1d38ca78b340beff1dc574eaea2a27c58
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NUnionType.class differ
diff --git a/src/main/resources/org/python/indexer/types/NUnknownType.class b/src/main/resources/org/python/indexer/types/NUnknownType.class
new file mode 100644
index 0000000000000000000000000000000000000000..66e48c39752df4068de654cc260d113464f7ee72
Binary files /dev/null and b/src/main/resources/org/python/indexer/types/NUnknownType.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngine$1.class b/src/main/resources/org/python/jsr223/PyScriptEngine$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..807c895bd8cde79b48fd7a39be9c6817b799eeb8
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngine$1.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngine$PyCompiledScript.class b/src/main/resources/org/python/jsr223/PyScriptEngine$PyCompiledScript.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4c284a8af2b4764132b3d2e9049fd348eb59c38
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngine$PyCompiledScript.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngine.class b/src/main/resources/org/python/jsr223/PyScriptEngine.class
new file mode 100644
index 0000000000000000000000000000000000000000..feb26314ebb321f6dd633784b1e83a149ecb0237
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngine.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineFactory.class b/src/main/resources/org/python/jsr223/PyScriptEngineFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..20ee5255c9eced67e8d5914476b653a54ec14fd1
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineFactory.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$PyExposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb55f0cd46bf0e20b05208db24b8da080c860a8e
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$PyExposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$ScopeIterator.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$ScopeIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f666594f429b948b33e536cefbc0104087abec8
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$ScopeIterator.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$__delitem___exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$__delitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ddab8d5fe9e8909f7d25b542e30840dac6e72c2
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$__delitem___exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$__getitem___exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$__getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d411c0e3902fa3271f352fab40a2ea2e76dc2229
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$__getitem___exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$__iter___exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..54f8e62be263ceea30cb337791817601721b4ad1
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$__setitem___exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$__setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b7a7809537c0c2aa15fd322a0efeec95b70cdc5
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$__setitem___exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$context_descriptor.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$context_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..59aeb03a95f2e019e5872b691f924d88a018342a
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$context_descriptor.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$engine_descriptor.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$engine_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6d9cded920d262807483f35c842c8ba3e0de6655
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$engine_descriptor.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope___contains___exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope___contains___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..92f6226f7c2460055f4c0a0bd18f885934c88b8d
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope___contains___exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_get_exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_get_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c84309a56b47c25148db8f54fa99d58cdd291f89
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_get_exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_has_key_exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_has_key_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..56160a512e1f7272681d3b90f75466bc11e90e7d
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_has_key_exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_keys_exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_keys_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f14dc8ff16d7e48f49b504c062d0257178ca3a7
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_keys_exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_setdefault_exposer.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_setdefault_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e0b6d2f3f6b160e6dd99396ebc6251873fa0899
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope$scope_setdefault_exposer.class differ
diff --git a/src/main/resources/org/python/jsr223/PyScriptEngineScope.class b/src/main/resources/org/python/jsr223/PyScriptEngineScope.class
new file mode 100644
index 0000000000000000000000000000000000000000..54801d2f86f7bd01a13a3db068b49cfb1c5a3e00
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PyScriptEngineScope.class differ
diff --git a/src/main/resources/org/python/jsr223/PythonCallable.class b/src/main/resources/org/python/jsr223/PythonCallable.class
new file mode 100644
index 0000000000000000000000000000000000000000..701c62bcc7383204f5773e76520d6e9fe05da83c
Binary files /dev/null and b/src/main/resources/org/python/jsr223/PythonCallable.class differ
diff --git a/src/main/resources/org/python/jsr223/ScriptEngineIOTest.class b/src/main/resources/org/python/jsr223/ScriptEngineIOTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..1cee151bb3d274336d921a9f83ad305bba62609c
Binary files /dev/null and b/src/main/resources/org/python/jsr223/ScriptEngineIOTest.class differ
diff --git a/src/main/resources/org/python/jsr223/ScriptEngineTest$ThreadLocalBindingsTest.class b/src/main/resources/org/python/jsr223/ScriptEngineTest$ThreadLocalBindingsTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2cd8bdfe34bba7093406f06f77564c8519fb0ab
Binary files /dev/null and b/src/main/resources/org/python/jsr223/ScriptEngineTest$ThreadLocalBindingsTest.class differ
diff --git a/src/main/resources/org/python/jsr223/ScriptEngineTest.class b/src/main/resources/org/python/jsr223/ScriptEngineTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4bde1ab3e460bd903d83b34a6ad1c7a54a67ff8
Binary files /dev/null and b/src/main/resources/org/python/jsr223/ScriptEngineTest.class differ
diff --git a/src/main/resources/org/python/modules/ArrayModule.class b/src/main/resources/org/python/modules/ArrayModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..14920b9166be8c3b1dea72961dc8f8847170a92e
Binary files /dev/null and b/src/main/resources/org/python/modules/ArrayModule.class differ
diff --git a/src/main/resources/org/python/modules/OperatorFunctions.class b/src/main/resources/org/python/modules/OperatorFunctions.class
new file mode 100644
index 0000000000000000000000000000000000000000..70bed0eae269c06a055d2b066791fa934672c11c
Binary files /dev/null and b/src/main/resources/org/python/modules/OperatorFunctions.class differ
diff --git a/src/main/resources/org/python/modules/PyIOFile.class b/src/main/resources/org/python/modules/PyIOFile.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c15c2b5d27feb26e1722713390af40e490137a7
Binary files /dev/null and b/src/main/resources/org/python/modules/PyIOFile.class differ
diff --git a/src/main/resources/org/python/modules/PyIOFileFactory$FileIOFile.class b/src/main/resources/org/python/modules/PyIOFileFactory$FileIOFile.class
new file mode 100644
index 0000000000000000000000000000000000000000..22998d58226a45f4466f0bdc153cb1335d340098
Binary files /dev/null and b/src/main/resources/org/python/modules/PyIOFileFactory$FileIOFile.class differ
diff --git a/src/main/resources/org/python/modules/PyIOFileFactory$ObjectIOFile.class b/src/main/resources/org/python/modules/PyIOFileFactory$ObjectIOFile.class
new file mode 100644
index 0000000000000000000000000000000000000000..cdf7cc170dd416caf4a94210aad630e5ef609533
Binary files /dev/null and b/src/main/resources/org/python/modules/PyIOFileFactory$ObjectIOFile.class differ
diff --git a/src/main/resources/org/python/modules/PyIOFileFactory$cStringIOFile.class b/src/main/resources/org/python/modules/PyIOFileFactory$cStringIOFile.class
new file mode 100644
index 0000000000000000000000000000000000000000..6cc71cd451107aaa2a48a555d6b46e3a1cf860ca
Binary files /dev/null and b/src/main/resources/org/python/modules/PyIOFileFactory$cStringIOFile.class differ
diff --git a/src/main/resources/org/python/modules/PyIOFileFactory.class b/src/main/resources/org/python/modules/PyIOFileFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..34c727986638739182b318a90dd534d252854ea4
Binary files /dev/null and b/src/main/resources/org/python/modules/PyIOFileFactory.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$PyExposer.class b/src/main/resources/org/python/modules/PyStruct$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..01c4e28aee150e0def717ed5304dd29ed07cb025
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$__class___descriptor.class b/src/main/resources/org/python/modules/PyStruct$__class___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7bf01d6bbad68b8177b4fddfb98821ce61b1627
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$__class___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$exposed___new__.class b/src/main/resources/org/python/modules/PyStruct$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8b5352e3da712ed634667eb6723dfb98d05dbcc
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$format_descriptor.class b/src/main/resources/org/python/modules/PyStruct$format_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e29435ef488d0957d41b919c5b507382e6198c2
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$format_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$pack_exposer.class b/src/main/resources/org/python/modules/PyStruct$pack_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e275676af3eefeb5554d58ca6c5e61e556a43ca3
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$pack_exposer.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$pack_into_exposer.class b/src/main/resources/org/python/modules/PyStruct$pack_into_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a91b9ff8366f7fe565a4f768fbd4e69096e64ef8
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$pack_into_exposer.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$size_descriptor.class b/src/main/resources/org/python/modules/PyStruct$size_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d985a3b9629e44656e45d303b83dd9dfd21fa270
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$size_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$unpack_exposer.class b/src/main/resources/org/python/modules/PyStruct$unpack_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b55bc0accb13cb53aa4d2af56692a454e0d5d65
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$unpack_exposer.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct$unpack_from_exposer.class b/src/main/resources/org/python/modules/PyStruct$unpack_from_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..06718e1acbfd3378d8bad8954e7d4b9df08e55c2
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct$unpack_from_exposer.class differ
diff --git a/src/main/resources/org/python/modules/PyStruct.class b/src/main/resources/org/python/modules/PyStruct.class
new file mode 100644
index 0000000000000000000000000000000000000000..eda349f38656dc0df3419e3f5b1d748cceb83bb7
Binary files /dev/null and b/src/main/resources/org/python/modules/PyStruct.class differ
diff --git a/src/main/resources/org/python/modules/SHA224Digest.class b/src/main/resources/org/python/modules/SHA224Digest.class
new file mode 100644
index 0000000000000000000000000000000000000000..fec8fc384ac44e37ac933242f25c926efbb79846
Binary files /dev/null and b/src/main/resources/org/python/modules/SHA224Digest.class differ
diff --git a/src/main/resources/org/python/modules/Setup.class b/src/main/resources/org/python/modules/Setup.class
new file mode 100644
index 0000000000000000000000000000000000000000..aadde29135303d26f3e15d815a5d8d6378f92472
Binary files /dev/null and b/src/main/resources/org/python/modules/Setup.class differ
diff --git a/src/main/resources/org/python/modules/_codecs$ByteOrder.class b/src/main/resources/org/python/modules/_codecs$ByteOrder.class
new file mode 100644
index 0000000000000000000000000000000000000000..96720c1509f4be298cc749d76e3493ba38822b31
Binary files /dev/null and b/src/main/resources/org/python/modules/_codecs$ByteOrder.class differ
diff --git a/src/main/resources/org/python/modules/_codecs$EncodingMap$PyExposer.class b/src/main/resources/org/python/modules/_codecs$EncodingMap$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..50ea8aab8db0459eb67eb9deb0cec7ef2f4d69bc
Binary files /dev/null and b/src/main/resources/org/python/modules/_codecs$EncodingMap$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_codecs$EncodingMap.class b/src/main/resources/org/python/modules/_codecs$EncodingMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd9de8d1b79b54815ba74c15ab66e323d50ca3af
Binary files /dev/null and b/src/main/resources/org/python/modules/_codecs$EncodingMap.class differ
diff --git a/src/main/resources/org/python/modules/_codecs.class b/src/main/resources/org/python/modules/_codecs.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb14f50b3fed2cf3b5c5c66338a4bab2cc0aa29a
Binary files /dev/null and b/src/main/resources/org/python/modules/_codecs.class differ
diff --git a/src/main/resources/org/python/modules/_collections/Collections.class b/src/main/resources/org/python/modules/_collections/Collections.class
new file mode 100644
index 0000000000000000000000000000000000000000..748c0b39322cbfaba7eb0b9c57f6ccd3cfdb263a
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/Collections.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$1.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5748dfcefcdcd6513b587134982e28b294d05b1d
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$1.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$PyExposer.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ba40c13c467ff4f0bfea6d443a9aaee35c35772
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$default_factory_descriptor.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$default_factory_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9945dcfe5acf53430779904b290f5eabc828ecd9
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$default_factory_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___getitem___exposer.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e71f861b37474be3604efde62e6cea2eb974dab
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___init___exposer.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4964e7d39e67a12607e16810bfdd7a6899221a8
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___missing___exposer.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___missing___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..37e4519d1729ed8359a2312623aeda8945040262
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___missing___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___reduce___exposer.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d74ac6dcddac611fa914294f6054ff9cd48642d6
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict_copy_exposer.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict_copy_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..11c5d32f3edc7ae22e9176a3747332365220dda3
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict_copy_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict_toString_exposer.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e318aaba97375646ae80dd3be2a9725054d6f7d
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$defaultdict_toString_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict$exposed___new__.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6d89f4fda8203729dec73906da858df3c52d56b
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDict.class b/src/main/resources/org/python/modules/_collections/PyDefaultDict.class
new file mode 100644
index 0000000000000000000000000000000000000000..5117da8aadf96e65d4fca78795c1020800dc1eb1
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDict.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDefaultDictDerived.class b/src/main/resources/org/python/modules/_collections/PyDefaultDictDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..20c9c07a5cbbc399341de2801e87eb9b17593ed8
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDefaultDictDerived.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$Node.class b/src/main/resources/org/python/modules/_collections/PyDeque$Node.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd4411c991f23b4a2e097fe3aee059bd496ba7df
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$Node.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$PyDequeIter.class b/src/main/resources/org/python/modules/_collections/PyDeque$PyDequeIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8171f3ec6e654be4f519eaa9f87c67c00e44680
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$PyDequeIter.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$PyExposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3406264ad79b59562b4961c7d2ca92bc803e62b
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___copy___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___copy___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..193e7cac141356b917b9ca8e762e6a256f679679
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___copy___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___delitem___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___delitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2c6aa5c45e3f79c1a06ad7ceaf3fdf0ab99d926
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___delitem___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___eq___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..da67df3c8f48ecf8d81570a0a7f7b40008a82dc5
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___eq___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___ge___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___ge___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2fa58d90027182d7f125711b48f65a59d730993
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___ge___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___getitem___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___getitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6bfd950cd736fa21f0cd31c1a6e6f617b1934d9
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___getitem___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___gt___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___gt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7a6b34537fef08cc164ab2f95671454274cc782
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___gt___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___init___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d628c9676a73142e6ea974b75bf1787eee62c6b3
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___iter___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3de2548b123458c47721bb31ac043a1fbe201e3
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___le___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___le___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae2fb454f2586e22dc63475038cec1c4375a46b5
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___le___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___len___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b66934c701eb23154e5cf0e3c3aaa0d6df3c803
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___len___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___lt___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___lt___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa2a4d71b2479841a9a25562ccd9874c9f6518f0
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___lt___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___ne___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5905b01142abb908acb01e6ebd855c7292a5f379
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___ne___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___nonzero___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___nonzero___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc29f3d969ff595714289fcab2dcb98e8b7a6ef6
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___nonzero___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___reduce___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d15733306135ad5511ded370b7aa86e42151b50
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque___setitem___exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque___setitem___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8a70bc9edd4a354e77864188299e221d1854aff3
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque___setitem___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_append_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_append_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e52edcb7df621ed8f4e98b1f071720d7498b74c
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_append_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_appendleft_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_appendleft_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d91d8457253ea31101ede036cc8b3e1364a7d5a2
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_appendleft_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_clear_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_clear_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e2fe22eaeaf42ee5625f1161e7a609257847849
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_clear_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_extend_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_extend_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e7e5182a964a7893400edffd3f8bf056ec5957d
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_extend_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_extendleft_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_extendleft_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8cc23d862e506ec862181dc265dfaf4de0e4eb9
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_extendleft_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_hashCode_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_hashCode_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e84638d43300c21e2c276d156be2c37db431341
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_hashCode_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_pop_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_pop_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c67ceddcae563842d5ebec9fea63363533749a84
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_pop_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_popleft_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_popleft_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..48be8550600bcb73e8cf6da232f01a07e52e05dd
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_popleft_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_remove_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_remove_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6c7b5b76cabdffdf71159626a03be250b978fbd
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_remove_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_rotate_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_rotate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..234f375c7b6fd1e96a4f8f169f05594dee1269a5
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_rotate_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$deque_toString_exposer.class b/src/main/resources/org/python/modules/_collections/PyDeque$deque_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..72f499669bcbfdbcee52d123cf6dba1589e5dbb6
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$deque_toString_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque$exposed___new__.class b/src/main/resources/org/python/modules/_collections/PyDeque$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..01587f24c18f3e909586071afe859f4af44372ce
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDeque.class b/src/main/resources/org/python/modules/_collections/PyDeque.class
new file mode 100644
index 0000000000000000000000000000000000000000..d538db1ad8514ff16236a8a6707f463b123d9a21
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDeque.class differ
diff --git a/src/main/resources/org/python/modules/_collections/PyDequeDerived.class b/src/main/resources/org/python/modules/_collections/PyDequeDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9cbd4cd51c41ab7672e7a0a18f7bf169b0a18dd1
Binary files /dev/null and b/src/main/resources/org/python/modules/_collections/PyDequeDerived.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$PyExposer.class b/src/main/resources/org/python/modules/_csv/PyDialect$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f36810e5cf650705f9f645982b5dfc48dc828eb
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$delimiter_descriptor.class b/src/main/resources/org/python/modules/_csv/PyDialect$delimiter_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7921edb213a90710faa61d81e407de28883f83e9
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$delimiter_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$doublequote_descriptor.class b/src/main/resources/org/python/modules/_csv/PyDialect$doublequote_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..16b7ce7bcc94562d1d584c4cae5894b30c609360
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$doublequote_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$escapechar_descriptor.class b/src/main/resources/org/python/modules/_csv/PyDialect$escapechar_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..44f83defc4705319bc1f6e82b64e56f11f87fc9e
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$escapechar_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$exposed___new__.class b/src/main/resources/org/python/modules/_csv/PyDialect$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb127d7fb24579513bbd20ef39892a6650e6c5f0
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$lineterminator_descriptor.class b/src/main/resources/org/python/modules/_csv/PyDialect$lineterminator_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..dae43e99a103228fe0424462d5dd7ce15c1a1055
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$lineterminator_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$quotechar_descriptor.class b/src/main/resources/org/python/modules/_csv/PyDialect$quotechar_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3020d99e7f57a0c67cca8cad12440da509367208
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$quotechar_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$quoting_descriptor.class b/src/main/resources/org/python/modules/_csv/PyDialect$quoting_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7eb4d051a66f54c14890c830713ed8cb809641f2
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$quoting_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$skipinitialspace_descriptor.class b/src/main/resources/org/python/modules/_csv/PyDialect$skipinitialspace_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..066591e5fa779937e585dfd1943e75811359d401
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$skipinitialspace_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect$strict_descriptor.class b/src/main/resources/org/python/modules/_csv/PyDialect$strict_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad5f34b7091419ef8f6c8195b12c9347e488df9b
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect$strict_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialect.class b/src/main/resources/org/python/modules/_csv/PyDialect.class
new file mode 100644
index 0000000000000000000000000000000000000000..50197da36856f5e22d436fc6ba8001d5e6350161
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialect.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyDialectDerived.class b/src/main/resources/org/python/modules/_csv/PyDialectDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..f62ad9dc8ccfe44b3e8a84a953764a67bb219de0
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyDialectDerived.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyReader$1.class b/src/main/resources/org/python/modules/_csv/PyReader$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bb8dbc63abca5fc54da9e032a6378467469efe2
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyReader$1.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyReader$ParserState.class b/src/main/resources/org/python/modules/_csv/PyReader$ParserState.class
new file mode 100644
index 0000000000000000000000000000000000000000..712c6e53549524a3e745c795c0a059fbdf3391a3
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyReader$ParserState.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyReader$PyExposer.class b/src/main/resources/org/python/modules/_csv/PyReader$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1df63db4de41b7457798966f01a95c66f4f0fa8b
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyReader$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyReader$dialect_descriptor.class b/src/main/resources/org/python/modules/_csv/PyReader$dialect_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..54b7db9f4aefe851af160263f2bab26ff8f8dc74
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyReader$dialect_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyReader$line_num_descriptor.class b/src/main/resources/org/python/modules/_csv/PyReader$line_num_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..493fce24ff137e1572f029b7f5792f6d25c25f44
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyReader$line_num_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyReader.class b/src/main/resources/org/python/modules/_csv/PyReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..25547c2e86ea4e3b55e64f569f0ceeefd79b7b56
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyReader.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyWriter$1.class b/src/main/resources/org/python/modules/_csv/PyWriter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c68a8c1f2d55cdcd0be1511f8a0a8b51ea74fb09
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyWriter$1.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyWriter$PyExposer.class b/src/main/resources/org/python/modules/_csv/PyWriter$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d3df551bf2a7f7910c31c1fa8aea7745b55995c
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyWriter$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyWriter$dialect_descriptor.class b/src/main/resources/org/python/modules/_csv/PyWriter$dialect_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7772b3e125d7f4314340f38483486890bab93aa7
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyWriter$dialect_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyWriter$writer_writerow_exposer.class b/src/main/resources/org/python/modules/_csv/PyWriter$writer_writerow_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..82f041abc1767595abf1d2ec0d96f50be335bc24
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyWriter$writer_writerow_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyWriter$writer_writerows_exposer.class b/src/main/resources/org/python/modules/_csv/PyWriter$writer_writerows_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..08e6ffcd908254140f89d5e97eb831e088d8e2bd
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyWriter$writer_writerows_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_csv/PyWriter.class b/src/main/resources/org/python/modules/_csv/PyWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c74c5247ae28d0bec8eb0d79c872ff504e7e719
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/PyWriter.class differ
diff --git a/src/main/resources/org/python/modules/_csv/QuoteStyle.class b/src/main/resources/org/python/modules/_csv/QuoteStyle.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ca656e1fcfd40eb5cd6eefbf3fc906703699e59
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/QuoteStyle.class differ
diff --git a/src/main/resources/org/python/modules/_csv/_csv.class b/src/main/resources/org/python/modules/_csv/_csv.class
new file mode 100644
index 0000000000000000000000000000000000000000..8863f819165666782375c893a3ea874136093fcb
Binary files /dev/null and b/src/main/resources/org/python/modules/_csv/_csv.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial$PyExposer.class b/src/main/resources/org/python/modules/_functools/PyPartial$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dae6fd3055b8b62531d046773f5aa6beb31d2b90
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial$__dict___descriptor.class b/src/main/resources/org/python/modules/_functools/PyPartial$__dict___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..c70dc7c3aaf838a5c6ec0ebbc6632dc8dc6bed2c
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial$__dict___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial$args_descriptor.class b/src/main/resources/org/python/modules/_functools/PyPartial$args_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb0000c725693298f3bd72fa6739c14a8ef6c699
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial$args_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial$exposed___new__.class b/src/main/resources/org/python/modules/_functools/PyPartial$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbcdfa1dc4893b6276c40f3df83e344a18d83f8a
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial$func_descriptor.class b/src/main/resources/org/python/modules/_functools/PyPartial$func_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5d5cf2bdcf1959accbc82814b1da8636031b864b
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial$func_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial$keywords_descriptor.class b/src/main/resources/org/python/modules/_functools/PyPartial$keywords_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e174e035c7e734344184cb6c408e498cee6fb1e0
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial$keywords_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial$partial___call___exposer.class b/src/main/resources/org/python/modules/_functools/PyPartial$partial___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c75d3c75de8956dc3235fc8a187b2a95d941428
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial$partial___call___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial$partial___setattr___exposer.class b/src/main/resources/org/python/modules/_functools/PyPartial$partial___setattr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a80e70f38d90e6b90878028aceb443b54f8e52f2
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial$partial___setattr___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartial.class b/src/main/resources/org/python/modules/_functools/PyPartial.class
new file mode 100644
index 0000000000000000000000000000000000000000..03e950ba0406c750f74ae51a8b96dadb6585dcaa
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartial.class differ
diff --git a/src/main/resources/org/python/modules/_functools/PyPartialDerived.class b/src/main/resources/org/python/modules/_functools/PyPartialDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd314ef28c4af32f6bad93d9fcac852382747461
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/PyPartialDerived.class differ
diff --git a/src/main/resources/org/python/modules/_functools/_functools.class b/src/main/resources/org/python/modules/_functools/_functools.class
new file mode 100644
index 0000000000000000000000000000000000000000..8154670856dd34bf251e29d7dd63598049435fc9
Binary files /dev/null and b/src/main/resources/org/python/modules/_functools/_functools.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$1.class b/src/main/resources/org/python/modules/_hashlib$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb744e2544a90f6a6d11135dd07f1c6d3b710dfa
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$1.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$1.class b/src/main/resources/org/python/modules/_hashlib$Hash$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..9baac97cdba76b930f81cdc572479d05d9ac06c9
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$1.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$HASH_copy_exposer.class b/src/main/resources/org/python/modules/_hashlib$Hash$HASH_copy_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..18216a7d1478dd0de4d1df7b7c91d88340c45bce
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$HASH_copy_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$HASH_digest_exposer.class b/src/main/resources/org/python/modules/_hashlib$Hash$HASH_digest_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..95623622ed5ef8c11549c84565e35bc59b4babf3
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$HASH_digest_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$HASH_hexdigest_exposer.class b/src/main/resources/org/python/modules/_hashlib$Hash$HASH_hexdigest_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..20b787cf2c58d2cc828582a8f9042b6856628045
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$HASH_hexdigest_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$HASH_update_exposer.class b/src/main/resources/org/python/modules/_hashlib$Hash$HASH_update_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d574aede61aab6aae78ff6fe0e4a2925cdf5c299
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$HASH_update_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$PyExposer.class b/src/main/resources/org/python/modules/_hashlib$Hash$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5017c47537736ab10ccb12a81ca0c79ef3092355
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$block_size_descriptor.class b/src/main/resources/org/python/modules/_hashlib$Hash$block_size_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e7faba11917621fc4e03b6fb7e44486a5016eaa
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$block_size_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$digest_size_descriptor.class b/src/main/resources/org/python/modules/_hashlib$Hash$digest_size_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3feed527c09a1a6c912569752092952c5444fed
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$digest_size_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$digestsize_descriptor.class b/src/main/resources/org/python/modules/_hashlib$Hash$digestsize_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3090304f8d1e36b1d823ca95cb0970dfcbc3c16
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$digestsize_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash$name_descriptor.class b/src/main/resources/org/python/modules/_hashlib$Hash$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd1db18f7779274f51a6d185ea8253c26f0766b5
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash$name_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib$Hash.class b/src/main/resources/org/python/modules/_hashlib$Hash.class
new file mode 100644
index 0000000000000000000000000000000000000000..dcc9a5dd54800931e3a7a49cf5d7395f7036fc8c
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib$Hash.class differ
diff --git a/src/main/resources/org/python/modules/_hashlib.class b/src/main/resources/org/python/modules/_hashlib.class
new file mode 100644
index 0000000000000000000000000000000000000000..53f5e4fb0a5794c2a005149f3c03cd4db876366c
Binary files /dev/null and b/src/main/resources/org/python/modules/_hashlib.class differ
diff --git a/src/main/resources/org/python/modules/_io/Closer.class b/src/main/resources/org/python/modules/_io/Closer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0fca533cce89ede92a414ac5eafb39597a69f794
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/Closer.class differ
diff --git a/src/main/resources/org/python/modules/_io/OpenMode.class b/src/main/resources/org/python/modules/_io/OpenMode.class
new file mode 100644
index 0000000000000000000000000000000000000000..aaa1c607559a327cca7415787c4b84d43bb33eb1
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/OpenMode.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$1.class b/src/main/resources/org/python/modules/_io/PyFileIO$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..31e15fc2f9c789952be6bae9bc7e7362bc8d5271
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$1.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_close_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_close_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..574db210179a6ed4c50cbc8e711a53b86a1fcb10
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_close_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_fileno_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_fileno_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a7bf45197bb05cbf518817f9493423260087fde4
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_fileno_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_flush_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_flush_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..76d9a41ad04064df680885eb3a63f6dc7c99ebb5
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_flush_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_isatty_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_isatty_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f6ba0773c2a5534e47aaaf0da49b5827508c554
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_isatty_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_readable_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_readable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9837db8586be09dde6150fbb65ec95cb28759ec4
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_readable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_readinto_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_readinto_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc7523951fe5f0c2c63f8c5ec6565ff54032eab6
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_readinto_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_seek_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_seek_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2065709997d3274b3258cdfb54bc2839f2958cf2
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_seek_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_seekable_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_seekable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..08ead44276ab96c5ff38696c71e0c6aaae2624a8
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_seekable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_toString_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6070943711bcfac3622087cea0c4bd998b57560
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_toString_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_truncate_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_truncate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e2d196464b9329c42a681606c53120f8f7ad03b
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_truncate_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_writable_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_writable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2f8751e97551f97075b0ce23221394aad2b7d99d
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_writable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_write_exposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_write_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e39d1ec23f0fbd80b86a7bd19aac9da9bf3e4f9e
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$FileIO_write_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$PyExposer.class b/src/main/resources/org/python/modules/_io/PyFileIO$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..10154ae53597fab8281d45b57ee70358b32e9867
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$closefd_descriptor.class b/src/main/resources/org/python/modules/_io/PyFileIO$closefd_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ada0b4c6343731853a5a560e433cb4ccfce092fd
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$closefd_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$exposed___new__.class b/src/main/resources/org/python/modules/_io/PyFileIO$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3f6ac9df5ced2fe9f6b4bf197385eef37290dfb
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO$mode_descriptor.class b/src/main/resources/org/python/modules/_io/PyFileIO$mode_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9eb015f81e6321823db9a344175f8e634ff10345
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO$mode_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIO.class b/src/main/resources/org/python/modules/_io/PyFileIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..8579b7324608926f042636f4c06ed3f61d5c5121
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIO.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyFileIODerived.class b/src/main/resources/org/python/modules/_io/PyFileIODerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..76ff38c0593312ab67a4a372a7f013e5b8a5d1ab
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyFileIODerived.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$PyExposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c7349280332bad61fb0baf3500e5701ac0014eb
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase___enter___exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase___enter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc2851030879d27d319c95b24ec4819058fac6f2
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase___enter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase___exit___exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase___exit___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9025c843b6e15fae218e573ffb5abae0a44e120
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase___exit___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkClosed_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkClosed_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b89327834f8bdda6fd17557cd51e5730e4282083
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkClosed_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkReadable_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkReadable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d72bc3b3f57c179e7a0f7c394d306091444f108a
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkReadable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkSeekable_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkSeekable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..59e532e287d74548061482967234d7df06d4ea4c
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkSeekable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkWritable_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkWritable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c88789c622ca328c7c6669effd9b05d0be362cf
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__checkWritable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__unsupported_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__unsupported_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e88afe818f78205fdc928f545c08ae59c6cb462
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase__unsupported_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_close_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_close_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..536d4e9a0a15a13e43ded71740319806ca5b0c12
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_close_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_fileno_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_fileno_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..84569010a3eec8f4270b492b5099c97ff38427b1
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_fileno_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_flush_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_flush_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..bff5f2e01fa263a246b33d03a290d455ddb70da5
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_flush_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_isatty_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_isatty_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f40ef877ad22a0ec1d0a796becb597ca43b3b932
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_isatty_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_next_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2faa1827f5abec444eba8ec1ca9896a17052974
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readable_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e50034ecdda81517a1122e635b284c84490cb3c
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readline_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readline_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f127a9fb79aca915b4e2d4ae74a13309da2f3d2
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readline_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readlines_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readlines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..92258610fbc91f936b4d2547c5d9ad8d2bc36d45
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_readlines_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_seek_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_seek_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ed5895060b6ff3814bd5b076469d91fcf0893f9
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_seek_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_seekable_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_seekable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4628e100e491cbe478cf3b9c24940378f08a8ef7
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_seekable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_tell_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_tell_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1fd9f7e6779cebc073a0c0ac33add6cfd78b4d16
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_tell_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_truncate_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_truncate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e8a0bb31d08e878d5d7cb5cd705158047fdeca7
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_truncate_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_writable_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_writable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..91aa972238544d0511b0c838d9cb8eeca89ea88b
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_writable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_writelines_exposer.class b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_writelines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e5c47ffd5fa8dcf6dbba33ad3faa3d0152c895b
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$_IOBase_writelines_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$__dict___descriptor.class b/src/main/resources/org/python/modules/_io/PyIOBase$__dict___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..60c20555134247849cc0bfefd9c995e63bfadd42
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$__dict___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$closed_descriptor.class b/src/main/resources/org/python/modules/_io/PyIOBase$closed_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0fb7a37468a17fb051ab7fe9b4bf9511a20bb4fc
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$closed_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase$exposed___new__.class b/src/main/resources/org/python/modules/_io/PyIOBase$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..0206319b925d31ef0d8a95d2cbbd89ae4895e373
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBase.class b/src/main/resources/org/python/modules/_io/PyIOBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..a42162d72e8b78f41d672e9026f1906e20c3bb02
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBase.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyIOBaseDerived.class b/src/main/resources/org/python/modules/_io/PyIOBaseDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..86bee4c2b181974f5ba594dd5349954b8a645fa7
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyIOBaseDerived.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyRawIOBase$PyExposer.class b/src/main/resources/org/python/modules/_io/PyRawIOBase$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..900ac970084b85100e243d64fbc4a201e0b12824
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyRawIOBase$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_read_exposer.class b/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_read_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9143667e16cdf157b93b0b2501806bb8e79e29fc
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_read_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_readall_exposer.class b/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_readall_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed86da5d2cb381c7bc05c9a90c252dd26923d99d
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_readall_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_readinto_exposer.class b/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_readinto_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..81a2d3658a82c493d78aeae4b0bab99d48dbcbef
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_readinto_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_write_exposer.class b/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_write_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d74bc65293462d60f161e42d59dfc4ab7b14a7a6
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyRawIOBase$_RawIOBase_write_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyRawIOBase$exposed___new__.class b/src/main/resources/org/python/modules/_io/PyRawIOBase$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..5834aebf68906b1772c30db4a9bd76d111280412
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyRawIOBase$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyRawIOBase.class b/src/main/resources/org/python/modules/_io/PyRawIOBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..feeb3b9756064212f74f6aa24075ca59527dae94
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyRawIOBase.class differ
diff --git a/src/main/resources/org/python/modules/_io/PyRawIOBaseDerived.class b/src/main/resources/org/python/modules/_io/PyRawIOBaseDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..aad87809187b5f7cb1424aefd01e023fdcb584fe
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/PyRawIOBaseDerived.class differ
diff --git a/src/main/resources/org/python/modules/_io/_io$1.class b/src/main/resources/org/python/modules/_io/_io$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac22f1dc97f25d8995e5969cd7af76124b372958
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/_io$1.class differ
diff --git a/src/main/resources/org/python/modules/_io/_io.class b/src/main/resources/org/python/modules/_io/_io.class
new file mode 100644
index 0000000000000000000000000000000000000000..17324eb1a3dc05a0d815d9b3f896eb2bb34699fb
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/_io.class differ
diff --git a/src/main/resources/org/python/modules/_io/_ioTest.class b/src/main/resources/org/python/modules/_io/_ioTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..208d9e25422a3295a2e85a8e306d1454aba93097
Binary files /dev/null and b/src/main/resources/org/python/modules/_io/_ioTest.class differ
diff --git a/src/main/resources/org/python/modules/_marshal$Marshaller.class b/src/main/resources/org/python/modules/_marshal$Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ffae35834a813943b7a3ed22e0a5847eab655b4
Binary files /dev/null and b/src/main/resources/org/python/modules/_marshal$Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/_marshal$Unmarshaller.class b/src/main/resources/org/python/modules/_marshal$Unmarshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1107526fbd6a4ba7316303776eaadb82087039a
Binary files /dev/null and b/src/main/resources/org/python/modules/_marshal$Unmarshaller.class differ
diff --git a/src/main/resources/org/python/modules/_marshal.class b/src/main/resources/org/python/modules/_marshal.class
new file mode 100644
index 0000000000000000000000000000000000000000..e3c99be8b4d9dd9e1735e3b862893edee8632c1e
Binary files /dev/null and b/src/main/resources/org/python/modules/_marshal.class differ
diff --git a/src/main/resources/org/python/modules/_py_compile.class b/src/main/resources/org/python/modules/_py_compile.class
new file mode 100644
index 0000000000000000000000000000000000000000..bca081f5824f55a37f32d85ab36abab2f82e439d
Binary files /dev/null and b/src/main/resources/org/python/modules/_py_compile.class differ
diff --git a/src/main/resources/org/python/modules/_sre.class b/src/main/resources/org/python/modules/_sre.class
new file mode 100644
index 0000000000000000000000000000000000000000..098160f999ab45d9609e360d7eedb08b499d96a6
Binary files /dev/null and b/src/main/resources/org/python/modules/_sre.class differ
diff --git a/src/main/resources/org/python/modules/_systemrestart$1.class b/src/main/resources/org/python/modules/_systemrestart$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a2cbaa796dec18cf57bab712eda24788c40110f
Binary files /dev/null and b/src/main/resources/org/python/modules/_systemrestart$1.class differ
diff --git a/src/main/resources/org/python/modules/_systemrestart.class b/src/main/resources/org/python/modules/_systemrestart.class
new file mode 100644
index 0000000000000000000000000000000000000000..823bd946a09f611ecd8b67c3d69e526ddfca29e4
Binary files /dev/null and b/src/main/resources/org/python/modules/_systemrestart.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition___enter___exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition___enter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..23338852de26dc77fb191b26ed7e2eb2209bae69
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition___enter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition___exit___exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition___exit___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4284234d52dbf1b6695af9297b5650743908e651
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition___exit___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition__is_owned_exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition__is_owned_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..073429777cdd68d898b70da2adef5013636650d1
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition__is_owned_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition_acquire_exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition_acquire_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..59f8f29a6d1f3801f1a23feaa6d27d0e5b89f4ad
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition_acquire_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition_notifyAll_exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition_notifyAll_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..808eebb20dbd566d5623832f17a3d21807f57f5f
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition_notifyAll_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition_notify_all_exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition_notify_all_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ab5ca22509ecf8417a04df5462c0d3be477d6d5
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition_notify_all_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition_notify_exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition_notify_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5859e056f3d2f9dbf13ebe4ee99d55b2d5580141
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition_notify_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition_release_exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition_release_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..490a21cfc12e1233e663bdb665d8177d80c3d233
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition_release_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$Condition_wait_exposer.class b/src/main/resources/org/python/modules/_threading/Condition$Condition_wait_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c5d70796611f4e688baba5895fccaab77f7c2e57
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$Condition_wait_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$PyExposer.class b/src/main/resources/org/python/modules/_threading/Condition$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..edf77e130db638aadc709efcf5fadf768f5dffed
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition$exposed___new__.class b/src/main/resources/org/python/modules/_threading/Condition$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..d574d89e95ea2df594ba6448f7c317e96b702e95
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Condition.class b/src/main/resources/org/python/modules/_threading/Condition.class
new file mode 100644
index 0000000000000000000000000000000000000000..9754044959a56a09048cd2c36bd05bce75870e67
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Condition.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock$Lock___enter___exposer.class b/src/main/resources/org/python/modules/_threading/Lock$Lock___enter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5e6759e53ea1c1eff0e5825c5695b0db22bbf07
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock$Lock___enter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock$Lock___exit___exposer.class b/src/main/resources/org/python/modules/_threading/Lock$Lock___exit___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f87c339b8c41247fd701334909db9f86587fc34
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock$Lock___exit___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock$Lock__is_owned_exposer.class b/src/main/resources/org/python/modules/_threading/Lock$Lock__is_owned_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..996301ea8acbfe26358c8e7c7c5fe0ab3f2a2729
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock$Lock__is_owned_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock$Lock_acquire_exposer.class b/src/main/resources/org/python/modules/_threading/Lock$Lock_acquire_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7eed1b94b7fe7e9c1a8c5afe4edabc9a2a4ce5d3
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock$Lock_acquire_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock$Lock_locked_exposer.class b/src/main/resources/org/python/modules/_threading/Lock$Lock_locked_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c2fef912d7feb712a2812791ef4aec2b56fd114
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock$Lock_locked_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock$Lock_release_exposer.class b/src/main/resources/org/python/modules/_threading/Lock$Lock_release_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a3e0ab773ff88240b8d14b9de7f291f0e7fad18
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock$Lock_release_exposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock$PyExposer.class b/src/main/resources/org/python/modules/_threading/Lock$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7b3526d512ea25d06c44a628946fdfcb11e3a2c
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock$exposed___new__.class b/src/main/resources/org/python/modules/_threading/Lock$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf797889943cb7e0ab8764fb16d5a728da885c89
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_threading/Lock.class b/src/main/resources/org/python/modules/_threading/Lock.class
new file mode 100644
index 0000000000000000000000000000000000000000..f60dd19aa992d9f5579e3384cd5fe1a810c2a0e8
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/Lock.class differ
diff --git a/src/main/resources/org/python/modules/_threading/_threading.class b/src/main/resources/org/python/modules/_threading/_threading.class
new file mode 100644
index 0000000000000000000000000000000000000000..7af7b04d8e93e1fb593d6df983c18eadb3fe0b54
Binary files /dev/null and b/src/main/resources/org/python/modules/_threading/_threading.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/AbstractReference.class b/src/main/resources/org/python/modules/_weakref/AbstractReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..4deb676a6ce2cc24cc9348fe91d6a2818680dceb
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/AbstractReference.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/CallableProxyType$PyExposer.class b/src/main/resources/org/python/modules/_weakref/CallableProxyType$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ae7d1eeb3d2ea442dc957d7c5122793335208dd
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/CallableProxyType$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/CallableProxyType$weakcallableproxy___call___exposer.class b/src/main/resources/org/python/modules/_weakref/CallableProxyType$weakcallableproxy___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..943850c15e069c5c09306e40ac04696e03f13a8a
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/CallableProxyType$weakcallableproxy___call___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/CallableProxyType.class b/src/main/resources/org/python/modules/_weakref/CallableProxyType.class
new file mode 100644
index 0000000000000000000000000000000000000000..5615f49f85f5f2dcdbfd29b1689b5b69712237ce
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/CallableProxyType.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/GlobalRef$RefReaperThread.class b/src/main/resources/org/python/modules/_weakref/GlobalRef$RefReaperThread.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e0abc9eb09534a88df04aadf5f38ef6f957bb7c
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/GlobalRef$RefReaperThread.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/GlobalRef.class b/src/main/resources/org/python/modules/_weakref/GlobalRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..d688a56d9a20ba0fed9d1564456997f9418454be
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/GlobalRef.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/ProxyType$PyExposer.class b/src/main/resources/org/python/modules/_weakref/ProxyType$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b0b8296f5939394b6e5c99da207c480d2523705
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/ProxyType$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/ProxyType.class b/src/main/resources/org/python/modules/_weakref/ProxyType.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c01676669be905952252aea3fab09bb6405d519
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/ProxyType.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/ReferenceType$PyExposer.class b/src/main/resources/org/python/modules/_weakref/ReferenceType$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..121bb6df620d115d8ab3bae5f2ca3501d19eb13c
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/ReferenceType$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/ReferenceType$exposed___new__.class b/src/main/resources/org/python/modules/_weakref/ReferenceType$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ea84ae89a07f0db1954b26cf2a934a6c4e34dff
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/ReferenceType$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/ReferenceType$weakref___call___exposer.class b/src/main/resources/org/python/modules/_weakref/ReferenceType$weakref___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6cd12aff1ca1728504605a7125ee8bf6a8bb0db9
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/ReferenceType$weakref___call___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/ReferenceType$weakref___init___exposer.class b/src/main/resources/org/python/modules/_weakref/ReferenceType$weakref___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0e0f5814de05a60e34681641f62af1d08e459c9
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/ReferenceType$weakref___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/ReferenceType.class b/src/main/resources/org/python/modules/_weakref/ReferenceType.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6daebad858a4e784651702a1cc4503a19350680
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/ReferenceType.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/ReferenceTypeDerived.class b/src/main/resources/org/python/modules/_weakref/ReferenceTypeDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc25c90e16e7fbb01a713d30d5d78b3c6d919584
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/ReferenceTypeDerived.class differ
diff --git a/src/main/resources/org/python/modules/_weakref/WeakrefModule.class b/src/main/resources/org/python/modules/_weakref/WeakrefModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d31ea071a2e682cfe3cb259ce5c61ca1219f02b
Binary files /dev/null and b/src/main/resources/org/python/modules/_weakref/WeakrefModule.class differ
diff --git a/src/main/resources/org/python/modules/binascii.class b/src/main/resources/org/python/modules/binascii.class
new file mode 100644
index 0000000000000000000000000000000000000000..1184b8fab242091b3255e101c3ba192d80cddb97
Binary files /dev/null and b/src/main/resources/org/python/modules/binascii.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$1.class b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c1f97d4227a47395fd393745a765f4151f42754
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$1.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$BZ2Compressor_compress_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$BZ2Compressor_compress_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0da78517694ce98558130738d1e6d5a9923e994e
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$BZ2Compressor_compress_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$BZ2Compressor_flush_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$BZ2Compressor_flush_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ccc7874000477459f10e3ee5007d1416a3583f6
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$BZ2Compressor_flush_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$CaptureStream.class b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$CaptureStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..2fa1781cd3a5069fbf69610fb3818adc5d6468e7
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$CaptureStream.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$PyExposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a4bc11b01de446b187e395d5ff9ba835ab5e791
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$exposed___new__.class b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..749ba24318fc7abf237e57f4bc8e361885df906a
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Compressor.class b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb85f049c5c7ae30c965ed571e1781c265a4f3e8
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Compressor.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2CompressorDerived.class b/src/main/resources/org/python/modules/bz2/PyBZ2CompressorDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d4036d84d6b7a43e5f148fbf41f87d344f27071
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2CompressorDerived.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$BZ2Decompressor___init___exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$BZ2Decompressor___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f067f0e056500bbf521b45e00f5d9b106c386715
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$BZ2Decompressor___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$BZ2Decompressor_decompress_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$BZ2Decompressor_decompress_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f68bfbcbd9702ffd4e50b443a238d8eb8582b7a
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$BZ2Decompressor_decompress_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$PyExposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7cf9cfe8cafd1992e2293502b71ebb52f9eda607
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$exposed___new__.class b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..587c365a79bc671970e087ac8f074d869c172860
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$unused_data_descriptor.class b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$unused_data_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..84d15a8019ba4e6f3fdbd4f69cce0e0639d4f296
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor$unused_data_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor.class b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor.class
new file mode 100644
index 0000000000000000000000000000000000000000..347317c30eac98c8b4c79ab55515e4d08013ae33
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2Decompressor.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2DecompressorDerived.class b/src/main/resources/org/python/modules/bz2/PyBZ2DecompressorDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff8338a01b8edf2cc247532bc924a77d9842ea91
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2DecompressorDerived.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$1.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3fa10b958bbf7594f3b56c623c78789c5b765627
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$1.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2FileIterator.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2FileIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..5410a9660876676e22d8685f1ceadf894d4e5111
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2FileIterator.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___enter___exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___enter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c441068da861f731bee9dbbb476d5489700edd3
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___enter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___exit___exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___exit___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4c367c1e08606a094f54e39a02513582281fa34
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___exit___exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___init___exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..22200501baebe74b306ac16bfc5803449cf82453
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_close_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_close_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..821362ea06fdb69685f37830ceddb5bb2eed6621
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_close_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_next_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..608b5761395090330fed855e156bcec3685461ee
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_read_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_read_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b422710304d49d27eb61c6c4fc0b1b8fe534a2b5
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_read_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_readline_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_readline_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9331279ddfb7abdbe5a9dc5b9193add8e0f2fa22
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_readline_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_readlines_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_readlines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..23c2b62e252d450715be47bc0fea971ed027f617
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_readlines_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_seek_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_seek_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a2619eeca9a03e3bff6feeaac48aa52d7fe695f
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_seek_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_tell_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_tell_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b70cbc6ecb077a8aba288794a5e7f28f0a7edc2f
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_tell_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_write_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_write_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..42a523a44bf77fb2e55603e73c775e08e2a5d245
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_write_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_writelines_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_writelines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd435ee36616fb3e40bbdfdb9ad4b561e889b5e1
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_writelines_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_xreadlines_exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_xreadlines_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd76106070d6c63476ea9f75aab2e68862bac13b
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$BZ2File_xreadlines_exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$PyExposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..59cfec86d03ec30098577087d1e771a254aca721
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$__del___exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$__del___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6f9c333f77b6020f7d976e2a431e7f1046c2362
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$__del___exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$__iter___exposer.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..519b93603b9c634378ef24b0a13725fc4c65fbef
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$exposed___new__.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b23747c0f886188aa9a43e24bb797308512d120
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File$newlines_descriptor.class b/src/main/resources/org/python/modules/bz2/PyBZ2File$newlines_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..127da494177d864f739e7b2093adec011d7337d8
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File$newlines_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2File.class b/src/main/resources/org/python/modules/bz2/PyBZ2File.class
new file mode 100644
index 0000000000000000000000000000000000000000..53e306f1accdba11c783a1ce9f28c37240a3e2ef
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2File.class differ
diff --git a/src/main/resources/org/python/modules/bz2/PyBZ2FileDerived.class b/src/main/resources/org/python/modules/bz2/PyBZ2FileDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..a598d045bbcd0d0d26cd235311f329fe0792bc52
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/PyBZ2FileDerived.class differ
diff --git a/src/main/resources/org/python/modules/bz2/bz2.class b/src/main/resources/org/python/modules/bz2/bz2.class
new file mode 100644
index 0000000000000000000000000000000000000000..2737418da66a29423d114f537b8e7d1b07c1831d
Binary files /dev/null and b/src/main/resources/org/python/modules/bz2/bz2.class differ
diff --git a/src/main/resources/org/python/modules/cPickle$PickleMemo.class b/src/main/resources/org/python/modules/cPickle$PickleMemo.class
new file mode 100644
index 0000000000000000000000000000000000000000..c31d0d267054bcbe0c7ddba453a3456dcdd287d2
Binary files /dev/null and b/src/main/resources/org/python/modules/cPickle$PickleMemo.class differ
diff --git a/src/main/resources/org/python/modules/cPickle$Pickler.class b/src/main/resources/org/python/modules/cPickle$Pickler.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c4e1e30dc09fcb7bf17ee478a053ba5f7b5473e
Binary files /dev/null and b/src/main/resources/org/python/modules/cPickle$Pickler.class differ
diff --git a/src/main/resources/org/python/modules/cPickle$Unpickler.class b/src/main/resources/org/python/modules/cPickle$Unpickler.class
new file mode 100644
index 0000000000000000000000000000000000000000..375a137bcbc17c458d9fa69207e137528a8a43f9
Binary files /dev/null and b/src/main/resources/org/python/modules/cPickle$Unpickler.class differ
diff --git a/src/main/resources/org/python/modules/cPickle.class b/src/main/resources/org/python/modules/cPickle.class
new file mode 100644
index 0000000000000000000000000000000000000000..852fe5c54e25f1b0d377c6b2a8fdc599f2000536
Binary files /dev/null and b/src/main/resources/org/python/modules/cPickle.class differ
diff --git a/src/main/resources/org/python/modules/cStringIO$StringIO.class b/src/main/resources/org/python/modules/cStringIO$StringIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..79355db7dcd4bae7cd31881e72861fe987794a8d
Binary files /dev/null and b/src/main/resources/org/python/modules/cStringIO$StringIO.class differ
diff --git a/src/main/resources/org/python/modules/cStringIO$os.class b/src/main/resources/org/python/modules/cStringIO$os.class
new file mode 100644
index 0000000000000000000000000000000000000000..fb87562aa8776e50bec74082b28a84d3dfd1c14c
Binary files /dev/null and b/src/main/resources/org/python/modules/cStringIO$os.class differ
diff --git a/src/main/resources/org/python/modules/cStringIO.class b/src/main/resources/org/python/modules/cStringIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a55289c4a1a60fa4c468ba4b92aea1349e76d10
Binary files /dev/null and b/src/main/resources/org/python/modules/cStringIO.class differ
diff --git a/src/main/resources/org/python/modules/cmath.class b/src/main/resources/org/python/modules/cmath.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bdec7e2ca7c287da973cd4eb0d85c74d5cab2b0
Binary files /dev/null and b/src/main/resources/org/python/modules/cmath.class differ
diff --git a/src/main/resources/org/python/modules/errno.class b/src/main/resources/org/python/modules/errno.class
new file mode 100644
index 0000000000000000000000000000000000000000..76d9dd72bf30c080121cfa8d2a773a096cb9a78f
Binary files /dev/null and b/src/main/resources/org/python/modules/errno.class differ
diff --git a/src/main/resources/org/python/modules/gc.class b/src/main/resources/org/python/modules/gc.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c9b732174d3e650c158e731dc9563f991cdb910
Binary files /dev/null and b/src/main/resources/org/python/modules/gc.class differ
diff --git a/src/main/resources/org/python/modules/imp$ModuleInfo.class b/src/main/resources/org/python/modules/imp$ModuleInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9fb02d0fa2eb07e2d3772243fda3e5d764cb41f
Binary files /dev/null and b/src/main/resources/org/python/modules/imp$ModuleInfo.class differ
diff --git a/src/main/resources/org/python/modules/imp.class b/src/main/resources/org/python/modules/imp.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b686af9d952573b36724227f4f4a3a33f8e1416
Binary files /dev/null and b/src/main/resources/org/python/modules/imp.class differ
diff --git a/src/main/resources/org/python/modules/itertools/PyTeeIterator$PyExposer.class b/src/main/resources/org/python/modules/itertools/PyTeeIterator$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d70eff99818002b58976859392bd334afe11ab7
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/PyTeeIterator$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/PyTeeIterator$PyTeeData.class b/src/main/resources/org/python/modules/itertools/PyTeeIterator$PyTeeData.class
new file mode 100644
index 0000000000000000000000000000000000000000..a354f13e21f47d4d48456ebf044cc92f3aa44014
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/PyTeeIterator$PyTeeData.class differ
diff --git a/src/main/resources/org/python/modules/itertools/PyTeeIterator$exposed___new__.class b/src/main/resources/org/python/modules/itertools/PyTeeIterator$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..534dc46fda3b46f45037e6350f6ea12366233213
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/PyTeeIterator$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/PyTeeIterator$tee___copy___exposer.class b/src/main/resources/org/python/modules/itertools/PyTeeIterator$tee___copy___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..af2327305143225109f3c354adda7aa9e3ef8479
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/PyTeeIterator$tee___copy___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/PyTeeIterator$tee_next_exposer.class b/src/main/resources/org/python/modules/itertools/PyTeeIterator$tee_next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5163017854099b923b9b7e87a136f6d249a41c36
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/PyTeeIterator$tee_next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/PyTeeIterator.class b/src/main/resources/org/python/modules/itertools/PyTeeIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bd33ec4d04f0f6ad9a0c533951b23727ad0b91e
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/PyTeeIterator.class differ
diff --git a/src/main/resources/org/python/modules/itertools/PyTeeIteratorDerived.class b/src/main/resources/org/python/modules/itertools/PyTeeIteratorDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b9c389fc80ec2c5370a18c5423dc0773607f6e7
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/PyTeeIteratorDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain$1.class b/src/main/resources/org/python/modules/itertools/chain$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..37534c63b82a092615dc414836d7f82c525505ad
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain$PyExposer.class b/src/main/resources/org/python/modules/itertools/chain$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..baeac61c898afcc1ad36991b0f9de9e9fbda180b
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/chain$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..12be0a8816ed1883dafe4f81ecfb4f6f43a34f0f
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/chain$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f96e44a9c267d43cc7d35e1b4a3c22eeb026c724
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain$chain___init___exposer.class b/src/main/resources/org/python/modules/itertools/chain$chain___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2e19e544261b6f33f89e464ac8ef3df14700774
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain$chain___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain$exposed___new__.class b/src/main/resources/org/python/modules/itertools/chain$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..845be52c9d9f6ca730dad9e23fa1c64e0dc251e0
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain$from_iterable_exposer.class b/src/main/resources/org/python/modules/itertools/chain$from_iterable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..68f1907f5bb5c839413839fbb07ac4c0a71797b1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain$from_iterable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain$next_exposer.class b/src/main/resources/org/python/modules/itertools/chain$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a2cd233bc7ca503a8defe7830d797f8210ef556
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chain.class b/src/main/resources/org/python/modules/itertools/chain.class
new file mode 100644
index 0000000000000000000000000000000000000000..bbdd1b494abc2fd9f8a7c75de1082b33d5a5f7d9
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chain.class differ
diff --git a/src/main/resources/org/python/modules/itertools/chainDerived.class b/src/main/resources/org/python/modules/itertools/chainDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..a77cf3b97a73ffad58dbdd8ff479d5251c5f5b3d
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/chainDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinations$1.class b/src/main/resources/org/python/modules/itertools/combinations$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e34a4eb22f593dec93edcaab5556529f812a0e4e
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinations$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinations$PyExposer.class b/src/main/resources/org/python/modules/itertools/combinations$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..98015bcfebc1e02cbbd2f88793e7f7db1cc8d08c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinations$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinations$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/combinations$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f53711bc35e0fec770c3a49b9e4199cd0338568a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinations$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinations$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/combinations$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..64cfb9bde6a5b62a1b2a59e182bab51b1215e8bc
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinations$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinations$combinations___init___exposer.class b/src/main/resources/org/python/modules/itertools/combinations$combinations___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec7cb878f3e572a5b371dc1c01b52270ba6fdfab
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinations$combinations___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinations$exposed___new__.class b/src/main/resources/org/python/modules/itertools/combinations$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1098a483c0ae7cb4df5596d8c11c08895864459
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinations$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinations$next_exposer.class b/src/main/resources/org/python/modules/itertools/combinations$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c330d774f429912b465a3e1e1d12fc236ed00a51
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinations$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinations.class b/src/main/resources/org/python/modules/itertools/combinations.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd5a889da63ec76adeee9ad771a80926ca8f28c6
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinations.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsDerived.class b/src/main/resources/org/python/modules/itertools/combinationsDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..eeaf375502d4edea34a1050d269803d1993903a5
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$1.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4359aaac9c41571e9544e26fdd8da28d7611d30
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$PyExposer.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f85a95b4111435fb5f8a1a3f4bef64da4022c5c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..107595cf39ff76e4c1bc5c1ffce884bab8905d07
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6260eb994bf4c90fb26e81bb58575f017b9ab882
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$combinationsWithReplacement___init___exposer.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$combinationsWithReplacement___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..503c82245291349dab7b4eb2d56796575f67945d
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$combinationsWithReplacement___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$exposed___new__.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d8f37829101cec766e0c2ad4b37d9217230bb9f
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$next_exposer.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..76b3dd2ab48004d3faafe098623bfc2e50e63bad
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacement.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5d08f8f580ca5f5eb1396bf4b8c09da60578176
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacement.class differ
diff --git a/src/main/resources/org/python/modules/itertools/combinationsWithReplacementDerived.class b/src/main/resources/org/python/modules/itertools/combinationsWithReplacementDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..37b6e88898a3f6fb6fc947fccbdfa3ba06089881
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/combinationsWithReplacementDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compress$1.class b/src/main/resources/org/python/modules/itertools/compress$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ecc211173f0db99a01fd0ae07d963b37be8d3cf
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compress$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compress$PyExposer.class b/src/main/resources/org/python/modules/itertools/compress$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6646afabbb0c4bd616241d7dc6a86629956403ce
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compress$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compress$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/compress$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ea3b9e2e53a6c040659976d2b0f3559831ebdc3
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compress$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compress$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/compress$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f56b7210fcd1052cfb3ff8f6dd19c32e6d3bdae8
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compress$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compress$compress___init___exposer.class b/src/main/resources/org/python/modules/itertools/compress$compress___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0961612705e0cb240dbe5a8dbd45acf8b09124a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compress$compress___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compress$exposed___new__.class b/src/main/resources/org/python/modules/itertools/compress$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..d479e725ba4340bf8c0471290d212e750a7199aa
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compress$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compress$next_exposer.class b/src/main/resources/org/python/modules/itertools/compress$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..86a8cc70f5271d7c6f6e9ce2c8d5494d514e9404
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compress$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compress.class b/src/main/resources/org/python/modules/itertools/compress.class
new file mode 100644
index 0000000000000000000000000000000000000000..ead69c2fef487b7833a7409dd51e36f01b961008
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compress.class differ
diff --git a/src/main/resources/org/python/modules/itertools/compressDerived.class b/src/main/resources/org/python/modules/itertools/compressDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2b26411da9ce6dbe75a6bbd01128a572231e08e
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/compressDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count$1.class b/src/main/resources/org/python/modules/itertools/count$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..87c448896458270f74f629f04dd28954a8a11556
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count$PyExposer.class b/src/main/resources/org/python/modules/itertools/count$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e337486023fed755d1e80ef8adb806ae5fb11f1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/count$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..10216c42e725ad3dcf2b0f7de1e71f65d44913a7
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/count$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4e763dd3a0bce55c26e476d33dc0be9bc9fe376
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count$__repr___exposer.class b/src/main/resources/org/python/modules/itertools/count$__repr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c38f7f703f8289731a589a7b7097f8796effff2b
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count$__repr___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count$count___init___exposer.class b/src/main/resources/org/python/modules/itertools/count$count___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b37823725747ed3e5c3657141c0541fcdabb293d
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count$count___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count$exposed___new__.class b/src/main/resources/org/python/modules/itertools/count$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..07bf202a4f42c3b6846f7777c4bd551c6944efcd
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count$next_exposer.class b/src/main/resources/org/python/modules/itertools/count$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ea2aa404c55d8885093f7883074dddc98303183b
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/count.class b/src/main/resources/org/python/modules/itertools/count.class
new file mode 100644
index 0000000000000000000000000000000000000000..56db479c3465749f94a3a8fbe198c1232ef223e9
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/count.class differ
diff --git a/src/main/resources/org/python/modules/itertools/countDerived.class b/src/main/resources/org/python/modules/itertools/countDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..c94dc06b1d82572589f73b7ce551e77b18b22ea0
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/countDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycle$1.class b/src/main/resources/org/python/modules/itertools/cycle$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..651550340e3077ea915a24fec1ebbe124a4f5093
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycle$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycle$PyExposer.class b/src/main/resources/org/python/modules/itertools/cycle$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a63b7dc13423fe1be82b30e9aa3533dfc391229d
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycle$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycle$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/cycle$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b613b5d5b94a36f8c7802811d87d8aeea894d2cb
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycle$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycle$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/cycle$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..21a3953d9c03988ed367dc842df6835815f33800
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycle$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycle$cycle___init___exposer.class b/src/main/resources/org/python/modules/itertools/cycle$cycle___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c347cdc54b1d84435c6c1acdb16713331896af5
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycle$cycle___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycle$exposed___new__.class b/src/main/resources/org/python/modules/itertools/cycle$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..9abe8a899cf34801a91e83c91399a1c6c6cbe7eb
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycle$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycle$next_exposer.class b/src/main/resources/org/python/modules/itertools/cycle$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..792b262c6182fc9f48a645b80883d947d5e74a99
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycle$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycle.class b/src/main/resources/org/python/modules/itertools/cycle.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fffe0c40bc771d1eb38459937733f63d18dd19b
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycle.class differ
diff --git a/src/main/resources/org/python/modules/itertools/cycleDerived.class b/src/main/resources/org/python/modules/itertools/cycleDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..259b157a28e156f8b50e394fbe7d94bcbda19e6b
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/cycleDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/dropwhile$PyExposer.class b/src/main/resources/org/python/modules/itertools/dropwhile$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..99b60cddf1e04d26a7551c1b8bdb36ea19718f14
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/dropwhile$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/dropwhile$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/dropwhile$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..82630625410b637f4350ffb256ffaa31aae3877e
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/dropwhile$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/dropwhile$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/dropwhile$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2e00787e63b16f830e1a6b5525c490b84ef2b71
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/dropwhile$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/dropwhile$dropwhile___init___exposer.class b/src/main/resources/org/python/modules/itertools/dropwhile$dropwhile___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..205fb066f368b76236467ff8915892bdb4557a4e
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/dropwhile$dropwhile___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/dropwhile$exposed___new__.class b/src/main/resources/org/python/modules/itertools/dropwhile$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbc833bbd0b1112975a476955660f6e07a2e345c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/dropwhile$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/dropwhile$next_exposer.class b/src/main/resources/org/python/modules/itertools/dropwhile$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..99e84262312d00f6b9d43aca188122bbc236f2c0
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/dropwhile$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/dropwhile.class b/src/main/resources/org/python/modules/itertools/dropwhile.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfeb498bf32e0b68e8c85fe5cd89a039b50be5e3
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/dropwhile.class differ
diff --git a/src/main/resources/org/python/modules/itertools/dropwhileDerived.class b/src/main/resources/org/python/modules/itertools/dropwhileDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..7c30bfcc8e004b3caf9862b29fd527b298e59e4b
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/dropwhileDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby$1$GroupByIterator.class b/src/main/resources/org/python/modules/itertools/groupby$1$GroupByIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c01abf8c96150c1eeb31df403f3d2050ae8b837
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby$1$GroupByIterator.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby$1.class b/src/main/resources/org/python/modules/itertools/groupby$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9a29597e17fc494742fd933f3a24eff84130a53
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby$PyExposer.class b/src/main/resources/org/python/modules/itertools/groupby$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d91ed0b9d458bec3d76c5a1364528f0e9f70ea58
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/groupby$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..12a416da8ced43c5002a43ccc70fbdf8b3096867
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/groupby$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ceec3f494c948cd88f9fba1d97cd533d16b20bb1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby$exposed___new__.class b/src/main/resources/org/python/modules/itertools/groupby$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ad58f838404f5a624319566557348c8c9a0556e
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby$groupby___init___exposer.class b/src/main/resources/org/python/modules/itertools/groupby$groupby___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d034deef301bfb381e80c8a4b2283f0021bf9040
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby$groupby___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby$next_exposer.class b/src/main/resources/org/python/modules/itertools/groupby$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd11d97915e0cc489b05218cac118a777ad17b0c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupby.class b/src/main/resources/org/python/modules/itertools/groupby.class
new file mode 100644
index 0000000000000000000000000000000000000000..35b9332536cb1d043840771f0ea1d776186146e3
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupby.class differ
diff --git a/src/main/resources/org/python/modules/itertools/groupbyDerived.class b/src/main/resources/org/python/modules/itertools/groupbyDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..6b16fa5b539cc753098de3168e2b97c0a5bbd22a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/groupbyDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilter$PyExposer.class b/src/main/resources/org/python/modules/itertools/ifilter$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..958ce607d8d22d512dbd05342ae1f118e4a344e2
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilter$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilter$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/ifilter$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..84a8a662d709940ec1f35773e1b4baedf8367f93
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilter$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilter$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/ifilter$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5186d5cd8dc17b7fc9c710d685bcd98a3736f7b1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilter$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilter$exposed___new__.class b/src/main/resources/org/python/modules/itertools/ifilter$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b746e63391817cea25a8b4e1c2ff36151a9feb43
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilter$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilter$ifilter___init___exposer.class b/src/main/resources/org/python/modules/itertools/ifilter$ifilter___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d832f99f6d29aba876026e8909fa455eb97d0a82
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilter$ifilter___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilter$next_exposer.class b/src/main/resources/org/python/modules/itertools/ifilter$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..49c59c5319ae672ff1bf7d72dc5f34069454b205
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilter$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilter.class b/src/main/resources/org/python/modules/itertools/ifilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d554c5c21ebeffef65429d0edac24d1baf39cca
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilter.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterDerived.class b/src/main/resources/org/python/modules/itertools/ifilterDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7806609eaf2b06e235faf0ee8a27da93bf64ddb
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterfalse$PyExposer.class b/src/main/resources/org/python/modules/itertools/ifilterfalse$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0ea8fcfdab5d50546426d49be370a3b08dc09581
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterfalse$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterfalse$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/ifilterfalse$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..970fbe483792a7e7b00f4008c24bd8df0f40620e
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterfalse$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterfalse$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/ifilterfalse$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b612f3cc1f46e32e644c0c40023be1b543e7cc7
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterfalse$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterfalse$exposed___new__.class b/src/main/resources/org/python/modules/itertools/ifilterfalse$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..0adb4506f5cdbf03a6dacaa2111693f4b08934d2
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterfalse$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterfalse$ifilterfalse___init___exposer.class b/src/main/resources/org/python/modules/itertools/ifilterfalse$ifilterfalse___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d390fbe100257e8ab76781f6b096ceedb847431
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterfalse$ifilterfalse___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterfalse$next_exposer.class b/src/main/resources/org/python/modules/itertools/ifilterfalse$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..486d67eb1a3a90715bc5e31253560941957269f8
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterfalse$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterfalse.class b/src/main/resources/org/python/modules/itertools/ifilterfalse.class
new file mode 100644
index 0000000000000000000000000000000000000000..9427b94fe81a145693318e1d6bdf398d0c17d4be
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterfalse.class differ
diff --git a/src/main/resources/org/python/modules/itertools/ifilterfalseDerived.class b/src/main/resources/org/python/modules/itertools/ifilterfalseDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fc17d22cd88a6f85a37d79eceb8158423b722e8
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/ifilterfalseDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/imap$1.class b/src/main/resources/org/python/modules/itertools/imap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..2edbb4648d757e5e3d3de5d361a3ff9f1f7bf762
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/imap$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/imap.class b/src/main/resources/org/python/modules/itertools/imap.class
new file mode 100644
index 0000000000000000000000000000000000000000..70e52ff803744e564cc88ce68d52b037617d0402
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/imap.class differ
diff --git a/src/main/resources/org/python/modules/itertools/islice$1.class b/src/main/resources/org/python/modules/itertools/islice$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..37cb0ef92a6bd4d7685da028a44130b60382b646
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/islice$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/islice$PyExposer.class b/src/main/resources/org/python/modules/itertools/islice$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb0499b45dd8eaf604c9c1d13b6129ab0981e7a6
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/islice$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/islice$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/islice$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..27d86104aa5b24271f63bff6bf731051a8479f08
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/islice$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/islice$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/islice$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..11230e1d95c51c3347223fe2bc2d4252280fcc64
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/islice$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/islice$exposed___new__.class b/src/main/resources/org/python/modules/itertools/islice$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..18064685d414c3d3bebaa32d5207852f41480b2f
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/islice$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/islice$islice___init___exposer.class b/src/main/resources/org/python/modules/itertools/islice$islice___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..17ece8b7c847615ae9e66c20064481a944ac8805
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/islice$islice___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/islice$next_exposer.class b/src/main/resources/org/python/modules/itertools/islice$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5d83d5fbd436dda7f197351834179c018dc0bb5
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/islice$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/islice.class b/src/main/resources/org/python/modules/itertools/islice.class
new file mode 100644
index 0000000000000000000000000000000000000000..466c23925e4b9c08102f4b0bdf0f474c4180b275
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/islice.class differ
diff --git a/src/main/resources/org/python/modules/itertools/isliceDerived.class b/src/main/resources/org/python/modules/itertools/isliceDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3f8aad2e2849531333f7ccc9c1b2930e53d67a0
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/isliceDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/itertools$FilterIterator.class b/src/main/resources/org/python/modules/itertools/itertools$FilterIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..edb58cdf569d5f278d9283821e8a8b1428ed969c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/itertools$FilterIterator.class differ
diff --git a/src/main/resources/org/python/modules/itertools/itertools$ItertoolsIterator.class b/src/main/resources/org/python/modules/itertools/itertools$ItertoolsIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e114e8b3f15ff545e30b3a5c62cab890d6c1c81
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/itertools$ItertoolsIterator.class differ
diff --git a/src/main/resources/org/python/modules/itertools/itertools$WhileIterator.class b/src/main/resources/org/python/modules/itertools/itertools$WhileIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..e29d6167f7e02488712a23e27a072c5cdea3bfa4
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/itertools$WhileIterator.class differ
diff --git a/src/main/resources/org/python/modules/itertools/itertools.class b/src/main/resources/org/python/modules/itertools/itertools.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf7e1571fee1522943b3c14338555c10626b8117
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/itertools.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izip$1.class b/src/main/resources/org/python/modules/itertools/izip$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f79c495bc2a9ac16f40131aab96236481f069d8
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izip$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izip$PyExposer.class b/src/main/resources/org/python/modules/itertools/izip$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8338fb4013859f582dc8ed9bce99c51aee9432b8
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izip$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izip$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/izip$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..fbf9f2198e023b70140a4e28cc5720d1f8ebb1de
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izip$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izip$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/izip$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bc1b357a33d5a753bb3a6a3d6ac2fb5f7e92611
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izip$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izip$exposed___new__.class b/src/main/resources/org/python/modules/itertools/izip$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ed7791603c495558d104bac6d6d33d34ed5a972
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izip$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izip$izip___init___exposer.class b/src/main/resources/org/python/modules/itertools/izip$izip___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..33c90c25f5974dd0235cf9110c9e78a61a873fa0
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izip$izip___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izip$next_exposer.class b/src/main/resources/org/python/modules/itertools/izip$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..fea64c618a322bf1c7c11a8cafb8c1381a1bf835
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izip$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izip.class b/src/main/resources/org/python/modules/itertools/izip.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce7d026f17e165e394f38db3478e13fa3accf06a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izip.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipDerived.class b/src/main/resources/org/python/modules/itertools/izipDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..f171e0b133f01ef23f7207f674dd4d05653c844c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongest$1.class b/src/main/resources/org/python/modules/itertools/izipLongest$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..3dc57a40e2c434dd98a2f6fe056fe56f59ed3808
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongest$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongest$PyExposer.class b/src/main/resources/org/python/modules/itertools/izipLongest$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed6519c41d574a4d360a29bd93b03a416fdc733b
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongest$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongest$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/izipLongest$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3f76d6174b468750465f7e7fc829274db663980c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongest$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongest$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/izipLongest$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..390dcffeb1377f57e9660757c6bb1008d82b8904
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongest$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongest$exposed___new__.class b/src/main/resources/org/python/modules/itertools/izipLongest$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6409b1922db28d2dc9c1cf20901ad42baf4fefa
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongest$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongest$izipLongest___init___exposer.class b/src/main/resources/org/python/modules/itertools/izipLongest$izipLongest___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4d0ed45813d703d1f0da2796bb6a2fdac352073
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongest$izipLongest___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongest$next_exposer.class b/src/main/resources/org/python/modules/itertools/izipLongest$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ef7914501882f27a7de625903b6b2cc946ca1d4
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongest$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongest.class b/src/main/resources/org/python/modules/itertools/izipLongest.class
new file mode 100644
index 0000000000000000000000000000000000000000..c75ee990d1442ad08142ed77cf8c6f66c54d54a6
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongest.class differ
diff --git a/src/main/resources/org/python/modules/itertools/izipLongestDerived.class b/src/main/resources/org/python/modules/itertools/izipLongestDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd0ef2bb53db96c9ad72fbf497426fe9d0b8f1b7
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/izipLongestDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutations$1.class b/src/main/resources/org/python/modules/itertools/permutations$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..639dd3f9648611e56ce52de5d3fdd051fc255587
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutations$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutations$PyExposer.class b/src/main/resources/org/python/modules/itertools/permutations$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..39ec7cfda17f2682a46a85f8da36a9e405485918
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutations$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutations$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/permutations$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff1792d2c4d9ff1337d80bed330e0c4464f8986a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutations$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutations$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/permutations$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a59fdddd5b9d39c8ce79e844f318586dbb32c5bd
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutations$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutations$exposed___new__.class b/src/main/resources/org/python/modules/itertools/permutations$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..06467162600f67f0e304e8b9801eaa8efd035b8a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutations$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutations$next_exposer.class b/src/main/resources/org/python/modules/itertools/permutations$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d998cf4b51856803cbfdc9eee70a761ed6719f1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutations$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutations$permutations___init___exposer.class b/src/main/resources/org/python/modules/itertools/permutations$permutations___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8908d94fbd9ee63be72fa0a0541e07f9a3642a1a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutations$permutations___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutations.class b/src/main/resources/org/python/modules/itertools/permutations.class
new file mode 100644
index 0000000000000000000000000000000000000000..7dcb58294f13698cfa271bc15ff57851efa2efa5
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutations.class differ
diff --git a/src/main/resources/org/python/modules/itertools/permutationsDerived.class b/src/main/resources/org/python/modules/itertools/permutationsDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..190824160acbf3446a34554adf58377cb371d0f1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/permutationsDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/product$1.class b/src/main/resources/org/python/modules/itertools/product$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d31438c5a7e662715d46f2dc55464a1926b0d78b
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/product$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/product$PyExposer.class b/src/main/resources/org/python/modules/itertools/product$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c684d00e11634d8f015554de2645637f96bec5dc
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/product$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/product$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/product$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ead70f4742ffa0447e0851243eb875b877534e66
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/product$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/product$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/product$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0151edd8f10eb36f4ca6ddb2e31373d70c124ff
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/product$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/product$exposed___new__.class b/src/main/resources/org/python/modules/itertools/product$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7fba01a658af0413a154c8ea06b71c68c0c0019
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/product$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/product$next_exposer.class b/src/main/resources/org/python/modules/itertools/product$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d30d863a2800b7c71c2ed7fe23c9ddbc9d28258
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/product$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/product$product___init___exposer.class b/src/main/resources/org/python/modules/itertools/product$product___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3364c947f07cbfe917aef61100ae50bfd53e868f
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/product$product___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/product.class b/src/main/resources/org/python/modules/itertools/product.class
new file mode 100644
index 0000000000000000000000000000000000000000..a50d30eff75cf40f31b72167fad89d3d71dc21f1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/product.class differ
diff --git a/src/main/resources/org/python/modules/itertools/productDerived.class b/src/main/resources/org/python/modules/itertools/productDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..3875cee45abb9e6c500b0a5bdb9460b30fceaf12
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/productDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$1.class b/src/main/resources/org/python/modules/itertools/repeat$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcaef0b475f9cf7ac27ddf362307ca801db98179
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$2.class b/src/main/resources/org/python/modules/itertools/repeat$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..d508bbff4870092e03bc0cdc4279830df3509145
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$2.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$PyExposer.class b/src/main/resources/org/python/modules/itertools/repeat$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c668ffe123ed8161bf7d5b7a3b1df5a4e8c0a6fc
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/repeat$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..71695017249c65809358534c55a55b56e66a40dd
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/repeat$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..196519a501343a24fc1bff89946f56cb277c950c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$__len___exposer.class b/src/main/resources/org/python/modules/itertools/repeat$__len___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f54cb9a2a48694594ef9c0ec393c0cab538fb2f
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$__len___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$__repr___exposer.class b/src/main/resources/org/python/modules/itertools/repeat$__repr___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8149d1eb0a5f1f5255f677ce8938bba0b219e876
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$__repr___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$exposed___new__.class b/src/main/resources/org/python/modules/itertools/repeat$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bfe629df6f444b23db415dceef63b9fe6c71c17
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$next_exposer.class b/src/main/resources/org/python/modules/itertools/repeat$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b858401b7a8befa587d06adb00d58d4917d60b94
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat$repeat___init___exposer.class b/src/main/resources/org/python/modules/itertools/repeat$repeat___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e38dbae571f4c39d29ed40907f06330fdd13a5bd
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat$repeat___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeat.class b/src/main/resources/org/python/modules/itertools/repeat.class
new file mode 100644
index 0000000000000000000000000000000000000000..604c197c959961f918563dc9aab2d00f2bec0dd0
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeat.class differ
diff --git a/src/main/resources/org/python/modules/itertools/repeatDerived.class b/src/main/resources/org/python/modules/itertools/repeatDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..07d102742c6313ca3a35fe59cf0a87ae89ed17b7
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/repeatDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmap$1.class b/src/main/resources/org/python/modules/itertools/starmap$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..847bf166674ce74f8a1c5ea369359364d8dbccfe
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmap$1.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmap$PyExposer.class b/src/main/resources/org/python/modules/itertools/starmap$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..98cbe354ca3676fcf4b9122c8a9a78cd0f87e8ee
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmap$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmap$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/starmap$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7afb7d43fbd04b5457617421b7c1e83b4b3864b1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmap$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmap$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/starmap$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3817e997cddee32071fd4a834f39c509ea94a034
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmap$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmap$exposed___new__.class b/src/main/resources/org/python/modules/itertools/starmap$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a067d8688693a7c7c8d60a1095c648e6849e487
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmap$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmap$next_exposer.class b/src/main/resources/org/python/modules/itertools/starmap$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..8888d4ca1655d6b2f36b05dda64e3ecd9eb280c1
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmap$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmap$starmap___init___exposer.class b/src/main/resources/org/python/modules/itertools/starmap$starmap___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..19e94fc276c7f969365762c492afe8799835be74
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmap$starmap___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmap.class b/src/main/resources/org/python/modules/itertools/starmap.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce6b1fa9603edd9dbab417f9ad4b21a7b9b851da
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmap.class differ
diff --git a/src/main/resources/org/python/modules/itertools/starmapDerived.class b/src/main/resources/org/python/modules/itertools/starmapDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..1ec780c5330f1e657db7a10d04a5d6069341f27e
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/starmapDerived.class differ
diff --git a/src/main/resources/org/python/modules/itertools/takewhile$PyExposer.class b/src/main/resources/org/python/modules/itertools/takewhile$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f5fb6bc91aaef6cb9984b2d0518cf237510acf0a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/takewhile$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/takewhile$__doc___descriptor.class b/src/main/resources/org/python/modules/itertools/takewhile$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..52c7e51c5f5adfc901b638ce27a6bf4bb8703f8c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/takewhile$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/itertools/takewhile$__iter___exposer.class b/src/main/resources/org/python/modules/itertools/takewhile$__iter___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6612b0498d86308ccd56810569e8a98c7b5fb6f
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/takewhile$__iter___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/takewhile$exposed___new__.class b/src/main/resources/org/python/modules/itertools/takewhile$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4953fa74f8e934a2907ed38a689e2b94b11fa36c
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/takewhile$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/itertools/takewhile$next_exposer.class b/src/main/resources/org/python/modules/itertools/takewhile$next_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2420e5119acf0e916f0b82dbfff902a6981a1f8f
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/takewhile$next_exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/takewhile$takewhile___init___exposer.class b/src/main/resources/org/python/modules/itertools/takewhile$takewhile___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1f605a59c7d4a32e49141c4b91fd7c105bfb1025
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/takewhile$takewhile___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/itertools/takewhile.class b/src/main/resources/org/python/modules/itertools/takewhile.class
new file mode 100644
index 0000000000000000000000000000000000000000..78488cd0240fc2d3521ae3fadd9105a5465bda4a
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/takewhile.class differ
diff --git a/src/main/resources/org/python/modules/itertools/takewhileDerived.class b/src/main/resources/org/python/modules/itertools/takewhileDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb759dee1558aa47091b1946f88d8d1559cf8d48
Binary files /dev/null and b/src/main/resources/org/python/modules/itertools/takewhileDerived.class differ
diff --git a/src/main/resources/org/python/modules/jarray.class b/src/main/resources/org/python/modules/jarray.class
new file mode 100644
index 0000000000000000000000000000000000000000..958501c0649eaea19ef661598589b29437dde58e
Binary files /dev/null and b/src/main/resources/org/python/modules/jarray.class differ
diff --git a/src/main/resources/org/python/modules/jffi/AbstractMemoryCData.class b/src/main/resources/org/python/modules/jffi/AbstractMemoryCData.class
new file mode 100644
index 0000000000000000000000000000000000000000..5b55bdeb55c9ed0577cddcd18882d0e12424dec9
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/AbstractMemoryCData.class differ
diff --git a/src/main/resources/org/python/modules/jffi/AbstractNumericMethodGenerator$1.class b/src/main/resources/org/python/modules/jffi/AbstractNumericMethodGenerator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0de5e4fa8ef9e2f59f1c904f39ff766eb5da2407
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/AbstractNumericMethodGenerator$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/AbstractNumericMethodGenerator.class b/src/main/resources/org/python/modules/jffi/AbstractNumericMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d377b231c3343c0f5d799f67dd16e2f271ceac1
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/AbstractNumericMethodGenerator.class differ
diff --git a/src/main/resources/org/python/modules/jffi/AllocatedDirectMemory.class b/src/main/resources/org/python/modules/jffi/AllocatedDirectMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd3dd8bc16d5ccfd5834ff4ed95184092dbc32a9
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/AllocatedDirectMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/AllocatedNativeMemory.class b/src/main/resources/org/python/modules/jffi/AllocatedNativeMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..df27c137eb53ef59f881fecb0af22ff0c1223ec0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/AllocatedNativeMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ArrayCData$1.class b/src/main/resources/org/python/modules/jffi/ArrayCData$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..424eaddb44e64648b68c9a65ab3f5192cee5d18a
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ArrayCData$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ArrayCData$ArrayIter.class b/src/main/resources/org/python/modules/jffi/ArrayCData$ArrayIter.class
new file mode 100644
index 0000000000000000000000000000000000000000..f26b5cd3b1d1584d234470858206c521cda0f275
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ArrayCData$ArrayIter.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ArrayCData$PyExposer.class b/src/main/resources/org/python/modules/jffi/ArrayCData$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..95a243122ace5d6194b94612d2762bf21d501780
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ArrayCData$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ArrayCData$exposed___new__.class b/src/main/resources/org/python/modules/jffi/ArrayCData$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..9846574056c398764bbb24239dd6746a9ecc3ecd
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ArrayCData$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ArrayCData$from_address_exposer.class b/src/main/resources/org/python/modules/jffi/ArrayCData$from_address_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c6c1f823a2ea206fe8ff4ef6b5d914d27619a37
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ArrayCData$from_address_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ArrayCData.class b/src/main/resources/org/python/modules/jffi/ArrayCData.class
new file mode 100644
index 0000000000000000000000000000000000000000..369224334c511835fc01ac5f677b181f16e7245c
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ArrayCData.class differ
diff --git a/src/main/resources/org/python/modules/jffi/AsmClassBuilder$JITClassLoader.class b/src/main/resources/org/python/modules/jffi/AsmClassBuilder$JITClassLoader.class
new file mode 100644
index 0000000000000000000000000000000000000000..e8c4cf5f5313c3852e177318565375a7d5af85b8
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/AsmClassBuilder$JITClassLoader.class differ
diff --git a/src/main/resources/org/python/modules/jffi/AsmClassBuilder.class b/src/main/resources/org/python/modules/jffi/AsmClassBuilder.class
new file mode 100644
index 0000000000000000000000000000000000000000..9b52158e6936aaf65d0046fd9378febf2f1051f6
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/AsmClassBuilder.class differ
diff --git a/src/main/resources/org/python/modules/jffi/BasePointer.class b/src/main/resources/org/python/modules/jffi/BasePointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..34eec33fdbc9e1ac4ef5462d2cf500b0f78acc23
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/BasePointer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/BoundedNativeMemory.class b/src/main/resources/org/python/modules/jffi/BoundedNativeMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b075ae27e2cf9c0ca1ebe49c7d96085242ffcf0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/BoundedNativeMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ByReference$PyExposer.class b/src/main/resources/org/python/modules/jffi/ByReference$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..606e9164623805d65251993564f72c1c3b4f05a5
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ByReference$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ByReference.class b/src/main/resources/org/python/modules/jffi/ByReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c84baccb8ba9720f49a4744acd8c34f94bf084e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ByReference.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CData$PyExposer.class b/src/main/resources/org/python/modules/jffi/CData$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5dfc6efa6f445727644982ee43789b2497eb290a
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CData$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CData$address_exposer.class b/src/main/resources/org/python/modules/jffi/CData$address_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e676b057c152259700d2a734ddf94fb2004c68f0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CData$address_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CData$byref_exposer.class b/src/main/resources/org/python/modules/jffi/CData$byref_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4cc4f7c030120382351e6a86fa8bdef850b8b50
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CData$byref_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CData$pointer_exposer.class b/src/main/resources/org/python/modules/jffi/CData$pointer_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a78fae663d8449bb91fc37b5dff3ff6ee2585143
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CData$pointer_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CData.class b/src/main/resources/org/python/modules/jffi/CData.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a9bb59823307343b732bf17770d7c3fea30da8e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CData.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Array$PyExposer.class b/src/main/resources/org/python/modules/jffi/CType$Array$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9ed05cbe2561d1b94e8ee2644cf0873f64d25c6
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Array$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Array$exposed___new__.class b/src/main/resources/org/python/modules/jffi/CType$Array$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9c56217e792943ac5030f36f6ed8cd0d2dc8977
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Array$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Array$length_descriptor.class b/src/main/resources/org/python/modules/jffi/CType$Array$length_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f5f0842e068ce4882711bb1ba9effdf7ba58a11
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Array$length_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Array.class b/src/main/resources/org/python/modules/jffi/CType$Array.class
new file mode 100644
index 0000000000000000000000000000000000000000..6efc99d22acda21262581bb9a3ae4051b534038c
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Array.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Builtin.class b/src/main/resources/org/python/modules/jffi/CType$Builtin.class
new file mode 100644
index 0000000000000000000000000000000000000000..f3defd2adfa1dba887ef64a56e08012948fe9936
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Builtin.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Custom.class b/src/main/resources/org/python/modules/jffi/CType$Custom.class
new file mode 100644
index 0000000000000000000000000000000000000000..ebc9c83e32df9dd02dd6f88265d2436b552459e5
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Custom.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Pointer$PyExposer.class b/src/main/resources/org/python/modules/jffi/CType$Pointer$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..56433f4718ba0f7919dba5a3fda4a464189e2f5b
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Pointer$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Pointer$ScalarOp.class b/src/main/resources/org/python/modules/jffi/CType$Pointer$ScalarOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..b08b4796e3d110d64c5c2738e46e215c737f18a4
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Pointer$ScalarOp.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Pointer$exposed___new__.class b/src/main/resources/org/python/modules/jffi/CType$Pointer$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..28ad0e8b3affe89f6605917df4688642292e7ee3
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Pointer$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$Pointer.class b/src/main/resources/org/python/modules/jffi/CType$Pointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0506ccd7d9a42eeaa35b1ab94e02c22535b3f89
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$Pointer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$PyExposer.class b/src/main/resources/org/python/modules/jffi/CType$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7e4f841d233dcafbda584db3a9392106ee67ef75
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$pyalignment_exposer.class b/src/main/resources/org/python/modules/jffi/CType$pyalignment_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..178a0edf7ae528a2a50f593c15c208c6f1ac8630
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$pyalignment_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType$pysize_exposer.class b/src/main/resources/org/python/modules/jffi/CType$pysize_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad507c036aed759a5a4e6d5627205fdd6d33e2cc
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType$pysize_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CType.class b/src/main/resources/org/python/modules/jffi/CType.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1b508bbf6e0f063767daa75e2deb91b5dcb52a0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CType.class differ
diff --git a/src/main/resources/org/python/modules/jffi/CodegenUtils.class b/src/main/resources/org/python/modules/jffi/CodegenUtils.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e4c3962affce8f92a0eb8e3276e4e81353cd908
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/CodegenUtils.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$1.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..65d638b1b648ebf7d9530480b3ac516dd567ed57
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$BaseInvoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$BaseInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..185e50ff64c18ef8ae5da2cc6df872fae278d98c
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$BaseInvoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$BaseMarshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$BaseMarshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..1945a8ff96080c5b6ce77f685d7cafc87df2eee2
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$BaseMarshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$DoubleInvoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$DoubleInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3cd0393e2f18cb8b8702350f1f0571fcdd0bd0f
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$DoubleInvoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$DoubleMarshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$DoubleMarshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..0229877884b784dbef3b356d05f17f9060bfaccb
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$DoubleMarshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$FloatInvoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$FloatInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..7de09a1ddd5880fdfbc7c338bfb7044fc4a4d91c
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$FloatInvoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$FloatMarshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$FloatMarshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ba721235bb5adcd968da46a3393c21b091bd22f
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$FloatMarshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$ParameterMarshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$ParameterMarshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbc3aea025cdde04d5de82c55395d3f7c1ddfef8
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$ParameterMarshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$PointerInvoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$PointerInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..4cf6d278e30114be4cd73e9a27961c6e6aff8f63
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$PointerInvoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$PointerMarshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$PointerMarshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ba2db8a844308d7ca6c8880507d09f9e44f18bb
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$PointerMarshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed16Invoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed16Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a78d25807de26e480f387768e2d8d6d5a5f1dc1
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed16Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed16Marshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed16Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..b142ff110cad3588591c2ff792161cc5915be5f2
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed16Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed32Invoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed32Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..720d93fbc2bd1e638f22414b926ebbf3b874d92e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed32Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed32Marshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed32Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..571944e4f6014d9296ab2d1cbfc2f4e3afa54848
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed32Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed64Invoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed64Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..18a4eb64e1bd43a675b9e938ed1a7ed98436a800
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed64Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed64Marshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed64Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..eff0cfb2172cc06c05f7bdcc2e1067f832406d06
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed64Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed8Invoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed8Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..64f60794177d147c17495aa9342512264491fb9e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed8Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed8Marshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed8Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..0da4e861608eadfea3687c4f7e121d8d06e1ea71
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Signed8Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$SingletonHolder.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..96644258c33dc2f746806688b0e5db0350257b2c
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$SingletonHolder.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$StringInvoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$StringInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..09e90518efc122ae6736b5bd2992a44d47d613ef
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$StringInvoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$StringMarshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$StringMarshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..02ee0faa17982a785a37788d914d223827fc601e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$StringMarshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned16Invoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned16Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f0fc217fe52b097ea2050ddc6ec6c7233b8996f
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned16Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned16Marshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned16Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..e80b1bec36ce345c281c415427c34e4c4c9bd621
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned16Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned32Invoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned32Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..a327119a5412b4a7a82fb931cabe8c7d4e8f410a
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned32Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned32Marshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned32Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..d69c9f0347a3532df5aec760111b6118a5398168
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned32Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned64Invoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned64Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed430e2ec527dfc008fa7f49f4add200535242c2
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned64Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned64Marshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned64Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..9322c0331a293e03c5c24697aa9401a2958b0650
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned64Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned8Invoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned8Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..9031517030cd1090939d0af844b0e36418fb9dc5
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned8Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned8Marshaller.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned8Marshaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..6fbc302d6b644af8a70c045a261e3c16dcd627a0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$Unsigned8Marshaller.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$VoidInvoker.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$VoidInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ac23e3a7676121ca0af5a1e3a8fb3552700d9c5
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory$VoidInvoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory.class b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..2bebb887feeaf6547e4fa2b582f42f1aafda66ff
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DefaultInvokerFactory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DirectMemory.class b/src/main/resources/org/python/modules/jffi/DirectMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a80312b127c167771ec5262eda7ddcd5ca090ce
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DirectMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$DataSymbol.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$DataSymbol.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb1256d2d08f2b6183fb0829c02eb836394d8ff5
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$DataSymbol.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$PyExposer.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..147e3a4008ca61cef54cdfdc3b1fc95f199d6228
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol$PyExposer.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ed5cae98bbd59b8b69546efb04bd65512fcf896
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol$name_descriptor.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e7d222899607108167283ef654fdecc109b5a43
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol$name_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol.class
new file mode 100644
index 0000000000000000000000000000000000000000..c1baa88432999fb53c7825c2d2df66b60004aebf
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$Symbol.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$SymbolMemory.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$SymbolMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..310eaf951c285991b19770d38bb677dae9203e6e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$SymbolMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$TextSymbol.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$TextSymbol.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4da59b2b59a6cb68dc7b052136748f83cce3d10
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$TextSymbol.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_function_exposer.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_function_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2239b3f2bc3fc1a56835495346cf0a7bf4267525
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_function_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_symbol_exposer.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_symbol_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8670864318e4a538cf773c2f2c81cf567d84f59
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_symbol_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_variable_exposer.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_variable_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..84bb20f832efe0d5430d7c19ec64782bb8179943
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$find_variable_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary$name_descriptor.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d24b41998cb9f6ec0fd85d261385b8f69b9d8299
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary$name_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/DynamicLibrary.class b/src/main/resources/org/python/modules/jffi/DynamicLibrary.class
new file mode 100644
index 0000000000000000000000000000000000000000..86eec25ff4818c3e79816df1d2b18027ca16338e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/DynamicLibrary.class differ
diff --git a/src/main/resources/org/python/modules/jffi/FastIntMethodGenerator$1.class b/src/main/resources/org/python/modules/jffi/FastIntMethodGenerator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..e49951c76dc8ca518f591f656b973c8f2c0b17c0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/FastIntMethodGenerator$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/FastIntMethodGenerator.class b/src/main/resources/org/python/modules/jffi/FastIntMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..66622a9abc0b9b3ed438cab47f1a4dbd95ef598f
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/FastIntMethodGenerator.class differ
diff --git a/src/main/resources/org/python/modules/jffi/FastLongMethodGenerator$1.class b/src/main/resources/org/python/modules/jffi/FastLongMethodGenerator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..a31fef34c5bc80357353412339b34328e42232ff
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/FastLongMethodGenerator$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/FastLongMethodGenerator.class b/src/main/resources/org/python/modules/jffi/FastLongMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f408b9d7421516a8adcb5eb74232f210bbea2c8
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/FastLongMethodGenerator.class differ
diff --git a/src/main/resources/org/python/modules/jffi/FastNumericMethodGenerator$1.class b/src/main/resources/org/python/modules/jffi/FastNumericMethodGenerator$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9856f8bc1b566adbf8d27fb3ccbba0ad222e041
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/FastNumericMethodGenerator$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/FastNumericMethodGenerator.class b/src/main/resources/org/python/modules/jffi/FastNumericMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..0525ee19fa8b851a3d7bd1d5baff60ed55232cbb
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/FastNumericMethodGenerator.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Function$ErrCheckInvoker.class b/src/main/resources/org/python/modules/jffi/Function$ErrCheckInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..cdf376353f55384d06371f22e03d16337b0bb8bf
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Function$ErrCheckInvoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Function$PyExposer.class b/src/main/resources/org/python/modules/jffi/Function$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1aaf29561c61c0508100277a57e8eb4c9236b16b
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Function$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Function$argtypes_descriptor.class b/src/main/resources/org/python/modules/jffi/Function$argtypes_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..347c3d01d173f70ce2fb2f74da9d13fb28e6c187
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Function$argtypes_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Function$errcheck_descriptor.class b/src/main/resources/org/python/modules/jffi/Function$errcheck_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..78b8ec4675baf846d8da4b802f9dccec7b96b5ea
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Function$errcheck_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Function$exposed___new__.class b/src/main/resources/org/python/modules/jffi/Function$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4d799f6807b5f6e8f17a55b48369ba4de33941df
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Function$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Function$name_descriptor.class b/src/main/resources/org/python/modules/jffi/Function$name_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cde7542aa6bc2b7648d178e63fe50b8bc07bfa6
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Function$name_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Function$restype_descriptor.class b/src/main/resources/org/python/modules/jffi/Function$restype_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..70d3e56d28203d30468cdb0202043bc3879bdbfe
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Function$restype_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Function.class b/src/main/resources/org/python/modules/jffi/Function.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ef0c96d81b3974928cbe7184ef52ffbd5b8a603
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Function.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory$1.class b/src/main/resources/org/python/modules/jffi/HeapMemory$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb2ab56a21f2c94c4b9d57dd5ee811a4d569619d
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory$ArrayIO.class b/src/main/resources/org/python/modules/jffi/HeapMemory$ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..e80e316cd8ffbaf43eb818d2430685e1feee4741
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory$ArrayIO.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory$BE32ArrayIO.class b/src/main/resources/org/python/modules/jffi/HeapMemory$BE32ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..45b95e0f59f70c03b827e27551ad19d6a9f45921
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory$BE32ArrayIO.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory$BE64ArrayIO.class b/src/main/resources/org/python/modules/jffi/HeapMemory$BE64ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..76cbf8e78918dea560bd276c67ebe27e57ed08ac
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory$BE64ArrayIO.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory$BigEndianArrayIO.class b/src/main/resources/org/python/modules/jffi/HeapMemory$BigEndianArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f7eff6b53b1ec76918b789becaa1d2c73c46ce8
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory$BigEndianArrayIO.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory$LE32ArrayIO.class b/src/main/resources/org/python/modules/jffi/HeapMemory$LE32ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7104e91a80349d12b701ede5e585c9ab7688037
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory$LE32ArrayIO.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory$LE64ArrayIO.class b/src/main/resources/org/python/modules/jffi/HeapMemory$LE64ArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..bb4e6c4f8dfd5bd95110439c8b4a7948366d95ef
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory$LE64ArrayIO.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory$LittleEndianArrayIO.class b/src/main/resources/org/python/modules/jffi/HeapMemory$LittleEndianArrayIO.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2d8a477d7b031a47a492ba9bf316967337657cf
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory$LittleEndianArrayIO.class differ
diff --git a/src/main/resources/org/python/modules/jffi/HeapMemory.class b/src/main/resources/org/python/modules/jffi/HeapMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7fb6789b68281b59916c5b291f8d33a35d17696
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/HeapMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/InvalidMemory.class b/src/main/resources/org/python/modules/jffi/InvalidMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..3d691de708b3fef8abb457d8666248d85169507b
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/InvalidMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Invoker.class b/src/main/resources/org/python/modules/jffi/Invoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..fecc31d158a805208c929808685d2db08000fb11
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Invoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITCompiler$HandleRef.class b/src/main/resources/org/python/modules/jffi/JITCompiler$HandleRef.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2bae613f9432871c86882137eba0512c15cb48a
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITCompiler$HandleRef.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITCompiler$SingletonHolder.class b/src/main/resources/org/python/modules/jffi/JITCompiler$SingletonHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..f4f5cd483ccb87693a3146c0cce5f28b681dc12e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITCompiler$SingletonHolder.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITCompiler.class b/src/main/resources/org/python/modules/jffi/JITCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..2926e15e5ac06690b5491ff4f9471da32907e6bd
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITCompiler.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITHandle.class b/src/main/resources/org/python/modules/jffi/JITHandle.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c471becf0afce1d6c8e9f309ac3332a20a73d90
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITHandle.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITInvoker.class b/src/main/resources/org/python/modules/jffi/JITInvoker.class
new file mode 100644
index 0000000000000000000000000000000000000000..198ed1fd51410951b3cffeb62f39ce3d3ccdf985
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITInvoker.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITInvoker0.class b/src/main/resources/org/python/modules/jffi/JITInvoker0.class
new file mode 100644
index 0000000000000000000000000000000000000000..439449dbaab86b41a6002d868d9ead3fd450b2e1
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITInvoker0.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITInvoker1.class b/src/main/resources/org/python/modules/jffi/JITInvoker1.class
new file mode 100644
index 0000000000000000000000000000000000000000..df3c91c39104724bb369bf591a5e4d9c0b5343a3
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITInvoker1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITInvoker2.class b/src/main/resources/org/python/modules/jffi/JITInvoker2.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d8c0aac9ee8ec105ada3b87e6e745c6e2cc4794
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITInvoker2.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITInvoker3.class b/src/main/resources/org/python/modules/jffi/JITInvoker3.class
new file mode 100644
index 0000000000000000000000000000000000000000..89d8ab1b02f5f06ec5bb6f022f99eb68bee0201f
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITInvoker3.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITInvoker4.class b/src/main/resources/org/python/modules/jffi/JITInvoker4.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2e101342ad9d582340588235b62dae7b1e55614
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITInvoker4.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITInvoker5.class b/src/main/resources/org/python/modules/jffi/JITInvoker5.class
new file mode 100644
index 0000000000000000000000000000000000000000..e2a9a6b93b286a3b8f965ce2d76d443cf342bef0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITInvoker5.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITInvoker6.class b/src/main/resources/org/python/modules/jffi/JITInvoker6.class
new file mode 100644
index 0000000000000000000000000000000000000000..8540050ca9cc46b912619a6f7e83d2bdbdfbf043
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITInvoker6.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITMethodGenerator.class b/src/main/resources/org/python/modules/jffi/JITMethodGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab30cb7b0f89e84f18f15b6e72973efcb576a810
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITMethodGenerator.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITRuntime.class b/src/main/resources/org/python/modules/jffi/JITRuntime.class
new file mode 100644
index 0000000000000000000000000000000000000000..f42e6d6905d13881ef39c421f2fc6ed28f3b7b97
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITRuntime.class differ
diff --git a/src/main/resources/org/python/modules/jffi/JITSignature.class b/src/main/resources/org/python/modules/jffi/JITSignature.class
new file mode 100644
index 0000000000000000000000000000000000000000..1449d4418bd02e99f91d447ffbfa004cca0fce2f
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/JITSignature.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Memory.class b/src/main/resources/org/python/modules/jffi/Memory.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7f4cbfaa06ae89096939452f473fe41e3c47bd3
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Memory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$1.class b/src/main/resources/org/python/modules/jffi/MemoryOp$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..bfabb1f179f9982a044ca676cd55be46666762be
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$BooleanOp.class b/src/main/resources/org/python/modules/jffi/MemoryOp$BooleanOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..d0338937ed0ff8802c468589c92d78deb028be6e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$BooleanOp.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Float32.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Float32.class
new file mode 100644
index 0000000000000000000000000000000000000000..350d69fd896a8936f802fd886f3450be3c0e3549
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Float32.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Float64.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Float64.class
new file mode 100644
index 0000000000000000000000000000000000000000..b9e4a6b28622c6b6d5970c9aabd1727157be5c9a
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Float64.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$InvalidOp.class b/src/main/resources/org/python/modules/jffi/MemoryOp$InvalidOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4d6e824213c012ffe9f6f2d937f945ff9d0faa5
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$InvalidOp.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$PointerOp.class b/src/main/resources/org/python/modules/jffi/MemoryOp$PointerOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..8168e40725abeeeb36e11d4f8904b00828a18bf7
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$PointerOp.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Signed16.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Signed16.class
new file mode 100644
index 0000000000000000000000000000000000000000..b38f4b4882684e710b42bbfb269cd5dc8a1b5eea
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Signed16.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Signed32.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Signed32.class
new file mode 100644
index 0000000000000000000000000000000000000000..6340a0675ae8c00c542b6c6c0f39a2dc635ce977
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Signed32.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Signed64.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Signed64.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf20698c46db54a7f76d275767a9d8730bc216e1
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Signed64.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Signed8.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Signed8.class
new file mode 100644
index 0000000000000000000000000000000000000000..939d41f38f1ce8e5e603b87df8926650c17819cb
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Signed8.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$StringOp.class b/src/main/resources/org/python/modules/jffi/MemoryOp$StringOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..7479d30caee5f03170258cc2fc80459bdfb906ad
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$StringOp.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$StructOp.class b/src/main/resources/org/python/modules/jffi/MemoryOp$StructOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..bfd4b124c49b59bfddf4e6389c3dde6615058ded
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$StructOp.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned16.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned16.class
new file mode 100644
index 0000000000000000000000000000000000000000..7245151bef11aac7241e5c99fd7693aa45ec7c75
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned16.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned32.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned32.class
new file mode 100644
index 0000000000000000000000000000000000000000..023700d7470e54c1b658e21625f9bdd81d21dfcf
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned32.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned64.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned64.class
new file mode 100644
index 0000000000000000000000000000000000000000..c089eaf1e0f24f0246137e47fa9d95d1322cdd62
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned64.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned8.class b/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned8.class
new file mode 100644
index 0000000000000000000000000000000000000000..15a20a7d6259627545bd12f57c274fd2407b5c7e
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$Unsigned8.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp$VoidOp.class b/src/main/resources/org/python/modules/jffi/MemoryOp$VoidOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..81c24cbf4284373937b6dc449c2b5138800d5b50
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp$VoidOp.class differ
diff --git a/src/main/resources/org/python/modules/jffi/MemoryOp.class b/src/main/resources/org/python/modules/jffi/MemoryOp.class
new file mode 100644
index 0000000000000000000000000000000000000000..911d5f0a41f7191b8eeb868a87f8d01a6202e6aa
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/MemoryOp.class differ
diff --git a/src/main/resources/org/python/modules/jffi/NativeDataConverter.class b/src/main/resources/org/python/modules/jffi/NativeDataConverter.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8a0a2d5958e37bb33a9cbde0473ca6694c38838
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/NativeDataConverter.class differ
diff --git a/src/main/resources/org/python/modules/jffi/NativeMemory.class b/src/main/resources/org/python/modules/jffi/NativeMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..acaece754876d7b759efa9b53216a194ebc0050d
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/NativeMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/NativeType$1.class b/src/main/resources/org/python/modules/jffi/NativeType$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0626f1f9029633f33811a892e1d9d599ab03a9f3
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/NativeType$1.class differ
diff --git a/src/main/resources/org/python/modules/jffi/NativeType.class b/src/main/resources/org/python/modules/jffi/NativeType.class
new file mode 100644
index 0000000000000000000000000000000000000000..97edac18d56508bec78908e440fc5f836da63835
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/NativeType.class differ
diff --git a/src/main/resources/org/python/modules/jffi/NullMemory.class b/src/main/resources/org/python/modules/jffi/NullMemory.class
new file mode 100644
index 0000000000000000000000000000000000000000..16b2e600b8fd5fd9c16c1a8c36d03be21192fd37
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/NullMemory.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Pointer.class b/src/main/resources/org/python/modules/jffi/Pointer.class
new file mode 100644
index 0000000000000000000000000000000000000000..24013683a5084612c8b9575766a296773475da3d
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Pointer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/PointerCData$PyExposer.class b/src/main/resources/org/python/modules/jffi/PointerCData$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d49e9129edd1d442dd4df6fd7cd226eca9de3515
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/PointerCData$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/PointerCData$contents_descriptor.class b/src/main/resources/org/python/modules/jffi/PointerCData$contents_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7ac0a8160f2e1b9359b18b7c07a28dba3c1572f1
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/PointerCData$contents_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/PointerCData$exposed___new__.class b/src/main/resources/org/python/modules/jffi/PointerCData$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..6be4ce0df6a224308d0c7821761fc4304be1f943
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/PointerCData$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/PointerCData$from_address_exposer.class b/src/main/resources/org/python/modules/jffi/PointerCData$from_address_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc1ba6af900f9d81938a9a41ccfc8163787c9a39
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/PointerCData$from_address_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/PointerCData.class b/src/main/resources/org/python/modules/jffi/PointerCData.class
new file mode 100644
index 0000000000000000000000000000000000000000..a50cf4ef5ca3871dd849ac644ce025ff50d716a4
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/PointerCData.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ScalarCData$PyExposer.class b/src/main/resources/org/python/modules/jffi/ScalarCData$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2da848cc84bc3f81299f6683cc142e8998ff7a31
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ScalarCData$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ScalarCData$__float___exposer.class b/src/main/resources/org/python/modules/jffi/ScalarCData$__float___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e17c5115e53335e21374422ebe47e8d83b406abc
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ScalarCData$__float___exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ScalarCData$__int___exposer.class b/src/main/resources/org/python/modules/jffi/ScalarCData$__int___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dd5b9b3c277d88eb118dd8fe4a60b2954a67b4cb
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ScalarCData$__int___exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ScalarCData$__long___exposer.class b/src/main/resources/org/python/modules/jffi/ScalarCData$__long___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2979ab5e37192e72460b4a006411f27797653924
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ScalarCData$__long___exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ScalarCData$exposed___new__.class b/src/main/resources/org/python/modules/jffi/ScalarCData$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..cf4d1212f4133214eb74d1a6d1ed6fdab0400bb7
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ScalarCData$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ScalarCData$from_address_exposer.class b/src/main/resources/org/python/modules/jffi/ScalarCData$from_address_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ce7003dec9acb5a28f7e2e0b1ddfc9d436a926c4
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ScalarCData$from_address_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ScalarCData$value_descriptor.class b/src/main/resources/org/python/modules/jffi/ScalarCData$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6c3fa7305408470c537290bca3626add9f7ee790
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ScalarCData$value_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/ScalarCData.class b/src/main/resources/org/python/modules/jffi/ScalarCData.class
new file mode 100644
index 0000000000000000000000000000000000000000..d244e39f0eb5f47721eb3adf591787694d63236d
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/ScalarCData.class differ
diff --git a/src/main/resources/org/python/modules/jffi/SkinnyMethodAdapter.class b/src/main/resources/org/python/modules/jffi/SkinnyMethodAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bf33c19e4b1f4b9a33055be9b3fadf1b89977f0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/SkinnyMethodAdapter.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StringCData$PyExposer.class b/src/main/resources/org/python/modules/jffi/StringCData$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..aa22ed092e57a607bedcc8293e6191b4c6b28e1d
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StringCData$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StringCData$exposed___new__.class b/src/main/resources/org/python/modules/jffi/StringCData$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..f237487b35cffc8a0acffc61ffccb871d822a516
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StringCData$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StringCData$from_address_exposer.class b/src/main/resources/org/python/modules/jffi/StringCData$from_address_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5410d34376a099a696133736508565746a09c732
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StringCData$from_address_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StringCData$value_descriptor.class b/src/main/resources/org/python/modules/jffi/StringCData$value_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0966f81888cc7788f9c5f26264c8416438becf89
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StringCData$value_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StringCData.class b/src/main/resources/org/python/modules/jffi/StringCData.class
new file mode 100644
index 0000000000000000000000000000000000000000..46ba7b57f14a33ec814e10c597a78a2e1bc337d7
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StringCData.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$Field$Field___get___exposer.class b/src/main/resources/org/python/modules/jffi/StructLayout$Field$Field___get___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad98f4a7e10dda81550ae85a890d3cc6378f507f
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$Field$Field___get___exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$Field$Field___set___exposer.class b/src/main/resources/org/python/modules/jffi/StructLayout$Field$Field___set___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b58fa2f2ccca0f240f34cc71515b99ef6fe907ec
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$Field$Field___set___exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$Field$PyExposer.class b/src/main/resources/org/python/modules/jffi/StructLayout$Field$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..45fd680a1a5c3f9980983920c9cb8eb0bd31e26f
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$Field$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$Field$ctype_descriptor.class b/src/main/resources/org/python/modules/jffi/StructLayout$Field$ctype_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8299780b6f22f10ecbb06f00bf9e4914338ad196
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$Field$ctype_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$Field$get_exposer.class b/src/main/resources/org/python/modules/jffi/StructLayout$Field$get_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..af42d4d6c43f71a7327c4a681c6cdb87de0a1a52
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$Field$get_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$Field$offset_descriptor.class b/src/main/resources/org/python/modules/jffi/StructLayout$Field$offset_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dede55c28036776c0236a9333225a77dd9cdfd4
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$Field$offset_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$Field$set_exposer.class b/src/main/resources/org/python/modules/jffi/StructLayout$Field$set_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..789e8d341e25db2fa5ea56ca61ed3cabbc260764
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$Field$set_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$Field.class b/src/main/resources/org/python/modules/jffi/StructLayout$Field.class
new file mode 100644
index 0000000000000000000000000000000000000000..91c517fff5a9475b772b1e2be2e5d660fcfa4f65
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$Field.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$PyExposer.class b/src/main/resources/org/python/modules/jffi/StructLayout$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..17e749beb179f6cbd306f122bc150e55ed538f6b
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField$PyExposer.class b/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..630897573e2bc68575c70a8e96e1d1d0b5c47685
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField$exposed___new__.class b/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..52948bc36fa3e1d7961ebcf4dbd0431a2f6184e5
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField.class b/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed974a124f77dce2873f1839900feaee8cff7f91
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$ScalarField.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$StructUtil.class b/src/main/resources/org/python/modules/jffi/StructLayout$StructUtil.class
new file mode 100644
index 0000000000000000000000000000000000000000..b050e155fb6cdd268b427018d5322abe0752a392
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$StructUtil.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout$exposed___new__.class b/src/main/resources/org/python/modules/jffi/StructLayout$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..04c2a6c8bbc528934adcd0652a35e93f88ad3b9d
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/StructLayout.class b/src/main/resources/org/python/modules/jffi/StructLayout.class
new file mode 100644
index 0000000000000000000000000000000000000000..168f50deb60fcc7246f8f90ac2a2ee0bae255a9b
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/StructLayout.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Structure$PyExposer.class b/src/main/resources/org/python/modules/jffi/Structure$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..94a101b19814e4f175b2b1dfec145c1d9d776713
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Structure$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Structure$exposed___new__.class b/src/main/resources/org/python/modules/jffi/Structure$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..e82604b12ef693a2237dab2e8317f159d567a30d
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Structure$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Structure$from_address_exposer.class b/src/main/resources/org/python/modules/jffi/Structure$from_address_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1109bf47771bccd2464ed707aa2fac187c680a4a
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Structure$from_address_exposer.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Structure.class b/src/main/resources/org/python/modules/jffi/Structure.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd8bdc4ca0657c4e94d0d71986279d87673b15c0
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Structure.class differ
diff --git a/src/main/resources/org/python/modules/jffi/Util.class b/src/main/resources/org/python/modules/jffi/Util.class
new file mode 100644
index 0000000000000000000000000000000000000000..be4dae2f0bd6fac97434f4d8d43fc808fc270b01
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/Util.class differ
diff --git a/src/main/resources/org/python/modules/jffi/jffi.class b/src/main/resources/org/python/modules/jffi/jffi.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9e335b22596db4f3eeebbbd16a80119c44b6fec
Binary files /dev/null and b/src/main/resources/org/python/modules/jffi/jffi.class differ
diff --git a/src/main/resources/org/python/modules/math.class b/src/main/resources/org/python/modules/math.class
new file mode 100644
index 0000000000000000000000000000000000000000..6349b7169ce33e50d0dcf653e53f2896b560f2fa
Binary files /dev/null and b/src/main/resources/org/python/modules/math.class differ
diff --git a/src/main/resources/org/python/modules/math_erf.class b/src/main/resources/org/python/modules/math_erf.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d3f4e1c9bffa9fc4a94f07a99ef57ca18630742
Binary files /dev/null and b/src/main/resources/org/python/modules/math_erf.class differ
diff --git a/src/main/resources/org/python/modules/math_gamma.class b/src/main/resources/org/python/modules/math_gamma.class
new file mode 100644
index 0000000000000000000000000000000000000000..fddc77809261af42ee2760e5b2da0d5a1929a1f5
Binary files /dev/null and b/src/main/resources/org/python/modules/math_gamma.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyAttrGetter$PyExposer.class b/src/main/resources/org/python/modules/operator$PyAttrGetter$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..00a582c876fb997e31d75a13e29bdc0b60bbfadf
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyAttrGetter$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyAttrGetter$attrgetter___call___exposer.class b/src/main/resources/org/python/modules/operator$PyAttrGetter$attrgetter___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d1c84f48099165dcadb05d811bd163a99132c461
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyAttrGetter$attrgetter___call___exposer.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyAttrGetter$exposed___new__.class b/src/main/resources/org/python/modules/operator$PyAttrGetter$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..88e81356e9586580ab1438205f5114943eccd895
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyAttrGetter$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyAttrGetter.class b/src/main/resources/org/python/modules/operator$PyAttrGetter.class
new file mode 100644
index 0000000000000000000000000000000000000000..946a3eec6f70330674496520eb51321b043078e8
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyAttrGetter.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyItemGetter$PyExposer.class b/src/main/resources/org/python/modules/operator$PyItemGetter$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fd200885520beb6af09cf92c32d63827007b915
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyItemGetter$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyItemGetter$exposed___new__.class b/src/main/resources/org/python/modules/operator$PyItemGetter$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..67ec660831568f88853349c086f17fb5ed214885
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyItemGetter$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyItemGetter$itemgetter___call___exposer.class b/src/main/resources/org/python/modules/operator$PyItemGetter$itemgetter___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7a2cc20d7581c33d3fb63b7dfe5d6d66d794b2d0
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyItemGetter$itemgetter___call___exposer.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyItemGetter.class b/src/main/resources/org/python/modules/operator$PyItemGetter.class
new file mode 100644
index 0000000000000000000000000000000000000000..519264ade92bef23ea28b857320191a4a66686e6
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyItemGetter.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyMethodCaller$PyExposer.class b/src/main/resources/org/python/modules/operator$PyMethodCaller$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..530810b334449e17ce77f0be6adbf31ad1752237
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyMethodCaller$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyMethodCaller$__doc___descriptor.class b/src/main/resources/org/python/modules/operator$PyMethodCaller$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9ba09e335f9d6ee72c2d38ad3e769e6412d5cc45
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyMethodCaller$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyMethodCaller$exposed___new__.class b/src/main/resources/org/python/modules/operator$PyMethodCaller$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0035f971811773deddebe0ecc59c8722846dea8
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyMethodCaller$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyMethodCaller$methodcaller___call___exposer.class b/src/main/resources/org/python/modules/operator$PyMethodCaller$methodcaller___call___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d5c30196decdbd3572eee2b4654cfb4c164777dd
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyMethodCaller$methodcaller___call___exposer.class differ
diff --git a/src/main/resources/org/python/modules/operator$PyMethodCaller.class b/src/main/resources/org/python/modules/operator$PyMethodCaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..caea14daf4f0cef8c15981166f077f8cb077d05f
Binary files /dev/null and b/src/main/resources/org/python/modules/operator$PyMethodCaller.class differ
diff --git a/src/main/resources/org/python/modules/operator.class b/src/main/resources/org/python/modules/operator.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae78cf32fdb29aeb2a2136c3948defc507b39b7b
Binary files /dev/null and b/src/main/resources/org/python/modules/operator.class differ
diff --git a/src/main/resources/org/python/modules/posix/Hide.class b/src/main/resources/org/python/modules/posix/Hide.class
new file mode 100644
index 0000000000000000000000000000000000000000..93aa06c99f7bd89d8898a1dac8801b3906729633
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/Hide.class differ
diff --git a/src/main/resources/org/python/modules/posix/Hider.class b/src/main/resources/org/python/modules/posix/Hider.class
new file mode 100644
index 0000000000000000000000000000000000000000..3442ade80a1c5bf2a9a346f2bb03d7b0b6af89cf
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/Hider.class differ
diff --git a/src/main/resources/org/python/modules/posix/OS.class b/src/main/resources/org/python/modules/posix/OS.class
new file mode 100644
index 0000000000000000000000000000000000000000..f670c4b399a4b07bfc9576b53d48579f9cfd2548
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/OS.class differ
diff --git a/src/main/resources/org/python/modules/posix/PosixImpl.class b/src/main/resources/org/python/modules/posix/PosixImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..ca5493b89cf44b298a30615ef8e87e426192a21f
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PosixImpl.class differ
diff --git a/src/main/resources/org/python/modules/posix/PosixModule$LstatFunction.class b/src/main/resources/org/python/modules/posix/PosixModule$LstatFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c1e7a83325d0da8190947d02f7e49109af85c5a
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PosixModule$LstatFunction.class differ
diff --git a/src/main/resources/org/python/modules/posix/PosixModule$StatFunction.class b/src/main/resources/org/python/modules/posix/PosixModule$StatFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e5b8ec6ff9058e52584cab810764dda23b4ebc7
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PosixModule$StatFunction.class differ
diff --git a/src/main/resources/org/python/modules/posix/PosixModule$UrandomSource.class b/src/main/resources/org/python/modules/posix/PosixModule$UrandomSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecad19d2a7e5a15bd8a019cfe4806c3a6bd7c7e8
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PosixModule$UrandomSource.class differ
diff --git a/src/main/resources/org/python/modules/posix/PosixModule.class b/src/main/resources/org/python/modules/posix/PosixModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..d528d7b28e792dbcb3bf954b9dbd95615ff53da6
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PosixModule.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$PyExposer.class b/src/main/resources/org/python/modules/posix/PyStatResult$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..29ab585e439f8cb0160b1c94fb82635d807eced9
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$exposed___new__.class b/src/main/resources/org/python/modules/posix/PyStatResult$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..395313d162464d2ec552cca509bdf4792a7a216c
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$n_fields_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$n_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..49a9b8ea98acb62951043836ee9a442cb0444922
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$n_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$n_sequence_fields_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$n_sequence_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c2620e9908b65f139758a02917d2f91980a3b94
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$n_sequence_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$n_unnamed_fields_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$n_unnamed_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..913a57ba28157f27d2a17da51ebcfc2bc81aabc2
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$n_unnamed_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_atime_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_atime_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..508a3f94d9f27496ee21a34320b3ce8f9fff83a9
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_atime_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_ctime_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_ctime_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..392bc11bcfb5afc55c3caad025a95aad44edc4a3
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_ctime_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_dev_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_dev_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff27a0e0bb0c06305fb4eebddff2fb287d152b88
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_dev_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_gid_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_gid_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..258b08ebe295c8004ceb4e5d319216ac007f7051
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_gid_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_ino_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_ino_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0fa96fff6e4ea5d84227ee610226499ecb3bc200
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_ino_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_mode_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_mode_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5d70e879542180300d9b96580a19de9778bea50
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_mode_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_mtime_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_mtime_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..d905430286dfc7fed7ea3f704a4051f792eb47b9
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_mtime_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_nlink_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_nlink_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..09c520fb96328a03470e8ec9d9c4f681398bc045
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_nlink_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_size_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_size_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b54bdd4fe66a3fd03e6e6eb3c80dfba5b8f36daa
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_size_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$st_uid_descriptor.class b/src/main/resources/org/python/modules/posix/PyStatResult$st_uid_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..60771cf35e8853b42001793a0d5e31b0b9006fa5
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$st_uid_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___eq___exposer.class b/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..26e56ccdc2c90eb9e9ba88dd52f4c1f117f1454a
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___eq___exposer.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___ne___exposer.class b/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7fbdbb1a400edd3b7e985bc923768a22b767f675
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___ne___exposer.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___reduce___exposer.class b/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b9de7a21d02583a2eec97f23c0989c325f5e85d
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult$stat_result___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/modules/posix/PyStatResult.class b/src/main/resources/org/python/modules/posix/PyStatResult.class
new file mode 100644
index 0000000000000000000000000000000000000000..b22eb3bf9035b6c7eba0816e3d26e09a9dcdb2b5
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PyStatResult.class differ
diff --git a/src/main/resources/org/python/modules/posix/PythonPOSIXHandler.class b/src/main/resources/org/python/modules/posix/PythonPOSIXHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..586e9689641d85028a438f819b81ed50222962eb
Binary files /dev/null and b/src/main/resources/org/python/modules/posix/PythonPOSIXHandler.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$PyExposer.class b/src/main/resources/org/python/modules/random/PyRandom$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..f90df54ebed4b45c29fcfa30bb029cdf482c8ef6
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$Random___init___exposer.class b/src/main/resources/org/python/modules/random/PyRandom$Random___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e457c09ce3b788574c158123dd8069997bbc945c
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$Random___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$Random_getrandbits_exposer.class b/src/main/resources/org/python/modules/random/PyRandom$Random_getrandbits_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..7069b5750e8dead62972a7ebb04c07b07eaff807
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$Random_getrandbits_exposer.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$Random_getstate_exposer.class b/src/main/resources/org/python/modules/random/PyRandom$Random_getstate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..5147f781a3c1260a60172dc7cfa3cf5b9daeee17
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$Random_getstate_exposer.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$Random_jumpahead_exposer.class b/src/main/resources/org/python/modules/random/PyRandom$Random_jumpahead_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..85f668a080c19a3f5be9a8178f9d0ac5cafed96b
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$Random_jumpahead_exposer.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$Random_random_exposer.class b/src/main/resources/org/python/modules/random/PyRandom$Random_random_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..edf7504f0c795ec9c8470608ee78efe14f5ba7b0
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$Random_random_exposer.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$Random_seed_exposer.class b/src/main/resources/org/python/modules/random/PyRandom$Random_seed_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac24c000b77da2960d708d89ed089c0fcc406cd2
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$Random_seed_exposer.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$Random_setstate_exposer.class b/src/main/resources/org/python/modules/random/PyRandom$Random_setstate_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..d4118be8e33b42dbb8dd7454abfd6ae51b25fc3a
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$Random_setstate_exposer.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom$exposed___new__.class b/src/main/resources/org/python/modules/random/PyRandom$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..b7bc588da84e4c3624a3acca268db9bf76733399
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandom.class b/src/main/resources/org/python/modules/random/PyRandom.class
new file mode 100644
index 0000000000000000000000000000000000000000..a54f8d8a147a165c19a88a874f485ddd9a827514
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandom.class differ
diff --git a/src/main/resources/org/python/modules/random/PyRandomDerived.class b/src/main/resources/org/python/modules/random/PyRandomDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..5fdee5fb4a64f94fe994610f64d67b9d43799ed3
Binary files /dev/null and b/src/main/resources/org/python/modules/random/PyRandomDerived.class differ
diff --git a/src/main/resources/org/python/modules/random/RandomModule.class b/src/main/resources/org/python/modules/random/RandomModule.class
new file mode 100644
index 0000000000000000000000000000000000000000..ac9558b9c67af6c99d0ca1aa575db32d1cdbfa63
Binary files /dev/null and b/src/main/resources/org/python/modules/random/RandomModule.class differ
diff --git a/src/main/resources/org/python/modules/sre/MatchObject.class b/src/main/resources/org/python/modules/sre/MatchObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..6bceda9b4e2a558a8dc193b2d5c5bb64a911c55a
Binary files /dev/null and b/src/main/resources/org/python/modules/sre/MatchObject.class differ
diff --git a/src/main/resources/org/python/modules/sre/PatternObject.class b/src/main/resources/org/python/modules/sre/PatternObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..6bcbfb431b38c5f2ed29a6603a2e316bb85b1c61
Binary files /dev/null and b/src/main/resources/org/python/modules/sre/PatternObject.class differ
diff --git a/src/main/resources/org/python/modules/sre/SRE_REPEAT.class b/src/main/resources/org/python/modules/sre/SRE_REPEAT.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ecee77153104e91fad457128efd09da56d340e0
Binary files /dev/null and b/src/main/resources/org/python/modules/sre/SRE_REPEAT.class differ
diff --git a/src/main/resources/org/python/modules/sre/SRE_STATE.class b/src/main/resources/org/python/modules/sre/SRE_STATE.class
new file mode 100644
index 0000000000000000000000000000000000000000..a8e5c525163c318715a1c5a66d107ffd81d15ff3
Binary files /dev/null and b/src/main/resources/org/python/modules/sre/SRE_STATE.class differ
diff --git a/src/main/resources/org/python/modules/sre/ScannerObject.class b/src/main/resources/org/python/modules/sre/ScannerObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..8779abd253d98241b34986c03b9357b6b2e3194a
Binary files /dev/null and b/src/main/resources/org/python/modules/sre/ScannerObject.class differ
diff --git a/src/main/resources/org/python/modules/struct$BEDoubleFormatDef.class b/src/main/resources/org/python/modules/struct$BEDoubleFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd62410930f25c2110946f5985404a86dfe61acb
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$BEDoubleFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$BEFloatFormatDef.class b/src/main/resources/org/python/modules/struct$BEFloatFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..3cf7131d5ea0fdcd9d64787ad185b50eea41e4b9
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$BEFloatFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$BEIntFormatDef.class b/src/main/resources/org/python/modules/struct$BEIntFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..687258a1c2704b5024822d9271734f0523a2e72f
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$BEIntFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$BELongFormatDef.class b/src/main/resources/org/python/modules/struct$BELongFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..76777c17fc217b2ada90ab90e1f35734130ab5ee
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$BELongFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$BEShortFormatDef.class b/src/main/resources/org/python/modules/struct$BEShortFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..940aea75626f40c3ce24aaa3fe5d3b25c52d441f
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$BEShortFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$BEUnsignedIntFormatDef.class b/src/main/resources/org/python/modules/struct$BEUnsignedIntFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0a20bd2203ea4a997a7164b523e4cd311df4a5e
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$BEUnsignedIntFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$BEUnsignedLongFormatDef.class b/src/main/resources/org/python/modules/struct$BEUnsignedLongFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..56270ed4f629f9d85258b4df3e3c5113d4d8fd08
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$BEUnsignedLongFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$BEUnsignedShortFormatDef.class b/src/main/resources/org/python/modules/struct$BEUnsignedShortFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..2ea9228bbfaad7b2b1708374a675a77a8aa5cd25
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$BEUnsignedShortFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$ByteFormatDef.class b/src/main/resources/org/python/modules/struct$ByteFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3da83f274e53572bf227cf8ab705aad45fcea84
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$ByteFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$ByteStream.class b/src/main/resources/org/python/modules/struct$ByteStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b8b2e7f2fead6bff814381aec79cc10c6d4014c
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$ByteStream.class differ
diff --git a/src/main/resources/org/python/modules/struct$CharFormatDef.class b/src/main/resources/org/python/modules/struct$CharFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc52beed33bbc1518e38007801c7bfe84aca5fde
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$CharFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$FormatDef.class b/src/main/resources/org/python/modules/struct$FormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..710a50e6c3c4c23f087cb1584850be5e6d8e6dae
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$FormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$LEDoubleFormatDef.class b/src/main/resources/org/python/modules/struct$LEDoubleFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..a450bc3db206530ff3efb604c036e1c71a5ed561
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$LEDoubleFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$LEFloatFormatDef.class b/src/main/resources/org/python/modules/struct$LEFloatFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e20b5dd28597ce3bc3e67e4570722a737a3aa8c
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$LEFloatFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$LEIntFormatDef.class b/src/main/resources/org/python/modules/struct$LEIntFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..cac35a157befcbb498b2687fb3e3b42d9462be2f
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$LEIntFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$LELongFormatDef.class b/src/main/resources/org/python/modules/struct$LELongFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bc1489ecfb6ada7c4f72e3c38fdcd003bb8519a
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$LELongFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$LEShortFormatDef.class b/src/main/resources/org/python/modules/struct$LEShortFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..e925315ce9379ab8055f432192902651406da893
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$LEShortFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$LEUnsignedIntFormatDef.class b/src/main/resources/org/python/modules/struct$LEUnsignedIntFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a6bba7821b00031e3b97690ce744b92521388d4
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$LEUnsignedIntFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$LEUnsignedLongFormatDef.class b/src/main/resources/org/python/modules/struct$LEUnsignedLongFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..5ca9368513973cb1dbba260a0969590e6ce1bc6a
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$LEUnsignedLongFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$LEUnsignedShortFormatDef.class b/src/main/resources/org/python/modules/struct$LEUnsignedShortFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..7156cf62e668670a6beed45b16a8d818d00223ca
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$LEUnsignedShortFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$PadFormatDef.class b/src/main/resources/org/python/modules/struct$PadFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..5312aac2adc89f4fd5a09e2e7813c76ca0d1f6c6
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$PadFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$PascalStringFormatDef.class b/src/main/resources/org/python/modules/struct$PascalStringFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..5de8c5d8a97f9e011528703a91e7aa9dfa8f5277
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$PascalStringFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$PointerFormatDef.class b/src/main/resources/org/python/modules/struct$PointerFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..b768c7041e3891e85045fb79370b92188efb1317
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$PointerFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$StringFormatDef.class b/src/main/resources/org/python/modules/struct$StringFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..0834d8629b323c6d48fef73b67b6703d1bb2c34e
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$StringFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct$UnsignedByteFormatDef.class b/src/main/resources/org/python/modules/struct$UnsignedByteFormatDef.class
new file mode 100644
index 0000000000000000000000000000000000000000..13398de9abf04892b8ee637e986d3e1c08e217cb
Binary files /dev/null and b/src/main/resources/org/python/modules/struct$UnsignedByteFormatDef.class differ
diff --git a/src/main/resources/org/python/modules/struct.class b/src/main/resources/org/python/modules/struct.class
new file mode 100644
index 0000000000000000000000000000000000000000..a639703138433b00d2714af98e2eb10358380fe2
Binary files /dev/null and b/src/main/resources/org/python/modules/struct.class differ
diff --git a/src/main/resources/org/python/modules/synchronize$SynchronizedCallable.class b/src/main/resources/org/python/modules/synchronize$SynchronizedCallable.class
new file mode 100644
index 0000000000000000000000000000000000000000..3ab0d55fc66a77f4c8da984997f0886c6eba91fd
Binary files /dev/null and b/src/main/resources/org/python/modules/synchronize$SynchronizedCallable.class differ
diff --git a/src/main/resources/org/python/modules/synchronize.class b/src/main/resources/org/python/modules/synchronize.class
new file mode 100644
index 0000000000000000000000000000000000000000..00c52b1f50f1005ef7f90d609f5f8d01e58453d7
Binary files /dev/null and b/src/main/resources/org/python/modules/synchronize.class differ
diff --git a/src/main/resources/org/python/modules/thread/PyLocal$PyExposer.class b/src/main/resources/org/python/modules/thread/PyLocal$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ee4fdd18b4616f9029b29fda3efa53baed13c212
Binary files /dev/null and b/src/main/resources/org/python/modules/thread/PyLocal$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/thread/PyLocal$__dict___descriptor.class b/src/main/resources/org/python/modules/thread/PyLocal$__dict___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..22024bdd8cd03054a1cad8bd75e95b6431338934
Binary files /dev/null and b/src/main/resources/org/python/modules/thread/PyLocal$__dict___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/thread/PyLocal$exposed___new__.class b/src/main/resources/org/python/modules/thread/PyLocal$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..4bc3715c8c8bcb9bd0df1923624fe0cc0977b4b8
Binary files /dev/null and b/src/main/resources/org/python/modules/thread/PyLocal$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/thread/PyLocal.class b/src/main/resources/org/python/modules/thread/PyLocal.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a303e24c225d3bb4c517caedf907b56f7048381
Binary files /dev/null and b/src/main/resources/org/python/modules/thread/PyLocal.class differ
diff --git a/src/main/resources/org/python/modules/thread/PyLocalDerived.class b/src/main/resources/org/python/modules/thread/PyLocalDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..134c2450817ca7b8e43ad2370f2898016752be8d
Binary files /dev/null and b/src/main/resources/org/python/modules/thread/PyLocalDerived.class differ
diff --git a/src/main/resources/org/python/modules/thread/PyLock.class b/src/main/resources/org/python/modules/thread/PyLock.class
new file mode 100644
index 0000000000000000000000000000000000000000..931c1de48afa51da89c16ef11b7efe2c59183d1b
Binary files /dev/null and b/src/main/resources/org/python/modules/thread/PyLock.class differ
diff --git a/src/main/resources/org/python/modules/thread/thread.class b/src/main/resources/org/python/modules/thread/thread.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e8786f08335f8762e156850ca869c450d92b5fb
Binary files /dev/null and b/src/main/resources/org/python/modules/thread/thread.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$PyExposer.class b/src/main/resources/org/python/modules/time/PyTimeTuple$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6868d5c719c406dcd64553ed42f8fa1bc3f7921
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$exposed___new__.class b/src/main/resources/org/python/modules/time/PyTimeTuple$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..856e45726f6516162a2877026dda91c40dc9ade3
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$n_fields_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$n_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..dbf19fa040393726b734a4a5e63567f410375afd
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$n_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$n_sequence_fields_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$n_sequence_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..52feb43a2ff02a64bad2c55b9f315cf7d167e393
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$n_sequence_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$n_unnamed_fields_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$n_unnamed_fields_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b3e603d3a5390bf09b4cf5ffba354d248dbc83a9
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$n_unnamed_fields_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___eq___exposer.class b/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___eq___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..baebbb72b8bbaa5ef796c88796c7db0c09761d4d
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___eq___exposer.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___ne___exposer.class b/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___ne___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..62371ee0f78d21f34cd8fb90edfb05b372435482
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___ne___exposer.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___reduce___exposer.class b/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___reduce___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d1de2d7d1460c06977e2987265f9ebc74b1c9e5
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time___reduce___exposer.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time_toString_exposer.class b/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..126f54561c88109671340a59a11671b931a1559b
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$struct_time_toString_exposer.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_hour_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_hour_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b5876ada8747be2ff8f4adeeb3cb3cb3019be247
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_hour_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_isdst_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_isdst_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..0af45f25c683ee04ca1cf0c06e79137acc7ce24d
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_isdst_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_mday_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_mday_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..f84a37bcd3990011d39604d90bccbe8d05687c7f
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_mday_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_min_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_min_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6aad3b35f784d5497bd2834925a16957a5a1d238
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_min_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_mon_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_mon_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..37af7253df8c37a48ad04162e93c94e74465c21b
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_mon_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_sec_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_sec_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e84a9b1ba81e583fb677bef5d0b9571ca112f70
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_sec_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_wday_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_wday_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e14f361429be81479106c6de9a5baa2b19dece19
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_wday_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_yday_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_yday_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2e74cb0519068696490f81b528b5a6786f2d37a6
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_yday_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple$tm_year_descriptor.class b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_year_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8a7797e93a3e3ca2563ed84d02da87437a071be
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple$tm_year_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/time/PyTimeTuple.class b/src/main/resources/org/python/modules/time/PyTimeTuple.class
new file mode 100644
index 0000000000000000000000000000000000000000..36f26bd8bc0ceb3c03ede8c0e4a8ada9142ca121
Binary files /dev/null and b/src/main/resources/org/python/modules/time/PyTimeTuple.class differ
diff --git a/src/main/resources/org/python/modules/time/Time$1.class b/src/main/resources/org/python/modules/time/Time$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9939b1aceb9fe73221291617d1aead174b576cb
Binary files /dev/null and b/src/main/resources/org/python/modules/time/Time$1.class differ
diff --git a/src/main/resources/org/python/modules/time/Time$2.class b/src/main/resources/org/python/modules/time/Time$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..638ce27cf2f25bb2187800afbd88c3dcd96eb6ec
Binary files /dev/null and b/src/main/resources/org/python/modules/time/Time$2.class differ
diff --git a/src/main/resources/org/python/modules/time/Time.class b/src/main/resources/org/python/modules/time/Time.class
new file mode 100644
index 0000000000000000000000000000000000000000..46caf8b21e5bdc62f832004626cbdcd782593f08
Binary files /dev/null and b/src/main/resources/org/python/modules/time/Time.class differ
diff --git a/src/main/resources/org/python/modules/time/TimeFunctions.class b/src/main/resources/org/python/modules/time/TimeFunctions.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c9f26adf09b0d9c90f7339d4bac8180cc2262e1
Binary files /dev/null and b/src/main/resources/org/python/modules/time/TimeFunctions.class differ
diff --git a/src/main/resources/org/python/modules/ucnhash.class b/src/main/resources/org/python/modules/ucnhash.class
new file mode 100644
index 0000000000000000000000000000000000000000..450004449fb1e30e5f448e37a027bf6cfcd35af0
Binary files /dev/null and b/src/main/resources/org/python/modules/ucnhash.class differ
diff --git a/src/main/resources/org/python/modules/ucnhash.dat b/src/main/resources/org/python/modules/ucnhash.dat
new file mode 100644
index 0000000000000000000000000000000000000000..2fd71d4741af7336a16adf2096c8a3714e448c85
Binary files /dev/null and b/src/main/resources/org/python/modules/ucnhash.dat differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimport$1.class b/src/main/resources/org/python/modules/zipimport/zipimport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e04b68925d9dbe9976826c12ace73b5a719ffb8
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimport$1.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimport.class b/src/main/resources/org/python/modules/zipimport/zipimport.class
new file mode 100644
index 0000000000000000000000000000000000000000..da12138012958183397dd5f497f57515aa7778b5
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimport.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$PyExposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$PyExposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..78e48d56699d6b79f420174892421da591597652
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$PyExposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$ZipBundle.class b/src/main/resources/org/python/modules/zipimport/zipimporter$ZipBundle.class
new file mode 100644
index 0000000000000000000000000000000000000000..a18a006260625ac323fdeeaadcd7d840996347d8
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$ZipBundle.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$__doc___descriptor.class b/src/main/resources/org/python/modules/zipimport/zipimporter$__doc___descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..edac3b0952dd74f34003d03ad78ddb3e3c932e53
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$__doc___descriptor.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$_files_descriptor.class b/src/main/resources/org/python/modules/zipimport/zipimporter$_files_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e450125d66c6d1f230b08491ebd0f96c341b59eb
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$_files_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$archive_descriptor.class b/src/main/resources/org/python/modules/zipimport/zipimporter$archive_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..6156f45979ab86f3ae257e810820fc9def6c6a07
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$archive_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$exposed___new__.class b/src/main/resources/org/python/modules/zipimport/zipimporter$exposed___new__.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c6a58056be3abf1cf20dab5a219699244bbd5b5
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$exposed___new__.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$prefix_descriptor.class b/src/main/resources/org/python/modules/zipimport/zipimporter$prefix_descriptor.class
new file mode 100644
index 0000000000000000000000000000000000000000..2a19dcf18e254b4cfea65f2eb755b206870eb421
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$prefix_descriptor.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter___init___exposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter___init___exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..9edeff557ac3d89b45211a205a35a0fc4b79b554
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter___init___exposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_find_module_exposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_find_module_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..616ea3ea9a03b9cb2c67b4bb571d27c33d605358
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_find_module_exposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_code_exposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_code_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c81c4523ad9a45bc905f85a2b5a20e8f7a69a52
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_code_exposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_data_exposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_data_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b26a4afd74c6fe36d70c75824dcb5b5be43064d2
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_data_exposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_source_exposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_source_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec5f5c8e09e574536e5a789e63dcb913a10b24a9
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_get_source_exposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_is_package_exposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_is_package_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..dffea0cc43518d518fa1555c9c9558f2e31af696
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_is_package_exposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_load_module_exposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_load_module_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e51fda50dd7355c274546c7aec258f7873c8256
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_load_module_exposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_toString_exposer.class b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_toString_exposer.class
new file mode 100644
index 0000000000000000000000000000000000000000..b61973f0e48cbd10aadb4b127bd7fa2155da7ea0
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter$zipimporter_toString_exposer.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporter.class b/src/main/resources/org/python/modules/zipimport/zipimporter.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b61cfebe8b3f10aa97a8e7a9c28483e2c59a172
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporter.class differ
diff --git a/src/main/resources/org/python/modules/zipimport/zipimporterDerived.class b/src/main/resources/org/python/modules/zipimport/zipimporterDerived.class
new file mode 100644
index 0000000000000000000000000000000000000000..522a4602aed37cd6a310ef46655efba0f0a62edb
Binary files /dev/null and b/src/main/resources/org/python/modules/zipimport/zipimporterDerived.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/AnnotationVisitor.class b/src/main/resources/org/python/objectweb/asm/AnnotationVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..57a19c21108302f3085748c5cfa188d6b27ee154
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/AnnotationVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/AnnotationWriter.class b/src/main/resources/org/python/objectweb/asm/AnnotationWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..319a0c033ec145a6aa603f4ee73366c3c993f859
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/AnnotationWriter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Attribute.class b/src/main/resources/org/python/objectweb/asm/Attribute.class
new file mode 100644
index 0000000000000000000000000000000000000000..30ff51963b6bbdbd470ebc79fa44d2139f53925f
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Attribute.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/ByteVector.class b/src/main/resources/org/python/objectweb/asm/ByteVector.class
new file mode 100644
index 0000000000000000000000000000000000000000..587b9ced3ceb873d3c22bc2d5a3e0d797462531e
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/ByteVector.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/ClassReader.class b/src/main/resources/org/python/objectweb/asm/ClassReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..2dd0d3c0f2d9f2e0880d5b64ca54f73bf1ffaf2d
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/ClassReader.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/ClassVisitor.class b/src/main/resources/org/python/objectweb/asm/ClassVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cccedec5c2d3ce2f0d4c486d24e26c7fce096af6
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/ClassVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/ClassWriter.class b/src/main/resources/org/python/objectweb/asm/ClassWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..f277a40d0fe4eb9428cfb256d3c684d43c878e56
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/ClassWriter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Edge.class b/src/main/resources/org/python/objectweb/asm/Edge.class
new file mode 100644
index 0000000000000000000000000000000000000000..3e2f92ec4a3774dabef5c876cb4d9217f7392d5a
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Edge.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/FieldVisitor.class b/src/main/resources/org/python/objectweb/asm/FieldVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..3b725e4e2a1a93438a23c265c50baaf5eff80241
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/FieldVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/FieldWriter.class b/src/main/resources/org/python/objectweb/asm/FieldWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d5952c975a5e6623f24a28395b18f6e974ba695
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/FieldWriter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Frame.class b/src/main/resources/org/python/objectweb/asm/Frame.class
new file mode 100644
index 0000000000000000000000000000000000000000..e7b24ec691a2f460b1428b58405617da98cf9d2f
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Frame.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Handle.class b/src/main/resources/org/python/objectweb/asm/Handle.class
new file mode 100644
index 0000000000000000000000000000000000000000..fe7961af7d7f9775e9350204765b8d442f3c1fb9
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Handle.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Handler.class b/src/main/resources/org/python/objectweb/asm/Handler.class
new file mode 100644
index 0000000000000000000000000000000000000000..357811d95ba64272ab33d6425623df3969979e2e
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Handler.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Item.class b/src/main/resources/org/python/objectweb/asm/Item.class
new file mode 100644
index 0000000000000000000000000000000000000000..0dd6bc164e1bc8765644f56f7729278b0b7edc01
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Item.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Label.class b/src/main/resources/org/python/objectweb/asm/Label.class
new file mode 100644
index 0000000000000000000000000000000000000000..3df01bd4d766682d95ac383f77789fad6c7e8939
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Label.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/MethodVisitor.class b/src/main/resources/org/python/objectweb/asm/MethodVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..67cd7502a2a66b80f383c6b87d6c44c8b930da7b
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/MethodVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/MethodWriter.class b/src/main/resources/org/python/objectweb/asm/MethodWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c3ba943be4289a96a47c2264ff75c24eab841eba
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/MethodWriter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Opcodes.class b/src/main/resources/org/python/objectweb/asm/Opcodes.class
new file mode 100644
index 0000000000000000000000000000000000000000..83fe29e53afd55104d70016b49d5aacc0a1d63d0
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Opcodes.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/Type.class b/src/main/resources/org/python/objectweb/asm/Type.class
new file mode 100644
index 0000000000000000000000000000000000000000..29eae8aa6567fb3b687fa1d9f291bb57a890f9a6
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/Type.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/AdviceAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/AdviceAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..471d45053ffe8bb5bb98c854559067a22d0370a7
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/AdviceAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/AnalyzerAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/AnalyzerAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..71235773a6241e7db48defe960af6c9b0ca902bf
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/AnalyzerAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/CodeSizeEvaluator.class b/src/main/resources/org/python/objectweb/asm/commons/CodeSizeEvaluator.class
new file mode 100644
index 0000000000000000000000000000000000000000..80e8527d7eee6ece73428644646c39c8074bad14
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/CodeSizeEvaluator.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/GeneratorAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/GeneratorAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6083ed23c3ce272a644466ae650148709357ce4
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/GeneratorAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/InstructionAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/InstructionAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..1d00639b3518240494f1eb7033f975f778a38bee
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/InstructionAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/JSRInlinerAdapter$Instantiation.class b/src/main/resources/org/python/objectweb/asm/commons/JSRInlinerAdapter$Instantiation.class
new file mode 100644
index 0000000000000000000000000000000000000000..363122969c11f70c12f6160d3aeeff7962df5d08
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/JSRInlinerAdapter$Instantiation.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/JSRInlinerAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/JSRInlinerAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..91cb454345592265d5ab650c2ba534d396cbd557
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/JSRInlinerAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/LocalVariablesSorter.class b/src/main/resources/org/python/objectweb/asm/commons/LocalVariablesSorter.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec9bfe8a970c0460dc12938598fef74a5c574a75
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/LocalVariablesSorter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/Method.class b/src/main/resources/org/python/objectweb/asm/commons/Method.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0e5757c24ac709f7fc681884d83a5a086604624
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/Method.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/Remapper.class b/src/main/resources/org/python/objectweb/asm/commons/Remapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd0d20288077f8b9e7e91e935a50be773aac86c2
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/Remapper.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/RemappingAnnotationAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/RemappingAnnotationAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..1160642005a85ae781b5900c1ba7c668d8490497
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/RemappingAnnotationAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/RemappingClassAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/RemappingClassAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..920a1e72f1583d70ad8a1667a6288edcf29c325b
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/RemappingClassAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/RemappingFieldAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/RemappingFieldAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..46fa559551919ec7d2935d44a16cd22ab5ac20d6
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/RemappingFieldAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/RemappingMethodAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/RemappingMethodAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..3bf52997e81a7a1c1f23a3ea7f6ebefcac64688b
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/RemappingMethodAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/RemappingSignatureAdapter.class b/src/main/resources/org/python/objectweb/asm/commons/RemappingSignatureAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1decaa10a8487c82af9bef15d3dbe30ee79b5a1
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/RemappingSignatureAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/SerialVersionUIDAdder$Item.class b/src/main/resources/org/python/objectweb/asm/commons/SerialVersionUIDAdder$Item.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6a4fb558fff5861837c8377c4640357f3073b58
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/SerialVersionUIDAdder$Item.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/SerialVersionUIDAdder.class b/src/main/resources/org/python/objectweb/asm/commons/SerialVersionUIDAdder.class
new file mode 100644
index 0000000000000000000000000000000000000000..a0bee9bf07d499745058d524a1b7f8030ccd192e
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/SerialVersionUIDAdder.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/SimpleRemapper.class b/src/main/resources/org/python/objectweb/asm/commons/SimpleRemapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..3528a6452f3c4eeca1d02b0968d0f901f3cf3fd9
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/SimpleRemapper.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/StaticInitMerger.class b/src/main/resources/org/python/objectweb/asm/commons/StaticInitMerger.class
new file mode 100644
index 0000000000000000000000000000000000000000..79940b633c64023bb7d6844879389c815c8e9aca
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/StaticInitMerger.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/TableSwitchGenerator.class b/src/main/resources/org/python/objectweb/asm/commons/TableSwitchGenerator.class
new file mode 100644
index 0000000000000000000000000000000000000000..309750368bc588330e56c2389632a1134a544b5b
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/TableSwitchGenerator.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/TryCatchBlockSorter$1.class b/src/main/resources/org/python/objectweb/asm/commons/TryCatchBlockSorter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..67b8950d0590d76de963d94782b691b5e91a3239
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/TryCatchBlockSorter$1.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/commons/TryCatchBlockSorter.class b/src/main/resources/org/python/objectweb/asm/commons/TryCatchBlockSorter.class
new file mode 100644
index 0000000000000000000000000000000000000000..37a73aaf5e60f4ac1763497b7064000159a90d65
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/commons/TryCatchBlockSorter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/signature/SignatureReader.class b/src/main/resources/org/python/objectweb/asm/signature/SignatureReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c3328eb0cea043eeb2ee53b85c6eb7263667eb6
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/signature/SignatureReader.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/signature/SignatureVisitor.class b/src/main/resources/org/python/objectweb/asm/signature/SignatureVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..e23eb1f3089ea95eb0f223c972695fbc2a50a5af
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/signature/SignatureVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/signature/SignatureWriter.class b/src/main/resources/org/python/objectweb/asm/signature/SignatureWriter.class
new file mode 100644
index 0000000000000000000000000000000000000000..165924a6063f74f58cf53f2c8d021dce61e99e3e
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/signature/SignatureWriter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/ASMifiable.class b/src/main/resources/org/python/objectweb/asm/util/ASMifiable.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0e83ac53c659c4896047c0b1e5921907633b240
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/ASMifiable.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/ASMifier.class b/src/main/resources/org/python/objectweb/asm/util/ASMifier.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5c3c6a6a855419fc15bd127ec93ddeb6b5327b1
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/ASMifier.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/CheckAnnotationAdapter.class b/src/main/resources/org/python/objectweb/asm/util/CheckAnnotationAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6b0b56e03d3665a2fd3dd0482c616f9528057db
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/CheckAnnotationAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/CheckClassAdapter.class b/src/main/resources/org/python/objectweb/asm/util/CheckClassAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..9129d3b4cbee759a8c15dd4db3295812288f2399
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/CheckClassAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/CheckFieldAdapter.class b/src/main/resources/org/python/objectweb/asm/util/CheckFieldAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e3f75047827e13edb2b4b20ecf6a0a36dbd4408
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/CheckFieldAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/CheckMethodAdapter$1.class b/src/main/resources/org/python/objectweb/asm/util/CheckMethodAdapter$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..42d453ff27b992791a6866e3b38253546957887c
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/CheckMethodAdapter$1.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/CheckMethodAdapter.class b/src/main/resources/org/python/objectweb/asm/util/CheckMethodAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..5826cc4ad587e1951292ab90881d115dce5fe983
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/CheckMethodAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/CheckSignatureAdapter.class b/src/main/resources/org/python/objectweb/asm/util/CheckSignatureAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..77f2e73986d8db53026bde401cb57bdc9ae5dc86
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/CheckSignatureAdapter.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/Printer.class b/src/main/resources/org/python/objectweb/asm/util/Printer.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c90211adfd61566f31b6faf2cd41f1e371270f4
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/Printer.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/Textifiable.class b/src/main/resources/org/python/objectweb/asm/util/Textifiable.class
new file mode 100644
index 0000000000000000000000000000000000000000..279468708d2e4121205bcf1957b49d350ff04125
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/Textifiable.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/Textifier.class b/src/main/resources/org/python/objectweb/asm/util/Textifier.class
new file mode 100644
index 0000000000000000000000000000000000000000..01b7ee534a8e727e5ea0b63efcd992ab878d040e
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/Textifier.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/TraceAnnotationVisitor.class b/src/main/resources/org/python/objectweb/asm/util/TraceAnnotationVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..edd1e107afca903756c2358763facebb84e7caa6
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/TraceAnnotationVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/TraceClassVisitor.class b/src/main/resources/org/python/objectweb/asm/util/TraceClassVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9564350766e87925bc6a11fead028f8dab6c6fd0
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/TraceClassVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/TraceFieldVisitor.class b/src/main/resources/org/python/objectweb/asm/util/TraceFieldVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a8cbb6616ba90b1d560a86fa20576bed37b4d36
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/TraceFieldVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/TraceMethodVisitor.class b/src/main/resources/org/python/objectweb/asm/util/TraceMethodVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..a05cbc0b0b58e0ce5f4281646d648c390604f2f4
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/TraceMethodVisitor.class differ
diff --git a/src/main/resources/org/python/objectweb/asm/util/TraceSignatureVisitor.class b/src/main/resources/org/python/objectweb/asm/util/TraceSignatureVisitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb801c25e99740cc4bdb7b3f20a172695e851476
Binary files /dev/null and b/src/main/resources/org/python/objectweb/asm/util/TraceSignatureVisitor.class differ
diff --git a/src/main/resources/org/python/tests/BadStaticInitializer.class b/src/main/resources/org/python/tests/BadStaticInitializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..cad1fb20328f06ca400c20f34a02cfd990cdae51
Binary files /dev/null and b/src/main/resources/org/python/tests/BadStaticInitializer.class differ
diff --git a/src/main/resources/org/python/tests/Bar.class b/src/main/resources/org/python/tests/Bar.class
new file mode 100644
index 0000000000000000000000000000000000000000..72e1ae999f1807cd48cf7f1586da4cb97db229cd
Binary files /dev/null and b/src/main/resources/org/python/tests/Bar.class differ
diff --git a/src/main/resources/org/python/tests/BeanImplementation.class b/src/main/resources/org/python/tests/BeanImplementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..a684b807ce6b3ad547061ebe2bdda88cd70beec2
Binary files /dev/null and b/src/main/resources/org/python/tests/BeanImplementation.class differ
diff --git a/src/main/resources/org/python/tests/BeanInterface.class b/src/main/resources/org/python/tests/BeanInterface.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9449edf15586737b516cb2d3ce1d7ea94d81116
Binary files /dev/null and b/src/main/resources/org/python/tests/BeanInterface.class differ
diff --git a/src/main/resources/org/python/tests/Callbacker$Callback.class b/src/main/resources/org/python/tests/Callbacker$Callback.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4b885c1cdbd7ad06090359603341add9431a8e2
Binary files /dev/null and b/src/main/resources/org/python/tests/Callbacker$Callback.class differ
diff --git a/src/main/resources/org/python/tests/Callbacker$CollectingCallback.class b/src/main/resources/org/python/tests/Callbacker$CollectingCallback.class
new file mode 100644
index 0000000000000000000000000000000000000000..123a10e20aa727a85fbcb4d1f247f79ffb29a6ec
Binary files /dev/null and b/src/main/resources/org/python/tests/Callbacker$CollectingCallback.class differ
diff --git a/src/main/resources/org/python/tests/Callbacker.class b/src/main/resources/org/python/tests/Callbacker.class
new file mode 100644
index 0000000000000000000000000000000000000000..37382b18e50915547a333070e0cfd4b856359ecf
Binary files /dev/null and b/src/main/resources/org/python/tests/Callbacker.class differ
diff --git a/src/main/resources/org/python/tests/Child.class b/src/main/resources/org/python/tests/Child.class
new file mode 100644
index 0000000000000000000000000000000000000000..78521c5336ae1aecf6933e243feb8f9c6278d43b
Binary files /dev/null and b/src/main/resources/org/python/tests/Child.class differ
diff --git a/src/main/resources/org/python/tests/Child2.class b/src/main/resources/org/python/tests/Child2.class
new file mode 100644
index 0000000000000000000000000000000000000000..54954f94c2b65ba84d8478b58acf85813e53a4ac
Binary files /dev/null and b/src/main/resources/org/python/tests/Child2.class differ
diff --git a/src/main/resources/org/python/tests/Coercions.class b/src/main/resources/org/python/tests/Coercions.class
new file mode 100644
index 0000000000000000000000000000000000000000..f428002d5b066e7a64811408fa180fda7998fa7c
Binary files /dev/null and b/src/main/resources/org/python/tests/Coercions.class differ
diff --git a/src/main/resources/org/python/tests/CustomizableMapHolder$1.class b/src/main/resources/org/python/tests/CustomizableMapHolder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7fe89e0179c53c7a31f448c62ef5543bf1b78e8
Binary files /dev/null and b/src/main/resources/org/python/tests/CustomizableMapHolder$1.class differ
diff --git a/src/main/resources/org/python/tests/CustomizableMapHolder$2.class b/src/main/resources/org/python/tests/CustomizableMapHolder$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..6137cdd35bade1e8204130d51912c8135d86f5f5
Binary files /dev/null and b/src/main/resources/org/python/tests/CustomizableMapHolder$2.class differ
diff --git a/src/main/resources/org/python/tests/CustomizableMapHolder$3.class b/src/main/resources/org/python/tests/CustomizableMapHolder$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..64a28541b6c8c833cba9403c4fc172bd05c72387
Binary files /dev/null and b/src/main/resources/org/python/tests/CustomizableMapHolder$3.class differ
diff --git a/src/main/resources/org/python/tests/CustomizableMapHolder.class b/src/main/resources/org/python/tests/CustomizableMapHolder.class
new file mode 100644
index 0000000000000000000000000000000000000000..f12bf4e9ac699c58c7330d2a9398985ab29956ea
Binary files /dev/null and b/src/main/resources/org/python/tests/CustomizableMapHolder.class differ
diff --git a/src/main/resources/org/python/tests/ExceptionTest$Checked.class b/src/main/resources/org/python/tests/ExceptionTest$Checked.class
new file mode 100644
index 0000000000000000000000000000000000000000..c07374b1e9417028c6a404d012fce325593a626b
Binary files /dev/null and b/src/main/resources/org/python/tests/ExceptionTest$Checked.class differ
diff --git a/src/main/resources/org/python/tests/ExceptionTest$Thrower.class b/src/main/resources/org/python/tests/ExceptionTest$Thrower.class
new file mode 100644
index 0000000000000000000000000000000000000000..3187c102e2977cd3ea0b9c797649654ea1f5b676
Binary files /dev/null and b/src/main/resources/org/python/tests/ExceptionTest$Thrower.class differ
diff --git a/src/main/resources/org/python/tests/ExceptionTest.class b/src/main/resources/org/python/tests/ExceptionTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ce21283f4a05cfaa569f527a41e47f0a5f6d38b
Binary files /dev/null and b/src/main/resources/org/python/tests/ExceptionTest.class differ
diff --git a/src/main/resources/org/python/tests/HiddenSuper.class b/src/main/resources/org/python/tests/HiddenSuper.class
new file mode 100644
index 0000000000000000000000000000000000000000..92f9113c273e8234d4c9207a8912166d37bafb52
Binary files /dev/null and b/src/main/resources/org/python/tests/HiddenSuper.class differ
diff --git a/src/main/resources/org/python/tests/InterfaceCombination$1.class b/src/main/resources/org/python/tests/InterfaceCombination$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd784f30d00e10f628bb40f29411792e41775496
Binary files /dev/null and b/src/main/resources/org/python/tests/InterfaceCombination$1.class differ
diff --git a/src/main/resources/org/python/tests/InterfaceCombination$Base.class b/src/main/resources/org/python/tests/InterfaceCombination$Base.class
new file mode 100644
index 0000000000000000000000000000000000000000..226e35c976ba63cc91a1a8eda734b7d5c8cbfea4
Binary files /dev/null and b/src/main/resources/org/python/tests/InterfaceCombination$Base.class differ
diff --git a/src/main/resources/org/python/tests/InterfaceCombination$Hidden.class b/src/main/resources/org/python/tests/InterfaceCombination$Hidden.class
new file mode 100644
index 0000000000000000000000000000000000000000..a45ec6ea843a64f5751c109656c6b7466c7c2066
Binary files /dev/null and b/src/main/resources/org/python/tests/InterfaceCombination$Hidden.class differ
diff --git a/src/main/resources/org/python/tests/InterfaceCombination$IFace.class b/src/main/resources/org/python/tests/InterfaceCombination$IFace.class
new file mode 100644
index 0000000000000000000000000000000000000000..046850113ba35bf75900725909047248d8357c8b
Binary files /dev/null and b/src/main/resources/org/python/tests/InterfaceCombination$IFace.class differ
diff --git a/src/main/resources/org/python/tests/InterfaceCombination$IIFace.class b/src/main/resources/org/python/tests/InterfaceCombination$IIFace.class
new file mode 100644
index 0000000000000000000000000000000000000000..69e36165da1edd1b80f88c294159c0681275506b
Binary files /dev/null and b/src/main/resources/org/python/tests/InterfaceCombination$IIFace.class differ
diff --git a/src/main/resources/org/python/tests/InterfaceCombination$Implementation.class b/src/main/resources/org/python/tests/InterfaceCombination$Implementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc38e9f8fa0f554b919ecf9215550472c3a5bcbe
Binary files /dev/null and b/src/main/resources/org/python/tests/InterfaceCombination$Implementation.class differ
diff --git a/src/main/resources/org/python/tests/InterfaceCombination.class b/src/main/resources/org/python/tests/InterfaceCombination.class
new file mode 100644
index 0000000000000000000000000000000000000000..a983ea76ae2fe94aef24a8a113ad2b60903626d1
Binary files /dev/null and b/src/main/resources/org/python/tests/InterfaceCombination.class differ
diff --git a/src/main/resources/org/python/tests/Invisible.class b/src/main/resources/org/python/tests/Invisible.class
new file mode 100644
index 0000000000000000000000000000000000000000..6546096cc9e9711d458bd025171c93de53b55738
Binary files /dev/null and b/src/main/resources/org/python/tests/Invisible.class differ
diff --git a/src/main/resources/org/python/tests/Listenable.class b/src/main/resources/org/python/tests/Listenable.class
new file mode 100644
index 0000000000000000000000000000000000000000..36513c3861cbb69d54f25a3c5238bf9c7b518d49
Binary files /dev/null and b/src/main/resources/org/python/tests/Listenable.class differ
diff --git a/src/main/resources/org/python/tests/Matryoshka$Outermost$Middle$Innermost.class b/src/main/resources/org/python/tests/Matryoshka$Outermost$Middle$Innermost.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8b6e04ad4028fc45bdd2a2b1d201441181c845c
Binary files /dev/null and b/src/main/resources/org/python/tests/Matryoshka$Outermost$Middle$Innermost.class differ
diff --git a/src/main/resources/org/python/tests/Matryoshka$Outermost$Middle.class b/src/main/resources/org/python/tests/Matryoshka$Outermost$Middle.class
new file mode 100644
index 0000000000000000000000000000000000000000..b23b7845fb2354a01a94531a67007153564fa0a9
Binary files /dev/null and b/src/main/resources/org/python/tests/Matryoshka$Outermost$Middle.class differ
diff --git a/src/main/resources/org/python/tests/Matryoshka$Outermost.class b/src/main/resources/org/python/tests/Matryoshka$Outermost.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9215a45526e85d3987f601113174c21626fab58
Binary files /dev/null and b/src/main/resources/org/python/tests/Matryoshka$Outermost.class differ
diff --git a/src/main/resources/org/python/tests/Matryoshka.class b/src/main/resources/org/python/tests/Matryoshka.class
new file mode 100644
index 0000000000000000000000000000000000000000..d01218dba2763938f2bc301ede013cfda5d9f410
Binary files /dev/null and b/src/main/resources/org/python/tests/Matryoshka.class differ
diff --git a/src/main/resources/org/python/tests/OnlySubclassable.class b/src/main/resources/org/python/tests/OnlySubclassable.class
new file mode 100644
index 0000000000000000000000000000000000000000..a54241085d48c1fe43a132a9301fed6befd7d393
Binary files /dev/null and b/src/main/resources/org/python/tests/OnlySubclassable.class differ
diff --git a/src/main/resources/org/python/tests/OtherSubVisible.class b/src/main/resources/org/python/tests/OtherSubVisible.class
new file mode 100644
index 0000000000000000000000000000000000000000..42663114e872a2c78c7adfc74c95547c24fd47b8
Binary files /dev/null and b/src/main/resources/org/python/tests/OtherSubVisible.class differ
diff --git a/src/main/resources/org/python/tests/OwnMethodCaller.class b/src/main/resources/org/python/tests/OwnMethodCaller.class
new file mode 100644
index 0000000000000000000000000000000000000000..4e48b5be2bf0d1b219e1d39a7776db3c29b323b4
Binary files /dev/null and b/src/main/resources/org/python/tests/OwnMethodCaller.class differ
diff --git a/src/main/resources/org/python/tests/Parent.class b/src/main/resources/org/python/tests/Parent.class
new file mode 100644
index 0000000000000000000000000000000000000000..8b1b641bae3a86f47c921c5f273486073c7b53cc
Binary files /dev/null and b/src/main/resources/org/python/tests/Parent.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$AbstractImplementation.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$AbstractImplementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..26ac830c087902dd93a78606f23b8d9dc623be34
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$AbstractImplementation.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ClassArg.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ClassArg.class
new file mode 100644
index 0000000000000000000000000000000000000000..e345c67ea6c621774a2d688f8b57ffdc99370bbd
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ClassArg.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraClass.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraClass.class
new file mode 100644
index 0000000000000000000000000000000000000000..5e448ee5b84bb3d084baecd833b2859902510b34
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraClass.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraClassAndString.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraClassAndString.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2ecaf261e75f4dc227d5285a1e60ed81e40b18b
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraClassAndString.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraString.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraString.class
new file mode 100644
index 0000000000000000000000000000000000000000..da5bfa77cc108d8d69dd97181bc2dd4ceb33be6b
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraString.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraStringAndClass.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraStringAndClass.class
new file mode 100644
index 0000000000000000000000000000000000000000..c01993095421cf78465984277e1c11375f40fe8b
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$ExtraStringAndClass.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$Implementation.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$Implementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..da511f1b5e9b5df82406b3739052059416c2d330
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$Implementation.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$IntArg.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$IntArg.class
new file mode 100644
index 0000000000000000000000000000000000000000..43f4bb9d00f893208d7d0563221a7c0d97682c1d
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$IntArg.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$StringArg.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$StringArg.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7a7952849b0b7e209473ca3d06439ada0c8c40c
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations$StringArg.class differ
diff --git a/src/main/resources/org/python/tests/RedundantInterfaceDeclarations.class b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations.class
new file mode 100644
index 0000000000000000000000000000000000000000..369bd2dd6fc3149cafdb311847545716d54181a6
Binary files /dev/null and b/src/main/resources/org/python/tests/RedundantInterfaceDeclarations.class differ
diff --git a/src/main/resources/org/python/tests/RespectJavaAccessibility$Banana.class b/src/main/resources/org/python/tests/RespectJavaAccessibility$Banana.class
new file mode 100644
index 0000000000000000000000000000000000000000..2cf0cdff156692032860a8409972ed5f83be7cff
Binary files /dev/null and b/src/main/resources/org/python/tests/RespectJavaAccessibility$Banana.class differ
diff --git a/src/main/resources/org/python/tests/RespectJavaAccessibility$Pear.class b/src/main/resources/org/python/tests/RespectJavaAccessibility$Pear.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bf1c8ff549d38850482a38eba7038657ed1a71c
Binary files /dev/null and b/src/main/resources/org/python/tests/RespectJavaAccessibility$Pear.class differ
diff --git a/src/main/resources/org/python/tests/RespectJavaAccessibility.class b/src/main/resources/org/python/tests/RespectJavaAccessibility.class
new file mode 100644
index 0000000000000000000000000000000000000000..c880634b78be8e359d05701730bb01073d57d0fc
Binary files /dev/null and b/src/main/resources/org/python/tests/RespectJavaAccessibility.class differ
diff --git a/src/main/resources/org/python/tests/SerializationTest.class b/src/main/resources/org/python/tests/SerializationTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..0b70cdd2f695c48cb12a97676685e7f428031f94
Binary files /dev/null and b/src/main/resources/org/python/tests/SerializationTest.class differ
diff --git a/src/main/resources/org/python/tests/SomePyMethods.class b/src/main/resources/org/python/tests/SomePyMethods.class
new file mode 100644
index 0000000000000000000000000000000000000000..c77ba9cca15ff4aa28e19ef0aa514292a38f741a
Binary files /dev/null and b/src/main/resources/org/python/tests/SomePyMethods.class differ
diff --git a/src/main/resources/org/python/tests/SubVisible.class b/src/main/resources/org/python/tests/SubVisible.class
new file mode 100644
index 0000000000000000000000000000000000000000..3013df76561b34e6303467138995aa257f806ea4
Binary files /dev/null and b/src/main/resources/org/python/tests/SubVisible.class differ
diff --git a/src/main/resources/org/python/tests/ToUnicode.class b/src/main/resources/org/python/tests/ToUnicode.class
new file mode 100644
index 0000000000000000000000000000000000000000..528815d4ff592e584042fbaee251d3e61fe0814a
Binary files /dev/null and b/src/main/resources/org/python/tests/ToUnicode.class differ
diff --git a/src/main/resources/org/python/tests/VisibilityResults.class b/src/main/resources/org/python/tests/VisibilityResults.class
new file mode 100644
index 0000000000000000000000000000000000000000..c19313890f7d9d23f3c1f23670233b0e12db4a53
Binary files /dev/null and b/src/main/resources/org/python/tests/VisibilityResults.class differ
diff --git a/src/main/resources/org/python/tests/Visible$StaticInner.class b/src/main/resources/org/python/tests/Visible$StaticInner.class
new file mode 100644
index 0000000000000000000000000000000000000000..f9366e1b1ad6cfaf243057adaadcd56723ac9fc5
Binary files /dev/null and b/src/main/resources/org/python/tests/Visible$StaticInner.class differ
diff --git a/src/main/resources/org/python/tests/Visible.class b/src/main/resources/org/python/tests/Visible.class
new file mode 100644
index 0000000000000000000000000000000000000000..7db936477889680bd27ad21f831408823a561633
Binary files /dev/null and b/src/main/resources/org/python/tests/Visible.class differ
diff --git a/src/main/resources/org/python/tests/VisibleOverride.class b/src/main/resources/org/python/tests/VisibleOverride.class
new file mode 100644
index 0000000000000000000000000000000000000000..d7a76be1f6981402d805ee077916215a1f467ef7
Binary files /dev/null and b/src/main/resources/org/python/tests/VisibleOverride.class differ
diff --git a/src/main/resources/org/python/tests/constructor_kwargs/ConstructorKWArgsTest.class b/src/main/resources/org/python/tests/constructor_kwargs/ConstructorKWArgsTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..12d557dd3d7c3dc14dd71524efe4fa03d8c16394
Binary files /dev/null and b/src/main/resources/org/python/tests/constructor_kwargs/ConstructorKWArgsTest.class differ
diff --git a/src/main/resources/org/python/tests/constructor_kwargs/KWArgsObject.class b/src/main/resources/org/python/tests/constructor_kwargs/KWArgsObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..ef44f56a36ddef570672c27a3a817a00ab8acf0e
Binary files /dev/null and b/src/main/resources/org/python/tests/constructor_kwargs/KWArgsObject.class differ
diff --git a/src/main/resources/org/python/tests/identity/IdentityObject.class b/src/main/resources/org/python/tests/identity/IdentityObject.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c6b66fc3306d5d412b0607fa264f3663784a22e
Binary files /dev/null and b/src/main/resources/org/python/tests/identity/IdentityObject.class differ
diff --git a/src/main/resources/org/python/tests/identity/IdentityTest.class b/src/main/resources/org/python/tests/identity/IdentityTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..8649d00f6280685d28eb62e26b392642d4137ed9
Binary files /dev/null and b/src/main/resources/org/python/tests/identity/IdentityTest.class differ
diff --git a/src/main/resources/org/python/tests/imp/ImportTests.class b/src/main/resources/org/python/tests/imp/ImportTests.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3ce0a34269d883640139ae9e2915b04f4c85863
Binary files /dev/null and b/src/main/resources/org/python/tests/imp/ImportTests.class differ
diff --git a/src/main/resources/org/python/tests/inbred/Metis.class b/src/main/resources/org/python/tests/inbred/Metis.class
new file mode 100644
index 0000000000000000000000000000000000000000..a6a2df48d803845ad490769cb86ced9781c15cb9
Binary files /dev/null and b/src/main/resources/org/python/tests/inbred/Metis.class differ
diff --git a/src/main/resources/org/python/tests/inbred/Zeus$Athena.class b/src/main/resources/org/python/tests/inbred/Zeus$Athena.class
new file mode 100644
index 0000000000000000000000000000000000000000..cde7c57d78a6d2af9a6a17df1c6bf4104ae00583
Binary files /dev/null and b/src/main/resources/org/python/tests/inbred/Zeus$Athena.class differ
diff --git a/src/main/resources/org/python/tests/inbred/Zeus.class b/src/main/resources/org/python/tests/inbred/Zeus.class
new file mode 100644
index 0000000000000000000000000000000000000000..708994e0b22938fd5d6eaf41933c916edde5bb4a
Binary files /dev/null and b/src/main/resources/org/python/tests/inbred/Zeus.class differ
diff --git a/src/main/resources/org/python/tests/mro/ConfusedOnGetitemAdd.class b/src/main/resources/org/python/tests/mro/ConfusedOnGetitemAdd.class
new file mode 100644
index 0000000000000000000000000000000000000000..121dcffbb41e8b8ca933fe7c92052c8b74240565
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/ConfusedOnGetitemAdd.class differ
diff --git a/src/main/resources/org/python/tests/mro/ConfusedOnImport.class b/src/main/resources/org/python/tests/mro/ConfusedOnImport.class
new file mode 100644
index 0000000000000000000000000000000000000000..aaa3c1e20e4ab54f153a02b5ec35c999192dd538
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/ConfusedOnImport.class differ
diff --git a/src/main/resources/org/python/tests/mro/FirstAndPost.class b/src/main/resources/org/python/tests/mro/FirstAndPost.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf17e40e05ef5f40902c1e87d5bc940d096b33e0
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/FirstAndPost.class differ
diff --git a/src/main/resources/org/python/tests/mro/FirstAndSecond.class b/src/main/resources/org/python/tests/mro/FirstAndSecond.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a8d75d5bd98a6e9861eedff88b2ceac4ee8abe5
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/FirstAndSecond.class differ
diff --git a/src/main/resources/org/python/tests/mro/FirstPredefinedGetitem.class b/src/main/resources/org/python/tests/mro/FirstPredefinedGetitem.class
new file mode 100644
index 0000000000000000000000000000000000000000..20c081047d0c7398986c4ad295e54c5fbc1ad166
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/FirstPredefinedGetitem.class differ
diff --git a/src/main/resources/org/python/tests/mro/GetitemAdder$1.class b/src/main/resources/org/python/tests/mro/GetitemAdder$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..c715c85a20249d35bff10c186fd16c44f5bd268b
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/GetitemAdder$1.class differ
diff --git a/src/main/resources/org/python/tests/mro/GetitemAdder$2.class b/src/main/resources/org/python/tests/mro/GetitemAdder$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f652a98b708144875ca8b28af2e54e033ba33cb
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/GetitemAdder$2.class differ
diff --git a/src/main/resources/org/python/tests/mro/GetitemAdder.class b/src/main/resources/org/python/tests/mro/GetitemAdder.class
new file mode 100644
index 0000000000000000000000000000000000000000..d670869c5735c11bd43ff918313560afcb2c1f16
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/GetitemAdder.class differ
diff --git a/src/main/resources/org/python/tests/mro/PostAndFirst.class b/src/main/resources/org/python/tests/mro/PostAndFirst.class
new file mode 100644
index 0000000000000000000000000000000000000000..4fcbd04fed553f372e926e9cb1d59ecbf8884210
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/PostAndFirst.class differ
diff --git a/src/main/resources/org/python/tests/mro/PostdefinedGetitem.class b/src/main/resources/org/python/tests/mro/PostdefinedGetitem.class
new file mode 100644
index 0000000000000000000000000000000000000000..8cbd034687279a98db45a69d735d880cea7a52d2
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/PostdefinedGetitem.class differ
diff --git a/src/main/resources/org/python/tests/mro/SecondAndFirst.class b/src/main/resources/org/python/tests/mro/SecondAndFirst.class
new file mode 100644
index 0000000000000000000000000000000000000000..cac7db738aa4dbc26843f68a02938f08ca58102d
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/SecondAndFirst.class differ
diff --git a/src/main/resources/org/python/tests/mro/SecondPredefinedGetitem.class b/src/main/resources/org/python/tests/mro/SecondPredefinedGetitem.class
new file mode 100644
index 0000000000000000000000000000000000000000..8ed9f94c86139131463e9bd19ea9cfab9d0493b7
Binary files /dev/null and b/src/main/resources/org/python/tests/mro/SecondPredefinedGetitem.class differ
diff --git a/src/main/resources/org/python/tests/multihidden/BaseConnection.class b/src/main/resources/org/python/tests/multihidden/BaseConnection.class
new file mode 100644
index 0000000000000000000000000000000000000000..52e4186eb36e05cf269c22fe75a0173fb216c059
Binary files /dev/null and b/src/main/resources/org/python/tests/multihidden/BaseConnection.class differ
diff --git a/src/main/resources/org/python/tests/multihidden/Connection.class b/src/main/resources/org/python/tests/multihidden/Connection.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a3be862b7e9820c8fd66663512157bf55447f9e
Binary files /dev/null and b/src/main/resources/org/python/tests/multihidden/Connection.class differ
diff --git a/src/main/resources/org/python/tests/multihidden/ConnectionWrapper.class b/src/main/resources/org/python/tests/multihidden/ConnectionWrapper.class
new file mode 100644
index 0000000000000000000000000000000000000000..1452f998f26e5425c6bf236764d803a0566cd9d2
Binary files /dev/null and b/src/main/resources/org/python/tests/multihidden/ConnectionWrapper.class differ
diff --git a/src/main/resources/org/python/tests/multihidden/SpecialConnection.class b/src/main/resources/org/python/tests/multihidden/SpecialConnection.class
new file mode 100644
index 0000000000000000000000000000000000000000..d17bc146f150aca1faa2b8b08d439f0132830c87
Binary files /dev/null and b/src/main/resources/org/python/tests/multihidden/SpecialConnection.class differ
diff --git a/src/main/resources/org/python/tests/props/BeanPropertyTest.class b/src/main/resources/org/python/tests/props/BeanPropertyTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..b4ba11bb5b8ca09ece7f8e82e18ddf96bb39058b
Binary files /dev/null and b/src/main/resources/org/python/tests/props/BeanPropertyTest.class differ
diff --git a/src/main/resources/org/python/tests/props/PropShadow$Base.class b/src/main/resources/org/python/tests/props/PropShadow$Base.class
new file mode 100644
index 0000000000000000000000000000000000000000..04ac1b5fc7ebe16223f34c086e495099c0b894cb
Binary files /dev/null and b/src/main/resources/org/python/tests/props/PropShadow$Base.class differ
diff --git a/src/main/resources/org/python/tests/props/PropShadow$Derived.class b/src/main/resources/org/python/tests/props/PropShadow$Derived.class
new file mode 100644
index 0000000000000000000000000000000000000000..bd72949d526bb3aa8ea0fe6765722162a8d9a11a
Binary files /dev/null and b/src/main/resources/org/python/tests/props/PropShadow$Derived.class differ
diff --git a/src/main/resources/org/python/tests/props/PropShadow.class b/src/main/resources/org/python/tests/props/PropShadow.class
new file mode 100644
index 0000000000000000000000000000000000000000..be18175f144d270057a97b3735dfc644ee2e42aa
Binary files /dev/null and b/src/main/resources/org/python/tests/props/PropShadow.class differ
diff --git a/src/main/resources/org/python/tests/props/Readonly.class b/src/main/resources/org/python/tests/props/Readonly.class
new file mode 100644
index 0000000000000000000000000000000000000000..a09817f335c83e3548c998d59a20023c241f77af
Binary files /dev/null and b/src/main/resources/org/python/tests/props/Readonly.class differ
diff --git a/src/main/resources/org/python/util/BreakTraceFunction.class b/src/main/resources/org/python/util/BreakTraceFunction.class
new file mode 100644
index 0000000000000000000000000000000000000000..e368fd8a5325ca3fd523bfceddab7f3a31052059
Binary files /dev/null and b/src/main/resources/org/python/util/BreakTraceFunction.class differ
diff --git a/src/main/resources/org/python/util/CodegenUtils.class b/src/main/resources/org/python/util/CodegenUtils.class
new file mode 100644
index 0000000000000000000000000000000000000000..f1fe4e57c272db3fd9577f9cf9a8677e351fbd0e
Binary files /dev/null and b/src/main/resources/org/python/util/CodegenUtils.class differ
diff --git a/src/main/resources/org/python/util/CommandLineOptions.class b/src/main/resources/org/python/util/CommandLineOptions.class
new file mode 100644
index 0000000000000000000000000000000000000000..bce7672d38e26ae3415531f54b84488c5079736a
Binary files /dev/null and b/src/main/resources/org/python/util/CommandLineOptions.class differ
diff --git a/src/main/resources/org/python/util/ConsoleInputStream$1.class b/src/main/resources/org/python/util/ConsoleInputStream$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..5db43ab90f1328b9ebeda79fc2c8a89141da2385
Binary files /dev/null and b/src/main/resources/org/python/util/ConsoleInputStream$1.class differ
diff --git a/src/main/resources/org/python/util/ConsoleInputStream$EOLPolicy.class b/src/main/resources/org/python/util/ConsoleInputStream$EOLPolicy.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f96a9fd396caf5dabab2d96a625f7e3c1547e63
Binary files /dev/null and b/src/main/resources/org/python/util/ConsoleInputStream$EOLPolicy.class differ
diff --git a/src/main/resources/org/python/util/ConsoleInputStream.class b/src/main/resources/org/python/util/ConsoleInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a95bdaa625d0475ef8d330113a6da9209af141d
Binary files /dev/null and b/src/main/resources/org/python/util/ConsoleInputStream.class differ
diff --git a/src/main/resources/org/python/util/ConsoleOutputStream.class b/src/main/resources/org/python/util/ConsoleOutputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2e0c49a69c74155fd2029eec59f69866b93216c
Binary files /dev/null and b/src/main/resources/org/python/util/ConsoleOutputStream.class differ
diff --git a/src/main/resources/org/python/util/Generic.class b/src/main/resources/org/python/util/Generic.class
new file mode 100644
index 0000000000000000000000000000000000000000..4179affba5faa8721cef0b5c55dcfeb2b981506c
Binary files /dev/null and b/src/main/resources/org/python/util/Generic.class differ
diff --git a/src/main/resources/org/python/util/GlobMatchingTask.class b/src/main/resources/org/python/util/GlobMatchingTask.class
new file mode 100644
index 0000000000000000000000000000000000000000..72da47d9156c5f48936f1f679654e1fd6f9d248d
Binary files /dev/null and b/src/main/resources/org/python/util/GlobMatchingTask.class differ
diff --git a/src/main/resources/org/python/util/InteractiveConsole$1.class b/src/main/resources/org/python/util/InteractiveConsole$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..4863a41d298f563fd75f8066491c166d4296b6ca
Binary files /dev/null and b/src/main/resources/org/python/util/InteractiveConsole$1.class differ
diff --git a/src/main/resources/org/python/util/InteractiveConsole.class b/src/main/resources/org/python/util/InteractiveConsole.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bf24ce48f9be01110f947c9739492a42e6e9846
Binary files /dev/null and b/src/main/resources/org/python/util/InteractiveConsole.class differ
diff --git a/src/main/resources/org/python/util/InteractiveInterpreter.class b/src/main/resources/org/python/util/InteractiveInterpreter.class
new file mode 100644
index 0000000000000000000000000000000000000000..4222c3001a3e9116a180331605fe554947bcca23
Binary files /dev/null and b/src/main/resources/org/python/util/InteractiveInterpreter.class differ
diff --git a/src/main/resources/org/python/util/InterpreterTest$1.class b/src/main/resources/org/python/util/InterpreterTest$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..cb9ff42a16a418dbbd9135019a09d3fe82113be4
Binary files /dev/null and b/src/main/resources/org/python/util/InterpreterTest$1.class differ
diff --git a/src/main/resources/org/python/util/InterpreterTest.class b/src/main/resources/org/python/util/InterpreterTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..ab002e43476283655c9c4160b71a994b5ad33799
Binary files /dev/null and b/src/main/resources/org/python/util/InterpreterTest.class differ
diff --git a/src/main/resources/org/python/util/JLineConsole$Stream.class b/src/main/resources/org/python/util/JLineConsole$Stream.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8341c68ea6e68ce94700e26fe6ea8663031b3c3
Binary files /dev/null and b/src/main/resources/org/python/util/JLineConsole$Stream.class differ
diff --git a/src/main/resources/org/python/util/JLineConsole.class b/src/main/resources/org/python/util/JLineConsole.class
new file mode 100644
index 0000000000000000000000000000000000000000..29abe7518627a5f82465c2c848fb305594c4d377
Binary files /dev/null and b/src/main/resources/org/python/util/JLineConsole.class differ
diff --git a/src/main/resources/org/python/util/JarRunner.class b/src/main/resources/org/python/util/JarRunner.class
new file mode 100644
index 0000000000000000000000000000000000000000..7743e7e0354e9e4c5e199706c79dfa60137ea371
Binary files /dev/null and b/src/main/resources/org/python/util/JarRunner.class differ
diff --git a/src/main/resources/org/python/util/JycompileAntTask.class b/src/main/resources/org/python/util/JycompileAntTask.class
new file mode 100644
index 0000000000000000000000000000000000000000..d6c57b91492741752bc2a965338e964a09fb37af
Binary files /dev/null and b/src/main/resources/org/python/util/JycompileAntTask.class differ
diff --git a/src/main/resources/org/python/util/JythoncAntTask.class b/src/main/resources/org/python/util/JythoncAntTask.class
new file mode 100644
index 0000000000000000000000000000000000000000..202103f01425584e39a1ba1e916b53895c491d71
Binary files /dev/null and b/src/main/resources/org/python/util/JythoncAntTask.class differ
diff --git a/src/main/resources/org/python/util/NameUnionAntType.class b/src/main/resources/org/python/util/NameUnionAntType.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7851d9dd554971e1faa1f84f7e3b3635846debe
Binary files /dev/null and b/src/main/resources/org/python/util/NameUnionAntType.class differ
diff --git a/src/main/resources/org/python/util/ProxyCompiler.class b/src/main/resources/org/python/util/ProxyCompiler.class
new file mode 100644
index 0000000000000000000000000000000000000000..417a1ce11d53d49db9d942fb5e0ca57ffa8291a1
Binary files /dev/null and b/src/main/resources/org/python/util/ProxyCompiler.class differ
diff --git a/src/main/resources/org/python/util/PyFilter.class b/src/main/resources/org/python/util/PyFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..d2c06d864c871223d6cdf4aef052dc71bd6f8164
Binary files /dev/null and b/src/main/resources/org/python/util/PyFilter.class differ
diff --git a/src/main/resources/org/python/util/PyServlet$CacheEntry.class b/src/main/resources/org/python/util/PyServlet$CacheEntry.class
new file mode 100644
index 0000000000000000000000000000000000000000..642ea7ba0d03e13670111c63260aef0c70089c01
Binary files /dev/null and b/src/main/resources/org/python/util/PyServlet$CacheEntry.class differ
diff --git a/src/main/resources/org/python/util/PyServlet.class b/src/main/resources/org/python/util/PyServlet.class
new file mode 100644
index 0000000000000000000000000000000000000000..386245d8ee431993ab1ae6ec8b49b5faac38ba01
Binary files /dev/null and b/src/main/resources/org/python/util/PyServlet.class differ
diff --git a/src/main/resources/org/python/util/PyServletInitializer.class b/src/main/resources/org/python/util/PyServletInitializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..ff45be684b86b4ca20ff708d0444a518f07e9613
Binary files /dev/null and b/src/main/resources/org/python/util/PyServletInitializer.class differ
diff --git a/src/main/resources/org/python/util/PythonInterpreter.class b/src/main/resources/org/python/util/PythonInterpreter.class
new file mode 100644
index 0000000000000000000000000000000000000000..caeadfbdd584f6d52f31ac58a3ff546f43d634fc
Binary files /dev/null and b/src/main/resources/org/python/util/PythonInterpreter.class differ
diff --git a/src/main/resources/org/python/util/PythonObjectInputStream.class b/src/main/resources/org/python/util/PythonObjectInputStream.class
new file mode 100644
index 0000000000000000000000000000000000000000..57cdee2c6cf75aba95114df65e8b185d37ccc701
Binary files /dev/null and b/src/main/resources/org/python/util/PythonObjectInputStream.class differ
diff --git a/src/main/resources/org/python/util/ReadlineConsole$Stream.class b/src/main/resources/org/python/util/ReadlineConsole$Stream.class
new file mode 100644
index 0000000000000000000000000000000000000000..c06e51f0bb5d05755f533a05b178ef5dbdf9cb56
Binary files /dev/null and b/src/main/resources/org/python/util/ReadlineConsole$Stream.class differ
diff --git a/src/main/resources/org/python/util/ReadlineConsole.class b/src/main/resources/org/python/util/ReadlineConsole.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6cee19a5d0788c65d993bf0a568c79ea315ff98
Binary files /dev/null and b/src/main/resources/org/python/util/ReadlineConsole.class differ
diff --git a/src/main/resources/org/python/util/TemplateAntTask.class b/src/main/resources/org/python/util/TemplateAntTask.class
new file mode 100644
index 0000000000000000000000000000000000000000..eca1bdf158103f86dcef1b86f27fb86b986d96c9
Binary files /dev/null and b/src/main/resources/org/python/util/TemplateAntTask.class differ
diff --git a/src/main/resources/org/python/util/jline-keybindings.properties b/src/main/resources/org/python/util/jline-keybindings.properties
new file mode 100644
index 0000000000000000000000000000000000000000..177450010f1afd9e2a88149dd4ec5e12481d7c9e
--- /dev/null
+++ b/src/main/resources/org/python/util/jline-keybindings.properties
@@ -0,0 +1,64 @@
+# Keybinding mapping for JLine. The format is:
+#    [key code]: [logical operation]
+
+# CTRL-B: move to the previous character
+2: PREV_CHAR
+
+# CTRL-G: move to the previous word
+7: PREV_WORD
+
+# CTRL-F: move to the next character
+6: NEXT_CHAR
+
+# CTRL-A: move to the beginning of the line
+1: MOVE_TO_BEG
+
+# CTRL-D: close out the input stream
+4: EXIT
+
+# CTRL-E: move the cursor to the end of the line
+5: MOVE_TO_END
+
+# BACKSPACE, CTRL-H: delete the previous character
+# 8 is the ASCII code for backspace and therefor
+# deleting the previous character
+8: DELETE_PREV_CHAR
+
+## TAB, CTRL-I: signal that console completion should be attempted
+#9: COMPLETE
+# Jython needs a real TAB, disable completion
+9: UNKNOWN
+
+# CTRL-J, CTRL-M: newline
+10: NEWLINE
+
+# CTRL-K: erase the current line
+11: KILL_LINE
+
+# ENTER: newline
+13: NEWLINE
+
+# CTRL-L: clear screen
+12: CLEAR_SCREEN
+
+# CTRL-N: scroll to the next element in the history buffer
+14: NEXT_HISTORY
+
+# CTRL-P: scroll to the previous element in the history buffer
+16: PREV_HISTORY
+
+# CTRL-R: redraw the current line
+18: REDISPLAY
+
+# CTRL-U: delete all the characters before the cursor position
+21: KILL_LINE_PREV
+
+# CTRL-V: paste the contents of the clipboard (useful for Windows terminal)
+22: PASTE
+
+# CTRL-W: delete the word directly before the cursor
+23: DELETE_PREV_WORD
+
+# DELETE, CTRL-?: delete the previous character
+# 127 is the ASCII code for delete
+127: DELETE_PREV_CHAR
diff --git a/src/main/resources/org/python/util/jython.class b/src/main/resources/org/python/util/jython.class
new file mode 100644
index 0000000000000000000000000000000000000000..4858695242296ce3672b5e784f5dd431aa324286
Binary files /dev/null and b/src/main/resources/org/python/util/jython.class differ
diff --git a/src/main/resources/org/python/util/jythonTest.class b/src/main/resources/org/python/util/jythonTest.class
new file mode 100644
index 0000000000000000000000000000000000000000..bcc32ef4165b5ab8dfebfd900d2f90ecfc51d54e
Binary files /dev/null and b/src/main/resources/org/python/util/jythonTest.class differ
diff --git a/src/main/resources/org/python/util/jythonTestPlain.class b/src/main/resources/org/python/util/jythonTestPlain.class
new file mode 100644
index 0000000000000000000000000000000000000000..80cc680bebd15d0bf0bb45ce4c11835275c68028
Binary files /dev/null and b/src/main/resources/org/python/util/jythonTestPlain.class differ
diff --git a/src/main/resources/org/python/version.properties b/src/main/resources/org/python/version.properties
new file mode 100644
index 0000000000000000000000000000000000000000..8297568cb833b254c9c6ff945cee775e8d65d21c
--- /dev/null
+++ b/src/main/resources/org/python/version.properties
@@ -0,0 +1,12 @@
+# Jython version information
+jython.version=2.7b1+
+jython.major_version=2
+jython.minor_version=7
+jython.micro_version=0
+jython.release_level=11
+jython.release_serial=1
+jython.build.date=nov. 18 2013
+jython.build.time=10:35:32
+jython.build.hg_branch=default
+jython.build.hg_tag=tip
+jython.build.hg_version=7b44ea13a028+
\ No newline at end of file
diff --git a/src/main/resources/org/w3c/dom/Attr.class b/src/main/resources/org/w3c/dom/Attr.class
new file mode 100644
index 0000000000000000000000000000000000000000..b8ad862e0c5c6e3958d896ddb6c02586308bc1d9
Binary files /dev/null and b/src/main/resources/org/w3c/dom/Attr.class differ
diff --git a/src/main/resources/org/w3c/dom/CDATASection.class b/src/main/resources/org/w3c/dom/CDATASection.class
new file mode 100644
index 0000000000000000000000000000000000000000..e93f1bce7bdf3a2d36c9005a1102a8ee351c48f5
Binary files /dev/null and b/src/main/resources/org/w3c/dom/CDATASection.class differ
diff --git a/src/main/resources/org/w3c/dom/CharacterData.class b/src/main/resources/org/w3c/dom/CharacterData.class
new file mode 100644
index 0000000000000000000000000000000000000000..43704a0512e5026ed70164ea9fccd26e26f8d05f
Binary files /dev/null and b/src/main/resources/org/w3c/dom/CharacterData.class differ
diff --git a/src/main/resources/org/w3c/dom/Comment.class b/src/main/resources/org/w3c/dom/Comment.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc2b50ae724e3fc19c233fe33998c1c56fca0a22
Binary files /dev/null and b/src/main/resources/org/w3c/dom/Comment.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMConfiguration.class b/src/main/resources/org/w3c/dom/DOMConfiguration.class
new file mode 100644
index 0000000000000000000000000000000000000000..8e6cff22fd71223ad0128622ed5dfff4a8a51d52
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMConfiguration.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMError.class b/src/main/resources/org/w3c/dom/DOMError.class
new file mode 100644
index 0000000000000000000000000000000000000000..80f9776eed68636485f3dfb7af52275dc706efdb
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMError.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMErrorHandler.class b/src/main/resources/org/w3c/dom/DOMErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..6304efcb197dca30ff7a8ea30f81ec8a673e08c5
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMErrorHandler.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMException.class b/src/main/resources/org/w3c/dom/DOMException.class
new file mode 100644
index 0000000000000000000000000000000000000000..c19e745296272b276c9ca58fdc10ad42e4ce843d
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMException.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMImplementation.class b/src/main/resources/org/w3c/dom/DOMImplementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..b86f2b2fac9ad4e8735b1a46213288d216d2d1ee
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMImplementation.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMImplementationList.class b/src/main/resources/org/w3c/dom/DOMImplementationList.class
new file mode 100644
index 0000000000000000000000000000000000000000..00f32b763596736bae7bfd10c735e37a516e57b3
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMImplementationList.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMImplementationSource.class b/src/main/resources/org/w3c/dom/DOMImplementationSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6fd5d560c1960a69faf19546f59186b52c4a47f
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMImplementationSource.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMLocator.class b/src/main/resources/org/w3c/dom/DOMLocator.class
new file mode 100644
index 0000000000000000000000000000000000000000..064c0b3b13c0b9133752698b481b11f1072ae8cb
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMLocator.class differ
diff --git a/src/main/resources/org/w3c/dom/DOMStringList.class b/src/main/resources/org/w3c/dom/DOMStringList.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc55618ebd0a7991fbcf5e9008be9d50a60e2871
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DOMStringList.class differ
diff --git a/src/main/resources/org/w3c/dom/Document.class b/src/main/resources/org/w3c/dom/Document.class
new file mode 100644
index 0000000000000000000000000000000000000000..b1c7a4ab7555845540db7e5c697994a05c192dbf
Binary files /dev/null and b/src/main/resources/org/w3c/dom/Document.class differ
diff --git a/src/main/resources/org/w3c/dom/DocumentFragment.class b/src/main/resources/org/w3c/dom/DocumentFragment.class
new file mode 100644
index 0000000000000000000000000000000000000000..862f6976884c6c70410bc3de65e1c7c9833ffd3e
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DocumentFragment.class differ
diff --git a/src/main/resources/org/w3c/dom/DocumentType.class b/src/main/resources/org/w3c/dom/DocumentType.class
new file mode 100644
index 0000000000000000000000000000000000000000..923664b9729b15ee8df0a34a06fa937f066246f9
Binary files /dev/null and b/src/main/resources/org/w3c/dom/DocumentType.class differ
diff --git a/src/main/resources/org/w3c/dom/Element.class b/src/main/resources/org/w3c/dom/Element.class
new file mode 100644
index 0000000000000000000000000000000000000000..722bd51bf10cf097d014a56fd92e9589ca8fee3a
Binary files /dev/null and b/src/main/resources/org/w3c/dom/Element.class differ
diff --git a/src/main/resources/org/w3c/dom/ElementTraversal.class b/src/main/resources/org/w3c/dom/ElementTraversal.class
new file mode 100644
index 0000000000000000000000000000000000000000..7979546110e11ddd11766ac02cbbc46dbfabc41a
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ElementTraversal.class differ
diff --git a/src/main/resources/org/w3c/dom/Entity.class b/src/main/resources/org/w3c/dom/Entity.class
new file mode 100644
index 0000000000000000000000000000000000000000..072bd8debc9287a42636472904253ed4a59368c2
Binary files /dev/null and b/src/main/resources/org/w3c/dom/Entity.class differ
diff --git a/src/main/resources/org/w3c/dom/EntityReference.class b/src/main/resources/org/w3c/dom/EntityReference.class
new file mode 100644
index 0000000000000000000000000000000000000000..b60e2e1be608d7cca9956c4d66b1303ffe0d254f
Binary files /dev/null and b/src/main/resources/org/w3c/dom/EntityReference.class differ
diff --git a/src/main/resources/org/w3c/dom/NameList.class b/src/main/resources/org/w3c/dom/NameList.class
new file mode 100644
index 0000000000000000000000000000000000000000..d08f34514040c3efb60ad3f02832a5af13eca625
Binary files /dev/null and b/src/main/resources/org/w3c/dom/NameList.class differ
diff --git a/src/main/resources/org/w3c/dom/NamedNodeMap.class b/src/main/resources/org/w3c/dom/NamedNodeMap.class
new file mode 100644
index 0000000000000000000000000000000000000000..6eca9f1e8bd2e93a54728ace5233b0c331c35ba6
Binary files /dev/null and b/src/main/resources/org/w3c/dom/NamedNodeMap.class differ
diff --git a/src/main/resources/org/w3c/dom/Node.class b/src/main/resources/org/w3c/dom/Node.class
new file mode 100644
index 0000000000000000000000000000000000000000..04d63b68dc501de6ba4f390796b3e96585fed6f8
Binary files /dev/null and b/src/main/resources/org/w3c/dom/Node.class differ
diff --git a/src/main/resources/org/w3c/dom/NodeList.class b/src/main/resources/org/w3c/dom/NodeList.class
new file mode 100644
index 0000000000000000000000000000000000000000..03a0ca7ba13ad8e3ffe7008073c787318f8dbbe0
Binary files /dev/null and b/src/main/resources/org/w3c/dom/NodeList.class differ
diff --git a/src/main/resources/org/w3c/dom/Notation.class b/src/main/resources/org/w3c/dom/Notation.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc8bdcd8108b14cbbbcd97aaca2ddd56aa30d941
Binary files /dev/null and b/src/main/resources/org/w3c/dom/Notation.class differ
diff --git a/src/main/resources/org/w3c/dom/ProcessingInstruction.class b/src/main/resources/org/w3c/dom/ProcessingInstruction.class
new file mode 100644
index 0000000000000000000000000000000000000000..e716bd79bcd8b2136ecfb57f7f1fc8638eddbcce
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ProcessingInstruction.class differ
diff --git a/src/main/resources/org/w3c/dom/Text.class b/src/main/resources/org/w3c/dom/Text.class
new file mode 100644
index 0000000000000000000000000000000000000000..682a58b91fad5bf4f97c08ff08d03cf21a877ad5
Binary files /dev/null and b/src/main/resources/org/w3c/dom/Text.class differ
diff --git a/src/main/resources/org/w3c/dom/TypeInfo.class b/src/main/resources/org/w3c/dom/TypeInfo.class
new file mode 100644
index 0000000000000000000000000000000000000000..920a0df2f47321f4e31fc50e190fc227a1f4dd19
Binary files /dev/null and b/src/main/resources/org/w3c/dom/TypeInfo.class differ
diff --git a/src/main/resources/org/w3c/dom/UserDataHandler.class b/src/main/resources/org/w3c/dom/UserDataHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..da259bf126d2725e8d8d9e09482f89df945779a8
Binary files /dev/null and b/src/main/resources/org/w3c/dom/UserDataHandler.class differ
diff --git a/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$1.class b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..335129d0c9e02adfc92c4b4901305137f2a8bb3c
Binary files /dev/null and b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$1.class differ
diff --git a/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$2.class b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e88418778d51e818a402277822d6ffae5d05d94
Binary files /dev/null and b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$2.class differ
diff --git a/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$3.class b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d377f9b711129631ea84efc26a64ac65e803302
Binary files /dev/null and b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$3.class differ
diff --git a/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$4.class b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..a21f686140c029ab2714fa66c77cc650ea50ac5c
Binary files /dev/null and b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry$4.class differ
diff --git a/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry.class b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry.class
new file mode 100644
index 0000000000000000000000000000000000000000..67ea9a70dd2c1d9324f3768a93b80e6c4a5a3423
Binary files /dev/null and b/src/main/resources/org/w3c/dom/bootstrap/DOMImplementationRegistry.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSS2Properties.class b/src/main/resources/org/w3c/dom/css/CSS2Properties.class
new file mode 100644
index 0000000000000000000000000000000000000000..be309846740f2bc1edf4e2bbf91f948920bd9165
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSS2Properties.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSCharsetRule.class b/src/main/resources/org/w3c/dom/css/CSSCharsetRule.class
new file mode 100644
index 0000000000000000000000000000000000000000..2d66b68ef8f59999f230190721ad798d9f4274d4
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSCharsetRule.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSFontFaceRule.class b/src/main/resources/org/w3c/dom/css/CSSFontFaceRule.class
new file mode 100644
index 0000000000000000000000000000000000000000..5a1d4e83132174f78bad5f77a816b7fe315c3087
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSFontFaceRule.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSImportRule.class b/src/main/resources/org/w3c/dom/css/CSSImportRule.class
new file mode 100644
index 0000000000000000000000000000000000000000..20d45e6a8fb59b526619d2d280be63ddbc8f4380
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSImportRule.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSMediaRule.class b/src/main/resources/org/w3c/dom/css/CSSMediaRule.class
new file mode 100644
index 0000000000000000000000000000000000000000..1b5781cc914ce4d1befb5095b82bad01f402802c
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSMediaRule.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSPageRule.class b/src/main/resources/org/w3c/dom/css/CSSPageRule.class
new file mode 100644
index 0000000000000000000000000000000000000000..c890d9fac88b4d65945a55dd803b4e25c16f06fe
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSPageRule.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSPrimitiveValue.class b/src/main/resources/org/w3c/dom/css/CSSPrimitiveValue.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb7f5c94e0fc3790860f9457eecf7998b103ba3f
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSPrimitiveValue.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSRule.class b/src/main/resources/org/w3c/dom/css/CSSRule.class
new file mode 100644
index 0000000000000000000000000000000000000000..48dda481cfad7b03eca2a35170a56eadae3115e0
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSRule.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSRuleList.class b/src/main/resources/org/w3c/dom/css/CSSRuleList.class
new file mode 100644
index 0000000000000000000000000000000000000000..0d6a48788ae69b47a6d59ca4cbc5fe83d51a5483
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSRuleList.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSStyleDeclaration.class b/src/main/resources/org/w3c/dom/css/CSSStyleDeclaration.class
new file mode 100644
index 0000000000000000000000000000000000000000..8f3b8dd6c497148927c3e6f4b8257a7bc0120ef9
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSStyleDeclaration.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSStyleRule.class b/src/main/resources/org/w3c/dom/css/CSSStyleRule.class
new file mode 100644
index 0000000000000000000000000000000000000000..df31d2403929857e769531a4465c3f0257ef9baf
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSStyleRule.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSStyleSheet.class b/src/main/resources/org/w3c/dom/css/CSSStyleSheet.class
new file mode 100644
index 0000000000000000000000000000000000000000..e84e9db9dc17ee30688173ff17ea370aa2ab9fce
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSStyleSheet.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSUnknownRule.class b/src/main/resources/org/w3c/dom/css/CSSUnknownRule.class
new file mode 100644
index 0000000000000000000000000000000000000000..8338f82b23359e734084a38282c87c289cc3e967
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSUnknownRule.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSValue.class b/src/main/resources/org/w3c/dom/css/CSSValue.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a91c92f760c400379e969820d87fd3f582f0d58
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSValue.class differ
diff --git a/src/main/resources/org/w3c/dom/css/CSSValueList.class b/src/main/resources/org/w3c/dom/css/CSSValueList.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd67a7ee81698b81629456d470b2c87120e510f6
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/CSSValueList.class differ
diff --git a/src/main/resources/org/w3c/dom/css/Counter.class b/src/main/resources/org/w3c/dom/css/Counter.class
new file mode 100644
index 0000000000000000000000000000000000000000..20cb23f7758ec87c9128aff64c93be31b3ea5e83
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/Counter.class differ
diff --git a/src/main/resources/org/w3c/dom/css/DOMImplementationCSS.class b/src/main/resources/org/w3c/dom/css/DOMImplementationCSS.class
new file mode 100644
index 0000000000000000000000000000000000000000..acc17f3683a79c8c2b8f788991be1a0d6dceba5a
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/DOMImplementationCSS.class differ
diff --git a/src/main/resources/org/w3c/dom/css/DocumentCSS.class b/src/main/resources/org/w3c/dom/css/DocumentCSS.class
new file mode 100644
index 0000000000000000000000000000000000000000..a5947e5781629dd6bcaf87e65ac32635a5eacf69
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/DocumentCSS.class differ
diff --git a/src/main/resources/org/w3c/dom/css/ElementCSSInlineStyle.class b/src/main/resources/org/w3c/dom/css/ElementCSSInlineStyle.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b5249da6f4ee4fc99fb6c4d0c1a2c7236fbbf87
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/ElementCSSInlineStyle.class differ
diff --git a/src/main/resources/org/w3c/dom/css/RGBColor.class b/src/main/resources/org/w3c/dom/css/RGBColor.class
new file mode 100644
index 0000000000000000000000000000000000000000..7054a5a36fb432a791554e185b7c7b3e905fc4cf
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/RGBColor.class differ
diff --git a/src/main/resources/org/w3c/dom/css/Rect.class b/src/main/resources/org/w3c/dom/css/Rect.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f47695d4653905e20cc2c0a675ed338222de315
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/Rect.class differ
diff --git a/src/main/resources/org/w3c/dom/css/ViewCSS.class b/src/main/resources/org/w3c/dom/css/ViewCSS.class
new file mode 100644
index 0000000000000000000000000000000000000000..3859a58d9a724a976cd27f4bc0644fb78e8d9ff5
Binary files /dev/null and b/src/main/resources/org/w3c/dom/css/ViewCSS.class differ
diff --git a/src/main/resources/org/w3c/dom/events/DocumentEvent.class b/src/main/resources/org/w3c/dom/events/DocumentEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..c8aa7e71ac691a314a09fdcb0e602e964e1cbd75
Binary files /dev/null and b/src/main/resources/org/w3c/dom/events/DocumentEvent.class differ
diff --git a/src/main/resources/org/w3c/dom/events/Event.class b/src/main/resources/org/w3c/dom/events/Event.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9539270a67b807776deacacbbd7862838b09684
Binary files /dev/null and b/src/main/resources/org/w3c/dom/events/Event.class differ
diff --git a/src/main/resources/org/w3c/dom/events/EventException.class b/src/main/resources/org/w3c/dom/events/EventException.class
new file mode 100644
index 0000000000000000000000000000000000000000..4b11285dc59698230868031d50224eaa804fcd40
Binary files /dev/null and b/src/main/resources/org/w3c/dom/events/EventException.class differ
diff --git a/src/main/resources/org/w3c/dom/events/EventListener.class b/src/main/resources/org/w3c/dom/events/EventListener.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f65c509456af24ad4f616ec05d54464d9ee9d58
Binary files /dev/null and b/src/main/resources/org/w3c/dom/events/EventListener.class differ
diff --git a/src/main/resources/org/w3c/dom/events/EventTarget.class b/src/main/resources/org/w3c/dom/events/EventTarget.class
new file mode 100644
index 0000000000000000000000000000000000000000..c6b5fed717ce92b1fad68cead9fbcaa8c0f0a694
Binary files /dev/null and b/src/main/resources/org/w3c/dom/events/EventTarget.class differ
diff --git a/src/main/resources/org/w3c/dom/events/MouseEvent.class b/src/main/resources/org/w3c/dom/events/MouseEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..8272fae2ca81163f0e1c42c7a6d8da9080216204
Binary files /dev/null and b/src/main/resources/org/w3c/dom/events/MouseEvent.class differ
diff --git a/src/main/resources/org/w3c/dom/events/MutationEvent.class b/src/main/resources/org/w3c/dom/events/MutationEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc8beebc1e9d018bf7994a6b20f12c245d846e4a
Binary files /dev/null and b/src/main/resources/org/w3c/dom/events/MutationEvent.class differ
diff --git a/src/main/resources/org/w3c/dom/events/UIEvent.class b/src/main/resources/org/w3c/dom/events/UIEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4d08483f09de4fdd49ed1516af10e395074f8e8
Binary files /dev/null and b/src/main/resources/org/w3c/dom/events/UIEvent.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLAnchorElement.class b/src/main/resources/org/w3c/dom/html/HTMLAnchorElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..f2b97fdb755b3abe1b6571b0ff04d110adce6742
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLAnchorElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLAppletElement.class b/src/main/resources/org/w3c/dom/html/HTMLAppletElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad0e609764978cdeef4c5b1fe58b1313d9988c54
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLAppletElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLAreaElement.class b/src/main/resources/org/w3c/dom/html/HTMLAreaElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..30408d12404301162505bcd0003ee42bae7f3fe9
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLAreaElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLBRElement.class b/src/main/resources/org/w3c/dom/html/HTMLBRElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..d36a70305e38fbf73605c6e3aea0779fe0e228c6
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLBRElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLBaseElement.class b/src/main/resources/org/w3c/dom/html/HTMLBaseElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f2cbb74f055c4d44d3558a2676da7bb9d429af1
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLBaseElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLBaseFontElement.class b/src/main/resources/org/w3c/dom/html/HTMLBaseFontElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..ec702616ccc2cd3f84a295dd6c1485698eb8cc25
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLBaseFontElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLBodyElement.class b/src/main/resources/org/w3c/dom/html/HTMLBodyElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..71a312deb52c7047db4aadca0a11929b0d0f2a49
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLBodyElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLButtonElement.class b/src/main/resources/org/w3c/dom/html/HTMLButtonElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..bc52f7cf69538466cd822a8c03b85e9863b22aa3
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLButtonElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLCollection.class b/src/main/resources/org/w3c/dom/html/HTMLCollection.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e7abbae8bb36691061c897d42b4fb71e001b516
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLCollection.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLDListElement.class b/src/main/resources/org/w3c/dom/html/HTMLDListElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..fd5495cfa89ce7f70b0f3ef806368ed584639e9f
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLDListElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLDOMImplementation.class b/src/main/resources/org/w3c/dom/html/HTMLDOMImplementation.class
new file mode 100644
index 0000000000000000000000000000000000000000..15ced5835843ccbf8d8899deff8d470fa0242c1d
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLDOMImplementation.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLDirectoryElement.class b/src/main/resources/org/w3c/dom/html/HTMLDirectoryElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0eb9a0ea56ffa3f7b32146da9b0fb6a98bd9b08
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLDirectoryElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLDivElement.class b/src/main/resources/org/w3c/dom/html/HTMLDivElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..08a0bf0f6ff417b43ce297dc3c0987cf6eb56946
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLDivElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLDocument.class b/src/main/resources/org/w3c/dom/html/HTMLDocument.class
new file mode 100644
index 0000000000000000000000000000000000000000..43e1e13f39d9ee863130709443e59656c1cd8170
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLDocument.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLElement.class b/src/main/resources/org/w3c/dom/html/HTMLElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..e6ef303bbc532c2ed4e33f9da64294e925ec5e41
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLFieldSetElement.class b/src/main/resources/org/w3c/dom/html/HTMLFieldSetElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..c4253076b3466ecc3d3c0d784110639992c8646b
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLFieldSetElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLFontElement.class b/src/main/resources/org/w3c/dom/html/HTMLFontElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..14e9cceaa5d4dff632543dec00b6f26abe0a5756
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLFontElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLFormElement.class b/src/main/resources/org/w3c/dom/html/HTMLFormElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f90d0393056973b01b2559ef634839655b772c2
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLFormElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLFrameElement.class b/src/main/resources/org/w3c/dom/html/HTMLFrameElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..cc9499593bcdc822bd8c6527f2959e59e87e6aa7
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLFrameElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLFrameSetElement.class b/src/main/resources/org/w3c/dom/html/HTMLFrameSetElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f08752fe54d0a520fa4aa524776cc302c9272af
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLFrameSetElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLHRElement.class b/src/main/resources/org/w3c/dom/html/HTMLHRElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c3d711d7466b745ead38b8b07cd4b69d88329f1
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLHRElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLHeadElement.class b/src/main/resources/org/w3c/dom/html/HTMLHeadElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bc12dd52cd875cce211b2f702fd734807c71b74
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLHeadElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLHeadingElement.class b/src/main/resources/org/w3c/dom/html/HTMLHeadingElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..a9cdaae986eaa30a1f4c8afcf921410cf0a91a29
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLHeadingElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLHtmlElement.class b/src/main/resources/org/w3c/dom/html/HTMLHtmlElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..192fc4f7e7dfcbdae70b051453c6269870e583d1
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLHtmlElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLIFrameElement.class b/src/main/resources/org/w3c/dom/html/HTMLIFrameElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..202f3addcaf8d72b893d529cf8f74091fc7bc1b5
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLIFrameElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLImageElement.class b/src/main/resources/org/w3c/dom/html/HTMLImageElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..5457c67ffd5f1dbe01b8995182e15fbcf80aa565
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLImageElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLInputElement.class b/src/main/resources/org/w3c/dom/html/HTMLInputElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..75a8c1c01652dce4633c88338f696e5e0be30c3a
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLInputElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLIsIndexElement.class b/src/main/resources/org/w3c/dom/html/HTMLIsIndexElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..57d90384d4210896f0fa096416448dd148a788a6
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLIsIndexElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLLIElement.class b/src/main/resources/org/w3c/dom/html/HTMLLIElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..49396f60320a023424282109a535650eb757053b
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLLIElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLLabelElement.class b/src/main/resources/org/w3c/dom/html/HTMLLabelElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..1851a82870befaae0eaaab67a41772ff940d25a9
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLLabelElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLLegendElement.class b/src/main/resources/org/w3c/dom/html/HTMLLegendElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..6f6794b0d2789665545cf95b2606491b1266f630
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLLegendElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLLinkElement.class b/src/main/resources/org/w3c/dom/html/HTMLLinkElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..9fbc3000c3314d2890c98eb1936244783882ae2a
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLLinkElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLMapElement.class b/src/main/resources/org/w3c/dom/html/HTMLMapElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0aa7e12f8e45bf9fa52b1754f101c7856633524
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLMapElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLMenuElement.class b/src/main/resources/org/w3c/dom/html/HTMLMenuElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..acaffaf3b1875f63628aa2f257e666b6859b0b3b
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLMenuElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLMetaElement.class b/src/main/resources/org/w3c/dom/html/HTMLMetaElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae7ee97ad8ddf5bfb2a9cd217d87df82c7538fcd
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLMetaElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLModElement.class b/src/main/resources/org/w3c/dom/html/HTMLModElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..eb01f1c9136a6e0348bf776e67a68631b701026d
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLModElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLOListElement.class b/src/main/resources/org/w3c/dom/html/HTMLOListElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..3c3204827b17980941cf05fcbca00f555fc9774c
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLOListElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLObjectElement.class b/src/main/resources/org/w3c/dom/html/HTMLObjectElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..d29580444951fb605ccc0d38c3d35000887dda3b
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLObjectElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLOptGroupElement.class b/src/main/resources/org/w3c/dom/html/HTMLOptGroupElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..1adb8f69c4585fc23014a96034713bc08c03bd9a
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLOptGroupElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLOptionElement.class b/src/main/resources/org/w3c/dom/html/HTMLOptionElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..709ffab4b4a7b52dc0fd9c6f683d6917ad951168
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLOptionElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLParagraphElement.class b/src/main/resources/org/w3c/dom/html/HTMLParagraphElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..793bf7454b76adf08a3a6299faa2aa9201344438
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLParagraphElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLParamElement.class b/src/main/resources/org/w3c/dom/html/HTMLParamElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a5910e9d54ac4a447448f355c96c89b42f661de
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLParamElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLPreElement.class b/src/main/resources/org/w3c/dom/html/HTMLPreElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfed0ebcd44788ee659a80a365e69b0bc6edf3a3
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLPreElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLQuoteElement.class b/src/main/resources/org/w3c/dom/html/HTMLQuoteElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..0e4cadfe3d32f4a7887715fbdeb5651008f418f8
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLQuoteElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLScriptElement.class b/src/main/resources/org/w3c/dom/html/HTMLScriptElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..abbce244e5290d86ca8a43d7082713da16953692
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLScriptElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLSelectElement.class b/src/main/resources/org/w3c/dom/html/HTMLSelectElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..669e10765e69b3d599213e145cb909ac036ff4cf
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLSelectElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLStyleElement.class b/src/main/resources/org/w3c/dom/html/HTMLStyleElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..d8e996f4e6f89b2718a5778c53b5d1000a3229f7
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLStyleElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLTableCaptionElement.class b/src/main/resources/org/w3c/dom/html/HTMLTableCaptionElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..56a09142f3ff0fa46bd08c41ae9b468fa25aa855
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLTableCaptionElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLTableCellElement.class b/src/main/resources/org/w3c/dom/html/HTMLTableCellElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..fba8d5bc9d36d327744b9ebc965d279787d9fbaf
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLTableCellElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLTableColElement.class b/src/main/resources/org/w3c/dom/html/HTMLTableColElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..5cb4db6008ef8fdc65469d6a08410e1899ac470c
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLTableColElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLTableElement.class b/src/main/resources/org/w3c/dom/html/HTMLTableElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..8666c20c928ca8fcc13c554262ed36be122fd2d2
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLTableElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLTableRowElement.class b/src/main/resources/org/w3c/dom/html/HTMLTableRowElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..440a4b34fc526da1e52d6033ec92d72ba3308a5b
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLTableRowElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLTableSectionElement.class b/src/main/resources/org/w3c/dom/html/HTMLTableSectionElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..927fced73bc6392b97fca5637b49dc3da6ff72d3
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLTableSectionElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLTextAreaElement.class b/src/main/resources/org/w3c/dom/html/HTMLTextAreaElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..200ba2f74d56fd17731228caeab09a17c12857c8
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLTextAreaElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLTitleElement.class b/src/main/resources/org/w3c/dom/html/HTMLTitleElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..4764bf41666f81a4010e103fbdb4a7feb1f9bb7c
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLTitleElement.class differ
diff --git a/src/main/resources/org/w3c/dom/html/HTMLUListElement.class b/src/main/resources/org/w3c/dom/html/HTMLUListElement.class
new file mode 100644
index 0000000000000000000000000000000000000000..0a76d71c73bd12cc9a1f397b7fd6cfb0683efbaa
Binary files /dev/null and b/src/main/resources/org/w3c/dom/html/HTMLUListElement.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/DOMImplementationLS.class b/src/main/resources/org/w3c/dom/ls/DOMImplementationLS.class
new file mode 100644
index 0000000000000000000000000000000000000000..8059a172538805787243c39edfbc54dec119c3a0
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/DOMImplementationLS.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSException.class b/src/main/resources/org/w3c/dom/ls/LSException.class
new file mode 100644
index 0000000000000000000000000000000000000000..a2d312f9eeed7f11a26dc95cb26e29c525d40159
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSException.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSInput.class b/src/main/resources/org/w3c/dom/ls/LSInput.class
new file mode 100644
index 0000000000000000000000000000000000000000..6be91c4a11da18415bf4dcff77a041d4a3da8682
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSInput.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSLoadEvent.class b/src/main/resources/org/w3c/dom/ls/LSLoadEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..b296e36ee890f7b794c39062d8f301bc6d584918
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSLoadEvent.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSOutput.class b/src/main/resources/org/w3c/dom/ls/LSOutput.class
new file mode 100644
index 0000000000000000000000000000000000000000..c9a9e372f50de41596d0c489b8f01f34ede4f40e
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSOutput.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSParser.class b/src/main/resources/org/w3c/dom/ls/LSParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..b90fef69d44710fbe7db34bf1acd46cbd68a212d
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSParser.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSParserFilter.class b/src/main/resources/org/w3c/dom/ls/LSParserFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..c80d619210769664b0a7ae611ba1be5b7ab45508
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSParserFilter.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSProgressEvent.class b/src/main/resources/org/w3c/dom/ls/LSProgressEvent.class
new file mode 100644
index 0000000000000000000000000000000000000000..6e954d9ce18e208122a947a8cd8c46c5e6566957
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSProgressEvent.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSResourceResolver.class b/src/main/resources/org/w3c/dom/ls/LSResourceResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..da6a934e95e64b234412e19e5558f3c5a06fbd56
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSResourceResolver.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSSerializer.class b/src/main/resources/org/w3c/dom/ls/LSSerializer.class
new file mode 100644
index 0000000000000000000000000000000000000000..00ce3fe5221a786e717d2c6cfd90bca32363aa70
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSSerializer.class differ
diff --git a/src/main/resources/org/w3c/dom/ls/LSSerializerFilter.class b/src/main/resources/org/w3c/dom/ls/LSSerializerFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..6ad5bd637a12886fc06b557d8af5fb60840bfadb
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ls/LSSerializerFilter.class differ
diff --git a/src/main/resources/org/w3c/dom/ranges/DocumentRange.class b/src/main/resources/org/w3c/dom/ranges/DocumentRange.class
new file mode 100644
index 0000000000000000000000000000000000000000..7d6aec12b413963ef77f3a37ec6488ac3c03b502
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ranges/DocumentRange.class differ
diff --git a/src/main/resources/org/w3c/dom/ranges/Range.class b/src/main/resources/org/w3c/dom/ranges/Range.class
new file mode 100644
index 0000000000000000000000000000000000000000..9c4036175d938f9261eebd905d86656e00271c6c
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ranges/Range.class differ
diff --git a/src/main/resources/org/w3c/dom/ranges/RangeException.class b/src/main/resources/org/w3c/dom/ranges/RangeException.class
new file mode 100644
index 0000000000000000000000000000000000000000..f6d49be846ad5e174fa693d0955999a291b3efaf
Binary files /dev/null and b/src/main/resources/org/w3c/dom/ranges/RangeException.class differ
diff --git a/src/main/resources/org/w3c/dom/stylesheets/DocumentStyle.class b/src/main/resources/org/w3c/dom/stylesheets/DocumentStyle.class
new file mode 100644
index 0000000000000000000000000000000000000000..3363ac7eab7dbc2f8fb6c8d52ff7b28decac7b20
Binary files /dev/null and b/src/main/resources/org/w3c/dom/stylesheets/DocumentStyle.class differ
diff --git a/src/main/resources/org/w3c/dom/stylesheets/LinkStyle.class b/src/main/resources/org/w3c/dom/stylesheets/LinkStyle.class
new file mode 100644
index 0000000000000000000000000000000000000000..a88504eeeabe5c4055f4bd69484823c5e0ff910e
Binary files /dev/null and b/src/main/resources/org/w3c/dom/stylesheets/LinkStyle.class differ
diff --git a/src/main/resources/org/w3c/dom/stylesheets/MediaList.class b/src/main/resources/org/w3c/dom/stylesheets/MediaList.class
new file mode 100644
index 0000000000000000000000000000000000000000..418bbd5807bf634085cb178483b6fb1926937099
Binary files /dev/null and b/src/main/resources/org/w3c/dom/stylesheets/MediaList.class differ
diff --git a/src/main/resources/org/w3c/dom/stylesheets/StyleSheet.class b/src/main/resources/org/w3c/dom/stylesheets/StyleSheet.class
new file mode 100644
index 0000000000000000000000000000000000000000..a3e453907aa1bb81c2c75c0835acfe63253b1fd7
Binary files /dev/null and b/src/main/resources/org/w3c/dom/stylesheets/StyleSheet.class differ
diff --git a/src/main/resources/org/w3c/dom/stylesheets/StyleSheetList.class b/src/main/resources/org/w3c/dom/stylesheets/StyleSheetList.class
new file mode 100644
index 0000000000000000000000000000000000000000..523bb84082f2031b6d28e75115f0d2f5d52fda66
Binary files /dev/null and b/src/main/resources/org/w3c/dom/stylesheets/StyleSheetList.class differ
diff --git a/src/main/resources/org/w3c/dom/traversal/DocumentTraversal.class b/src/main/resources/org/w3c/dom/traversal/DocumentTraversal.class
new file mode 100644
index 0000000000000000000000000000000000000000..1a80c64eae389a1f0e1bdc7185f86e43543e3dc7
Binary files /dev/null and b/src/main/resources/org/w3c/dom/traversal/DocumentTraversal.class differ
diff --git a/src/main/resources/org/w3c/dom/traversal/NodeFilter.class b/src/main/resources/org/w3c/dom/traversal/NodeFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..ae9978bc43f3145134986ee4dcddb08d0ffe6cb1
Binary files /dev/null and b/src/main/resources/org/w3c/dom/traversal/NodeFilter.class differ
diff --git a/src/main/resources/org/w3c/dom/traversal/NodeIterator.class b/src/main/resources/org/w3c/dom/traversal/NodeIterator.class
new file mode 100644
index 0000000000000000000000000000000000000000..30202989f88629b4f6f54ba1c3b6137cc618fee3
Binary files /dev/null and b/src/main/resources/org/w3c/dom/traversal/NodeIterator.class differ
diff --git a/src/main/resources/org/w3c/dom/traversal/TreeWalker.class b/src/main/resources/org/w3c/dom/traversal/TreeWalker.class
new file mode 100644
index 0000000000000000000000000000000000000000..d3c9d8a184d28b07b6a5a14612b04683d667dd36
Binary files /dev/null and b/src/main/resources/org/w3c/dom/traversal/TreeWalker.class differ
diff --git a/src/main/resources/org/w3c/dom/views/AbstractView.class b/src/main/resources/org/w3c/dom/views/AbstractView.class
new file mode 100644
index 0000000000000000000000000000000000000000..782492197b070de3797a7d959caefede57a9fa3a
Binary files /dev/null and b/src/main/resources/org/w3c/dom/views/AbstractView.class differ
diff --git a/src/main/resources/org/w3c/dom/views/DocumentView.class b/src/main/resources/org/w3c/dom/views/DocumentView.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed8e233914f73c54456a4a212a8bd79eecc436b0
Binary files /dev/null and b/src/main/resources/org/w3c/dom/views/DocumentView.class differ
diff --git a/src/main/resources/org/w3c/dom/xpath/XPathEvaluator.class b/src/main/resources/org/w3c/dom/xpath/XPathEvaluator.class
new file mode 100644
index 0000000000000000000000000000000000000000..e5f9cc8e9f10134badbfa1917f302e624b14b677
Binary files /dev/null and b/src/main/resources/org/w3c/dom/xpath/XPathEvaluator.class differ
diff --git a/src/main/resources/org/w3c/dom/xpath/XPathException.class b/src/main/resources/org/w3c/dom/xpath/XPathException.class
new file mode 100644
index 0000000000000000000000000000000000000000..fdd3cd3ceb5e825e76aff6baabac9bbe4ae1bf1e
Binary files /dev/null and b/src/main/resources/org/w3c/dom/xpath/XPathException.class differ
diff --git a/src/main/resources/org/w3c/dom/xpath/XPathExpression.class b/src/main/resources/org/w3c/dom/xpath/XPathExpression.class
new file mode 100644
index 0000000000000000000000000000000000000000..097d43a1c0e805b4c5fd7f1ee0d40c982f8282ba
Binary files /dev/null and b/src/main/resources/org/w3c/dom/xpath/XPathExpression.class differ
diff --git a/src/main/resources/org/w3c/dom/xpath/XPathNSResolver.class b/src/main/resources/org/w3c/dom/xpath/XPathNSResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..def33a27aa7fc4c3e91115a13d4531e3c25096cb
Binary files /dev/null and b/src/main/resources/org/w3c/dom/xpath/XPathNSResolver.class differ
diff --git a/src/main/resources/org/w3c/dom/xpath/XPathNamespace.class b/src/main/resources/org/w3c/dom/xpath/XPathNamespace.class
new file mode 100644
index 0000000000000000000000000000000000000000..27c65cc586059aca4ea741878d7e59e76e7ac53e
Binary files /dev/null and b/src/main/resources/org/w3c/dom/xpath/XPathNamespace.class differ
diff --git a/src/main/resources/org/w3c/dom/xpath/XPathResult.class b/src/main/resources/org/w3c/dom/xpath/XPathResult.class
new file mode 100644
index 0000000000000000000000000000000000000000..4f76d58a4bc366fec7fd9b53bb2986e555722d0d
Binary files /dev/null and b/src/main/resources/org/w3c/dom/xpath/XPathResult.class differ
diff --git a/src/main/resources/org/xml/sax/AttributeList.class b/src/main/resources/org/xml/sax/AttributeList.class
new file mode 100644
index 0000000000000000000000000000000000000000..875e99c6fd15d903a866d1578234689e3285c170
Binary files /dev/null and b/src/main/resources/org/xml/sax/AttributeList.class differ
diff --git a/src/main/resources/org/xml/sax/Attributes.class b/src/main/resources/org/xml/sax/Attributes.class
new file mode 100644
index 0000000000000000000000000000000000000000..31bdddfda2f61914b0121e876ff16d87bb4fe139
Binary files /dev/null and b/src/main/resources/org/xml/sax/Attributes.class differ
diff --git a/src/main/resources/org/xml/sax/ContentHandler.class b/src/main/resources/org/xml/sax/ContentHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..d275d1bb5f55582f1dc188fa90e495605326a280
Binary files /dev/null and b/src/main/resources/org/xml/sax/ContentHandler.class differ
diff --git a/src/main/resources/org/xml/sax/DTDHandler.class b/src/main/resources/org/xml/sax/DTDHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..c2507e4bb159ac09b2f4647f534886ac213dd38f
Binary files /dev/null and b/src/main/resources/org/xml/sax/DTDHandler.class differ
diff --git a/src/main/resources/org/xml/sax/DocumentHandler.class b/src/main/resources/org/xml/sax/DocumentHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..4686549f1a80d3c74815c160c67a50b5738e158e
Binary files /dev/null and b/src/main/resources/org/xml/sax/DocumentHandler.class differ
diff --git a/src/main/resources/org/xml/sax/EntityResolver.class b/src/main/resources/org/xml/sax/EntityResolver.class
new file mode 100644
index 0000000000000000000000000000000000000000..b33c56a3a9811918bb37ae72b678390063087092
Binary files /dev/null and b/src/main/resources/org/xml/sax/EntityResolver.class differ
diff --git a/src/main/resources/org/xml/sax/ErrorHandler.class b/src/main/resources/org/xml/sax/ErrorHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..34f95c94c999dcc0789aac07966034d1469e6a1e
Binary files /dev/null and b/src/main/resources/org/xml/sax/ErrorHandler.class differ
diff --git a/src/main/resources/org/xml/sax/HandlerBase.class b/src/main/resources/org/xml/sax/HandlerBase.class
new file mode 100644
index 0000000000000000000000000000000000000000..459e87e2636569f15474639dbcba574f77151b77
Binary files /dev/null and b/src/main/resources/org/xml/sax/HandlerBase.class differ
diff --git a/src/main/resources/org/xml/sax/InputSource.class b/src/main/resources/org/xml/sax/InputSource.class
new file mode 100644
index 0000000000000000000000000000000000000000..31d7e9f45489a5db8a878d1d9f495e39acfe7765
Binary files /dev/null and b/src/main/resources/org/xml/sax/InputSource.class differ
diff --git a/src/main/resources/org/xml/sax/Locator.class b/src/main/resources/org/xml/sax/Locator.class
new file mode 100644
index 0000000000000000000000000000000000000000..9f0eec2f5ff6d74a7bf876983a681dc9329d5669
Binary files /dev/null and b/src/main/resources/org/xml/sax/Locator.class differ
diff --git a/src/main/resources/org/xml/sax/Parser.class b/src/main/resources/org/xml/sax/Parser.class
new file mode 100644
index 0000000000000000000000000000000000000000..9d5c143114c4ff46cfe2145b2b69a05db453557b
Binary files /dev/null and b/src/main/resources/org/xml/sax/Parser.class differ
diff --git a/src/main/resources/org/xml/sax/SAXException.class b/src/main/resources/org/xml/sax/SAXException.class
new file mode 100644
index 0000000000000000000000000000000000000000..9a10b4b356015a5d827d5cde521ec6aaa448e887
Binary files /dev/null and b/src/main/resources/org/xml/sax/SAXException.class differ
diff --git a/src/main/resources/org/xml/sax/SAXNotRecognizedException.class b/src/main/resources/org/xml/sax/SAXNotRecognizedException.class
new file mode 100644
index 0000000000000000000000000000000000000000..9328ea63aa40a9ee49c94a08e7513a26d30109d7
Binary files /dev/null and b/src/main/resources/org/xml/sax/SAXNotRecognizedException.class differ
diff --git a/src/main/resources/org/xml/sax/SAXNotSupportedException.class b/src/main/resources/org/xml/sax/SAXNotSupportedException.class
new file mode 100644
index 0000000000000000000000000000000000000000..3826106d33a85da4df09a78a95b1d3af1f2f422e
Binary files /dev/null and b/src/main/resources/org/xml/sax/SAXNotSupportedException.class differ
diff --git a/src/main/resources/org/xml/sax/SAXParseException.class b/src/main/resources/org/xml/sax/SAXParseException.class
new file mode 100644
index 0000000000000000000000000000000000000000..cfe9cec6d9caae0d9e3fae78a3fca4d640cf7cb9
Binary files /dev/null and b/src/main/resources/org/xml/sax/SAXParseException.class differ
diff --git a/src/main/resources/org/xml/sax/XMLFilter.class b/src/main/resources/org/xml/sax/XMLFilter.class
new file mode 100644
index 0000000000000000000000000000000000000000..e93bdee606ef923b2adb0efe3efb008e8313a593
Binary files /dev/null and b/src/main/resources/org/xml/sax/XMLFilter.class differ
diff --git a/src/main/resources/org/xml/sax/XMLReader.class b/src/main/resources/org/xml/sax/XMLReader.class
new file mode 100644
index 0000000000000000000000000000000000000000..5cc1983740424fa48d383e47bd9e4efddc8165b7
Binary files /dev/null and b/src/main/resources/org/xml/sax/XMLReader.class differ
diff --git a/src/main/resources/org/xml/sax/ext/Attributes2.class b/src/main/resources/org/xml/sax/ext/Attributes2.class
new file mode 100644
index 0000000000000000000000000000000000000000..b6a1e0b816191842f2345876910c6dcf01bdf5c7
Binary files /dev/null and b/src/main/resources/org/xml/sax/ext/Attributes2.class differ
diff --git a/src/main/resources/org/xml/sax/ext/Attributes2Impl.class b/src/main/resources/org/xml/sax/ext/Attributes2Impl.class
new file mode 100644
index 0000000000000000000000000000000000000000..cd4783d8ca7e34452a418948bb4a0c3be1c0cd23
Binary files /dev/null and b/src/main/resources/org/xml/sax/ext/Attributes2Impl.class differ
diff --git a/src/main/resources/org/xml/sax/ext/DeclHandler.class b/src/main/resources/org/xml/sax/ext/DeclHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..62dc5784eac3431bf8cc5c6cfa1974468fcc01f9
Binary files /dev/null and b/src/main/resources/org/xml/sax/ext/DeclHandler.class differ
diff --git a/src/main/resources/org/xml/sax/ext/DefaultHandler2.class b/src/main/resources/org/xml/sax/ext/DefaultHandler2.class
new file mode 100644
index 0000000000000000000000000000000000000000..102bcf33fae762c842ac4ccea266bfd18e16e53f
Binary files /dev/null and b/src/main/resources/org/xml/sax/ext/DefaultHandler2.class differ
diff --git a/src/main/resources/org/xml/sax/ext/EntityResolver2.class b/src/main/resources/org/xml/sax/ext/EntityResolver2.class
new file mode 100644
index 0000000000000000000000000000000000000000..282c79850df1db0253d697e721873dd83f48ce22
Binary files /dev/null and b/src/main/resources/org/xml/sax/ext/EntityResolver2.class differ
diff --git a/src/main/resources/org/xml/sax/ext/LexicalHandler.class b/src/main/resources/org/xml/sax/ext/LexicalHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..a654bf25f0bfbf0aa8c9380775874519d317bb9a
Binary files /dev/null and b/src/main/resources/org/xml/sax/ext/LexicalHandler.class differ
diff --git a/src/main/resources/org/xml/sax/ext/Locator2.class b/src/main/resources/org/xml/sax/ext/Locator2.class
new file mode 100644
index 0000000000000000000000000000000000000000..af658416d2707f947bad20b0bb33a4a70320dc1e
Binary files /dev/null and b/src/main/resources/org/xml/sax/ext/Locator2.class differ
diff --git a/src/main/resources/org/xml/sax/ext/Locator2Impl.class b/src/main/resources/org/xml/sax/ext/Locator2Impl.class
new file mode 100644
index 0000000000000000000000000000000000000000..10cb3ba76c799cdbbba2a385cd1953ee533dcb91
Binary files /dev/null and b/src/main/resources/org/xml/sax/ext/Locator2Impl.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/AttributeListImpl.class b/src/main/resources/org/xml/sax/helpers/AttributeListImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..7bed59434b3c3bb634e6ae4f0b75d947d521bd90
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/AttributeListImpl.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/AttributesImpl.class b/src/main/resources/org/xml/sax/helpers/AttributesImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..e66c1cdffd43af9a40633f3284ca93e67c15046a
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/AttributesImpl.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/DefaultHandler.class b/src/main/resources/org/xml/sax/helpers/DefaultHandler.class
new file mode 100644
index 0000000000000000000000000000000000000000..b2546d2d2b2354113c9a90088da90d124a76a61a
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/DefaultHandler.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/LocatorImpl.class b/src/main/resources/org/xml/sax/helpers/LocatorImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..82353ed2338af5918f5a5258efe4afffb034f6f7
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/LocatorImpl.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/NamespaceSupport$Context.class b/src/main/resources/org/xml/sax/helpers/NamespaceSupport$Context.class
new file mode 100644
index 0000000000000000000000000000000000000000..ed722a130f3b00226835d09e795f783072098d8a
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/NamespaceSupport$Context.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/NamespaceSupport.class b/src/main/resources/org/xml/sax/helpers/NamespaceSupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..014a1337d3495bf00de89a787bff73c6eec57e39
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/NamespaceSupport.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/NewInstance.class b/src/main/resources/org/xml/sax/helpers/NewInstance.class
new file mode 100644
index 0000000000000000000000000000000000000000..b23d41a46ba13ace54c798dd4e4ff8fcbd552a87
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/NewInstance.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/ParserAdapter$AttributeListAdapter.class b/src/main/resources/org/xml/sax/helpers/ParserAdapter$AttributeListAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..a1059a14b611d99b38a10e1e21bd50dca7bfa83f
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/ParserAdapter$AttributeListAdapter.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/ParserAdapter.class b/src/main/resources/org/xml/sax/helpers/ParserAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..5f0a82e17ea5e0fa1db8e6bb2f45de4505a11855
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/ParserAdapter.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/ParserFactory.class b/src/main/resources/org/xml/sax/helpers/ParserFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..0145475a837f7a926d1f8e43fd20afa5b93c5f57
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/ParserFactory.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/SecuritySupport$1.class b/src/main/resources/org/xml/sax/helpers/SecuritySupport$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..1e960e31ea1073ef8b8d68a49a4a56018151cab7
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/SecuritySupport$1.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/SecuritySupport$2.class b/src/main/resources/org/xml/sax/helpers/SecuritySupport$2.class
new file mode 100644
index 0000000000000000000000000000000000000000..c7b392cfcb3fe091ec6dadab8d2fda00fbe5d2c5
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/SecuritySupport$2.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/SecuritySupport$3.class b/src/main/resources/org/xml/sax/helpers/SecuritySupport$3.class
new file mode 100644
index 0000000000000000000000000000000000000000..562edcd30944c15cb5cf211434bd933b7b70add5
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/SecuritySupport$3.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/SecuritySupport$4.class b/src/main/resources/org/xml/sax/helpers/SecuritySupport$4.class
new file mode 100644
index 0000000000000000000000000000000000000000..d9c61550f30fab87ed623b1d65039637a7e2e85a
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/SecuritySupport$4.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/SecuritySupport.class b/src/main/resources/org/xml/sax/helpers/SecuritySupport.class
new file mode 100644
index 0000000000000000000000000000000000000000..c046160ed880d93ac6c1666a72758fddcf4fd90a
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/SecuritySupport.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/XMLFilterImpl.class b/src/main/resources/org/xml/sax/helpers/XMLFilterImpl.class
new file mode 100644
index 0000000000000000000000000000000000000000..838bbb278883b38b06fa1b85f0066bcef56c9a99
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/XMLFilterImpl.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/XMLReaderAdapter$AttributesAdapter.class b/src/main/resources/org/xml/sax/helpers/XMLReaderAdapter$AttributesAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..776cf915b548836f448333d1ce7cb7474cd9a2ac
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/XMLReaderAdapter$AttributesAdapter.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/XMLReaderAdapter.class b/src/main/resources/org/xml/sax/helpers/XMLReaderAdapter.class
new file mode 100644
index 0000000000000000000000000000000000000000..6369a3aea86abfce1d721dec0e38b95b06b5b96b
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/XMLReaderAdapter.class differ
diff --git a/src/main/resources/org/xml/sax/helpers/XMLReaderFactory.class b/src/main/resources/org/xml/sax/helpers/XMLReaderFactory.class
new file mode 100644
index 0000000000000000000000000000000000000000..f17301bbd92dd896b56cc7a46a8daa596f3dbdcb
Binary files /dev/null and b/src/main/resources/org/xml/sax/helpers/XMLReaderFactory.class differ